fix(rectification): invite-first collect, holdout at 4 events, Skill 10.0.23 (BUG-646–648)
Stop domain-wheel collecting and age-band years in prompts. Ask until the training gate, then discriminate until convergence, then deliver a range plus a concrete follow-up. Reserve holdout only with four dated events. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -29,6 +29,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_QUESTION_RELOAD_LABEL = "接着问";
|
||||
export const RECTIFICATION_QUESTION_REPAIR_FAILED_COPY = "暂时接不上,请新建一次校正。";
|
||||
export const RECTIFICATION_QUESTION_REPAIR_LIMIT = 2;
|
||||
@@ -63,6 +64,11 @@ export type RectificationCaseSnapshotPayload = Readonly<{
|
||||
step_state?: unknown;
|
||||
question_source?: unknown;
|
||||
next_user_action?: Readonly<{ id?: unknown }>;
|
||||
interview?: Readonly<{
|
||||
stop_reason?: unknown;
|
||||
session_outcome?: unknown;
|
||||
type?: unknown;
|
||||
}>;
|
||||
case?: Readonly<{
|
||||
status?: unknown;
|
||||
accepted_time?: unknown;
|
||||
@@ -262,7 +268,8 @@ export type RectificationQuestionGapState =
|
||||
| "preparing"
|
||||
| "unavailable"
|
||||
| "verified_idle"
|
||||
| "persisted_question";
|
||||
| "persisted_question"
|
||||
| "collect_waiting";
|
||||
|
||||
export type RectificationQuestionGapInput = Readonly<{
|
||||
/** The current question is rendered live inside an assistant message. */
|
||||
@@ -280,6 +287,8 @@ export type RectificationQuestionGapInput = Readonly<{
|
||||
* settled assistant message carries it yet.
|
||||
*/
|
||||
questionPersisted?: boolean;
|
||||
/** Training gate still closed; pool empty; keep the case open for another dated event. */
|
||||
collectWaiting?: boolean;
|
||||
busy: boolean;
|
||||
readonly: boolean;
|
||||
regenerating: boolean;
|
||||
@@ -304,6 +313,7 @@ export function rectificationQuestionGapState(input: RectificationQuestionGapInp
|
||||
if (!input.snapshotLoaded) return retryGate;
|
||||
if (!input.resumableCase) return "idle";
|
||||
if (input.liveQuestionVisible || input.offerAwaitingReader) return "idle";
|
||||
if (input.collectWaiting) return "collect_waiting";
|
||||
if (input.questionPersisted) return "persisted_question";
|
||||
if (input.nextUserActionId === "start_consultation") return "verified_idle";
|
||||
if (input.questionLoadFailed) return "unavailable";
|
||||
@@ -317,6 +327,39 @@ export function rectificationQuestionRetryActive(state: RectificationQuestionGap
|
||||
return state === "preparing";
|
||||
}
|
||||
|
||||
export function interviewStopReasonFromSnapshot(payload: RectificationCaseSnapshotPayload | null): string | null {
|
||||
if (!payload) return null;
|
||||
const interviewReason = payload.interview?.stop_reason;
|
||||
if (typeof interviewReason === "string" && interviewReason.trim()) return interviewReason.trim();
|
||||
const latest = payload.latest_result;
|
||||
if (latest && typeof latest === "object" && !Array.isArray(latest)) {
|
||||
const reason = (latest as { evidence_stop_reason?: unknown; stop_reason?: unknown }).evidence_stop_reason
|
||||
?? (latest as { stop_reason?: unknown }).stop_reason;
|
||||
if (typeof reason === "string" && reason.trim()) return reason.trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function interviewSessionOutcomeFromSnapshot(payload: RectificationCaseSnapshotPayload | null): string | null {
|
||||
if (!payload) return null;
|
||||
const interviewOutcome = payload.interview?.session_outcome;
|
||||
if (typeof interviewOutcome === "string" && interviewOutcome.trim()) return interviewOutcome.trim();
|
||||
return null;
|
||||
}
|
||||
|
||||
export function interviewCollectWaiting(input: Readonly<{
|
||||
stopReason?: string | null;
|
||||
sessionOutcome?: string | null;
|
||||
questionMissing: boolean;
|
||||
offeringCards?: boolean;
|
||||
}>): boolean {
|
||||
if (!input.questionMissing || input.offeringCards) return false;
|
||||
if (input.sessionOutcome && input.sessionOutcome !== "collect_evidence") return false;
|
||||
return input.stopReason === "insufficient_dated_events"
|
||||
|| input.stopReason === "insufficient_domains"
|
||||
|| input.stopReason === "insufficient_events";
|
||||
}
|
||||
|
||||
function probeHasYear(value: unknown): boolean {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
||||
const year = (value as { year?: unknown }).year;
|
||||
|
||||
Reference in New Issue
Block a user