ai-osEvolving Agents Labs 0.906 AUC · kill line 0.80

ai-os/HEMO-VERIFIED

The other half of the problem: when there is no right answer to check against

COCLEA-SR has closed forms, so a gate can compare against truth. Most real work does not. This project asks what a gate is worth when nothing can be compared — and then puts the gate itself on trial.

Can a set of physics checks tell you that a flow prediction is wrong, without ever seeing the right answer? The pre-registered kill gate says yes, at 0.906 composite AUC against a threshold of 0.80 written down first. It also says three things it cannot show — and one of its seven numbers turned out to be a property of the machine it ran on rather than of the physics.

Why this project exists next to the other one

COCLEA-SR is the easy case in one specific sense: an exact solution exists. truth/ holds closed forms, src/ holds the solver, the first is forbidden to import the second, and a gate compares them. When the model was wrong, the mathematics said so.

Now take that away. In haemodynamics — blood moving through a heart chamber — there is no closed form for the geometry anyone cares about. A surrogate model predicts a flow field and nobody has the right answer to compare it to. The whole apparatus of the previous project stops applying.

So the question changes shape:

Can you catch a wrong prediction using only what must be true of any answer?

Mass is conserved. Momentum balances. Velocity is zero at a wall. None of those requires knowing the correct field — they are properties any correct field has. Each becomes an oracle: a cheap, independent check that scores a prediction without the answer.

And then the same discipline, one level up

A panel of oracles that agrees with itself is worth nothing. So the panel goes on trial, against a condition registered before the run:

H0, the kill gate. Run the oracles on exact solutions of the Navier–Stokes equations — steady Poiseuille and pulsatile Womersley — and on those same solutions corrupted by amounts chosen in advance, so the true error is known by construction rather than estimated. If the panel cannot separate bad from good at 0.80 AUC, the project ends.

98 predictions, 31.6% of them worse than 5% true error

  AUC (composite)   0.906     kill below 0.80  ->  SURVIVES
  Spearman rho      0.822
  false-accept      2.1%      target <= 2%
  decisions         ACCEPT 48   ESCALATE 18   REJECT 32

Every corruption type that produces more than 5% error is caught:

corruptionbad casesnot acceptedAUC alone
phase55/51.000
bias87/80.988
divergence44/40.982
noise88/80.863
slip66/60.819

The single false accept is a Womersley bias case whose true error is 0.050 against a bad-case boundary of 0.050 — the boundary itself, not a miss.

The result that makes it a portfolio rather than a trick

The obvious suspicion is that one good oracle is doing all the work and the others are decoration. It is not what the numbers say. Six of the seven are near a coin flip on their own, and the panel still reaches 0.906:

oraclealonecatches
A3 momentum residual0.838most things
A4 no-slip (hard)0.652slip — and see below
A10 temporal envelope0.639phase
A2 local mass0.590divergence
A1 global mass0.585divergence
A6 energy budget0.522bias, steady only
A5 inlet vs BC0.521bias, steady only

Remove both A3 and A4 and the remainder still reaches 0.896. Individually weak gates covering different failures beat each of their members — which is the argument for a panel rather than a better single check.

Two of those seven cells had been wrong on this page's ancestor: A5 and A6 were transposed, and A4 read 0.706. Every number in the table is now read out of gates/reports/h0.json by a script that fails the build when it stops matching.

The finding that is worth more than the AUC

On 2026-08-23 the suite was built from a clean clone, on a different machine with a different BLAS. Two things came back, and the first is the sharper one.

The attested report could not have come from the code beside it. eval/h0.py writes runtime: {seconds}; the committed h0.json carried a top-level seconds and no runtime at all. That nesting was introduced by the very commit that existed to make the run reproducible — so the artifact had been regenerated mid-change and never again. A report whose provenance nobody checks is a report, not an attestation.

Then, on a fresh run, the composite AUC, the Spearman coefficient, the decision counts and the false-accept rate came back bit-identical — and A4 alone moved from 0.706 to 0.652.

A4 alone   0.706  →  0.652     49 of 98 measurements differ in their last decimals
                                66 of 98 are exactly 0.0

one uncorrupted case:  1.03e-13  on one machine
                       0.0       on the other
                       → crosses into a 66-wide tie block
                       → drags a rank statistic by 0.054

The composite is untouched because A4 is a HARD gate: it contributes a pass/fail against a threshold far above the noise floor, never its score. But the lesson generalises past this project. A statistic that moves with a library version rather than with the data is not a property of the physics, and the only way to find out which of your numbers are like that is to run them somewhere else. make reproduce is the instrument that was missing; h0.json now records the environment it was produced on, so the next comparison can tell disagrees from was produced somewhere else.

environment recorded inside the artifact

  python   3.13.12
  numpy    2.5.2
  scipy    1.18.1
  machine  x86_64

The report reproduced 1,207 of 1,207 fields bit-identical on a third environment afterwards — the attestation machinery doing its job on hardware it had never seen.

Four more defects, each of which produced a plausible number first

The first two would each have produced a clean H0 number that meant nothing. The third and the fifth would have produced one nobody could reproduce — and the fifth would have looked reproducible while doing it, because the test the third one added compares two processes on one machine and never reads the committed artifact at all.

What this does not show, stated by the project itself

The corruptions and the oracles were designed by the same author. H0 shows the panel ranks errors of a kind we thought of. It cannot show it ranks the errors a trained surrogate actually makes, because no surrogate has been trained. That is H1 — the next gate, not a refinement of this one.

Two more: A7 (wall shear bounds) and A8 (residence-time scalar) are specified and unbuilt, because neither quantity exists on an analytical pipe. And every number here is on a rigid axisymmetric tube — the simplest geometry with an exact solution, and nothing like an atrium.

H1 is recorded in the system as open work that cannot proceed, with a null observation and a note explaining why it is stated at all: a scope with nothing red in it reads as a finished one. The activity canvas draws it as a hollow square — held, no verdict — which is a different mark from the one it uses for a step that ran and failed. Getting that distinction wrong in the interface was itself a bug found while building this site.

Why it is on this website

Every number on this page is read out of projects/hemo-verified/gates/reports/h0.json. Twenty-one of them are named individually in check-numbers.py, which fetches the artifact and fails this website's build if the page has stopped carrying one — on every push and nightly, because the artifact lives in another repository and can move without anything here changing. Each of the seven per-oracle cells is named separately, since two of them were wrong once. That is the evidence layer applied to the page describing it.

The check's own limit, since this page is about stating them: it asks whether the page contains a value, so it catches an artifact that moved while the page did not — the failure this project has actually had — and not one mistyped occurrence among several.

And the honest limit of that, the same one the front page now states: the hash chain proves nobody altered these numbers. It does not prove the code that computed them is right. What argues for that here is different and older — the threshold was declared before the run, the oracles never see the answer, and the artifact was re-derived on a machine that had never seen it. Which is how A4 was caught.

The full write-up → Specification Check the numbers yourself Repository