Files
Jyotisha/docs/tasks/TASK-rectification-message-cleanup-20261001.md
T

9.4 KiB
Raw Blame History

TASK · 生时校正消息清理:题干只出现一次 / 正文复述变短 / 去掉结算后的步骤回执(2026-10-01)

基线

  • origin/staging @ 00420f89(写作时 head;开工时以最新 origin/staging 为准)。盘型口径(BUG-1115~1117、1131)已在其中。
  • 分支 codex/rectification-message-cleanup-20261001,工作树 .worktrees/rectification-message-cleanup-20261001。
  • 并行关系:与 TASK-rectification-chart-tier-caveats-20261001.md(报告 / 聊天标注不可判分盘)文件不重叠,可并行;两单都会追加 docs/BUG_HISTORY.md、CHANGELOG.md、frontend/DESIGN.md,后合入者解冲突保留两侧。与 TASK-consult-plain-answer-20261001.md 不重叠。
  • 不动冻结计分文件(sealed_holdout_rerun.py::PRODUCTION_FILES)、引擎、出题、出卡时机、盘型交付逻辑。

事故实证

产品负责人 2026-09-29 staging 真机,一条校正回复呈现为:

已完成 3 步
1.
记下了:2000年 随家人搬家、2006年 小学毕业、…、2025-02 工作开始不稳定。
2024 年 1 月前后,你有过搬家或者长期住到外地的情况吗?
2024 年 1 月前后,你有过搬家或者长期住到外地的情况吗?
A. 明确发生且时间吻合 B. 发生过但程度较弱 C. 明确没有发生 D. 这段记不清楚

2026-10-01 产品追问「为什么 Agent 输出下面要跟一个问题,这一部分怎么优化」。Claude 只读调研(origin/staging @ a8820f2c):

块 渲染位置
步骤回执「已完成 N 步」 components/chat-message-row.tsx(rectification 分支)→ ConsultationRunTimeline(components/consultation-run-timeline.tsx 的 已完成 ${rows.length} 步),行来自 rectification-message-entry.tsx::rectificationTimelineRows
正文 ChatMessageContent(chat-message-row.tsx)
题干 rectification-message-entry.tsx 的 <p className="rectification-message-question__prompt">{question.prompt}</p>——只要 question 存在且消息已结算就打印,即使嵌入卡为 null(作废 / 被替换的旧题)
选项 components/rectification-choice-card.tsx(legend 是 sr-only,不另显示题目)
独立问题块 components/rectification-question-gap-notices.tsx 两处打印 currentQuestion.prompt + 嵌入卡

题干可见位置共三处:正文(未剥净时)、消息内题干、独立问题块。

根因

  1. 题干两遍(主因,待执行方 DOM 复现确认):最新消息挂着一道已作废 / 被替换的旧焦点,题干文字与新焦点相同。rectification-message-entry.tsx 对它仍打印题干(BUG-917 路径,无选项);rectification-snapshot-messages.ts::placePersistedQuestion 因焦点 id 不同把新题设为 standalone,rectification-question-gap-notices.tsx 再打印一次题干 + 选项 → 「题干、题干、选项」。turn-question.ts::attachQuestionsToTurns 同一轮多个焦点只保留最后一个,是可能的诱因。
  2. 次因(同时防住):placePersistedQuestion 把问题挂到最新已结算消息时不剥正文里的题干;正文剥离只在 agent-run-attempt.ts(焦点已绑本轮时)、turn-question.ts(GET)、rectification-snapshot-messages.ts::mergeTurnQuestions(turnId 命中时)三条路径做。
  3. 正文过长:证据轮正文按提示要求逐条复述「记下了:年 月 事件、…」,开场一次说 12 件时整段占满屏幕,题目被挤到下面。
  4. 结算后步骤回执:记录经历、重打分、出题是系统内部步骤,结算后折叠的「已完成 N 步」对用户无信息量;「1.」疑为列表序号泄漏(globals.css 已 list-style: none,需执行方定位)。

决策记录(产品 2026-10-01)

  • D1 一屏一题干:任一时刻屏幕上只有当前有效焦点打印题干;作废 / 被替换的旧焦点在消息上什么都不显示(不留半句题干,不显示「已作废」)。题干只能出现一次(DESIGN.md 现有规则不变,本单补代码守卫)。
    • 推翻:BUG-917 中「作废题保留题干、去掉选项」的显示方式;执行方在该条防复发下追加「2026-10-01 产品修订:见本任务书 D1」,不删原文。
  • D2 正文复述变短:证据轮正文只说「记下了 N 件事」(N = 本轮实际入账件数);入账清单作为可展开的列表,数据来自服务端证据记录,不来自模型正文。N ≤ 2 时可直接列出两件,不折叠。
    • 推翻 frontend/docs/VOICE.md 与 Agent 提示中「证据轮正文只写一句复述『记下了:年 月 事件短语(、…)。』」的逐条复述要求,改为本条。
  • D3 校正回复结算后不再显示「已完成 N 步」:生成中的步骤进度(等待态)保留不变;结算后整块不渲染。只作用于生时校正,普通对话不变。
    • 推翻 DESIGN.md 中校正与普通对话「共享全部等待词汇」里结算后回执这一项;等待态共享不变。
  • 不做:不改选项、不改题干写法(仍由 Agent 经 set-focus 写、服务端核对)、不改出题与计分、不改盘型交付卡。

硬红线

  1. 不得再出现第二个问题渲染位置;不得手写第二个聊天输入框 / 滚动跟随 / 加载动画(AGENTS §6)。
  2. 刷新、历史打开、实时三条路径(实时流式、GET 重建、快照合并)都满足 D1;旧 Case(盘型口径之前、旧 Skill 版本)打开不报错、不丢选项(BUG-621)。
  3. 前端:tsc 0、lint 0 error、npm test 失败清单与开工基线逐名一致且基线测试名 0 丢失(按 frontend/AGENTS.md 的名单 diff)、/ Static、首屏 gzip ±2%。
  4. 改既有断言写「原值 / 新值 / 原因」;按源码文本断言的合同测试先 grep(frontend/tests/、tests/)。
  5. Agent 提示改动按 CHANGELOG 规则记录;若改到 Skill 文本须 bump 并验证历史 Case 可打开。
  6. 隐私:测试 fixture 只用虚构数据;Bug 历史不写真机事件内容。

任务分解

  • T1 一屏一题干(BUG-1135)
    • 先写失败测试复现两种形状:(a) 最新消息带作废旧焦点 + 独立问题块的新焦点、题干文字相同 → 页面题干出现 2 次;(b) 正文末尾含题干句 + placePersistedQuestion 挂题 → 题干出现 2 次。DOM 级(渲染后数 rectification-message-question__prompt 与 persisted-question 中题干文本出现次数),不只断言数据结构。
    • 修:rectification-message-entry.tsx 只为当前有效焦点打印题干;placePersistedQuestion 挂题时同样剥正文题干句(复用 collect-prompt.ts::stripQuestionSentences,不新写正则);查清 attachQuestionsToTurns 同轮多焦点是否会让旧焦点落到最新消息,必要时只挂有效焦点。
    • 验收:(a)(b) 先红后绿;实时 / GET / 快照三路径表驱动断言「题干恰好 1 次」;BUG-917、BUG-1045、BUG-1046 的既有测试不放宽。
  • T2 正文复述变短(BUG-1136)
    • 服务端:证据轮正文改为确定性的「记下了 N 件事」,N 与清单来自本轮入账证据(agentic_rectification_evidence 读模型 / 现有 dossier 投影),模型不再写复述;Agent 提示相应删去逐条复述要求。
    • 前端:清单作为该消息内可展开列表(默认折叠,N ≤ 2 直接显示),展开交互不新增加载动画。
    • 验收:一次说 12 件 → 正文一行 + 折叠清单 12 条,日期与精度显示与 display_date_label 一致;0 件入账(全被拒)时正文说明而非「记下了 0 件」;VOICE.md / DESIGN.md 同提交更新。
  • T3 结算后不显示步骤回执 + 「1.」泄漏(BUG-1137)
    • 校正消息结算后不渲染 ConsultationRunTimeline;生成中保留。定位截图中「1.」来源并修。
    • 验收:结算 / 刷新 / 历史打开均无「已完成 N 步」;生成中步骤进度照常;普通对话回执不变(测试锁定)。
  • T4 记录:docs/BUG_HISTORY.md(BUG-1135~1137,检索 BUG-585 / 917 / 1045 / 1046 并在 1135 写「复发自」关联及旧防线为何未拦住)、CHANGELOG.md、frontend/DESIGN.md、frontend/docs/VOICE.md、docs/testing/rectification-message-cleanup-20261001.md 真机清单(开场一次说 10 件以上;答一题后出下一题;刷新;打开旧 Case)、docs/tasks/PROGRESS-rectification-message-cleanup-20261001.md、docs/tasks/README.md。

让步顺序

T1 > T3 > T2 > T4 之外的截图。T1 缺之不可合入。

开工前置命令

git fetch origin --prune
export PATH=/exec-daemon:$PATH && node -v   # 22.x
git worktree add -b codex/rectification-message-cleanup-20261001 .worktrees/rectification-message-cleanup-20261001 origin/staging
cd .worktrees/rectification-message-cleanup-20261001/frontend && npm ci
./node_modules/.bin/tsc --noEmit && npm run lint
npm test 2>&1 | grep -E "^(not )?ok [0-9]+ - " | sed -E 's/^(not )?ok [0-9]+ - //' | sort > /tmp/msg-cleanup-names-base.txt

BUG 编号

开工时核对 docs/BUG_HISTORY.md 最大号(写作时 BUG-1131;1132~1134 已被 TASK-consult-plain-answer-20261001.md 预留)。本单:BUG-1135(题干两遍)、BUG-1136(证据轮正文逐条复述过长)、BUG-1137(结算后步骤回执与「1.」泄漏)。号冲突顺延并在 PROGRESS 说明。关联 BUG-585、BUG-917、BUG-1045、BUG-1046、BUG-621。