138 lines
4.1 KiB
TypeScript
138 lines
4.1 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { candidateResultSchema } from "../src/lib/birth-time-journey.ts";
|
|
import { completeScoreTransition } from "../src/lib/birth-time-journey-score-transition.ts";
|
|
import type { CandidateResult } from "../src/lib/birth-time-evidence.ts";
|
|
import type { LegacyStoredRectificationCase as StoredRectificationCase } from "../src/lib/birth-time-journey-service.ts";
|
|
import {
|
|
existingCareerEvent,
|
|
existingEducationEvent,
|
|
guidedCase,
|
|
} from "./birth-time-journey-test-support.ts";
|
|
|
|
const scoreJobId = "c70ea014-f8b4-41f2-9305-e4ae60c0d4d1";
|
|
|
|
function candidate(
|
|
confidence: CandidateResult["confidence"],
|
|
resultId: string,
|
|
) {
|
|
const winningSegment = confidence === "high"
|
|
? { startTime: "14:22", endTime: "14:26", representativeTime: "14:24", widthMinutes: 5 }
|
|
: null;
|
|
return candidateResultSchema.parse({
|
|
resultId,
|
|
confidence,
|
|
canApply: confidence === "high",
|
|
winningSegment,
|
|
eventCount: 4,
|
|
domainCount: 3,
|
|
topScore: 12,
|
|
secondScore: 8,
|
|
marginPercent: 33,
|
|
reasons: confidence === "low" ? ["Candidate scores remain close."] : [],
|
|
evidence: [],
|
|
algorithmVersion: "birth-time-event-scoring-v1",
|
|
});
|
|
}
|
|
|
|
function scoringCase(adaptiveRound: number): StoredRectificationCase {
|
|
const stored = guidedCase({
|
|
version: 6,
|
|
adaptiveRound,
|
|
askedDomains: ["education", "career"],
|
|
lifeEvents: [existingEducationEvent, existingCareerEvent],
|
|
});
|
|
return {
|
|
...stored,
|
|
turnState: {
|
|
turnVersion: 6,
|
|
nextAction: { kind: "score_pending", jobId: scoreJobId },
|
|
progress: {
|
|
phase: "scoring",
|
|
baselineDomainCount: 2,
|
|
confirmedEvidenceCount: 2,
|
|
adaptiveRound,
|
|
maxAdaptiveRounds: 3,
|
|
},
|
|
permissions: { canConfirmCandidate: false },
|
|
evidenceDraft: null,
|
|
},
|
|
};
|
|
}
|
|
|
|
test("completed baseline low score advances to adaptive round one", () => {
|
|
const low = candidate("low", "d833c219-8dd6-4ff4-a89d-d13b56c3084c");
|
|
|
|
const result = completeScoreTransition({
|
|
stored: scoringCase(0),
|
|
candidateResult: low,
|
|
nextVersion: 7,
|
|
});
|
|
|
|
assert.equal(result.turnState?.nextAction.kind, "ask_adaptive_evidence");
|
|
assert.equal(result.turnState?.progress.adaptiveRound, 1);
|
|
assert.equal(result.candidateResult, low);
|
|
});
|
|
|
|
test("completed adaptive round one low score advances to round two", () => {
|
|
const low = candidate("low", "e4ee1f83-4ae1-45ef-a917-a14ed3e40c02");
|
|
|
|
const result = completeScoreTransition({
|
|
stored: scoringCase(1),
|
|
candidateResult: low,
|
|
nextVersion: 7,
|
|
});
|
|
|
|
assert.equal(result.turnState?.nextAction.kind, "ask_adaptive_evidence");
|
|
assert.equal(result.turnState?.progress.adaptiveRound, 2);
|
|
});
|
|
|
|
test("completed adaptive round three low score becomes terminal", () => {
|
|
const low = candidate("low", "6370de71-b768-4faf-910f-5b6dc447b825");
|
|
|
|
const result = completeScoreTransition({
|
|
stored: scoringCase(3),
|
|
candidateResult: low,
|
|
nextVersion: 7,
|
|
});
|
|
|
|
assert.deepEqual(result.turnState?.nextAction, {
|
|
kind: "present_low_result",
|
|
resultId: low.resultId,
|
|
});
|
|
assert.equal(result.snapshot.state, "candidate");
|
|
});
|
|
|
|
test("completed medium score becomes terminal save-only", () => {
|
|
const medium = candidate("medium", "c73cf3cb-b95e-4d1b-94e4-56d7ae067a6b");
|
|
|
|
const result = completeScoreTransition({
|
|
stored: scoringCase(0),
|
|
candidateResult: medium,
|
|
nextVersion: 7,
|
|
});
|
|
|
|
assert.deepEqual(result.turnState?.nextAction, {
|
|
kind: "present_medium_result",
|
|
resultId: medium.resultId,
|
|
});
|
|
assert.equal(result.turnState?.permissions.canConfirmCandidate, false);
|
|
});
|
|
|
|
test("completed high score requests guarded candidate confirmation", () => {
|
|
const high = candidate("high", "3253fca4-e812-4d81-961c-9a6ef680295b");
|
|
|
|
const result = completeScoreTransition({
|
|
stored: scoringCase(0),
|
|
candidateResult: high,
|
|
nextVersion: 7,
|
|
});
|
|
|
|
assert.deepEqual(result.turnState?.nextAction, {
|
|
kind: "request_candidate_confirmation",
|
|
resultId: high.resultId,
|
|
});
|
|
assert.equal(result.turnState?.permissions.canConfirmCandidate, true);
|
|
assert.equal(result.snapshot.state, "confirming");
|
|
});
|