import { z } from "zod"; import { AnalysisReviewError, isDiagnosticToken, MODEL_DIAGNOSTIC_CHECKS, MODEL_DIAGNOSTIC_LIMITS, runModelDiagnostics, type ModelDiagnosticRequest, type ModelDiagnosticResult } from "@actuarial-ts/core"; import { modelRequestSchema } from "./reviewContracts.js"; import { parseReviewBoundary } from "./reviewBoundary.js"; const token = z.string().refine(isDiagnosticToken, "Expected a valid identifier"); /** Internal builder for the graph's retained-model link. */ export function modelDiagnosticSchemaForRun(run: T) { return z.object({ id: token, version: token, run, checks: z.array(z.enum(MODEL_DIAGNOSTIC_CHECKS)).min(1).max(MODEL_DIAGNOSTIC_CHECKS.length), policies: z.object({ correlationTies: z.enum(["retain-approximation", "not-evaluated"]), residualReference: z.literal("volume-weighted-mack") }).strict(), limits: z.object({ maximumInputCharacters: z.number().int().positive().max(MODEL_DIAGNOSTIC_LIMITS.maximumInputCharacters), maximumOrigins: z.number().int().positive().max(MODEL_DIAGNOSTIC_LIMITS.maximumOrigins), maximumCells: z.number().int().positive().max(MODEL_DIAGNOSTIC_LIMITS.maximumCells) }).strict(), }).strict(); } /** Model result content remains intact for exact core replay; parsing does not certify a saved result. */ export function parseModelDiagnosticRequest(input: unknown): ModelDiagnosticRequest { const raw = parseReviewBoundary(modelDiagnosticSchemaForRun(z.unknown()), input); try { parseReviewBoundary(z.object({ request: modelRequestSchema }).passthrough(), raw.run); } catch (error) { if (!(error instanceof AnalysisReviewError)) throw error; throw new AnalysisReviewError(error.findings.map((finding) => ({ ...finding, path: `$.run${finding.path.startsWith("$") ? finding.path.slice(1) : finding.path.slice(5)}` }))); } return raw as ModelDiagnosticRequest; } export function runModelDiagnosticsFromInput(input: unknown): ModelDiagnosticResult { return runModelDiagnostics(parseModelDiagnosticRequest(input)); }