diff --git a/deferment.md b/deferment.md index f37496e9..6f3dc75f 100644 --- a/deferment.md +++ b/deferment.md @@ -59,7 +59,7 @@ So everything below is **untracked work**. Nothing in it is a data-loss or outag | ~~**3 carried-open archreview findings** — the failure-visibility trio~~ **Update 2026-08-07 (truth sweep): mostly CLOSED.** 01/S-1 **FIXED** — `AddressSpaceApplier.cs:95-97` tallies swallowed removal-pass failures into `AddressSpaceApplyOutcome.FailedNodes` (comment cites 01/S-1). 03/S4 **FIXED** — `PrimaryGatePolicy.cs` default-denies on unknown role when a driver peer exists (doc-comment "Fixes archreview 03/S4"), live-proven R2-04 T15. 06/S-1 **PARTIAL** — fail-closed advise path + `galaxy.writes.unconfirmed` meter shipped in `GatewayGalaxyDataWriter.cs`; residual = gateway-side WriteComplete correlation (cross-repo, mxaccessgw). **Update 2026-08-09: the gateway half SHIPPED** — mxaccessgw main `b948e69` correlates the worker's `OnWriteComplete` onto the unary `WriteSecured` reply (`statuses[0]`; bounded wait default **1.5 s** — deliberately under OtOpcUa's 2 s Tier A Write budget, configurable via `MxGateway:Worker:WriteCompletionWaitMilliseconds`; timeout falls back to today's empty-statuses shape, still metered unconfirmed). **Update 2026-08-09 (later): 06/S-1 CLOSED — live-gated end to end, and the gate found + fixed three defects.** The user-authorized redeploy exposed (1) the correlation covered `WriteSecured` only while OtOpcUa's dominant no-login path emits plain `Write` — fixed gateway-side (worker `53f69cd`, all four unary write kinds, redeployed both hosts); (2) OtOpcUa's `StatusCodeMap.FromMxStatus` truncated the correlated failure row's MxStatus detail code to a byte (`1007 & 0xFF = 239` → OPC DA Good band), mapping a REFUSED write to Good — fixed with the not-IsSuccess-never-Good invariant + category routing (`SECURITY_ERROR → BadUserAccessDenied`); (3) the writer's borrow-from-subscription-registry optimization could never commit (a subscription handle is plain-advised; MXAccess refuses the no-login write `SECURITY_ERROR 1008` AND the advise upgrade `E_INVALIDARG` — one advise per HANDLE, not per attribute) — borrow path REMOVED, writer always owns a supervisory-advised handle. Live legs all PASSED on windev: happy write Good off confirmed `statuses[0]` + both meters flat; read-only refusal surfaces Bad-family + node-revert input; `WriteCompletionWaitMilliseconds=0` control → provisional Good + metered unconfirmed (override removed after). Pinned by `Live_correlated_write_statuses_confirm_commit_and_surface_refusal`, `Live_write_to_subscribed_tag_commits_via_own_handle`, `GatewayGalaxyWriteMeterLiveTests`, and the new `StatusCodeMapTests` rows. | ~~Residual is only the 06/S-1 live leg~~ **CLOSED 2026-08-09** — nothing remains. | §6.3 | | ~~**1 genuinely unexecuted plan** — `2026-05-29-adminui-followups`, **19 pending / 0 completed**~~ ✅ **CLOSED 2026-08-07 by the overlap audit it asked for — it was bookkeeping drift, not backlog.** All 19 tasks are shipped, superseded by v3, or moot; **no code was needed.** The warning was right and then some: WS1's whole *premise* died with v3 (driver-embedded tag lists in `DriverConfig` are no longer the runtime source of truth — the artifact populates `RawTags`), and its capability was delivered in the v3 shape (`TagConfigEditorMap` + `DeviceFormMap`, both verified **reachable**, not merely present). WS2/WS3 shipped; WS4's target files were deleted by v3 Batch 2 + #542. Per-task evidence in the `.tasks.json`. | §6.2 | | ~~**11 other open plan tasks**~~ **3 as of 2026-08-10** — ~~5 akka-hosting partials (likely v3-superseded)~~ *(verified superseded 2026-08-07 — F8/F9/F10/F13/F14 marked completed; `Phase7Composer`/`ScriptedAlarmActor` deleted, evaluators/SDK sinks/security policies all production-wired)*, ~~4+1 followups-batch (open *by choice*)~~ *(2026-08-10: Tasks 9 + 10 VERIFIED PASS live — Int64 authoring end-to-end on the rebuilt rig; probe E2E 12/12 with the "needs Windows-VM" premise corrected to TCP-reachability gating)*, ~~fixedtree Task 11~~ *(closed 2026-08-10: obsolete — the injection feature it gated was deleted with #507)*, ~~1 manual smoke checklist~~ *(closed 2026-08-10: obsolete — the driver pages it smokes were retired in v3 Batch 2)*. ~~**Remaining 3: F10b + SetSeverity (reconsider gates, decisions already taken — do not build without a fresh go-ahead) and the device-gated proofs (hardware-blocked).**~~ **Remaining 1 as of 2026-08-10 (later that day): F10b + SetSeverity reconsider gates put to the user and CLOSED decided-against (F10b re-open trigger: operator complaints about rebuild churn on data-type edits; SetSeverity is operationally invisible — engine overwrites on first eval); the device-gated proofs bundle trimmed to its 2 genuinely-gated sub-items (H6 native-ack→AVEVA + AbLegacy/TwinCAT/FOCAS probes).** | Hardware-blocked only. | §6.2, §9 2026-08-10 (sixth) | -| **Review-coverage gap** — 10 shipped projects never reviewed (Calculation, Historian.Gateway, Mqtt +Browser/Contracts, MTConnect +Contracts, Sql +Browser/Contracts) while **3 modules still review the retired Wonderware backend** | Re-verified 2026-08-04 against `code-reviews/`. Unchanged since the audit. | §6.3 | +| ~~**Review-coverage gap** — 10 shipped projects never reviewed (Calculation, Historian.Gateway, Mqtt +Browser/Contracts, MTConnect +Contracts, Sql +Browser/Contracts) while **3 modules still review the retired Wonderware backend**~~ **CLOSED 2026-08-10**: all 14 unreviewed projects (the 10 + Mqtt.Transport, Sql.Dialect, Calculation.Contracts, OpcUaClient.Session) reviewed by 6 parallel agents — 61 findings, 26 fixed, 35 Open in `findings.md`; Wonderware reviews banner-retired to history; README at 65 modules, `--check` clean | §9 2026-08-10 (seventh) | §6.3, §9 2026-08-10 (seventh) | | ~~**`RawBrowseModal` stale-open race** (added 2026-08-05) — `OnParametersSetAsync` never re-checks staleness after its awaits, so a superseded open's late resolve can install the wrong device's browse config. The identical shape was found by review and **fixed** in `RawTagModal`/`RawManualTagEntryModal` (post-await staleness re-check; see `docs/plans/2026-08-05-raw-modal-picker-live-config-design.md` §6); the browse modal was deliberately left out of that branch's scope.~~ ✅ **CLOSED 2026-08-09** (`87637e4e`, merge `0739f4b9`) — the sibling `_openGeneration` guard ported to every post-await write, **plus two departures the siblings did not need**: this modal resolves inside `try/finally`, so the `catch` (a stale open's failure would paint its error over the live device) and the `finally` (a stale `return` still runs the tail, dropping the LIVE open's spinner) are generation-guarded too. Four `RawBrowseModalStaleOpenTests` facts, each observed red pre-guard and each re-falsified by reverting only its own guard (1-failed/3-passed per revert — no redundant pin). | ~~Lower stakes than the fixed pair… but the fix pattern is proven and cheap to port.~~ Ported. | design doc §6 | ⚠️ **One correction worth carrying forward.** archreview **03/S4** — "primary gate default-allows on @@ -1280,6 +1280,54 @@ drivers), 3 carried-open archreview findings led by 01/S-1 (`AddressSpaceApplier --- +### 2026-08-10 (seventh round) — review-coverage gap CLOSED: 14 modules reviewed, Wonderware reviews retired to history + +The §0.1 "Review-coverage gap" row is done. Six parallel isolated-worktree agents (4 Opus on the big +families, 2 Sonnet on the small ones) reviewed every never-reviewed project — the row's 10 plus +`Mqtt.Transport`, `Sql.Dialect`, `Calculation.Contracts` and `OpcUaClient.Session` (the last absent +from both the row and the request; found by listing `src/` against `code-reviews/`). All six branches +merged `--no-ff`; consolidated verification on the merged tree: build clean, **11 suites / 4,033 +tests green, 0 failed** (Mqtt 729 proves the two Mqtt branches compose: 708 base + 16 + 5). README +regenerated — **65 modules**, `--check` clean. + +**61 findings recorded; 26 fixed TDD-red-first on the branches; 35 recorded Open** (cross-module, +design-decision, or Low record-only — the same disposition split as the 2026-06-19 sweep). The fixed +Highs, all previously invisible to every suite: + +- **Historian.Gateway**: alarm severity written as enum NAME while the read side `int.TryParse`s it — + every read-back collapsed to severity 1, and an existing test asserted the wrong value as correct. +- **Mqtt.Contracts**: a write to a wildcard `writeTopic` published an MQTT-3.3.2-2 protocol violation — + a conformant broker closes the connection, taking the whole driver (every subscription) dark. +- **Mqtt runtime ×2, same class — "state that outlives the session it describes"**: the plain-path + subscription manager never cleared `_subscribedTopics` across a session rebuild, so the #527 + watchdog's automatic reconnect came back deaf (Connected/Healthy, zero subscriptions, values frozen); + and `InitializeCoreAsync` overwrote live `_connection`/`_primaryHost` without teardown, stranding a + connected broker session (reachable via `AdoptConfigDuringInit` racing a reconnect). The Sparkplug + siblings had both hardened already — worth re-checking other drivers keeping per-session bookkeeping + across Shutdown/Initialize. +- **Calculation**: multi-dep tags evaluated against partial snapshots during warm-up — a spurious + "script threw" Warning on every ordinary deploy for the standard calc-tag shape. + +Notable Open (recorded in `findings.md`, fix sites named): **Driver.MTConnect-003 (High, +cross-module)** — browse-committed MTConnect tags coerce to `String` at runtime while their nodes are +typed from the same probe inference (the #536 class; fix in AdminUI `RawBrowseCommitMapper`, which got +the typed-model branch without the native-type forwarding its 3 siblings have); Driver.Sql-002 +(unchunked `IN` list vs. the 2100-param SqlClient cap); Driver.Sql.Contracts-002 (cross-module: +`Enum.TryParse` accepts numeric strings, so `"type":"99"` deploys an undefined `DriverDataType` — +belongs in `Core.Abstractions`); Driver.Calculation-005 (evaluation runs under `_lock` on the mux +actor thread, up to `RunTimeout`). + +Also this round: the **three `Historian.Wonderware*` review modules got retired-module banners** +(backend deleted in the gateway cutover, zero slnx references; Server/Admin deleted-module precedent) +and the untracked `bin`/`obj` litter dirs under `src/Drivers/` were removed. Process traps for next +time: (1) my brief's regen-readme gotcha was worded over-broadly and one agent made its finding +headings `####` — **invisible to the generator's `^###\s+` split**; `--check` catches it only when the +header claims Open findings, so a 0-open file fails silently — audit `grep -c '^### '` per new file; +(2) the harness Write tool refuses subagent-written `findings.md` (pattern-matches "report files") — +agents worked around via scratchpad-copy or heredoc, legitimately. + +--- + ### 2026-08-10 (sixth round) — open-plan-task sweep: 2 verified live, 2 closed obsolete; 7 → 3 A freshness audit of the 7 open plan tasks (parsed from `*.tasks.json`, per the re-derive rule)