SAFETY-37: correct a wall-clock tick and a false size claim
checks / unit (pull_request) Successful in 5m32s

Two blocking findings from review, both in prose, both corrected at every
site.

1. "trips on tick 7" was not what the fixture prints. It prints 11, five
   runs out of five, and the developer's own report says 11. ⚠️ But the
   deeper problem is that the number should never have been quoted: the
   tick is counted on the WALL CLOCK inside cycle() (hold_s 2 s, ticks
   0.20 s apart), so it is load-dependent - 7 is what a box slow enough
   to stretch each tick to ~0.29 s would print - and nothing pins it.
   The DECISIONS transcript now says 11 because it is a transcript of a
   run; the CHANGELOG stops quoting a tick at all and states the
   checkable thing instead: it trips without the gate and never with it,
   which part 3 grades.

2. ⚠️ SURVIVOR 2's SIZE CLAIM WAS FALSE FOR ONE OF THE TWO CONSUMERS THIS
   CARD EXISTS TO PROTECT. It read "one contributing at most 250 W to a
   loop whose reporting floor is 700 W" at three sites. That bounds the
   COMMAND. Once the register is frozen its REPORTED value is unrelated
   to the command - which is exactly HW-01's shape: commanded ~0 W,
   register stuck on the last large number.

   Measured in review: a unit frozen at -1200 W beside a healthy +900 W
   sibling yields circulating_w = 1800 W against the 700 W floor, 2.6x
   OVER, with no gate armed.

   So the scoping is TRUE for the per-unit sign check and FALSE for
   circulation. Corrected to say exactly that, and the circulation
   consumer's exposure below MOVE_W is now recorded as a KNOWN GAP rather
   than a covered one.

   It survived because part 9's S2 check asserts only `not stale` and
   part 4 pairs the frozen unit with a RESTING sibling
   (circulating_w([A_FROZEN_W, 0.0]) == 0.0) - neither grades the size
   sentence.

No behaviour change. Full suite: 22 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
This commit is contained in:
glenn schrooyen
2026-09-06 12:35:27 +02:00
co-authored by Claude Opus 5
parent 6864109a01
commit 8e241a3243
3 changed files with 19 additions and 7 deletions
@@ -218,7 +218,7 @@ The counterfactual is run, not argued. `test_freshness.py` part 3 drives real
```
standing on A: [0, 445, 890, 1335, 1335, ...] (the shipped control law)
gated : sign trip tick=None circulating_w=[1800, 1800, 1800, None, None, ...]
counterfact : sign trip tick=7 circulating_w=[1800, 1800, 1800, 1800, 1800, ...]
counterfact : sign trip tick=11 circulating_w=[1800, 1800, 1800, 1800, 1800, ...]
```
---
@@ -257,7 +257,7 @@ surprises.
| # | kind | what survives | size |
|---|---|---|---|
| 1 | **false positive** | an inverter physically unable to follow — saturating, thermally derating, or a BMS refusing a charge — is declared stale while telling the truth | one spurious **site stop**, behind `stale_input_s`, self-clearing the moment the register moves. It cannot drive the battery anywhere |
| 2 | **miss** | a register frozen under a command that never travels 250 W is never detected, for 400 s or for ever | scoped, not overlooked: such a unit is one no per-unit sign check can speak about (`unit_sign_disagree_w` = 250 W) and one contributing at most 250 W to a loop whose reporting floor is 700 W |
| 2 | **miss** | a register frozen under a command that never travels 250 W is never detected, for 400 s or for ever | ⚠️ scoped for ONE consumer, NOT both, and the earlier claim here was wrong. TRUE for the per-unit sign check: no such check can speak about that unit (`unit_sign_disagree_w` = 250 W). **FALSE for circulation.** "Contributing at most 250 W" bounds the COMMAND; once the register is frozen its REPORTED value is unrelated to the command, which is exactly HW-01's shape - commanded ~0 W, register stuck on the last large number. Measured: a unit frozen at −1200 W beside a healthy +900 W sibling yields `circulating_w` = **1800 W against the 700 W floor, 2.6× over**, with no gate armed. Found in review; part 9's S2 check asserts only `not stale` and part 4 pairs the frozen unit with a RESTING sibling, so neither graded the sentence |
| 3 | **miss — the largest** | a dead publisher whose last values **alternate**, or a cache replaying two old samples, never starts the unchanged clock at all | **this gate detects a value that STOPPED; it cannot detect a value that is WRONG.** Nothing in this add-on can. TEL-06's arrival stamp inside the firmware is the only layer that could |
Recorded because it looks like a survivor and is not: a publisher failure that