docs(rectification): add walkthrough polish task brief

首次真实走查确认三轮修复生效;本轮修五个抛光项:选择卡题干
fail-closed、题干时序与 UI 断言措辞、同域重问去重、采用后切入
前事核对、coverage 门与 offer 链路一致性(需产品选边,默认对齐引擎)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
This commit is contained in:
Jesse_Chen
2026-09-02 04:07:36 +00:00
parent f7428909d2
commit 701d4f92a2
@@ -0,0 +1,77 @@
# 任务书 · 首次真实走查抛光:题干必达、时序、去重、采用后续流、门一致性(2026-09-02)
基线:`origin/staging` 当前 tip(含 PR #47/#48/#49 全部合并)。
## 0. 背景
2026-09-02 产品负责人在真实 staging 环境完整走查生时校正(case `a17efc37-1494-4d13-91a9-d719838ef66c`,快照向发起人索取)。**三轮修复全部生效**:收窄有进度播报、offer 出牌、采用 04:53 成功、ledger 含 `dasha-transition-proximity`、品质题生成、`matrix-scoring-7 / policy-v3` 在线。本轮修走查暴露的 5 个抛光问题,全部已静态定位。**不改任何决策门语义与真实性边界**(问题 E 除外,它是把两个已存在的权威对齐,需产品选边)。
## 问题 A(P0)· 选择卡出现过"无题干"——静默降级必须 fail-closed
**现象**:第一道区分题(D9 相处方式)卡片只有 A-D 选项,无题干;同一 focus 的题干也没写进 turn 历史(后续各题的题干均由 answer_choice 路径正常写入并显示)。
**定位**:卡片组件渲染 `card.prompt``rectification-choice-card.tsx:51``<legend>`),无题干 = focus 创建时 schema.prompt 为空。`serverOwnedChoiceCopy``choice-card.ts:433`)在 `frame.prompt`/`period` 缺失或超出 4-80 字符窗时**静默 return null**`server-focus.ts:80-84` 拿到 null 后 focus 仍带空 prompt 建立 → 卡出、题干丢;turn-exit 的题干持久化因 `question?.prompt` 空同步被跳过——一个根因两个症状。message/agent 路径创建的第一个 choice focus 命中此路径(answer_choice 路径正常,说明缺口在 agent 后 `persistNextInterviewIfIdle``persistServerOwnedFocus`/`persistFocusAfterChoice` 这条创建链上;按符号追)。
**修法**
1. choice focus 创建 fail-closed`serverOwnedChoiceCopy` 返回 null 时**不得**建立可渲染的 choice focus——回退为 spoken collect`spokenCollectFallbackFollowup` 已存在)或跳过该 probe 记入 droppedreason 如 `unrenderable_choice_copy`),二选一并写明理由。
2. 排查 null 的实际成因(该 D9 probe 的 `question` 为"亲密关系里,你更接近哪一种相处方式?",14 字在窗内——大概率是 choice_frame 组装时 prompt 字段没接上,而不是超长),修实际断点。
3. 不变量测试:任何 `choice_card` 非空 ⇒ `choice_card.prompt` 非空;任何 active choice focus ⇒ `projectCurrentQuestion(...)?.prompt` 非空。用走查 case 的 probe 形状做回归。
## 问题 B(P1)· "界面上有下一问"先于问题出现——时序与措辞双修
**现象**:模型正文说"界面上继续有下一问",但题干 turn 在流结束后的 turn-exit 才持久化,用户当下看不到。
**修法**
1. 措辞:`agentic-rectification.ts` 指令补一条——正文不得断言界面当前状态("界面上有/出现了…"),过渡用中性表述("接下来我们继续"类);VOICE.md 同步。
2. 时序:turn-exit 持久化题干/focus 后,在关闭流之前向前端 emit 一个已允许的公开事件(如 question.ready,走 `safePublicEvent` 白名单)或由前端在 `done` 事件后立即刷新 case 快照。选实现小的,说明理由。前端已有刷新机制的话只需确认时机覆盖。
## 问题 C(P2)· 同域采集问句逐字复读
**现象**:"感情这边,还记得哪年认真在一起、分开,或结婚吗?"在历史里逐字出现两次(用户第一次用工作事件回答,感情域仍未覆盖,重问正确,但复读机器感强)。
**修法**:同一域的 collect 问句在**已问过且未被拒答**时重问,需换第二措辞(copy 模块每域加一条 retry 变体,如"回到感情这边——刚才说的工作我记下了,哪年认真在一起或分开还记得吗?")。判定用结构化状态(该域 collect focus 曾建立过),不做正文匹配。
## 问题 D(P1)· 采用后没有切入前事核对,旧采集问题挂在卡下
**现象**:采用 04:53 成功后,`current_question` 仍是采用前的"钱的方面…"采集 focus,显示在候选卡下方、脱离对话流;预期是 `verify_adopted_time`:按采用分钟反推最多两件前事核对(reverse_verify 链路已实现但没被接上)。
**修法**
1. 采用(accept RPC 成功)后的下一次 turn-exit / GET 投影:关闭或替换采用前的 collect focus,按 `next_user_action.id=verify_adopted_time` 建立 reverse_verify 焦点(`remainingReverseVerifyProbes` 已存在,`MAX_REVERSE_VERIFY=2`);无可用前事探针时给出 `start_consultation` 引导,不留旧问题。
2. UI:当前问题槽在候选卡区域之后渲染时必须仍在对话流内(作为最新一条内容),不得视觉上悬挂在卡片外;具体实现交给前端组件(`rectification-agentic-chat.tsx` 的 currentQuestion 渲染位置)。
3. 不变量:`accepted_time` 非空 ⇒ `current_question` 为 reverse_verify 类或空且 `next_user_action ∈ {verify_adopted_time, start_consultation}`;不得为采用前的 collect focus。
## 问题 EP1,需产品选边)· coverage 门与 offer 工具不一致
**现象**:走查中 occupation(职业)从未被问,TS overlay 判 `can_adopt: false`(coverage 未完成),但模型 offer 工具 + 引擎 `accept_allowed=true` 照常出牌且采用成功——coverage 门被 offer 链路绕过。结果可用但两个权威打架,且 skill 文本写"职业挡出牌"。
**二选一(在 PR 里写明选择与理由,默认选 1)**
1. **对齐引擎(推荐)**coverage(含 occupation)从 `deliveryCapability` 的采用门移除,只保留为**问询路由**优先级(没问过职业时优先问,但不挡出牌);skill 10.0.14 文本中"职业挡出牌"一句需在下次 skill 版本 bump 时同步修订(本轮先在 PR 记录偏差,不 bump skill)。
2. 对齐 TSoffer 工具服务端校验 coverage,未完成时拒绝 offer。风险:重新引入"差一问才能出牌"的摩擦,与 Round A 的用户体验目标相悖。
无论选哪个:overlay 与实际可执行动作必须一致——不允许再出现 `can_adopt:false` 与"卡已出、采用成功"并存。
## 硬红线
1. 不改采用/确认门的真实性语义(问题 E 按上面二选一后对齐,不新增放宽);确认门恒 fail-closed。
2. 问题槽服务端唯一所有不变;所有判定结构化,不做正文字符串匹配。
3. 引擎(Python)不动。
4. `./node_modules/.bin/tsc --noEmit` 通过(不要用 `npx tsc`);`rectification-*` / `consultation-*` / `consult-*` / `chat-*` 测试 fail=0;改动的既有断言逐条三栏说明(旧→新→保留语义)。
5. 无凭据不得声称已真实环境验证;修完把走查 case 形状的前后对照贴 PR。
## 开工前置
```bash
git fetch origin --prune
git worktree add -b codex/rectification-walkthrough-polish-20260902 \
../.worktrees/rectification-walkthrough-polish-20260902 origin/staging
```
`frontend/AGENTS.md``docs/BUG_HISTORY.md`BUG-456/460/463/468/469 链)、`frontend/docs/VOICE.md`。**行号是线索,按符号名定位。**
## 验收标准
1. 问题 A 的两条不变量全绿;D9 probe 形状回归:卡必有题干,历史必有题干 turn。
2. 问题 D 的采用后不变量全绿;走查 case 形状:采用后 `current_question` 切换为前事核对。
3. 问题 E 所选方案落地后:overlay 的 `can_adopt` 与 offer/accept 实际可执行性一致(合成两个方向的测试)。
4. tsc + 四组测试 fail=0BUG_HISTORY 追加条目(编号接现有最大号之后,先 grep 确认,避免再撞号)。
5. 建议真实环境复测清单(人工):完整走一遍并确认——首道选择卡有题干;无"界面上有下一问"式断言;同域重问换措辞;采用后立即出现前事核对问题且在对话流内。