SAFETY-81 review: 10 s hold, ERROR line per episode, more scenarios
checks / unit (pull_request) Successful in 20m31s
infra-pin / fresh (pull_request) Successful in 2s

- The alarm must hold for peakguard.ALARM_HOLD_S (10 s) on the projection's
  clock. A load that tops cap + battery for ~5 s every 30 s alarmed at every
  quarter start while the quarter landed under the aim (sine4500_fast).
- A cycle with no battery reading leaves the hold alone.
- Notified once per quarter, but the ERROR line is written per episode.
- New sim scenarios (sine4500_fast, twice7000, step6500_gap) with 5a4cdc2
  digests; control still byte-identical. Unit checks for export and the
  hold across a missing reading. test_peakguard's saturated fixture moves
  the hold start back instead of waiting it out.
- DECISIONS and DOCS updated: costs of the hold, tolerance reasoning, the
  double count in control left to a follow-up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-29 20:58:37 +02:00
co-authored by Claude Opus 5.5
parent 6eb67c0f9c
commit f967073cfe
7 changed files with 170 additions and 47 deletions
+3
View File
@@ -870,6 +870,9 @@ def decide(projection, *, batt_w, cap_w, margin_w, reading, achievable_w, soc,
# "Load too high for battery" fires. Above the guard's own landing error at
# margin 0 (up to +5.7 W, SAFETY-79 test check 5), which margin 0 accepts.
ALARM_MISS_W = 10.0
# ...and for this long without a break, so a load that peaks for a few seconds
# (a hob or heater cycling) is not read as the rest of the quarter.
ALARM_HOLD_S = 10.0
def load_too_high(projection, *, batt_w, ceiling_w, achievable_w) -> bool: