fix(rectification): stop occupation coverage from locking questions and the range exit
Independent Staging Quality Gate / validate (push) Successful in 11m40s
Independent Staging Quality Gate / publish (push) Successful in 9m36s

Occupation answers were stored as career, so coverage never closed, yearless
cards never fired, and the decision layer suppressed an engine-allowed range.
Normalize occupation-collect writes, allow yearless cards once training is
open, offer a range when no distinguish card remains, and align the public
house table to the representative minute.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-30 03:05:28 +08:00
co-authored by Cursor
parent f5c02924c9
commit 02d4c91626
16 changed files with 815 additions and 69 deletions
@@ -34,11 +34,12 @@ import {
} from "@/lib/rectification-agentic/v9/turn-intent-classifier";
import { persistServerOwnedFocus, openQuestionFromPersistedFocus, isCollectFocusSchema, isRenderableChoiceOpenQuestion } from "@/lib/rectification-agentic/v9/server-focus";
import { buildMethodFollowupPlan } from "@/lib/rectification-agentic/v9/method-followup";
import { isNonConvergingRangeOffer } from "@/lib/rectification-agentic/core/rectification-decision";
export const runtime = "nodejs";
export const maxDuration = 240;
export const DISCRIMINATOR_EXHAUSTED_NARRATION = "当前几个候选已经构成可信区间。你可以再一件记得时间的经历,也可以先按这个区间看盘。";
export const DISCRIMINATOR_EXHAUSTED_NARRATION = "可以先按当前区间看盘,也可以再一件记得时间的经历";
function completedMessageResponse(text: string, requestId: string, caseId: string) {
const body = [
@@ -429,6 +430,14 @@ export async function POST(request: Request) {
// Ranking stays fail-open when compute is unavailable.
}
const decision = decideFromDossier(dossier, { birthDate });
if (isNonConvergingRangeOffer(decision)) {
await persistV9DeterministicTurn(accounting, userId, caseId, {
requestId,
userMessage: parsed.data.message ?? null,
assistantMessage: DISCRIMINATOR_EXHAUSTED_NARRATION,
});
return completedMessageResponse(DISCRIMINATOR_EXHAUSTED_NARRATION, requestId, caseId);
}
if (decision.nextAction === "ask_candidate_discriminator") {
const catalog = rectificationFollowupCatalog(
dossier.latestResult,
@@ -437,6 +446,7 @@ export async function POST(request: Request) {
const plan = buildMethodFollowupPlan({
evidence: dossier.evidence,
declinedTopics: dossier.conversationSummary.declinedSkippedTopics,
closedCollectFocuses: dossier.conversationSummary.declinedSkippedTopics,
sessionOutcome: "discriminate_candidates",
...catalog,
birthDate,