fix(rectification): drop same-year probes after a dated answer (BUG-592)

Point-choice used one compare packet, so a May existence card and the same-domain year card both stayed eligible. Hard-exclude same domain+year; keep adjacent years downranked.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-08 15:47:25 +08:00
parent f17af254c5
commit 8ae17a2630
10 changed files with 562 additions and 12 deletions
+19 -3
View File
@@ -8647,9 +8647,9 @@
## BUG-559 | 同年月拆成多道「有没有 X」,同域同年再问,无锚点性格卡
- 状态:mitigated
- 状态:mitigated(点选同年复发见 BUG-592
- 首次发现:2026-09-06
- 最近更新:2026-09-06
- 最近更新:2026-09-08
- 影响面:`scripts/rectification/event_probes.py``asked_probe_keys``existenceProbeAsked``rankRenderableDiscriminators`
- 用户现象:同一大运边界月按领域各问一次「那时候有没有入职 / 有没有搬家」;已问过某年 5 月后又问同年无月份;没有对应经历的「平时做事更接近哪一种」性格卡也会出。
- 触发条件:引擎按领域扫描边界月;去重只看账本年份不看已问探针;`varga_style` 不要求同域带年月证据。
@@ -8657,7 +8657,7 @@
- 修复:请求可带 `asked_probe_keys`(不进结果指纹)。已问 `domain.Y.MM.*` 后,同年与相邻年不再出该领域 existence / activation。`varga_style` 无同域 confirmed 带年月事件则 `dropped_probes(unanchored_varga_style)`;有锚点时 hint 带年月、分数 ×0.8,用户可见题干仍不写年份。邻近账本事件以领域+年月(无摘要)写入 `user_prompt_hint`。B2 同年月合并卡 `choice_kind=boundary_pair` 本单未做。
- 验证:`tests/test_rectification_event_probes.py` 已问同年相邻年不再产出;`frontend/tests/rectification-probe-year-dedupe-20260906.test.ts`
- 防复发:不得把 `asked_probe_keys` 写入结果指纹。点选答案仍不写证据账本。不得为性格卡在用户可见题干里写年份。
- 相关记录:BUG-540、BUG-390
- 相关记录:BUG-540、BUG-390、BUG-592
- 复发自:无
- 修复版本:`3a9ae736`
@@ -9174,3 +9174,19 @@
- 复发自:BUG-462`:next` 重试本为穷尽采集撞开场题号)
- 修复版本:待提交(`codex/rectification-covered-domain-recollect-20260908`
## BUG-592 | 答完「2023 年 5 月前后」又问「2023 年前后」(同域同年点选题)
- 状态:resolved
- 首次发现:2026-09-08
- 最近更新:2026-09-08
- 影响面:`inspectDiscriminatorProbes``rankRenderableDiscriminators``existenceProbeAsked` / `sameYearProbeAsked`、点选后 `decideAfterInferenceChange`
- 用户现象:已经答过某年某月「有没有入职/换工作」,下一张点选卡又问同一领域同一年的整年题,题干几乎同一句。
- 触发条件:同一次候选比较生成的 `inference_state.probes` 里同时有 `domain.YYYY.MM.*``domain.YYYY.*`;点选不重跑引擎,按信息量从高到低问。
- 根因:BUG-559 引擎侧只在重新生成时按 `asked_probe_keys` 屏蔽同年与相邻年;点选下一题走 TS 对照包。`inspectDiscriminatorProbes` 只认精确 `semantic_key` / hash / `probe_id`,没有领域+年份规则。`rankRenderableDiscriminators` 虽调 `existenceProbeAsked`,结果只是把 `asked=true` 交给 `rankDiscriminatorScore` 降权,不排除。旧验证只锁了引擎重生成和 `existenceProbeAsked` 返回值。
- 修复:同领域同年份硬排除(`dropped_probes(reason="same_year_asked")`),`year=0` 的分盘风格题不动。相邻年(±1)继续降权、不硬排除。`existenceProbeAsked` 拆出 `sameYearProbeAsked`。引擎 `asked_probe_keys``SCORE_DELTA`、四选项合同、Skill 版本(仍 10.0.15)不动。
- 验证:`frontend/tests/rectification-probe-year-dedupe-20260906.test.ts`:答完 5 月后不得再问同年 activation、相邻年 2024 仍可问、`buildMethodFollowupPlan` 同口径、事故五题回放第五题不再是同年整年题。`frontend/tests/rectification-inference-machine.test.ts` 锁核心 identity 不去重、inspect 硬排除。`tests/test_rectification_event_probes.py` 不改、须仍绿。
- 防复发:同一份 probes 列表里,同领域同年份答过一道就不得再问第二道。不得只靠降权。相邻年不得被硬排除。点选路径必须走 `inspectDiscriminatorProbes` / `rankRenderableDiscriminators` 的同年硬排除,不能只依赖引擎重生成。
- 相关记录:BUG-559
- 复发自:BUG-559(引擎侧只管重生成;TS 侧只降权)
- 修复版本:待提交(`codex/rectification-same-year-probe-dedupe-20260908`
@@ -0,0 +1,41 @@
# PROGRESS · 同域同年点选题去重(2026-09-08)
工作树:`.worktrees/rectification-same-year-probe-dedupe-20260908`
分支:`codex/rectification-same-year-probe-dedupe-20260908`
任务书:`docs/tasks/TASK-rectification-same-year-probe-dedupe-20260908.md`
基线:`origin/staging` @ `f17af254`(含 BUG-592 修复单 `f3a1a583`;代码基线仍是 `7ca6ade2`
本单状态:**待验收**。
未改:引擎 `asked_probe_keys``SCORE_DELTA`、四选项合同、采用门、确认门、Skill 版本(仍 10.0.15)。相邻年仍只降权。
## 做了什么
- **决策 1** `sameYearProbeAsked`:同 `domain` 且同 `year``SEMANTIC_YEAR_KEY` 解析)硬排除。`inspectDiscriminatorProbes``rankRenderableDiscriminators`event / contrast)都 `dropped_probes(reason="same_year_asked")``year=0` 分盘风格题不受影响。
- **决策 2** 相邻年(±1)仍走 `existenceProbeAsked``rankDiscriminatorScore` 降权,不硬排除。`remainingReverseVerifyProbes` 继续按邻近年排除(采用后核对,不动)。
- **决策 3** `remainingConflictProbes` 改用 `sameYearProbeAsked`,让邻近年事件探针还能进排序降权,而不是在进目录前被整年砍掉。
- **决策 4** 记录 BUG-592(复发自 BUG-559)、CHANGELOG、手测脚本第 9 条。
## 三栏(被触碰断言)
| 用例 | 原值 | 新值 | 理由 |
| --- | --- | --- | --- |
| 答完 `career.2023.05.*` 后选 `career.2023.dasha_activation` | 会问(inspect 无年份规则;followup 只降权) | 不问,`dropped_probes.reason = same_year_asked` | 决策 1 |
| 同列表 `career.2024.04.*` | 可问 | 仍可问 | 决策 2 |
| 事故五题回放第五题 | `career.2023.dasha_activation` | D10 风格题或交付 | 决策 1 |
| 核心 `isDuplicateProbe` | 不同 key 不算重复 | 仍不算;inspect 负责硬排除 | 旧防线缺口 |
## 测试
- `frontend` `./node_modules/.bin/tsc --noEmit`exit 0
- 任务书指定 TS 切片(`tests/rectification-*.test.ts` + `agent-voice-copy-contract.test.ts`,排除 database):**1012 passed / 0 failed**
- `.venv/bin/python -m pytest tests/test_rectification_event_probes.py -q`34 passed
- `npm run lint`:本机对改动文件 ReadLints 0 error;全量 `npm run lint` 未在本轮沙盒跑完
- 浏览器真人走查:本轮未跑,见 `docs/testing/rectification-scenarios-20260907.md` §9
- 工作期间 `origin/staging` 又合入 `06e44104`BUG-593)。本分支仍基于 `f17af254`,未自动 merge(工作区有未提交文档与代码,且与 BUG-593 改了同一批 changelog / BUG_HISTORY / 手测脚本)
## 偏离
1. 任务书开工基线写 `7ca6ade2`。本 worktree 跟 `origin/staging` 尖端 `f17af254`(多了 BUG-593 修复单文档,无代码差)。
2. `sameYearProbeAsked` 放在 `probe-question-contract.ts`,避免 `candidate-contrast-packet``method-followup` 循环依赖。
3. `remainingConflictProbes` 从邻近年硬排除改为仅同年硬排除,否则 event 探针路径仍会把有信息量的 2024 题提前砍掉。
+1 -1
View File
@@ -76,7 +76,7 @@
| `TASK-rectification-other-collect-fallback-20260908.md` | `PROGRESS-rectification-other-collect-fallback-20260908.md` | 七领域问完落到「也可以再说一件」、职业题从未出现、不自动出卡:`USER_COLLECT_QUESTION.other` 仍有三条活路(职业焦点 `target_domain` 压成 other 后被 active-focus 承接 followup 重建;set-focus 两次无效兜底查表;无领域采集归 other),`collect:other:*` 焦点挂着让 `persistNextInterviewIfIdle` 的出卡路径永远不跑 | 已验收通过(触发链仍 investigatingBUG-586 mitigated | `9aec5029`BUG-586 |
| `TASK-rectification-probe-replay-loss-20260908.md` | `PROGRESS-rectification-probe-replay-loss-20260908.md` | **P0** 收敛不了的直接原因:答完 5 道题范围收到 8 分钟,之后每补一件经历触发的重算换了候选集,`buildInferenceState` 找不到已答题定义(引擎与对照包按 asked keys 排除、状态 probes 不携带、分盘 key 内嵌分钟列表)→ `rounds:[]`、posterior=prior,交付回到 29 分钟;证据轮旁白不报范围变化;交付卡闪现待证实 | 已验收通过(真实 Case 范围收到 2 分钟;BUG-589 闪现 investigating | `df182c16`BUG-587589 |
| `TASK-rectification-covered-domain-recollect-20260908.md` | `PROGRESS-rectification-covered-domain-recollect-20260908.md` | 范围已收到 2 分钟、决策已是采用,却再问答过的财务题:职业覆盖后的 yearless→采集分支(L2224)不看领域是否已覆盖;`shouldSkipFollowupPersist` 把它当剩余采集挡住出卡;`persistCollectFocus` 撞 id 无条件 `:next` 再插;holdout `occupied` 不认 health/health_pressure 同义 | 已验收通过 | `7ca6ade2`BUG-590591 |
| `TASK-rectification-same-year-probe-dedupe-20260908.md` | `PROGRESS-rectification-same-year-probe-dedupe-20260908.md` | 答完「2023 年 5 月前后」又问「2023 年前后」(BUG-559 复发):点选不重跑引擎,同一份 probes 里同域同年两题并存;TS 侧 `existenceProbeAsked` 只降权不排除,`inspectDiscriminatorProbes` 连领域+年份规则都没有。决策:同域同年硬排除、相邻年维持降权 | 待执行 | `codex/rectification-same-year-probe-dedupe-20260908`BUG-592 |
| `TASK-rectification-same-year-probe-dedupe-20260908.md` | `PROGRESS-rectification-same-year-probe-dedupe-20260908.md` | 答完「2023 年 5 月前后」又问「2023 年前后」(BUG-559 复发):点选不重跑引擎,同一份 probes 里同域同年两题并存;TS 侧 `existenceProbeAsked` 只降权不排除,`inspectDiscriminatorProbes` 连领域+年份规则都没有。决策:同域同年硬排除、相邻年维持降权 | 待验收 | `codex/rectification-same-year-probe-dedupe-20260908`BUG-592 |
| `TASK-rectification-delivery-report-facts-20260908.md` | `PROGRESS-rectification-delivery-report-facts-20260908.md` | 交付轮验证报告写「宽度 29 分钟」「主限偏向 05:06 / 分盘大运偏向 04:59」「04:53 D10 升狮子座」,与卡片(04:51–04:53)矛盾:`skill_verification_report` 用引擎推断前的 width / dasha_agreement,分盘星座让模型自算 | 待执行 | `codex/rectification-delivery-report-facts-20260908`BUG-593Skill 10.0.16 |
| `TASK-api-not-configured-mislabel-20260904.md` | `PROGRESS-api-not-configured-mislabel-20260904.md` | 16 处路由把数据库瞬断(部署切换窗口)兜底翻译成 503「服务尚未配置」;改为仅配置错误用该文案,其余 `service_unavailable`,收敛为共享 helper | 已验收 | `5483649b`(BUG-542);2 条子进程测试留 CI Node 22 复核 |
| `TASK-rectification-ux-20260902.md` | `PROGRESS-rectification-ux-20260903.md` | 会话面空白假死与交互摩擦 | 已验收 | `d159f08e`(09-03 在新基线重做后合入,BUG-505509 |
@@ -127,3 +127,15 @@
- 若范围变了,证据轮旁白必须出现「范围从 … 变为 …」
- 不得出现:只说「记下了」,交付时范围弹回大约半小时,候选分数跟没答过题一样
## 9. 同领域同年份的点选题只出一次
资料:家人记得大概时间,钟点任意,范围「差不多准」。地点任意公开城市。
开场后说到能出对照卡。若出现「某年某月前后有没有入职/换工作」,答「明确没有发生」。
期望:
- 下一张点选卡不得再问同一领域同一年的整年题(例如刚答过 2023 年 5 月,不得再问 2023 年前后)
- 相邻年(例如 2024 年 4 月)仍可以问
- 不得出现:同一句「有没有入职、换工作或职责加重」只把月份去掉再问一遍