import assert from "node:assert/strict"; import test from "node:test"; import { EFFECTIVE_ANSWER_SAFETY_CAP } from "../src/lib/birth-time-dynamic-stop-policy.ts"; import { DEFAULT_MAX_DISCRIMINATION_ROUNDS } from "../src/lib/rectification-agentic/core/types.ts"; import { decideRectification } from "../src/lib/rectification-agentic/core/rectification-decision.ts"; import { RECTIFICATION_POLICY } from "../src/lib/rectification-policy.ts"; import type { CandidateDiscriminatorProbe } from "../src/lib/rectification-agentic/core/candidate-contrast-packet.ts"; const PROBE: CandidateDiscriminatorProbe = { probeId: "probe-1", candidateSetVersion: "set-1", question: "这件事更接近哪一种情况?", expectedOutcomes: [ { outcomeId: "yes", supportsCandidateIds: ["05:00"], conflictsCandidateIds: ["05:06", "05:07"], }, { outcomeId: "no", supportsCandidateIds: ["05:06", "05:07"], conflictsCandidateIds: ["05:00"], }, ], candidateSplitHash: "05:00|05:06|05:07", informationGain: 0.5, sourceFeatures: [{ technique: "test", calculationResultId: null }], domain: "career", year: 2020, semanticKey: "career.2020.test", }; const BASE_INPUT = { methodCoverageAll: true, trainingGateOpen: true, candidateScores: [ { time: "05:00", score: 34 }, { time: "05:06", score: 33 }, { time: "05:07", score: 33 }, ], discriminatorProbe: PROBE, holdoutValidation: "unavailable" as const, }; function decideWithBudget(budget: { inferenceRounds?: number; effectiveAnswerCount?: number; plateauRounds?: number; }) { return decideRectification({ ...BASE_INPUT, ...budget }); } test("every persisted discrimination budget terminates before asking another probe", () => { for (const budget of [ { inferenceRounds: DEFAULT_MAX_DISCRIMINATION_ROUNDS }, { effectiveAnswerCount: EFFECTIVE_ANSWER_SAFETY_CAP }, { plateauRounds: RECTIFICATION_POLICY.maxPlateauRounds }, ]) { const decision = decideWithBudget(budget); assert.equal(decision.nextAction, "complete_with_range"); assert.equal(decision.sessionOutcome, "completed_with_range"); assert.notEqual(decision.nextAction, "ask_candidate_discriminator"); } }); test("repeated declined or unsure answers reach the existing plateau terminal", () => { const decision = decideWithBudget({ inferenceRounds: 0, effectiveAnswerCount: RECTIFICATION_POLICY.maxPlateauRounds, plateauRounds: RECTIFICATION_POLICY.maxPlateauRounds, }); assert.equal(decision.nextAction, "complete_with_range"); assert.equal(decision.sessionOutcome, "completed_with_range"); }); test("exhausted discrimination still delivers the credible candidate range", () => { const decision = decideWithBudget({ inferenceRounds: DEFAULT_MAX_DISCRIMINATION_ROUNDS, effectiveAnswerCount: 0, plateauRounds: 0, }); assert.equal(decision.resultStatus, "completed_with_range"); assert.equal(decision.sessionOutcome, "completed_with_range"); assert.equal(decision.canOfferRange, true); assert.equal(decision.canAdopt, true); assert.deepEqual(decision.credibleRange, ["05:00", "05:07"]); }); test("additional score evidence never widens the credible range", () => { const before = decideRectification({ ...BASE_INPUT, candidateScores: [ { time: "05:00", score: 34 }, { time: "05:06", score: 33 }, { time: "05:07", score: 33 }, ], inferenceRounds: DEFAULT_MAX_DISCRIMINATION_ROUNDS, }); const after = decideRectification({ ...BASE_INPUT, candidateScores: [ { time: "05:00", score: 42 }, { time: "05:06", score: 33 }, { time: "05:07", score: 33 }, ], inferenceRounds: DEFAULT_MAX_DISCRIMINATION_ROUNDS, }); const width = (range: readonly [string, string] | null) => { assert.ok(range); const toMinutes = (time: string) => Number(time.slice(0, 2)) * 60 + Number(time.slice(3, 5)); return toMinutes(range[1]) - toMinutes(range[0]); }; assert.ok(width(after.credibleRange) <= width(before.credibleRange)); });