- open_agentic_rectification_case_v2 (12 args) becomes SECURITY INVOKER: the immutable-skill ACL reconciliation leaves EXECUTE on the 11-arg open only to service_role, so the definer wrapper hit 42501 on every homepage/new open. - The pending-opening read moves to owner function agentic_rectification_opening_pending_v1, granted to service_role only. - History test and persisted replay harness append turns through the V10 request-idempotent overload; the V9 overload is revoked from service_role. - Opening test fixture adds the required birth_time_source. - Segment migrations renamed to 20261001* so they sort after staging's 20260930* migrations on both fresh and existing databases. - Stale Windows replay replaced with the production-path replay (M1/M2 equal to accepted research, implementation_identity included). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
138 lines
9.6 KiB
TypeScript
138 lines
9.6 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
import { createElement } from "react";
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
import { RectificationRangeDelivery } from "../src/components/rectification-range-delivery.tsx";
|
|
import { parseRectificationCandidateResult } from "../src/lib/rectification-candidate-result.ts";
|
|
import { buildRectificationTimeline } from "../src/lib/rectification-timeline-scale.ts";
|
|
import { deliveryTurnNarration, nonConvergingRangeNarration } from "../src/lib/rectification-agentic/user-copy.ts";
|
|
import { buildProductCaseInferenceState } from "../src/lib/rectification-agentic/v9/product-inference.ts";
|
|
import { productDeliveryForDomain, parseProductDelivery } from "../src/lib/rectification-agentic/v9/product-delivery.ts";
|
|
import { runV9CandidateScore } from "../src/lib/rectification-agentic/v9/engine-client.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 { parseV9CaseDossier } from "../src/lib/rectification-agentic/v9/tool-service.ts";
|
|
import { dossierFixture } from "./rectification-v9-test-support.ts";
|
|
import { buildGoldenLatest } from "./rectification-grounding-support.ts";
|
|
|
|
// Unmodified native API capture; absent/partial scans are fault-injection
|
|
// controls. These test real projection/render/copy, not SQL or calibration.
|
|
const golden = JSON.parse(readFileSync(new URL("./fixtures/varga-api-response.golden.json", import.meta.url), "utf8"));
|
|
|
|
for (const domain of [null, "marriage", "career", "general", "report", "other"] as const) {
|
|
for (const scan of ["missing", "partial", "complete"] as const) {
|
|
test(`actual product delivery keeps ${domain ?? "legacy-null"} separate with ${scan} scan`, async (t) => {
|
|
t.mock.method(globalThis, "fetch", async () => Response.json(golden.response));
|
|
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 score = await runV9CandidateScore({ baselineBirthSnapshot: {
|
|
birth_date: req.birth_date, latitude: req.lat, longitude: req.lon, timezone_offset: req.tz,
|
|
}, candidateRange: range, events: req.events });
|
|
const identityGolden = await buildGoldenLatest();
|
|
const inference = buildProductCaseInferenceState({ range, candidates: score.candidates, evidence: [], probes: [],
|
|
...(scan === "complete" ? { segmentMinutes: golden.scan.minutes, segmentScanComplete: true } : {}),
|
|
segmentTargets: productDeliveryForDomain(domain)?.targets,
|
|
}, domain);
|
|
const withoutScan = { ...inference };
|
|
delete withoutScan.segment_summary;
|
|
delete withoutScan.segment_minutes;
|
|
delete withoutScan.segment_targets;
|
|
delete withoutScan.segment_scan_complete;
|
|
delete withoutScan.segment_order_enabled;
|
|
const receipt = { ...score.decisionReceipt, inference_state: scan === "missing" ? withoutScan : inference };
|
|
const raw = dossierFixture({ candidateRange: range, latestResult: { ...identityGolden.latest,
|
|
candidates: score.candidates.map(candidate => ({ ...candidate, candidate_id: candidate.candidateId, time: candidate.time,
|
|
rank: candidate.rank, relative_support: candidate.relativeSupport, tied_minute_count: candidate.tiedMinuteCount })),
|
|
representative_time: score.representativeTime, decision_receipt: receipt,
|
|
} });
|
|
Object.assign(raw.case, { rectification_domain: domain });
|
|
const dossier = parseV9CaseDossier(raw)!;
|
|
const publicDossier = dossierResponse(dossier, [], { status: "verified", requiresSkillAdoption: false } as never,
|
|
{ liveIdentity: { algorithmVersion: identityGolden.scored.algorithmVersion, policyVersion: identityGolden.scored.policyVersion } });
|
|
const projected = publicDossier.latest_result!;
|
|
const parsed = parseRectificationCandidateResult(projected);
|
|
assert.ok(parsed);
|
|
const delivery = parsed.rangeDelivery!;
|
|
const decision = decideFromDossier(dossier);
|
|
const markup = renderToStaticMarkup(createElement(RectificationRangeDelivery, { result: parsed,
|
|
acceptingCandidateId: null, readonly: false, onAccept: () => assert.fail("render cannot adopt") }));
|
|
const timeline = buildRectificationTimeline({ searchWindow: [range.start_time, range.end_time],
|
|
candidateTimes: parsed.candidates.map(candidate => candidate.time), credibleRange: parsed.credibleRange,
|
|
stage: "minute", workingTime: parsed.representativeTime, segmentSummary: delivery.segment_summary,
|
|
productDelivery: delivery.product_delivery });
|
|
const narration = deliveryTurnNarration(decision);
|
|
const stopped = nonConvergingRangeNarration(decision);
|
|
const report = parsed.verificationReportMarkdown ?? "";
|
|
if (domain === null) {
|
|
assert.equal(delivery.product_delivery, null);
|
|
assert.equal(delivery.segment_summary, null);
|
|
assert.match(markup, /目前范围/);
|
|
assert.doesNotMatch(markup, /用哪张盘解读/);
|
|
assert.doesNotMatch(narration + stopped + report, /上升盘型暂未知|representative_diagnostic_not_adopted_chart/);
|
|
} else {
|
|
assert.deepEqual(delivery.product_delivery, productDeliveryForDomain(domain));
|
|
assert.match(markup, /用哪张盘解读/);
|
|
assert.doesNotMatch(markup, /最可能/);
|
|
assert.doesNotMatch(narration + stopped + timeline?.workingLabel, /目前范围|眼下更像|代表分钟 \d/);
|
|
assert.match(report, /只供引擎诊断/);
|
|
const nestedMissing = { ...delivery };
|
|
delete nestedMissing.product_delivery;
|
|
const recovered = parseRectificationCandidateResult({ ...projected, rangeDelivery: nestedMissing });
|
|
assert.deepEqual(recovered?.rangeDelivery?.product_delivery, productDeliveryForDomain(domain), "persisted identity survives missing nested contract");
|
|
const wrongSummary = delivery.segment_summary ? { ...delivery.segment_summary, targets: ["D1"] } : null;
|
|
const mismatch = parseRectificationCandidateResult({ ...projected, rangeDelivery: { ...delivery, segment_summary: wrongSummary } });
|
|
assert.equal(mismatch?.rangeDelivery?.segment_summary, null, "mismatched targets cannot render or adopt a product summary");
|
|
assert.deepEqual(mismatch?.rangeDelivery?.product_delivery, productDeliveryForDomain(domain));
|
|
const explicitlyLegacy = parseRectificationCandidateResult({ ...projected, productDelivery: null });
|
|
assert.equal(explicitlyLegacy?.rangeDelivery?.product_delivery, null, "explicit server legacy null overrides receipt and nested opt-in identity");
|
|
assert.equal(explicitlyLegacy?.rangeDelivery?.segment_summary, null);
|
|
if (scan === "missing") {
|
|
assert.equal(delivery.segment_summary, null);
|
|
assert.match(markup + narration + stopped + timeline?.workingLabel + report, /上升盘型暂未知/);
|
|
assert.doesNotMatch(markup, /<button|分盘解读需要更准的出生时间/);
|
|
} else {
|
|
assert.ok(delivery.segment_summary);
|
|
assert.equal(delivery.segment_summary.scan_complete, scan === "complete");
|
|
assert.deepEqual(delivery.segment_summary.targets, productDeliveryForDomain(domain)?.targets);
|
|
if (scan === "partial") {
|
|
assert.match(markup, /候选盘型不能证明全窗一致/);
|
|
for (const copy of [narration, stopped, timeline?.workingLabel ?? "", report]) {
|
|
assert.match(copy, /完整窗口扫描暂不可用/);
|
|
assert.match(copy, /仅是候选盘型,不能证明全窗一致/);
|
|
}
|
|
assert.equal(delivery.segment_summary.adoption_minute, null);
|
|
assert.doesNotMatch(markup, /<button/);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
test("product identity covers every SQL-legal persisted domain without opting legacy in", () => {
|
|
const sql = readFileSync(new URL("../supabase/migrations/20261001020000_rectification_segment_checks.sql", import.meta.url), "utf8");
|
|
const domainRows = ["general", "report", "education", "career", "relationship", "marriage", "relocation", "finance", "health", "family", "other"];
|
|
assert.deepEqual([...sql.matchAll(/p_(?:product_)?domain not in \(([^)]+)\)/g)].map(match =>
|
|
[...match[1].matchAll(/'([^']+)'/g)].map(domain => domain[1])), [domainRows, domainRows]);
|
|
for (const domain of domainRows) {
|
|
const targets = ["marriage", "relationship"].includes(domain) ? ["D1", "D9"]
|
|
: domain === "career" ? ["D1", "D10"] : ["D1", "D9", "D10"];
|
|
const expected = { contract: "segment-product-v1", domain, targets };
|
|
assert.deepEqual(productDeliveryForDomain(domain), expected);
|
|
assert.deepEqual(parseProductDelivery(expected), expected);
|
|
}
|
|
assert.equal(productDeliveryForDomain(null), null);
|
|
assert.equal(productDeliveryForDomain(undefined), null);
|
|
assert.equal(productDeliveryForDomain("invented"), null);
|
|
});
|
|
|
|
test("product delivery parser accepts only the persisted domain target contract", () => {
|
|
assert.equal(parseProductDelivery(null), null);
|
|
assert.equal(parseProductDelivery({ contract: "segment-product-v1", domain: "career", targets: ["D1", "D9"] }), null);
|
|
assert.equal(parseProductDelivery({ contract: "segment-product-v1", domain: "general", targets: ["D1", "D7"] }), null);
|
|
assert.equal(parseProductDelivery({ contract: "segment-product-v1", domain: "invented", targets: ["D1"] }), null);
|
|
assert.deepEqual(parseProductDelivery(productDeliveryForDomain("marriage")), productDeliveryForDomain("marriage"));
|
|
});
|