解读校验放过「不一定会」(BUG-1461 复验补修)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate (push) Canceled after 6m8s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LutgzyJqNhPpZy1nFsJtN3
This commit is contained in:
Jesse_Chen
2026-10-27 11:31:11 +08:00
co-authored by Claude Opus 5.5
parent a2c919a103
commit e433c0e4a8
2 changed files with 10 additions and 2 deletions
+4 -2
View File
@@ -34,7 +34,7 @@ export const REPORT_READING_TIMEOUT_MS = 120_000;
/** Never in the reading: deterministic fate, medical, investment (AGENTS Part B4). */
const BANNED_PHRASES = [
"注定", "先苦后甜", "宿命", "命中注定", "必然会", "一定会",
"注定", "先苦后甜", "宿命", "命中注定",
"癌", "肿瘤", "糖尿病", "高血压", "心脏病", "抑郁症", "焦虑症", "不孕", "流产", "早逝", "寿命", "死亡", "去世",
"股票", "基金", "炒股", "期货", "比特币", "加密货币", "买入", "卖出", "抄底", "投资建议",
// Internal wording the engine report leaked (research §4.1).
@@ -42,6 +42,8 @@ const BANNED_PHRASES = [
// One name per thing, same as the chat (罗睺 / 计都).
"北交点", "南交点", "克图", "凯图",
];
/** 「一定会」「必然会」 are fate claims; 「不一定会」 is the opposite and stays allowed. */
const CERTAINTY = /(?<!不)(一定会|必然会)/;
const DISCLAIMER = /仅供参考|不构成|请咨询专业|不能替代/g;
export type ReadingRejection =
@@ -72,7 +74,7 @@ export function acceptReportReadingDraft(value: unknown):
if (paragraph.length > MAX_PARAGRAPH_CHARS) return { ok: false, reason: "too_long" };
if (/[A-Za-z]/.test(paragraph)) return { ok: false, reason: "latin" };
if (/[_={}<>#*|`]/.test(paragraph)) return { ok: false, reason: "field_name" };
if (BANNED_PHRASES.some((phrase) => paragraph.includes(phrase))) return { ok: false, reason: "banned_phrase" };
if (BANNED_PHRASES.some((phrase) => paragraph.includes(phrase)) || CERTAINTY.test(paragraph)) return { ok: false, reason: "banned_phrase" };
disclaimers += paragraph.match(DISCLAIMER)?.length ?? 0;
total += paragraph.length;
}
@@ -59,6 +59,11 @@ test("a clean eight-part draft becomes the stored reading with our titles", () =
assert.equal(accepted.reading.language, "zh");
});
test("「不一定会」 is not a fate claim and is accepted", () => {
const accepted = acceptReportReadingDraft(draft({ love: [`${PARAGRAPH}这不一定会马上发生。`] }));
assert.equal(accepted.ok, true);
});
test("drafts with Latin, field names, fate, disease, investment or stacked disclaimers are rejected", () => {
const cases: Array<[string, unknown]> = [
["latin", draft({ career: [`${PARAGRAPH}这段是 Rahu 大运。`] })],
@@ -69,6 +74,7 @@ test("drafts with Latin, field names, fate, disease, investment or stacked discl
["banned_phrase", draft({ wealth: [`${PARAGRAPH}适合炒股。`] })],
["banned_phrase", draft({ overview: [`${PARAGRAPH}北交点在 10 宫。`] })],
["banned_phrase", draft({ overview: [`${PARAGRAPH}本仓功能吉凶层这样判。`] })],
["banned_phrase", draft({ love: [`${PARAGRAPH}明年一定会结婚。`] })],
["disclaimer", draft({ health: [`${PARAGRAPH}仅供参考。`, `${PARAGRAPH}不构成医疗意见。`] })],
["shape", { sections: draft().sections.slice(0, 7) }],
["shape", { sections: [...draft().sections].reverse() }],