import { describe, expect, it } from "vitest"; import { parseCompactDraft } from "../server/compact"; import { assess } from "../server/context"; import type { Draft, Review, Source } from "../src/types"; // Synthetic, deterministic fault injection. These tests measure the review gate, // not the rate at which any live model omits medication information. const variants = [ { name: "and-separated medicines", text: "She takes Warfarin 5 mg and Ibuprofen 200 mg.", ibuprofenRef: 2 }, { name: "comma-separated medicines", text: "She takes Warfarin 5 mg, Ibuprofen 200 mg.", ibuprofenRef: 2 }, { name: "semicolon-separated medicines", text: "She takes Warfarin 5 mg; she also takes Ibuprofen 200 mg.", ibuprofenRef: 2 }, { name: "reversed medicine order", text: "She takes Ibuprofen 200 mg and Warfarin 5 mg.", ibuprofenRef: 2 }, { name: "medicine on a separate line", text: "She takes Warfarin 5 mg.\nShe also takes Ibuprofen 200 mg.", ibuprofenRef: 3 }, ]; function extraction(variant: (typeof variants)[number], complete: boolean) { const sources: Source[] = [{ id: "synthetic-note", title: "Synthetic omission regression", kind: "Synthetic", date: "2026-10-29", text: "Patient: Amina Stone\n" + variant.text, }]; const facts: [number, string][] = [[2, "Medication: Warfarin; strength: 5 mg"]]; if (complete) facts.push([variant.ibuprofenRef, "Medication: Ibuprofen; strength: 200 mg"]); const draft = parseCompactDraft({ facts }, sources, "simulated-response", 0); const review: Review = Object.fromEntries(draft.facts.map((fact) => [fact.id, "include"])); return { sources, draft, review }; } function check(input: { sources: Source[]; draft: Draft; review: Review }, acknowledged: boolean) { return assess(input.sources, input.review, input.draft.fingerprint, acknowledged, input.draft); } describe("medication omission safety contract", () => { it.each(variants)("complete extraction retains the interaction: $name", (variant) => { const input = extraction(variant, true); expect(input.draft.facts.filter((fact) => fact.kind === "medicine")).toHaveLength(2); expect(input.draft.warnings).toHaveLength(0); const finding = check(input, true).contextual.findings.find((item) => item.ruleId === "vka-nsaid"); expect(finding).toBeDefined(); expect(finding!.medicines.map((medicine) => medicine.id).sort()).toEqual( input.draft.facts.filter((fact) => fact.kind === "medicine").map((fact) => fact.id).sort(), ); }); it.each(variants)("existing acknowledgement gate remains enforced: $name", (variant) => { const input = extraction(variant, false); expect(input.draft.facts.filter((fact) => fact.kind === "medicine")).toHaveLength(1); expect(input.draft.sourceReviewRequired).toBe(true); expect(() => check(input, false)).toThrow("Review the original notes for omissions"); }); // Generic acknowledgement cannot resolve a detected unmatched medication. it.each(variants)("unresolved omission blocks assessment after acknowledgement: $name", (variant) => { const input = extraction(variant, false); expect(() => check(input, true)).toThrow(/omission|coverage|unresolved medication/i); }); });