import assert from "node:assert/strict"; import test from "node:test"; import { EXISTENCE_STYLE_OPTIONS, QUALITY_STYLE_OPTIONS, QUESTION_CONTRACT_VERSION, completeStyleOptions, isRenderableProbe, rankDiscriminatorScore, } from "../src/lib/rectification-agentic/v9/probe-question-contract.ts"; test("existence probes complete to four answer classes without engine style_options", () => { const completed = completeStyleOptions({ choiceKind: "existence" }); assert.deepEqual(completed, [...EXISTENCE_STYLE_OPTIONS]); assert.equal(QUESTION_CONTRACT_VERSION, "probe-question-v1"); }); test("event_quality probes use quality labels and still cover unsure", () => { const completed = completeStyleOptions({ choiceKind: "event_quality" }); assert.deepEqual(completed, [...QUALITY_STYLE_OPTIONS]); assert.equal(completed?.some((item) => item.answer_class === "unsure"), true); }); test("varga-style probes stay dynamic and fail closed without two scoring labels", () => { assert.equal(completeStyleOptions({ choiceKind: "varga_style", styleOptions: [{ label: "巨蟹相处主动热情", answer_class: "yes" }], }), null); const completed = completeStyleOptions({ choiceKind: "varga_style", styleOptions: [ { label: "巨蟹相处主动热情", answer_class: "yes", sign: "巨蟹" }, { label: "狮子独立强势", answer_class: "weak_yes", sign: "狮子" }, ], }); assert.equal(completed?.length, 4); assert.equal(completed?.find((item) => item.answer_class === "no")?.label, "都不是这些特质"); assert.equal(completed?.find((item) => item.answer_class === "unsure")?.label, "这段记不清楚"); }); test("illegal clock or appearance copy cannot become a renderable probe", () => { assert.equal(isRenderableProbe({ informationGain: 1.2, candidateIds: ["05:00", "05:04"], expectedOutcomeCount: 2, choiceKind: "existence", styleOptions: [ { label: "08:12 左右发生", answer_class: "yes" }, ], }), true); assert.equal(completeStyleOptions({ choiceKind: "existence", styleOptions: [{ label: "08:12 左右发生", answer_class: "yes" }], })?.find((item) => item.answer_class === "yes")?.label, "明确发生且时间吻合"); assert.equal(isRenderableProbe({ informationGain: 1.2, candidateIds: ["05:00", "05:04"], expectedOutcomeCount: 2, choiceKind: "varga_style", styleOptions: [ { label: "外貌更接近第一种", answer_class: "yes" }, { label: "相处更独立", answer_class: "weak_yes" }, ], }), false); }); test("asked probes keep a novelty penalty so unused high-gain probes rank first", () => { const askedCareer = rankDiscriminatorScore({ informationGain: 0.56, asked: true, candidateIds: ["05:00", "05:07"], }); const unusedD24 = rankDiscriminatorScore({ informationGain: 2.5, asked: false, candidateIds: ["05:00", "05:07", "05:10"], }); assert.ok(unusedD24 > askedCareer); assert.ok(unusedD24 > 0.56); });