import { z } from "zod"; import { AnalysisReviewError, canonicalJson, createAnalysisReference, isDiagnosticPlainRecord, isDiagnosticToken, isVerifiedReviewPlanReplay, replayReviewPlanRun, validateReviewPlanReplayRequest, REVIEW_PLAN_REPLAY_LIMITS, validateReviewSensitivityReplayInput, validateReviewSensitivityGridReplayInput, validateReviewSensitivityRequest, validateReviewSensitivityGridRequest, replayReviewSensitivity, replayReviewSensitivityGrid, snapshotDiagnosticJson, type AnalysisReviewFinding, type ReviewPlanRun, type ReviewPlanReplay, type ReviewSensitivity, type ReviewSensitivityGrid } from "@actuarial-ts/core"; import { parseReviewBoundary } from "./reviewBoundary.js"; import { replayDiagnosticSuite, validateDiagnosticSuiteReplayInput, assessDiagnosticSuiteInput } from "./diagnosticSuite.js"; import { reviewPlanReplayRequestSchema } from "./reviewPlanReplayContracts.js"; import { reviewSourcePathSchema, reviewSourceValueAt } from "./reviewSourceDecoding.js"; import { DATA_PACKAGE_VERSION } from "./version.js"; import { REVIEW_STUDY_COLLECTION_CONTRACT_VERSION, REVIEW_STUDY_COLLECTION_LIMITS, type ReviewStudyAttachment, type ReviewStudyBindingEvidence, type ReviewStudyCollection, type ReviewStudyCollectionRequest, type ReviewStudyExecutionRequest, type ReviewStudyReplayRequest, type ReviewStudyExecutionPreflight } from "./reviewStudyTypes.js"; import { reviewStudyFindings } from "./reviewStudyFindings.js"; import type { DiagnosticSuiteResult } from "./diagnosticSuiteTypes.js"; const token = z.string().refine(isDiagnosticToken), object = z.custom>(isDiagnosticPlainRecord); const related = z.object({ kind: z.literal("declared-related"), rationale: token }).strict(); const scenarioBinding = z.union([z.object({ kind: z.literal("review-baseline") }).strict(), related]); const common = { id: token, rationale: token }; export const reviewStudyAttachmentSchema: z.ZodType = z.discriminatedUnion("kind", [ z.object({ ...common, kind: z.literal("sensitivity"), result: z.custom(isDiagnosticPlainRecord), binding: scenarioBinding }).strict(), z.object({ ...common, kind: z.literal("sensitivity-grid"), result: z.custom(isDiagnosticPlainRecord), binding: scenarioBinding }).strict(), z.object({ ...common, kind: z.literal("diagnostic-suite"), result: z.custom(isDiagnosticPlainRecord), binding: z.object({ models: z.array(z.object({ subject: token, target: z.union([z.object({ kind: z.literal("review-model"), node: token }).strict(), related]) }).strict()).max(16), datasets: z.array(z.object({ subject: token, target: z.union([z.object({ kind: z.literal("review-input"), node: token, path: reviewSourcePathSchema }).strict(), related]) }).strict()).max(16), }).strict() }).strict(), ]); const limitsSchema = z.object({ maximumAttachments: z.number().int().positive().max(REVIEW_STUDY_COLLECTION_LIMITS.maximumAttachments), maximumGraphRuns: z.number().int().positive().max(REVIEW_STUDY_COLLECTION_LIMITS.maximumGraphRuns), maximumDiagnosticModels: z.number().int().positive().max(REVIEW_STUDY_COLLECTION_LIMITS.maximumDiagnosticModels), maximumDiagnosticRows: z.number().int().positive().max(REVIEW_STUDY_COLLECTION_LIMITS.maximumDiagnosticRows), maximumInputCharacters: z.number().int().positive().max(REVIEW_STUDY_COLLECTION_LIMITS.maximumInputCharacters), maximumOutputCharacters: z.number().int().positive().max(REVIEW_STUDY_COLLECTION_LIMITS.maximumOutputCharacters), }).strict(); export const reviewStudyCollectionRequestSchema: z.ZodType = z.object({ id: token, version: token, attachments: z.array(reviewStudyAttachmentSchema).min(1).max(REVIEW_STUDY_COLLECTION_LIMITS.maximumAttachments), limits: limitsSchema }).strict(); const same = (a: unknown, b: unknown) => canonicalJson(a) === canonicalJson(b); function invalid(message: string, path = "$", code = "REVIEW_STUDY_INVALID"): never { throw new AnalysisReviewError([{ code, path, message, remedies: ["Retain exact study evidence and explicitly bind each subject or declare its related-evidence limitation"] }]); } function distinct(values: readonly string[], expected?: readonly string[], path = "$.attachments"): void { if (new Set(values).size !== values.length || expected && !same([...values].sort(), [...expected].sort())) invalid("Bindings must identify every distinct study subject exactly once", path); } function checkReview(replay: ReviewPlanReplay): void { if (!isVerifiedReviewPlanReplay(replay)) invalid("A study collection requires an authentic current-process review replay; reopen the saved graph first", "$.review"); } function budget(request: ReviewStudyCollectionRequest): ReviewStudyCollection["execution"] { const limits = request.limits; if (request.attachments.length > limits.maximumAttachments || canonicalJson(request).length > limits.maximumInputCharacters) invalid("Study collection exceeds its declared attachment/input budget", "$.limits", "RESOURCE_LIMIT_EXCEEDED"); let graphRunCeiling = 0, diagnosticModels = 0, diagnosticRows = 0; for (const attachment of request.attachments) { const value = attachment.result; if (attachment.kind === "diagnostic-suite") { const suite = attachment.result.request; if (!suite || !Array.isArray(suite.models) || !Array.isArray(suite.datasets)) invalid("Malformed diagnostic suite request"); diagnosticModels += suite.models.length; for (const dataset of suite.datasets) { if (!Array.isArray(dataset?.input?.losses) || dataset.input.exposures !== undefined && !Array.isArray(dataset.input.exposures)) invalid("Malformed diagnostic dataset"); diagnosticRows += dataset.input.losses.length + (dataset.input.exposures?.length ?? 0); } } else { const ceiling = isDiagnosticPlainRecord(value.request) && isDiagnosticPlainRecord(value.request.limits) && "maximumRuns" in value.request.limits ? value.request.limits.maximumRuns : null; if (typeof ceiling !== "number" || !Number.isSafeInteger(ceiling) || ceiling < 1 || ceiling > 64) invalid("A scenario study requires its bounded native run ceiling"); graphRunCeiling += ceiling; } } if (graphRunCeiling > limits.maximumGraphRuns || diagnosticModels > limits.maximumDiagnosticModels || diagnosticRows > limits.maximumDiagnosticRows) invalid("Study collection exceeds its aggregate native execution budgets", "$.limits", "RESOURCE_LIMIT_EXCEEDED"); return { graphRunCeiling, diagnosticModels, diagnosticRows }; } function bindingsFor(attachment: ReviewStudyAttachment, replay: Pick): readonly ReviewStudyBindingEvidence[] { const evidence: ReviewStudyBindingEvidence[] = []; const addRelated = (kind: ReviewStudyBindingEvidence["subject"]["kind"], id: string, rationale: string) => evidence.push({ attachment: attachment.id, subject: { kind, id }, status: "declared-related", target: null, node: null, path: null, qualification: `Caller-declared related evidence; no exact review-subject binding is established: ${rationale}` }); if (attachment.kind !== "diagnostic-suite") { if (attachment.binding.kind === "declared-related") addRelated("baseline", attachment.result.request.baseline.id, attachment.binding.rationale); else { const saved = attachment.result; if (!Number.isSafeInteger(saved.baseline) || saved.baseline < 0 || !Array.isArray(saved.runs) || !isDiagnosticPlainRecord(saved.runs[saved.baseline]?.run)) invalid("Study baseline must identify an actual retained run", "$.result.baseline"); const baseline = atStudy("$.result.runs[" + saved.baseline + "]", () => validateReviewPlanReplayRequest({ run: saved.runs[saved.baseline]!.run, limits: REVIEW_PLAN_REPLAY_LIMITS })); if (!same(baseline.plan, replay.run.plan) || !same(baseline.nodes.map((item) => item.result), replay.run.nodes.map((item) => item.result)) || !same(baseline.outputs, replay.run.outputs)) invalid("Study baseline differs from the exact review graph or its native calculations", "$.binding", "REVIEW_STUDY_BINDING_MISMATCH"); evidence.push({ attachment: attachment.id, subject: { kind: "baseline", id: baseline.plan.plan.id }, status: "exact-review-baseline", target: replay.source, node: null, path: null, qualification: "Exact authored graph and native results; cache/execution metadata is not independently replayed" }); } return evidence; } distinct(attachment.binding.models.map((item) => item.subject), attachment.result.request.models.map((item) => item.id), "$.binding.models"); distinct(attachment.binding.datasets.map((item) => item.subject), attachment.result.request.datasets.map((item) => item.id), "$.binding.datasets"); for (const item of attachment.binding.models) { if (item.target.kind === "declared-related") { addRelated("model", item.subject, item.target.rationale); continue; } const target = item.target, node = replay.run.nodes.find((entry) => entry.result.node.id === target.node)?.result; const output = node?.status === "completed" ? node.outputs.find((out) => out.port === "model") : undefined; const model = attachment.result.request.models.find((model) => model.id === item.subject)!; if (output?.port !== "model" || !same(model.request.run, output.value)) invalid("Diagnostic model subject differs from the named review model", "$.binding.models", "REVIEW_STUDY_BINDING_MISMATCH"); evidence.push({ attachment: attachment.id, subject: { kind: "model", id: item.subject }, status: "exact-review-model", target: output.value.reference, node: target.node, path: null, qualification: "Exact native model result; diagnostic adequacy and calibration independence are not implied" }); } for (const item of attachment.binding.datasets) { if (item.target.kind === "declared-related") { addRelated("dataset", item.subject, item.target.rationale); continue; } const target = item.target, node = replay.run.nodes.find((entry) => entry.result.node.id === target.node)?.result; const dataset = attachment.result.request.datasets.find((dataset) => dataset.id === item.subject)!; if (!node || node.status !== "completed" || !same(reviewSourceValueAt(node.node.input, target.path), dataset.input)) invalid("Diagnostic dataset differs from the exact retained graph input", "$.binding.datasets", "REVIEW_STUDY_BINDING_MISMATCH"); evidence.push({ attachment: attachment.id, subject: { kind: "dataset", id: item.subject }, status: "exact-retained-input", target: node.reference, node: target.node, path: target.path, qualification: "Exact retained diagnostic input; use in a model fit and cross-population comparability are not inferred" }); } return evidence; } function located(findings: readonly AnalysisReviewFinding[], path: string, attachment?: string): AnalysisReviewFinding[] { return findings.map((finding) => ({ ...finding, path: `${path}${finding.path.startsWith("$") ? finding.path.slice(1) : finding.path.startsWith("input") ? finding.path.slice(5) : `.${finding.path}`}`, ...(attachment ? { coordinates: { ...finding.coordinates, attachment } } : {}) })); } function atStudy(path: string, execute: () => T, attachment?: string): T { try { return execute(); } catch (error) { if (!(error instanceof AnalysisReviewError)) throw error; throw new AnalysisReviewError(located(error.findings, path, attachment)); } } /** Shared structural preparation. Comparing retained bytes does not authenticate their numerical claims. */ function prepareCollection(input: unknown, review: Pick) { const request = snapshotDiagnosticJson(parseReviewBoundary(reviewStudyCollectionRequestSchema, input)); distinct(request.attachments.map((item) => item.id)); const execution = budget(request), bindings: ReviewStudyBindingEvidence[] = [], findings: AnalysisReviewFinding[] = []; for (const [index, attachment] of request.attachments.entries()) { const path = `$.attachments[${index}]`, resultPath = `${path}.result`; if (attachment.kind === "sensitivity") { atStudy(resultPath, () => validateReviewSensitivityReplayInput(attachment.result), attachment.id); atStudy(`${resultPath}.request`, () => validateReviewSensitivityRequest(attachment.result.request), attachment.id); } else if (attachment.kind === "sensitivity-grid") { atStudy(resultPath, () => validateReviewSensitivityGridReplayInput(attachment.result), attachment.id); atStudy(`${resultPath}.request`, () => validateReviewSensitivityGridRequest(attachment.result.request), attachment.id); } else { atStudy(resultPath, () => validateDiagnosticSuiteReplayInput(attachment.result), attachment.id); const assessment = atStudy(`${resultPath}.request`, () => assessDiagnosticSuiteInput(attachment.result.request), attachment.id); findings.push(...located(assessment.findings, `${resultPath}.request`, attachment.id)); } const retainedBindings = atStudy(path, () => bindingsFor(attachment, review), attachment.id); bindings.push(...retainedBindings); for (const binding of retainedBindings.filter((item) => item.status === "declared-related")) findings.push({ code: "STUDY_SUBJECT_DECLARED_RELATED", path: `${path}.binding`, message: binding.qualification, coordinates: { attachment: attachment.id, subject: binding.subject.id, kind: binding.subject.kind }, remedies: ["Retain the declared relationship qualification; no exact review-subject match is established"] }); } return { request, execution, bindings, findings }; } /** Replays every native study and binds it to an already verified review, without I/O or new mathematics. */ export function createReviewStudyCollection(input: ReviewStudyCollectionRequest, replay: ReviewPlanReplay): ReviewStudyCollection { checkReview(replay); const { request, execution, bindings } = prepareCollection(input, replay); for (const [index, attachment] of request.attachments.entries()) { atStudy(`$.attachments[${index}].result`, () => { if (attachment.kind === "sensitivity") replayReviewSensitivity(attachment.result); else if (attachment.kind === "sensitivity-grid") replayReviewSensitivityGrid(attachment.result); else replayDiagnosticSuite(attachment.result); }, attachment.id); } const content = { contractVersion: REVIEW_STUDY_COLLECTION_CONTRACT_VERSION, sdkVersion: DATA_PACKAGE_VERSION, ...request, review: replay.source, bindings, findings: reviewStudyFindings(request.attachments, bindings), execution, assurance: { studies: "replayed-current-sdk", sourceAuthenticity: "not-verified", independence: "not-established", causality: "not-established", completeness: "caller-selected-studies-only", publication: "not-reported" } as const }; const result = { ...content, reference: createAnalysisReference("result", request.id, request.version, content) }; if (canonicalJson(result).length > request.limits.maximumOutputCharacters) invalid("Study collection exceeds its complete output budget", "$.limits", "RESOURCE_LIMIT_EXCEEDED"); return snapshotDiagnosticJson(result); } function savedCollection(input: unknown): ReviewStudyCollection { const saved = snapshotDiagnosticJson(parseReviewBoundary(object, input)) as unknown as ReviewStudyCollection; if (canonicalJson(saved).length > REVIEW_STUDY_COLLECTION_LIMITS.maximumOutputCharacters) invalid("Saved study collection exceeds its replay budget", "$", "RESOURCE_LIMIT_EXCEEDED"); if (saved.contractVersion !== REVIEW_STUDY_COLLECTION_CONTRACT_VERSION || saved.sdkVersion !== DATA_PACKAGE_VERSION) invalid("Study collection replay requires its current contract and SDK"); return saved; } /** Serialized assurance claims never bypass current native replay and subject binding. */ export function replayReviewStudyCollection(input: unknown, replay: ReviewPlanReplay): ReviewStudyCollection { checkReview(replay); const saved = savedCollection(input); const result = createReviewStudyCollection({ id: saved.id, version: saved.version, attachments: saved.attachments, limits: saved.limits }, replay); if (!same(result, saved)) invalid("Saved studies, subject bindings or findings differ from exact replay", "$", "REVIEW_STUDY_REPLAY_MISMATCH"); return result; } export const reviewStudyExecutionRequestSchema: z.ZodType = z.object({ request: reviewStudyCollectionRequestSchema, review: reviewPlanReplayRequestSchema }).strict(); export const reviewStudyReplayRequestSchema: z.ZodType = z.object({ collection: z.custom(isDiagnosticPlainRecord), review: reviewPlanReplayRequestSchema }).strict(); export function parseReviewStudyExecutionRequest(input: unknown): ReviewStudyExecutionRequest { return snapshotDiagnosticJson(parseReviewBoundary(reviewStudyExecutionRequestSchema, input)); } export function parseReviewStudyReplayRequest(input: unknown): ReviewStudyReplayRequest { return snapshotDiagnosticJson(parseReviewBoundary(reviewStudyReplayRequestSchema, input)); } function prepareExecution(input: unknown) { const request = parseReviewStudyExecutionRequest(input); const run = atStudy("$.review", () => validateReviewPlanReplayRequest(request.review)); const prepared = atStudy("$.request", () => prepareCollection(request.request, { run, source: run.reference })); const preflight: ReviewStudyExecutionPreflight = snapshotDiagnosticJson({ execution: prepared.execution, findings: located(prepared.findings, "$.request"), assurance: "retained-structure-and-inputs-only", bindingBasis: "structurally-checked-saved-review" }); return { request, preflight }; } /** No native model is fitted; retained result equality is not numerical verification or receipt authority. */ export function validateReviewStudyExecutionRequest(input: unknown): ReviewStudyExecutionPreflight { return prepareExecution(input).preflight; } /** Reopens the saved review and uses its actual live receipt with the existing collection creator. */ export function createReviewStudyCollectionFromInput(input: unknown): ReviewStudyCollection { const { request } = prepareExecution(input); const review = atStudy("$.review", () => replayReviewPlanRun(request.review)); return atStudy("$.request", () => createReviewStudyCollection(request.request, review)); } /** Replays the saved review and collection; neither serialized assurance nor a copied receipt authorizes execution. */ export function replayReviewStudyCollectionFromInput(input: unknown): ReviewStudyCollection { const request = parseReviewStudyReplayRequest(input); const saved = atStudy("$.collection", () => savedCollection(request.collection)); const review = atStudy("$.review", () => replayReviewPlanRun(request.review)); return atStudy("$.collection", () => replayReviewStudyCollection(saved, review)); }