Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
4.5 KiB
4.5 KiB
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. 决策记录
- 宽度统一为含两端分钟数:
widthLabel = timelineDurationLabel(bandEnd - bandStart + 1);整天窗口显示"24 小时";单分钟显示"1 分钟"。DESIGN.md §10 示例改为"05:07–05:09 · 3 分钟"。 - 标记来源改为推断层候选全集:客户端从
decisionReceipt.inference_state.candidates(有time、status)取点;state = status === "eliminated" ? "out" : "in",不再按位置判。没有inference_state时退回现有行为(引擎候选全部实心)。RectificationCandidateResult加只读字段inferenceMarks: [{time, eliminated}],解析放在rectification-candidate-result.ts,组件不碰 receipt。 - 二元编码、只读、固定条高、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_range04: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. 开工前置命令
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)"