Files
Jyotisha/frontend/tests/rectification-product-inference.test.ts
T
66f087b588 feat(rectification): submit varga-resolution implementation for review
Review-only snapshot for BUG-1115 through BUG-1117; not merge-ready. New opening and append-turn PostgreSQL permission failures remain blocked. Persisted joint replay has zero completed questions; segment ordering remains off by default. The existing offline replay JSON is retained stale and unchanged after a denied overwrite, including its CRLF line endings. Browser/provider validation and final serial gates remain pending. No deployment, role permission changes, or staging/main push.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-01 08:04:04 +08:00

137 lines
9.9 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import { scoreAndPersistCurrentEvidence } from "../src/lib/rectification-agentic/v9/score-persist.ts";
import { buildProductCaseInferenceState } from "../src/lib/rectification-agentic/v9/product-inference.ts";
import { buildCaseInferenceState } from "../src/lib/rectification-agentic/v9/inference-adapter.ts";
import { asInferenceState } from "../src/lib/rectification-agentic/core/compose-receipt.ts";
import { rangeDeliveryForSnapshot } from "../src/lib/rectification-agentic/v9/divergence-panel.ts";
import { productDeliveryForDomain } from "../src/lib/rectification-agentic/v9/product-delivery.ts";
import { parseV9CaseDossier } from "../src/lib/rectification-agentic/v9/tool-service.ts";
import { dossierResponse } from "../src/lib/rectification-agentic/v9/case-dossier-response.ts";
import { decideFromDossier } from "../src/lib/rectification-agentic/v9/decision-from-dossier.ts";
import { latestResultToolProjection } from "../src/mastra/rectification-v9-tools.ts";
import { parseRectificationCandidateResult } from "../src/lib/rectification-candidate-result.ts";
import { deliveryTurnNarration, nonConvergingRangeNarration } from "../src/lib/rectification-agentic/user-copy.ts";
import { buildGoldenLatest } from "./rectification-grounding-support.ts";
import { runV9CandidateScore } from "../src/lib/rectification-agentic/v9/engine-client.ts";
import { refinementFromDecisionReceipt } from "../src/lib/rectification-agentic/v9/refinement-packet.ts";
import { CASE_ID, USER_ID, TURN_ID, computeFixture, dossierFixture, fakeAccounting } from "./rectification-v9-test-support.ts";
// Unmodified real native API captures for a public AA case; persistence doubles
// below are not SQL, Skill-upgrade history or six-question calibration evidence.
const golden = JSON.parse(readFileSync(new URL("./fixtures/varga-api-response.golden.json", import.meta.url), "utf8"));
const req = golden.request;
const range = { start_time: req.start_time, end_time: req.end_time, candidate_intervals: golden.response.decision_receipt.candidate_intervals };
const snapshot = { birth_date: req.birth_date, reported_birth_time: "09:09", active_birth_time: null,
birth_time_source: "approximate", latitude: req.lat, longitude: req.lon, timezone_id: "America/Los_Angeles", timezone_offset: req.tz };
for (const domain of [null, "marriage", "career", "general", "report", "other"] as const) {
for (const scanFails of [false, true]) {
test(`production rescore keeps persisted opt-in delivery boundary: ${domain ?? "legacy-null"}${scanFails ? " with failed scan" : ""}`, async (t) => {
const keys = ["RECTIFICATION_ALGORITHM_VERSION", "RECTIFICATION_DECISION_POLICY_VERSION", "RECTIFICATION_SEGMENT_ORDER"];
const saved = keys.map(key => [key, process.env[key]] as const);
process.env.RECTIFICATION_ALGORITHM_VERSION = golden.response.algorithm_version;
process.env.RECTIFICATION_DECISION_POLICY_VERSION = golden.response.decision_policy_version;
process.env.RECTIFICATION_SEGMENT_ORDER = "on";
t.after(() => { for (const [key, value] of saved) { if (value === undefined) delete process.env[key]; else process.env[key] = value; } });
const requests: string[] = [];
t.mock.method(globalThis, "fetch", async (endpoint: unknown) => {
requests.push(String(endpoint));
if (String(endpoint).includes("varga-segments")) {
assert.ok(domain, "nullable history must not trigger a product segment scan");
if (scanFails) throw new Error("controlled optional scan failure");
return Response.json(golden.scan);
}
return Response.json(golden.response);
});
const raw = dossierFixture({ candidateRange: range, latestResult: null, evidence: req.events.map((event: Record<string, string>) => ({
id: event.id, source_turn_id: TURN_ID, subject: "self", event_kind: event.event_kind, domain: event.domain,
occurred_from: event.date_start, occurred_to: event.date_end, date_precision: event.precision, summary: event.summary,
status: "confirmed", supersedes_evidence_id: null, created_at: "2026-09-30T00:00:00Z",
})) });
Object.assign(raw.case, { rectification_domain: domain });
const accounting = fakeAccounting({
get_agentic_rectification_case_dossier: () => raw,
get_agentic_rectification_case_compute: () => ({ ...computeFixture({ baselineBirthSnapshot: snapshot }), candidate_range: range }),
persist_agentic_rectification_candidate_v2: (_fn, args) => ({
...golden.response.decision_receipt, result_id: args.p_engine_result_id, candidates: args.p_candidates,
algorithm_version: args.p_algorithm_version, decision_policy_version: args.p_decision_policy_version,
decision_receipt: args.p_decision_receipt,
}),
});
const scored = await scoreAndPersistCurrentEvidence({ accounting: accounting.client, userId: USER_ID, caseId: CASE_ID, keepAnswers: false });
const inference = asInferenceState(scored.decisionReceipt.inference_state);
assert.ok(inference);
const packet = rangeDeliveryForSnapshot({ decisionReceipt: scored.decisionReceipt, candidateRange: range });
assert.ok(scored.score.candidates.some(candidate => candidate.rawScore !== undefined && candidate.signature), "raw native audit remains available");
if (!domain) {
assert.equal(inference.segment_summary, undefined);
assert.equal(inference.segment_targets, undefined);
assert.equal(inference.segment_minutes, undefined);
assert.equal(packet.segment_summary, null, "freshly scored legacy packet does not render a new product card");
assert.equal(requests.filter(endpoint => endpoint.includes("varga-segments")).length, 0);
} else {
const targets = domain === "marriage" ? ["D1", "D9"] : domain === "career" ? ["D1", "D10"] : ["D1", "D9", "D10"];
assert.deepEqual(inference.segment_targets, targets);
assert.ok(inference.segment_summary);
assert.deepEqual(packet.segment_summary?.targets, targets);
assert.equal(requests.filter(endpoint => endpoint.includes("varga-segments")).length, 1);
}
const persist = accounting.calls.find(call => call.fn === "persist_agentic_rectification_candidate_v2");
assert.ok(persist);
const savedReceipt = persist.args.p_decision_receipt as Record<string, unknown>;
assert.deepEqual(savedReceipt.inference_state, scored.decisionReceipt.inference_state);
assert.deepEqual(savedReceipt.product_delivery ?? null, productDeliveryForDomain(domain));
assert.deepEqual(packet.product_delivery, productDeliveryForDomain(domain));
const identityGolden = await buildGoldenLatest();
const reloadRaw = dossierFixture({ candidateRange: range, latestResult: { ...identityGolden.latest,
candidates: persist.args.p_candidates, representative_time: scored.score.representativeTime,
decision_receipt: savedReceipt } });
Object.assign(reloadRaw.case, { rectification_domain: domain });
const reloaded = parseV9CaseDossier(reloadRaw)!;
const decision = decideFromDossier(reloaded);
const tools = latestResultToolProjection(reloaded.latestResult as never, decision, productDeliveryForDomain(domain));
const publicDossier = dossierResponse(reloaded, [], { status: "verified", requiresSkillAdoption: false } as never,
{ liveIdentity: { algorithmVersion: identityGolden.scored.algorithmVersion, policyVersion: identityGolden.scored.policyVersion } });
const parsed = parseRectificationCandidateResult(publicDossier.latest_result);
assert.ok(parsed);
assert.deepEqual(parsed.rangeDelivery?.product_delivery, productDeliveryForDomain(domain));
assert.deepEqual(tools.product_delivery, productDeliveryForDomain(domain));
if (domain && scanFails) {
assert.equal(inference.segment_summary?.scan_complete, false);
assert.equal(inference.segment_summary?.no_rectification_needed, false);
assert.equal(inference.segment_summary?.adoption_minute, null);
assert.equal(parsed.rangeDelivery?.segment_summary?.scan_complete, false);
const report = tools.skill_verification_report as { markdown: string; segment_summary: { scan_complete: boolean } };
assert.equal(report.segment_summary.scan_complete, false);
assert.match(report.markdown, /完整窗口扫描暂不可用|完整扫描缺失/);
assert.match(parsed.verificationReportMarkdown!, /只供引擎诊断/);
assert.doesNotMatch(deliveryTurnNarration(decision) + nonConvergingRangeNarration(decision) + report.markdown,
/目前范围|最可能|眼下更像|盘型一致,不用校正/);
}
});
}
}
test("legacy inference clears optional segment carryover without changing frozen minute convergence", async (t) => {
t.mock.method(globalThis, "fetch", async () => Response.json(golden.response));
const score = await runV9CandidateScore({ baselineBirthSnapshot: snapshot, candidateRange: range, events: req.events });
const input = { range, candidates: score.candidates, evidence: [],
probes: refinementFromDecisionReceipt(score.decisionReceipt).discriminating_event_probes };
const legacy = buildProductCaseInferenceState(input, null);
const withoutMetadata = buildCaseInferenceState({ ...input, candidates: input.candidates.map(candidate => {
const minuteCandidate = { ...candidate };
delete minuteCandidate.rawScore;
delete minuteCandidate.signature;
return minuteCandidate;
}) });
assert.deepEqual(legacy, withoutMetadata, "minute prior/posterior, holdout, stops and original probes remain unchanged");
const dirtyPrevious = { ...legacy, segment_targets: ["D1", "D9", "D10"] as const,
segment_minutes: golden.scan.minutes, segment_order_enabled: true, segment_scan_complete: true };
const restored = buildProductCaseInferenceState({ ...input, previous: dirtyPrevious }, null);
assert.equal(restored.segment_summary, undefined);
assert.equal(restored.segment_targets, undefined);
assert.equal(restored.segment_minutes, undefined);
});