产品追问:事件题答「没有」不应连带关掉风格题。核实后 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
13 KiB
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 响应:
{ "ok": true, "choiceReady": true, "hostNarration": "只微调排序,不改目前范围。", "focusId": "…" }
服务端成功了:参考题焦点已创建,确定性 turn 也写了。问题在前端:
// frontend/src/components/rectification-agentic-chat.tsx:1399(requestTieBreak 内)
await loadCaseSnapshot(); // ← 没有传合并回调
// :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)
卡上「能把它们分开的是这几条线:哪年结婚或订婚、哪年收入明显变过、家里哪年添丁」与「还能再收窄:如果记得哪年结婚或订婚、哪年收入明显变过」——这三条用户在前面全部答过「没有/跳过」。根因是文案故意忽略拒答:
// 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 的既有行为);两道答完(或参考题不可用)后再走交付,仍平局时在卡上说明「这两分钟按现有信息分不开,参考题已经用过」。 产品原话背景:用户在真机上认为「你平时做事」「感情里你倾向」这类题从没被问就出了卡,观感是没问完。本决策只改问的时机,不改性格题的权重。 |
| 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. 硬红线
tsc --noEmit0 错;npm run lint0 error;npm test失败清单与基线逐条一致;next build通过且/仍○ Static;首屏 gzip ±2%。- 新增断言必须是行为断言。
- 不得回退 BUG-680~684 的修复;不得放宽
can_adopt/ 置信度边界。 - 参考题自动进入时,不得产生第二条交付消息(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——必须有地方渲染这道题。
- 行为单测:模拟 tie-break POST 返回
任务 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。
- 回归:不得产生两条交付消息。
- 行为单测:前两名 16 / 16、参考题可用、未用过 → 决策不是交付,
任务 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 必做(现在点按钮等于什么都没发生,还留下看不见的活动焦点)。
- 任务 2 必做(产品已拍板 A)。
- 任务 3 必做(文案误导直接引发"没问就出卡"的判断)。
- 任务 4 可延后,但要写进进度记录。
7. 开工前置命令
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)。