fix(rectification): restore targeted collect cards from spoken focus (BUG-673)
Independent Staging Quality Gate / validate (push) Successful in 10m39s
Independent Staging Quality Gate / publish (push) Successful in 2m9s

Keep targeted existence questions as A-D cards. Recover collect-schema
stock by question-id prefix, surface the stem when persist fails, and
send spoken targeted existence to the repair exit instead of a naked prompt.
This commit is contained in:
jesse-ux
2026-09-14 01:51:55 +08:00
parent 9a943cc2dc
commit 8221c6121b
17 changed files with 673 additions and 38 deletions
+16
View File
@@ -10468,3 +10468,19 @@
- 相关记录:BUG-590、BUG-626、BUG-586、BUG-641
- 复发自:BUG-590 决策 4(occupied 已归并,其余站点未归并)
- 修复版本:待发布
## BUG-673 | 定向补事存在题被存成口述焦点,裸题顶掉卡片
- 状态:resolved
- 首次发现:2026-09-13
- 最近更新:2026-09-13
- 影响面:`serverOwnedExpectedAnswerSchema``persistServerOwnedFocusCore``persistSkippedCollectFocus``rectification-set-focus``buildMethodFollowupPlan` 承接焦点、`projectCurrentQuestion``interviewChoiceCardUnavailable`
- 用户现象:答完带年月题后出现一行没有头像、没有 A/B/C/D 的粗体裸题(如「家里添过丁或长辈住过院吗?」),无法点选;本轮计划的 D9 关系题消失。
- 触发条件:定向存在题以采集型 schema(`collect: true``collect_kind: targeted:*`)落进活动焦点;`choice.applied``nextInterviewPersisted=true` 让前端不再追一轮。
- 根因:写入侧在 `expectedAnswerSchemaFor` 没产出 `.choice` 时把采集意图降成口述 schema;复原侧只认 `targeted_collect === true` 章,拦不住采集型 schema。BUG-670 的识别条件覆盖不到这条不经模型的路径。
- 修复:定向存在题禁止降级成采集型 schema,重建不出 frame 就不写焦点。承接焦点与 GET 投影按题号前缀识别口述定向存在题并重建四点选。焦点落库失败时 `persistNextInterviewAfterChoice` 显式 `persisted: false`,题干进本轮旁白。`persistSkippedCollectFocus` resolve 失败重试一次,不得留下 `status=active`。前端把口述形态的定向存在题当缺卡,走 repair-exit。年份阶段 `collect:targeted:<domain>:year` 仍是口述。
- 验证:`frontend/tests/rectification-targeted-spoken-focus-recovery-20260913.test.ts``rectification-targeted-card-live-20260913.test.ts``rectification-surface-state.test.ts` 补口述定向存在题。
- 防复发:定向补事存在题的焦点 schema 只允许点选形态;识别定向存在题以题号前缀为准,不得只认 `targeted_collect` 字段。不得把 `persisted_question` 块画成卡片来绕过数据层。
- 相关记录:BUG-670、BUG-669、BUG-671、BUG-661
- 复发自:BUG-670
- 修复版本:待发布
@@ -0,0 +1,30 @@
# 进度 · 定向补事口述焦点复原(2026-09-13)
## 范围
- 分支:`codex/rectification-targeted-collect-spoken-focus-20260913`(基于 `origin/staging` @ `9a943cc2`
- 任务单:`docs/tasks/TASK-rectification-targeted-collect-spoken-focus-20260913.md`
- BUG-673(复发自 BUG-670);最大号核对时为 672
- 不改数据库、迁移、`deploy/**`、workflow、`page.tsx`
## 完成
- T1 写入侧:`serverOwnedExpectedAnswerSchema` / `persistServerOwnedFocusCore` 对定向存在题先 `rebuildTargetedCollectExistenceFollowup`;重建失败返回 null / skipped,不得 `collectFocusSchema``rectification-set-focus` 同一条件不降级,spokenPrompt 不替换卡片题干。年份阶段 `collect:targeted:<domain>:year` 仍是口述。
- T2 复原侧:承接焦点与 GET `choice_card` 按题号前缀识别采集型 schema,用 `schema.prompt` 重建 frame。`projectCurrentQuestion` 同条件投影 `kind: "choice"``:next` 后缀同样能复原。
- T3 `persistNextInterviewAfterChoice` 尾部显式 `persisted: false``keptNextQuestion` 为假时 `next_user_action` 不再引用未落库的题。`persistSkippedCollectFocus` 对定向存在题写点选 schema,resolve 失败重试一次,返回值不得为 `active`
- T4 `interviewChoiceCardUnavailable` 增加 `questionId`:口述形态的定向存在题走 unavailable + repair-exit;普通口述与 year 阶段不误伤。
- T5 BUG-673、CHANGELOG、本文件、`docs/testing/rectification-targeted-collect-spoken-focus-20260913.md`
## 让步
- 任务书 T4 写「questionId 以 `collect:targeted:` 开头」一律判不可用。年份追问 `collect:targeted:<domain>:year` 本来就是口述,若按字面会误伤。实现只把存在题(可带 `:next`)当缺卡。
## 验收
- `tsc --noEmit`0 错
- ESLint(改动文件):0 error;既有 unused-vars warning 未新增
- 新测试 `rectification-targeted-spoken-focus-recovery-20260913.test.ts`10/10
- 相关回归:`rectification-server-focus` / `question-ownership` / `answer-choice` / `spoken-prompt` 69/69`targeted-card-live` + `surface-state` 通过
- 本机 `npm test`2948 tests2775 pass / 159 fail / 14 skip。失败项是 Windows CRLF、无 Docker、bash 脚本合同(Caddy `\n` vs `\r\n`、deploy/*.sh、database-*),与本单无关。新增测试只增加通过数。
- `next build`Compile + TypeScript 通过;collect page data 在本机 Windows 因 `EPERM symlink` 与 Skill 10.0.26 SHA 校验失败(未改 `skills/`)。`/` 是否仍 `○ Static` 未在本机核对。
- 真机存量会话复验见 `docs/testing/rectification-targeted-collect-spoken-focus-20260913.md`
+1 -1
View File
@@ -184,7 +184,7 @@
| `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-targeted-collect-spoken-focus-20260913.md` | `PROGRESS-rectification-targeted-collect-spoken-focus-20260913.md` | **P0**:定向补事题以采集型 schema 存进焦点,前端只能裸画一行题干(无头像无卡无修复入口),本轮计划的 D9 题被静默吞掉;BUG-670 的识别条件只认 `targeted_collect` 章,复原不了(BUG-673,复发自 BUG-670 | 待执行 | `codex/rectification-targeted-collect-spoken-focus-20260913` |
| `TASK-rectification-targeted-collect-spoken-focus-20260913.md` | `PROGRESS-rectification-targeted-collect-spoken-focus-20260913.md` | **P0**:定向补事题以采集型 schema 存进焦点,前端只能裸画一行题干(无头像无卡无修复入口),本轮计划的 D9 题被静默吞掉;BUG-670 的识别条件只认 `targeted_collect` 章,复原不了(BUG-673,复发自 BUG-670 | 待验收 | `codex/rectification-targeted-collect-spoken-focus-20260913` |
| `TASK-rectification-house-lord-gochara-research-20260913.md` | `PROGRESS-rectification-house-lord-gochara-research-20260913.md` | 研究单:宫主触发与木星/土星过运(合冲本命宫主、罗睺紧密合、年精度、用于 block 选上升)四种放宽,20 例公开 AA 离线量 block 层与 minute 层两组指标;引擎里已有宫主/功能吉凶/受控过运,只量缺的四条 | 待验收(无收益,关闭;不立实现单) | `codex/rectification-house-lord-gochara-research-20260913` |
@@ -0,0 +1,19 @@
# 定向补事口述焦点复原:真机清单(2026-09-13)
分支 `codex/rectification-targeted-collect-spoken-focus-20260913`,任务书 `docs/tasks/TASK-rectification-targeted-collect-spoken-focus-20260913.md`
本环境无 staging 登录态与该会话数据库/日志,**线上那条存量家庭焦点是否已复原成卡片只能由产品负责人在真机复验**。自动化锁的是写入、承接、投影与缺卡修复入口。
## 存量会话
进入当时那个校正会话,刷新页面。
- [ ] 「家里添过丁或长辈住过院吗?」以四选一卡出现(有过这件事 / 没有发生过 / 记不太清楚 / 这条先跳过),不再是没有头像、没有选项的裸题。
- [ ] 若仍没有卡,应出现「接着问」修复入口,而不是停在「再说一件带年月的事就能继续」。
## 新路径
再走一遍「答完带年月题 → 定向补事」。
- [ ] 下一问是点选卡,不是口述裸题。
- [ ] 点 C「明确没有发生」后,下一问(含 D9)要么是可点卡,要么题干出现在本轮旁白里,不会整题消失。