Files
goodwe-addon/goodwe_controller/DECISIONS/SAFETY-121-bound-every-quarter.md
T
glenn schrooyenandClaude 8bf25696cb
checks / unit (pull_request) Successful in 44m51s
infra-pin / fresh (pull_request) Successful in 1s
SAFETY-121: a recurring overload warns every quarter
TEST-23 F-1: on a 5 s meter a steady overload warned once in 70 min. The
loop was at its bound 4-5 cycles a quarter, all inside SAFETY-119's settle
of 12 cycles (60 s) and under its budget of 8 per 900 s. The simulation
fed the meter a cycle behind the battery reading, so the guard and the
charge chased each other and gave ~20 bound cycles a quarter.

The settle is now 4 cycles and 22 s (HANDBACK_CYCLES, SHORT_SPAN_S), and
the rolling budget one number, 11 per 900 s, at every cycle length. The
cycle length is no longer tracked. Commands unchanged; the re-pinned
digests of test_safety84/87 differ from bee7431 in OUTPUT_CLAMP rows only.
test_safety119 runs the rig's shape (meter in the same cycle) at 1-15 s
and checks a stop keeps the budget (review F2, X3).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 10:09:14 +02:00

5.4 KiB

SAFETY-121 - a recurring overload warns every quarter

Status: for review. Tests: test_safety119.py (parts 2, 4, 5, 6). Follows DECISIONS/SAFETY-119-bound-after-hand-back.md.

The defect (TEST-23, SAFETY-119 rig test F-1). 5 s meter, 2 x 2500 W, cap 5000 W, maintenance charge, no forecast, house 5100 W. bee7431 warned once in 70 min (04:31:01), then not at 04:45, 05:00 or 05:15. Base 75f0804 warned at every quarter start. The loop held the wire once a quarter, at its start, and was at its bound on 4 or 5 cycles. SAFETY-119's settle (12 cycles, 60 s at 5 s) covered all of them, and 5 cycles a quarter fit in its budget of 8 per 900 s.

Why the simulation said "every quarter". test_safety119.py fed the meter one cycle behind the battery reading (delay counts cycles: 5 s at a 5 s meter). Just after the loop leaves its rail, the guard's charge headroom (house = meter + battery) is then off by up to 5000 W, the charge pulls 2000 W, the guard steps in again, and the two chase each other: 8 to 10 hand-backs and about 20 bound cycles a quarter at 5 s (rig: 1 and 4-5). With the meter read in the same cycle (delay 0, the rig's shape) the sim gives the rig's numbers: 3 to 5 bound cycles a quarter at 5 s, all inside SAFETY-119's settle, and bee7431 warns in 0 to 2 of 7 quarters. The test now runs both shapes.

Decision. After a hand-back the loop's bound is hidden until 4 cycles (HANDBACK_CYCLES) and 22 s (SHORT_SPAN_S) have passed; across all hand-backs on at most 11 cycles (ROLLING_BOUND_CYCLES) in any 900 s. The budget no longer follows the cycle length, and the cycle length is not tracked. A stop ends the settle and keeps the budget. An over-rating always counts. Commands are unchanged.

Why it holds for any number of bound cycles a quarter. The settle is fixed: at most 3 cycles or 22 s after a hand-back, whichever is longer. A bound that lasts past it counts on its first cycle after it. So one hand-back a quarter, with the loop at its rail past the settle, warns in that quarter, whether it is 1 bound cycle or 100. A bound that never lasts past a settle counts once more than 11 are hidden within 900 s. Hidden are only shapes with at most 11 bound cycles in 900 s, each within 3 cycles or 22 s of a hand-back. That is the quarter-edge kick: in every steady-meter run below it is on the 1st to 3rd cycle after its hand-back (up to 30 s at a 30 s meter). In the rig's shape at 5 s the bound comes 30 to 55 s after the hand-back.

Sweep (goodwe-addon-checks:1, 2 h runs, scratch/SAFETY-121/dev/). Quarter edge = test_safety119 part 1 (house 800 W, cap 2500 W, no forecast). Overload = part 4 (2 x 2500 W, cap 5000 W, house 5050 or 5100 W, seeds 0-3). "Delay 1" is the old sim, "delay 0" the rig's shape.

meter quarter edge, runs with a warning (new / bee7431 / no fix) overload delay 1, quarters warned of 7 (new / bee7431 / no fix) overload delay 0, 5100 W (new / bee7431 / no fix)
1 s 0/70 / 0/70 / 68/70 7 / 7 / 7 7 / 7 / 7
2 s 0/70 / 0/70 / 39/70 7 / 7 / 7 7 / 7 / 7
3 s 0/70 / 0/70 / 40/70 7 / 7 / 7 7 / 7 / 7 (5050 W: 7 / 1-7 / 7)
5 s 0/70 / 0/70 / 40/70 7 / 7 / 7 7 / 0-2 / 7
10 s 0/70 / 0/70 / 40/70 7 / 7 / 7 7 / 0 / 7
15 s 0/70 / 0/70 / 40/70 7 / 4-7 / 7 no fix warns 0-1 (5300 W: 7 / 0 / 7)
20 s 0/60 / 0/60 / 30/60 7 / 5-7 / 7 no fix warns 0 (5300 W: 7 / 0 / 7)
30 s 0/60 / 0/60 / 30/60 7 / 3-5 / 7 no fix warns 0 (5300 W: 6-7 / 0 / 6-7)

Quarter-edge seeds: 1-30 with the meter in the same cycle, and 1-40 (1-30 at 20 and 30 s) with the test's 1-2 cycle delay. 5300 W: seeds 1-5. Commands identical to no fix and to bee7431 in all 1013 runs (these and the limits below). Choosing the numbers: the runs above were recorded without the fix and replayed through candidate rules; with 3, 4 or 5 cycles, budgets 9 to 13 met both cases at 1-30 s. 8 warns at the quarter edge (2 s, seed 25) and 14 misses quarters in the rig's shape (1 s, 5050 W), both checked in part 4. 11 is the middle, and 4 the middle of 3 to 5; with a jittery meter (below) 3 gave more false alarms, 5 more quiet quarters (replay).

First warning after one hand-back (the loop at its rail; later than no fix by): 11 s at 1 s, 22 s at 2 s, 24 s at 3 s, 25 s at 5 s (default), 30 s at 10 s, 45 s at 15 s, 60 s at 20 s, 90 s at 30 s, 180 s at 60 s. bee7431: 10, 20, 30, 40, 80, 90, 80, 120, 240 s. In the overload runs at 1 to 30 s, the first warning was at most 90 s later than without the fix.

Limits (measured, not fixed).

  • A meter that jitters by 30 % with cycle_floor_s 15 (11 seeds): with the test's 1-2 cycle meter delay the quarter edge warns on 2 of 11 seeds at 15 s, 2 at 20 s and 5 at 30 s (bee7431: 4, 0, 10; no fix: 11 each); with the meter in the same cycle on none (no fix: 10, 9, 11). The overload at 5100 W leaves up to 4 quiet quarters in a row at 15 and 20 s (bee7431: no warning at all on some seeds); at 5200 W at most 1.
  • With cycles over about 40 s, a bound that is never past a settle cannot use up 11 in 900 s, so it is never counted (part 5 prints it at 60 s).
  • Hidden as designed: a real bound with the kick's shape (at most 11 cycles in 900 s, each within 3 cycles or 22 s of a hand-back).

Re-pinned. test_safety84 (all six) and test_safety87 (n1_crossing, n1_above, n1_charge_low): only OUTPUT_CLAMP log rows differ from bee7431 and from no fix; commands, claims, guard and phases are the same.