106 lines
3.8 KiB
TypeScript
106 lines
3.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { parseRectificationScoring } from "../src/lib/birth-time-journey-adapters.ts";
|
|
import { projectJourneyTurn } from "../src/lib/birth-time-journey-turn.ts";
|
|
import type { CandidateResult } from "../src/lib/birth-time-evidence.ts";
|
|
|
|
const snapshot = {
|
|
state: "rectifying",
|
|
assistantIntent: "continue_rectification_questions",
|
|
input: "rectification_questions",
|
|
route: "rectification",
|
|
confidence: "low",
|
|
canApply: false,
|
|
activeTime: null,
|
|
reportedRange: { label: "10:00—11:00", startTime: "10:00", endTime: "11:00" },
|
|
} as const;
|
|
|
|
const lowResult: CandidateResult = {
|
|
resultId: "1d8ee348-61a3-433d-8907-ff6d281b9992",
|
|
confidence: "low",
|
|
canApply: false,
|
|
winningSegment: null,
|
|
eventCount: 3,
|
|
domainCount: 3,
|
|
topScore: 8,
|
|
secondScore: 7,
|
|
marginPercent: 12.5,
|
|
reasons: [],
|
|
evidence: [],
|
|
algorithmVersion: "birth-time-event-scoring-v1",
|
|
};
|
|
|
|
const questionnaire = { samples: [
|
|
{ d4Sign: "Aries", d9Sign: "Leo", d10Sign: "Virgo", d24Sign: "Gemini", d30Sign: "Pisces" },
|
|
{ d4Sign: "Aries", d9Sign: "Leo", d10Sign: "Libra", d24Sign: "Gemini", d30Sign: "Pisces" },
|
|
] } as const;
|
|
|
|
const lifeEvents = [
|
|
{ id: "5cb071d6-6d99-46be-85dc-a9bf59ef6ac5", domain: "education", date: "2011", precision: "year" },
|
|
{ id: "0790866c-ad5e-4a45-b2b4-a5c73f6be6ea", domain: "relocation", date: "2019", precision: "year" },
|
|
{ id: "0ef52e51-ab5f-453b-81e5-adb44a929224", domain: "health_pressure", date: "2021", precision: "year" },
|
|
] as const;
|
|
|
|
test("scoring adapter prefers the server-selected next question", () => {
|
|
const scoring = parseRectificationScoring({
|
|
answered_count: 1,
|
|
candidate_cluster_rankings: [],
|
|
next_round: 2,
|
|
next_round_questions: [{ id: "fallback", domain: "career", prompt: "fallback" }],
|
|
next_round_selection: {
|
|
selected_questions: [{ id: "selected", domain: "relationship", prompt: "selected" }],
|
|
},
|
|
});
|
|
|
|
assert.equal(scoring.nextRoundQuestions[0]?.id, "selected");
|
|
assert.equal(scoring.nextRoundQuestions[0]?.domain, "relationship");
|
|
});
|
|
|
|
test("adaptive projection prefers a valid server-selected question", () => {
|
|
const turn = projectJourneyTurn({
|
|
turnVersion: 1,
|
|
snapshot,
|
|
questionnaire,
|
|
persistedProgress: { adaptiveRound: 0, askedDomains: [] },
|
|
candidateResult: lowResult,
|
|
serverSelectedQuestion: { id: "relationship_followup", domain: "relationship" },
|
|
lifeEvents,
|
|
});
|
|
|
|
assert.equal(turn.nextAction.kind, "ask_adaptive_evidence");
|
|
if (turn.nextAction.kind === "ask_adaptive_evidence") {
|
|
assert.equal(turn.nextAction.question.questionId, "relationship_followup");
|
|
assert.equal(turn.nextAction.question.domain, "relationship");
|
|
}
|
|
});
|
|
|
|
test("invalid server domains fall back locally and baseline stays local", () => {
|
|
const adaptive = projectJourneyTurn({
|
|
turnVersion: 1,
|
|
snapshot,
|
|
questionnaire,
|
|
persistedProgress: { adaptiveRound: 0, askedDomains: [] },
|
|
candidateResult: lowResult,
|
|
serverSelectedQuestion: { id: "invalid", domain: "unsupported" },
|
|
lifeEvents,
|
|
});
|
|
assert.equal(adaptive.nextAction.kind, "ask_adaptive_evidence");
|
|
if (adaptive.nextAction.kind === "ask_adaptive_evidence") {
|
|
assert.equal(adaptive.nextAction.question.domain, "career");
|
|
}
|
|
|
|
const baseline = projectJourneyTurn({
|
|
turnVersion: 0,
|
|
snapshot: { ...snapshot, confidence: null },
|
|
questionnaire,
|
|
persistedProgress: { adaptiveRound: 0, askedDomains: [] },
|
|
candidateResult: null,
|
|
serverSelectedQuestion: { id: "relationship_followup", domain: "relationship" },
|
|
lifeEvents: lifeEvents.slice(0, 1),
|
|
});
|
|
assert.equal(baseline.nextAction.kind, "ask_baseline_evidence");
|
|
if (baseline.nextAction.kind === "ask_baseline_evidence") {
|
|
assert.equal(baseline.nextAction.question.domain, "career");
|
|
}
|
|
});
|