SAFETY-18: verify on the real rig, and record what it showed

AC3 says "verified on the rig". The previous commit drove hwsim in-process
because `riglock status` reported UNKNOWN - which is the tool declining to
observe, not an observation. riglock shells out to the local docker CLI; on a
Windows host without DOCKER_HOST that resolves to a Docker Desktop npipe which
is not running, and the result is indistinguishable from a genuinely absent rig.
The rig was up the whole time. With DOCKER_HOST=ssh://homelab@192.168.2.147 it
reads FREE.

Re-run under sim/riglock.py against the real goodwe-sim compose project, with
the shipped modules staged into goodwe-sim-plant so they poll that container's
own hwsim while plantsim drives it. Both phases passed, lock released cleanly.

The rig produced a result the in-process stub could not, and it strengthens the
design rather than merely confirming it: in the NEGATIVE twin - +8000 W of house
load, healthy meter, correctly railed command - `active_power_w` did not move at
all, sitting at exactly 10130.0 W for 26 consecutive polls. The only thing
keeping `unchanged_s` at 0.0 s was the kWh registers advancing.

So the register terms in measurement_fingerprint() are not belt-and-braces for
this detector, they ARE the negative case: fingerprinted on the power figure
alone it would have raised a false alarm on a healthy meter under a real load,
which is precisely how a safety guard gets switched off. Recorded in freeze.py
so nobody simplifies the fingerprint without meeting that run first.

No behaviour change - documentation and the harness note only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015VXjA3LWccN1rJsk3okyPC
This commit is contained in:
glenn schrooyen
2026-08-30 02:49:55 +02:00
co-authored by Claude Opus 5
parent 7aa1bd052e
commit 0ba3a200fe
2 changed files with 37 additions and 0 deletions
+14
View File
@@ -71,6 +71,20 @@ meter, and a kilowatt advances a 1 Wh register every 3.6 s.
The two terms fail for independent reasons. That is the whole design.
⚠️ AND THE SECOND HALF OF THAT WAS MEASURED ON THE RIG, WITH A RESULT WORTH
READING CAREFULLY. Driving the real transport against the rig's own hwsim under
+8000 W of house load - a genuinely railed command, meter perfectly healthy - the
POWER FIGURE DID NOT MOVE AT ALL: `active_power_w` sat at exactly 10130.0 W for
26 consecutive polls. What kept `unchanged_s` pinned at 0.0 s was the kWh
registers advancing, and nothing else.
So the register terms in `measurement_fingerprint()` are not belt-and-braces
here, they are the entire negative case. A freeze detector fingerprinted on the
power figure alone would have raised a false alarm on that rig run - a healthy
meter, a real load, a correctly railed command - which is the exact failure mode
that gets a safety guard switched off. Anyone tempted to simplify the fingerprint
should read that run first.
------------------------------------------------------------------------------
WHERE `hold_s` COMES FROM
+23
View File
@@ -28,6 +28,29 @@ is replayed rather than lived.
same railed command against a meter that is still MOVING, at the same 10 s
threshold. If that one alarms, the detector is a `unchanged_s` threshold with
extra steps and the whole reason for the conjunction is gone.
------------------------------------------------------------------------------
THE RIG RUN THIS STANDS IN FOR
Part 3 is the portable version of a run done on the real rig - the `goodwe-sim`
compose project on 192.168.2.147, under `sim/riglock.py`, with the driver staged
into `goodwe-sim-plant` so it polls that container's own hwsim while plantsim
drives it. Both phases passed there. To repeat it:
DOCKER_HOST=ssh://homelab@192.168.2.147 python sim/riglock.py status
⚠️ WITHOUT `DOCKER_HOST` SET, ON A WINDOWS HOST, `riglock status` REPORTS
`rig: UNKNOWN` - it shells out to the local `docker` CLI, which resolves to a
Docker Desktop npipe that is not running. That is INDISTINGUISHABLE from a
genuinely absent rig, and it is not one: the rig lives on the homelab box and was
up the whole time. `UNKNOWN` is the tool declining to observe, not an
observation. Do not read it as "no rig" (this cost this ticket a wrong caveat).
The rig run also produced a result part 3's stub cannot: under +8000 W of house
load the meter's POWER FIGURE never moved - 10130.0 W for 26 consecutive polls -
and only the kWh registers kept `unchanged_s` at zero. See the note in
freeze.py; it is why the fingerprint's register terms are the negative case
rather than a nicety.
"""
import asyncio