diff --git a/docs/plans/2026-08-05-skipped-tag-visibility-live-gate.md b/docs/plans/2026-08-05-skipped-tag-visibility-live-gate.md index 8410f7e3..6080625e 100644 --- a/docs/plans/2026-08-05-skipped-tag-visibility-live-gate.md +++ b/docs/plans/2026-08-05-skipped-tag-visibility-live-gate.md @@ -3,7 +3,8 @@ **Date:** 2026-08-05 **Rig:** local `docker-dev/` (OrbStack), MAIN pair `central-1` / `central-2`, AdminUI `http://localhost:9200` **Build under test:** `fix/541-skipped-tag-visibility` -**Result: PASS**, and the gate found one defect that unit tests did not (§4). +**Result: PASS.** The gate found one defect unit tests did not (§4). Round two on 2026-08-06 closed +the two items round one left unproven and corrected a wrong claim about the rig's topology (§6). ## What needed proving @@ -85,10 +86,47 @@ The three `pymodbus` blobs were restored from the pre-change backup and MAIN red shows `13 tags`. The three pre-existing skipping drivers were left exactly as they were — they are the rig's own configuration, not this gate's. -## Not proven here +## 6. Round two (2026-08-06) — truncation note + the central proto path -- The `+N more not shown` truncation note (needs a deployment skipping more than - `SkippedTagLedger.MaxSample` = 20 tags; unit-covered only). -- The central-side proto path — the rig's central pair is fused admin+driver, so the health snapshot - never crossed the Phase 5 gRPC telemetry stream. `TelemetryProtoMapCentral`/`Node` are unit-covered - round-trip only. +Both items round one left unproven were closed by one setup, chosen so that a single observation +settles both. **One correction first:** round one recorded "the rig's central pair is fused +admin+driver, so the snapshot never crossed the Phase 5 gRPC telemetry stream." That was wrong about +the rig. All six `ClusterNode` rows carry `GrpcPort 4056`, every node runs `Telemetry__Mode=Grpc`, and +central dials all six — the two `Telemetry stream to node …` lines seen in round one were startup +*failure warnings*, not the dial set. + +**Setup.** 25 tags with `region: NoSuchRegion` added to `sa-modbus2` on **SITE-A**, joining its one +good tag (26 total), then SITE-A deployed. SITE-A is the discriminator: Phase 6 partitioned it into +its own Akka mesh, so central's MEMBERS panel lists only `central-1:4053` and `central-2:4053`. +DistributedPubSub fans out within one mesh's mediator and does not federate, and the single +`akka.tcp://otopcua@site-a-1` reference in central's log is the ClusterClient **receptionist** — a +point-to-point command path, not gossip. So a SITE-A driver's health can reach central's `/hosts` by +exactly one route: `TelemetryProtoMapNode` → gRPC `TelemetryStreamService/Subscribe` → +`TelemetryProtoMapCentral`. + +**Result — 25 skipped of 26 authored:** + +| Fact | Observed | +|---|---| +| Chip | `25 / 26 SKIPPED`, `chip-warn` | +| Driver status | HEALTHY, 0 errors (as ever) | +| Sample entries in tooltip | **20** (= `SkippedTagLedger.MaxSample`) | +| Truncation note | **`(+5 more not shown)`** | +| Skips logged on `site-a-1` | 25 | + +That proves the truncation note, and simultaneously proves the proto path: the counts *and* all 20 +sample entries with their RawPath + reason survived the wire. + +**Positive control, doubling as the cap boundary.** Five of the 25 broken tags were deleted and SITE-A +redeployed. Central's page tracked the change made only on the site node — `20 / 21 SKIPPED`, sample +still 20, and **no truncation note**, correct at exactly `MaxSample` (the off-by-one that would have +read "+0 more not shown"). A live-updating view of a node with no gossip path is conclusive. + +**Rig restored:** all 25 test tags deleted, SITE-A redeployed, `sa-modbus2` back to `1 tag`; the +deployment revision hash returned to the pre-test `6178a8f3…`. + +## Still not proven live + +Nothing outstanding from the original two. Remaining unit-only coverage is the ledger's concurrency +guard (a torn read under a real init/publish interleaving) — inherently hard to force on a rig, and +the lock makes it a code-inspection matter rather than an observational one.