5.8 KiB
Stream D — Legacy OtOpcUa.Host Removal Procedure
Sequenced playbook for the next session that takes Phase 2 to its full exit gate. All Stream A/B/C work is committed. The blocker is structural: the 494 v1
OtOpcUa.Testsinstantiate v1Hostclasses directly, so they must be retargeted (or archived) before the Host project can be deleted.
Decision: Option A or Option B
Option A — Rewrite the 494 v1 tests to use v2 topology
Effort: 3-5 days. Highest fidelity (full v1 test coverage carries forward).
Steps:
- Build a
ProxyMxAccessClientAdapterin a newOtOpcUa.LegacyTestCompat/project that implements v1'sIMxAccessClientby forwarding toDriver.Galaxy.Proxy.GalaxyProxyDriver. Maps v1Vtq↔ v2DataValueSnapshot, v1Qualityenum ↔ v2StatusCodeu32, the v1OnTagValueChangedevent ↔ v2ISubscribable.OnDataChange. - Same idea for
IGalaxyRepository— adapter that wraps v2'sBackend.Galaxy.GalaxyRepository. - Replace
MxAccessClientconstructions inOtOpcUa.Teststest fixtures with the adapter. Most tests use a single fixture so the change-set is concentrated. - For each test class: run; iterate on parity defects until green. Expected defect families: timing-sensitive assertions (IPC adds ~5ms latency; widen tolerances), Quality enum vs StatusCode mismatches, value-byte-encoding differences.
- Once all 494 pass: proceed to deletion checklist below.
When to pick A: regulatory environments that need the full historical test suite green, or when the v2 parity gate is itself a release-blocking artifact downstream consumers will look for.
Option B — Archive the 494 v1 tests, build a smaller v2 parity suite
Effort: 1-2 days. Faster to green; less coverage initially, accreted over time.
Steps:
- Rename
tests/ZB.MOM.WW.OtOpcUa.Tests/→tests/ZB.MOM.WW.OtOpcUa.Tests.v1Archive/. Add<IsTestProject>false</IsTestProject>so CI doesn't run them; mark every class with[Trait("Category", "v1Archive")]so a future operator can opt in via--filter. - New
tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.E2E/project (.NET 10):ParityFixturespawns Galaxy.Host EXE per test class withOTOPCUA_GALAXY_BACKEND=mxaccesspointing at the dev box's live Galaxy. Pattern fromHostSubprocessParityTests.- 10-20 representative tests covering the core paths: hierarchy shape, attribute count, read-Manufacturer-Boolean, write-Operate-Float roundtrip, subscribe-receives-OnDataChange, Bad-quality on disconnect, alarm-event-shape.
- The four 2026-04-13 stability findings get individual regression tests in this project.
- Once green: proceed to deletion checklist below.
When to pick B: typical dev velocity case. The v1 archive is reference, the new suite is the live parity bar.
Deletion checklist (after Option A or B is green)
Pre-conditions:
- Chosen-option test suite green (494 retargeted OR new E2E suite passing on this box)
phase-2-compliance.ps1runs and exits 0Get-Service aaGR, aaBootstrap→ RunningDriver.Galaxy.Hostx86 publish output verified atsrc/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host/bin/Release/net48/- Migration script tested:
scripts/migration/Migrate-AppSettings-To-DriverConfig.ps1 -AppSettingsPath src/ZB.MOM.WW.OtOpcUa.Host/appsettings.json -DryRunproduces a well-formed DriverConfig - Service installer scripts dry-run on a test box:
scripts/install/Install-Services.ps1 -InstallRoot C:\OtOpcUa -ServiceAccount LOCALHOST\testuserregisters both services and they start
Steps:
- Delete
src/ZB.MOM.WW.OtOpcUa.Host/(the legacy in-process Host project). - Edit
ZB.MOM.WW.OtOpcUa.slnx— remove the legacy Host<Project>line; keep all v2 project lines. - Migrate the dev
appsettings.jsonGalaxy sections toDriverConfigJSON via the migration script; insert into the Configuration DB for the dev cluster's Galaxy driver instance. - Run the chosen test suite once more — confirm zero regressions from the deletion.
- Build full solution (
dotnet build ZB.MOM.WW.OtOpcUa.slnx) — confirm clean build with no references to the deleted project. - Commit:
git rm -r src/ZB.MOM.WW.OtOpcUa.Hostfollowed by the slnx + cleanup edits in one atomic commit titled "Phase 2 Stream D — retire legacy OtOpcUa.Host". - Run
/codex:adversarial-review --base v2on the merged Phase 2 diff. - Record
exit-gate-phase-2-final.mdwith: Option chosen, deletion-commit SHA, parity test count + duration, adversarial-review findings (each closed or deferred with link). - Open PR against
v2, link the exit-gate doc + compliance script output + parity report. - Merge after one reviewer signoff.
Rollback
If Stream D causes downstream consumer failures (ScadaBridge / Ignition / SystemPlatform IO
clients seeing different OPC UA behavior), the rollback is git revert of the deletion
commit — the whole v2 codebase keeps Galaxy.Proxy + Galaxy.Host installed alongside the
restored legacy Host. Production can run either topology. OtOpcUa.Driver.Galaxy.Proxy
becomes dormant until the next attempt.
Why this can't one-shot in an autonomous session
- The parity-defect debug cycle is intrinsically interactive: each iteration requires running the test suite against live Galaxy, inspecting the diff, deciding if the difference is a legitimate v2 improvement or a regression, then either widening the assertion or fixing the v2 code. That decision-making is the bottleneck, not the typing.
- The legacy-Host deletion is destructive — needs explicit operator authorization on a real PR review, not unattended automation.
- The downstream consumer cutover (ScadaBridge, Ignition, AppServer) lives outside this repo and on an integration-team track; "Phase 2 done" inside this repo is a precondition, not the full release.