# PR 2 — Phase 2 Stream D Option B (archive v1 + E2E suite) → v2

**Source**: `phase-2-stream-d` (branched from `phase-1-configuration`)
**Target**: `v2`
**URL** (after push): https://gitea.dohertylan.com/dohertj2/lmxopcua/pulls/new/phase-2-stream-d

## Summary

Phase 2 Stream D Option B per `docs/v2/implementation/stream-d-removal-procedure.md`:

- **Archived the v1 surface** without deleting:
  - `tests/ZB.MOM.WW.OtOpcUa.Tests/` → `tests/ZB.MOM.WW.OtOpcUa.Tests.v1Archive/`
    (`<AssemblyName>` kept as `ZB.MOM.WW.OtOpcUa.Tests` so v1 Host's `InternalsVisibleTo`
    still matches; `<IsTestProject>false</IsTestProject>` so solution test runs skip it).
  - `tests/ZB.MOM.WW.OtOpcUa.IntegrationTests/` — `<IsTestProject>false</IsTestProject>`
    + archive comment.
  - `src/ZB.MOM.WW.OtOpcUa.Host/` + `src/ZB.MOM.WW.OtOpcUa.Historian.Aveva/` — archive
    PropertyGroup comments. Both still build (Historian plugin + 41 historian tests still
    pass) so Phase 2 PR 3 can delete them in a focused, reviewable destructive change.
- **New `tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.E2E/`** test project (.NET 10):
  - `ParityFixture` spawns `OtOpcUa.Driver.Galaxy.Host.exe` (net48 x86) as a subprocess via
    `Process.Start`, connects via real named pipe, exposes a connected `GalaxyProxyDriver`.
    Skips when Galaxy ZB unreachable / Host EXE not built / Administrator shell.
  - `HierarchyParityTests` (3) and `StabilityFindingsRegressionTests` (4) — one test per
    2026-04-13 stability finding (phantom probe, cross-host quality clear, sync-over-async,
    fire-and-forget alarm shutdown race).
- **`docs/v2/V1_ARCHIVE_STATUS.md`** — inventory + deletion plan for PR 3.
- **`docs/v2/implementation/exit-gate-phase-2-final.md`** — supersedes the two partial-exit
  docs with the as-built state, adversarial review of PR 2 deltas (4 new findings), and the
  recommended PR sequence (1 → 2 → 3 → 4).

## What's NOT in this PR

- Deletion of the v1 archive — saved for PR 3 with explicit operator review (destructive change).
- Wonderware Historian SDK plugin port — Task B.1.h, follow-up to enable real `HistoryRead`.
- MxAccess subscription push-frames — Task B.1.s, follow-up to enable real-time
  data-change push from Host → Proxy.

## Tests

**`dotnet test ZB.MOM.WW.OtOpcUa.slnx`**: **470 pass / 7 skip / 1 pre-existing baseline**.

The 7 skips are the new E2E tests, all skipping with the documented reason
"PipeAcl denies Administrators on dev shells" — the production install runs as a non-admin
service account and these tests will execute there.

Run the archived v1 suites explicitly:
```powershell
dotnet test tests/ZB.MOM.WW.OtOpcUa.Tests.v1Archive   # → 494 pass
dotnet test tests/ZB.MOM.WW.OtOpcUa.IntegrationTests  # → 6 pass
```

## Test plan for reviewers

- [ ] `dotnet build ZB.MOM.WW.OtOpcUa.slnx` succeeds with no warnings beyond the known
      NuGetAuditSuppress + NU1702 cross-FX
- [ ] `dotnet test ZB.MOM.WW.OtOpcUa.slnx` shows the 470/7-skip/1-baseline result
- [ ] Both archived suites pass when run explicitly
- [ ] Build the Galaxy.Host EXE (`dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host`),
      then run E2E tests on a non-admin shell — they should actually execute and pass
      against live Galaxy ZB
- [ ] Spot-read `docs/v2/V1_ARCHIVE_STATUS.md` and confirm the deletion plan is acceptable

## Follow-up tracking

- **PR 3** (next session, when ready): execute the deletion plan in `V1_ARCHIVE_STATUS.md`.
  4 projects removed, .slnx updated, full solution test confirms parity.
- **PR 4** (Phase 2 follow-up): port Historian plugin + wire MxAccess subscription pushes +
  close the high/medium open findings from `exit-gate-phase-2-final.md`.
