SAFETY-12: record the six-minute observation, not just the unit check

test_loop.py proves the property in 35 s. This is the same three scenarios run
for six and three real minutes each, on one binary, and it is what AC2 and AC3
were actually asked for: 1 cycle before vs 24 after on a constant meter with the
command stuck at 220 W against a 350 W import, and byte-identical write
sequences on both the converged and the normally-changing meter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Du77usMj8XNKNFZGmUiWDa
This commit is contained in:
glenn schrooyen
2026-08-28 20:48:49 +02:00
co-authored by Claude Opus 5
parent 96a808a057
commit 8cc9438aec
+12
View File
@@ -84,6 +84,18 @@ per-cycle gain the tuning was measured against are unchanged - asserted in
`cycle_floor_s` reproduces the old behaviour exactly) and comparing the
commanded values.
Observed over six real minutes on the same rig, one binary, meter held at a
literally constant 350.0 W: **before, 1 cycle** (at startup) and then nothing,
the command stuck at 220 W against a 350 W import for the rest of the window.
**After, 24 cycles**, worst gap 15.14 s, and the ordinary PI ramp doing its job -
220, 430, 650, 860, 1080, 1300, 1510, 1730, 1940, 2000 W, one step per cycle,
rail at t=136 s and flat after. Three minutes with the meter parked at the
target instead: **1 cycle before, 12 after, and 19 writes either way - the same
19**. Three minutes on a normally-changing meter: **36 cycles and 49 writes on
both sides, the same values in the same order.** The heartbeat write count never
moves; the only writes the fix adds are the ten the loop was supposed to be
making all along.
15 s is bracketed, not round. Below it: arrivals are ~5 s (NOTES.md measures
4.97 s), detected up to 1 s late by the 1 s poll, and one dropped poll is
retried on the next tick - about 11 s worst case on a meter that is merely