Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
7.9 KiB
PROGRESS · 证据轮只说「记下了」却没写入(2026-09-10)
工作树:.worktrees/rectification-unwritten-evidence-claim-20260910
分支:codex/rectification-unwritten-evidence-claim-20260910
任务书:docs/tasks/TASK-rectification-unwritten-evidence-claim-20260910.md
基线:任务书写 origin/staging @ d96b24c2;开工接到 84572c07;合入前再接到 origin/staging @ 301827ad(collect-semantics 任务书 + BUG-635 决策 4 去掉年份正则)。
开工回执
- 编号 BUG-635(P1)/ BUG-636(P2)。
docs/BUG_HISTORY.md当时最大已发布号是 634。 - 顺序:分类器
expectedWrite→ 无写入的「记下了」收回并重试一次 → 第二次主持人正文且不结算 → 客户端只认最后一条 settled 助手消息 → schema 拒绝信封失败映射 → 记录。 - 未实现 BUG-641~643。同一工作树交付 BUG-637~640,见
PROGRESS-rectification-latent-audit-20260910.md。
决策 3
选 turn status=completed + answer_origin=host_fallback + 不结算计费。
实现:completeAttempt(false) → settleBilling === false → billing.release(),不写 billing.settled。客户端仍走完成轮刷新;未答焦点靠 T4 的主持人问题行。
决策 4(301827ad 修订)
expectedWrite: "evidence" | "none" | "unknown"。分类器 null/出错重试一次,仍失败则 "unknown",守卫 fail-open。没有年份正则 / 关键词兜底。 无焦点的 message 路径也跑同一分类器。正文里的「记下了」仍触发守卫(决策 1)。
已完成
- T1:
expectedWrite声明在immediateResponseIIFE 之外(POST作用域),否则runV9AgentTurn({ expectedWrite })编译失败(TS18004)。collect / choice / 无焦点 message 都走classifyTurnIntentWithRetry。provide_new_evidence或answer_current_focus+has_new_dated_event→"evidence"。opening/read_only不触发。 - T2:
streamAttempt在empty_stream之后、loadV9CaseDossier之前:needsWrite && !publicWriteToolCompleted && !hostFallbackUsed→ 第一次evidence_not_written+retractSpoken()(不进RETRYABLE_ERROR_CODES);第二次主持人正文RECTIFICATION_USER_COPY.evidenceNotRecorded。needsWrite=expectedWrite === "evidence"或正文含「记下了」。batch 已完成且无正文仍走 BUG-633applyHostFallback。 - T3:
buildAgentMessages在attempt > 1时用retryConstraintForAttempt(lastAttemptError)。 - T4:
liveQuestionOnMessages只认latestSettledAssistant。未答焦点落到既有persisted_question主持人问题行。frontend/DESIGN.md表已补完成轮未答焦点。 - T5:schema 拒绝信封
{ error: true, validationErrors: object }→tool.activity failed code=tool_call_rejected;phase 映射与 batch recap 返回 null;公开事件不含validationErrors。 - T6:BUG-635/636、CHANGELOG、走查第 15 条、任务表待验收、本文件。Skill 版本不变(
10.0.21)。
验收命令(实测)
工作树 codex/rectification-unwritten-evidence-claim-20260910,相对 origin/staging @ 301827ad。
| 命令 | 结果 |
|---|---|
frontend tsx --test 任务书相关文件(unwritten / host-fallback / spoken-collect / turn-intent / agentic-entry / agent-voice / v9-stream) |
141/141 pass |
frontend ./node_modules/.bin/tsc --noEmit |
0 error |
frontend npm run lint |
0 error / 111 warning(既有债) |
git diff --check |
干净 |
next build |
未跑;记环境缺口 |
本单测试名
collect intent maps provide_new_evidence and dated current-focus to expectedWriterunner does not use a year-utterance fallbackretry bootstrap uses the unwritten-evidence constraint only for that errorroute passes classifier expectedWrite into the agent runnerclassifyTurnIntentWithRetry fails open as unknown after two missesunwritten 记下了 retries once then host-falls-back without billingread-case then batch then set-focus then 记下了 stays on the baseline pathempty body after a completed batch still uses BUG-633 host fallbackread_only action with a dated utterance does not trigger the write guardschema rejection envelopes fail the tool and never count as a batch recaprejected batch tool-result is failed in the runner terminal statuschat live question only reads the last settled assistant message- host-fallback:
schema rejection envelopes are not treated as batch recaps or write completion - host-fallback:
year fallback is gone; only explicit evidence expectedWrite triggers the guard
既有断言改动
rectification-v9-stream.test.tsempty_stream 二次成功正文:原值「记下了这件事。」/ 新值「先继续核对。」;原因:BUG-635 把无写入的「记下了」收口成evidence_not_written,该用例只锁 empty_stream 重试。rectification-v9-agent.test.tsevidence persist keeps the first sentence when the model writes three:断言未改。原夹具 read-case 后直接写三句「记下了」、无 batch / 新夹具 batch + set-focus completed 后再写那三句 / 原因:GiteaIndependent Staging Quality Gaterun 2545 全文套件 3082/3083,该条被 635 收口成「这件我还没记上」;用例名是 persist,夹具必须真写入。
环境缺口
- 无登录态:
docs/testing/rectification-scenarios-20260907.md第 15 节真人走查未做,不得写通过。 - 未跑
next build,未核/是否仍○ Static、首屏 gzip ±2%。 - 推 staging 后才核
/api/health的deployment.gitCommit;未部署则记缺口。
未做
- 未提升
main。Skill 未升版。 - 观察项与 BUG-641~643 未做。
验收结论(Claude,2026-09-10,基线 origin/staging @ 8f9eb587,staging 已部署同 SHA)
| 项 | 结论 |
|---|---|
T1 路由 expectedWrite → 运行器;无焦点 message 也跑分类器;分类器失败重试一次后 unknown fail-open;无年份正则 |
通过(grep 'd{4}' 四个文件为空) |
T2 收尾守卫:无写入的「记下了」/expectedWrite=evidence → 收回、evidence_not_written 重试一次;第二次主持人正文、answer.host_fallback、不结算(billing.release) |
通过(rectification-unwritten-evidence.test.ts 5 条运行器用例) |
T3 重试约束句只对 evidence_not_written |
通过 |
T4 客户端只认最后一条 settled 助手消息;DESIGN.md 已补 |
通过 |
T5 Mastra 拒绝信封 → tool.activity failed code=tool_call_rejected,batch recap / phase 不认信封 |
通过 |
T6 BUG-635/636、CHANGELOG、docs/testing 第 15 条 |
通过;Bug 历史无个人资料 |
tsc --noEmit |
0 错 |
npm run lint |
0 error / 110 warning(既有债) |
| 前端全套 | 3083 条:3042 过、14 跳过、27 失败;18 条 spawnSync docker ENOENT,其余 9 条在基线 d96b24c2 同环境下逐条同样失败(@/ 别名 eval 解析、部署/环境断言),非本轮引入 |
| 静态测试数 | 3045 → 3066(+21) |
| 既有断言改动 | 两处均写明原值 / 新值 / 原因,理由成立 |
| 部署 | /api/health deployment.gitCommit = 8f9eb587 |
口径缺口(P2,已并入 TASK-rectification-collect-semantics-20260910.md T3):expectedWriteFromCollectIntent 只把 provide_new_evidence 与 answer_current_focus + has_new_dated_event 判为需要写入;按分类器提示词,用户直接用一件带年月的事回答采集题会被标成 answer_current_focus + yes 且 has_new_dated_event=false(该字段定义为「除了回答当前问题之外」),于是 expectedWrite="none",守卫只剩「记下了」文字判定兜着。这是任务书决策 4 自身的漏写,不是执行方偏差。
环境缺口:未跑 next build(worktree 下 Turbopack 拒外部软链),/ 是否仍 Static 与首屏 gzip 未核;无登录态,第 15 条真人走查未做。