From 26ef8131b0e1001054660d658171de2995822608 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 15 Jul 2026 18:14:03 -0400 Subject: [PATCH] docs(browse): Wave-0 live-gate result + follow-ups (Task 18) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- ...versal-discovery-browser-implementation.md | 34 +++++++++++++++++++ ...overy-browser-implementation.md.tasks.json | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/plans/2026-07-15-universal-discovery-browser-implementation.md b/docs/plans/2026-07-15-universal-discovery-browser-implementation.md index a08bbe5b..5f946d95 100644 --- a/docs/plans/2026-07-15-universal-discovery-browser-implementation.md +++ b/docs/plans/2026-07-15-universal-discovery-browser-implementation.md @@ -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). diff --git a/docs/plans/2026-07-15-universal-discovery-browser-implementation.md.tasks.json b/docs/plans/2026-07-15-universal-discovery-browser-implementation.md.tasks.json index 0c5f9151..f34d5db4 100644 --- a/docs/plans/2026-07-15-universal-discovery-browser-implementation.md.tasks.json +++ b/docs/plans/2026-07-15-universal-discovery-browser-implementation.md.tasks.json @@ -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" }