Files
Jyotisha/docs/tasks/TASK-rectification-explain-layer-20260906.md
T

83 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TASK · 生时校正过程解释层:每题"为什么问、答了会怎样",每轮"现在第几步、为什么、下一步"2026-09-06
- 基线:`origin/staging` @ `b938c76a`(文档头 `211f9bb2`
- 分支:`codex/rectification-explain-layer-20260906`
- 执行方:coding agent;验收:Claude
- 串行:排在 `TASK-rectification-convergence-exit-fix-20260906.md` 之后、`TASK-rectification-range-reading-20260906.md` 之前(都改 `answer-choice.ts` / `rectification-agentic-chat.tsx`
- 涉及文件:`frontend/src/lib/rectification-agentic/v9/choice-card.ts``probe-question-contract.ts``choice-action.ts``answer-choice.ts``method-followup.ts``case-service.ts`(快照投影)、`frontend/src/lib/rectification-candidate-result.ts``frontend/src/components/rectification-choice-card.tsx``rectification-agentic-chat.tsx``frontend/src/lib/rectification-agentic/user-copy.ts`
- 不改:Python 探针契约(`contracts/probe-question-v1.json` 字节不变)、任何门、SKILL.md
- BUG 编号:本单是能力补齐,不预留;执行中发现缺陷再按当时最大号续
## 0. 为什么做这件事
产品负责人 9-06 实测的原话是"用户也不知道怎么做,就卡在这里"。修复单堵的是出口,这一单补的是**过程可见性**:上游 yinduzhanxing 旧校时工作台的 `buildRectificationAIContext()`(当前阶段 → priority action → reason → next step)、题库里的 `why_this_question` / `answer_impact`,是它相对我们唯一明显更强的业务层。我们的数据都有,只是没投影给用户。
## 1. 现状实证
| # | 事实 | 位置 |
| --- | --- | --- |
| 1 | 点选卡的 `why` = `probe.user_meaning`(引擎给模型的作题简报,如"时间范围锁定…领域锁定…语义目标是…"),经 `engineMeaningToDisplayCopy` 过滤后基本为空,用户看不到"为什么问" | `choice-card.ts::hypothesisFor` L73`rectification-choice-card.tsx` L63 |
| 2 | 答完只回固定句"已记录你的选择,并更新了候选比较",虽然 `inference_state.rounds[].score_deltas``credible_range` 前后值都在 | `choice-action.ts::composeChoiceNarration` L94116`build-state.ts` rounds |
| 3 | 每轮只有一句"本轮对照了 D1、D9…"(技法清单),没有"现在在哪一步 / 为什么 / 下一步" | `rectification-varga-sentence.ts` L33receipt `methods` |
| 4 | 服务端其实已经知道阶段:`methods` 覆盖表、`decision.nextAction``precision_stage.current``stopReason` | `method-followup.ts` plan、`rectification-decision.ts` |
| 5 | 看盘板(`rectification-board`)已经是"专业视图"(宫位表、换升时刻),不需要再做双模式开关 | `rectification-board.tsx` |
## 2. 决策记录
1. **解释文案全部服务端生成**,模型只写题干;不得让模型解释分数或候选变化(防止编造)。
2. **"为什么问这题"**:从探针数据生成一句:`{period} 这段经历能把当前 {n} 段候选分成两组({tracks 中文})`varga_style 卡写"这题对照 {D9/D10} 的类型差异"。挂在卡片题干下方,默认折叠为"为什么问这题",点开显示。
3. **"答了会怎样"**:每个选项一句,来自 `expected_outcomes`A/B → "会让 {supports 段落} 领先、{conflicts 段落} 落后"C → 反向;D → "不计分,换一题"。段落用可信区间口径("04:3104:39 这段"),不用概率词。放在卡片底部一行小字,随选项高亮。
4. **答后旁白**改为三段式(服务端拼):"{已记录}。{哪段升/降,来自 score_deltas 聚合到簇}。{范围从 X 收到 Y / 范围没变}。" unsure 保持"这题先不计分,换一件事问"。
5. **步骤条**case 快照新增 `step_state = { stage: "collect"|"discriminate"|"deliver"|"post_adopt", index: 1..4, headline, reason, next }`,服务端从 `methods` / `decision.nextAction` / `precision_stage` / `stopReason` 派生(纯函数,放 `frontend/src/lib/rectification-agentic/v9/step-state.ts`)。UI 固定显示在输入框上方、与口述态停止按钮同一行左侧;每轮重算。文案例:"第 2 步·区分候选 — 带年月的经历已经够了,现在用几道选择题分开相邻的候选 — 下一步:答完当前这题,或者按'先这样'看结果"。
6. 不做 guided/professional 双视图;看盘板就是专业视图。
## 3. 硬红线
- BUG-390 四选项契约不变;`contracts/probe-question-v1.json` 字节不变;新增字段只在 TS 的 `RectificationChoiceFrame` / `RectificationChoiceCard``why_user``answer_impact`),Python 不改。
- 不得在用户可见文案里出现"概率 / 置信度 / 确定"字样(`agent-voice-copy-contract` 已有守卫,新文案要过它)。
- 答后旁白的段落只能来自 `score_deltas``credible_range` 前后值;范围没变时必须如实说"范围没变"。
- `page.tsx` 不增长;新逻辑进 `lib/` 或组件。
- 既有断言改动写三栏。
## 4. 任务分解
### B1 卡片解释字段
- `choice-card.ts::buildChoiceFrame` 新增 `why_user`(决策 2)与 `answer_impact: {A,B,C,D}`(决策 3);生成函数放 `probe-explain.ts`(纯函数,输入 probe + 活跃候选 + 簇范围)。
- `rectification-choice-card.tsx`:折叠"为什么问这题";选项 hover/选中时显示对应 impact 行。`DESIGN.md` 记录。
- 验收:`rectification-choice-card.test.ts` 新增——existence 探针生成的 `why_user` 含年月与"分成两组"`answer_impact.A` 含 supports 段落的时间;varga_style 卡 `why_user` 含分盘名;文案守卫通过。
### B2 答后旁白
- `composeChoiceNarration` 接收 `{deltasByCluster, rangeBefore, rangeAfter}``persistApplied` 在应用推断后计算并传入(`scoreDeltas` + `clusterRangeFor` 已有)。
- 验收:`rectification-answer-choice.test.ts` 新增——答 A 后旁白含"领先 / 落后"与"范围从 … 收到 …";范围不变时含"范围没变";答 D 不变。
### B3 步骤条
- `step-state.ts` 纯函数 + 单测(四个阶段各一例,含 `probe_pool_exhausted``user_uncertainty_too_high` 的 reason 文案);`case-service.ts` 快照投影加 `step_state``rectification-agentic-chat.tsx` 渲染;`rectification-candidate-result.ts` 解析。
- 验收:快照契约测试(`rectification-v9-contracts.test.ts`)含 `step_state`;组件源扫描断言存在 `rectification-step-state`
### B4 记录
- `CHANGELOG.md``PROGRESS-rectification-explain-layer-20260906.md``docs/testing/rectification-explain-layer-20260906.md`(真实环境:每张卡能展开"为什么问";答完一题看到哪段升降与范围变化;每轮顶部有第 N 步 / 原因 / 下一步);`frontend/DESIGN.md``frontend/docs/VOICE.md`
## 5. 让步顺序
B3 步骤条最便宜、最直接回应"不知道下一步",先做;B1、B2 其次;B4 不可省。
## 6. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/rectification-explain-layer-20260906 .worktrees/rectification-explain-layer-20260906 origin/staging
cd .worktrees/rectification-explain-layer-20260906
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
cd frontend && ls tests/rectification-*.test.ts tests/agent-voice-copy-contract.test.ts | grep -v database | xargs npx tsx --test 2>&1 | grep -E "^# (tests|pass|fail)"
```
## 验收(Claude2026-09-07`origin/staging` @ `814c924e`
| 项 | 结论 |
| --- | --- |
| B1 卡片 why_user / answer_impact | 通过。服务端生成,折叠展示,选项 hover/选中显示影响句 |
| B2 答后旁白 | **未通过(P1BUG-569**`applyRectificationChoice` 传给 `composeChoiceNarration``rangeBefore/rangeAfter` 取的是 `InferenceState.range_start/range_end`——那是候选**搜索窗口**,答题从不改变;真正收窄的是 `credible_range`。线上每一题都会说「范围没变」,与顶部只读范围矛盾。单测之所以过,是因为直接给 `composeChoiceNarration` 喂了两个不同的范围 |
| B3 步骤条 | 通过。四段派生纯函数 + 快照投影 + UI |
| B4 记录 | 通过 |
| 文案 | P2why_user 里把 Vimshottari / Narayana 写成「毗湿奴多利、那罗延」,产品其他位置(`rectification-varga-sentence.ts`)一律用 Vimshottari / Narayana,见修复单 |