Files
Jyotisha/docs/tasks/TASK-rectification-probe-answer-covers-domain-20260905.md
T

69 lines
5.6 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 · 刚在区分卡上答过"是",紧接着又被问同一领域的采集题(2026-09-05)
- 基线:`origin/staging` @ `c295b853`(含 BUG-546/547
- 分支:`codex/rectification-probe-answer-covers-domain-20260905`
- 执行方:coding agent;验收:Claude
- 涉及文件:`frontend/src/lib/rectification-agentic/v9/method-followup.ts``decision-from-dossier.ts`(把已答探针透传给计划层);不改引擎
- BUG 编号起点:**BUG-549**(开工时 `grep -o "^## BUG-5[0-9][0-9]" docs/BUG_HISTORY.md | tail -1` 复核;BUG-542 仍为 `TASK-api-not-configured-mislabel-20260904.md` 预留)
## 1. 事故实证(staging2026-09-05
用户连续三轮:
| 轮 | 助手问 | 用户 |
| --- | --- | --- |
| 1 | 区分卡「2024 年 4 月前后,有没有入职、换工作或职责加重?A/B/C/D」 | 点选 |
| 2 | 区分卡「2015 年 5 月前后,有没有搬家或长期住到外地?A/B/C/D」 | 点选 |
| 3 | 口述采集「工作上呢,还记得哪年入职、换工作,或职责一下子变重吗?」(`USER_COLLECT_QUESTION.career` 原文) | 反馈"相同的问题又问了一遍" |
第 1 轮如果点的是 A/B(发生了),用户已经交代了一件 2024 年 4 月的工作变化;第 3 轮再让他"说哪年入职、换工作",在用户眼里就是同一道题。
## 2. 根因
1. 区分卡的点选答案只进推断层(`applyChoiceWithoutEvidence``inference_state.answered_probes``classified_from: "choice"`),**不写证据账本**。这是既定设计(BUG-389–393:探针与账本分层,不双计分),本单不推翻。
2. 计划层判断"某领域问过没有"只看账本:`method-followup.ts::hasConfirmedDomain` 驱动 `relationshipCovered / careerCovered / familyCovered`(约 L15631565)和 `datedCollectDomainBlocked``DATED_COLLECT_ORDER` 补采集)。已答探针只以 `askedProbeKeys`(字符串集合)进入计划层,用于探针去重,**不参与领域覆盖判断**,且不带 `answer_class`
3. 区分卡在场时 `if (!next)` 采集链不跑;BUG-546/547 之后区分卡问完才进采集链,于是"刚答完的领域马上被再问一次"从偶发变成必现。
## 3. 决策记录
1. **对探针答 A/B`yes` / `weak_yes`)的领域,视为该领域采集已覆盖**`careerCovered` / `relationshipCovered` / `familyCovered``datedCollectDomainBlocked` 都要把它算进去。不写账本、不改 `meetsAcceptanceEventQuality`、不动训练门与确认门。
2. 答 C/D`no` / `unsure`)不算覆盖:用户说那年没发生,仍可能有别的年份,采集题是新信息。此项产品可否决——若觉得连 C/D 后紧跟同领域采集也别扭,改为"同领域采集至少隔一轮",在进度记录写明选了哪个。
3. 领域从探针的 `domain` 字段取;`answered_probes` 行只有 `semantic_key`,执行方用 `eventProbes``semantic_key` / `probe_id` 回查 domain,回查不到的行忽略(不要从 `semantic_key` 前缀硬拆字符串)。
4. 不删 `USER_COLLECT_QUESTION.career` 这类文案,不新增"除了刚才那次以外"的变体文案。
## 4. 硬红线
- 不得把点选答案写进证据账本(BUG-389–393 分层);不得放宽 `meetsAcceptanceEventQuality``buildConfirmationGate`
- BUG-546(无区分卡时继续补采集)与 BUG-547(有卡先问卡)的用例原样通过。
- BUG-520:区分卡答"否"不是领域拒答,`declinedDomains` 不改。
- 任务书 / 进度 / Bug 历史只用抽象年份。
## 5. 任务分解
### 5.1 已答探针透传到计划层
- `buildMethodFollowupPlan` 新增可选入参 `answeredProbes?: readonly { semantic_key: string; probe_id?: string; answer_class: string }[]`,由 `decision-from-dossier.ts` 现有的 `askedProbeKeys` 同一来源(`inference_state.answered_probes`)填充;`adopt-narration.ts``interview-state.ts``answer-choice.ts``route.ts` 的调用点同样透传(缺省为空数组,行为不变)。
- 验收:`tsc` 0 错;不传时所有既有用例结果不变。
### 5.2 覆盖判定叠加
- 新增 `domainsAnsweredYes(answeredProbes, eventProbes): Set<string>``relationshipCovered / careerCovered / familyCovered``datedCollectDomainBlocked``hasConfirmedDomain(...) || answeredYes.has(domain)`
- 验收:`frontend/tests/rectification-choice-card.test.ts``rectification-collect-direction-20260904.test.ts` 新增用例——账本无 career 证据、`answered_probes` 含 career 探针 `yes`、无剩余区分卡 → 下一问**不是** career 采集(按 `DATED_COLLECT_ORDER` 落到下一未覆盖域或职业口述);同样输入但 `answer_class: "no"` → 仍问 career 采集(决策 2)。
### 5.3 记录
- `docs/BUG_HISTORY.md` BUG-549`CHANGELOG.md``docs/tasks/PROGRESS-rectification-probe-answer-covers-domain-20260905.md``docs/testing/rectification-probe-answer-covers-domain-20260905.md`(真实环境:对某领域区分卡点 A 后,该领域的"哪年…"采集题不再出现)。
## 6. 让步顺序
5.1 + 5.2 一起做,不可拆;5.3 不可省。
## 7. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/rectification-probe-answer-covers-domain-20260905 .worktrees/rectification-probe-answer-covers-domain-20260905 origin/staging
cd .worktrees/rectification-probe-answer-covers-domain-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`