b1173f7245
Three collected events with a reserved holdout were stalling because the discriminator door counted holdout. Public selection_allowed still had snapshot fallbacks, and health only proved the image SHA. Co-authored-by: Cursor <cursoragent@cursor.com>
113 lines
4.8 KiB
TypeScript
113 lines
4.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
decideRectification,
|
|
publicDecisionFields,
|
|
} from "../src/lib/rectification-agentic/core/rectification-decision.ts";
|
|
import { decideNextAction } from "../src/lib/rectification-agentic/core/decide-next-action.ts";
|
|
import { overlayPublicDecision } from "../src/lib/rectification-agentic/v9/decision-from-dossier.ts";
|
|
import { conversationalSessionOutcome } from "../src/lib/rectification-agentic/v9/method-followup.ts";
|
|
|
|
const SEPARATED = [
|
|
{ time: "04:48", score: 58 },
|
|
{ time: "04:49", score: 42 },
|
|
];
|
|
|
|
function readSource(relative: string) {
|
|
return readFileSync(new URL(relative, import.meta.url), "utf8");
|
|
}
|
|
|
|
test("public decision fields are derived from decideRectification", () => {
|
|
const fixtures = [
|
|
{
|
|
methodCoverageAll: false,
|
|
trainingGateOpen: false,
|
|
candidateScores: SEPARATED,
|
|
},
|
|
{
|
|
methodCoverageAll: true,
|
|
trainingGateOpen: true,
|
|
candidateScores: [
|
|
{ time: "05:00", score: 34 },
|
|
{ time: "05:01", score: 33 },
|
|
{ time: "05:02", score: 33 },
|
|
],
|
|
},
|
|
{
|
|
methodCoverageAll: true,
|
|
trainingGateOpen: true,
|
|
candidateScores: SEPARATED,
|
|
holdoutValidation: "passed" as const,
|
|
},
|
|
{
|
|
methodCoverageAll: true,
|
|
userStopped: true,
|
|
candidateScores: SEPARATED,
|
|
holdoutValidation: "not_started" as const,
|
|
},
|
|
];
|
|
for (const input of fixtures) {
|
|
const decision = decideRectification(input);
|
|
const fields = publicDecisionFields(decision);
|
|
assert.deepEqual(fields, {
|
|
type: decision.nextAction,
|
|
session_outcome: decision.sessionOutcome,
|
|
completion_status: decision.completionStatus,
|
|
validated: decision.validated,
|
|
can_offer_range: decision.canOfferRange,
|
|
can_adopt: decision.canAdopt,
|
|
can_confirm_exact_minute: decision.canConfirmExactMinute,
|
|
selection_allowed: decision.selectionAllowed,
|
|
propose_allowed: decision.proposeAllowed,
|
|
precision_stage: decision.precisionStage,
|
|
representative_time: decision.representativeTime,
|
|
credible_range: decision.credibleRange,
|
|
});
|
|
assert.equal(overlayPublicDecision({ selectionAllowed: true }, decision).selectionAllowed, fields.selection_allowed);
|
|
assert.equal(overlayPublicDecision({ selectionAllowed: true }, decision).validated, fields.validated);
|
|
assert.equal(decideNextAction(input).type, decision.nextAction);
|
|
assert.equal(conversationalSessionOutcome({
|
|
selectionAllowed: decision.selectionAllowed,
|
|
proposeAllowed: decision.proposeAllowed,
|
|
confirmationAllowed: false,
|
|
nextFollowup: null,
|
|
userStopped: input.userStopped,
|
|
candidateScores: input.candidateScores,
|
|
holdoutValidation: input.holdoutValidation,
|
|
trainingGateOpen: input.trainingGateOpen,
|
|
}), decision.sessionOutcome);
|
|
}
|
|
});
|
|
|
|
test("interview, choice, refresh and next-action all call the same reducer", () => {
|
|
const interview = readSource("../src/lib/rectification-agentic/v9/interview-state.ts");
|
|
const adapter = readSource("../src/lib/rectification-agentic/v9/decision-from-dossier.ts");
|
|
const choice = readSource("../src/lib/rectification-agentic/v9/answer-choice.ts");
|
|
const refresh = readSource("../src/lib/rectification-agentic/v9/turn-decision.ts");
|
|
const followup = readSource("../src/lib/rectification-agentic/v9/method-followup.ts");
|
|
const tools = readSource("../src/mastra/rectification-v9-tools.ts");
|
|
const caseRoute = readSource("../src/app/api/rectification/cases/[caseId]/route.ts");
|
|
assert.match(interview, /decideFromDossier\(/);
|
|
assert.match(refresh, /decideFromDossier\(/);
|
|
assert.match(choice, /decideAfterInferenceChange\(/);
|
|
assert.match(adapter, /decideRectification\(/);
|
|
assert.match(followup, /decideRectification\(/);
|
|
assert.match(tools, /decideConversationalSession\(/);
|
|
assert.match(caseRoute, /overlayPublicDecision/);
|
|
assert.match(caseRoute, /publicDecisionFields\(decision\)/);
|
|
assert.doesNotMatch(interview, /sessionOutcomeFromGate/);
|
|
assert.doesNotMatch(choice, /sessionOutcomeFromGate/);
|
|
assert.doesNotMatch(refresh, /sessionOutcomeFromGate/);
|
|
assert.doesNotMatch(tools, /sessionOutcomeFromGate/);
|
|
assert.doesNotMatch(interview, /selectionAllowed: dossier\.latestResult/);
|
|
assert.doesNotMatch(refresh, /selection_allowed: dossier\.latestResult\?\.selectionAllowed/);
|
|
assert.doesNotMatch(tools, /selection_allowed: decision\?\.selectionAllowed \?\? latest/);
|
|
assert.doesNotMatch(tools, /propose_allowed: decision\?\.proposeAllowed \?\? proposeAllowed/);
|
|
assert.match(tools, /evidence: parsed\.evidence/);
|
|
assert.match(followup, /evidence: input\.evidence/);
|
|
assert.match(adapter, /trainingGateOpen: trainingGate\.open/);
|
|
assert.match(adapter, /blockingMethodsCovered/);
|
|
});
|