Files
Jyotisha/frontend/tests/rectification-engine-convergence.test.ts
T
Jesse_Chen c48a965640
Independent Staging Quality Gate / validate (pull_request) Failing after 6m13s
Independent Staging Quality Gate / publish (pull_request) Has been skipped
fix(rectification): close round A/2 tail gaps in tests, CI, and stale-score reuse
Window_scan assertions now match the public from_sign/to_sign contract, the
staging quick gate runs the rectification Python suite, and compare-candidates
rescores when stored policy lags the live engine identity.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 18:17:33 +08:00

218 lines
7.8 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync, readdirSync, statSync } from "node:fs";
import { join } from "node:path";
import test from "node:test";
import { answersFromEvidence } from "../src/lib/rectification-agentic/core/build-state.ts";
import {
classifySnapshotStaleReason,
storedSnapshotIsCurrent,
type CandidateSnapshotSource,
} from "../src/lib/rectification-agentic/core/snapshot-source.ts";
import type { ConflictProbe } from "../src/lib/rectification-agentic/core/types.ts";
import { contrastPacketFromLatestResult } from "../src/lib/rectification-agentic/v9/decision-from-dossier.ts";
import {
cachedEngineScoreIsReusable,
liveEngineScoringIdentityFromEnv,
} from "../src/lib/rectification-agentic/v9/engine-client.ts";
import {
parseDiscriminatingEventProbes,
parseProspectiveProbes,
prospectiveWindowsNarration,
} from "../src/lib/rectification-agentic/v9/refinement-packet.ts";
const OUTCOMES = [
{ answer_class: "yes" as const, supports: ["05:00"], conflicts: ["05:07"] },
{ answer_class: "no" as const, supports: ["05:07"], conflicts: ["05:00"] },
];
function source(overrides: Partial<CandidateSnapshotSource> = {}): CandidateSnapshotSource {
return {
birthProfileFingerprint: "birth-a",
scoreableEvidenceFingerprint: "score-a",
inferenceRevision: 3,
candidateSetVersion: "set-a",
scoringPolicyVersion: "rectification-candidate-policy-v3",
...overrides,
};
}
function qualityProbe(overrides: Record<string, unknown> = {}) {
return {
year: 2016,
year_label: "2016 年 9 月",
domain: "education",
event_family: "学业或考试发挥失常、压力特别大",
source: "known_event_quality",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "2016 年 9 月那次上大学,更接近哪一种实际体验。",
role: "distinguish",
phase: "candidate_discriminator",
semantic_key: "education.2016.known_event_quality",
information_gain: 0.42,
candidate_split_hash: "quality-split",
candidate_set_version: "set-a",
candidate_ids: ["05:00", "05:07"],
expected_outcomes: OUTCOMES,
choice_kind: "event_quality",
question_contract_version: "probe-question-v1",
target_evidence_id: "00000000-0000-4000-8000-000000000001",
display_date_label: "2016 年 9 月",
...overrides,
};
}
function walkFiles(root: string, suffixes: readonly string[]): string[] {
const skip = new Set(["node_modules", ".next", "dist"]);
const out: string[] = [];
const visit = (dir: string) => {
for (const name of readdirSync(dir)) {
if (skip.has(name)) continue;
const path = join(dir, name);
const stat = statSync(path);
if (stat.isDirectory()) visit(path);
else if (suffixes.some((suffix) => name.endsWith(suffix))) out.push(path);
}
};
visit(root);
return out;
}
test("scoring policy version changes stale stored snapshots", () => {
const current = source();
const previous = source({ scoringPolicyVersion: "rectification-candidate-policy-v2" });
assert.equal(classifySnapshotStaleReason(previous, current), "scoring_policy_changed");
assert.equal(storedSnapshotIsCurrent(previous, current), false);
assert.equal(storedSnapshotIsCurrent(current, current), true);
});
test("matching fingerprints still rescore when stored policy lags the live engine", () => {
const fingerprints = {
evidenceLedgerFingerprint: "b".repeat(64),
candidateRangeFingerprint: "c".repeat(64),
};
const stored = {
...fingerprints,
algorithmVersion: "rectification-v5-matrix-scoring-6",
policyVersion: "rectification-candidate-policy-v2",
};
assert.equal(
cachedEngineScoreIsReusable(stored, fingerprints, {
algorithmVersion: "rectification-v5-matrix-scoring-6",
policyVersion: "rectification-candidate-policy-v2",
}),
true,
);
assert.equal(
cachedEngineScoreIsReusable(stored, fingerprints, {
algorithmVersion: "rectification-v5-matrix-scoring-7",
policyVersion: "rectification-candidate-policy-v3",
}),
false,
);
const fromEnv = liveEngineScoringIdentityFromEnv({
RECTIFICATION_ENGINE_VERSION: "rectification-v5",
RECTIFICATION_DECISION_POLICY_VERSION: "rectification-candidate-policy-v3",
});
assert.equal(fromEnv.algorithmVersion, null);
assert.equal(fromEnv.policyVersion, "rectification-candidate-policy-v3");
assert.equal(cachedEngineScoreIsReusable(stored, fingerprints, fromEnv), false);
});
test("anchored known_event_quality distinguish probes stay in the public packet", () => {
const parsed = parseDiscriminatingEventProbes([qualityProbe()]);
assert.equal(parsed.length, 1);
assert.equal(parsed[0]?.source, "known_event_quality");
assert.equal(parsed[0]?.role, "distinguish");
assert.equal(parsed[0]?.target_evidence_id, "00000000-0000-4000-8000-000000000001");
const unanchored = parseDiscriminatingEventProbes([qualityProbe({ target_evidence_id: undefined })]);
assert.equal(unanchored.length, 0);
const packet = contrastPacketFromLatestResult({
resultId: "result-a",
decisionReceipt: {
discriminating_event_probes: [qualityProbe()],
inference_state: {
probes: [{
id: "probe:education.2016.known_event_quality:quality-split",
semantic_key: "education.2016.known_event_quality",
candidate_split_hash: "quality-split",
domain: "education",
year: 2016,
question: "2016 年 9 月那次上大学,更接近哪一种实际体验。",
candidate_ids: ["05:00", "05:07"],
expected_outcomes: OUTCOMES,
information_gain: 0.42,
source: "known_event_quality",
choice_kind: "event_quality",
target_evidence_id: "00000000-0000-4000-8000-000000000001",
}],
answered_probes: [],
},
},
});
assert.equal(
packet.probes.some((item) => (
item.semanticKey === "education.2016.known_event_quality"
|| item.choiceKind === "event_quality"
)),
true,
);
});
test("quality answers are not inferred from event existence alone", () => {
const probe: ConflictProbe = {
id: "probe-quality",
semantic_key: "education.2016.known_event_quality",
candidate_split_hash: "quality-split",
domain: "education",
year: 2016,
question: "那次上大学更接近哪一种体验",
candidate_ids: ["05:00", "05:07"],
expected_outcomes: OUTCOMES,
information_gain: 0.42,
source: "known_event_quality",
choice_kind: "event_quality",
};
const answers = answersFromEvidence([probe], [{
id: "00000000-0000-4000-8000-000000000001",
domain: "education",
year: 2016,
precision: "month",
}]);
assert.equal(answers.length, 0);
});
test("prospective probes stay out of scoring copy", () => {
const parsed = parseProspectiveProbes([{
candidate_label: "A",
domain: "career",
window_label: "2027 年 3 月附近",
user_meaning: "候选 A 预测下一次事业变动更可能在 2027 年 3 月附近。这是预测窗口,不是承诺;下次发生时回来补一条,可进一步分辨。",
used_for_scoring: false,
}]);
assert.equal(parsed.length, 1);
const copy = prospectiveWindowsNarration(parsed);
assert.match(String(copy), /预测窗口/);
assert.equal(parsed[0]?.used_for_scoring, false);
});
test("scripts and frontend contain no answer-key literals", () => {
const forbidden = ["target" + "_minute", "pl9_" + "1993", "regression" + "_only"];
const files = [
...walkFiles(join(process.cwd(), "src"), [".ts", ".tsx", ".js"]),
...walkFiles(join(process.cwd(), "tests"), [".ts", ".tsx"]),
];
const hits: string[] = [];
for (const file of files) {
const text = readFileSync(file, "utf8");
for (const token of forbidden) {
if (text.includes(token)) hits.push(`${file}:${token}`);
}
}
assert.deepEqual(hits, []);
});