docs(#36): design doc §8/§10 — live-gate results and the String-node retarget

Claude-Session: https://claude.ai/code/session_01XPsuy2ZZ5Gbyfpt8PrK5BV
This commit is contained in:
Joseph Doherty
2026-09-10 15:54:11 -04:00
parent 29ca6b15ab
commit 31b1b8db76
@@ -170,9 +170,10 @@ not a `HandshakeResult` naming the phase it died in.
change).
- `docker/seed-delmia-sim.sh` — unchanged behaviour (static attributes; cache updates
synchronously so the race cannot occur); add a comment saying so.
- **Rig live gate** — `docker/seed-handshake-demo.sh`: a template with two data-sourced Boolean
attributes on writable OPC UA sim nodes (`Motor.Running` class, `CurrentReadOrWrite`, not
simulated so they hold what is written), a `Call` script using the new overload, and a
- **Rig live gate** — `docker/seed-handshake-demo.sh`: a template with two data-sourced **String**
attributes on the rig's two writable OPC UA String nodes (not simulated, so they hold what is
written; String rather than Boolean because of deferred-work register row 120, found by this
very gate), a `Call` script using the new overload, and a
ValueChange "device" script that sets the complete flag when the trigger rises. Proves the reset
echo round-trips through a real subscription and that `Phase` reports correctly.
- Deferred-work register — one row: *port the QA/prod MES receiver scripts (13/14/15/16/25/26/36/
@@ -186,3 +187,28 @@ Additive only: a new overload, two new Commons types, no message/proto/schema ch
scripts compile and behave identically. An older site receiving a script that uses the overload
fails the deploy gate's compile (the member does not exist there), which is the intended
mixed-version outcome — upgrade sites before porting scripts.
## 10. Live gate 2026-09-10 (docker rig, main after the #36 merge)
`docker/seed-handshake-demo.sh` → instance `handshake-demo-1` on site-a, flags on the rig's two
writable OPC UA **String** nodes (`TestChildObject.TestString` = Trigger, `JoeAppEngine.BTCS` =
Complete). The Boolean/Double nodes rejected the scalar writes with `BadTypeMismatch`
(`0x80740000`) — a pre-existing gap in the data-sourced scalar write path (only List values are
decoded before the DCL write; the OPC UA client sends the encoded string as a String variant),
recorded as deferred-work register row 120. The ordering this gate proves is identical on String
flags. `flow-debug run-script --instance-id <id> --script Handshake --show-logs`, two consecutive
runs, traced steps as reported by the CLI:
| Leg | Run 1 | Run 2 (cache holds run 1's `True`) |
|---|---|---|
| reset write `Complete = "False"` | 1 ms | 1 ms |
| reset-echo wait (`Complete == "False"`) | 217 ms, satisfied | **751 ms, satisfied** |
| batch + trigger write `Trigger = "True"` | 7 ms | 1 ms |
| response wait (`Complete == "True"`) | 2009 ms, satisfied | 2029 ms, satisfied |
| script result | `Matched=true, Phase=Response` | `Matched=true, Phase=Response` |
Run 2 is the #36 case: the cache still held `True` from run 1, the reset wait did **not**
fast-path, and the trigger was not written until the device echoed the reset 751 ms later. The
response wait is dominated by the Device script's own two data writes plus the subscription
round-trip. The optional negative control (planting a stale `True` with the OPC UA tool) was
skipped: `infra/tools/opcua_tool.py` needs the `asyncua` module, which is not installed here.