Blazor does not serialize OnParametersSetAsync against its own outstanding
task, and the modal's `_open` bool cannot tell two opens apart. ResetAndResolveAsync
awaits LoadMergedProbeConfigAsync and ResolveGroupContextAsync and then wrote
_driverType/_mergedConfig/_effectiveDeviceId/_groupPrefix/_canBrowse/_disabledReason
with no staleness re-check, so a close-reopen onto another device let the first
open's late continuation install its device's browse context under the displayed
modal — "Connect & browse" would silently dial the wrong controller and the commit
would land under the wrong tag-group.
Ports the per-open `_openGeneration` counter proven in the two sibling modals
(RawManualTagEntryModal, RawTagModal, 2026-08-05) to every post-await write here:
after both awaits, in the catch's error banner, and in the finally. The finally is
the one departure from the sibling shape and it is load-bearing — this modal resolves
inside a try/finally, so a stale `return` still runs the tail and would drop the LIVE
open's spinner mid-resolve.
Pinned by four RawBrowseModalStaleOpenTests facts, each observed red before the guard
and each re-falsified afterwards by reverting only its own guard. The modal calls
StateHasChanged on the open path, which throws without a render handle, so the test
attaches an inert Renderer subclass (file-local BL0006 pragma); [Parameter]s are set
by reflection per the BL0005 convention.
AdminUI suite 1117/1117 green.
All three legs pass against the patched AbCip fixture: the edit modal and the
manual-entry grid both browse the live nine-tag symbol table, and an unreachable
device degrades to the graceful error chip while the modal still saves.
The gate also found a defect unrelated to this change and filed it as #539: the
AbCip discovery path (LibplctagTagEnumerator, LibplctagTemplateReader) passes
libplctag the bare host, so an authored non-default EtherNet/IP port is dropped
and the browse reaches whatever answers on 44818 — #534's defect surviving in the
discovery half. Discovered because the first negative-leg endpoint differed from
the fixture only by port, which never reached the wire.
Records the outcome in the design doc §6 (including the stale-open race the
review found and fixed in both modals), closes the follow-up in the tracking
doc and the universal-browser plan, and registers RawBrowseModal's shared
race shape in deferment.md §0.1 as the deliberate leftover.
The tracking doc and program-design §9 still showed Wave 0's live gate open —
it closed 2026-08-01 (c2c3c522). Both now record Waves 0-2 complete.
New design doc for the one residual item: the raw modals' typed tag editors
pass a '{}' stub as GetDriverConfigJson, so the AbCip/TwinCAT/FOCAS pickers'
Browse button captures against no endpoint and can never succeed. Decision:
wire the merged Driver+Device config through (the RawBrowseModal/Test-connect
seam already exists), not hide the button.