docs(tasks): tie-break before the range card, and make the entry actually respond

参考题 POST 实际成功(ok/choiceReady/focusId),但 requestTieBreak 调的是不带
合并回调的 loadCaseSnapshot(),新助手 turn 不进 messages,题也就没有渲染位置
(BUG-685)。产品拍板方案 A:前两名 posterior 分差 ≤1 时先问两道参考题再出
交付卡,卡上收起按钮(BUG-686)。rangeNarrowHint 无视 declinedTopics,把用户
刚答过「没有/跳过」的线又列一遍(BUG-687)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
This commit is contained in:
Jesse_Chen
2026-09-14 09:49:54 +00:00
co-authored by Claude Fable 5
parent 9da42c99d2
commit a6381e029b
2 changed files with 150 additions and 0 deletions
+2
View File
@@ -184,6 +184,8 @@
| `TASK-rectification-targeted-card-dead-20260913.md` | `PROGRESS-rectification-targeted-card-dead-20260913.md` | **P0**:定向补事卡在快照投影里拿不到 `choice_card`(承接焦点分支不重建 `choice_frame`),卡片看得见点不动、流程停在采集等待态;模型还会把定向题改写成口述题(BUG-669~671)。先于 tie-break 修复单执行 | 待验收 | `codex/rectification-targeted-card-dead-20260913` |
| `TASK-rectification-tiebreak-before-card-20260914.md` | `PROGRESS-rectification-tiebreak-before-card-20260914.md` | **P0**:点「再答两道参考题」服务端 ok 但界面无反应(`requestTieBreak` 的 `loadCaseSnapshot()` 不带合并回调,新 turn 不入对话区)(BUG-685);产品拍板 A——前两名分差 ≤1 时先问参考题再出卡,卡上收起按钮(BUG-686);交付文案列出用户已拒答的线(BUG-687) | 待执行 | `codex/rectification-tiebreak-before-card-20260914` |
| `TASK-rectification-tied-first-premature-delivery-fix-20260914.md` | `PROGRESS-rectification-tied-first-fix-20260914.md` | **P0 回归修复单**BUG-680 的 `tied_first` 早退被实现到 `coverageBlocks` 之前且无 `probe` 守卫 → 新案子答两题、区间还是整个开局窗口就宣布 `can_adopt`/代表分钟(BUG-683);交付态下仍出现死卡致 `delivered` 终态不触发、印「没有拿到下一个问题」(BUG-684 investigating | 待验收 | `codex/rectification-tied-first-fix-20260914` |
| `TASK-rectification-delivery-vs-collect-split-20260914.md` | `PROGRESS-rectification-delivery-vs-collect-20260914.md` | **P0**:并列到顶(tied_first)时 POST 播了交付结论、GET 又算回 collect_evidence——刷新尝试落库失败仍回报「已尝试」+ `stillNeedNarrowing` 压过 exhaustedBUG-680);交付话术闸门与交付卡闸门不一致,`completed_with_range`/`provisional_range` 能说不能画(BUG-681);缺口状态机没有终态,兜底印「没有拿到下一个问题」(BUG-682) | 待验收 | `codex/rectification-delivery-vs-collect-20260914` |
@@ -0,0 +1,148 @@
# TASK · 平局先问参考题再出卡 + 参考题点了没反应 + 交付文案列出已拒答的线 — 2026-09-14
- 基线:`origin/staging` @ `9da42c99`staging 已部署该 SHA,含 BUG-683/684 修复)。
- 分支:`codex/rectification-tiebreak-before-card-20260914`worktree `.worktrees/rectification-tiebreak-before-card-20260914`
- 关联:BUG-663(卡下「再答两道参考题」入口)、BUG-666~668(入口与执行判据不同源)、BUG-680~684(交付线)、yearless probes 的产品决策(性格题只做平局裁决、±1、不淘汰)。
- 串行:改 `rectification-agentic-chat.tsx``answer-choice.ts`/决策层一处、`collection-question-pool.ts` 文案一处。
## 1. 事故实证(产品负责人 staging 真机,2026-09-14,部署 SHA `9da42c99`
交付卡内容(节选):
```
目前范围 04:48–05:07(对照了 5 件经历)
现在还剩 04:48–05:07 里 5 个候选,能把它们分开的是这几条线:哪年结婚或订婚、哪年收入明显变过、家里哪年添丁。
还能再收窄:如果记得哪年结婚或订婚、哪年收入明显变过
[再答两道参考题微调排序]
04:53 相对可能性 26% 05:00 相对可能性 26% 05:06 相对可能性 20%
```
同一会话 `last_inference_round`(第 6 轮后):`scores_after` 04:53 = 16、05:00 = 16、05:06 = 15、04:51 = 14、04:59 = 13`eliminated_ids` = 05:13 / 05:08 / 04:47 / 05:15。**前两名完全并列。**
### P0-1 · 点「再答两道参考题微调排序」没有任何反应(BUG-685)
产品负责人抓到的 POST 响应:
```json
{ "ok": true, "choiceReady": true, "hostNarration": "只微调排序,不改目前范围。", "focusId": "…" }
```
**服务端成功了**:参考题焦点已创建,确定性 turn 也写了。问题在前端:
```ts
// frontend/src/components/rectification-agentic-chat.tsx:1399requestTieBreak 内)
await loadCaseSnapshot(); // ← 没有传合并回调
```
```ts
// :686 loadCaseSnapshot(mergeMessages?) —— 不传回调时只 applyCaseSnapshot(payload)
// turns 拿到了却不并进 messages
```
对比 `submitChoice`:1017 / :1028 / :1185)都传了 `(turns) => { mergeTurnQuestions / appendUnseenAssistantTurns }`。所以参考题那条新助手消息「只微调排序,不改目前范围。」**没有进入对话区**,挂在它上面的参考题自然也没有渲染位置。
同时交付卡还在(`showSelectionCards` 为真)→ `offerAwaitingReader` 为真 → 缺口状态是 `idle``persisted_question` 分支也不会兜底画这道题。于是屏幕上什么都没变,但**会话里已经多了一个看不见的活动焦点**。
### P0-2 · 平局就出卡,让用户在 26% / 26% / 20% 里蒙(BUG-686
带年月的判别题已耗尽;定向补事四条线里结婚、收入、家人都被用户答「没有发生过/这条先跳过」,只剩搬家,答完即交付。此时前两名 posterior 完全相等(16 / 16)。
现有设计把参考题(性格题,按既有产品决策只做 ±1 平局裁决、不淘汰候选)放成**出卡之后的可选按钮**——最需要它的时刻(平局)反而要用户自己想起来去点。产品负责人 2026-09-14 拍板改为方案 A。
### P1 · 交付文案把用户刚拒答过的线又列一遍(BUG-687)
卡上「能把它们分开的是这几条线:哪年结婚或订婚、哪年收入明显变过、家里哪年添丁」与「还能再收窄:如果记得哪年结婚或订婚、哪年收入明显变过」——这三条用户在前面全部答过「没有/跳过」。根因是文案故意忽略拒答:
```ts
// frontend/src/lib/rectification-agentic/v9/collection-question-pool.ts rangeNarrowHint
const open = targetedCollectPool(remainingLayers, evidence, [], splitTimes, candidateCount);
// ↑ 空数组,无视 declinedTopics
// 注释:Card copy ignores a declined targeted collect so the delivered range still says what would narrow it
```
用户读到的是"这些都没问就出卡了"。
## 2. 根因
- BUG-685`requestTieBreak` 用不带合并回调的 `loadCaseSnapshot()`,新 turn 不入 `messages`;叠加交付卡在场使缺口为 `idle`,新题没有任何渲染位置。
- BUG-686:平局裁决被设计成出卡后的可选入口,而不是出卡前的必经步骤。
- BUG-687:交付文案有意忽略拒答,导致列出已经关闭的线。
## 3. 决策记录
| 决策 | 内容 |
| --- | --- |
| D1 | **产品拍板(2026-09-14):采用方案 A —— 平局时先问参考题,再出卡。** 判据:候选前两名 posterior 分差 ≤ 1(含完全并列)且参考题可用(`tieBreakPersonalityAvailable`)。满足时**不出交付卡**,先连着问参考题(最多两道,沿用 BUG-667 一次连出 D9+D10 的既有行为);两道答完后重新评估:仍平局才出交付卡,并在卡上说明「这两分钟按现有信息分不开,参考题已经用过」。 |
| D2 | **参考题用过之后,卡上不再显示「再答两道参考题微调排序」按钮**;未用过且仍可用时(例如用户中途停止)保留按钮,但点击必须有可见结果(见 D3)。 |
| D3 | **任何会产生新助手 turn 的前端动作,都必须把新 turn 并进对话区。** `requestTieBreak` 改用带合并回调的 `loadCaseSnapshot((turns) => …)`,与 `submitChoice` 同一套 `mergeTurnQuestions` / `appendUnseenAssistantTurns`。另外:服务端 `ok: true` 而界面无变化,属于必须消除的状态——本单加一条守卫测试。 |
| D4 | **交付文案不得列出已拒答或已回答的线。** `rangeNarrowHint` 改为传入真实 `declinedTopics`;一条都不剩时改说「能问的都问完了」,不得再暗示还有没问的线。 |
| D5 | 入口与执行的判据必须同源:`case-dossier-response.ts` 计算 `tie_break_available` 时缺 `birthDate``followupCaseArgs(...)`,而 `requestTieBreakPersonality` 传了。本轮统一成同一个入参构造函数(本次事故没触发,但属同型隐患,BUG-666 复发风险)。 |
| D6 | 不动数据库结构与迁移、不动 `deploy/**` 与 workflow、不动 `page.tsx`、不新增依赖。参考题仍然**不淘汰候选**、只做 ±1 排序微调(既有产品决策不变);不得因为想把差距拉开而让性格题参与淘汰。 |
## 4. 硬红线
1. `tsc --noEmit` 0 错;`npm run lint` 0 error`npm test` 失败清单与基线逐条一致;`next build` 通过且 `/``○ Static`;首屏 gzip ±2%。
2. 新增断言必须是行为断言。
3. 不得回退 BUG-680~684 的修复;不得放宽 `can_adopt` / 置信度边界。
4. 参考题自动进入时,**不得**产生第二条交付消息(BUG-597 的两条交付消息守卫仍然有效)。
## 5. 任务分解
### 任务 1 · 参考题结果必须出现在对话里(BUG-685,P0)
- `requestTieBreak` 改为 `await loadCaseSnapshot((turns) => { setMessages((current) => appendUnseenAssistantTurns(mergeTurnQuestions(current, turns), turns)); })`
- 审一遍另外三处不带回调的 `loadCaseSnapshot()`:1347、:1393、:1625、:1653),凡是服务端可能新写 turn 的路径都要带回调;只读刷新的可以不带,在进度记录里逐处说明判断依据。
- 验收标准:
- 行为单测:模拟 tie-break POST 返回 `ok/choiceReady/focusId` 且快照多出一条助手 turn + 一道参考题 → 断言 `messages` 增加了该 turn,且该 turn 携带 question`mergeTurnQuestions` 生效)。
- 行为单测:交付卡在场(`showSelectionCards` 为真)且存在未答的活动焦点时,缺口状态不得是 `idle`——必须有地方渲染这道题。
### 任务 2 · 平局先问参考题再出卡(BUG-686,P0)
- 决策层:在交付分支之前加判断——`separation.lead <= 1 && tieBreakAvailable && !tieBreakRoundsUsed` 时,返回"问参考题"而不是交付(复用既有 `tieBreakPersonalityFollowup``continueTieBreakRound` 通路,不新造机制)。
- 两道答完(或参考题不再可用)后恢复既有交付路径;仍平局时交付卡文案加一句「这两分钟按现有信息分不开,参考题已经用过」。
- 卡上按钮按 D2 收起。
- 验收标准:
- 行为单测:前两名 16 / 16、参考题可用、未用过 → 决策不是交付,`next_followup.choice_kind === "varga_style"`
- 行为单测:同样分数、参考题已用过两道 → 交付,且 `tie_break_available === false`(按钮不显示)。
- 行为单测:前两名 16 / 14(lead = 2)→ 维持现有行为,不插参考题。
- 回归:不得产生两条交付消息。
### 任务 3 · 文案不列已关闭的线(BUG-687,P1)
- `rangeNarrowHint` 传入真实 `declinedTopics`;剩余为空时输出「能问的都问完了」类文案(对照 `frontend/docs/VOICE.md`)。
- 验收标准:行为单测——relationship / finance / family 均已 declined、只剩 relocation 已回答时,文案不得包含「结婚」「收入」「添丁」任何一条;全部关闭时输出收口文案。
### 任务 4 · 判据同源(D5,P2)
- 抽一个 `tieBreakGateInput(dossier, catalog, birthDate)``case-dossier-response.ts``requestTieBreakPersonality` 共用。
- 验收标准:行为单测——同一份 dossier 下,`tie_break_available``requestTieBreakPersonality``choiceReady` 必须一致(表驱动至少覆盖"可用"和"不可用"两种)。
### 任务 5 · 记录
- `docs/BUG_HISTORY.md`BUG-685、686、687 三条(686 记产品决策 A 与拍板日期);BUG-685 的防复发写明:**服务端返回 ok 而界面无变化,一律视为缺陷;任何新写 turn 的前端动作必须把 turn 并进对话区。**
- `CHANGELOG.md` 一行(用户可感知:平局时会先问两道参考题再给范围卡);Skill 文案若有改动写明是否 bump。
- `PROGRESS-rectification-tiebreak-before-card-20260914.md``docs/testing/` 清单:并列时先出两道参考题→再出卡;卡上不再有参考题按钮;卡上文案不再提已经答过的线。
## 6. 让步顺序
1. 任务 1 必做(现在点按钮等于什么都没发生,还留下看不见的活动焦点)。
2. 任务 2 必做(产品已拍板 A)。
3. 任务 3 必做(文案误导直接引发"没问就出卡"的判断)。
4. 任务 4 可延后,但要写进进度记录。
## 7. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/rectification-tiebreak-before-card-20260914 \
.worktrees/rectification-tiebreak-before-card-20260914 origin/staging
cd .worktrees/rectification-tiebreak-before-card-20260914
ln -s /workspace/Jyotisha/.venv .venv
cd frontend && npm ci
```
开工前检索 `docs/BUG_HISTORY.md`:「参考题」「tie break」「平局」「rangeNarrowHint」,至少读完 BUG-663、666、667、668、684 五条。
## 8. BUG 编号起点
- 起点 **BUG-685**(当前最大号 684)。