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/); });