marmar-context / web / context / test / load-failures.test.ts
load-failures.test.ts
Raw
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
  configureAzureSession,
  extract,
  modelVerification,
} from "../server/model";
import { modelLoad, retryAfterMs } from "../server/model-runtime";
import { parseCompactDraft } from "../server/compact";
import { groundedFact } from "../server/guards";
const source = [
  {
    id: "load",
    title: "Synthetic load note",
    kind: "Synthetic",
    date: "2026-10-23",
    text: "Patient: Nora Test\nShe takes Metformin 500 mg twice daily.",
  },
];
const good = () =>
  new Response(
    JSON.stringify({
      choices: [
        {
          finish_reason: "stop",
          message: {
            content: JSON.stringify({
              facts: [
                [
                  2,
                  "Medication: Metformin; strength: 500 mg; frequency: 2/day",
                ],
              ],
            }),
          },
        },
      ],
    }),
    { status: 200 },
  );
function configure() {
  configureAzureSession({
    endpoint:
      "https://synthetic.services.ai.azure.com/openai/v1/chat/completions",
    key: "synthetic",
    model: "test",
    auth: "api-key",
  });
}
beforeEach(configure);
afterEach(() => {
  vi.unstubAllGlobals();
  vi.restoreAllMocks();
});

describe("bounded provider work", () => {
  it("admits four calls, rejects overflow promptly, and releases capacity", async () => {
    const finish: Array<(r: Response) => void> = [];
    vi.stubGlobal(
      "fetch",
      vi.fn(() => new Promise<Response>((resolve) => finish.push(resolve))),
    );
    const admitted = Array.from({ length: 4 }, () =>
      extract(source, true, true),
    );
    expect(modelLoad().active).toBe(4);
    const rejected = await Promise.allSettled(
      Array.from({ length: 8 }, () => extract(source, true, true)),
    );
    expect(
      rejected.every(
        (r) =>
          r.status === "rejected" && /slots are busy/.test(r.reason.message),
      ),
    ).toBe(true);
    for (const resolve of finish) resolve(good());
    await Promise.all(admitted);
    expect(modelLoad().active).toBe(0);
  });
  it("aborts provider work and permits a later successful retry", async () => {
    const fetcher = vi.fn(
      (_url, options) =>
        new Promise((_r, reject) =>
          options.signal.addEventListener(
            "abort",
            () => reject(new Error("private abort")),
            { once: true },
          ),
        ),
    );
    vi.stubGlobal("fetch", fetcher);
    const controller = new AbortController();
    const pending = extract(source, true, true, controller.signal);
    controller.abort();
    await expect(pending).rejects.toThrow("cancelled");
    expect(fetcher).toHaveBeenCalledTimes(1);
    expect(modelLoad().active).toBe(0);
    vi.stubGlobal(
      "fetch",
      vi.fn(async () => good()),
    );
    expect((await extract(source, true)).strategy).toBe("narrative");
  });
  it("does not publish or cache an in-flight result after reconfiguration", async () => {
    let finish!: (r: Response) => void;
    vi.stubGlobal(
      "fetch",
      vi.fn(
        () =>
          new Promise<Response>((r) => {
            finish = r;
          }),
      ),
    );
    const pending = extract(source, true, true);
    configure();
    finish(good());
    await expect(pending).rejects.toThrow("cancelled");
    expect(modelVerification()).toBeNull();
    expect(modelLoad().active).toBe(0);
  });
  it("honors HTTP-date Retry-After and prevents a subsequent retry storm", async () => {
    const date = new Date(Date.now() + 60_000).toUTCString();
    const fetcher = vi.fn(
      async () =>
        new Response("", { status: 429, headers: { "Retry-After": date } }),
    );
    vi.stubGlobal("fetch", fetcher);
    await expect(extract(source, true, true)).rejects.toThrow("busy");
    await expect(extract(source, true, true)).rejects.toThrow("rate limited");
    expect(fetcher).toHaveBeenCalledTimes(1);
    expect(modelLoad().active).toBe(0);
  });
  it.each([null, [], {}, "invalid"])(
    "rejects invalid provider envelope %j with a safe message",
    async (body) => {
      vi.stubGlobal(
        "fetch",
        vi.fn(async () => new Response(JSON.stringify(body))),
      );
      await expect(extract(source, true, true)).rejects.toThrow(
        "invalid response",
      );
      expect(modelLoad().active).toBe(0);
    },
  );
  it("handles numeric, date and invalid retry delay formats", () => {
    expect(retryAfterMs("2")).toBe(2000);
    expect(retryAfterMs("garbage")).toBe(0);
    expect(retryAfterMs(new Date(60000).toUTCString(), 0)).toBe(60000);
  });
});

describe("expanded messy source boundaries", () => {
  it.each([
    ["She has a Penicillin allergy.", "Allergies: Penicillin"],
    [
      "Her eGFR was 38 mL/min/1.73m2 on 2026-10-12.",
      "Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12",
    ],
  ])(
    "withholds ambiguous pronouns after a relative on a previous line: %s",
    (quote, normalized) => {
      const sources = [
        {
          ...source[0],
          text: "Patient: Nora Test\nHer sister came yesterday.\n" + quote,
        },
      ];
      const d = parseCompactDraft(
        { facts: [[3, normalized]] },
        sources,
        "test",
        0,
      );
      expect(d.facts.at(-1)?.problem).toContain("subject");
    },
  );
  it("retains an explicitly named patient after a relative", () => {
    const sources = [
      {
        ...source[0],
        text: "Patient: Nora Test\nHer sister has a Penicillin allergy.\nNora has no known drug allergies.",
      },
    ];
    expect(
      parseCompactDraft(
        { facts: [[3, "Allergies: No known allergies"]] },
        sources,
        "test",
        0,
      ).facts.at(-1)?.problem,
    ).toBeNull();
  });
  it("does not turn a conditional prescription into a current medicine", () => {
    expect(
      groundedFact(
        "Medication: Amlodipine; strength: 5 mg",
        "If her pressure rises, Nora may start Amlodipine 5 mg.",
        ["Nora Test"],
      )?.problem,
    ).toBeTruthy();
  });
  it.each([
    "Nora's eGFR was not 38 mL/min/1.73m2 on 2026-10-12.",
    "The old eGFR 38 mL/min/1.73m2 dated 2026-10-12 was entered in error.",
  ])("withholds negated/erroneous labs: %s", (quote) => {
    expect(
      groundedFact(
        "Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12",
        quote,
        ["Nora Test"],
      )?.problem,
    ).toBeTruthy();
  });
});