Files
Jyotisha/docs/tasks/TASK-rectification-walkthrough-polish-20260902.md
T
Jesse_Chen 8db71aaf81 docs: product-level README, AGENTS.md split into code/reading parts, add CLAUDE.md, move task briefs to docs/tasks
- README.md is now the product/repo front door (architecture, repo map,
  local dev, test tiers, delivery flow, doc map). Engine positioning,
  VedAstro/Codex setup and the oracle/benchmark command reference move
  verbatim to docs/engine/README.md, docs/engine/vedastro-gateway.md and
  docs/benchmark/README.md. Capability badges realigned with the registry
  (91/78/8/0); tests/test_readme_badges.py was red on staging.
- AGENTS.md: Part A (environment truth, delivery, worktrees, record
  placement, bug workflow, growth freeze, frontend red lines, privacy,
  pre-work check, test tiers) and Part B (reading-rigor constraints).
  GitHub issue-tracker/triage boilerplate removed: GitHub is a read-only
  mirror. All strings locked by tests/ are preserved.
- CLAUDE.md added: roles, three working modes, task-brief sections,
  acceptance criteria, session discipline; imports AGENTS.md.
- 50 tracked TASK-*/PROGRESS-* files and 3 never-committed briefs move to
  docs/tasks/ with an index; REPO_LAYOUT.md merged into README.

Docs-only change (no gated path touched).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
2026-09-03 06:56:06 +00:00

7.8 KiB
Raw Blame History

任务书 · 首次真实走查抛光:题干必达、时序、去重、采用后续流、门一致性(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.promptrectification-choice-card.tsx:51<legend>),无题干 = focus 创建时 schema.prompt 为空。serverOwnedChoiceCopychoice-card.ts:433)在 frame.prompt/period 缺失或超出 4-80 字符窗时静默 return nullserver-focus.ts:80-84 拿到 null 后 focus 仍带空 prompt 建立 → 卡出、题干丢;turn-exit 的题干持久化因 question?.prompt 空同步被跳过——一个根因两个症状。message/agent 路径创建的第一个 choice focus 命中此路径(answer_choice 路径正常,说明缺口在 agent 后 persistNextInterviewIfIdlepersistServerOwnedFocus/persistFocusAfterChoice 这条创建链上;按符号追)。

修法

  1. choice focus 创建 fail-closedserverOwnedChoiceCopy 返回 null 时不得建立可渲染的 choice focus——回退为 spoken collectspokenCollectFallbackFollowup 已存在)或跳过该 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。

问题 E(P1,需产品选边)· 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。

开工前置

git fetch origin --prune
git worktree add -b codex/rectification-walkthrough-polish-20260902 \
  ../.worktrees/rectification-walkthrough-polish-20260902 origin/staging

frontend/AGENTS.mddocs/BUG_HISTORY.mdBUG-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. 建议真实环境复测清单(人工):完整走一遍并确认——首道选择卡有题干;无"界面上有下一问"式断言;同域重问换措辞;采用后立即出现前事核对问题且在对话流内。