import { describe, it, expect } from "vitest"; import { parseCompactDraft } from "../server/compact"; import { groundedFact } from "../server/guards"; const source = (text: string) => [ { id: "note", title: "Note", kind: "Synthetic", date: "2026-10-23", text }, ]; describe("real-world normalization boundaries", () => { it.each([ [ "Medication: Metformin; strength: 500 mg; form: tablet; dose: 1 tablet; frequency: 2/day", "Prescribed Metformin 500mg tab, 1 tab BID.", ], [ "Medication: Metformin; dose: 0.5 tablet; frequency: 2/day", "Metformin: half a tablet twice daily.", ], [ "Medication: Amlodipine; strength: 2.5 mg; frequency: 1/day", "She takes Amlodipine 2.5mg tablets once daily.", ], [ "Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12", "Her eGFR was 38 mL/min/1.73m2 on 12 October 2026.", ], ])("accepts explicitly supported normalization %s", (normalized, quote) => expect(groundedFact(normalized, quote)?.problem).toBeNull(), ); it.each([ [ "Medication: Metformin; strength: 500 mg", "Metformin 1500 mg is recorded.", ], [ "Medication: Metformin; strength: 5 mg", "Prescribed Metformin 500 mg and Amlodipine 5 mg.", ], [ "Medication: Amlodipine; dose: 1 tablet", "Metformin one tablet and Amlodipine 5 mg.", ], [ "Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12", "eGFR 38 mL/min/1.73m2 on 12/10/2026.", ], ])("rejects inferred or misattributed fields %s", (normalized, quote) => expect(() => groundedFact(normalized, quote)).toThrow(), ); it.each([ ["Patient: Yara Brook", "Her mother Yara Brook is 65 years old."], ["Age: 65", "Her mother Yara Brook is 65 years old."], ["Allergies: Penicillin", "She denied a Penicillin allergy."], ["Condition: asthma", "She is negative for asthma."], [ "Medication: Metformin; strength: 500 mg", "She does not take Metformin 500 mg.", ], [ "Medication: Metformin; strength: 500 mg", "She denies taking Metformin 500 mg.", ], ["Allergies: Penicillin", "Her mother has a Penicillin allergy."], ["Condition: diabetes", "Family history includes diabetes."], [ "Medication: Ibuprofen; strength: 200 mg; frequency: 3/day", "She takes Ibuprofen 200 mg as needed, up to three times daily.", ], ["Medication: Metformin; strength: 500 mg", "Metformin 500 mg OD."], [ "Lab: eGFR; value: 38; unit: mL/min/1.73m2", "Her eGFR was 38 mL/min/1.73m2.", ], ])( "keeps ambiguous or incomplete facts out of assessment %s", (normalized, quote) => expect(groundedFact(normalized, quote)?.problem).toBeTruthy(), ); it("quarantines an unsupported generated row without discarding usable records", () => { const sources = source( "Patient: Amina Stone\nMedication: Metformin; strength: 500 mg\nHer eGFR was 38 mL/min/1.73m2.", ); const d = parseCompactDraft( { facts: [ [3, "Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12"], ], }, sources, "test", 1, ); expect(d.facts).toHaveLength(2); expect(d.warnings).toHaveLength(1); expect(d.unparsed).toHaveLength(1); expect(d.sourceReviewRequired).toBe(true); }); it("canonicalizes explicit tablet and capsule dose abbreviations without losing quantities", () => { const d = parseCompactDraft( { facts: [ [ 1, "Medication: Metformin; strength: 500 mg; form: tab; dose: 1 tab; frequency: 2/day", ], ], }, source("- Prescribed Metformin 500mg tab, 1 tab BID."), "test", 1, ); expect(d.facts[0].normalizedLine).toContain("dose: 1 tablet"); expect(d.warnings).toHaveLength(0); }); it("retains supported medicine fields while making invented optional quantities unknown", () => { const d = parseCompactDraft( { facts: [ [ 1, "Medication: Amlodipine; strength: 2.5 mg; form: tablets; dose: 1 tablet; frequency: 1/day", ], ], }, source("She takes Amlodipine 2.5mg tablets once daily."), "test", 1, ); expect(d.facts).toHaveLength(1); expect(d.facts[0].problem).toBeNull(); expect(d.facts[0].detail).toContain("Dose unknown"); expect(d.facts[0].normalizedLine).not.toContain("dose:"); expect(d.warnings?.[0].reason).toContain("Removed that field"); expect(d.warnings?.[0].normalizedLine).toContain("dose: 1 tablet"); }); it("never lets the model replace deterministic fields", () => expect(() => parseCompactDraft( { facts: [[1, "Patient: Other"]] }, source("Patient: Amina Stone"), "test", 1, ), ).toThrow("locked")); it("requires source references to exist", () => expect(() => parseCompactDraft( { facts: [[99, "Patient: Amina Stone"]] }, source("Amina Stone is a patient."), "test", 1, ), ).toThrow("unknown")); });