import fs from "node:fs/promises"; const base = process.env.CONTEXT_TEST_ORIGIN || "http://127.0.0.1:4191"; if (!/^http:\/\/(127\.0\.0\.1|localhost):4191$/.test(base)) throw new Error("Use the local Context server."); const call = async (path, body) => { const response = await fetch( base + "/api/" + path, body ? { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), signal: AbortSignal.timeout(60000), } : undefined, ); const data = await response.json(); return { ok: response.ok, status: response.status, data }; }; const health = (await call("status")).data; if (!health.modelConfigured) throw new Error("Connect the model through the demo interface first."); const cases = (await call("cases")).data; const report = { runAt: new Date().toISOString(), model: health.model, engine: health.engineVersion, scope: "Live synthetic integration checks, not clinical validation", cases: [], }; for (const scenario of cases) { const row = { id: scenario.id, passed: false }; const started = performance.now(); try { const extraction = await call("extract", { sources: scenario.sources, syntheticOnly: true, useModel: true, freshModel: true, }); if (!extraction.ok) throw new Error(extraction.data.error); const draft = extraction.data; row.mode = draft.mode; row.strategy = draft.strategy; row.providerCalls = draft.metrics?.providerCalls; if (draft.mode === "local" && draft.metrics?.providerCalls !== 0) throw new Error("Incorrect structured-reader telemetry"); row.extractionMs = draft.durationMs; row.attempts = draft.attempts ?? 0; row.factCount = draft.facts.length; const review = Object.fromEntries( draft.facts.map((f) => [f.id, "include"]), ); const payload = { sources: scenario.sources, review, fingerprint: draft.fingerprint, acknowledgeUnparsed: Boolean( draft.sourceReviewRequired || draft.unparsed.length, ), syntheticOnly: true, ...(draft.id ? { draftId: draft.id } : {}), }; if (scenario.id === "conflicting-records") { const blocked = await call("assess", payload); row.conflictBlocked = !blocked.ok && /[Cc]onflict/.test(blocked.data.error); if (!row.conflictBlocked) throw new Error("Conflicting medication records were not blocked"); const rejected = draft.facts.find( (f) => f.sourceId === "fatima-clinic" && f.kind === "medicine", ); review[rejected.id] = "exclude"; } const checked = await call("assess", payload); if (!checked.ok) throw new Error(checked.data.error); row.ruleIds = checked.data.contextual.findings.map((f) => f.ruleId); row.addedRuleIds = checked.data.addedRuleIds; const expected = scenario.id === "allergy-context" ? "allergy-penicillin" : "lab-metformin-egfr-45"; if (!row.addedRuleIds.includes(expected)) throw new Error("Expected contextual finding was absent"); row.passed = true; } catch (error) { row.error = error.message; } row.totalMs = Math.round(performance.now() - started); report.cases.push(row); console.log(JSON.stringify(row)); } report.passed = report.cases.filter((r) => r.passed).length; report.total = report.cases.length; const target = process.argv[2] || "validation/live-latest.json"; await fs.writeFile(target, JSON.stringify(report, null, 2) + "\n"); console.log(`Saved ${target}: ${report.passed}/${report.total} passed`); process.exitCode = report.passed === report.total ? 0 : 1;