Do three safety checks written into the code actually do anything?
No. A magnetic warning was dropped, a key guard was never used and two settings were ignored; two are now wired, one still is not.
In the log: Three guards that exist and do nothing
recordedDate not stated in the log; it was written between the commit of 2026-09-16 17:21 and the first commit that contains it, 2026-09-16 17:52rung 4 · DFT0 predictions · 1 result paragraphEXPERIMENTS.md lines 8844–8877, lines 8879–8904, lines 8906–8922
What E146 did and how it came out, drawn from this record and the files it names (book/assets/diagrams/exp/E146.svg).
Pre-registration
The pre-registration, as written
E146 correction: the guard broke four tests and I reported the commit before the suite
finished.
Verifier.__init__ now refuses an uncorrected thermo, and four tests in test_verifier.py
construct one — _StubThermo and a local _Thermo that exercise the DFT rung, which
never touches the expansion's references and so had no _ref_shift. The guard was right and
the doubles were incomplete; both now declare _ref_shift = 0.0, the honest value for a stub
holding no expansion, with a comment saying why.
234 passing, 2 skipped. Up two from 232 — the two new guard tests.
The process failure is worth recording separately from the code one. E146 was committed with
"two new tests, no current result changes" while a fourteen-minute suite was still running,
and it came back with four failures caused by that commit. That is the third report ahead of
the measurement tonight, after E128's number and E141's generalisation. The others were
expensive because they entered the scientific record; this one was cheap because a test caught
it. The pattern is the same and the rule already exists: measure, then write.
Results
EXPERIMENTS.md · line 8879
E146 result: all three wired, and prediction 2 holds — no top find is affected.
Verifier now honours seeds and steps_per_site.expansion() read its own
attributes instead of hardcoded 90/1. Prediction 3 confirmed: nothing currently changes,
because every caller uses the defaults. It was a latent trap, and a caller trying to escape
E113's +11 per cent bias would have silently got the bias.
The magnetic flag reaches promotion.verify() returns unmodelled and
promote_by_niche carries it, so a composition whose failure mode no rung can evaluate
arrives labelled. Checked on E134's in-class list: Cr0.25 Mo0.25 V0.25 W0.25 reports
['Cr'], as it should.
The reference convention is now checked at construction.Verifier.__init__ raises if
thermo._ref_shift is None. screen() adds equilibrium references to whatever
random_energy returns, and that return is on equilibrium references only ifcorrect_references() was called — which exactly one construction path did. Any other
silently double-counted the strain, up to 505 meV/atom for vanadium alone (E55). This is
the assertion MixingEnergy implies and never got to make.
Prediction 2 confirmed: the top in-class finds are Mo/W/Ta/Nb/Ti and carry no flagged
element, so the ranking does not move. Prediction 1 is untestable as stated — E134's saved
finds predate the flag, so the count of affected compositions can only be taken on the next
run, not from the file.
Two new tests. The MixingEnergy class itself still has no call site: what it guards is now
guarded, but by an inline assertion rather than by the type. That is the smaller fix and it is
the one that removes the live hazard; using the type properly would mean carrying conventions
through every energy in the pipeline, which is a refactor and not an hour's work.
The full record
This entry is written in 3 separate places in the log, shown here in log order.
EXPERIMENTS.md · lines 8844–8877
E146 — Three guards that exist and do nothing
The audits found three mechanisms written, tested, and wired to nothing. Verified again this
hour: transitions_unmodelled has zero readers outside the function that computes it,
MixingEnergy has zero production call sites, and Verifier.__init__ declares seeds and
steps_per_site and assigns neither.
Each has a concrete consequence:
The magnetic flag never reaches a decision.screen() computes it (E122) and
stage_b.verify() drops it before the generator, the promotion list or the operator sees
it. The standing instruction not to promote anything Cr-, Ni- or Co-rich above rung 0 is
unenforced in code.
MixingEnergy is the guard docs/README.md calls the most important module in the repo
— "it encodes the mistake that has cost this project the most" — and nothing constructs
one. Every energy subtraction in the pipeline is done on bare floats. Its test file gives
the appearance of coverage.
Verifier(steps_per_site=1000, seeds=(1,2,3,4)) silently does nothing.expansion()
hardcodes 90 sweeps and one seed, which E113 measured as the worst corner of its budget
table. Anyone trying to escape the +11 per cent bias gets the bias, with no error.
Predicted, wiring the magnetic flag through to promotion:
Between 2 and 6 of the in-class finds on file carry an unmodelled transition, since
the nine-element set contains Cr and the class-constrained searches reached it — E134's
list included Cr0.25 Mo0.25 V0.25 W0.25 and similar.
None of the current top finds is affected, because the best in-class compositions are
Mo/W/Ta/Nb/Ti and carry no flagged element.
Fixing the Verifier parameters changes no current result, because every caller uses
the defaults, so this is a latent trap rather than a live error.
Falsified if a top find is flagged, which would mean the project's best in-class
composition has a failure mode no rung can evaluate, and the ranking needs re-deriving before
anything goes up the ladder.
EXPERIMENTS.md · lines 8879–8904
E146 result: all three wired, and prediction 2 holds — no top find is affected.
Verifier now honours seeds and steps_per_site.expansion() read its own
attributes instead of hardcoded 90/1. Prediction 3 confirmed: nothing currently changes,
because every caller uses the defaults. It was a latent trap, and a caller trying to escape
E113's +11 per cent bias would have silently got the bias.
The magnetic flag reaches promotion.verify() returns unmodelled and
promote_by_niche carries it, so a composition whose failure mode no rung can evaluate
arrives labelled. Checked on E134's in-class list: Cr0.25 Mo0.25 V0.25 W0.25 reports
['Cr'], as it should.
The reference convention is now checked at construction.Verifier.__init__ raises if
thermo._ref_shift is None. screen() adds equilibrium references to whatever
random_energy returns, and that return is on equilibrium references only ifcorrect_references() was called — which exactly one construction path did. Any other
silently double-counted the strain, up to 505 meV/atom for vanadium alone (E55). This is
the assertion MixingEnergy implies and never got to make.
Prediction 2 confirmed: the top in-class finds are Mo/W/Ta/Nb/Ti and carry no flagged
element, so the ranking does not move. Prediction 1 is untestable as stated — E134's saved
finds predate the flag, so the count of affected compositions can only be taken on the next
run, not from the file.
Two new tests. The MixingEnergy class itself still has no call site: what it guards is now
guarded, but by an inline assertion rather than by the type. That is the smaller fix and it is
the one that removes the live hazard; using the type properly would mean carrying conventions
through every energy in the pipeline, which is a refactor and not an hour's work.
EXPERIMENTS.md · lines 8906–8922
E146 correction: the guard broke four tests and I reported the commit before the suite
finished.
Verifier.__init__ now refuses an uncorrected thermo, and four tests in test_verifier.py
construct one — _StubThermo and a local _Thermo that exercise the DFT rung, which
never touches the expansion's references and so had no _ref_shift. The guard was right and
the doubles were incomplete; both now declare _ref_shift = 0.0, the honest value for a stub
holding no expansion, with a comment saying why.
234 passing, 2 skipped. Up two from 232 — the two new guard tests.
The process failure is worth recording separately from the code one. E146 was committed with
"two new tests, no current result changes" while a fourteen-minute suite was still running,
and it came back with four failures caused by that commit. That is the third report ahead of
the measurement tonight, after E128's number and E141's generalisation. The others were
expensive because they entered the scientific record; this one was cheap because a test caught
it. The pattern is the same and the rule already exists: measure, then write.
Related entries
E122 — Closing the magnetic hole, or rather admitting it