From e433c0e4a80313aec8bda75a76c1ad884b9182fb Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Tue, 27 Oct 2026 11:31:11 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E8=AF=BB=E6=A0=A1=E9=AA=8C=E6=94=BE?= =?UTF-8?q?=E8=BF=87=E3=80=8C=E4=B8=8D=E4=B8=80=E5=AE=9A=E4=BC=9A=E3=80=8D?= =?UTF-8?q?=EF=BC=88BUG-1461=20=E5=A4=8D=E9=AA=8C=E8=A1=A5=E4=BF=AE?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LutgzyJqNhPpZy1nFsJtN3 --- frontend/src/lib/personal-report-reading.ts | 6 ++++-- frontend/tests/report-reading-20261027.test.tsx | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/personal-report-reading.ts b/frontend/src/lib/personal-report-reading.ts index b8f98d31..4893af43 100644 --- a/frontend/src/lib/personal-report-reading.ts +++ b/frontend/src/lib/personal-report-reading.ts @@ -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 = /(? 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; } diff --git a/frontend/tests/report-reading-20261027.test.tsx b/frontend/tests/report-reading-20261027.test.tsx index 07d7ade1..47c5e456 100644 --- a/frontend/tests/report-reading-20261027.test.tsx +++ b/frontend/tests/report-reading-20261027.test.tsx @@ -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() }],