DEV-02: correct the operator instruction the latch rename made wrong
checks / unit (pull_request) Successful in 4m13s

HANDOVER.md told an operator to "delete `sign_tripped` from
/data/state.json" to clear a sign-disagreement trip by hand. After this card
that key is a FOSSIL: the live latch is `unit/<inverter>/sign_tripped`, and
the flat one is left in the file only so a rollback finds its latch and is
never read again. Following the old instruction would delete a key that clears
nothing, on the one path an operator reaches while staring at a FAILSAFE
banner - so the instruction would look like it had failed.

DOCS.md's §SAFETY-02 section named the file but not the key; it now names both,
and says why there is one per inverter.

No code change; the suite is unaffected and green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
This commit is contained in:
glenn schrooyen
2026-09-02 15:02:58 +02:00
co-authored by Claude Opus 5
parent e941bf7f62
commit d48c6b971d
2 changed files with 14 additions and 2 deletions
+11 -1
View File
@@ -83,7 +83,17 @@ rejected.
⚠️ **If you are testing the failsafe by hand, note that stopping and starting the ⚠️ **If you are testing the failsafe by hand, note that stopping and starting the
add-on will not clear a trip.** That is the point of it; use the *Start / stop add-on will not clear a trip.** That is the point of it; use the *Start / stop
control* button twice, or delete `sign_tripped` from `/data/state.json`. control* button twice, or delete the trip from `/data/state.json`.
⚠️ **DEV-02 renamed that key and the old name is now a fossil.** There is one
`SignWatchdog` per inverter, so the latch lives under
`unit/<inverter>/sign_tripped` — `unit/inverter-a/sign_tripped` on a
single-inverter site. The pre-DEV-02 flat `sign_tripped` is still written in
the file on purpose (so a rollback finds its latch) and is **never read again**,
so deleting it clears nothing. An install upgrading is migrated on first start,
and if the latch cannot be made to survive that migration the controller
re-arms it from the old key and says so in the log rather than coming up
disarmed.
⚠️ `test_loop.py` takes about **95 seconds** (measured 93 s) and that is not a bug. It ⚠️ `test_loop.py` takes about **95 seconds** (measured 93 s) and that is not a bug. It
drives the real control loop, which sleeps 1 s a tick, eight times over, to prove a drives the real control loop, which sleeps 1 s a tick, eight times over, to prove a
+3 -1
View File
@@ -306,7 +306,9 @@ does. That is deliberate on both counts:
always vanishes the instant the trip works. A watchdog that took that as proof always vanishes the instant the trip works. A watchdog that took that as proof
the fault was over would hand the inverter straight back to the loop that was the fault was over would hand the inverter straight back to the loop that was
driving the wrong way, three minutes later, forever. driving the wrong way, three minutes later, forever.
- The trip is written to `/data/state.json` and restored on startup. Restarting - The trip is written to `/data/state.json` — under
`unit/<inverter>/sign_tripped`, one key per inverter since DEV-02, so a trip
caused by one inverter cannot latch another — and restored on startup. Restarting
the add-on is the first thing most people try when they see a red banner, and the add-on is the first thing most people try when they see a red banner, and
a latch that a restart clears would bring the controller back **armed, into the a latch that a restart clears would bring the controller back **armed, into the
same fault, unattended** — and under a Supervisor that restarts a crashed add-on same fault, unattended** — and under a Supervisor that restarts a crashed add-on