import assert from "node:assert/strict"; import test from "node:test"; import { inspectDiscriminatorProbes } from "../src/lib/rectification-agentic/core/candidate-contrast-packet.ts"; import { buildChoiceFrame, serverOwnedChoiceCopy } from "../src/lib/rectification-agentic/v9/choice-card.ts"; import { decideFromDossier, followupAsksRenderableDiscriminator, type DecisionDossier, } from "../src/lib/rectification-agentic/v9/decision-from-dossier.ts"; import { buildMethodFollowupPlan, shouldAttachChoiceFrame } from "../src/lib/rectification-agentic/v9/method-followup.ts"; import { isRenderableProbe, isRenderableStyleOptions, } from "../src/lib/rectification-agentic/v9/probe-question-contract.ts"; import type { DiscriminatingEventProbe } from "../src/lib/rectification-agentic/v9/refinement-packet.ts"; import { d9StyleLabel, d10StyleLabel } from "../src/lib/rectification-agentic/v9/varga-type-tables.ts"; const YEARLESS_LAYERS = [ { layer: "d4", kind: "existence" as const, domain: "relocation", family: "搬家或长期住到外地" }, { layer: "d7", kind: "existence" as const, domain: "family", family: "家人结婚、添丁或住院" }, { layer: "d12", kind: "existence" as const, domain: "family", family: "家人结婚、添丁或住院" }, { layer: "d2", kind: "existence" as const, domain: "finance", family: "收入明显变化、大笔支出或欠债" }, { layer: "d11", kind: "existence" as const, domain: "finance", family: "收入明显变化、大笔支出或欠债" }, { layer: "d30", kind: "existence" as const, domain: "health_pressure", family: "生病、受伤或压力特别大" }, { layer: "d24", kind: "event_quality" as const, domain: "education", family: "学业或考试发挥失常、压力特别大" }, { layer: "d5", kind: "event_quality" as const, domain: "education", family: "学业或考试发挥失常、压力特别大" }, ] as const; const DATED_EXISTENCE: DiscriminatingEventProbe = { year: 2016, year_label: "2016 年前后", domain: "relocation", event_family: "搬家、离乡或长期异地", source: "dasha_activation", tracks: ["vimshottari", "narayana"], tracks_agree: true, unique_minute_claim: false, user_meaning: "年份锁定 2016 年前后。", role: "distinguish", information_gain: 0.8, candidate_ids: ["05:00", "05:20"], expected_outcomes: [ { answer_class: "yes", supports: ["05:00"], conflicts: ["05:20"] }, { answer_class: "no", supports: ["05:20"], conflicts: ["05:00"] }, ], choice_kind: "existence", semantic_key: "relocation.2016.dasha_boundary", }; function yearlessProbe(layer: string, kind: "existence" | "event_quality" | "varga_style", domain: string, family: string): DiscriminatingEventProbe { return { year: 0, year_label: "当前这几个候选", domain: domain as DiscriminatingEventProbe["domain"], event_family: family, source: "dasha_activation", tracks: ["vimshottari", "narayana"], tracks_agree: true, unique_minute_claim: false, user_meaning: "对照分盘差异只作校时方法,不是命运承诺。", role: "distinguish", information_gain: 1.2, candidate_ids: ["05:00", "05:07"], expected_outcomes: [ { answer_class: "yes", supports: ["05:00"], conflicts: ["05:07"] }, { answer_class: "no", supports: ["05:07"], conflicts: ["05:00"] }, ], choice_kind: kind, semantic_key: `varga.${layer}.05:00/05:07`, }; } function contrastFromYearless(layer: string, kind: "existence" | "event_quality" | "varga_style", domain: string, extra: Record = {}) { return { probeId: `contrast:varga.${layer}.05:00/05:07`, candidateSetVersion: "05:00-05:07", question: "当前几个候选还分得开。", expectedOutcomes: [ { outcomeId: "yes", supportsCandidateIds: ["05:00"], conflictsCandidateIds: ["05:07"] }, { outcomeId: "no", supportsCandidateIds: ["05:07"], conflictsCandidateIds: ["05:00"] }, ], candidateSplitHash: `varga.${layer}.05:00/05:07`, informationGain: 1.4, sourceFeatures: [{ technique: layer.toUpperCase(), calculationResultId: null }], domain, year: null as number | null, semanticKey: `varga.${layer}.05:00/05:07`, choiceKind: kind, ...extra, }; } function frameFor(probe: DiscriminatingEventProbe) { return buildChoiceFrame({ method_id: "dasha_events", ask_theme: "dated_event", domain: probe.domain, user_prompt_hint: "unused", choice_kind: probe.choice_kind, semantic_key: probe.semantic_key, style_options: probe.style_options, }, { probes: [probe] }); } test("yearless existence and quality varga layers do not mint a choice frame", () => { for (const row of YEARLESS_LAYERS) { const frame = frameFor(yearlessProbe(row.layer, row.kind, row.domain, row.family)); assert.equal(frame, null, `yearless ${row.layer} should not card`); } }); test("yearless signed D9/D10 varga_style still cards; unsigned varga_style does not", () => { const signed = frameFor({ ...yearlessProbe("d9", "varga_style", "relationship", "相处方式更接近其中一种"), style_options: [ { sign: "天秤座", label: d9StyleLabel("天秤座"), answer_class: "yes" }, { sign: "天蝎座", label: d9StyleLabel("天蝎座"), answer_class: "weak_yes" }, ], }); assert.ok(signed); const copy = serverOwnedChoiceCopy(signed!); assert.ok(copy); assert.equal(isRenderableStyleOptions(copy!.options.map((item) => ({ label: item.label, answer_class: item.answer_class, }))), true); assert.equal(copy!.options.some((item) => item.label.includes("时间吻合") || item.label.includes("这段")), false); assert.equal(signed!.option_a_answer_class, "yes"); assert.equal(signed!.option_b_answer_class, "weak_yes"); const unsigned = frameFor({ ...yearlessProbe("d9", "varga_style", "relationship", "相处方式更接近其中一种"), semantic_key: "varga.d9.05:00/05:07", style_options: [ { label: d9StyleLabel("天秤座"), answer_class: "yes" }, { label: d9StyleLabel("天蝎座"), answer_class: "weak_yes" }, ], }); assert.equal(unsigned, null); const d10 = frameFor({ ...yearlessProbe("d10", "varga_style", "career", "做事风格更接近其中一种"), style_options: [ { sign: "巨蟹座", label: d10StyleLabel("巨蟹座"), answer_class: "yes" }, { sign: "狮子座", label: d10StyleLabel("狮子座"), answer_class: "weak_yes" }, ], }); assert.ok(d10); }); test("dated dasha, age-band, quality, and reserved-event cards still mint", () => { assert.ok(frameFor(DATED_EXISTENCE)); assert.match(frameFor(DATED_EXISTENCE)!.prompt, /2016 年前后/); const month = frameFor({ ...DATED_EXISTENCE, year: 2018, year_label: "2018 年 3 月前后", month: 3, semantic_key: "relocation.2018.03.dasha_boundary", }); assert.ok(month); assert.match(month!.prompt, /2018 年 3 月/); const quality = frameFor({ ...DATED_EXISTENCE, year: 2020, year_label: "2020 年前后", domain: "education", event_family: "学业或考试发挥失常、压力特别大", source: "known_event_quality", choice_kind: "event_quality", semantic_key: "education.2020.known_event_quality", }); assert.ok(quality); assert.match(quality!.prompt, /2020 年前后/); const holdout = buildChoiceFrame({ method_id: "oos_blind", ask_theme: "oos_blind", domain: "family", user_prompt_hint: "unused", choice_kind: "existence", }, { scoring: false, probes: [{ ...DATED_EXISTENCE, year: 2023, year_label: "2023 年前后", domain: "family", event_family: "家人结婚、添丁或住院", user_meaning: "盘外核对:只核对家人事件,不计入候选评分。", semantic_key: "family.2023.holdout", }], }); assert.ok(holdout); }); test("yearless ungrounded probes are dropped with a recognizable reason", () => { const probes = YEARLESS_LAYERS.map((row) => contrastFromYearless(row.layer, row.kind, row.domain)); const inspected = inspectDiscriminatorProbes({ candidateSetVersion: "05:00-05:07", vargaDifferences: [], probes, }); assert.equal(inspected.selected, null); for (const row of YEARLESS_LAYERS) { const dropped = inspected.dropped.find((item) => item.semantic_key === `varga.${row.layer}.05:00/05:07`); assert.ok(dropped, row.layer); assert.equal(dropped!.reason, "yearless_ungrounded_contrast"); } const plan = buildMethodFollowupPlan({ evidence: [ { status: "confirmed", domain: "education", datePrecision: "year", occurredFrom: "2016-01-01", occurredTo: null }, { status: "confirmed", domain: "career", datePrecision: "year", occurredFrom: "2020-01-01", occurredTo: null }, { status: "confirmed", domain: "relationship", datePrecision: "year", occurredFrom: "2024-01-01", occurredTo: null }, { status: "confirmed", domain: "family", datePrecision: "year", occurredFrom: "2021-01-01", occurredTo: null }, ], sessionOutcome: "discriminate_candidates", candidatesSeparated: false, contrastPacket: { candidateSetVersion: "05:00-05:07", vargaDifferences: [], probes }, }); assert.equal(plan.dropped_probes.some((item) => item.reason === "yearless_ungrounded_contrast"), true); }); test("decision and ask layer agree when only yearless ungrounded contrast remains", () => { const probes = YEARLESS_LAYERS.map((row) => contrastFromYearless(row.layer, row.kind, row.domain)); const evidence = [ { id: "e-edu", status: "confirmed", domain: "education", datePrecision: "year" as const, occurredFrom: "2016-01-01", occurredTo: null, eventKind: "education_start" }, { id: "e-career", status: "confirmed", domain: "career", datePrecision: "year" as const, occurredFrom: "2020-01-01", occurredTo: null, eventKind: "career_entry" }, { id: "e-rel", status: "confirmed", domain: "relationship", datePrecision: "year" as const, occurredFrom: "2024-01-01", occurredTo: null, eventKind: "relationship_end" }, ]; const dossier: DecisionDossier = { evidence, conversationSummary: { activeFocus: null, declinedSkippedTopics: [] }, latestResult: { resultId: "55555555-5555-4555-8555-555555555555", candidates: [ { candidateId: "05:00", time: "05:00", rank: 1, relativeSupport: 18 }, { candidateId: "05:07", time: "05:07", rank: 2, relativeSupport: 16 }, ], representativeTime: "05:00", decisionReceipt: { contrast_packet: { candidateSetVersion: "05:00-05:07", vargaDifferences: [], probes }, }, }, case: { acceptedTime: null }, }; const plan = buildMethodFollowupPlan({ evidence, sessionOutcome: "discriminate_candidates", candidatesSeparated: false, contrastPacket: { candidateSetVersion: "05:00-05:07", vargaDifferences: [], probes }, }); const decision = decideFromDossier(dossier); assert.equal(followupAsksRenderableDiscriminator(plan.next_followup), false); assert.notEqual(decision.nextAction, "ask_candidate_discriminator"); assert.equal(decision.probe, null); }); test("yearless cards cannot keep period-presupposing option copy; oos_blind without a year has no frame", () => { const signed = completeAndCheck(); assert.equal(signed, true); assert.equal(shouldAttachChoiceFrame({ intent: "out_of_sample_check", ask_theme: "holdout", source: "oos_blind", }), false); assert.equal(shouldAttachChoiceFrame({ intent: "out_of_sample_check", ask_theme: "holdout", source: "oos_blind", probe_year: 2023, year_label: "2023 年前后", }), true); const plan = buildMethodFollowupPlan({ evidence: [ { status: "confirmed", domain: "education", datePrecision: "year", occurredFrom: "2016-01-01", occurredTo: null }, { status: "confirmed", domain: "career", datePrecision: "year", occurredFrom: "2020-01-01", occurredTo: null }, { status: "confirmed", domain: "relationship", datePrecision: "year", occurredFrom: "2024-01-01", occurredTo: null }, { status: "confirmed", domain: "family", datePrecision: "year", occurredFrom: "2021-01-01", occurredTo: null }, { status: "confirmed", domain: "occupation", datePrecision: "unknown", occurredFrom: null, occurredTo: null, eventKind: "occupation_note" }, ], sessionOutcome: "validate_holdout", oosBlindPrompts: [{ domain: "family", user_meaning: "校时还没用过家人这条线。有没有一件没提过、但记得大概时间的家人变化?", used_for_scoring: false, }], candidatesSeparated: true, }); assert.ok(plan.next_followup); assert.equal(plan.next_followup!.choice_frame, null); assert.equal(plan.next_followup!.source, "oos_blind"); }); function completeAndCheck(): boolean { const renderable = isRenderableProbe({ informationGain: 1.2, candidateIds: ["05:00", "05:07"], expectedOutcomeCount: 2, choiceKind: "varga_style", year: 0, styleOptions: [ { sign: "天秤座", label: d9StyleLabel("天秤座"), answer_class: "yes" }, { sign: "天蝎座", label: d9StyleLabel("天蝎座"), answer_class: "weak_yes" }, ], }); assert.equal(renderable.ok, true); const leaked = isRenderableProbe({ informationGain: 1.2, candidateIds: ["05:00", "05:07"], expectedOutcomeCount: 2, choiceKind: "existence", year: 0, }); assert.equal(leaked.ok, false); assert.equal(leaked.ok ? null : leaked.reason, "yearless_ungrounded_contrast"); return renderable.ok; }