Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
7.9 KiB
TASK · 生时校正修复单:重算后新出现的候选分钟不继承已答题结论,范围从 13 分钟回弹到 28 分钟;batch 内重算不报范围变化(2026-09-08)
- 基线:
origin/staging@6a687085(BUG-592/593 已合入并部署;本轮转录跑在这版) - 分支:
codex/rectification-new-minute-inherit-20260908,基于origin/staging - 执行方:coding agent;验收:Claude
- 涉及文件:
frontend/src/lib/rectification-agentic/core/build-state.ts(carriedAnsweredProbes、重放循环)、core/apply-probe-outcome.ts(directionFor)、v9/inference-adapter.ts(buildCaseInferenceState传window_scan.transitions)、v9/divergence-panel.ts::signFromTransitions(复用)、v9/agent-run.tsL977(范围句触发条件) - BUG 编号起点:BUG-594
- 优先级:P1(BUG-587 的"新分钟中性"决策是我定的,实测证明它让范围回弹;用户问"这样是不是已经可以了",答案是流程可以、结果不行)
1. 事故实证(2026-09-08 staging 6a687085,只写结构)
| 时点 | 旁白报的范围 |
|---|---|
| 5 道点选题答完(D9、2023.05、2015.05、2024.04、D10) | 04:47–04:59(13 分钟) |
| 之后补迁居事件 → batch 内 compare 重算 | 旁白只说"接下来我们继续",没有范围句 |
| 健康拒答、职业答完 → 交付 | 卡片 04:47–05:14(28 分钟),报告"当前候选基本并列:04:53、04:59、04:51、04:47、05:14",相对支持 17/13/11/10/10 |
报告里的分盘表:05:14 的 D9 是射手座、D10 是狮子座。用户在 D9 题选了天蝎座一侧、D10 题选了巨蟹座一侧,05:14 在两道题上都该是 conflict;2024.04 事业题答"发生"支持 05:00 之后的分钟,2023.05 答"没发生"又反对 05:00–05:14——按老候选集的账,05:xx 这一侧早就被淘汰过(所以此前范围是 04:47–04:59)。05:14 是重算后新进候选集的分钟,它在任何一道已答题的 supports / conflicts 里都没有名字,于是 6 道题对它全部记 0,strong_conflict_count = 0,活着,范围右端被它拉到 05:14。
2. 根因
2.1 BUG-594(P1):新分钟对携带题一律中性
TASK-rectification-probe-replay-loss-20260908.md 决策 2 写的是"新候选集里不在旧 supports/conflicts 的分钟落为 neutral,不做邻近插值"。apply-probe-outcome.ts::directionFor 按候选 id 查成员,新分钟查不到 → neutral。引擎每次重算都重新挑 9 个分钟,几乎每次都有新分钟;新分钟零冲突就成了"幸存者",范围只会变宽不会变窄。这条是我在任务书里定错的,本单推翻。
题目语义本来就是按分钟连续定义的:分盘风格题按该分钟的分盘上升星座(window_scan.transitions 给出每层换升时刻),大运边界/激活题的 expected_outcomes 是连续分钟段。新分钟的结论可以确定性地推出来,不需要"插值"猜。
2.2 BUG-588 缺口:batch 内重算不触发范围句
agent-run.ts L977 只在 toolsUsed.has("rectification-compare-candidates") 时接范围句;证据轮的 compare 是 rectification-record-evidence-batch 内部跑的,工具集合里没有 compare,于是 13→28 分钟没有一句提示。
3. 决策记录
- 携带题对新分钟按题目语义推结论,不再中性。
- 分盘风格题(
choice_kind = varga_style,semantic_key以varga.<layer>.开头):用signFromTransitions(transitions, layer, minute)得到新分钟的该层上升星座,按style_options[].sign与已答answer_class判support / conflict;没有 transitions 或该层无星座 →neutral。 - 大运边界/激活/事件质量题(
expected_outcomes的 supports/conflicts 是分钟集合):新分钟落在某个 outcome 集合的最小分钟与最大分钟之间且两侧最近的旧分钟同属该集合 → 继承该集合;否则neutral。 - 携带题在状态里补
outcome_by_minute(或等价缓存)以便审计;rounds.score_deltas对新分钟出现非 0 值。
- 分盘风格题(
buildCaseInferenceState把window_scan.transitions传给核心层(score-persist.ts已有windowScan),核心层不依赖 v9;signFromTransitions下沉到core/,divergence-panel.ts改为引用。- 范围句改看事实不看工具。
agent-run.ts:本轮结算前比较dossier.latestResult.decisionReceipt.inference_state.credible_range与开始时的值(或resultId变化),变了就接withRangeChangedAfterEvidence,不再看toolsUsed。 - 淘汰阈值
STRONG_CONFLICT_ELIMINATION_COUNT = 3、SCORE_DELTA、各道门槛、四选项合同不动;Skill 不 bump。
4. 任务分解
4.1 BUG-594(决策 1、2)
- 验收(
rectification-probe-replay-loss-20260908.test.ts扩):- (a) 旧候选集 9 分钟、6 道已答题使 05:00 之后全部
strong_conflict_count ≥ 3被淘汰、范围 04:47–04:59;新候选集换入 05:14(D9 射手、D10 狮子,2024.04 supports 段内、2023.05 conflicts 段内)→ 重放后 05:14strong_conflict_count ≥ 3、status = eliminated,credible_range仍为 04:47–04:59。 - (b) 换入的新分钟落在两个 outcome 集合之间(两侧旧分钟分属不同集合)→ 该题对它
neutral。 - (c) 无
transitions时分盘题对新分钟neutral(退化到今天的行为,不报错)。 - (d) 真实 Case 回放(用
exp_case_head.py的合成 7 事件序列):每次加事件后credible_range宽度 ≤ 上一轮宽度 + 新分钟数中未被任何题覆盖的个数;本轮事故形状应保持 13 分钟。
- (a) 旧候选集 9 分钟、6 道已答题使 05:00 之后全部
4.2 BUG-588 缺口(决策 3)
- 验收:mock 一轮 batch 触发的 compare,范围 04:47–04:59 → 04:47–05:14,落库
assistant_message末尾含范围句;范围不变不含;用 compare 工具的路径行为不变。
4.3 记录
docs/BUG_HISTORY.mdBUG-594(关联 BUG-587;写明是任务书决策 2 定错);BUG-588 记录补"后续复发:batch 路径"并在同条下修复;CHANGELOG.md;PROGRESS-rectification-new-minute-inherit-20260908.md;docs/testing/rectification-scenarios-20260907.md加"答题后再补经历,范围不得变宽;变了必须有范围句"。
5. 让步顺序
4.1 (a) 必做并当天部署;(b)(c) 必做;(d) 可用现有合成序列;4.2 必做;4.3 不可省。
6. 开工前置命令
git fetch origin --prune
git worktree add -b codex/rectification-new-minute-inherit-20260908 .worktrees/rectification-new-minute-inherit-20260908 origin/staging
cd .worktrees/rectification-new-minute-inherit-20260908
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
cd frontend && ./node_modules/.bin/tsc --noEmit; npm run lint 2>&1 | tail -1
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)"
验收(Claude,2026-09-08,origin/staging @ be711043,staging 已部署同 SHA)
| 门 | 结果 |
|---|---|
| tsc | 0 错 |
| lint | 0 error / 103 warning |
| 前端 rectification + consultation + voice + skill-registry(非 DB) | 1274 / 0 |
| Python v5_services + growth contract | 全绿 |
| 项 | 结论 |
|---|---|
| 4.1 (a)(b)(c) | 通过。新分钟按分盘星座 / 连续分钟段继承结论;真实 Case(第九次实测)5 题后 04:50–04:59,补事业事件 04:50–05:15→04:50–05:15(有范围句)、补迁居 04:50–04:59→04:51–04:59,不再回弹 |
| 4.1 (d) | 执行方用合成 6 题 + 三次换分钟回放代替(仓库无 exp_case_head.py,那是我的 scratch 脚本),接受 |
| 4.2 BUG-588 缺口 | 通过。真实 Case 两轮证据旁白末尾都有"范围从 … 变为 …" |
| 4.3 记录 | 通过 |
结论:通过。收敛问题到此闭合;交付面精简另立 TASK-rectification-delivery-ui-simplify-20260908.md(BUG-595/596)。