Files
Jyotisha/docs/tasks/TASK-rectification-tiebreak-before-card-20260914.md
T
Jesse_ChenandClaude Fable 5 1c424bf6d5 docs(tasks): drop the event-anchor gate for style probes, keep the sign-count gate
产品追问:事件题答「没有」不应连带关掉风格题。核实后 varga_style 的
unanchored_varga_style 丢弃分支(method-followup.ts:1261)确实没有道理——风格题
只看该分盘上升星座,不依赖事件。本单删除该分支。真正该留的是区分力门:候选在该
分盘上上升星座少于两种时探针本就不生成(candidate-contrast-packet.ts:610),本案
三个候选 D9 同为天蝎,所以感情风格题仍不出现属正确行为;D10 巨蟹/狮子应出现。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
2026-09-14 10:01:14 +00:00

156 lines
13 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-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):带年月的题问完、出交付卡之前,只要参考题可用且本轮没用过,就先问两道,再出卡。** 不再以「前两名分差 ≤ 1」为门槛——平不平局都问。满足条件时**不出交付卡**,先连着问参考题(最多两道,沿用 BUG-667 一次连出 D9+D10 的既有行为);两道答完(或参考题不可用)后再走交付,仍平局时在卡上说明「这两分钟按现有信息分不开,参考题已经用过」。<br>产品原话背景:用户在真机上认为「你平时做事」「感情里你倾向」这类题从没被问就出了卡,观感是没问完。本决策只改**问的时机**,不改性格题的权重。 |
| D1b | **性格题仍然不淘汰候选,只做 ±1 排序微调**2026-09-09 决策、BUG-629/651 防复发条维持)。不得为了把 26%/26% 拉开而让性格题参与淘汰。 |
| D1c | **推翻风格题的事件锚点闸(2026-09-14 产品追问后修正)。** 现状:`method-followup.ts:1261``choice_kind === "varga_style"` 要求该领域账本里有带年月事件作锚,否则丢弃(`unanchored_varga_style`)。这条对事件题成立、对风格题没有道理——风格题问的是倾向,评分只看该分盘的上升星座,不依赖事件是否发生过。产品实证:用户答「2023 年 5 月结过婚吗 → 没有」后,连「感情里你倾向什么」也不再出现,观感是漏问。**本单删除 `varga_style` 的锚点丢弃分支**(其余 choice_kind 不受影响)。 |
| D1d | **真正该保留的门是区分力,不是锚点。** 候选在该分盘上的上升星座少于两种时,探针本就不生成(`core/candidate-contrast-packet.ts:610` `if (signs.length < 2) return null;`)——本案三个候选 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)
- 决策层:在交付分支之前加判断——`tieBreakAvailable && !tieBreakRoundsUsed` 时(不看分差),返回"问参考题"而不是交付(复用既有 `tieBreakPersonalityFollowup``continueTieBreakRound` 通路,不新造机制)。
- `method-followup.ts:1261` 删除 `varga_style``unanchored_varga_style` 丢弃分支(按 D1c);`dropped` 里不再出现该原因,其余 choice_kind 的锚点逻辑原样保留。
- 两道答完(或参考题不再可用、可用不足两道)后恢复既有交付路径;仍平局时交付卡文案加一句「这两分钟按现有信息分不开,参考题已经用过」。
- 卡上按钮按 D2 收起。
- 验收标准:
- 行为单测:前两名 16 / 16、参考题可用、未用过 → 决策不是交付,`next_followup.choice_kind === "varga_style"`
- 行为单测:**前两名 16 / 14(lead = 2,不平局)、参考题可用且未用过 → 同样先问参考题,不出交付卡**(放宽版 A 的核心断言)。
- 行为单测:参考题已用过两道 → 交付,且 `tie_break_available === false`(按钮不显示)。
- 行为单测:该领域**没有**带年月事件但候选在该分盘上有两种以上上升星座 → 该道风格题**必须出现**(锚点闸已拆)。
- 行为单测:候选在该分盘上上升星座只有一种(本案 D9 全是天蝎)→ 该道风格题不出现,可用不足两道时只问可用的。
- 行为单测:性格题作答后候选**不得**被淘汰,排序变化不超过 ±1。
- 回归:不得产生两条交付消息。
### 任务 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/` 清单:出卡前先出两道风格参考题(含不平局的案子)→再出卡;某分盘上候选上升星座只有一种时该题不出现属正常(本案 D9 全是天蝎);感情线没有事件但星座有区别时该题必须出现;卡上不再有参考题按钮;卡上文案不再提已经答过的线。
## 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)。