fix(rectification): deliver range cards on tied first place instead of falling back to collect (BUG-680/681/682)
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:
@@ -10,6 +10,7 @@
|
||||
|
||||
import type { PersistedRectificationTurn } from "../components/conversational-birth-time-rectification.tsx";
|
||||
import { BOOTSTRAP_PREPARE_TIMEOUT_MS } from "./home-bootstrap.ts";
|
||||
import { sessionOutcomeAllowsDelivery } from "./rectification-agentic/core/rectification-decision.ts";
|
||||
|
||||
/**
|
||||
* Upper bound on hydrating a Case (turns + snapshot) after `/cases/open`
|
||||
@@ -30,6 +31,7 @@ export const RECTIFICATION_QUESTION_RETRY_INTERVAL_MS = 2_000;
|
||||
export const RECTIFICATION_QUESTION_PREPARING_LABEL = "正在准备下一个问题…";
|
||||
export const RECTIFICATION_QUESTION_UNAVAILABLE_COPY = "没有拿到下一个问题。";
|
||||
export const RECTIFICATION_COLLECT_WAITING_PLACEHOLDER = "再说一件带年月的事";
|
||||
export const RECTIFICATION_DELIVERED_COPY = "再问下去也分不开了。范围在上面,对不上可以改选。";
|
||||
export const RECTIFICATION_QUESTION_RELOAD_LABEL = "接着问";
|
||||
export const RECTIFICATION_QUESTION_REPAIR_FAILED_COPY = "暂时接不上,请新建一次校正。";
|
||||
export const RECTIFICATION_QUESTION_REPAIR_LIMIT = 2;
|
||||
@@ -269,7 +271,8 @@ export type RectificationQuestionGapState =
|
||||
| "unavailable"
|
||||
| "verified_idle"
|
||||
| "persisted_question"
|
||||
| "collect_waiting";
|
||||
| "collect_waiting"
|
||||
| "delivered";
|
||||
|
||||
export type RectificationQuestionGapInput = Readonly<{
|
||||
/** The current question is rendered live inside an assistant message. */
|
||||
@@ -289,6 +292,8 @@ export type RectificationQuestionGapInput = Readonly<{
|
||||
questionPersisted?: boolean;
|
||||
/** Training gate still closed; pool empty; keep the case open for another dated event. */
|
||||
collectWaiting?: boolean;
|
||||
sessionOutcome?: string | null;
|
||||
stopReason?: string | null;
|
||||
busy: boolean;
|
||||
readonly: boolean;
|
||||
regenerating: boolean;
|
||||
@@ -313,6 +318,7 @@ export function rectificationQuestionGapState(input: RectificationQuestionGapInp
|
||||
if (!input.snapshotLoaded) return retryGate;
|
||||
if (!input.resumableCase) return "idle";
|
||||
if (input.liveQuestionVisible || input.offerAwaitingReader) return "idle";
|
||||
if (interviewDeliveredGap(input)) return "delivered";
|
||||
if (input.collectWaiting) return "collect_waiting";
|
||||
if (input.questionPersisted) return "persisted_question";
|
||||
if (input.nextUserActionId === "start_consultation") return "verified_idle";
|
||||
@@ -378,6 +384,16 @@ export function interviewChoiceCardUnavailable(input: Readonly<{
|
||||
return false;
|
||||
}
|
||||
|
||||
export function interviewDeliveredGap(input: Readonly<{
|
||||
questionMissing: boolean;
|
||||
sessionOutcome?: string | null;
|
||||
stopReason?: string | null;
|
||||
}>): boolean {
|
||||
if (!input.questionMissing) return false;
|
||||
if (sessionOutcomeAllowsDelivery(input.sessionOutcome)) return true;
|
||||
return input.stopReason === "tied_first" || input.stopReason === "user_uncertainty_too_high";
|
||||
}
|
||||
|
||||
export function interviewCollectWaiting(input: Readonly<{
|
||||
stopReason?: string | null;
|
||||
sessionOutcome?: string | null;
|
||||
|
||||
Reference in New Issue
Block a user