# PROGRESS · 同一轮旁白说两遍、题干出现两次(2026-09-07) 工作树:`.worktrees/rectification-duplicate-narration-20260907` 分支:`codex/rectification-duplicate-narration-20260907` 任务书:`docs/tasks/TASK-rectification-duplicate-narration-20260907.md` 基线:`origin/staging` @ `6c7a8b02`(任务书写 `f3e72702` / 代码头 `ab57d03f`;其后 `a00b069d` 已合入,tsc 不再报 `rectification-agentic-chat.tsx` L1655) 本单状态:**待验收**。未 commit、未 push。 未改:提示词、Skill 版本(仍 10.0.15)、采用门、确认门、`MIN_SEPARATION_LEAD`、`_relative_support`、`minute_step=1`、`page.tsx`。 并行:`codex/rectification-other-collect-fallback-20260908`(BUG-586)也改 `user-copy.ts` 与 `agent-voice-copy-contract.test.ts`。本单只加 `collectHandoff`;谁后合谁 rebase。 ## 做了什么 - **4.2 / BUG-585** `stripQuestionSentences`:按句删掉与题干相同、题干前 12 字开头、或以问号结尾的句子;问号后的非叙事尾巴一并丢掉。`composeCollectSpokenAssistantText` 改调它。agent-run 在 `answer.composed` 前复用 discriminator 那次 `loadV9CaseDossier`:本轮 focus 有 spokenPrompt 则剪,剪空用 `collectHandoff`,变化时 `replace:true`。`attachQuestionsToTurns` 同样剪。删除 `collectSpokenEmitted`。 - **4.1 / BUG-584** `StepAnswerState` 增加 `stemAttached`、`publishedAny`,不随 `resetBuffers` 清。set-focus 之后若本轮已发布正文,后续 `text-delta` discard。 - **决策 3** set-focus `tool-call` 把未直播的中文半句 `publish`;无 CJK 的规划稿 discard。未后置为 P3。 ## 三栏(被触碰断言) | 用例 | 原值 | 新值 | 理由 | | --- | --- | --- | --- | | set-focus 后第二段正文 | `live` 发布 | `discard` | 决策 2,丢掉工具结果后的复述 | | set-focus 前无正文、后有一段 | (原测试未覆盖) | 后段 `live` | BUG-533 开场仍通 | | 无句末标点的中文半句 + set-focus | 静默丢掉 | `publish` | 决策 3 | | 英文规划稿 + set-focus | 不直播 | `discard` | 维持原 discard | | `collectSpokenEmitted` | 恒 `false` | 字段删除 | 决策 4 | | 历史回看剥题干 | 只剥 `\n\n` 后缀 | `stripQuestionSentences` | 决策 1 | ## 测试 - `frontend` `./node_modules/.bin/tsc --noEmit`:exit 0 - 任务书指定 TS 切片(`tests/rectification-*.test.ts` + `agent-voice-copy-contract.test.ts`,排除 database):**988 passed / 0 failed** - Docker `database-rectification-*.test.ts`:本机未跑,记 blocked - 浏览器真人走查:无登录态,记环境缺口,见 `docs/testing/rectification-scenarios-20260907.md` §6 ## 偏离 1. 任务书点名的 `rectification-v9-agent-run*.test.ts` 不存在;agent-run 序列写在既有 `rectification-v9-agent.test.ts`。 2. 问号后的「有年份就行。」按非叙事续句丢掉,否则验收 (a) 会留下这半句。