WTWilly Tai
Case studyAI Governance & Assurance · Healthcare

A denial that cannot exist without a cited reason.

nH Predict allegedly let a length-of-stay score deny care that the documented criteria did not. PriorAuth Sentinel is its governed inverse. The decision is made in deterministic code; the model only locates the fact and phrases it. A denial is structurally impossible without a specific cited unmet criterion, and when the chart is silent the engine abstains to a named clinician rather than guess. This page shows how the boundary between code and model is drawn, the one near-miss the engine has to get right, and what it does and does not prove.

0
denials without a cited criterion
Structurally impossible. Silence routes to a human; it never denies.
100%
chart-silent cases abstained
5 of 5 silent charts routed to a clinician.
20 / 20
determinations ship an appeal packet
Replayable, criterion-by-criterion.
SYN
synthetic ruleset & charts
A control architecture, not a clinical claim.

Figures come from running the engine over the seeded synthetic suite. They are reproducible, not a real-world outcome.

01 / The pain, and the real anchor

The denial stood because almost nobody appeals.

In the nH Predict litigation (Estate of Lokken v. UnitedHealth), plaintiffs allege a predictive model drove post-acute coverage denials at scale, and that roughly 90% of appeals were overturned. Yet the denials held, because only about 0.2% of patients ever appealed. The harm was not only a wrong answer. It was a confident answer with no contestable reason attached, issued faster than any human could review it.

Regulators moved. From 1 January 2026, CMS-0057-F requires payers to give a specific reason for every prior-authorization denial and to publish approval, denial and overturn metrics. California SB 1120 (the Physicians Make Decisions Act) requires a licensed clinician, not an algorithm alone, to make medical-necessity denials, and the NAIC Model Bulletin puts AI-use governance on insurers. The compliance bar is now exactly the thing nH Predict allegedly lacked: a cited reason and a human in the loop.

Sources: CMS-0057-F Interoperability and Prior Authorization Final Rule (specific-reason mandate, eff. 1 Jan 2026); Estate of Lokken v. UnitedHealth Group (nH Predict / naviHealth class action); California SB 1120; NAIC Model Bulletin on the Use of AI by Insurers.

02 / Why naive AI fails here

A score that "predicts" a denial is the whole problem.

The tempting build is a model that reads the chart and outputs a medical-necessity probability: approve above a threshold, deny below. It demos beautifully, and it is exactly the failure mode now under litigation, for three reasons.

So the real job is not prediction. It is evaluating a published checklist against an incomplete chart, scoring each criterion as met, unmet, or unknown, and refusing to let "unknown" ever become "deny."

03 / The trust boundary, drawn

The decision is made in code. The model only finds the fact and puts it into words.

This is the load-bearing line of the whole system. A published, versioned ruleset evaluates each criterion, and the disposition rule computes the verdict. Both run in deterministic code, reproducible down to the hash. The model sits strictly downstream and stays read-only: it checks whether each criterion's fact appears in the chart and returns a verbatim citation. It never assigns a disposition, and it can never turn an absence into a denial.

DETERMINISTIC · decides, reproducible MODEL · locates & phrases, cited, read-only Rulesetversioned · published Evaluatemet / unmet / unknownthree-valued DispositionAPPROVE / DENY/ ROUTE Locate + citeverbatim from chartor abstain Human gateclinician signs adverse model feeds evidence IN; it never sets the verdict Append-only, hash-chained ledgerruleset version · criterion evidence · CMS reason · reviewer · replayable appeal packet
fig.1 · the boundary where the model's evidence stops and the ruleset's decision begins

The structural guarantee lives in one place. A criterion becomes unmet only when the chart contains an explicit contradicting fact. Absence of evidence is unknown, and the disposition rule routes any unknown to a human. There is no code path from "silent chart" to "denied."

# the load-bearing decision , every verdict comes from here, never from a model
def decide(proc_id, note):
    proc = RULES["procedures"][proc_id]
    results = [evaluate_criterion(c, note) for c in proc["criteria"]]

    # a denial REQUIRES a provably-unmet criterion, cited
    unmet = first(r for r in results if r.status == "unmet")
    if unmet:
        return Disposition("DENY", cited=unmet)        # CMS-0057-F specific reason

    # silence is UNKNOWN, never "deny" , abstain to a clinician
    unknown = first(r for r in results if r.status == "unknown")
    if unknown:
        return Disposition("ROUTE_TO_REVIEW", cited=unknown)

    return Disposition("APPROVE")                      # only when ALL criteria met

def evaluate_criterion(crit, note):
    # a NEGATIVE cue (explicit contradiction) is the ONLY route to "unmet"
    if any(cue in note for cue in crit.neg_cues): return Result("unmet")
    if any(cue in note for cue in crit.pos_cues): return Result("met")
    return Result("unknown")                           # absence != contradiction

Excerpt. The JavaScript engine in the live demo mirrors this exactly, so the on-screen verdicts and the published Python are the same function.

04 / The worked example that matters

The flagship: the same chart a black box denies, the engine abstains.

Request AR-5001 is an 82-year-old, day 18 post-hip-fracture, in a skilled nursing facility. This is the exact nH Predict scenario. The chart documents a skilled need and that goals are not yet met. It is silent on one thing: whether the patient is participating in therapy this week. Watch the two systems diverge on identical input.

SystemWhat it readsOutputReason attachedHuman?
Black boxopaque length-of-stay score = 0.86DENY"predicted LOS exceeded"none
GovernedC2 participation = unknown (silent)ROUTEabstained (no fact to cite)named clinician
Getting the abstention right is the hard part of the engineering. The black box manufactures a denial from a number the patient cannot contest. The governed engine reads the same note, finds that the participation criterion is silent rather than contradicted, and routes to a clinician. It would deny only if the chart said "refusing therapy." The chart does not say that, so it cannot. Reading the absence correctly is the whole difference between a control and the system that got sued.

It cuts the other way too. Request AR-5003 does say "refusing therapy for the last four sessions." That is an explicit contradiction of the participation criterion, so the engine denies, and the denial ships with the verbatim cited phrase in CMS specific-reason format, signed by a named reviewer. A real unmet criterion gets a real, contestable denial. A silent one never does.

05 / Numbers, and the honest caveats

What the suite shows, stated flatly, and what it cannot claim.

Run over the seeded synthetic suite of 20 requests across 5 procedures, the engine produces 7 approvals, 8 denials, and 5 routed-to-review. Every one of the 8 denials carries a cited unmet criterion; zero denials are issuable without one. All 5 chart-silent cases, and only those, abstain to a clinician. Every determination, approve or adverse, emits a replayable criterion-by-criterion appeal packet whose ledger hash re-verifies.

Where these numbers come from. I authored both the ruleset and the charts, so these counts are true by construction. They prove the mechanism holds, not that it survives a real payer's ledger. The "0 denials without a citation" claim is the strongest one here precisely because it is structural rather than statistical. It is a property of the control flow shown above, not a measured rate that could regress on new data.

The honest limits, in plain terms. Real MCG/InterQual criteria are proprietary; mine are a clearly-labelled synthetic stand-in. Medical necessity is genuinely contestable, and whether a fact is "present" in a chart is often a clinical judgement this demo collapses into a simple met/unmet/unknown. Real extraction is probabilistic. It would need calibration and a confidence floor below which it must abstain. So what this demonstrates is a control architecture that cites or abstains, keeps a human in the loop, and leaves a tamper-evident trail. It is not a system that adjudicates care correctly, and I make no such claim. The synthetic-ruleset disclaimer stays visible in the app for exactly this reason.

06 / Governance, shown not claimed

A flipped verdict breaks the chain at exactly that row.

Every determination is written to an append-only, hash-chained ledger: ruleset version, the criterion-by-criterion evidence, the CMS-style reason, the reviewer's identity, and the appeal packet. Each entry's hash covers its own contents and the previous hash. The Tamper button does the nH Predict move. It silently flips an adverse determination to APPROVE without recomputing its hash, and Verify chain catches it at the altered row. Replay re-derives every disposition from its stored request and confirms it reproduces, bit-for-bit.

Decision ledger · entryintegrity verified · replay 20/20
seq         : 14
request     : AR-5001  (continued SNF stay)
ruleset     : SYN-MEDNEC v1.4.0   [SYNTHETIC]
disposition : ROUTE_TO_REVIEW
evidence    : [C1:met("skilled need"), C2:unknown, C3:met("goals not met")]
cited       : C2  (participation , chart silent → abstained)
reviewer    : Dr S. Lindqvist, MD   (named clinician, HITL)
prev_hash   : 3af1c2e9
hash        : 9b7e04d1   ← = fnv1a(prev_hash + canonical(record))
Threat model: append-only. A flipped disposition changes the record → its hash no longer matches → Verify reports a break at that exact seq. The tamper test runs live in the app.

Why I build the refusal first.

The interesting engineering in a decisioning system is not the "yes." It is designing the "I won't" so that it cannot be bypassed: making a denial impossible to express without a cited reason, and a silence impossible to read as a no. I would rather ship a system that abstains correctly than one that is confident and occasionally catastrophic. Drawing that boundary in code (the model locates the fact, the ruleset owns the verdict, a human signs anything adverse, and a hash chain remembers all of it) is what separates an AI that looks governed in a demo from one a regulator, a clinician, and an appealing patient can each actually trust. Building that refusal so it holds under pressure is the real work here.

See it run.

Pick any of the 20 synthetic requests and watch the criteria resolve met / unmet / unknown, with the cited line highlighted in the chart. Then open the flagship case, flip Black-box against Governed on the same note, and build the appeal packet in one click.

Open the live engine →Runs client-side over synthetic data. No PHI, no sign-in, nothing to install.