Files
Jyotisha/docs/tasks/TASK-rectification-family-collect-continue-fix-20260905.md
T

65 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TASK · 家人拒答后继续采集(BUG-546)的修复单:补采集不得挤掉现成的区分题(2026-09-05)
- 基线:`origin/staging` @ `998406ce`(BUG-546 实现)
- 分支:`codex/rectification-family-collect-continue-fix-20260905`
- 验收方:Claude;本单是对 `998406ce` 的验收结论,不是新需求
- BUG 编号起点:**BUG-547**(开工时 `grep -n "^## BUG-5" docs/BUG_HISTORY.md | tail -1` 复核;BUG-542 仍为 `TASK-api-not-configured-mislabel-20260904.md` 预留)
## 1. 验收实证
在 `998406ce` 上跑 `npx tsx --test tests/rectification-*.test.ts tests/agent-voice-copy-contract.test.ts`:894 项,**3 失败**;同一命令在前一提交 `329f8a21` 上 0 失败。进度记录列出的套件没有包含这两个文件。
| # | 文件 / 用例 | 期望 | 实际 | 定性 |
| --- | --- | --- | --- | --- |
| A | `rectification-choice-card.test.ts` · `distinguish follow-up copy forbids competing-chart ranking` | 学业/感情/事业/家人/职业/占问全覆盖、精度阶段 `d4_refine`、引擎给了一条搬家 A/B 探针(两候选分钟各一边、增益 0.4)→ 下一问是那张 **A/B 卡** | 下一问变成财务口述采集「可以先问有没有记得住时间的收入变化…」;探针既不在 `deferred_followup` 也不在 `dropped_probes` | **行为回归** |
| B | `rectification-occupation-coverage-exit.test.ts` · `career evidence alone still does not cover occupation` | 下一问 `occupation` | `d2_finance` | 顺序变更,与 BUG-546 决策一致,缺三栏断言说明 |
| C | 同文件 · `training gate open does not mint yearless existence or quality varga cards` | 下一问 `occupation` | `d2_finance` | 同 B |
A 的复现路径不只在测试里:`app/api/rectification/agent/route.ts` 在 `decision.nextAction === "ask_candidate_discriminator"` 时调 `buildMethodFollowupPlan` 并把 `plan.next_followup` 写成焦点;现在只要财务 / 搬家 / 健康任一域未覆盖、未拒答,写下去的就是口述采集而不是区分卡,`isRenderableChoiceOpenQuestion` 为假,后续按口述路径走。
## 2. 根因
`method-followup.ts::buildMethodFollowupPlan` 的 `if (!next)` 链里,家人之后的分支从
`!meetsAcceptanceEventQuality(evidence) && nextDatedCollectFollowup(...)` 改成了无条件 `nextDatedCollectFollowup(...)`。这条分支排在 `d4_refine` 搬家 A/B 卡(同函数约 L2107)与其后所有 yearless / 精度层卡之前,所以只要 `DATED_COLLECT_ORDER` 里还有未覆盖域,现成的区分探针永远轮不到。
BUG-546 自己写的触发条件是"剩余区分探针被标成 `no_split_among_active`"——也就是**没有**可用区分题的时候。实现把它扩成了"不管有没有区分题都先采集"。
## 3. 决策记录
1. BUG-546 的产品意图保留:家人答「没有」而候选分钟仍分得开时,不得直接给结果,要继续收未问过的带年份域(学业 → 财务 → 搬家 → 健康)。
2. **但现成的区分题优先于口述补采集**。引擎已经算出哪一问能把剩余分钟分开,就先问它;只有当本轮没有任何可渲染的区分卡(`yearlessDiscriminators` 与精度层 / 搬家 A/B 卡都拿不出 `choice_frame`)时,才走 dated 补采集。这与 `Relocation stays out of domain rotation and is only asked at d4_refine` 的原始设计一致,也与 BUG-546 自述的触发条件一致。
3. `isRemainingEvidenceCollect` 对 `deferAdoption` / `shouldSkipFollowupPersist` 的豁免保留(否则采集写不进焦点,又回到 BUG-546)。
4. B、C 两条断言允许改为 `d2_finance`,但必须在进度记录写"原值 / 新值 / 原因"。A 不允许改断言。
## 4. 硬红线
- 不动 `DATED_COLLECT_ORDER`、`exhaustionSpokenCollectFollowup`(BUG-520 口径)。
- 不放宽 `meetsAcceptanceEventQuality` 与精确分钟确认门。
- `accepted` 早退路径(采用后只走 `remainingReverseVerifyProbes`)不得受影响;BUG-350 / 463 / 499 / 502 / 518 / 519 / 536–539 / 544 的测试原样通过。
- 已在 `998406ce` 里改过的断言(`collect-stall`、`adopt-narration`、`provisional-adopt`、`eight-method`、`range-offer-deadend`、`collect-direction`)不得再改回去,除非同样写三栏说明。
## 5. 任务分解
### 5.1 补采集让位于区分题
- 把家人之后的 dated 补采集改成"无可渲染区分卡时才取":最直接的做法是把该 `else if` 移到(或复制到)`d4_refine` 搬家卡与 yearless 卡分支之后、`!occupationCovered` 之前,且仍在 `if (!next)` 链内;或在分支条件里加"本轮 ranked / precision 探针都拿不出 `choice_frame`"的判定。两种取一,进度记录说明为何。
- 验收:`rectification-choice-card.test.ts` A 用例原样通过;新增用例——同样证据集但 **没有** 探针时,下一问是财务采集(证明 BUG-546 意图仍在)。
### 5.2 断言三栏说明
- `rectification-occupation-coverage-exit.test.ts` B、C 改为 `d2_finance`,三栏写进 `PROGRESS-rectification-family-collect-continue-20260905.md`(追加一节,不新开进度文件)。
### 5.3 记录
- `docs/BUG_HISTORY.md`:BUG-546 追加"复发/修正"段并新增 BUG-547(现成区分题被口述采集挤掉),关联 BUG-546、BUG-519。
- `CHANGELOG.md` 一条。
## 6. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/rectification-family-collect-continue-fix-20260905 .worktrees/rectification-family-collect-continue-fix-20260905 origin/staging
cd .worktrees/rectification-family-collect-continue-fix-20260905
ln -s /workspace/Jyotisha/frontend/node_modules frontend/node_modules
cd frontend && npx tsx --test tests/rectification-*.test.ts tests/agent-voice-copy-contract.test.ts 2>&1 | grep -E "^# (tests|pass|fail)|^not ok"
```
收尾必须跑同一条命令并达到 fail=0,再 `tsc --noEmit`、`npm run lint`。