Virtual Trial
Repo
Judge modeEach section shows the criterion it speaks to and a link to the evidence.Full evidence map

Proof

Does it catch harmful changes, and only those?

We seeded realistic dosing bugs and harmless refactors into oref0 and ran each through four checks: what exists today, two simpler checks, and Virtual Trial. A good check catches every harmful change and flags no harmless one.

Run 2026-10-17 15:39:23 UTC on commit ea81d331: 6 virtual patients x 10 scenarios per version, 27830 seconds. Reproduce with python -m bench.run. Worst-day hunter on commit 86c948f8 (4922 seconds; python -m bench.hunter).

Headline

oref0's own unit tests

What exists today: fixed inputs, expected outputs.

6 of 9harmful changes caught
3 of 7harmless changes wrongly flagged

Open-loop replay

Replays thousands of real inputs from the trial; flags any changed decision, harmful or not.

9 of 9harmful changes caught
3 of 7harmless changes wrongly flagged

Release safety envelope

Our engine release gate: oref0's own hard limits on 150 inputs.

1 of 9harmful changes caught
0 of 7harmless changes wrongly flagged

Virtual Trial

Closed loop on virtual patients: 10 fixed scenarios plus a search for the worst day, human-set limits.

9 of 9harmful changes caught
0 of 7harmless changes wrongly flagged
Perfect on this benchmark

Every change, every check

ChangeKindUnit testsOpen loopEnvelopeVirtual Trial
Insulin-on-board safety cap raised 4x
A moved safety limit: oref0 may stack four times the configured insulin.
Harmful: too much insulinStops it 1 new failuresStops it 356 of 4968 decisions changedLets it through Stops it lbgi (paired)
Insulin sensitivity halved
A wrong factor: each unit is assumed to lower glucose half as much, so more insulin is given.
Harmful: too much insulinStops it 6 new failuresStops it 1596 of 4968 decisions changedLets it through Stops it time_below_70_pct, lbgi (paired)
Low-glucose suspend threshold lowered
A moved safety threshold: insulin keeps flowing closer to a low before oref0 stops it.
Harmful: too much insulinLets it through Stops it 185 of 4968 decisions changedLets it through Stops it worst day found (severe lows), worst day found (severe lows)
Insulin on board undercounted by half
The failure class behind Trio #898 and AndroidAPS #2580: insulin already given is missed, so more is given.
Harmful: too much insulinStops it 12 new failuresStops it 1260 of 4968 decisions changedLets it through Stops it time_below_70_pct, lbgi (paired)
Carb effect doubled
A unit or ratio error: carbs are predicted to raise glucose twice as much, so meals get extra insulin.
Harmful: too much insulinLets it through Stops it 320 of 4968 decisions changedLets it through Stops it lbgi (paired)
Max safe basal doubled
A moved hard cap: temporary basal rates may go twice as high as oref0's own limit.
Harmful: too much insulinStops it 10 new failuresStops it 544 of 4968 decisions changedStops it 25 outside limitsStops it time_below_70_pct, severe_low_events, lbgi (paired)
Falling glucose trend ignored
An ignored input: the most optimistic recent trend is used, so falls are noticed late.
Harmful: too much insulinLets it through Stops it 942 of 4968 decisions changedLets it through Stops it time_below_70_pct, lbgi (paired)
Insulin sensitivity doubled
A wrong factor in the other direction: too little insulin, glucose runs high.
Harmful: too little insulinStops it 10 new failuresStops it 2433 of 4968 decisions changedLets it through Stops it hbgi (paired)
Insulin-on-board cap cut to a quarter
An over-tight limit: oref0 cannot give enough insulin to correct highs.
Harmful: too little insulinStops it 5 new failuresStops it 1245 of 4968 decisions changedLets it through Stops it time_in_range_70_180_pct, hbgi (paired)
Refactor: rename a variable
Same behavior, different name.
HarmlessLets it through Lets it through 0 of 4968 decisions changedLets it through Lets it through
Refactor: equivalent arithmetic
min_bg - 0.5*(min_bg-40) rewritten as (min_bg + 40) / 2, which is the same number.
HarmlessLets it through Lets it through 0 of 4968 decisions changedLets it through Lets it through
Refactor: reorder a multiplication
Same factors in a different order.
HarmlessLets it through Stops it 1 of 4968 decisions changedLets it through Lets it through
Change an explanation message
Only the text oref0 writes in its reason string changes.
HarmlessStops it 3 new failuresLets it through 0 of 4968 decisions changedLets it through Lets it through
Add a comment
No code changes at all.
HarmlessLets it through Lets it through 0 of 4968 decisions changedLets it through Lets it through
Finer temp basal rounding (0.025 U/hr)
Supports pumps with a finer increment: many rates change by up to 0.025 U/hr, a clinically negligible amount.
HarmlessStops it 5 new failuresStops it 463 of 4968 decisions changedLets it through Lets it through
Low-glucose suspend threshold raised slightly
A more cautious setting: oref0 suspends a little earlier when a low is predicted.
HarmlessStops it 1 new failuresStops it 154 of 4968 decisions changedLets it through Lets it through

Green means the check made the right call: it stops a harmful change, or lets a harmless one through. Red means it got it wrong.

Real bugs from oref0's history

Bugs that oref0's maintainers found and fixed, years after they shipped. We undid each fix on today's code and ran every check, as if the bug were a new merge request. 6 virtual patients x 10 scenarios per version, plus the worst-day hunter.

BugUnit testsOpen loopVirtual TrialWhat it means
Low-glucose suspend skipped (bug fixed in 2017)
Before oref0 PR #476, suspending insulin at low glucose also required insulin on board above a mis-scaled bound (basal x sensitivity x 20/60), so oref0 could keep insulin flowing while glucose was already low.
The fix, 2017 (647a35f9) · original logic ported to today's code
Lets it throughStops it 184 of 4968 decisions changedStops it worst day found (severe lows)

Blocked. The hunter found a day with a new severe low and confirmed it on 12 variations of that day.

LBGI +9%, worse in 33 of 60 runs, p=0.035
HBGI +0%, worse in 20 of 60 runs, p=0.98
Hunter: 59 days searched; worst: child#001, lowest 55.4 -> 53.1 mg/dL; suspect day (child#001) rerun 12 ways: head lower on 12, p=0.0002, confirmed
Last temp age wrong when the last temp is unknown (bug fixed in 2023)
With no recorded last temp basal, oref0 assumed it had just been set (age 0) and could refuse to change a running temp when glucose data was stale.
The fix, 2023 (0cf223c7) · fix reverted with git
Lets it throughStops it 3 of 4968 decisions changedLets it through

Passed: no change in outcomes measured. The hunter's one bad day did not hold up on 12 variations, so it did not block.

LBGI +0%, worse in 2 of 60 runs, p=0.5
HBGI -0%, worse in 1 of 60 runs, p=0.97
Hunter: 59 days searched; worst: child#001, lowest 55.4 -> 51.8 mg/dL; suspect day (child#001) rerun 12 ways: head lower on 6, p=0.6128, not confirmed
Overreacting to negative deviations after a big drop (bug fixed in 2017)
Before oref0 PR #615, one large drop in glucose made oref0 project the drop forward too strongly and cut insulin too much, which can leave glucose high.
The fix, 2017 (dd6e1a64) · fix reverted with git
Lets it throughStops it 426 of 4968 decisions changedLets it through

Passed, with the harm measured: high blood sugar risk +8%, worse in 59 of 60 runs, p=5.3e-17. That is under the 15% block limit, so it is reported for a person, not blocked.

LBGI -13%, worse in 1 of 60 runs, p=1
HBGI +8%, worse in 59 of 60 runs, p=5.3e-17
Hunter: 59 days searched; worst: child#001, lowest 55.4 -> 53.4 mg/dL; suspect day (child#001) rerun 12 ways: head lower on 6, p=0.6128, not confirmed
Rate at the safety cap returned as text (bug fixed in 2016)
Before oref0 PR #177, when the requested rate hit max safe basal oref0 returned it with toFixed(1), a text value instead of a number rounded for the pump.
The fix, 2016 (244ba9dd) · original logic ported to today's code
Stops itStops it 112 of 4968 decisions changedLets it through

Passed: no change in outcomes measured.

LBGI -2%, worse in 2 of 60 runs, p=1
HBGI +0%, worse in 13 of 60 runs, p=0.26
Hunter: 48 days searched; worst: adolescent#003, lowest 72.1 -> 69.9 mg/dL

Of four dosing bugs that shipped, oref0's own tests caught one (a value-type bug with no effect on outcomes). Virtual Trial blocked the one that let insulin flow during a low, which the unit tests missed, and measured the consistent rise in highs from a second. Open-loop replay flagged all four but cannot say which ones harm anyone.

In a real pipeline

A merge request that raised oref0's insulin-on-board cap 4x ran the full trial (30 patients, 10 scenarios, 6 parallel jobs) in GitLab CI. Low blood sugar risk rose 30%, in 222 of 300 matched runs (p = 1.5e-50): blocked. A minute later the explain agent posted why, on its own.

Open the gate job log · Open the merge request

On another real codebase

Trio's dosing code (trio-oref) ran through our reusable CI component, unchanged: before vs after Trio's November 2025 dosing changes. Full trial in 6 parallel jobs plus 48 hunted days: passed, no limit crossed. Adopting it is one include: line.

Open the gate job log · Open the pipeline

When production regresses

In a drill, a harmful change shipped on a test branch. The clinic's incident opened, and the incident agents found the dosing commit behind it and opened a merge request undoing exactly that commit, in about three minutes, on their own. The full trial passed the undo (low blood sugar risk down 29%), and it waits for a person to merge.

Open the incident · Open the revert merge request · Open its gate job

In production

On Oct 13 a new engine build crashed at startup. The canary never gave it traffic; the public engine kept serving the previous version.

Open the pipeline