Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
61 lines
5.3 KiB
Markdown
61 lines
5.3 KiB
Markdown
# TASK · 生时校正时间轴修复单:宽度读数与卡片/报告口径不一致;被排除的分钟根本到不了客户端,"空心点"画不出来(2026-09-09)
|
||
|
||
- 基线:`origin/staging` @ `724a1215`(时间轴 `ce91a0d2` 已合入并部署)
|
||
- 分支:`codex/rectification-timeline-fix-20260909`,基于 `origin/staging`
|
||
- 执行方:coding agent;验收:Claude
|
||
- 涉及文件:`frontend/src/lib/rectification-timeline-scale.ts`、`frontend/src/components/rectification-agentic-chat.tsx`(`timelineView` 的 `candidateTimes` 来源)、`frontend/src/lib/rectification-candidate-result.ts`(或直接读 `decisionReceipt.inference_state.candidates`)、`frontend/tests/rectification-timeline-20260909.test.ts`、`frontend/DESIGN.md` §10
|
||
- BUG 编号起点:**BUG-602**(`docs/BUG_HISTORY.md` 当前最大 BUG-601)
|
||
- 优先级:**P1**(两处都是"条上写的和别处不一样",用户会当成算错)
|
||
|
||
## 1. 事实
|
||
|
||
### 1.1 BUG-602:宽度按差值算,卡片与报告按含两端算
|
||
|
||
`timelineDurationLabel(bandEnd - bandStart)`:04:51–04:59 显示"8 分钟",05:07–05:09 显示"2 分钟",整天窗口显示"23 小时 59 分"。而 BUG-593 已把交付报告与三列卡的宽度定为**含两端的分钟数**:04:51–04:59 = 9 分钟、04:51–04:53 = 3 分钟(`rectification-delivery-report-facts.test.ts`)。同一屏上条写 8、卡写 9。任务书 §4.3 的示例"05:07–05:09 · 2 分钟"本身就是差值口径,执行方照抄了。
|
||
|
||
### 1.2 BUG-603:客户端候选列表只含 active 分钟,被排除的分钟不会变空心、而是消失
|
||
|
||
`inference-adapter.ts` L292 `candidates = active.flatMap(...)`:投影只保留 `status !== "eliminated"` 的候选;`rectification-agentic-chat.tsx` 把 `candidateResult.candidates.map(time)` 喂给时间轴,`buildRectificationTimeline` 再按"是否落在区间带内"判 in/out。结果:分钟阶段所有到达客户端的点都在带内、全是实心;答完一题被淘汰的分钟直接从条上消失。DESIGN.md §10 写的"被排除的点留在原地变空心、不消失——用户由此看见自己刚才那一答排掉了哪几分钟"在真实数据下不成立;测试里的 `["out","in","in","in","out"]` 是合成输入。另外 `credible_range` 是 active 候选的跨度,带内若有被淘汰分钟(可能出现)也会被按位置判成 in。
|
||
|
||
## 2. 决策记录
|
||
|
||
1. **宽度统一为含两端分钟数**:`widthLabel = timelineDurationLabel(bandEnd - bandStart + 1)`;整天窗口显示"24 小时";单分钟显示"1 分钟"。DESIGN.md §10 示例改为"05:07–05:09 · 3 分钟"。
|
||
2. **标记来源改为推断层候选全集**:客户端从 `decisionReceipt.inference_state.candidates`(有 `time`、`status`)取点;`state = status === "eliminated" ? "out" : "in"`,不再按位置判。没有 `inference_state` 时退回现有行为(引擎候选全部实心)。`RectificationCandidateResult` 加只读字段 `inferenceMarks: [{time, eliminated}]`,解析放在 `rectification-candidate-result.ts`,组件不碰 receipt。
|
||
3. 二元编码、只读、固定条高、grid 行、transform-only 全部不动;`use-conversation-scroll-anchor.ts` 仍一行不改。
|
||
|
||
## 3. 验收
|
||
|
||
- (a) 04:51–04:59 → "9 分钟";05:07–05:09 → "3 分钟";00:00–23:59 整天 → "24 小时";`rectification-delivery-report-facts.test.ts` 的同一形状与条读数一致。
|
||
- (b) 推断层 9 个候选、7 个 eliminated、`credible_range` 04:51–04:53 → 条上 9 个点,7 空心 2 实心;下一轮再淘汰 1 个 → 8 空心 1 实心,点的 key 不变(过渡不重建)。
|
||
- (c) 无 `inference_state`(时段阶段刚选定)→ 引擎候选全部实心,行为同今天。
|
||
- (d) 三栏:`widthLabel` 用例原值/新值/原因;合成 marks 用例改为按 status。
|
||
- (e) 记录:BUG-602(关联 BUG-593)、BUG-603(关联 BUG-560、DESIGN §10);`CHANGELOG.md`;`PROGRESS-…`;`docs/testing/rectification-timeline-20260909.md` §4 第一条改为"被排除的分钟变空心且不消失(数据来自推断层)"。
|
||
|
||
## 4. 开工前置命令
|
||
|
||
```bash
|
||
git fetch origin --prune
|
||
git worktree add -b codex/rectification-timeline-fix-20260909 .worktrees/rectification-timeline-fix-20260909 origin/staging
|
||
cd .worktrees/rectification-timeline-fix-20260909
|
||
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
|
||
cd frontend && ./node_modules/.bin/tsc --noEmit; npm run lint 2>&1 | tail -1
|
||
npx tsx --test tests/rectification-timeline-20260909.test.ts tests/rectification-delivery-report-facts.test.ts 2>&1 | grep -E "^# (tests|pass|fail)"
|
||
```
|
||
|
||
## 验收(Claude,2026-09-09,`origin/staging` @ `04ad3325`;staging 当时部署 `fa293b31`)
|
||
|
||
| 门 | 结果 |
|
||
| --- | --- |
|
||
| tsc | 0 错 |
|
||
| lint | 0 error / 108 warning |
|
||
| 前端 rectification + consultation + session + voice + skill-registry(非 DB) | 1347 / 0 |
|
||
| Python v5_services + event_probes + growth contract | 72 passed / 0 failed |
|
||
|
||
| 项 | 结论 |
|
||
| --- | --- |
|
||
| BUG-602 宽度含两端 | 通过。`bandEnd - bandStart + 1`;七组三栏齐全,与 BUG-593 报告口径一致 |
|
||
| BUG-603 空心点来自推断层 | 通过。`inferenceMarks` 由 `decisionReceipt.inference_state.candidates` 解析,`eliminated` 是唯一判据;无推断层退回全实心 |
|
||
| 偏离 2(`inferenceMarks` 可选、解析器始终赋值) | 接受 |
|
||
|
||
结论:通过(实现 `92e3d5e7`)。
|