# 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.Tests` instantiate v1 `Host` classes 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**:
1. Build a `ProxyMxAccessClientAdapter` in a new `OtOpcUa.LegacyTestCompat/` project that
   implements v1's `IMxAccessClient` by forwarding to `Driver.Galaxy.Proxy.GalaxyProxyDriver`.
   Maps v1 `Vtq` ↔ v2 `DataValueSnapshot`, v1 `Quality` enum ↔ v2 `StatusCode` u32, the v1
   `OnTagValueChanged` event ↔ v2 `ISubscribable.OnDataChange`.
2. Same idea for `IGalaxyRepository` — adapter that wraps v2's `Backend.Galaxy.GalaxyRepository`.
3. Replace `MxAccessClient` constructions in `OtOpcUa.Tests` test fixtures with the adapter.
   Most tests use a single fixture so the change-set is concentrated.
4. 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.
5. 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**:
1. 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`.
2. New `tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.E2E/` project (.NET 10):
   - `ParityFixture` spawns Galaxy.Host EXE per test class with `OTOPCUA_GALAXY_BACKEND=mxaccess`
     pointing at the dev box's live Galaxy. Pattern from `HostSubprocessParityTests`.
   - 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.
3. The four 2026-04-13 stability findings get individual regression tests in this project.
4. 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.ps1` runs and exits 0
- [ ] `Get-Service aaGR, aaBootstrap` → Running
- [ ] `Driver.Galaxy.Host` x86 publish output verified at
      `src/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 -DryRun` produces a
      well-formed DriverConfig
- [ ] Service installer scripts dry-run on a test box: `scripts/install/Install-Services.ps1
      -InstallRoot C:\OtOpcUa -ServiceAccount LOCALHOST\testuser` registers both services
      and they start

Steps:
1. Delete `src/ZB.MOM.WW.OtOpcUa.Host/` (the legacy in-process Host project).
2. Edit `ZB.MOM.WW.OtOpcUa.slnx` — remove the legacy Host `<Project>` line; keep all v2
   project lines.
3. Migrate the dev `appsettings.json` Galaxy sections to `DriverConfig` JSON via the
   migration script; insert into the Configuration DB for the dev cluster's Galaxy driver
   instance.
4. Run the chosen test suite once more — confirm zero regressions from the deletion.
5. Build full solution (`dotnet build ZB.MOM.WW.OtOpcUa.slnx`) — confirm clean build with
   no references to the deleted project.
6. Commit:
   `git rm -r src/ZB.MOM.WW.OtOpcUa.Host` followed by the slnx + cleanup edits in one
   atomic commit titled "Phase 2 Stream D — retire legacy OtOpcUa.Host".
7. Run `/codex:adversarial-review --base v2` on the merged Phase 2 diff.
8. Record `exit-gate-phase-2-final.md` with: Option chosen, deletion-commit SHA, parity
   test count + duration, adversarial-review findings (each closed or deferred with link).
9. Open PR against `v2`, link the exit-gate doc + compliance script output + parity report.
10. 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.
