diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 269cbb82..934bd6a1 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -101,8 +101,9 @@ | `TASK-rectification-superseded-focus-duplicate-20260910.md` | `PROGRESS-rectification-superseded-focus-duplicate-20260910.md` | P0:一轮两次 batch 让感情采集题被顶替成 superseded 行;题号唯一约束含已结束行、汇总只聚合 declined/skipped,计划层看不见→撞号 `duplicate_focus` 被当「已问过」→出口误走交付旁白无卡(BUG-644);交付口吻与 `can_adopt=false` 矛盾(BUG-645) | 待验收(环境缺口:`next build` / 真人走查) | `a3a51c32`(BUG-644/645) | | `TASK-rectification-exhausted-gate-exit-20260910.md` | `PROGRESS-rectification-exhausted-gate-exit-20260910.md` | 五领域全拒答 + 三件带月经历:门槛句后无载体、客户端误报「没有拿到下一个问题」并循环「接着问」(BUG-646);第三件被留作 holdout 导致永远没有选择题(BUG-647)。含产品建议:一次性开放追问 + 终态标记 + 穷尽后释放 holdout | 已被取代(并入采集重设计单) | — | | `TASK-rectification-collection-redesign-20260910.md` | `PROGRESS-rectification-collection-redesign-20260910.md` | 产品口径:用户先说、系统从已说的事锚定追问、不得用生日推年份、不得说「领域」、永远交付结果。无固定题数:收集问题池按信息价值排序问到训练门开;选择题问到收敛门开或增益见底;门关不出结果只出精确缺口句并保持开放;≥4 件才留 holdout;撤回 BUG-642 年份线索、BUG-646 单终态与「暂定采用」;Skill 10.0.23(BUG-646~648) | 待验收 | `dd8f35f7` | -| `TASK-rectification-year-focus-overlay-20260916.md` | `PROGRESS-rectification-year-focus-overlay-20260916.md` | 真机:定向健康题选 A 后打字给年月,助手追问「是你本人做的吗」,追问句下面挂着录入卡(`set-focus` 同号覆盖年月焦点题干、`event_date_entry` 仍在,BUG-908);事件入账后年月焦点没关(BUG-909,回放定 resolve 还是计划层);答短句撞「本轮达到步骤上限」(BUG-910,host 前置接无年月短句,先 investigating);persisted 问题块无 `--assistant-content-inset`(BUG-911)。**产品追加拍板:「哪一类事 + 发生年月」录入卡整个删掉,年月阶段直接打字(推翻 precision-gate 单 T3 与 SKILL.md:84)**。主体默认本人不追问,Skill 10.0.29 | 待验收 | `codex/rectification-year-focus-overlay-20260916` | -| `TASK-rectification-dead-d9-choice-20260916.md` | `PROGRESS-rectification-dead-d9-choice-20260916.md` | 真机(6aabbe38):删卡流程已通,但**P0** D9 感情题没有自己的探针,`stampChoiceSchemaWithProbe` 退到最高增益探针,盖上了 **D24 学业六星座对照探针**(BUG-375 (1) 复发):答「没有」按 D24 计分,04:48–04:59 收窄不可信;GET 投影又匹配不上 → 无卡(BUG-912);打字答「没有」后平局直接出交付卡待回放定性(BUG-913);`NAKSHATRA_TRAITS` 整对塞进一个 option,卡头把相反两极列成共同点(BUG-914)。**串行在 year-focus-overlay 验收之后** | 待验收 | `codex/rectification-dead-d9-choice-20260916` | +| `TASK-rectification-year-focus-overlay-20260916.md` | `PROGRESS-rectification-year-focus-overlay-20260916.md` | 真机:定向健康题选 A 后打字给年月,助手追问「是你本人做的吗」,追问句下面挂着录入卡(`set-focus` 同号覆盖年月焦点题干、`event_date_entry` 仍在,BUG-908);事件入账后年月焦点没关(BUG-909,回放定 resolve 还是计划层);答短句撞「本轮达到步骤上限」(BUG-910,host 前置接无年月短句,先 investigating);persisted 问题块无 `--assistant-content-inset`(BUG-911)。**产品追加拍板:「哪一类事 + 发生年月」录入卡整个删掉,年月阶段直接打字(推翻 precision-gate 单 T3 与 SKILL.md:84)**。主体默认本人不追问,Skill 10.0.29 | 已验收 | `6aabbe38`(BUG-908~911,Skill 10.0.29):tsc 0 / lint 0 error / npm test 3414 条 31 红与基线 05cf20fb 逐条相同 / `/` Static / 首屏 gzip 620,502→620,107(−0.06%)/ 快速门 Python 段 798 绿。两条小项(host 前置排在会话校验之前、`answer.host_year_entry` 未登记)并入 dead-d9 修复单 T2 | +| `TASK-rectification-dead-d9-choice-20260916.md` | `PROGRESS-rectification-dead-d9-choice-20260916.md` | 真机(6aabbe38):删卡流程已通,但**P0** D9 感情题没有自己的探针,`stampChoiceSchemaWithProbe` 退到最高增益探针,盖上了 **D24 学业六星座对照探针**(BUG-375 (1) 复发):答「没有」按 D24 计分,04:48–04:59 收窄不可信;GET 投影又匹配不上 → 无卡(BUG-912);打字答「没有」后平局直接出交付卡待回放定性(BUG-913);`NAKSHATRA_TRAITS` 整对塞进一个 option,卡头把相反两极列成共同点(BUG-914)。**串行在 year-focus-overlay 验收之后** | **验收未通过(P0)** | `227a7571`+`8d7dfbf0`:不借探针、一列一句、BUG-913 定性均过;但自建探针只在盖戳时注入内存 state,生产答题路径读持久化 state → `stale_probe` 报错、GET 无卡、idle 立刻 superseded(生产路径回放实证)。修复单见下一行 | +| `TASK-rectification-dead-d9-choice-fix-20260916.md` | `PROGRESS-rectification-dead-d9-choice-fix-20260916.md` | **验收修复单**:自建分盘探针照 `withNakshatraBoundaryProbe` 模式在每个读 state 的地方(盖戳 / 答题 / `previousInferenceFromReceipt` / GET 投影 / idle 过期判定 / 计划承接)从 receipt 确定性重建(BUG-915);测试改走生产路径、删手工塞探针的 fixture;顺带 host 前置挪到会话校验之后、登记 phase(BUG-916)。**staging 现状:风格题答不了,先跳过** | 待领取 | — | ### 聊天主链路与首页 diff --git a/docs/tasks/TASK-rectification-dead-d9-choice-fix-20260916.md b/docs/tasks/TASK-rectification-dead-d9-choice-fix-20260916.md new file mode 100644 index 00000000..d26580ef --- /dev/null +++ b/docs/tasks/TASK-rectification-dead-d9-choice-fix-20260916.md @@ -0,0 +1,67 @@ +# 验收修复单 · D9 自建探针只活在内存里:答题报 stale_probe、GET 无卡、idle 立刻 superseded(2026-09-16) + +## 0. 基线与验收对象 + +- 验收对象:`227a7571` + `8d7dfbf0`(任务书 `TASK-rectification-dead-d9-choice-20260916.md`,已合入并部署 staging)。 +- 代码基线:`8d7dfbf0`。分支:`codex/rectification-dead-d9-choice-fix-20260916`。 +- BUG 段:**BUG-915 起**(基线最大 BUG-914)。 +- 门禁数字(本机 Linux,`node_modules` 软链,`next build --webpack`):`tsc` 0 错;lint 0 error / 116 warning;`npm test` 3414 条、31 红,失败清单与基线 `05cf20fb`(3405 条、31 红)**逐条相同**;Python 定向 `refinement_packet` / `event_probes` / `engine_memoization` 63 绿。门禁本身是绿的,**红在生产路径没被测试覆盖**。 + +## 1. 验收结论 + +| 项 | 结论 | 证据 | +| --- | --- | --- | +| T1a 不再借最高增益探针 | 通过 | `inference-adapter.ts:553` `const next = matched`;测试断言 `probe_id` 不再是 D24 | +| T1b 风格题自建探针 | **未通过(P0)** | 探针只在 `expectedAnswerSchemaFor` 盖戳那一刻由 `withFollowupOwnedProbe` 注入内存 state(`server-focus.ts:136`),**没有进 `decision_receipt.inference_state`**。生产的答题路径 `answer-choice.ts:591` 用 `withNakshatraBoundaryProbe(previousInferenceFromReceipt(receipt))` 读持久化 state,`matchProbeForChoice` 找不到 `probe:d9_relationship:relationship_style` → `stale_probe` → `:852` 抛 `agentic_rectification_stale_probe`。我用任务书自己的 fixture 按生产路径回放(state 不含自建探针):`applied=false reason=stale_probe`。**点选或打字回答新的 D9 题都会报错,比修前更糟**(修前至少错分入账,修后答不了) | +| T1c 从落库副本投影 | **未通过** | `persistedDistinguishCard`(`method-followup.ts:3319-3350`)先要 `liveInferenceDistinguishProbe(input.inferenceState)` 在持久化 state 里找到该探针,找不到即 null;同一回放里 GET `choice_card` 为 **null**。任务书第二条测试是手工把自建探针塞进 `buildInferenceState({probes:[D24, 自建]})` 再断言有卡——fixture 不是生产形状(AGENTS §7.4 精神) | +| T1c 过期 → superseded | **未通过(反向误伤)** | `persistNextInterviewIfIdle`(`answer-choice.ts:1607-1643`):`liveDistinguishProbe(持久化 state, schema)` 对自建探针恒为 null → `staleDistinguish=true` → 刚落库的 D9 焦点在**每次 idle persist 时被 superseded**(route.ts 四处 + agent-run 一处都会调) | +| T2 BUG-913 closed_by_design | 通过 | `yearlessPersonalityCanAsk({datedCount:5})===false`;结论与 BUG-689 出口一致 | +| T3 BUG-914 一列一句 | 通过 | Python 断言 `traits` 长度 1、两 option 不同句;前端断言两极不同时进 `shared_traits`;63 绿 | +| T4 记录 | 通过(需随本单改状态) | BUG-912 现状写 `resolved` 不成立,改 `investigating` 直到本单过门 | + +**总结论:未通过。** 根因是一个:自建探针没有像月宿边界探针那样在**每个读 state 的地方**重建。 + +## 2. 修法(照 `withNakshatraBoundaryProbe` 的既有模式) + +月宿边界探针也不在引擎 state 里,它的做法是三处都从 receipt 重建:`server-focus.ts:124`(盖戳)、`answer-choice.ts:591`(答题)、`inference-adapter.ts:235`(`previousInferenceFromReceipt` 之后)。自建分盘探针照抄: + +### T1 `withOwnedDistinguishProbes(state, receipt)`(BUG-915) + +- 新函数从 `decision_receipt` 的 `window_scan.transitions` + `candidates` **确定性**重建所有 `varga_observation` / `precision_stage` 风格题的自建探针(对每个 `candidates_differ` 的层调 `buildVargaDistinguishFields`),追加进 `state.probes`(同 id 不重复)。不依赖当前 followup,避免「哪个 followup 在问」的时序问题。 +- 接入点(缺一不可,写成源码契约断言):`server-focus.ts` 盖戳;`answer-choice.ts:591` 答题;`inference-adapter.ts` `previousInferenceFromReceipt` 出口(或紧随其后的同一包装);`interview-state.ts` `choiceCardFromCaseDossier` 传给投影的 `inferenceState`;`persistNextInterviewIfIdle` 的 `inferenceForStale`;`method-followup.ts` 计划层承接焦点用的 `liveDistinguishProbe`。 +- 重算后 `answered_probes` 里的自建条目要能被引擎回写的 state 保留:确认 `autoRescoreAfterEvidenceChange` / compare 回写 `inference_state` 时 `answered_probes` 不按 `probes` 白名单过滤;若过滤,自建条目要在重建时一并保留。 +- 验收(**必须走生产路径**): + - 回放:持久化 state 只含 D24 → 盖戳得到自建 `probe_id` → 用 `answer-choice.ts` 同一段代码(导出一个薄函数或直接调用 `answerRectificationChoice` 的纯部分)答 C → `applied=true`、`answered_probes` 末位 `semantic_key=d9_relationship:relationship_style`、后验只按 D9 分组变化。 + - GET:同一持久化 state 下 `choiceCardFromCaseDossier` 返回卡且 `question_id` 与 `current_question` 一致。 + - idle:同一状态下 `persistNextInterviewIfIdle` **不** supersede 该焦点;改账本使 `candidate_split_hash` 变化后才 supersede 并落下一问。 + - 删掉手工塞探针的 fixture,改用上面的生产形状。 + +### T2 顺带(BUG-916,P2/P3) + +- `agent-run.ts:341-360` 年月阶段 host 前置(BUG-910)排在 `dossier.case.sessionId !== sessionId` 校验之前,跨会话消息也会被写成确定性轮;把前置挪到该校验之后(计费之前不变)。 +- `phases: ["answer.host_year_entry"]` 不在 `PUBLIC_RECTIFICATION_PHASES`;要么登记,要么复用 `answer.host_fallback`。tsc 不报是因为类型是 string。 + +### T3 记录 + +- BUG-912 改 `investigating` → 本单过门后 `resolved`,并写「首版只在盖戳时注入内存 state,答题/GET/idle 三处读持久化 state 找不到」。BUG-915/916 新增。BUG-375 复发段补一句。CHANGELOG、PROGRESS、真机清单更新。 + +## 3. 让步顺序 + +1. 若 `previousInferenceFromReceipt` 出口统一注入会让既有 `rectification-inference-machine` 断言变红(state.probes 数量),允许只在六个接入点各自包装,但要有源码契约测试钉住六处。 +2. T2 的 phase 登记可让步为复用 `answer.host_fallback`。 +3. T1 验收三条与 T3 不可让步。 + +## 4. 开工前置命令 + +```bash +git fetch origin --prune +git worktree add -b codex/rectification-dead-d9-choice-fix-20260916 .worktrees/rectification-dead-d9-choice-fix-20260916 origin/staging +cd .worktrees/rectification-dead-d9-choice-fix-20260916/frontend +./node_modules/.bin/tsx --test tests/rectification-dead-d9-choice-20260916.test.ts tests/rectification-inference-machine*.test.ts 2>&1 | tail -5 +grep -o "BUG-[0-9]\+" ../docs/BUG_HISTORY.md | sort -t- -k2 -n | tail -1 +``` + +## 5. 给产品负责人 + +- **staging 当前状态**:D9/D10 风格题不再错分,但**答不了**(点选会报错)。在修复单过门前,遇到风格题请先跳过(D)或补一件带年月的事。 +- 事发 Case 的 04:48–04:59 仍不可采用(建立在错分上)。