fix(rectification): deliver range cards on tied first place instead of falling back to collect (BUG-680/681/682)
Independent Staging Quality Gate / validate (push) Successful in 17m18s
Independent Staging Quality Gate / publish (push) Successful in 13m52s

Refresh persist failures no longer count as attempts. tied_first completes with a range before stillNeedNarrowing. Delivery narration and cards share DELIVERY_OUTCOMES. The question gap gets a delivered terminal so the unavailable copy does not appear after a range is given.
This commit is contained in:
jesse-ux
2026-09-14 15:41:04 +08:00
parent e59ef9fbfd
commit d5a8db0a4e
16 changed files with 644 additions and 9 deletions
+48
View File
@@ -10580,3 +10580,51 @@
- 相关记录:BUG-678、BUG-635、BUG-677
- 复发自:BUG-678DESIGN 与合同测试分叉)
- 修复版本:待发布
## BUG-680 | 刷新尝试落库失败仍按已尝试推进,POST 交付 GET 回采集
- 状态:resolved
- 首次发现:2026-09-14
- 最近更新:2026-09-14
- 影响面:`refreshDatedDiscriminatorPoolIfNeeded``persistRefreshAttempt``decideRectification``shouldSkipFollowupPersist`
- 用户现象:跳过最后一道定向补事题后,助手播出完整交付结论,刷新后没有交付卡、没有下一题,时间轴写「再说一件带年月的事就能继续」,并印出「没有拿到下一个问题。」
- 触发条件:前两名 posterior 并列(如 16/16),`stop_reason=tied_first`;本轮选择题刚推进 revision,刷新尝试用旧 revision 写库撞版本冲突。
- 根因:`persistRefreshAttempt` 失败时返回值被丢弃,`attemptRecorded` 仍为 truePOST 第二次 `decideFromDossier``refreshExhausted` 当成真并交付;GET 读库没有这条 attempt`stillNeedNarrowing` 为真,把 `tied_first` 压回 `collect_evidence`。并列到顶本是终局,被「还有收窄手段」无条件压过。
- 修复:落库失败时 `attemptRecorded=false`,不把内存态写进 dossier,并打 `rectification_refresh_attempt_persist_failed``tied_first``stillNeedNarrowing` / coverageBlocks 之前直接 `completeWithRange`。idle persist 在 `tied_first` 且 outcome 属于交付集合时跳过下一问。不放宽 `can_adopt`
- 验证:`frontend/tests/rectification-delivery-vs-collect-20260914.test.ts`persist 抛错后 attemptRecorded=false;同一份并列 dossier 上 `persistNextInterviewIfIdle``decideFromDossier` 都交付。
- 防复发:任何「是否已尝试/已耗尽」的标志,落库失败时一律按未完成处理。POST 与 GET 对同一状态的决策必须一致,并由对拍测试守着。不得靠内存 overlay 播交付。
- 相关记录:BUG-674、BUG-681、BUG-682
- 复发自:BUG-674POST 与 GET 对同一状态判定不一致)
- 修复版本:待发布
## BUG-681 | 交付话术能说、交付卡不能画
- 状态:resolved
- 首次发现:2026-09-14
- 最近更新:2026-09-14
- 影响面:`DELIVERY_OUTCOMES``deliveryNarrationAllowed``canShowRectificationSelectionCards``canShowRectificationReadonlyRange`
- 用户现象:正文已经念完「现在给的范围是…代表分钟为…」,界面没有区间交付卡。
- 触发条件:`session_outcome``completed_with_range``provisional_range``can_adopt` 为假。
- 根因:卡片闸门用 `ADOPT_OUTCOMES` 且要求 `canAdopt`。这两种正常收尾不在采用集合里。话术闸门认 `offer_provisional_range` / 公开采用,于是能说不能画。
- 修复:新增 `DELIVERY_OUTCOMES` = 采用集合 `{completed_with_range, provisional_range}`。卡片闸门用它,不把 `can_adopt` 提权。交付 outcome 且 `selection_allowed` 时出卡、不出「再说一件」范围行。
- 验证:`rectification-delivery-vs-collect-20260914.test.ts``rectification-candidate-result.test.ts` 表驱动:话术为真则卡为真。
- 防复发:不得新增第二套交付卡。话术与卡必须由同一判据驱动。
- 相关记录:BUG-680、BUG-590
- 复发自:无
- 修复版本:待发布
## BUG-682 | 已交付无题时缺口状态机兜底成「没有拿到下一个问题」
- 状态:resolved
- 首次发现:2026-09-14
- 最近更新:2026-09-14
- 影响面:`rectificationQuestionGapState``interviewDeliveredGap``rectification-agentic-chat.tsx`
- 用户现象:没有题、没有卡时印出「没有拿到下一个问题。」并出现「接着问」。
- 触发条件:`current_question === null``session_outcome=collect_evidence``stop_reason=tied_first`(或已交付 outcome);不是 collect_waiting 的那几个不足理由。
- 根因:缺口状态机没有「已交付 / 没有更多可问」终态,重试耗尽后落到 `unavailable`
- 修复:新增 `delivered`:无题且 outcome 属于交付集合,或 `stop_reason``tied_first` / `user_uncertainty_too_high`。该状态显示出口说明,禁止「没有拿到下一个问题」。普通题没取到仍是 `unavailable`
- 验证:`rectification-delivery-vs-collect-20260914.test.ts``rectification-surface-state.test.ts`
- 防复发:已交付无题不得再走修复入口文案。不得把 `delivered` 误伤真正缺题的 `unavailable`
- 相关记录:BUG-680、BUG-681
- 复发自:无
- 修复版本:待发布
@@ -0,0 +1,23 @@
# 进度 · 播了交付却回到采集态(2026-09-14)
## 范围
- 分支:`codex/rectification-delivery-vs-collect-20260914`(基于 `origin/staging` @ `e59ef9fb`
- 任务单:`docs/tasks/TASK-rectification-delivery-vs-collect-split-20260914.md`
- BUG-680 / 681 / 682 resolved
- 任务 1/2/3 均做完,没有走让步
## 完成
- T1`persistRefreshAttempt` 失败时 `attemptRecorded=false`,不 overlay 内存态。`tied_first` 提到 `stillNeedNarrowing` 与 coverageBlocks 之前。idle persist 在并列到顶时跳过下一问。
- T2`DELIVERY_OUTCOMES`;卡片闸门用它;交付 outcome 且可选择时出卡、不出采集范围行。未提权 `can_adopt`
- T3:缺口状态 `delivered`,文案「再问下去也分不开了。范围在上面,对不上可以改选。」普通缺题仍 `unavailable`
- T4BUG_HISTORY、CHANGELOG、真机清单、DESIGN。
## 验收数字
- `./node_modules/.bin/tsc --noEmit`0 错
- `npm run lint`0 error / 120 warning(既有,未顺手改)
- 相关单测:`rectification-delivery-vs-collect-20260914.test.ts` 6/6candidate-result / surface-state / superseded-focus / unwritten-evidence 之外的定向套件 53/53probe-pool-exhausted 10/10convergence-budget 14/14
- 全量 `npm test`2996 / pass 2829 / fail 153 / skip 14。失败条数与本机 Windows 基线一致(spoken-orphan 轮次 2989/2822/153/14;本轮多 7 条新测全部通过)。153 条是 CRLF、Skill SHA、Docker/DB、`G:\\G:\\` 双盘符、无 symlink 权限,不是本单回归。Linux 门禁基线仍是任务书写的 27 条缺口。
- `next build`:本机 Turbopack 拒跨 worktree 的 `node_modules` junction`points out of the filesystem root`)。未在本树 `npm ci`(避免再占一份依赖)。Linux 门禁会在树内安装后构建。未测 `/` Static 与首屏 gzip。
+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-delivery-vs-collect-split-20260914.md` | `PROGRESS-rectification-delivery-vs-collect-20260914.md` | **P0**:并列到顶(tied_first)时 POST 播了交付结论、GET 又算回 collect_evidence——刷新尝试落库失败仍回报「已尝试」+ `stillNeedNarrowing` 压过 exhaustedBUG-680);交付话术闸门与交付卡闸门不一致,`completed_with_range`/`provisional_range` 能说不能画(BUG-681);缺口状态机没有终态,兜底印「没有拿到下一个问题」(BUG-682) | 待执行 | `codex/rectification-delivery-vs-collect-20260914` |
| `TASK-rectification-delivery-vs-collect-split-20260914.md` | `PROGRESS-rectification-delivery-vs-collect-20260914.md` | **P0**:并列到顶(tied_first)时 POST 播了交付结论、GET 又算回 collect_evidence——刷新尝试落库失败仍回报「已尝试」+ `stillNeedNarrowing` 压过 exhaustedBUG-680);交付话术闸门与交付卡闸门不一致,`completed_with_range`/`provisional_range` 能说不能画(BUG-681);缺口状态机没有终态,兜底印「没有拿到下一个问题」(BUG-682) | 待验收 | `codex/rectification-delivery-vs-collect-20260914` |
| `TASK-rectification-spoken-orphan-and-engine-representative-20260914.md` | `PROGRESS-rectification-spoken-orphan-20260914.md` | **P0**:口述题(定向补事年份追问)没有 `askedTurnId` 时仍是无头像裸行——BUG-675 的挂回规则只覆盖选择题(BUG-678);同屏两个范围口径(旁白用活跃候选首尾、时间轴用 credible_range);引擎 `representative_time` 把已淘汰分钟的宫位表带进模型上下文(BUG-676 收敛为 resolved | 待验收 | `codex/rectification-spoken-orphan-20260914` |
@@ -0,0 +1,16 @@
# 并列到顶交付 vs 采集回退:真机清单(2026-09-14)
分支 `codex/rectification-delivery-vs-collect-20260914`。本环境无 staging 登录态。
## BUG-680 / 681
进入当时那个校正会话,或再走一遍「定向补事问到家人并跳过」。
- [ ] 助手念完交付结论后,同一屏出现区间交付卡(范围、代表分钟、可点「更像这个」若允许选择)。
- [ ] 不会只剩「目前范围 …,再说一件带年月的事就能继续」而没有卡。
- [ ] 同屏不会既出交付卡又出「再说一件带年月的事就能继续」。
## BUG-682
- [ ] 没有下一题时,不再出现「没有拿到下一个问题。」和「接着问」。
- [ ] 可以改选或继续在输入框补经历,文案不是报错口吻。