# Arch-Review Remediation Plans — Index > **📊 Remediation status → [`STATUS.MD`](STATUS.md).** Round 1 (2026-07-08 review at `9cad9ed0`) is > **fully remediated and merged to master** — all 4 Criticals + guards + follow-ups #9–#13. The > 2026-07-12 **re-review at `f6eaa267`** produced an updated 12-item action list > ([`../00-OVERALL.md`](../00-OVERALL.md)) — see **Round 2 plans** below. > **✅ 2026-07-13 — ALL 12 ROUND-2 PLANS EXECUTED + MERGED** to `master` (`31c98200`), each as a Gitea PR > (#426–#437) in 3 dependency-ordered waves. Consolidated unit sweep green (integration + live-`/run` gates > deferred to a serialized heavy pass). See the "Round-2 COMPLETE" capstone at the bottom of > [`STATUS.md`](STATUS.md) for the PR/wave map, unit-sweep tallies, the 3 confirmed-pre-existing failures, and > the deferred heavy/live-pass checklist. ## Round 2 plans (2026-07-12, verified at `f6eaa267`) One plan per action item in the updated `00-OVERALL.md` prioritized list. Each verifies its findings against the tree, gives root cause → design (with alternatives) → file-level steps → tests → effort/risk, and ends with a bite-sized TDD task breakdown (classification / estimate / parallelizability) plus a co-located `.tasks.json` for resumable execution. | # | Plan | Findings | Tasks | Effort | |---|---|---|---|---| | 1 | [R2-01 S7 fault-path hardening](R2-01-s7-fault-hardening-plan.md) | 05/STAB-14 (High regression), STAB-15, STAB-8 seam note | 13 | S-M (~2–3 h) | | 2 | [R2-02 ResilienceConfig hardening](R2-02-resilience-config-hardening-plan.md) | 01/S-6 (High, +2nd brick vector), U-6 (delete), S-8, 04/C-7, S-7 race | 19 | S-M (~1 day) | | 3 | [R2-03 VT failure quality](R2-03-vt-failure-quality-plan.md) | 02/S13, S12, P7 | 12 | S (~2–3 h) | | 4 | [R2-04 Failure-visibility trio](R2-04-failure-visibility-plan.md) | 01/S-1, 06/S-1, 03/S4 (+ scripted-alarm emit gate) | 15 | M (~1.5–2 d + rig) | | 5 | [R2-05 AdminUI authz](R2-05-adminui-authz-plan.md) | 04/C-1 (38-page census; ConfigEditor + AuthenticatedRead policies + reflection guard) | 16 | S-M (~2.5–4 h) | | 6 | [R2-06 ServerHistorian fail-fast + 0.2.0 DataType](R2-06-serverhistorian-failfast-plan.md) | 06/S-11, U-7 (EnsureTags = upsert ⇒ retype probe), C-7 | 12 | S (~1 h + VPN gate) | | 7 | [R2-07 Surgical pure-adds](R2-07-surgical-pure-adds-plan.md) | 03/P1 — 3 phases; Phase 1 needs zero new sink members | 15 | L (~4–6 d) | | 8 | [R2-08 Async LDAP + HistoryRead](R2-08-ldap-historyread-async-plan.md) | 03/S2 (SDK raises callback under lock — worse than reported), S3 | 14 | M (~1.5–2 d) | | 9 | [R2-09 Driver fleet batch](R2-09-driver-fleet-batch-plan.md) | 05/STAB-3/4/5/8/12/16/17, ResolveHost, onError — 6 PR-sized sub-batches | 29 | L (~5.5–7 d) | | 10 | [R2-10 Resilience observability](R2-10-resilience-observability-plan.md) | 03/U10 = 04/U-5 — DPS mirror of the driver-health flow (+2 tracker bugs) | 11 | M (~1 day) | | 11 | [R2-11 TagConfig consolidation](R2-11-tagconfig-consolidation-plan.md) | 01/C-1, P-1 + 05 ReadEnum/Writable — 3-phase strictness rollout | 24 | M (~2–2.5 d) | | 12 | [R2-12 Repo hygiene](R2-12-repo-hygiene-plan.md) | 07/U-3/4/5/6, S-3, P-5, C-4/5/6 — destructive steps gated on sign-off | 13 | S (~½ day) | **Suggested execution order:** 1 → 2 → 3 (small, close everything new-and-sharp from the re-review) → 5 → 4 (the two-round-old Highs) → 6 → 12 (quick wins) → 10 → 11 → 8 → 9 → 7 (large). R2-01/02/03/05/06/12 have no cross-plan dependencies and can run in parallel branches; R2-09's B3 (PollGroupEngine v2) has explicit landing-order notes against R2-01; R2-11 Part 1 must precede any parse-site edits elsewhere. --- ## Round 1 (2026-07-08 at `9cad9ed0`) — COMPLETE, kept for reference Design + implementation plans for every finding in the 2026-07-08 architecture review (`archreview/*.md`, review commit `9cad9ed0`). Each plan verifies every finding against the current tree, then gives root cause → design (with alternatives) → concrete file-level steps → tests → effort/risk. ## Plan documents | # | Plan | Findings | Verification | |---|---|---|---| | 01 | [Core & composition](01-core-composition-plan.md) | 21 | all confirmed, 0 stale | | 02 | [Scripting & alarms](02-scripting-alarms-plan.md) | 30 | all confirmed, 0 stale | | 03 | [Server & runtime](03-server-runtime-plan.md) | 28 | all confirmed (U1 = stale *doc* only) | | 04 | [AdminUI](04-adminui-plan.md) | 20 | all confirmed (C-3/C-4 good, no action) | | 05 | [Protocol drivers](05-protocol-drivers-plan.md) | 37 + 1 positive | all confirmed, 0 stale | | 06 | [Gateway integrations](06-gateway-integrations-plan.md) | 28 (23 actionable) | all confirmed (U-1 = stale *doc*) | | 07 | [Client, tooling & engineering](07-client-tooling-engineering-plan.md) | 26 | all confirmed, 0 stale | **Total: ~190 findings planned. Zero were stale-because-already-fixed; the only "stale" items are two documentation drifts (CLAUDE.md Known Limitation 2) both flagged for correction.** ## The 4 Criticals (fix first) | # | Critical | Plan | Fix shape | |---|---|---|---| | 1 | Split-brain resolver never activated → no hard-crash failover | 03 S1 | `ClusterOptions.SplitBrainResolver = KeepOldestOption` + hard-kill failover test | | 2 | Production VT script timeout is dead code → one loop wedges the actor | 02 U2 (+U3) | Route through `TimedScriptEvaluator` + `CompiledScriptCache` | | 3 | S7 has no reconnect path → PLC reboot kills the driver | 05 STAB-1 | `IS7PlcFactory` seam + lazy `EnsureConnectedAsync` | | 4 | TwinCAT ADS subs orphaned after reconnect → silent data stop | 05 STAB-2 | Store replayable registration intent, replay on client swap | ## Cross-cutting guardrails (from OVERALL themes, span multiple plans) - **Theme #1 built-but-never-wired** — the recurring failure mode. Guardrails proposed across plans: reflection-exhaustive `DeferredAddressSpaceSink` forwarding test (03 U2, sequenced *before* the surgical-add work), wiring the OTOPCUA0001 analyzer repo-wide (07 C-1), a startup log line proving SBR is active (03 S1), and wiring/removing the dormant historian health surface (06 S-6). - **Theme #2/#6 fixes don't flow to shared templates** — Part B of plan 05: `PollGroupEngine` v2 (backoff + onError + delete the S7 fork), shared strict `ReadEnum`/`ReadBool`, `ConnectionBackoff` primitive, `ResolveHost`-via-resolver; plus `TagConfigIntent.Parse` in Commons (01 C-1) killing the 4-project byte-parity duplication. - **Theme #3 optimistic success** — failure-visibility fixes: `AddressSpaceApplyOutcome` failure field (01 S-1), Galaxy write fail-closed (06 S-1), primary-gate default-deny on unknown role (03 S4). - **Theme #4 verification gap** — CI to all unit suites + fail-on-skip (07 S-1/S-2), fault-injection tier (hard-kill / drop-PLC), the missing bUnit substitute = reflection/policy guards (04 C-1). - **Theme #5 doc drift** — fix CLAUDE.md Known Limitation 2 + scadaproj index (03 U1 / 06 U-1), ScriptAnalysis policy doc, Client.CLI docs (07 U-3). - **Theme #7 repo hygiene** — `git rm -r lib/` AVEVA DLLs, untrack planning files, delete Wonderware husks (07 U-4/U-5/U-6). ## Suggested execution order Front-loaded per the OVERALL prioritized action list — items 1–6 eliminate every Critical plus the two systemic guards (analyzer + CI) that stop the built-but-never-wired pattern recurring: 1. **Criticals** — 03 S1, 02 U2+U3, 05 STAB-1, 05 STAB-2 (each with its missing test) 2. **Systemic guards** — 07 C-1 (analyzer) + 07 S-1/S-2 (CI to all suites, fail-on-skip); 03 U2 (Deferred-sink forwarding test) 3. **Silent-corruption Highs** — 05 STAB-4/5 (AbCip lock, FOCAS caches), 05 Modbus timeout-fatal classification 4. **Failure-visibility Highs** — 01 S-1, 06 S-1, 03 S4 5. **AdminUI authz** — 04 C-1 (ConfigEditor policy + reflection guard) 6. **Perf** — 03 P1 (surgical pure-adds, after 03 U2 guard) 7. **Consolidation + hygiene + docs** — 01 C-1, 05 Part B, 07 U-4/U-5, doc fixes ## Open maintainer decision - **Prune vs. keep the dormant machinery** (01 U-2 / 02 U-1): the callerless Tier-C recycle machinery + `IDriverSupervisor`, and the ~2.4k-line `Core.VirtualTags` engine that production bypasses. Plans recommend retiring both *after* the live paths are hardened (02 U2/U3 first), but the delete-vs-keep call is the maintainer's.