产品追问:事件题答「没有」不应连带关掉风格题。核实后 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
156 lines
13 KiB
Markdown
156 lines
13 KiB
Markdown
# 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:1399(requestTieBreak 内)
|
||
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)。
|