Files
Jyotisha/frontend/tests/rectification-yearless-ungrounded.test.ts
T
Jesse_Chen b43808b016
Independent Staging Quality Gate / validate (push) Successful in 9m10s
Independent Staging Quality Gate / publish (push) Successful in 8m43s
fix(rectification): stop yearless ungrounded varga contrast from minting cards
Only sign-bound varga_style questions may omit a concrete period. Remaining-layer existence and quality probes now drop as yearless_ungrounded_contrast instead of scoring by group order.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-30 10:55:11 +08:00

319 lines
13 KiB
TypeScript

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<string, unknown> = {}) {
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;
}