docs(tasks): accept 814c924e (BUG-565~568, explain/range/unknown-time); capability fix brief (BUG-569~570)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
This commit is contained in:
Jesse_Chen
2026-09-07 01:18:00 +00:00
parent 814c924e4a
commit d6ee8cbb26
6 changed files with 121 additions and 4 deletions
+5 -4
View File
@@ -62,10 +62,11 @@
| `TASK-session-title-guard-fix-20260906.md` | `PROGRESS-session-title-guard-fix-20260906.md` | BUG-553 修复单:`consult/route.ts` 标题守卫比较的是 RPC 前快照,`append_consultation_question` 已改写标题,守卫恒 0 行,模型标题只靠客户端 PATCH 落库 | 待验收 | `codex/session-title-guard-fix-20260906`BUG-557 |
| `TASK-rectification-collect-vs-offer-consistency-20260905.md` | `PROGRESS-rectification-collect-vs-offer-consistency-20260905.md` | 带年份采集没问完就出采用卡 + 报告,同一轮又被搬家采集题把卡挤掉:决策层判 `adopt_representative` 而计划层仍有 dated 采集(BUG-546 只修了一半);改为剩余采集未完保持 `collect_evidence`,出牌轮才出卡写报告 | 已验收通过 `ca4e2408`2026-09-05staging 部署仍停在 `afd14948``deploy-staging``c295b853` 起连续失败,先解决 `bab07187` 的待迁移) | `codex/rectification-collect-vs-offer-consistency-20260905`BUG-550 |
| `TASK-rectification-convergence-exit-20260906.md` | `PROGRESS-rectification-convergence-exit-20260906.md` | 采集问完落到「也可以再说一件事」无出口(非收敛出牌/非终止修复兜底 `other`)、同年月多领域拆题与同域同年重复问、`relative_support` 正比例归一把引擎证据压平成 7–9 使 lead 8 不可达;改为穷尽即交付 + 口述态停止按钮、同年月合并为「发生了什么」四选卡 + 同域同年去重 + 性格题须锚点、prior 按 (分−窗口最低分) 归一并过 20 例公开 holdout 校准门 | 已验收(部分完成:B2 合并卡未做、C 校准未过门未启用;1 P1 + 2 P2 见修复单) | `150d7ef1` / `3a9ae736` / `62afa521`BUG-558560,已合入 staging|
| `TASK-rectification-convergence-exit-fix-20260906.md` | `PROGRESS-rectification-convergence-exit-fix-20260906.md` | BUG-558 修复单:门槛翻译句每回合写 2~3 条相同助手消息(`persistExhaustionCollect` 自己写 turn + 非终止修复再写一次)、穷尽分支排在问题持久化前吞掉可渲染区分卡/holdout 题、范围小字变按钮但文案仍是状态句;并把校准结论(引擎原始分分钟级区分力≈随机)写进 BUG-560 与 BLOCKED | 验收 | `codex/rectification-convergence-exit-fix-20260906`BUG-565567 |
| `TASK-rectification-explain-layer-20260906.md` | `PROGRESS-rectification-explain-layer-20260906.md` | 过程解释层(对照上游 yinduzhanxing 旧工作台唯一领先的业务层):每张卡服务端生成「为什么问这题」与 A/B/C/D「答了会怎样」、答后旁白改成「哪段升降 + 范围从 X 收到 Y」、每轮步骤条「第 N 步 / 为什么 / 下一步」;不做双视图 | 验收 | 叠在 `codex/rectification-convergence-exit-fix-20260906` |
| `TASK-rectification-range-reading-20260906.md` | `PROGRESS-rectification-range-reading-20260906.md` | 可信区间成为一等公民:采用时落库 `adopted_credible_range`,报告 `read_report_candidate_range` 与聊天 `verified_chart(accepted)` 都改读它并接同一份 `birth_time_sensitivity`(现在报告读的是开工窗口,BUG-568);引擎 >15 分钟只取 3 样本改为 ≤31 逐分钟;采用旁白加「稳定 / 随分钟变」两句;`declared_birth_window` 复用 | 验收 | 叠在 `codex/rectification-convergence-exit-fix-20260906`BUG-568 |
| `TASK-rectification-unknown-time-20260906.md` | `PROGRESS-rectification-unknown-time-20260906.md` | 完全不知道出生时间的两段式路线:`stage=block_scan` 以 10 分钟步长扫 24 小时只做事件计分、出五时段四选卡(不写账本不采用),选定后进现有分钟流程;引擎加 `minute_step`;开场读 `birth_time_clue`;删 intake 劝退文案 | 验收 | 叠在 `codex/rectification-convergence-exit-fix-20260906` |
| `TASK-rectification-convergence-exit-fix-20260906.md` | `PROGRESS-rectification-convergence-exit-fix-20260906.md` | BUG-558 修复单:门槛翻译句每回合写 2~3 条相同助手消息(`persistExhaustionCollect` 自己写 turn + 非终止修复再写一次)、穷尽分支排在问题持久化前吞掉可渲染区分卡/holdout 题、范围小字变按钮但文案仍是状态句;并把校准结论(引擎原始分分钟级区分力≈随机)写进 BUG-560 与 BLOCKED | 验收通过 | `814c924e`BUG-565567);staging 未部署,需先 Migrate Staging Database |
| `TASK-rectification-explain-layer-20260906.md` | `PROGRESS-rectification-explain-layer-20260906.md` | 过程解释层(对照上游 yinduzhanxing 旧工作台唯一领先的业务层):每张卡服务端生成「为什么问这题」与 A/B/C/D「答了会怎样」、答后旁白改成「哪段升降 + 范围从 X 收到 Y」、每轮步骤条「第 N 步 / 为什么 / 下一步」;不做双视图 | 验收(带修复单:答后旁白比的是搜索窗口,永远「范围没变」,P1) | `814c924e`;修复单 `TASK-rectification-capability-fix-20260907.md`BUG-569 |
| `TASK-rectification-range-reading-20260906.md` | `PROGRESS-rectification-range-reading-20260906.md` | 可信区间成为一等公民:采用时落库 `adopted_credible_range`,报告 `read_report_candidate_range` 与聊天 `verified_chart(accepted)` 都改读它并接同一份 `birth_time_sensitivity`(现在报告读的是开工窗口,BUG-568);引擎 >15 分钟只取 3 样本改为 ≤31 逐分钟;采用旁白加「稳定 / 随分钟变」两句;`declared_birth_window` 复用 | 验收通过(test:db 37/0 为执行方数字,本机无 Docker) | `814c924e`BUG-568;两条迁移待应用 |
| `TASK-rectification-unknown-time-20260906.md` | `PROGRESS-rectification-unknown-time-20260906.md` | 完全不知道出生时间的两段式路线:`stage=block_scan` 以 10 分钟步长扫 24 小时只做事件计分、出五时段四选卡(不写账本不采用),选定后进现有分钟流程;引擎加 `minute_step`;开场读 `birth_time_clue`;删 intake 劝退文案 | 验收(带修复单:时段支持度按段长偏置,下午段先天 25%,P1) | `814c924e`;修复单 `TASK-rectification-capability-fix-20260907.md`BUG-570 |
| `TASK-rectification-capability-fix-20260907.md` | `PROGRESS-rectification-capability-fix-20260907.md` | 能力补齐修复单:答后旁白把 `range_start/range_end`(搜索窗口)当范围比较,每题都说「范围没变」;`block_scan` 五段支持度按段内原始分求和,长时段先天占优(24/24/36/30/30 个候选);`TRACK_LABEL` 音译与产品 Vimshottari/Narayana 口径不一;BLK-001 写到 `docs/BLOCKED.md` 应回根目录 | 待领取 | `codex/rectification-capability-fix-20260907`BUG-569570 |
| `TASK-api-not-configured-mislabel-20260904.md` | `PROGRESS-api-not-configured-mislabel-20260904.md` | 16 处路由把数据库瞬断(部署切换窗口)兜底翻译成 503「服务尚未配置」;改为仅配置错误用该文案,其余 `service_unavailable`,收敛为共享 helper | 已验收 | `5483649b`(BUG-542);2 条子进程测试留 CI Node 22 复核 |
| `TASK-rectification-ux-20260902.md` | `PROGRESS-rectification-ux-20260903.md` | 会话面空白假死与交互摩擦 | 已验收 | `d159f08e`(09-03 在新基线重做后合入,BUG-505509 |
@@ -0,0 +1,72 @@
# TASK · 校正能力补齐修复单:答后旁白比错范围、时段支持度按时段长度偏置(2026-09-07)
- 基线:`origin/staging` @ `814c924e`(含 BUG-565~568 与三份能力任务书的实现)
- 分支:`codex/rectification-capability-fix-20260907`
- 执行方:coding agent;验收:Claude
- 涉及文件:`frontend/src/lib/rectification-agentic/v9/answer-choice.ts``probe-explain.ts``frontend/tests/rectification-answer-choice.test.ts``scripts/rectification/api_service.py::block_scan``tests/test_rectification_v5_services.py``BLOCKED.md` / `docs/BLOCKED.md`
- BUG 编号起点:**BUG-569**(开工时 `grep -o "^## BUG-5[0-9][0-9]" docs/BUG_HISTORY.md | tail -1` 复核)
- 父任务书:`TASK-rectification-explain-layer-20260906.md``TASK-rectification-unknown-time-20260906.md`(验收记录在各自末尾)
## 1. 事故实证
### 1.1 P1 · 答后旁白永远说「范围没变」(BUG-569)
`answer-choice.ts` L595596 把 `[previous.range_start, previous.range_end]``[applied.state.range_start, applied.state.range_end]` 传给 `composeChoiceNarration``InferenceState.range_start/range_end` 是候选**搜索窗口**`build-state.ts` L149 直接抄入参,答题从不改变);答题真正改变的是 `credible_range``build-state.ts` L159`unionStillValidRange`)。结果:无论候选如何淘汰,用户每答一题都看到「范围没变」,而顶部只读范围已经在收窄。`rectification-answer-choice.test.ts` L12101231 直接给 `composeChoiceNarration` 喂了两个不同范围,所以没拦住。
### 1.2 P1 · 时段支持度按时段长度偏置(BUG-570)
`api_service.py::block_scan` 对五个时段分别 `sum(score)`。10 分钟步长下段内候选数:清晨 24、上午 24、下午 36、傍晚 30、夜里 30。引擎原始分底座 11~15、事件差只有 4~5(BUG-560),所以在**没有任何证据差异**时下午段已占 25.0%、清晨只有 16.7%;第一张时段卡实际在比时段长度。
### 1.3 P2 · 文案
`probe-explain.ts``TRACK_LABEL` 把两条大运写成「毗湿奴多利、那罗延」。产品其他位置(`rectification-varga-sentence.ts`「本轮对照了 Vimshottari、Narayana…」、Skill 报告)一律用 Vimshottari / Narayana。
### 1.4 P3 · BLOCKED 位置
BLK-001 写进了新建的 `docs/BLOCKED.md``AGENTS.md` §4 约定被环境挡住的事项写根目录 `BLOCKED.md`(已有 85 行)。两处并存会漂。
## 2. 决策记录
1. 旁白比的是 `credible_range`(前:`previous.credible_range`;后:`applied.state.credible_range`),二者任一为空时不说范围句。
2. 时段支持度 = 段内候选**均值**减去**全日最低分**后归一(`max(mean_block min_day, 0)`),全部为零时均分。这是对 BUG-560「不得换尺度」的例外:BUG-560 说的是分钟级 prior,时段级比较本来就是任务书 C 授权的新口径,且不进采用门。
3. `TRACK_LABEL` 改 Vimshottari / Narayana,与 `rectification-varga-sentence.ts` 同源(直接复用其映射表,不再维护第二份)。
4. `docs/BLOCKED.md` 的 BLK-001 搬回根目录 `BLOCKED.md` 末尾,删除 `docs/BLOCKED.md`
## 3. 硬红线
- 不改 `minute_step=1` 路径的任何字节(`test_rectification_v5_services.py` 指纹用例继续通过)。
- 不动采用门、确认门、`MIN_SEPARATION_LEAD``_relative_support`(分钟级 prior 仍是 proportionalBUG-560 保持 blocked)。
- 既有断言改动写三栏;测试总数 ≥ 1518(本次验收实测口径:`rectification-*` + `consultation-*` + `report-*` + `personal-report-*` + voice 契约,排除 database)。
## 4. 任务分解
### 4.1 BUG-569
- `applyRectificationChoice` 改传 `credible_range``composeChoiceNarration` 入参改名 `credibleBefore/credibleAfter` 防止再传错。
- 验收:`rectification-answer-choice.test.ts` 新增端到端用例——构造 `previous` state`range_start/range_end` 固定,`credible_range` 宽)与答 A 后 `credible_range` 收窄,断言旁白含「范围从 X 收到 Y」;再一例 `credible_range` 不变 → 「范围没变」;三栏说明改掉 L1210–1231 的直喂用例或保留为纯函数用例。
### 4.2 BUG-570
- `block_scan``raw_support = max(mean(score in block) min(all scores), 0)``candidate_count` 已在返回里,保留。
- 验收:`test_rectification_v5_services.py` 新增——用 `row_provider` 或直接构造等分 `candidate_scores`144 行同分)→ 五段 `relative_support` 各 20.0;只把清晨段抬高 → 清晨最高且下午不再因长度领先。
### 4.3 P2 / P3
- `TRACK_LABEL` 复用 `rectification-varga-sentence.ts` 的标签表;`agent-voice-copy-contract` 增加「不得出现 毗湿奴多利 / 那罗延」守卫。
- BLK-001 搬回根目录 `BLOCKED.md`,删 `docs/BLOCKED.md``docs/tasks/PROGRESS-rectification-convergence-exit-fix-20260906.md` 的引用改路径。
### 4.4 记录
- `docs/BUG_HISTORY.md` BUG-569、BUG-570`CHANGELOG.md``docs/tasks/PROGRESS-rectification-capability-fix-20260907.md``docs/testing/rectification-explain-layer-20260906.md` 第 2 条改为「答完一题旁白里的范围与顶部范围一致」。
## 5. 让步顺序
4.1 + 4.2 不可拆;4.3 可后置到同分支第二次提交;4.4 不可省。
## 6. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/rectification-capability-fix-20260907 .worktrees/rectification-capability-fix-20260907 origin/staging
cd .worktrees/rectification-capability-fix-20260907
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
ln -s /workspace/Jyotisha/.venv .venv
.venv/bin/python -m pytest tests/test_rectification_v5_services.py -q
cd frontend && ls tests/rectification-*.test.ts tests/consultation-*.test.ts tests/report-*.test.ts tests/personal-report-*.test.ts tests/agent-voice-copy-contract.test.ts | grep -v database | xargs npx tsx --test 2>&1 | grep -E "^# (tests|pass|fail)"
```
@@ -89,3 +89,14 @@ cd frontend && ls tests/rectification-*.test.ts tests/agent-voice-copy-contract.
```
收尾同一命令 fail=0、总数 ≥ 905;`tsc --noEmit``npm run lint`
## 验收(Claude2026-09-07`origin/staging` @ `814c924e`
实现随 `814c924e` 一次提交合入(与 explain-layer / range-reading / unknown-time 同一提交)。独立复跑:tsc 0 错;lint 0 error / 82 warning`rectification-*` + `consultation-*` + `report-*` + `personal-report-*` + voice 契约 1518 pass / 0 fail。
| 项 | 结论 |
| --- | --- |
| 5.1 单一写入方 | 通过。`persistExhaustionCollect` 不再写 turn;流式消息回合经 `actionToBudget` 映射为 agent-run `evidence`,由 agent-run 用 `${turnId}:gate` 幂等键写一次,finalize 见 `askedTurnId` 跳过;点选路径只拼进正文。测试对 message / evidence / 最后一张卡各计 1 次 |
| 5.2 穷尽态视为已交付 | 通过。`isExhaustedGateState``inspectNonTerminalTurnExit` 共用 |
| 5.3 不吞题 | 通过。白名单 `offer_provisional_range / complete_with_range / ask_fact_collection` |
| 5.4 范围小字还原 + 记录 | 通过。BUG-560 根因升级已写;BLK-001 写进了 `docs/BLOCKED.md`——仓库约定是根目录 `BLOCKED.md`,见修复单 P3 |
@@ -70,3 +70,13 @@ 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,见修复单 |
@@ -83,3 +83,16 @@ cd frontend && ls tests/rectification-*.test.ts tests/consultation-*.test.ts tes
.venv/bin/python -m pytest tests/test_rectification_v5_services.py -q
grep -o "^## BUG-5[0-9][0-9]" docs/BUG_HISTORY.md | tail -1
```
## 验收(Claude2026-09-07`origin/staging` @ `814c924e`
| 项 | 结论 |
| --- | --- |
| A1 落库 + RPC | 通过(代码审阅)。迁移 `20260906020000_adopted_credible_range.sql`:加列、六参采用函数、`read_report_candidate_range` 优先 `adopted_credible_range`;不改 `candidate_range`。Docker `test:db` 由执行方在有 Docker 的机器跑 37/0,本机无 Docker,按环境缺口记,不重复宣称 |
| A2 引擎采样 | 通过。≤31 逐分钟;>31 等距 31 点;`approximate` 且 >31 才 3 采样(决策 5);`flexible_birth_time_profile` 上限 15→31(任务书按 31 写,仓库原值 15,执行方如实记录) |
| A3 聊天 | 通过。`verified_chart(accepted)` 加载最近一个 `candidate_accepted` Case 的区间(不带 case idSQL 取 `updated_at desc limit 1`,可接受),`birth_time_accuracy=provisional` + `candidate_range` 进 workflow`minute_sensitive_themes` 进 answer_policy 并触发输出守卫 |
| A4 采用旁白 | 通过。稳定/敏感两句由 `theme_sensitivity` 生成,带边界句,引擎不可用静默省略 |
| A5 declared_birth_window | 通过(「这只是粗看」) |
| A6 记录 | 通过 |
部署提醒:staging 当前 `b938c76a`,本轮两条新迁移(`20260906020000``20260906030000`)未应用,部署前先跑 Migrate Staging Database。
@@ -93,3 +93,13 @@ for start, end in (("04:30","05:30"), ("13:00","17:00")):
t = time.time(); out = score_candidates(req)
print(start, end, len(out["candidate_scores"]), "minutes", round(time.time()-t, 1), "s")
```
## 验收(Claude2026-09-07`origin/staging` @ `814c924e`
| 项 | 结论 |
| --- | --- |
| C1 引擎 `minute_step` | 通过。我用任务书附录的虚构资料在新旧引擎各跑一次:`candidate_scores`、公开候选与支持度、探针键、`result_id``calculation_spec_hash` 全部相等,`minute_step=1` 字节级不变成立。`minute_step>1` 不出探针、`precision_stage=block_scan` |
| C1 `block_scan` 聚合 | **未通过(P1BUG-570**:五段支持度 = 各段内候选**原始分之和**。10 分钟步长下五段候选数是 24 / 24 / 36 / 30 / 30,下午段仅因为长 6 小时就先天占 25%,清晨 16.7%;引擎原始分底座又远大于事件差(BUG-560),于是首张时段卡基本是在比时段长度。应按段内均值并减去全日最低分归一,等分网格必须得到 20/20/20/20/20 |
| C2 Case 阶段 | 通过(代码审阅)。`stage` 列 + check 约束 + 三个 RPC;存量 unknown 全日 Case 回填为 block_scan;无 Docker`test:db` 37/0 取执行方数字 |
| C3 采集与时段卡 | 通过。门槛用 3 件 / 2 域(不走 holdout 分层,执行方理由成立);A/B/C 改窗口切 minute 并重算;D 只写 `declined_at_fingerprint`block_scan 阶段 `can_adopt`/`selection_allowed` 恒 false、`latestProjection` 为空;开场读 `birth_time_clue` 只进旁白 |
| C4 记录 | 通过;SKILL 不 bump 的理由(stage 非 Case status)成立 |