fix(rectification): close non-converging range offer without an exit
Independent Staging Quality Gate / validate (push) Successful in 11m3s
Independent Staging Quality Gate / publish (push) Successful in 8m48s

When coverage still blocks adopt and no renderable discriminator remains, narrate the numeric range and persist a spoken collect instead of promising a time card that cannot be clicked. Recompute probe information gain on active candidates and drop zero-split probes explicitly.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-30 18:35:16 +08:00
co-authored by Cursor
parent 79f65ac8b0
commit 85b14b13ae
18 changed files with 961 additions and 37 deletions
+16
View File
@@ -6894,3 +6894,19 @@
- 相关记录:BUG-404、BUG-432、BUG-440、BUG-441
- 复发自:BUG-441
- 修复版本:待发布
## BUG-450 | 非收敛区间提议无数值、无时间卡、无下一问
- 状态:resolved
- 首次发现:2026-08-30
- 最近更新:2026-08-30
- 影响面:`offerRangeWithoutAdopt`、`persistNextInterviewIfIdle`、`projectRectificationChoiceCard`、`buildCandidateContrastPacket`、出题层 `rankRenderableDiscriminators`、POST `/api/rectification/agent` 消息快路径
- 用户现象:答完最后一问后助手说「可以先按当前区间看盘,也可以再补一件记得时间的经历」,界面既没有可采用的时间卡,也没有下一个问题,正文里连区间数值都没有,对话到此为止。
- 触发条件:训练门已开、occupation 等阻塞覆盖未齐、`datedMethodCollectOpen` 为假、引擎已放行 accept/propose、`probe === null`、`canOfferRange=true` 且 `canAdopt` / `selectionAllowed` / `proposeAllowed` 全假。本例活跃候选 04:47/04:51/04:53/04:59,family 已 declined,账本已有 2020 career 与 2024 relationship。
- 根因:三段叠加。(1) P0 消费端死胡同:`offerRangeWithoutAdopt` 把 `canOfferRange` 设真却把 `canAdopt`/`selectionAllowed` 保持假;`isNonConvergingRangeOffer` 让 `persistNextInterviewIfIdle` 早退不落下一问;`projectRectificationChoiceCard` 对 `provisional_range` 一律 null;前端时间卡要 `selectionAllowed`。同一句双出口常量又重复写在 `rectification-decision.ts`、`route.ts`、`answer-choice.ts`,正文许诺看盘或再补经历,两个出口都没有承载。(2) P1 `probe=null` 的真实输入:年份探针活在 `inference_state.probes`(对比包)而不是 `discriminating_event_probes`。`buildCandidateContrastPacket` 对非结构化探针在 `provided.has(domain)` 时整域丢弃,2020 career 证据因此杀掉全部 career 存在/大运题,包括 `career.2024.04.dasha_boundary`。这与出题层「Dasha existence 跳过账本已有的那年,不是整个领域」不一致。`remainingConflictProbes` 走年份邻近规则,所以把同一探针放进 `discriminating_event_probes` 的重建会问出来。出题层在 discriminate 模式下于是落到 occupation `method_coverage` 口述题,`followupAsksRenderableDiscriminator` 为假,决策把 `probe` 打成 null。occupation 阻塞 adopt 但不在 `datedMethodCollectOpen` 里,于是进入 `offerRangeWithoutAdopt`。该跳过没有写入 `dropped_probes`。已排除:`askedKeys` 把 `candidate_split_hash` 误判为已答(2023.05 与 2024.04 哈希不同);`activeFocus` 未关(`discriminatorProbeIfFollowupCanAsk` 不传入旧焦点)。(3) P2:即使按年保留,`career.2024.04` 切的是 05:00 之后 vs 之前,`career.2023.dasha_activation` 只拎 05:15;淘汰后活跃四分钟上信息量为 0。出题层原先沿用建题时对全窗口的 IG,零区分力探针既不问也不 drop。
- 修复:P0 选口述采集出口,不放开确认门与 `canAdopt`(occupation 仍挡住 adopt,也不新造无选项容器)。`offerRangeWithoutAdopt` 正文改为 `nonConvergingRangeNarration`(区间数值 + 代表分钟 + 既有免责口径);同一轮 `exhaustionSpokenCollectFollowup` 按 family → education → finance 落一条未用过的 `oos_blind` 口述题并持久化,使 `current_question` 非 null。三处相同字符串合并为该导出函数。P1:对比包与 `rankRenderableDiscriminators` 对带年份非结构化探针改为按年跳过,不再整域丢弃。P2:按当前活跃候选重算信息量;零区分力写入 `dropped_probes.reason=no_split_among_active`。未放宽 `MIN_BOUNDARY_DAYS`、distinguish 契约、confirmation gate,未回退 b43808b0 无年份收窄。
- 验证:`frontend/tests/rectification-range-offer-deadend.test.ts`。修复前:`persistNextInterviewIfIdle` 在 `isNonConvergingRangeOffer` 返回 `{persisted:false, hostNarration:null}`;正文是无数值的双出口常量;`projectRectificationChoiceCard` 为 null;`canAdopt=false`。修复后:正文含 `04:47–04:53` 与代表分钟 `04:51`,并落 education `collect_spoken`。P1 最小夹具:探针只在 `inference_state.probes`、career 领域已有 2020 证据、occupation 未覆盖;对活跃四分钟仍有切分的 `career.2022.dasha_boundary` 走 `ask_candidate_discriminator`,不得进区间提议。P2:`career.2024.04.dasha_boundary` 与 `career.2023.dasha_activation` 进入 `dropped_probes` 且 reason 为 `no_split_among_active`。`userStopped` 仍走 `provisional_range_user_stopped` 且 `canAdopt=true`。`rectification-collect-stall` / `rectification-spoken-collect` / BUG-442 occupation / b43808b0 无年份收窄保持绿。`assert.doesNotMatch(/answerText\.(?:includes|match|search)\(/)` 仍绿。
- 防复发:助手正文承诺的每个出口,同一轮必须有对应的可点承载;区间提议必须带区间数值与代表分钟口径;探针信息量必须对当前活跃候选计算,失去区分力的探针要显式 drop 而不是静默留着。不得为了出看盘按钮而放宽 `canAdopt` / confirmation gate。
- 相关记录:BUG-432、BUG-440、BUG-441、BUG-442、BUG-449
- 复发自:无
- 修复版本:待发布