stated the wrong mechanism ⚠️ REVIEW FINDING, BLOCKING, AND IT IS THE EVIDENCE THAT WAS WRONG RATHER THAN THE BEHAVIOUR. Part 8b's cut-out arm claimed an "identical power trace" to the wedged arm and that "what separates them is `account()`". EVERY PART OF THAT WAS FALSE, and the check survived deleting the gate it named. Measured: cut-out arm, account() live named 0/200, distinct B shares: [0] cut-out arm, account() FORCED None named 0/200, distinct B shares: [0] wedged arm, account() live named 200/200, shares 77/125/133/154 W At its own cut-out the pack's usable energy ABOVE that cut-out is zero, so `weights()` answers 0.0, `_fill()`'s preferred pass gives it nothing, the healthy sibling covers the load alone so the last-resort pass never runs, and its share is 0 W ON ALL 200 CYCLES. A unit with a 0 W share is not in `asked`, so `len(asked) < 2` returns {} BEFORE EITHER ARM IS EVALUATED and `account()` is never consulted. Nothing was identical, "100 % of the ask" was 0/0, and the arm never reached the comparison it was written to grade. WHAT REPLACES IT IS A BETTER FACT, NOT A WEAKER ONE: at its own cut-out OPT-09 STOPS ASKING THE PACK AT ALL, so SAFETY-43's relative arm is never reached. That is a SECOND, INDEPENDENT protection sitting UPSTREAM of `account()` - the allocator declines to ask before the detector has to decline to alarm. So the arm is kept and re-pointed, not deleted: * the 0 W share is now ASSERTED (`_sat_last[1][Bee] == 0`), not inferred from the silence - a control that cannot say WHY it is quiet cannot fail; * the arm runs a SECOND time with `account()` DELETED (`no_account=True`) and must still be silent, which is what proves which mechanism does the work; * the account gate's claim is re-pointed at test_delivery.py part 1, where it is graded on a REAL positive 125 W share. ⚠️ AND IT WAS INVISIBLE FOR ONE REASON WORTH KEEPING: that was the ONLY line in part 8b that did not print its shares. `inverter-b+0` would have been on screen from the first run. Every line in the part prints them now. The derated control's vacuity guard also now asserts ITS OWN unit is asked, rather than re-asserting a different run's 200/200 - which is exactly why the old guard could not see this. ALSO, from the same review: N1 app/delivery.py said 0.05 was "twelve times more sensitive" than 0.85. 0.85/0.05 = 17 and no reading of the pair gives 12. An unsupported number in shipped source; replaced with what was actually measured. N2 M14's recorded count was 4 named checks in test_delivery.py and it is 5 - part 1's pre-existing "a shortfall AT the threshold is not one" also goes red. It under-claimed, so it never inflated the evidence, but a recorded figure that does not reproduce is still one. N3 test_delivery.py part 1 printed the alarm sentence with a bare `delinquent(...)["b"]`, which raises KeyError under M12/M13 and ABORTED THE FILE AT PART 1, leaving parts 2-8 ungraded. The direction is safe (an abort is a red; MUTATION.md's defect fabricates only greens) but the recorded coverage read smaller than the truth. It is a `.get` now, and M12/M13's counts are re-run: 7 and 7 named checks, not 5 and 6. CFG-07: the assessment is unchanged (worse by one control cycle, 35.0 -> 40.0 s, deliberately not fixed here) and now says WHEN it has to close - BEFORE INVERTER B IS COMMISSIONED (~2026-09-12), because the band is unreachable at N=1 and commissioning B is when it first becomes reachable - and that CFG-07 HAS NO DECISION DOCUMENT IN THIS TREE, so whoever takes it writes one first. No behaviour change. `delinquent()`'s two arms, the fraction, `min_w` and the N=1 path are all untouched by this commit. 27/27 suites green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
23 KiB
SAFETY-43 — delinquency measured against the ask, not against a flat 500 W
Status: closed. delivery.delinquent() names a unit whose short_by() gap
exceeds min_w or exceeds a fraction of that unit's own share. The fraction
is delivery.DELIVERY_SHARE_FRACTION = 0.85, derived on the campaign in §3.
⚠️ INVERTER B DOES NOT PHYSICALLY EXIST (expected ~2026-09-12; NOTES.md
§1.1b). plantsim.INVERTER_B is inverter A copied, measured=False, and
test_packshare.py's plant is modelled in that file. Every two-inverter
figure in this document is two copies of A. Nothing here is a measurement of
inverter B.
0. The defect, and why it is the quiet regime that matters
OPT-09 passes SoC- and capacity-aware weights to the allocator. A weight is
a function of a pack's energy headroom, not of what the pack delivers, so a
wedged unit — one that accepts its share and produces nothing — is weighted
down exactly like a legitimately low-headroom one. delinquent() read an
absolute gap, min_w = Tuning.saturation_w = 500 W. Shrinking the share
shrinks the gap. Measured end to end on the real loop (test_packshare.py
part 8b: real compute(), real plan(), real packshare.weights(), real
delivery.account(), real delinquent(); B wedged at a healthy 15 % against its
own 10 % cut-out, so no envelope closes and account() explains nothing — a
SAFETY-42 true positive by that card's own definition):
load 1500 W equal weights shares {a:1500, b:1500} named on 199/200
load 1500 W OPT-09 weights shares {a:1505, b: 125} named on 0/200
A unit delivering 0 of 125 W is 100 % delinquent and 125 W short. Only the absolute threshold disagreed.
⚠️ THE SUPPRESSED REGIME IS THE DANGEROUS ONE. At a load the healthy sibling
covers, the meter is satisfied (grid within 5 W of zero on that fixture),
unmet_w is 0 because both units accepted their shares, no envelope closes and
no action-log line fires. The delinquency alarm is the only instrument that
would have told the operator the site was quietly running one inverter.
1. What was NOT done, and it is the larger half of this card
⚠️ min_w WAS NOT LOWERED. It is Tuning.saturation_w — the gap at which
the control law itself concludes the inverter is not following — and it exists to
stop normal saturation being reported as delinquency. Lowering it trades a
missed alarm for a false one on every unit at once. SAFETY-41 spent four
attempts on notification cadence in this system and the owner's words were
"i'm getting really annoyed by the notifications in my HA".
So the change is an or, never a looser first arm:
named if short_by() > min_w OR short_by() > frac * share
Everything min_w named before is still named. Nothing min_w refused becomes
noisy unless the unit is delivering almost none of its ask, which is not
saturation-shaped at all. test_delivery.py part 1 runs all seven of its
existing delinquent() fixtures under both rules — share_frac=None is
SAFETY-42's rule exactly — and requires identical answers on every one.
The absolute arm's suppression window is therefore unchanged: still
site target < 2·min_w = 1000 W at equal weights, still
site target < min_w·(w_A+w_B)/w_B = 6500 W under OPT-09's weights on part 8b's
fixture. Part 8b still asserts both numbers, now as evidence that the first arm
did not move.
2. The evidence is a diff between two rules on ONE run
delinquent() takes share_frac, and None means the absolute arm alone.
That parameter exists for one reason: so the red and the green come out of one
run over one tree instead of out of two commits that a reader has to trust.
test_packshare.py part 8b grades every cycle twice:
load 1500 W OPT-09 weights absolute arm alone named on 0/200 cycles
load 1500 W OPT-09 weights the shipped rule named on 200/200 cycles
load 1500 W equal weights absolute arm alone named on 199/200 cycles
load 1500 W equal weights the shipped rule named on 200/200 cycles
The equal-weights arm gains exactly one cycle — the first, where the slew limit holds the split at 500/500, a 500 W gap is not over a 500 W threshold (the absolute bound is strict) and the relative arm names a box delivering none of its 500 W. That single cycle is the whole of what this card costs an arm that was already firing.
⚠️ THE PIN THAT INVERTED. Part 8b was written by OPT-09 to pin the suppressed behaviour, and its comment said: "if it ever goes red because the alarm fired, read the card that made it fire before 'fixing' this line." This is that card. The pin now asserts the opposite answer and keeps the old one beside it, measured rather than remembered.
3. ⭐ Deriving the fraction
⚠️ DERIVED ON THE SAME CAMPAIGN AS delivery_hold_s's FLOOR, not chosen.
admin/goodwe:sim/delivery_window.py — the harness TEST-21 committed —
gained a second grading axis: the same 2640 no-fault runs at N=2 (three
families × 6 gains × 5 slews × write staggers; every unit executes the share the
allocator gave it) and the same 2640 N=1 control runs, graded at the shipped
min_w = 500 W for each candidate fraction, on every cycle of every run — so a
pass grades every fraction it is given, and the absolute arm beside them, over
one tree and one set of runs. Every row in a pass is comparable to every other
row in it, run for run.
cd goodwe/sim && GOODWE_ADDON_REPO=/path/to/goodwe-addon \
python3 -B delivery_window.py --selftest --campaign --fractions
⚠️ THE TABLE BELOW WAS PRODUCED BY TWO PASSES; FRACTIONS NOW HOLDS ALL
TWENTY SO IT TAKES ONE. The derivation ran the shipped ten
(0.25 … 0.99) and then the ten that resolve the low end
(0.05 … 0.65) with only that tuple edited between them. The absolute-arm
control row came out identical in both (30.0 / 0.0 / 35.0 / 0.0, same argmax),
which is what says the two passes are one campaign. A table a reviewer cannot
reproduce without knowing to edit a line nobody wrote down is PROC-01's shape in
miniature, so the committed FRACTIONS was widened to all twenty in review: the
command above now reproduces every row below.
3.1 The curve
Worst continuous legitimate episode (the measure DeliveryWatchdog actually
sees — its window is cleared by any cycle that does not name), runs naming in
brackets:
share_frac |
reversals (of 1050) | flapping (of 840) | weighted (of 750) | N=1 control (2640) |
|---|---|---|---|---|
| absolute only | 30.0 s (460) | 0.0 s (0) | 35.0 s (403) | 0.0 s (0) |
| 0.05 | 85.0 s (826) | 0.0 s (0) | 90.0 s (616) | 0.0 s (0) |
| 0.10 | 75.0 s (824) | 0.0 s (0) | 90.0 s (607) | 0.0 s (0) |
| 0.15 | 70.0 s (836) | 0.0 s (0) | 70.0 s (609) | 0.0 s (0) |
| 0.20 | 70.0 s (839) | 0.0 s (0) | 60.0 s (629) | 0.0 s (0) |
| 0.25 | 55.0 s (832) | 0.0 s (0) | 60.0 s (611) | 0.0 s (0) |
| 0.30 | 55.0 s (840) | 0.0 s (0) | 50.0 s (614) | 0.0 s (0) |
| 0.35 | 55.0 s (840) | 0.0 s (0) | 55.0 s (618) | 0.0 s (0) |
| 0.40 | 50.0 s (840) | 0.0 s (0) | 60.0 s (658) | 0.0 s (0) |
| 0.45 | 45.0 s (840) | 0.0 s (0) | 45.0 s (627) | 0.0 s (0) |
| 0.50 | 45.0 s (840) | 0.0 s (0) | 45.0 s (636) | 0.0 s (0) |
| 0.55 | 40.0 s (840) | 0.0 s (0) | 40.0 s (636) | 0.0 s (0) |
| 0.60 | 40.0 s (840) | 0.0 s (0) | 40.0 s (645) | 0.0 s (0) |
| 0.65 | 35.0 s (840) | 0.0 s (0) | 45.0 s (635) | 0.0 s (0) |
| 0.70 | 35.0 s (840) | 0.0 s (0) | 45.0 s (635) | 0.0 s (0) |
| 0.75 | 35.0 s (840) | 0.0 s (0) | 45.0 s (635) | 0.0 s (0) |
| 0.80 | 35.0 s (840) | 0.0 s (0) | 45.0 s (635) | 0.0 s (0) |
| 0.85 | 35.0 s (840) | 0.0 s (0) | 40.0 s (635) | 0.0 s (0) |
| 0.90 | 35.0 s (840) | 0.0 s (0) | 40.0 s (635) | 0.0 s (0) |
| 0.95 | 35.0 s (840) | 0.0 s (0) | 40.0 s (635) | 0.0 s (0) |
| 0.99 | 35.0 s (840) | 0.0 s (0) | 40.0 s (635) | 0.0 s (0) |
Worst of the three families, which is what delivery_hold_s has to cover:
frac 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50
worst 90.0 90.0 70.0 70.0 60.0 55.0 55.0 60.0 45.0 45.0 s
frac 0.55 0.60 0.65 0.70 0.75 0.80 *0.85 0.90 0.95 0.99
worst 40.0 40.0 45.0 45.0 45.0 45.0 40.0 40.0 40.0 40.0 s
⚠️ THE FIRST ROW IS THE CONTROL AND IT REPRODUCED SAFETY-42 §3.3 EXACTLY —
30.0 s / 0.0 s / 35.0 s, and the same argmax (gain=0.2 slew_w=1000 stagger=4 split=0.10/0.90, ±2200 W reversal). It is measured in the same run as every
row below it, which is what makes those rows a comparison rather than a claim.
3.2 What the curve says
- ⚠️ THERE IS NO CLIFF ANYWHERE IN THE CURVE, AND THAT IS THE FINDING. From 0.45 to 0.99 every figure is 40.0 or 45.0 s — within one control cycle (5.0 s) of every other — and below 0.45 it rises gradually: 60.0 s at 0.25, 70.0 s at 0.15, 90.0 s at 0.05. A reviewer asking "why 0.85 and not 0.90?" is asking about a difference this campaign cannot resolve, and the honest answer is that it cannot.
- ⚠️ IT IS NOT MONOTONE — 0.40 reports 60.0 s where 0.35 reports 55.0, and 0.65–0.80 report 45.0 s where 0.55/0.60 and 0.85–0.99 report 40.0 — and that is SAFETY-42 §3.3's own mechanism (c) rather than noise in the plant: a more sensitive rule puts MORE units into the short set, which can turn a proper subset into the WHOLE roster and END the episode. The reduction is not monotone in its own threshold. Do not read this column as a sensitivity curve in the ordinary sense.
- The shoulder is at about 0.45, and it is a shoulder rather than an edge: the reversal family's naming count saturates at 840 of 1050 runs from 0.30 upward, so below the shoulder what grows is the LENGTH of an episode, not the number of runs that have one.
- The N=1 column is 0.0 s at every fraction, in all 2640 one-inverter runs. The compatibility promise is measured for the new arm, not argued.
- The flapping family is 0.0 s at every fraction, in all 840 runs. A common stimulus makes both units short at once and the subset stops being proper — the property that defeated SAFETY-30's site window still holds.
3.3 ⚠️ "Zero false namings" is not available at ANY fraction
The card asked for the largest fraction that yields zero false namings across the whole no-fault campaign. There is none. Every fraction adds naming cycles: the reversal family goes from 460 runs naming to 840, the weighted family from 403 to 635. A relative arm that never fired on a legitimate transient would be a relative arm that never fired at all — the write stagger lands B's number up to four cycles late, and a unit whose new command has not arrived is, for those cycles, delivering a small fraction of what is standing on its wire.
What is zero at every fraction is false alarms:
the longest continuous legitimate episode anywhere in the 20-point sweep is 90.0 s — at 0.05, the most sensitive fraction measured — against a
delivery_hold_sof 185 s. Nothing in 2640 no-fault runs comes within 95 s of notifying an operator, at any fraction measured. At the shipped 0.85 it is 40.0 s, i.e. 145 s of slack.
That is the quantity SAFETY-41 cares about and it is the one this card had to protect. Stated as margin, at the shipped fraction: 185 s is 4.62× the worst legitimate episode, where the absolute arm alone gave 5.29×.
3.4 The bounds 0.85 answers to
- LOWER, from the campaign — the shoulder at about 0.45, below which the added episode starts to grow (60.0 s at 0.25, 90.0 s at 0.05). 0.85 is 0.40 above it.
- UPPER, from the card's own case — strictly below 1.0. At 1.0 the arm can only fire on a unit that is importing while asked to discharge, which is SAFETY-30's fault and not this one, so a unit delivering none of its share (gap/share exactly 1.0) would be missed. The 0.15 below 1.0 is what covers a wedged box reporting a small standby figure instead of a clean zero.
- UPPER, from the hold — every fraction in the flat range leaves
delivery_hold_sbetween 4.11× (45.0 s) and 4.62× (40.0 s) the worst legitimate episode, well inside the four bounds SAFETY-42 §3.3 requires of it.delivery_hold_sIS NOT CHANGED BY THIS CARD. - ⚠️ NOT DERIVED, AND SAID SO: the exact value inside [0.45, 1.0). The campaign cannot separate them. 0.85 is the midpoint of the argument above — 0.40 of margin above the shoulder, 0.15 below the ceiling — and a re-derivation that moved it to 0.90 would be moving a number this campaign never resolved. It is not moved for that reason.
4. The positive control — what the relative arm must still NOT say
A card that adds a way to raise an alarm has to show what it did not add.
test_packshare.py part 8b runs the same fixture, the same weights and the same
125 W share with the one fact that makes the shortfall legitimate changed:
| fixture | B's share | named | why it is silent |
|---|---|---|---|
| B wedged at a healthy 15 % (the fault) | 77–154 W | 200 / 200 | — it is the fault |
| B at its own 10 % cut-out | 0 W, all 200 cycles | 0 / 200 | it is never asked |
| B delivering half its share | 120 W | 0 / 200 | short by 50 %, inside both arms |
⚠️ The cut-out row does NOT grade account(), and this record said it did
Corrected in review. The first draft of this section claimed the wedged and
cut-out arms had "identical power traces — 0 W against a positive share, 100 %
of the ask missing" and that "what separates them is account()". Every
part of that was false, and the check that carried it was vacuous:
- at its own cut-out the pack's usable energy above that cut-out is zero, so
packshare.weights()answers 0.0 for it,_fill()'s preferred pass gives it nothing, the healthy sibling covers the load alone so the last-resort pass never runs, and its share is 0 W on all 200 cycles; - a unit with a 0 W share is not in
asked, solen(asked) < 2returns{}before either arm is evaluated andaccount()is never consulted; - the traces are not identical — the cut-out arm's share is 0 W on every cycle (asserted in part 8b and printed on its line) while the wedged arm's is 125 W at the last cycle (asserted in the GREEN check) and takes four distinct values 77/125/133/154 W across the 200, measured by re-running the same loop with per-cycle recording during review — and "100 % of the ask" is 0/0.
Measured, by deleting the gate the claim rested on:
cut-out arm, account() live named 0/200, distinct B shares: [0]
cut-out arm, account() DELETED named 0/200, distinct B shares: [0]
wedged arm, account() live named 200/200, shares [77,125,133,154]
⚠️ The fact that replaces it is better, not weaker. At its own cut-out
OPT-09 stops asking the pack at all, so SAFETY-43's relative arm is never
reached — a second, independent protection sitting upstream of account():
the allocator declines to ask before the detector has to decline to alarm. Part
8b now asserts the 0 W share and prints it, and runs the arm a second time with
account() deleted to show which mechanism is doing the work.
⚠️ It was invisible for one reason worth keeping: that line was the only one
in part 8b that did not print its shares. inverter-b+0 would have been on
screen from the first run. Every line in that part prints them now, and the
derated control's vacuity guard now asserts its own unit is asked, rather
than re-asserting a different run's 200/200 — which is exactly why the old guard
could not see this.
The account gate is graded where it is real, on a positive 125 W share, in
test_delivery.py part 1 ("THE ACCOUNT GATE IS UNTOUCHED BY IT" — the same
0 of 125 W with the shortfall explained names nobody). That part also carries
that the relative bound is strict (a gap of exactly frac · share is not
over it) and that the proper-subset rule still refuses a site-wide cause (both
units delivering none of a 125 W share names nobody).
5. N=1 is byte-identical, and it is asserted rather than argued
The live install is N=1. Two independent statements, each graded against the
thing that would break it (test_packshare.py part 8b):
allocator.plan()returns beforeweightsis read at all. Graded by handing it aweightsmapping that raises on any read: at a roster of one it answers identically to the same call with no weights; at a roster of two the same mapping is read and raises, so the tripwire is a real one.delinquent()answers{}at a roster of one for every input — 84 combinations of (share, measured, rule), including 0 of 125 W, the exact input this card added an arm for.len(asked) < 2returns before either threshold is compared, so the fraction is never even multiplied.
Nothing in this card is reachable at one inverter. It must land before inverter B is commissioned (~2026-09-12), not before the next deploy.
5b. Mutation — the fraction is pinned from BOTH directions
⚠️ RUN, NOT REASONED ABOUT. Each mutation was applied to a tree copied
fresh from this branch and mounted :ro inside the checks image, so no .pyc
could go stale — MUTATION.md's defect, and all three of these are reds, the
direction that defect cannot fabricate. Recorded in test_packshare.py part 11
as M12–M14.
| mutation | named checks | where |
|---|---|---|
M12 drop the relative arm, keep gap > min_w — the card itself reverted |
7 | test_delivery.py part 1 (3: the 0-of-125 W naming, the proportion in the sentence, the strict relative bound) + test_packshare.py 8b (4: GREEN back to 0/200, the equal arm's 200 back to 199, the 6000 W arm back to 195/199, the derated control's guard). test_alloc.py / test_control.py stay green — nothing outside this check moves. |
M13 DELIVERY_SHARE_FRACTION → 1.0 — too loose |
7 | part 1 (2) + 8b (5), including the PRECONDITION that the fraction is strictly below 1.0. At 1.0 the card is a no-op: gap/share of exactly 1.0 is not over 1.0. |
M14 DELIVERY_SHARE_FRACTION → 0.05 — too sensitive |
6 | part 1 (2: the strict bound, and "IT TOOK NOTHING AWAY" stops being true) + part 4b (3: the saturation_w pin goes vacuous, the relative arm naming B at every threshold) + 8b's derated control, where a unit delivering half its share starts being named. |
M13 and M14 are the pair that matters: the constant cannot be moved in either direction without a named check moving with it.
⚠️ Two of these counts were wrong, and the reason is worth keeping
Corrected in review.
- M12 and M13 read 1 and 1 in
test_delivery.py, not 3 and 2. Part 1 printed the alarm sentence with a bare subscript,delinquent(_tiny, 500)["b"]. On any tree where the relative arm is broken or absent that raisesKeyErrorand aborts the file at part 1, leaving parts 2–8 ungraded — so the recorded coverage of a mutation run read smaller than the truth. The direction is safe (an abort is a red, and MUTATION.md's defect can only fabricate a green), but a figure that does not reproduce is a figure that does not reproduce. It is a.getnow, with the reason written beside it, and the counts above are from re-runs with the guard in place. - M14 was recorded as 4 named checks in
test_delivery.pyand it is 5 — part 1's pre-existing "a shortfall AT the threshold is not one" also goes red. That one under-claimed, so it never inflated the evidence; it is still a recorded number that did not reproduce.
6. ⚠️ CFG-07 is adjacent and is NOT absorbed here
CFG-07 is that delivery_hold_s is declared int(30,900) in config.yaml's
schema while the measured worst legitimate episode at the shipped threshold is
35.0 s — so the schema offers an operator a value (30) that is below a
measured legitimate episode and would report on ordinary saturation.
This card makes it worse, and by exactly one control cycle. The relative arm
takes the worst legitimate episode from 35.0 s to 40.0 s at the shipped
fraction, so the band of schema-legal but false-tripping values widens from
[30, 35] to [30, 40]. The floor the schema should have is now 40 s, not
35 s. It is not fixed here: raising a schema floor is an option-surface change
with its own compatibility argument (an existing config carrying 35 would start
being refused), and folding it into a safety fix would hide it. CFG-07 should
be re-derived against 40.0 s, not 35.0 s.
⚠️ WHEN IT HAS TO CLOSE: BEFORE INVERTER B IS COMMISSIONED (~2026-09-12).
Not before the next deploy. The band is unreachable at N=1 — delinquent()
returns {} for every input at a roster of one, so no value of
delivery_hold_s can false-trip on the install that is running today — and the
live install is N=1 until B exists. Commissioning B is the moment the band
becomes reachable, and that is the deadline this card hands it.
⚠️ AND CFG-07 HAS NO DECISION DOCUMENT IN THIS TREE. It exists as a
[[CFG-07]] mention in CHANGELOG.md and in this section, and nowhere else —
so there is no file for the 40.0 s to be recorded in, and a reader who goes
looking will find a card reference with no record behind it. Whoever takes
CFG-07 writes DECISIONS/CFG-07-*.md first; the number it has to answer to is
40.0 s, measured here, and the harness that produces it is
admin/goodwe:sim/delivery_window.py --campaign --fractions.
7. Provenance of every number in this document
| number | where it came from |
|---|---|
| 199/200, 0/200, 200/200, shares 1505/125 | test_packshare.py part 8b, run |
| 35.0 s absolute-arm floor, and its argmax | delivery_window.py --campaign, re-run here, reproduces SAFETY-42 §3.3 |
| every row of §3.1 | delivery_window.py --campaign --fractions, two passes over the same campaign with FRACTIONS changed between them |
| 1000 W / 6500 W suppression windows | part 8b's arithmetic, asserted there |
| 185 s, 5.29× | SAFETY-42 §3.3 / TEST-21, unchanged by this card |
| 4.62× | 185 / 40.0, printed by the campaign |
| 0/200 on both positive controls, and B's 0 W share at the cut-out | part 8b, run and asserted |
| 0 W cut-out share / 125 W wedged share | part 8b, asserted and printed |
| 77/125/133/154 W (the wedged arm's four distinct shares) | the same loop re-run in review with per-cycle recording — NOT part 8b's printed line, which shows the last cycle only |
| M12/M13/M14 named-check counts (7 / 7 / 6) | re-run in review on fresh :ro trees, after the KeyError abort in part 1 was guarded |
| 84 single-unit rosters | part 8b, run |
⚠️ Every two-inverter figure above is two copies of inverter A.