AC 6 was not met for the reduction main.py actually hands decide(). The
reviewer removed the per-pack grading twice and the 19-file suite stayed green
both times. No shipped behaviour changes here - app/ is untouched. What changes
is what observes it.
WHY BOTH SURVIVED, and it is this repository's recurring defect landing on this
card's own Decision 2: under any rule-8-valid config every pack's
pack_floor_pct() equals peak_soc_floor, so `floors` is a list of IDENTICAL
numbers and max/min/first/last are four spellings of one answer. The only check
using a cut-out ABOVE the EMS floor - 12c's `_n1_deep` - ran on a roster of ONE,
where every reduction agrees. So no check ever evaluated binding_soc_floor() on
two packs whose floors differ. And the degeneracy is not a defence: this PR's own
argument ("unreachable is a claim about today's rule ordering, and
validate_startup_config() is also sim/inject.py's entry point") justifies writing
the reduction and equally obliges grading it.
* test_peakguard.py part 12c2 - NEW. binding_soc_floor() on a roster whose
per-pack floors ALL DIFFER: four SIMULATED cut-outs 30/25/40/35 %, each
strictly above peak_soc_floor, so max (40), min (25), first (30), last (35)
and the mean (32.5) are five different numbers and the extremes sit at
INTERIOR roster positions. Two packs structurally cannot separate those -
there max==last and min==first - and neither can three; four is the smallest
roster that can. Precondition is its own check (habit 1); the counterfactual
raises ONE pack - the last, neither extreme - past the old maximum and the
answer follows (habit 7); peak_soc_floor is then lifted above every cut-out
to grade the other side of the conjunction.
* test_peakguard.py part 12g - REWRITTEN as behaviour (habit 4). The old
assertion was `"self.packs" in <the unparsed call site>`, which `self.packs[:1]`
still satisfies. It now drives REAL Controller.cycle()s on a two-pack roster,
both packs at the same SoC, and reads PeakDecision.soc_floor - the argument,
echoed back by the shipped decide(). The cut-outs are the only thing varied,
and the SAME PAIR is carried in BOTH ORDERS.
* ⚠️ TWO MORE SURVIVORS, found by this round's own battery and recorded rather
than quietly repaired. (a) The first cut of 12g varied only pack B's cut-out,
so `self.packs[-1:]` (+5 bytes) agreed with the roster on both runs and stayed
green across all 19 files; the swapped pair closes it, and between the two
directions no single-position slice passes all three runs. (b)
binding_soc_floor()'s EMPTY-roster branch rewritten to `return None`
(-43 bytes) was green too - a defensive branch nothing in the suite reached.
Both directions of it are pinned now.
* wired_over_limit() gained a prepare(ctl) hook, inside its retry loop so every
attempt grades the same site.
* In-process mutation rows 22, 22b and 23 record all four survivors.
Nine further source mutations went through the harness on the fixed tree
(binding_soc_floor -> floors[0] / floors[-1], pack_floor_pct conjoining with
min, pack_permissions grading against packs[0], `any` -> `all` on the unknown
floor, Controller.packs reversed, decide(soc=) taking inverters[0].soc, and the
two survivors above). Seven were red on first run; the two survivors are now red
as well. Three of the nine have a ZERO byte delta and still went red, which is
the direction stale bytecode cannot fabricate - and the harness purged anyway.
MANDATORY PROOF, all in the CI image over a tree rsynced to a plain path and
bind-mounted :ro, bytecode entry count printed before and after the purge:
each of the four mutations now takes test_peakguard.py RED, and the unmutated
tree is 19/19 green (twice, plus test_peakguard.py five times in isolation -
card CI-06's flake did not reappear). The zero-byte one was proved to have RUN rather than
assumed: dis.get_instructions LOAD_GLOBALs were [float, pack_floor_pct, any,
min] and binding_soc_floor() returned 25.0 on the 12c2 roster where the shipped
code returns 40.0.
No measurement of inverter B appears anywhere. It does not physically exist.
Every second-pack and fourth-pack figure added here is SIMULATED and labelled at
its definition; only inverter A's 10 % is read off hardware. No hardware was
touched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU