docs(tasks): accept BUG-584~589 fixes; covered-domain recollect fix brief (BUG-590/591)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
This commit is contained in:
@@ -72,9 +72,10 @@
|
||||
| `TASK-rectification-stop-rescore-fix-20260907.md` | `PROGRESS-rectification-stop-rescore-fix-20260907.md` | **P0**:BUG-579 的停止路径用「裸重算」(`rescoreMinuteAfterWindowChange` 不重建 `inference_state`、不重放已答探针、不写 transition),停止后范围变宽、卡片变成引擎裸支持度、采用 RPC 报 `candidate_state_inconsistent`;无框区分题经 `spokenCollectFallbackFollowup` 变成 domain=other 的采集题,再次冒出开场句 `GENERIC_COLLECT_QUESTION`;holdout 采集排在带年月采集之前 | 已验收通过(逻辑);但同提交含区间卡 tsc 错,整体不可部署 | `ab57d03f`(BUG-581~582) |
|
||||
| `TASK-rectification-range-delivery-card-20260907.md` | `PROGRESS-rectification-range-delivery-card-20260907.md` | 结尾重设计:四张分钟卡 + 相对支持度换成一张区间交付卡(范围、代表分钟、稳定/敏感主题、边界句)+ 只列未问 D9/D10/月宿分歧的 2~3 列对比面板(文案只取类型表),动作只有「按这个范围用 / 再补一件经历」;删交付旁白里三行预测窗口;Skill §9 口径改、bump 10.0.15 | **未通过**:tsc 1 错(判空顺序);P2 预测窗口句兑现不了;P3 再补经历无提示 | `ab57d03f`;修复单 `TASK-rectification-range-delivery-fix-20260907.md` |
|
||||
| `TASK-rectification-range-delivery-fix-20260907.md` | `PROGRESS-rectification-range-delivery-fix-20260907.md` | 区间卡修复单:`candidateResult` 判空提到最前(tsc 阻断);预测窗口接到采用后首轮或删句;「再补一件经历」隐藏卡后给采集提示;进度记录须贴 tsc 原文 | 待验收 | `codex/rectification-range-delivery-fix-20260907`(BUG-583) |
|
||||
| `TASK-rectification-duplicate-narration-20260907.md` | `PROGRESS-rectification-duplicate-narration-20260907.md` | 每轮采集旁白说两遍 + 题干在正文与问题块各一次:`step-answer` 的 set-focus 例外(BUG-533)放行了 set-focus 前后两个 step 的正文并拼接;`detachCollectSpokenAssistantText` 只剥逐字后缀,模型写进正文的问句没有代码守卫(BUG-488 防线只在提示词) | 待验收 | `codex/rectification-duplicate-narration-20260907`(BUG-584~585) |
|
||||
| `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` 的出卡路径永远不跑 | 待验收(2.2 触发链仍 investigating) | `codex/rectification-other-collect-fallback-20260908`(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 分钟;证据轮旁白不报范围变化;交付卡闪现待证实 | 待验收 | `codex/rectification-probe-replay-loss-20260908`(BUG-587~588;P3 闪现仍 investigating) |
|
||||
| `TASK-rectification-duplicate-narration-20260907.md` | `PROGRESS-rectification-duplicate-narration-20260907.md` | 每轮采集旁白说两遍 + 题干在正文与问题块各一次:`step-answer` 的 set-focus 例外(BUG-533)放行了 set-focus 前后两个 step 的正文并拼接;`detachCollectSpokenAssistantText` 只剥逐字后缀,模型写进正文的问句没有代码守卫(BUG-488 防线只在提示词) | 已验收通过 | `9d1c08ca`(BUG-584~585) |
|
||||
| `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` 的出卡路径永远不跑 | 已验收通过(触发链仍 investigating,BUG-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-587~589) |
|
||||
| `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 同义 | 待执行 | `codex/rectification-covered-domain-recollect-20260908`(BUG-590~591) |
|
||||
| `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-505~509) |
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# TASK · 生时校正修复单:范围已收到 2 分钟、决策已是采用,却把答过的财务题再问一遍(2026-09-08)
|
||||
|
||||
- 基线:`origin/staging` @ `df182c16`(BUG-584~589 已合入并部署;事故 Case 就是这版跑出来的,Skill 10.0.15)
|
||||
- 分支:`codex/rectification-covered-domain-recollect-20260908`,基于 `origin/staging`
|
||||
- 执行方:coding agent;验收:Claude
|
||||
- 涉及文件:`frontend/src/lib/rectification-agentic/v9/method-followup.ts`(L2224 起的 yearless→采集分支、`holdoutFollowupFor`)、`v9/server-focus.ts`(`persistCollectFocus` 的 `:next` 重试)、`v9/answer-choice.ts`(`shouldSkipFollowupPersist`)
|
||||
- BUG 编号起点:**BUG-590**(`docs/BUG_HISTORY.md` 当前最大 BUG-589)
|
||||
- 优先级:**P1**(收敛已经成功,出口被一道重复题堵死;用户原话"怎么又问相同的问题 而且时间已经收敛到 2 分钟的范围了")
|
||||
|
||||
## 1. 事故实证(2026-09-08 staging `df182c16`,Case 导出;只写结构)
|
||||
|
||||
| 项 | 事实 |
|
||||
| --- | --- |
|
||||
| 推断状态 | 6 道题全部重放(`rounds` 6 条、`carried: true`、分盘 key 已是星座分区),`credible_range = 04:51–04:53`,`stop_reason = probe_pool_exhausted` |
|
||||
| 决策 | `type = ready_to_adopt`、`session_outcome = adopt_representative`、`can_adopt = true`、`step_state.stage = deliver` |
|
||||
| 当前问题 | `collect:finance:collect_method_evidence:next`,题干 = `USER_COLLECT_QUESTION.finance` 逐字。财务领域账本里已有一条带年月的确认事件(`usage = holdout`),该领域焦点早已 `resolved` |
|
||||
| 该轮 receipt | `rectification-set-focus` **failed** `focus_idempotency_conflict`;随后闲置路径把同题以 `:next` 后缀落库 |
|
||||
| 界面 | 没有区间交付卡(采集焦点挂着即 `interviewQuestionBlocksAdoptOffer`),输入框上方是财务题 |
|
||||
|
||||
BUG-587 的重放已经把范围收到 2 分钟,出口本该是区间交付卡。
|
||||
|
||||
## 2. 根因
|
||||
|
||||
### 2.1 BUG-590(P1):职业覆盖后的"无年份分盘题→采集"分支不看领域是否已覆盖
|
||||
|
||||
`method-followup.ts` L2224:`!next && dashaCovered && coverageComplete && occupationCovered` 时取 `yearlessDiscriminators[0]`(本例是 D11 财富分盘的对照题,D24 学业题因账本已提到该分盘被降权、D12 家人题被拒答),把它的领域直接变成一道 **dated collect**(`intent = collect_method_evidence`、`source = method_coverage`、无 `choice_frame`)。分支只检查 `!declined.has(domain)`,不检查该领域是否已有带年月事件、是否已问过采集题。财务已经答过,于是再问一遍。
|
||||
|
||||
这个分支的本意是"分盘对照题没有年份可锚,先向该领域要一件带年月的事";领域已经有带年月事件时,再要一件也锚不上(引擎把它标成 `yearless_ungrounded_contrast` 不是因为缺事件),应当跳过该领域、继续找下一个,没有就交付。
|
||||
|
||||
链条第二环:`answer-choice.ts::shouldSkipFollowupPersist` 对 `canAdopt = true` 的决策,只要 `isRemainingEvidenceCollect(followup)`(领域在 `DATED_COLLECT_ORDER` 里)就不跳过 → 采用被这道题挡住。第三环:工具层 set-focus 用同一 `next_followup` 落库,`questionId` 与已 resolved 的财务焦点相同 → `focus_idempotency_conflict`;闲置路径再来一次。
|
||||
|
||||
### 2.2 BUG-591(P2):采集焦点撞 id 时无条件加 `:next` 再插一次
|
||||
|
||||
`server-focus.ts::persistCollectFocus` L359:`insertFocus(questionId)` 报 `focus_idempotency_conflict` 就改用 `${questionId}:next` 再插。这是 `75fc456d`(BUG-462 附带)为"穷尽采集撞开场题号"加的;BUG-586 删掉 other 穷尽采集后,它只剩副作用——同一领域的采集题只要被计划层重复派出,就一定能以 `:next` 落地。撞 id 本身就是"这题问过了"的信号,非 `collect_retry` 的采集题应当在这里止步。
|
||||
|
||||
### 2.3 P2:holdout 的 `occupied` 不认 `health` / `health_pressure` 同义
|
||||
|
||||
`holdoutFollowupFor` 用账本领域算 `occupied`,账本里健康事件的 `domain = "health"`,而 `oos_blind_prompts` 用 `health_pressure`;用户答了健康事件后,holdout 仍会把健康当"没用过的线"再问一遍。`datedCollectDomainBlocked` 已经用 `hasConfirmedHealth` 处理了这对同义词,`holdoutFollowupFor` 没有。本例没触发(财务题先挡住),但下一次会。
|
||||
|
||||
### 2.4 记录:转录里选择题题干看似出现两次
|
||||
|
||||
选择题的题干在问题块 `<p>` 与卡片 `<legend class="sr-only">` 各一份,后者只给读屏,复制文本时会一起带出。视觉上只有一份,不是缺陷,不立单。
|
||||
|
||||
## 3. 决策记录
|
||||
|
||||
1. **L2224 分支加覆盖守卫。** 遍历 `yearlessDiscriminators`(不只取 `[0]`),跳过:`declined` 领域、`hasConfirmedDomain`(含 `health`/`health_pressure` 同义)为真的领域、账本或已关闭焦点里已出现过 `collect:<domain>:*` 的领域。全部跳过则 `next` 保持空。
|
||||
2. **采用优先。** `shouldSkipFollowupPersist`:`canAdopt && nextAction === "adopt_representative" && stopReason === "probe_pool_exhausted"` 时,`isRemainingEvidenceCollect` 只有在该领域**没有**确认事件且未拒答时才算"剩余采集";否则跳过持久化、走交付(`terminalNote`)。
|
||||
3. **撞 id 不再 `:next`。** `persistCollectFocus` 遇 `focus_idempotency_conflict`:`followup.collect_retry === true` 才用 `:next`,否则返回 `duplicate_focus`、不插入。`persistFocusAfterChoice` 把 `duplicate_focus` 当 `skipped` 处理,继续走交付分支。
|
||||
4. **holdout `occupied` 用同义表**:`health` ↔ `health_pressure` 归并(复用 `hasConfirmedHealth` 的口径)。
|
||||
5. 不动采用门、确认门、`MIN_SEPARATION_LEAD`、`_relative_support`、`minute_step=1`、`SCORE_DELTA`、四选项合同;Skill 不 bump。
|
||||
|
||||
## 4. 任务分解
|
||||
|
||||
### 4.1 BUG-590(决策 1、2)
|
||||
- 验收(形状用例,新建或扩 `rectification-occupation-coverage-exit.test.ts`):
|
||||
- (a) 账本:学业 2 件、感情 2 件、财务 1 件(`usage = holdout`)、事业 2 件、迁居 1 件、健康 1 件、职业 1 件;家人拒答;6 道题已答;yearless 目录里 D11/D2(财务)、D24/D5(学业)、D4(迁居)、D7/D12(家人)都在 → `buildMethodFollowupPlan().next_followup === null`。
|
||||
- (b) 同 (a) 但迁居账本为空、未拒答 → `next_followup.domain === "relocation"`(守卫只跳过已覆盖领域,不是删分支)。
|
||||
- (c) 同 (a) 的 dossier 进 `persistNextInterviewIfIdle`(decision `adopt_representative`、`probe_pool_exhausted`)→ 返回 `terminalNote: true` 的采用旁白,0 次 `setV10ConversationFocus`。
|
||||
- (d) agent-run 集成:该轮结束后 `current_question === null`、客户端 `canOfferCards` 为真。
|
||||
|
||||
### 4.2 BUG-591(决策 3)
|
||||
- 验收(`rectification-server-focus.test.ts` 扩):非 retry 采集题撞 id → `status: "duplicate_focus"`,RPC 只调一次;`collect_retry: true` 撞 id → 仍以 `:next` 落地(原值 / 新值 / 原因三栏:原"任何撞 id 都 `:next`"→ 新"仅 retry"→ 决策 3)。
|
||||
|
||||
### 4.3 P2(决策 4)
|
||||
- 验收:账本 `domain = "health"` 已确认、oos 提示 `health_pressure` → `holdoutFollowupFor` 不返回健康题。
|
||||
|
||||
### 4.4 记录
|
||||
- `docs/BUG_HISTORY.md` BUG-590(关联 BUG-586:同一"职业覆盖后多问一题"的现象,不同分支;关联 BUG-587:收敛成功后才暴露)、BUG-591(关联 BUG-462 / `75fc456d`);P2 记进 BUG-590 的防复发;`CHANGELOG.md`;`PROGRESS-rectification-covered-domain-recollect-20260908.md`;`docs/testing/rectification-scenarios-20260907.md` 加"七领域 + 职业问完后,下一步必须是区间交付卡,不得再出任何已答领域的采集题"。
|
||||
|
||||
## 5. 让步顺序
|
||||
|
||||
4.1 (a)(c) 当天必做并部署;(b)(d) 必做;4.2、4.3 同一提交;4.4 不可省。
|
||||
|
||||
## 6. 开工前置命令
|
||||
|
||||
```bash
|
||||
git fetch origin --prune
|
||||
git worktree add -b codex/rectification-covered-domain-recollect-20260908 .worktrees/rectification-covered-domain-recollect-20260908 origin/staging
|
||||
cd .worktrees/rectification-covered-domain-recollect-20260908
|
||||
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
|
||||
cd frontend && ./node_modules/.bin/tsc --noEmit; npm run lint 2>&1 | tail -1
|
||||
ls tests/rectification-*.test.ts tests/agent-voice-copy-contract.test.ts | grep -v database | xargs npx tsx --test 2>&1 | grep -E "^# (tests|pass|fail)"
|
||||
```
|
||||
@@ -74,3 +74,21 @@ ls tests/rectification-*.test.ts tests/agent-voice-copy-contract.test.ts | grep
|
||||
```
|
||||
|
||||
开工时 tsc 若仍报 `rectification-agentic-chat.tsx` L1655(BUG-583),先确认 `codex/rectification-range-delivery-fix-20260907` 是否已合入;未合入则本单不修它,进度记录里写清基线含该错。
|
||||
|
||||
## 验收(Claude,2026-09-08,`origin/staging` @ `df182c16`,staging 已部署同 SHA)
|
||||
|
||||
| 门 | 结果 |
|
||||
| --- | --- |
|
||||
| tsc | 0 错 |
|
||||
| lint | 0 error / 102 warning |
|
||||
| 前端 rectification + consultation + voice + skill-registry(非 DB) | 1253 / 0 |
|
||||
| Python v5_services + growth contract | 全绿(执行方记的 15s 壁钟用例本机未复现超时) |
|
||||
| Docker DB 套件、浏览器走查 | 环境缺口,同执行方记录 |
|
||||
|
||||
| 项 | 结论 |
|
||||
| --- | --- |
|
||||
| 4.1 BUG-584 | 通过。`stemAttached`/`publishedAny` 守卫;set-focus 后第二段 discard;半句 publish;三栏齐全。2026-09-08 真实 Case 每轮只剩一段旁白 |
|
||||
| 4.2 BUG-585 | 通过。`stripQuestionSentences` 在 agent-run 与 `attachQuestionsToTurns` 两处生效,`collectSpokenEmitted` 删除。真实 Case 正文不再含问句 |
|
||||
| 4.3 记录 | 通过 |
|
||||
|
||||
结论:通过。
|
||||
|
||||
@@ -81,3 +81,21 @@ grep -rn "也可以再说一件" src tests # 收工时必须为空
|
||||
```
|
||||
|
||||
与 `codex/rectification-duplicate-narration-20260907`(BUG-584/585,改 `step-answer.ts` / `agent-run.ts` / `collect-prompt.ts`)无文件重叠;谁后合谁 rebase。
|
||||
|
||||
## 验收(Claude,2026-09-08,`origin/staging` @ `df182c16`,staging 已部署同 SHA)
|
||||
|
||||
| 门 | 结果 |
|
||||
| --- | --- |
|
||||
| tsc | 0 错 |
|
||||
| lint | 0 error / 102 warning |
|
||||
| 前端 rectification + consultation + voice + skill-registry(非 DB) | 1253 / 0 |
|
||||
| Python v5_services + growth contract | 全绿(执行方记的 15s 壁钟用例本机未复现超时) |
|
||||
| Docker DB 套件、浏览器走查 | 环境缺口,同执行方记录 |
|
||||
|
||||
| 项 | 结论 |
|
||||
| --- | --- |
|
||||
| 决策 1–5 | 通过。`grep 也可以再说一件` 为空;`parseCollectFocusQuestionId` 让职业承接不再压成 other;同轮二次 set-focus 幂等;`isOrphanOtherCollectFocus` 放行出卡 |
|
||||
| 2.2 触发链 | 仍 investigating(执行方按事实写 mitigated,接受) |
|
||||
| 真实 Case(2026-09-08) | 职业题正常出现、其后不再出 other 句;但暴露下一道题(BUG-590,见 `TASK-rectification-covered-domain-recollect-20260908.md`) |
|
||||
|
||||
结论:通过。
|
||||
|
||||
@@ -83,3 +83,22 @@ cd .. && .venv/bin/python -m pytest tests/test_rectification_v5_services.py -q
|
||||
```
|
||||
|
||||
与 BUG-584/585(`step-answer.ts` / `agent-run.ts` 剪问句)在 `agent-run.ts` 有交叠:范围句接在剪问句之后,**先合 584/585 再做本单**,或本单 rebase 到其上。与 BUG-586 无重叠。
|
||||
|
||||
## 验收(Claude,2026-09-08,`origin/staging` @ `df182c16`,staging 已部署同 SHA)
|
||||
|
||||
| 门 | 结果 |
|
||||
| --- | --- |
|
||||
| tsc | 0 错 |
|
||||
| lint | 0 error / 102 warning |
|
||||
| 前端 rectification + consultation + voice + skill-registry(非 DB) | 1253 / 0 |
|
||||
| Python v5_services + growth contract | 全绿(执行方记的 15s 壁钟用例本机未复现超时) |
|
||||
| Docker DB 套件、浏览器走查 | 环境缺口,同执行方记录 |
|
||||
|
||||
| 项 | 结论 |
|
||||
| --- | --- |
|
||||
| 4.1 BUG-587 | 通过。真实 Case 导出:6 道题 `carried: true` 全部重放(`rounds` 6 条),分盘 key 已是星座分区,`credible_range` 04:51–04:53(此前同类流程为 29 分钟) |
|
||||
| 4.2 BUG-588 | 代码路径通过(compare 轮先剪问句再接范围句);真实转录里没有范围变化的轮次可核,留待场景清单 |
|
||||
| 4.3 P3 | `!busy && caseSnapshotLoaded` 守卫已加;闪现未复现,BUG-589 investigating |
|
||||
| 4.4 记录 | 通过 |
|
||||
|
||||
结论:通过。收敛成功后出口被 BUG-590 挡住,另立修复单。
|
||||
|
||||
Reference in New Issue
Block a user