SAFETY-103: test a dropped battery is not counted; guard a read
checks / unit (pull_request) Successful in 34m26s
infra-pin / fresh (pull_request) Successful in 1s

Mutation M13 (a battery out of the split counted in the house point)
survived; a direct check now kills it. win[0] is read through a guard
(test_named_absence).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 03:12:03 +02:00
co-authored by Claude Opus 5.5
parent 138e45b53f
commit 98dd110a4f
+7 -3
View File
@@ -118,7 +118,7 @@ def measure(rows, n, house):
seg = [r["target"] for r in rows if r["t"] >= te]
return dict(
end=te, swing=sw,
first=max(win[0]["cmd"][1:]),
first=max(win[0]["cmd"][1:]) if win else math.nan,
step=max(abs(b - a) for a, b in zip(seg, seg[1:])),
give=max(max(r["cmd"][1:]) for r in rows if r["t"] >= te),
gmin=min(r["grid"] for r in win), gmax=max(r["grid"] for r in win),
@@ -319,13 +319,13 @@ _c.inverters = [ia, ib]
check("N=1: nothing is tracked", _c._read_span == {})
def tail(now, grid, target, held=None):
def tail(now, grid, target, held=None, live=AB):
"""`_drain_grid_w` with A settling: the error it hands the loop (grid
minus aim) and the house point it holds."""
_c._now_mono, _c.grid, _c.target = now, grid, target
_c._drain_tail, _c._settle = {A}, {A: 0.0}
_c._drain_house = held
g = _c._drain_grid_w(AB)
g = _c._drain_grid_w(live)
return round(g - AIM, 6), _c._drain_house
@@ -374,6 +374,10 @@ check("a range from an older reading than the one in hand (a cycle the "
"loop did not run) is not used: A at its reading, 1241 W",
tail(15.0, 2000.0, 1140.0, held=1140.0) == (2011.0, 3151.0))
_c._read_span[A] = (0.0, 1241.0, 13.0)
check("⭐ a battery out of the split is not counted (the meter has its "
"power): B dropped, a grid of +2000 W puts the house at least at "
"2000 + 10 + 0 = 2010 W, not 1910 W",
tail(15.0, 2000.0, 1140.0, held=1140.0, live={A}) == (870.0, 2010.0))
_c._drain_tail, _c._settle, _c._drain_house = {A}, {}, 1140.0
_c.grid = -330.0
check("⭐ the tail's end lets the hold go: the meter again, and the next "