diff --git a/docs/tasks/README.md b/docs/tasks/README.md index de6a7f5f..f4124fd9 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -186,6 +186,8 @@ | `TASK-rectification-tiebreak-hold-exit-fix-20260914.md` | `PROGRESS-rectification-tiebreak-hold-exit-20260914.md` | **P0 回归修复单**:BUG-686 的风格题前置把耗尽与收口路径的交付也压住了,`npm test` 由 27 红涨到 33(6 条「该交付却不交付」)。后续 `6fd7925a` 只改断言把它们改绿:4 条文案放宽可接受,2 条实质弱化(「恰好一条交付闸」退化成短路、参考题确认语被算作出口载体)必须恢复;行为层根因未动。hold 要带出口、不得作用于 exhausted/closed-ceiling,最多 hold 一次(BUG-688)。尚未部署,未影响线上 | 待验收 | `codex/rectification-tiebreak-hold-exit-20260914` | +| `TASK-rectification-invite-copy-and-assertions-fix-20260915.md` | `PROGRESS-rectification-invite-copy-fix-20260915.md` | **P0 验收修复单**:BUG-689 的邀请语硬编码「这两分钟」却与同段话的「4 个候选」矛盾;BUG-689/690 各自把 4 条与 1 条契约断言留红(`npm test` 27→32)。修文案按候选数出话、两处断言跟上、并给精度研究 M1b 的 V1/V2 追加「未测」勘误(BUG-692) | 待执行 | `codex/rectification-invite-copy-fix-20260915` | + | `TASK-rectification-record-conflict-copy-20260914.md` | `PROGRESS-rectification-record-conflict-copy-20260914.md` | BUG-690 的 D4 收口:产品 2026-09-14 拍板**记录优先、分歧如实呈现**——默认仍按出生记录时间排盘(行为已成立),校正区间标成「证据倾向」,采用入口在冲突时改成「改用校正结果」;系统不得宣布记录错或校正无效(BUG-691) | 待执行 | `codex/rectification-record-conflict-copy-20260914` | | `TASK-rectification-birth-time-provenance-20260914.md` | `PROGRESS-rectification-birth-time-provenance-20260914.md` | 与上游流程对照发现的缺口(上游 R2):录入时已问「医院记录 / 家人记得大概 / 只知道时段」并落库 `birth_time_source`,但整条校正链只在放宽窗口时用过一次,决策与文案一律不看它——家人推算的时间和出生证在系统里等同对待,输出还直接称「你的出生时间」。本单把来源标签接进投影并分档措辞(BUG-690) | 待验收 | `codex/rectification-birth-time-provenance-20260914` | diff --git a/docs/tasks/TASK-rectification-invite-copy-and-assertions-fix-20260915.md b/docs/tasks/TASK-rectification-invite-copy-and-assertions-fix-20260915.md new file mode 100644 index 00000000..02973a11 --- /dev/null +++ b/docs/tasks/TASK-rectification-invite-copy-and-assertions-fix-20260915.md @@ -0,0 +1,102 @@ +# 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. 硬红线 + +1. `tsc --noEmit` 0 错;`npm run lint` 0 error;**`npm test` 失败数必须回到基线 27 条**,且不得靠弱化断言达成;`next build` 通过且 `/` 仍 `○ Static`。 +2. 新增/修改断言必须是行为断言;改既有断言按 §7.3 写「原值 / 新值 / 原因」三栏。 +3. 不得回退 BUG-688 恢复的两条断言语义。 +4. 文案改动对照 `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. 让步顺序 + +1. 任务 2 最优先(门禁红着不能发布)。 +2. 任务 1 必做(用户可见的数字矛盾)。 +3. 任务 3 可延后但不得省略。 + +## 7. 开工前置命令 + +```bash +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` 预留)。