验收 a266b6b7 / c5fbee56:tsc、lint、新套件全绿,但 npm test 由 27 涨到 32——
4 条 exit 断言的短语表没加新交付文案、1 条公开字段深比较没加 birth_time_source,
都不是行为回归但违反红线。另有用户可见的数字矛盾:邀请语硬编码「这两分钟」,
同段话却写着「还剩 4 个候选」。本单修文案按候选数出话、两处断言跟上,并给精度
研究 M1b 追加勘误:V1/V2 三档数字与 V0 完全相同且作者自承采集走错路径,判定
作废改为未测(V3 结论保留)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
8.0 KiB
8.0 KiB
TASK · 修复单:邀请文案说错候选数 + 5 条断言没跟上 — 2026-09-15
- 基线:
origin/staging@dfb572fc(代码最新c5fbee56。staging 当前部署cf972f40,BUG-689 / BUG-690 均未上线,本回归没有影响真实用户)。 - 分支:
codex/rectification-invite-copy-fix-20260915,worktree.worktrees/rectification-invite-copy-fix-20260915。 - 关联:本单是
TASK-rectification-open-collect-invite-20260914.md(BUG-689,实现a266b6b7)与TASK-rectification-birth-time-provenance-20260914.md(BUG-690,实现c5fbee56)的验收修复单。另关联 BUG-688(同一组 exit 断言上一轮刚恢复过)、BUG-587。 - 串行:改
user-copy.ts/collection-question-pool.ts文案一处 + 两个测试文件 + 一份研究文档勘误;与在途分支无重叠。
1. 事故实证(Claude 验收,2026-09-15)
在 dfb572fc 上跑门禁:tsc --noEmit 0 错、npm run lint 0 error、新增套件(open-collect-invite / birth-time-provenance / agent-voice-copy-contract)24/24 全绿、研究单 tests/test_precision_gate_research.py 12 passed。
但 npm test 从基线 27 条涨到 32 条,新增 5 条:
| 文件 | 红掉的断言 | 性质 |
|---|---|---|
rectification-exhaustion-exit-20260906.test.ts |
closed ceiling with training open delivers a range and a concrete next-collect hint、inconsistent projection logs ranked_count 0 and still delivers a gate、last closed-ceiling card concatenates the gate into one append、ensureNonTerminalTurnExit writes a host turn when exhausted with no carrier |
exitAppendCalls() 的短语表没有加入 BUG-689 的新交付文案,于是「有没有写出口载体」判成 0 |
rectification-decision-authority.test.ts |
public decision fields are derived from decideRectification |
深比较的字段集合没有加 BUG-690 新增的 birth_time_source |
这 5 条都不是行为回归——实测输出里交付旁白写得很完整(下面那段),只是断言的短语表与字段集合过期。但上一轮(BUG-688)刚刚因为同一组断言被弱化而立过修复单,这次连更新都没做就交付,违反任务书红线第 1 条(npm test 失败数必须等于基线)。
P2 · 邀请文案说错候选数(用户可见)
实测输出(rectification-exhaustion-exit 用例里原文):
已经从最初的 20 分钟收到 04:47–04:53 这 6 分钟。眼下更像 04:51。
现在还剩 04:47–04:53 里 4 个候选。这两分钟按现有信息分不开。
你要是还记得确切哪一天的事,不限领域,说出来我接着算——……
前一句刚说「还剩 4 个候选」,后一句就说「这两分钟按现有信息分不开」。根因是 RECTIFICATION_USER_COPY.rangeDeliveryCollectClosed(frontend/src/lib/rectification-agentic/user-copy.ts:176)把「这两分钟」硬编码进了句首——它原本是 tie-break 用语(rangeDeliveryTieBreakUsed,那里确实是两个候选),BUG-689 复用时没有按实际候选数改写。
调用点:collection-question-pool.ts:847 / :849(rangeNarrowHint)。
2. 根因
- 5 条断言:BUG-689 改了交付文案、BUG-690 加了公开字段,但两处"锁契约"的测试没同步。
- 文案:把固定两候选场景的句子复用到任意候选数的场景。
3. 决策记录
| 决策 | 内容 |
|---|---|
| D1 | exitAppendCalls() 的短语表加入 BUG-689 的新交付文案(「收到 … 这 N 分钟」「按现有信息分不开」「说出来我接着算」这一组)。这些确实是出口载体(它们就是交付旁白本身),加入合规。但不得再次放宽 assert.equal(gates.length, 1) 的"恰好一条"语义(BUG-688 的防复发条),也不得把参考题确认语「只微调排序」加回去。 |
| D2 | rectification-decision-authority.test.ts 补 birth_time_source 字段,保持深比较(不得改成部分匹配来绕过)。公开字段集合变化必须被这条测试挡住,这是它存在的意义。 |
| D3 | 文案按实际候选数出话。 候选数 = 2 才可以说「这两分钟」;> 2 说「这几个候选」或直接复述范围;候选数未知时不说这半句。不得在同一段话里出现互相矛盾的数字。 |
| D4 | 研究文档追加勘误(不删原文):docs/research/precision_gate_2026_09_14.md 的 M1b 里,V1 与 V2 在三档半径上的数字与 V0 完全相同,而该节自己写明「V0 采集误走了生产计分、没有打上分盘标签」;V3 有差异说明机制能生效,因此 V1/V2 大概率未被真正应用,其 no_benefit 判定作废,标为「未测」。V3(加 D60,±10 命中 0.80→0.70)的结论可信,保留。重跑与否另行决定,本单只做勘误。 |
| D5 | 不改打分、判据、置信度与确认门控;不改 BUG-689/690 的既有行为(交付卡照出、来源标签分档)。 |
4. 硬红线
tsc --noEmit0 错;npm run lint0 error;npm test失败数必须回到基线 27 条,且不得靠弱化断言达成;next build通过且/仍○ Static。- 新增/修改断言必须是行为断言;改既有断言按 §7.3 写「原值 / 新值 / 原因」三栏。
- 不得回退 BUG-688 恢复的两条断言语义。
- 文案改动对照
frontend/docs/VOICE.md;改 UI 的提交同时更新frontend/DESIGN.md。
5. 任务分解
任务 1 · 文案按候选数出话(P0)
user-copy.ts:176的rangeDeliveryCollectClosed改成函数或参数化模板,接收候选数;collection-question-pool.ts:847/:849两个调用点传入candidateCount。- 验收标准:
- 行为单测:候选数 = 2 → 文案含「这两分钟」;候选数 = 4 → 不含「这两分钟」,且与前半句的候选数一致(用正则同时校验两处数字);候选数未知 → 不出现该半句。
- 回归:邀请语的其余部分(不限领域、日期优先例子、年月例子)不变。
任务 2 · 两处断言跟上(P0)
rectification-exhaustion-exit-20260906.test.ts的exitAppendCalls()按 D1 加短语;四条恢复绿。rectification-decision-authority.test.ts按 D2 补字段;一条恢复绿。- 验收标准:
npm test失败数 = 27,且assert.equal(gates.length, 1)与「不含只微调排序」两条仍在。
任务 3 · 研究文档勘误(P1)
- 按 D4 在
docs/research/precision_gate_2026_09_14.md的 M1b 追加勘误段,并把总表里 V1/V2 的判定从no_benefit改成not_measured(原值保留在勘误里)。 - 同步更新
docs/research/rectification_minute_resolution_closure_2026_09_14.md的索引段,注明 M1b 的 V1/V2 未测。
任务 4 · 记录
docs/BUG_HISTORY.md新增 BUG-692(resolved):现象写「交付邀请语说『这两分钟』但同段话写着 4 个候选;同时 5 条契约断言未随文案与字段更新」;防复发条:文案里出现的数字必须来自同一份数据,不得硬编码;改用户可见文案或公开字段时,必须同步跑npm test并把失败数与基线比对。CHANGELOG.md一行;PROGRESS-rectification-invite-copy-fix-20260915.md;docs/testing/清单补一条:交付卡上"候选数"与"这两分钟/这几个候选"的说法必须一致。
6. 让步顺序
- 任务 2 最优先(门禁红着不能发布)。
- 任务 1 必做(用户可见的数字矛盾)。
- 任务 3 可延后但不得省略。
7. 开工前置命令
git fetch origin --prune
git worktree add -b codex/rectification-invite-copy-fix-20260915 \
.worktrees/rectification-invite-copy-fix-20260915 origin/staging
cd .worktrees/rectification-invite-copy-fix-20260915
ln -s /workspace/Jyotisha/.venv .venv
cd frontend && npm ci
npx tsx --test tests/rectification-exhaustion-exit-20260906.test.ts tests/rectification-decision-authority.test.ts # 先复现 5 条红
8. BUG 编号起点
- 起点 BUG-692(当前最大号 690;691 已被
TASK-rectification-record-conflict-copy-20260914.md预留)。