Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
108 lines
13 KiB
Markdown
108 lines
13 KiB
Markdown
# TASK · 生时校正:旁白事实有据 + 去掉重试按钮 + 给模型的资料瘦身(2026-09-27)
|
||
|
||
## 基线
|
||
|
||
- 开工时 `git fetch` 后的最新 `origin/staging`(写进 PROGRESS)。诊断基于 `599fe7a9`。
|
||
- 分支 `codex/rectification-grounding-20260927`,工作树 `.worktrees/rectification-grounding-20260927`。
|
||
- **并行**:`codex/consult-evidence-card-20260927`(普通对话数据卡)正在改 `frontend/src/app/api/consult/**`、`frontend/src/lib/stream-agent-response.ts`、`frontend/src/mastra/index.ts`、`consultation-*` 与可能的 `jyotish-vedic-astrology` Skill。本单**不得修改这些文件**;两单都可能改 `skills/skill-package-registry.json`、`CHANGELOG.md`、`docs/BUG_HISTORY.md`、`docs/tasks/README.md`,后合入的一方负责 rebase 合并,保留双方条目。
|
||
|
||
## 事故实证(诊断 2026-09-27,真实 Agent + 记录提示词的假模型 + 本机真实引擎,公开 AA 盘;行号按符号定位)
|
||
|
||
复现脚本与数据:`/tmp/claude-1000/-workspace-Jyotisha/725df462-ac7f-4544-90b7-60fba1501ed7/scratchpad/zz-diag-rect-context.test.ts`,同目录 `measure*.json`、`regen.json`、`offer.json`、`compare-projection.json`、`jolie30.json`(执行方可参考并改写成提交的回归测试)。
|
||
|
||
**主链没有 BUG-1053 那种盲写**:每次尝试一个 `agent.stream`,写正文的步看得到 read-case 与 batch 结果;题干(服务端校验 + 模板退回)、验证报告(服务端拼装)、采用旁白(结构化事实 + 数字白名单)、兜底句(batch recaps)均有依据。问题如下:
|
||
|
||
- **D1(复发自 BUG-588,已复现)服务端范围句被证据轮裁句裁掉,旧范围反而留下。** `frontend/src/lib/rectification-agentic/v9/agent-run-attempt.ts`(`withRangeChangedAfterEvidence` / `withRescoreSkippedNotice`,约 L588–600)先把「范围从 A 变为 B。」接到正文末尾;`agent-run-finish.ts`(`action === "evidence"` 分支 `trimSpokenTurnForInterview`,约 L169)再按 `collect-prompt.ts` `trimEvidenceTurnBody`(超过两句只留首句)裁掉。模型写两句 → 落库只剩首句,流式时范围句先闪出再被 `replace` 撤回;模型首句带 read-case 里的旧范围 → 落库旧范围。「这次没有重新比较」「候选比较这次没跑成」同样被裁。batch 返回(`rectification-v9-tools.ts` 约 L1706–1733)没有重算后的范围,模型唯一的范围来源是旧值;系统提示(`frontend/src/mastra/agentic-rectification.ts` 约第 39 行)又鼓励「有收窄就说进度」。证据轮与交付轮正文**没有**任何数字/时刻校验。
|
||
- **D2(新,BUG-1053 同型,已复现)「重试」重新生成是盲写且不校验就落库。** `v9/regenerate-turn.ts`(约 L150–157)`agent.generate` 只给旧正文 + read-case,Skill 未注入,输出不剪问句、不补范围句、不查数字/禁用词,直接 `regenerate_agentic_rectification_turn`。复现:写出「范围收在 09:00–09:05,吻合率 90%」原样落库,实际范围 08:54–09:24。入口在 `frontend/src/components/rectification-agentic-chat.tsx`(最新助手消息操作栏,约 L589)。
|
||
- **D3(新,已确认)read-case 超 6KB 时先清空对话与证据。** `v9/turn-decision.ts` `enforceTurnDecisionBudget`(约 L268–286)超限清空 `recent_turns`、`relevant_evidence_summary`,保留每个约 458 字节的候选定位元数据。模型消息里没有历史(`agent-run-messages.ts` 约 L46–74),read-case 是唯一对话记忆。9 个候选、2 条短对话即触发;约 7 个及以上候选的常见窗口都会「失忆」。现有测试只断言不超上限。
|
||
- **D4(BUG-588 / BUG-569 同族,按代码确认)点选题答案里带日期经历时,范围变化无人说。** `v9/agent-route-typed-message.ts`(约 L147–170、L227–247)`deferFollowup` 时 `applied.narration` 不落库;`answer-choice.ts` `persistV9ChoiceAction` 已先写入新推断,随后 Agent 轮 prepare 读到的 `rangeBeforeCompare` 已是答题后范围,两边都不写范围句。
|
||
- **R1(BUG-593 旁路)** offer-candidates 返回完整投影(`rectification-v9-tools.ts` 约 L2139–2187),含 `dasha_agreement_pre_inference`、`house_table_pre_inference`、`representative_time_pre_inference`;compare 里 `engine_indistinguishable_width_minutes` 可被引用。compare 返回的验证报告 Markdown 出现两次(`skill_verification_report` 与 `range_delivery.verification_markdown` 逐字相同)。
|
||
- **R3** 交付轮「三句(范围、吻合率、边界)」指令在打字证据轮无法落地:写正文时还没做交付决定(`agent-run-finish.ts` `persistNextInterviewIfIdle`),也没有吻合率数据。
|
||
- **R4** Mastra 自动注入 `<available_skills>` 与「请调用 skill 工具」,与引导语「不要调用 skill」矛盾,还带出临时目录路径。
|
||
- **体量**(公开盘 30 分钟窗、3 件事、9 个候选;token 为经验估算):Skill 10.0.31 全文每次调用重发约 10.7K 字符(证据轮只用得上 §5、§7,约 30%);14 个工具 schema 每步重发约 13.7KB;read-case 5.8K 字符中 4.1K 是候选元数据;compare 返回 32K 字符;offer 返回 100K 字符(含 31KB `candidate_contrast_packet`、27KB 探针)。一轮典型证据轮 4 次调用合计约 59K 输入 token,每次固定约 14K。
|
||
|
||
## 根因
|
||
|
||
服务端事实句与模型正文共用一条「先拼后裁」的管线,事实句不受保护;重新生成沿用了 V5 之前的自由重写、丢了校验;read-case 的预算裁剪顺序把最该留的对话记忆放在了最先被砍的位置;给模型的工具返回和 Skill 没有按轮次瘦身。
|
||
|
||
## 决策记录(产品 2026-09-27)
|
||
|
||
- P1 **生时校正里去掉「重试(重新生成)」按钮**(产品偏好:多余入口宁可删除也不修)。普通对话的重试不受影响。服务端重新生成路径若只服务于校正则一并删除;数据库函数 `regenerate_agentic_rectification_turn` 本单**不删**(AGENTS §7.6 两轮规则:先下线代码,另开单再退役函数)。
|
||
- P2 **资料瘦身与四个修复一起做**:read-case 瘦身与预算顺序、compare/offer 剥离与去重、batch 补重算后范围与是否交付、Skill 按轮次切片、关掉 Mastra `<available_skills>` 注入。
|
||
- P3 证据轮与交付轮的范围、时刻、吻合率**只由服务端说**;模型正文里带时刻或百分比的句子,若与服务端事实不符则整句丢弃(AGENTS 三通道原则:正则只当门不当刀,不就地删词)。
|
||
- 本单不推翻 BUG-606 / BUG-615 的「证据轮正文短」口径:裁句仍作用于**模型正文**,只是服务端事实句不再参与裁句。
|
||
|
||
## 硬红线
|
||
|
||
1. 服务端事实句(范围变化、未重算、比较失败、以及 D4 的答题范围句)**永不参与裁句**,落库与流式最终态一致(不得先出现再被 `replace` 撤回)。
|
||
2. 落库正文中出现的任何 HH:MM 区间 / 代表分钟 / 百分比,必须等于服务端当轮事实(白名单),否则该句不落库。测试用两句正文、首句带旧范围的真实 `runV9AgentTurn` 场景(诊断复现 1、2),以及带编造吻合率的场景。
|
||
3. 9 个候选、若干条对话时,read-case 仍保留 `recent_turns` 与 `relevant_evidence_summary`;超限时先砍候选明细(保留 time / score / status / cluster_range),最后才动对话与证据摘要。锁回归。
|
||
4. 不改打分、候选生成、交付门槛、收敛规则、题目选择逻辑;不改 Python 引擎;不动冻结计分文件(ERR-110)。瘦身只改**给模型看的投影**,不改落库的推断与回执。
|
||
5. 历史校正会话仍能打开(BUG-621):若 bump Skill,旧版本快照保留、registry 标 deprecated。
|
||
6. 前端红线全套(tsc 0、lint 0 error、全量测试 Node 22 失败名单与基线逐条一致、`/` ○ Static、gzip ±2%、改断言三栏);**全量 Python 门禁集必跑**(含 `tests/test_api_server_growth_contract.py`,handler 伪造点不得增长、注释里也不得出现该字面量)。
|
||
7. 隐私 AGENTS §8;只用公开 AA 盘或虚构数据。
|
||
8. 禁止 `git stash`;只 `git add <具体路径>`,提交前看 `git diff --cached --stat`(ERR-112);不推送。
|
||
|
||
## 任务分解(每条带验收标准)
|
||
|
||
### T1 D1 修复:事实句不参与裁句 + 数字白名单(BUG-1055,复发自 BUG-588)
|
||
|
||
- 顺序改为:先对模型正文执行证据轮裁句与数字白名单(P3),再追加服务端事实句;流式不再先接后撤。
|
||
- batch 工具返回补上重算后的 `credible_range` 与「本轮是否交付」,模型不再只能用旧值;系统提示「有收窄就说进度」改为「范围由系统说,你不写时刻和百分比」。
|
||
- **验收**:诊断复现 1、2 与编造吻合率场景转为回归测试并通过;「这次没有重新比较」「候选比较这次没跑成」保留;BUG-588 原测试不弱化。
|
||
|
||
### T2 D2:去掉生时校正的重试按钮(BUG-1056)
|
||
|
||
- 校正消息操作栏不再显示重试;普通对话不变。服务端重新生成入口对校正会话返回明确的不可用(或整条删除若无其他调用方);删除随之无用的代码与文案。
|
||
- **验收**:UI 测试(校正消息无重试、普通对话有);接口测试;`DESIGN.md` / `VOICE.md` 同步;数据库函数不动并在 PROGRESS 记「待另开单退役」。
|
||
|
||
### T3 D3:read-case 瘦身与预算顺序(BUG-1057)
|
||
|
||
- 候选只留 time / score / status / cluster_range;删掉与 `inference.candidates` 重复的 `candidate_summary.candidates`;超限时先砍候选明细、最后才动 `recent_turns` 与证据摘要。
|
||
- **验收**:红线 3 回归;9 个候选时 read-case 体量与内容对比表写进 PROGRESS。
|
||
|
||
### T4 D4:点选题 + 带日期经历路径的范围句(BUG-1058,关联 BUG-588 / BUG-569)
|
||
|
||
- `deferFollowup` 路径把答题前范围传给随后的 Agent 轮,或把 `applied.narration` 的范围句按 T1 规则并入正文(二选一,写明理由)。
|
||
- **验收**:真实路由级回归:点选题答案带日期经历、范围变化时,落库正文有且仅有一句服务端范围句。
|
||
|
||
### T5 compare / offer 投影剥离(R1、R3)
|
||
|
||
- offer 给模型的投影走与 compare 相同的剥离(去掉 `*_pre_inference`、对照包、探针,保留交付所需的结论字段);验证报告 Markdown 只留一份;`engine_indistinguishable_width_minutes` 不给模型。
|
||
- 交付轮的正文指令与「写正文时是否已知交付」一致(配合 T1 的「本轮是否交付」)。
|
||
- **验收**:投影合同测试(真实引擎响应 fixture,AGENTS §7.4);offer / compare 模型可见体量前后对比表;BUG-593 原测试不弱化。
|
||
|
||
### T6 Skill 按轮次切片 + 关掉 `<available_skills>` 注入(R4)
|
||
|
||
- 证据轮只给 Skill §5、§7 等本轮相关章节(切片规则写成代码常量并测试);删掉只在 `full_diagnostics` 里才有的字段说明或改到需要时才给;关掉 Mastra 自动 skills 注入。
|
||
- 可选:按轮次收窄每步给模型的工具 schema(只给本轮会用到的),不影响现有工具调用路径时才做。
|
||
- 若 Skill 文本改动则 bump 版本(快照、registry sha、旧版 deprecated),CHANGELOG 写明。
|
||
- **验收**:记录提示词的假模型测试断言证据轮不含无关章节、不含 `<available_skills>`;典型证据轮每次调用的固定开销与合计输入 token 前后对比表(目标:固定开销从约 14K 降到 8K 以下,给出实测)。
|
||
|
||
### T7 记录
|
||
|
||
- `docs/BUG_HISTORY.md`:BUG-1055~1058 完整记录(D1 写「复发自 BUG-588」及为何旧测试没拦住:只用单句正文);R1 在 BUG-593 下补充。
|
||
- CHANGELOG;`frontend/DESIGN.md`(操作栏);`frontend/docs/VOICE.md`(范围由系统说的口径);`docs/tasks/PROGRESS-rectification-grounding-20260927.md`(体量前后对比、红线测试清单、失败名单对比、三栏改动);`docs/testing/rectification-grounding-20260927.md`(真机:说一件带年月的事看范围句是否完整留存;候选多时说「那年」看是否记得;点选题顺手打字补经历看有无范围句;校正消息下没有重试按钮);`docs/tasks/README.md` 本单一行改「待验收」。
|
||
|
||
## 让步顺序
|
||
|
||
1. T1、T2、T3、T4 必须完成(用户可见的错误)。
|
||
2. T5 必须完成剥离部分;去重可降级。
|
||
3. T6 的 Skill 切片与关注入必须做;工具 schema 收窄可留下一单。
|
||
|
||
## 开工前置命令
|
||
|
||
```bash
|
||
cd /workspace/Jyotisha && git fetch origin --prune
|
||
git worktree add -b codex/rectification-grounding-20260927 .worktrees/rectification-grounding-20260927 origin/staging
|
||
ln -s /workspace/Jyotisha/frontend/node_modules .worktrees/rectification-grounding-20260927/frontend/node_modules
|
||
cd .worktrees/rectification-grounding-20260927 && git status -sb
|
||
export PATH=/exec-daemon:$PATH # Node 22
|
||
```
|
||
|
||
先读:`AGENTS.md`(§5–§8)、`frontend/AGENTS.md`、`frontend/DESIGN.md`、`frontend/docs/VOICE.md`、`docs/BUG_HISTORY.md` 的 BUG-569、588、593、606、615、621、1047、1053、`docs/research/pre_work_error_ledger.md` ERR-110/111/112。开工先在未改动的基线上跑全量前端测试(Node 22)与全量 Python 门禁集,存日志作对比。
|
||
|
||
## BUG 编号
|
||
|
||
本单预留 **BUG-1055(D1)、BUG-1056(D2)、BUG-1057(D3)、BUG-1058(D4)**;并行的数据卡单新缺陷从 BUG-1059 起。开工与提交时各核对一次最大号。
|