docs: live-gate record for #541 on docker-dev (PASS; found the 0-tags defect)
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# Live gate — skipped-tag visibility (Gitea #541)
|
||||
|
||||
**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).
|
||||
|
||||
## What needed proving
|
||||
|
||||
The unit suites pin the ledger semantics, the publish fingerprint, the proto round-trip and the
|
||||
view-model. None of them prove the thing an operator actually depends on: that the **Tags** column on
|
||||
`/hosts` renders the right cell, in the right colour, with actionable detail, against a driver that is
|
||||
genuinely skipping tags on a real deployment.
|
||||
|
||||
## Method
|
||||
|
||||
The rig already carried eleven driver instances. Three of the thirteen tags on the `pymodbus` Modbus
|
||||
driver had their `TagConfig.region` rewritten to `NoSuchRegion` — the realistic shape of a bad blob —
|
||||
then MAIN was redeployed via `POST /api/deployments`. Backup of the original thirteen blobs taken
|
||||
first; all three restored and redeployed at the end (§5).
|
||||
|
||||
## Results
|
||||
|
||||
Driver logs confirmed the skips reached the driver:
|
||||
|
||||
```
|
||||
[WRN] Modbus tag config did not map to a definition; skipping. Driver=MAIN-modbus RawPath=pymodbus/plc/Probe3
|
||||
[WRN] Modbus tag config did not map to a definition; skipping. Driver=MAIN-modbus RawPath=pymodbus/plc/Probe4
|
||||
[WRN] Modbus tag config did not map to a definition; skipping. Driver=MAIN-modbus RawPath=pymodbus/plc/Probe5
|
||||
```
|
||||
|
||||
`/hosts` then rendered — note every other column on the `pymodbus` row reads perfectly healthy, which
|
||||
is the entire point:
|
||||
|
||||
| Driver | Status | Errors/5 min | Last error | Last read | **Tags** | Chip |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `pymodbus` | HEALTHY | 0 | — | advancing | **3 / 13 SKIPPED** | `chip-warn` (amber) |
|
||||
| `sql-oracle-fixture` | HEALTHY | 0 | — | advancing | **1 / 1 SKIPPED** | `chip-bad` (red) |
|
||||
| `sql-postgres-fixture` | HEALTHY | 0 | — | advancing | **1 / 1 SKIPPED** | `chip-bad` (red) |
|
||||
| `gate-modbus-renamed` | HEALTHY | 0 | — | advancing | **1 / 1 SKIPPED** | `chip-bad` (red) |
|
||||
| `abcip-browse` | HEALTHY | 0 | — | advancing | 5 tags | none |
|
||||
| `adsfa` (Calculation) | HEALTHY | 0 | — | — | 0 tags | none |
|
||||
| `opcua1` | FAULTED | 1 | (config error) | — | — | none |
|
||||
| `rtu-gate` | FAULTED | 1 | Connection refused | — | — | none |
|
||||
|
||||
Tooltip on the amber chip, verbatim:
|
||||
|
||||
> 3 of 13 authored tag(s) are not being polled. They report BadNodeIdUnknown and the driver's state
|
||||
> does not reflect them. pymodbus/plc/Probe3: TagConfig did not map to a definition ·
|
||||
> pymodbus/plc/Probe4: … · pymodbus/plc/Probe5: …
|
||||
|
||||
and on a red one:
|
||||
|
||||
> This driver is polling NONE of its 1 authored tag(s). …
|
||||
|
||||
**Three of the four skipping drivers were not planted.** `sql-oracle-fixture`, `sql-postgres-fixture`
|
||||
and `gate-modbus-renamed` were already misconfigured on this rig and had been silently skipping their
|
||||
tags for an unknown length of time, each reporting Healthy with zero errors. The column surfaced them
|
||||
on its first run — an unplanned but fairly direct demonstration of the defect being real rather than
|
||||
theoretical.
|
||||
|
||||
Restoring the three blobs and redeploying returned `pymodbus` to `13 tags` with no chip, which also
|
||||
exercises the clear-on-clean-rebuild path live.
|
||||
|
||||
## 4. Defect the gate found — `0 tags` on a driver that never built a table
|
||||
|
||||
The first pass rendered **`0 tags`** for `opcua1` and `rtu-gate`. Both are FAULTED, both have **two
|
||||
authored tags** in the ConfigDb, and neither ever completed `InitializeAsync` — so their ledgers had
|
||||
never committed and `Snapshot()` returned `SkippedTagReport.Empty`.
|
||||
|
||||
A zero report is a **positive claim** — *"this driver skipped nothing"* — and making it on behalf of a
|
||||
driver that never got as far as looking is precisely the quiet inaccuracy #541 exists to remove. Not
|
||||
caught by unit tests because every one of them drove a driver through a completed build first.
|
||||
|
||||
Fixed by making `ISkippedTagReporter.GetSkippedTags()` and `SkippedTagLedger.Snapshot()` return
|
||||
**null until the first committed build**, so the column shows the same em-dash it already used for a
|
||||
driver that cannot report at all. Both are *no answer*; neither is *nothing skipped*. Pinned by three
|
||||
new `SkippedTagLedgerTests` cases plus a corrected FOCAS assertion. Re-gated on a rebuilt image: both
|
||||
faulted drivers now render `—`, while `adsfa` — which genuinely has zero authored tags and **did**
|
||||
build — correctly still renders `0 tags`. That pair is the discriminating case.
|
||||
|
||||
## 5. Rig left as found
|
||||
|
||||
The three `pymodbus` blobs were restored from the pre-change backup and MAIN redeployed; `/hosts`
|
||||
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
|
||||
|
||||
- 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.
|
||||
Reference in New Issue
Block a user