docs(browse): Wave-0 live-gate result + follow-ups (Task 18)

Live-verified on docker-dev: AbCip picker renders Browse button (full CanBrowse chain), clicking
it runs the universal-browser capture in production (central-2 logs) with PatchForBrowse
demonstrably applied (@tags walk ran without the authored config setting EnableControllerBrowse);
error surfaces gracefully. Modbus picker shows NO Browse button (negative). Populated tree-render
is fixture-blocked — ab_server returns ErrorUnsupported for the controller @tags walk (test sim
limitation, not a code defect). Two follow-ups recorded: (1) full tree-render needs a symbol-browse
capable AB backend; (2) driver-page pickers don't pass live config to the picker body.
This commit is contained in:
Joseph Doherty
2026-07-15 18:14:03 -04:00
parent 014c76b986
commit 26ef8131b0
2 changed files with 35 additions and 1 deletions
@@ -1083,6 +1083,40 @@ Identical shape (confirm DriverType string from the FOCAS `Register()`). Note in
---
## Live-gate result (Task 18 — docker-dev, 2026-07-15)
Executed against the local docker-dev rig (both centrals rebuilt from `feat/universal-discovery-browser`)
with the ControlLogix `ab_server` fixture up on `10.100.0.35:44818`. An AbCip driver (device
`ab://10.100.0.35:44818/1,0`, **`EnableControllerBrowse` deliberately left off**) was authored under an
Equipment-kind namespace and bound to an equipment; a tag was added on the Tags-tab TagModal.
-**Positive binding** — the AbCip address picker renders the **"Browse controller"** button. This
exercises the whole `CanBrowse` chain end-to-end: `SupportsOnlineDiscovery=true``BrowserSessionService.CanBrowse`
`DiscoveryDriverBrowser.CanBrowse` (constructs a throwaway driver with `PatchForBrowse`) → TagModal
`DriverType`/`GetDriverConfigJson` params → `AbCipTagConfigEditor` pass-through → `AbCipAddressPickerBody._canBrowse`.
-**Browse invocation runs in production** — clicking Browse drove the full capture path; central-2 logged
`BrowserSessionService.OpenUniversalAsync → DiscoveryDriverBrowser.OpenAsync → RunCaptureAsync → CaptureAsync
→ DiscoverTreeAsync`. Because the driver's authored config did **not** set `EnableControllerBrowse` yet the
capture attempted the controller `@tags` walk (which only runs when that flag is true), **`PatchForBrowse`
is demonstrably applied end-to-end**. The error surfaced as a graceful UI chip — no dead binding, no crash,
no hang; bounded shutdown ran.
-**Negative binding** — the Modbus picker shows only the manual Register/Offset/Length builder, **no Browse
button** (`SupportsOnlineDiscovery` false; picker body unchanged).
- ⚠️ **Not verifiable on this fixture** — a *populated* tree render + leaf-commit. The libplctag `ab_server`
test sim returns `ErrorUnsupported` for controller symbol enumeration (it implements tag read/write, not the
`@tags` Symbol Object walk). This is a **fixture limitation, not a code defect** — the binding is proven alive.
### Follow-ups discovered during the gate
1. **Full tree-render verification is fixture-blocked.** `ab_server` doesn't implement the `@tags` controller
walk. To live-verify a populated tree + `TagConfig.FullName` leaf commit, point the universal browser at a
symbol-enumeration-capable AB backend (a real ControlLogix, or a sim that serves `@tags`).
2. **Driver-page address pickers pass no live config.** `AbCipDriverPage`/`TwinCATDriverPage`/`FOCASDriverPage`
host the same `*AddressPickerBody` but do **not** pass `DriverType`/`GetConfigJson`, so their (now-visible)
Browse button would capture against `"{}"` (no device). Out of Task 14's scope (which listed only the
TagEditor pass-through); wire the live form config through there too, or hide the Browse affordance on the
driver-config picker.
## Out of scope (explicitly)
- TwinCAT/FOCAS live-fixture verification (no shipped fixtures assumed reachable; AbCip is the gate).
@@ -19,7 +19,7 @@
{"id": 15, "subject": "Task 15: TwinCAT picker body universal browse mode", "status": "completed", "blockedBy": [10, 12, 13, 4], "parallelWith": [14, 16]},
{"id": 16, "subject": "Task 16: FOCAS picker body universal browse mode", "status": "completed", "blockedBy": [10, 12, 13, 5], "parallelWith": [14, 15]},
{"id": 17, "subject": "Task 17: Full build/test sweep + doc status flip", "status": "completed", "blockedBy": [14, 15, 16]},
{"id": 18, "subject": "Task 18: Live /run verify on docker-dev (GATE)", "status": "pending", "blockedBy": [17]}
{"id": 18, "subject": "Task 18: Live /run verify on docker-dev (GATE)", "status": "completed", "blockedBy": [17]}
],
"lastUpdated": "2026-07-15T17:30:00Z"
}