fix(rectification): restore collect-phase exit and drop the consult handoff
Independent Staging Quality Gate / validate (push) Successful in 8m29s
Independent Staging Quality Gate / publish (push) Successful in 1m45s

Public can_adopt no longer starves the collect fallback, 改选 scrolls to
the offer, opening collect uses other, and probe_year stays on the
schema. The status bar no longer starts an empty consultation chat.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-03 10:41:36 +08:00
co-authored by Cursor
parent 15cf6d3bbc
commit e8c98c37cf
16 changed files with 578 additions and 103 deletions
+56 -24
View File
@@ -7653,15 +7653,15 @@
- 状态:resolved
- 首次发现:2026-09-02
- 最近更新:2026-09-02
- 影响面:`publicDecisionFields`、`POST .../candidates/accept`、`parseRectificationCandidateResult`、`rectification-agentic-chat`
- 用户现象:采集题还在问时,同一条助手消息下面出现三张「采用此时间」卡。
- 触发条件:`session_outcome=collect_evidence`,内部 `capability.canAdopt=true`,当前题是 `collect_spoken`。
- 根因:`collect()` 把 `canAdopt` 原样投影成公开 `can_adopt`。前端 `showSelectionCards` 只靠 `!showLiveChoiceCard`,采集题没有 A–D 卡,采用卡就露出来。v9 删掉 offer 门后,BUG-313 / BUG-323 的防复发条款失效。
- 修复:公开 `can_adopt` 只在 `adopt_representative` / `provisional_range_user_stopped` / `awaiting_confirmation` / `validated_range` 为真(后者是 holdout 已过、ready_to_adopt 的既有语义,不是新开口)。accept 在 `can_adopt=false` 时 409;前端再按 `session_outcome` 双保险。采集阶段只显示只读范围行,composer 旁提供「先这样」。
- 验证:`rectification-adopt-flow-20260902`、`rectification-decide-next-action`、`rectification-confirmation-gate`、`rectification-candidate-result`;accept 源码锁 409 在 RPC 之前。
- 防复发:`can_adopt` 只能收紧,不得在 `collect_evidence` / `discriminate_candidates` / `validate_holdout` 放行。`exact_minute_confirmed` / `completed_with_range` 不得新增放行。
- 相关记录:BUG-313、BUG-323
- 最近更新:2026-09-03
- 影响面:`publicDecisionFields`、`POST .../candidates/accept`、`parseRectificationCandidateResult`、`rectification-agentic-chat`、`OPENING_COLLECT_DOMAIN`
- 用户现象:采集题还在问时,同一条助手消息下面出现三张「采用此时间」卡。开场「随便一件带时间的经历」被跳过或答成搬家后,真正的教育采集题变成「再补一件」,或教育域被当成已拒。
- 触发条件:`session_outcome=collect_evidence`,内部 `capability.canAdopt=true`,当前题是 `collect_spoken`。开场题曾以 `collect:education:collect_method_evidence` 持久化。
- 根因:`collect()` 把 `canAdopt` 原样投影成公开 `can_adopt`。前端 `showSelectionCards` 只靠 `!showLiveChoiceCard`,采集题没有 A–D 卡,采用卡就露出来。v9 删掉 offer 门后,BUG-313 / BUG-323 的防复发条款失效。开场题不是教育题,却以 `education` 持久化。
- 修复:公开 `can_adopt` 只在 `adopt_representative` / `provisional_range_user_stopped` / `awaiting_confirmation` / `validated_range` 为真(后者是 holdout 已过、ready_to_adopt 的既有语义,不是新开口)。accept 在 `can_adopt=false` 时 409;前端再按 `session_outcome` 双保险。采集阶段只显示只读范围行,composer 旁提供「先这样」。开场域改为 `other`(id `collect:other:collect_method_evidence`);`declinedDomains` / `domainCollectFocusAsked` 忽略 `collect:other:` 开场行。occupation 仍走 `collect:occupation:`。
- 验证:`rectification-adopt-flow-20260902`、`rectification-decide-next-action`、`rectification-confirmation-gate`、`rectification-candidate-result`;accept 源码锁 409 在 RPC 之前。`rectification-adopt-flow-fix-20260903` 跳过开场后 exhaustion 仍给 education 且无 `collect_retry`。
- 防复发:`can_adopt` 只能收紧,不得在 `collect_evidence` / `discriminate_candidates` / `validate_holdout` 放行。`exact_minute_confirmed` / `completed_with_range` 不得新增放行。开场题不得占用 education/career/relationship/family,不得为 unknown。不改 DB check 约束。
- 相关记录:BUG-313、BUG-323、BUG-501
- 复发自:BUG-313、BUG-323
- 修复版本:待发布
@@ -7669,14 +7669,14 @@
- 状态:resolved
- 首次发现:2026-09-02
- 最近更新:2026-09-02
- 影响面:`keepAcceptedFocus`、`projectRectificationChoiceCard`、`rectification-set-focus`
- 用户现象:点「采用此时间」后出现核对题,嵌入卡 disabled,点不了 A–D。
- 触发条件:已采用,active focus 为 `reverse_verify:education_style:score`,随后 GET / set-focus 重算 followup。
- 根因:承接分支用 `method_id: active_focus` 重建 `question_id`,与已持久化 id 不一致;`projectRectificationChoiceCard` 按设计拒绝串题,返回 null。核对题 schema 还被最高增益区分探针盖上 relocation identity。
- 修复:`keepAcceptedFocus` / `out_of_sample_check` 沿用已持久化 `questionId`、`ask_theme`、`domain` 和选项。不放宽 choice-card 校验。reverse_verify schema 不盖区分探针。spokenPrompt 含钟点时保留服务端题干以免卡片不可解析。区分题 keep 仍走 `probe:` semantic_key。
- 验证:`rectification-adopt-flow-20260902`、`rectification-question-ownership` 采用后续跑 set-focus。
- 防复发:无 semantic_key 的 followup 必须 `focus.questionId === frame.question_id`。
- 最近更新:2026-09-03
- 影响面:`keepAcceptedFocus`、`projectRectificationChoiceCard`、`rectification-set-focus`、`expectedAnswerSchemaFor`
- 用户现象:点「采用此时间」后出现核对题,嵌入卡 disabled,点不了 A–D。题干有两个年份时沿用错年;schema 缺 `probe_year` 时从文案反推。
- 触发条件:已采用,active focus 为 `reverse_verify:education_style:score`,随后 GET / set-focus 重算 followup。schema 无 `probe_year` 且题干含 `19xx`/`20xx`。
- 根因:承接分支用 `method_id: active_focus` 重建 `question_id`,与已持久化 id 不一致;`projectRectificationChoiceCard` 按设计拒绝串题,返回 null。核对题 schema 还被最高增益区分探针盖上 relocation identity。`keepProbeYear` 用题干正则兜底,和「不得用字符串反推状态」同向。
- 修复:`keepAcceptedFocus` / `out_of_sample_check` 沿用已持久化 `questionId`、`ask_theme`、`domain` 和选项。不放宽 choice-card 校验。reverse_verify schema 不盖区分探针。spokenPrompt 含钟点时保留服务端题干以免卡片不可解析。区分题 keep 仍走 `probe:` semantic_key。reverse_verify / oos schema 写入 `followup.probe_year`;keep 只取匹配探针或 schema;缺年则省略。删除题干正则。
- 验证:`rectification-adopt-flow-20260902`、`rectification-question-ownership` 采用后续跑 set-focus。`rectification-adopt-flow-fix-20260903` 无 schema 年且无匹配探针时 followup 不带 `probe_year`,`method-followup.ts` 无年份正则。
- 防复发:无 semantic_key 的 followup 必须 `focus.questionId === frame.question_id`。不得从题干/正文抠年份或其它状态。
- 相关记录:BUG-492、BUG-497
- 复发自:无
- 修复版本:待发布
@@ -7685,15 +7685,15 @@
- 状态:resolved
- 首次发现:2026-09-02
- 最近更新:2026-09-02
- 最近更新:2026-09-03
- 影响面:`rectification-agentic-chat`、`attachOfferResultToTurns`、核对题 skip 文案
- 用户现象:采用后三张卡消失,列表末尾出现「用这个时间看盘」;续跑结束后卡又出现在新消息下,与核对题并存。被关掉的采集题无痕消失。
- 用户现象:采用后三张卡消失,列表末尾出现「用这个时间看盘」;续跑结束后卡又出现在新消息下,与核对题并存。被关掉的采集题无痕消失。状态条「改选」曾是不可点的 `<span>`。
- 触发条件:采用后续跑 `busy`;`savedStatus=accepted` 渲染 `rectification-consult-handoff`。
- 根因:卡永远锚在最新助手消息;采用后的界面动作散落在列表末尾,不跟出卡消息走。
- 修复:出卡消息拥有 `candidateOffer`;采用后原地结算「已采用 / 改选」;状态条承接「改选 / 用这个时间看盘」;核对题「这题跳过」;被关掉的采集题标「已跳过」。
- 验证:`rectification-agentic-entry`、`rectification-activity-receipt`、`rectification-adopt-flow-20260902` 组件源码锁。
- 防复发:已采用后不得把卡锚到最新消息;不得再渲染 `rectification-consult-handoff`。
- 相关记录:BUG-497、BUG-490
- 根因:卡永远锚在最新助手消息;采用后的界面动作散落在列表末尾,不跟出卡消息走。「改选」赋了 `offerSectionRef` 但从不清滚动。
- 修复:出卡消息拥有 `candidateOffer`;采用后原地结算「已采用 / 改选」;状态条承接「改选」;核对题「这题跳过」;被关掉的采集题标「已跳过」。「改选」改为 `<button type="button">`,点击 `scrollIntoView` 到出卡消息并闪一次 `rectification-message-flash`。`showSelectionCards` 为 false 时不渲染。「用这个时间看盘」见 BUG-502。
- 验证:`rectification-agentic-entry`、`rectification-activity-receipt`、`rectification-adopt-flow-20260902` 组件源码锁。`rectification-adopt-flow-fix-20260903` 锁「改选」为 button + `scrollIntoView`。
- 防复发:已采用后不得把卡锚到最新消息;不得再渲染 `rectification-consult-handoff`。「改选」必须是 button。
- 相关记录:BUG-497、BUG-490、BUG-502
- 复发自:无
- 修复版本:待发布
@@ -7713,3 +7713,35 @@
- 复发自:无
- 修复版本:待发布
## BUG-501 | 采集阶段关采用卡后无题无出口
- 状态:resolved
- 首次发现:2026-09-03
- 最近更新:2026-09-03
- 影响面:`inspectNonTerminalTurnExit`、`persistNextInterviewIfIdle`、`persistExhaustionCollect`
- 用户现象:采集阶段把题问完后 composer 空着,没有下一问、没有采用卡、也没有「先这样」。
- 触发条件:`session_outcome=collect_evidence`,内部 `canAdopt=true`,无 active focus,`next_followup` / `deferred_followup` 都空。
- 根因:`35e5781e` 收紧公开 `can_adopt` 后,非终止轮出口仍把内部 `decision.canAdopt` 当成「已有出口」。`persistNextInterviewIfIdle` 不建题,`ensureNonTerminalTurnExit` 又跳过 `persistExhaustionCollect`。此前漏出的采用卡(BUG-497)掩盖了这个死角。
- 修复:`satisfied` 与 idle 跳过持久化改看 `publicCanAdopt(decision)`。公开不能采用时走 `persistExhaustionCollect`,兜底采集题自带「先这样」。
- 验证:`rectification-adopt-flow-fix-20260903` 采集期 `ensureNonTerminalTurnExit` 建 `collect_spoken` 并打 `rectification_nonterminal_exit_repaired`;`adopt_representative` 对照不建题。
- 防复发:没有可回答问题且用户不能采用时,不得把内部 `canAdopt` 当成非终止轮已满足。公开 `can_adopt` 只能收紧。
- 相关记录:BUG-497
- 复发自:无
- 修复版本:待发布
## BUG-502 | 状态条「用这个时间看盘」无实际作用
- 状态:resolved
- 首次发现:2026-09-03
- 最近更新:2026-09-03
- 影响面:`rectification-agentic-chat`、`conversational-birth-time-rectification`、`page.tsx`、`use-session-management`
- 用户现象:采用后点「用这个时间看盘」,只开一个空会话并往输入框塞一句服务端不读的话,与自己点「新对话」无异。
- 触发条件:`savedStatus=accepted`,状态条渲染 `onStartConsultation` 按钮。
- 根因:采用时 RPC 已写 `profiles.active_birth_time`;按钮没有刷新档案、不带回原问题,只做 `startNewChat()` + 填 draft。
- 修复:删除按钮与 `onStartConsultation` / `startConsultationAfterRectification` 链。状态条改为「已采用 … · 改选」加「之后新建对话即按此时间排盘。」;待回问题横幅改为结束后新建对话再问。`onSaved` 仍 `refreshAccount`。
- 验证:`rectification-adopt-flow-fix-20260903` 扫描 `frontend/src`;`rectification-adopt-flow-20260902` / `rectification-agentic-entry` 改为 `doesNotMatch`。
- 防复发:不得再提供「用这个时间看盘」或 `rectification-consult-handoff`。新对话按 `verified_chart` 取采用时间。
- 相关记录:BUG-499
- 复发自:无
- 修复版本:待发布