Universal discovery browser: full controller-tree render is live-verify-blocked by the ab_server fixture (no @tags walk) #468
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
The Wave-0 universal Discover-backed browser (
DiscoveryDriverBrowser) merged to master (commit056887d6) — one generic browser that captures any discovery-capable driver'sITagDiscovery.DiscoverAsyncand serves it through the picker, lighting up AbCip/TwinCAT/FOCAS pickers with zero per-driver browser code. Design:docs/plans/2026-07-15-universal-discovery-browser-design.md; plan + live-gate result:docs/plans/2026-07-15-universal-discovery-browser-implementation.md(§ "Live-gate result").What the Task 18 live gate DID verify (docker-dev)
CanBrowsebinding chain works end-to-end.BrowserSessionService.OpenUniversalAsync -> DiscoveryDriverBrowser.OpenAsync -> RunCaptureAsync -> CaptureAsync -> DiscoverTreeAsync), withPatchForBrowsedemonstrably applied — the controller@tagswalk ran even though the authored config never setEnableControllerBrowse(that walk only runs when the flag is true).What is BLOCKED (this issue)
A populated controller-tag tree render + leaf-commit round-trip could not be verified. The libplctag
ab_servertest sim (ControlLogix fixture at10.100.0.35:44818,tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Docker/) implements tag read/write but not the CIP Symbol Object controller enumeration — the@tagswalk returnsErrorUnsupported. This is a fixture capability gap, not a code defect: the browse binding is proven alive andPatchForBrowseis proven to run in production.Definition of done
Point the universal browser at a symbol-enumeration-capable Allen-Bradley backend and confirm:
TagConfig.FullNameand the tag saves.Options: a real ControlLogix over VPN/on-prem, or an
ab_server/sim variant that serves@tags. TwinCAT (ADS symbol upload) and FOCAS (FixedTreeUntilStablesettle) have the same fixture-availability gap and can ride the same verification once a backend exists.Related follow-up (already fixed)
Driver-config-page pickers not passing live config -> fixed in commit
10e23f8b(threadedGetConfigJsonthroughAbCipDriverPage/TwinCATDriverPage/FOCASDriverPage).Closed by
c2c3c522— via the second option in the definition of done (a sim that serves@tags), since no real ControlLogix is reachable.What changed
The fixture now applies a vendored patch (
tests/Drivers/…AbCip.IntegrationTests/Docker/patches/) teachingab_serverto answer CIP 0x55 on class 0x6B, with partial-transfer paging. Checked against libplctag's ownlist_tags_logixrather than against our decoder — our decoder is the thing under test, so its agreement would have proved nothing. The clone is also pinned tov2.7.0; the Dockerfile described--branch releaseas "pinned" while tracking a branch that moves.Definition of done — all three green on docker-dev
AbCip → Device1 → Discovered, in wire order:Motor_Run,Line1_Count,Pump_1_Speed,TestArray,TestString,TestSINT,TestBOOL,TestREAL,TestDINT.Pump_1_Speed+TestDINTcommitted into the raw tree with their CIP tag paths inTagConfigand saved.The gate found a real defect
CipSymbolObjectDecoderadvanced to an even byte boundary after each symbol name. Entries are packed with no padding — libplctag walks them bysizeof(entry) + string_len, and a captured reply confirms it (281 bytes for nine entries; an even-padded stream would be 285). So any odd-length name desynchronised every entry behind it.Motor_Runis 9 bytes and first on the wire, so the browse in leg 1 would have shown that one tag and silently dropped the other eight.Every existing multi-entry test passed the whole time, because the test builder padded exactly as the decoder did — the pair agreed with each other and neither agreed with a controller. The builder no longer pads, and the layout is now pinned by the captured reply rather than by a restatement of the assumption. Restoring the alignment step reddens exactly the three new tests and none of the 29 others.
Two things the gate surfaced that it was not asked about
"dataType":"DInt"and the driver decodes off that field, not the row'sDataType. Filed rather than folded in here.@raw_cpu_typewhen no tags are authored, whichab_serverdoes not implement. Fixture limitation, documented in the fixture README; browse is unaffected.Explicitly NOT closed
This issue's last paragraph noted that TwinCAT (ADS symbol upload) and FOCAS (
FixedTreeUntilStablesettle) have the same fixture gap and could ride the same verification. They cannot ride this one — the patch teaches a CIP server to serve CIP symbol enumeration, and neither of those speaks CIP. Both still have no browsable backend in test, and #536 flags TwinCAT as sharing the data-type defect by inspection only for that reason.