Files
Jyotisha/docs/tasks/TASK-rectification-targeted-card-dead-20260913.md
T

67 lines
6.5 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 · 定向补事卡刷新后点不动(P02026-09-13
- 基线:`origin/staging` @ `ab1ade59`(已部署)
- 分支:`codex/rectification-targeted-card-dead-20260913`,基于 `origin/staging`
- 执行方:coding agent;验收:Claude
- BUG 编号起点:**BUG-669**(当前最大号 665666668 已被 `TASK-rectification-tie-break-entry-fix-20260913.md` 占用)
- 串行:**本单先做**`TASK-rectification-tie-break-entry-fix-20260913.md` 排在其后(两单都改 `projectRectificationChoiceCard` 相邻逻辑)
- 上游:`TASK-rectification-targeted-collect-cards-20260913.md`BUG-661663`530f260f`)引入的新形态
## 1. 事故实证(2026-09-13 真机,`ab1ade59`
用户六道带年月题答完后:
1. 先冒出一道「和页面上其它题 UI 都不一样」的问题,回答后问题消失;
2. 接着出现 `记下了,这方面先跳过。` + `现在还剩 04:51–05:06 里 5 个候选,能把它们分开的是这几条线:…` + 定向卡「收入明显变过或有过大笔进出吗?A/B/C/D」;
3. 这张卡**点不动**,时间轴显示「目前范围 04:48–05:07,再说一件带年月的事就能继续」,流程停住。搬家、添丁两条线再也没被问。
4. 2026-09-13 产品负责人复测:**刷新页面后选项依旧是灰的**——不是渲染时序,是快照投影本身拿不到卡。
## 2. 根因(已用脚本复现,非推测)
`buildMethodFollowupPlan` 里的「承接当前焦点」分支(`method-followup.ts``method_id: "active_focus"` 那段)对 `intent = collect_method_evidence` 的活动焦点重建的 followup **没有 `choice_frame`**——该分支只为 `reverse_verify` / `out_of_sample_check` / `distinguish_candidates` 重建点选。定向补事的存在题是**史上第一个「采集焦点 + 点选卡」**的组合,正好落进这个洞。
于是:
- `projectRectificationChoiceCard` 走到 `if (!frame) return persistedVerifyCard()`,而 `persistedVerifyCard()` 只认 `reverse_verify` / `out_of_sample_check`,返回 `null` → GET 的 `choice_card` 为空。
- `projectCurrentQuestion` 仍按已持久化 schema 给出 `kind: "choice"``current_question` → 前端 `liveQuestion` 要求 `choiceCard.focus_id === question.focus_id`,拿不到卡 → `RectificationChoiceCard``disabled` 渲染。**卡看得见、点不动**,与用户描述一致。
- 第一次能答,是因为 POST 应答里带着刚落库的焦点直接渲染;一旦页面重新拉快照(轮询/刷新/再进一次会话),卡就死了。
- 同一分支还要求模型「用 spokenPrompt 自己写题干」,这就是第 1 步里「UI 不一样的那道题」——模型把定向题重写成了口述题。
复现(`tsx` 直接调用,`ab1ade59`):活动焦点 = `collect:targeted:relocation`schema 为服务端四点选、`targeted_collect: true`)时,`plan.next_followup` 返回 `{"method_id":"active_focus", … "choice_frame":null}``projectRectificationChoiceCard` 返回 `null`;换成 `:next` 后缀或换成别的线,同样 `null`
## 3. 硬红线
- 卡片文案仍是服务端自有(`serverOwnedChoiceCopy`),模型不得改写定向题题干与选项。
- 不得放宽区分题(`distinguish_candidates`)的身份校验:`semantic_key` / `candidate_split_hash` 全等判定保持不变(BUG-559 / BUG-581 防复发)。
- 不改 `SCORE_DELTA`、确认门;定向存在题仍 `scoring: false`
- 采集焦点撞号仍可落 `:next`BUG-654),因此投影不得再用「`questionId` 与计划层 frame 全等」做定向卡的唯一身份判据。
## 4. 任务分解
- **T1(BUG-669)投影按已持久化文案出卡**:`projectRectificationChoiceCard` 增加一条与 `persistedVerifyCard()` 平行的路径——活动焦点 schema 满足「`targeted_collect === true` 且能 `parseAgentChoiceCopy` 出四点选」时,直接按持久化文案投影 `choice_card``question_id` 用焦点的、`focus_id` 用焦点的、`scoring: false``stop_label` 用「这题跳过」),不依赖计划层重建 frame,也不做 `questionId` 全等比较(`:next` 后缀必须照样出卡)。
验收:GET 快照在「定向存在题为活动焦点」时 `choice_card.focus_id === current_question.focus_id`、四个选项、`scoring:false``collect:targeted:finance:next` 同样出卡。
- **T2(BUG-670)承接分支别让模型改写定向题**:`buildMethodFollowupPlan` 的承接焦点分支,识别 `targeted_collect` schema 时重建 `choice_frame``buildTargetedCollectExistenceFrame` + 持久化文案),`user_prompt_hint` 改成「照发服务端卡片,不要自己写题干」。
验收:活动焦点为定向存在题时 `plan.next_followup.choice_frame` 非空且 `question_id` 等于焦点题号;不再出现模型自写的口述版定向题。
- **T3BUG-671)死角要能自救**`current_question``choice``choice_card` 拿不到时,前端不得静默停在采集等待态——进入 `unavailable` 分支给出修复按钮(现有 `repair-exit` 路径),或由服务端重发焦点。
验收:人为让 `choice_card` 为空时,界面出现可点的修复入口,不是一条「再说一件带年月的事就能继续」。
- **T4 回归与记录**:新增 `frontend/tests/rectification-targeted-card-live-20260913.test.ts` 锁 T1/T2(含 `:next`);BUG-669671 入历史(关联 BUG-661、BUG-654、BUG-591、reverse_verify 投影那条);`docs/testing/rectification-scenarios-20260907.md` 场景 0d 加:**答完一张定向卡后刷新页面,卡片仍可点**、**整轮不得出现看得见点不动的卡**。
## 5. 让步顺序
T1 不可省(没有它流程仍然死)。T2 次之(不做会继续出现模型自写的口述定向题)。T3 可拆下一单。
## 6. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/rectification-targeted-card-dead-20260913 .worktrees/rectification-targeted-card-dead-20260913 origin/staging
grep -o "^## BUG-[0-9]*" docs/BUG_HISTORY.md | sort -t- -k2 -n | tail -1 # 应为 665
cd frontend && npm test -- tests/rectification-targeted-collect-cards-20260913.test.ts tests/rectification-question-ownership.test.ts tests/rectification-v9-contracts.test.ts
```
## 7. 验收口径
- `tsc --noEmit` 0 错;`npm run lint` 0 error;相关套件 fail=0;测试总数 ≥ `ab1ade59` 实测 3139(其中 27 项为无 Docker 的数据库/部署套件)。
- `next build``/``○ Static`;首屏 `rootMainFiles` gzip-9 与 `ab1ade59` 的 130872 B 相差 ±2% 内。
- 部署后真机按场景 0d 走一遍,含刷新页面后继续答。