From 820abd1fa3891956c0ba94b4dfe3842b2f9aba41 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 30 Jul 2026 04:58:25 -0400 Subject: [PATCH] =?UTF-8?q?docs(deferment):=20record=20the=20#521/#522=20c?= =?UTF-8?q?losures=20=E2=80=94=20both=20resolved=20differently=20from=20ho?= =?UTF-8?q?w=20they=20were=20filed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also corrects two claims this register itself got wrong, which changed both decisions: - §3.2 said DriverHostStatus was "deliberately re-created in the v3 initial migration, so deleting on inference would be wrong". The publisher it waited for cannot be written at all — Phase 4 leaves a driver-only node with no ConfigDb. "Deliberately re-created" meant carried forward mechanically. - §3.3 said the Tier-C-only protections were dormant, implying Tier A/B ones ran. Nothing constructed MemoryTracking either, so the whole Core/Stability layer was dead — which is why 'pass real tiers' was never a flag flip. Open count stays 17 (verified against the tracker API, not derived — the derivation was wrong last round) but membership changed: #521/#522 closed, #524/#525 opened. Claude-Session: https://claude.ai/code/session_015p7wGqy3YpZNCpDzTpGMKo --- deferment.md | 81 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/deferment.md b/deferment.md index ce495d8c..9c765c7c 100644 --- a/deferment.md +++ b/deferment.md @@ -29,9 +29,9 @@ how much they should worry you: | # | Theme | Why it matters | Now | |---|---|---|---| -| **1** | **Three subsystems are fully authored, persisted, and shipped — and never executed.** Node ACLs, `IRediscoverable`/`IHostConnectivityProbe`, and `DriverTypeRegistry`. | An operator can author a rule, save it, deploy it green, and have it do **nothing**. §3 | ◐ `IRediscoverable` now consumed; the other two are **documented as inert** and tracked (#520, #521, #522) rather than fixed | +| **1** | **Three subsystems are fully authored, persisted, and shipped — and never executed.** Node ACLs, `IRediscoverable`/`IHostConnectivityProbe`, and `DriverTypeRegistry`. | An operator can author a rule, save it, deploy it green, and have it do **nothing**. §3 | ◐ **Two of three now settled**: `IRediscoverable` consumed (#518), `IHostConnectivityProbe` re-transported to telemetry (#521), `DriverTypeRegistry` + the tier machinery **deleted** (#522). Only **node ACLs** remain authored-but-inert, tracked as #520 | | **2** | **AdminUI authoring-dispatch gaps.** Calculation is offered in the driver picker but has no config form; three drivers have no device form; CSV + browse-commit dispatch maps miss the new drivers. | The "registered but unauthorable" class that has now bitten twice. §1.2 | ✅ **Closed** — G-1…G-6 fixed and guarded; G-7 remains | -| **3** | **17 open issues, all confirmed still open**, several broader than filed. | §2 | ◐ 4 resolved + closed, 4 new filed (one since closed) → **17 open**, none stale | +| **3** | **17 open issues, all confirmed still open**, several broader than filed. | §2 | ◐ 6 resolved + closed, 6 new filed (one since closed) → **17 open**, none stale. Two of the six closures (#521, #522) resolved *differently from how they were filed* — see §3.2/§3.3 | | **4** | **Bookkeeping drift.** 8 `.tasks.json` files show ~140 "pending" tasks for work that shipped; 5 CLAUDE.md status claims are stale. | Someone follows the tracker and rebuilds a shipped driver. §6, §7 | ✅ **Closed** — 13 plan files + 11 archreview gates written back | Nothing here is a data-loss or outage defect. The sharpest edge is §3 — silent non-enforcement. @@ -44,8 +44,8 @@ themes into tracked decisions. What remains: | Item | Nature | Where | |---|---|---| | **#520** node ACLs authored + deployed but **never enforced** | Decision: wire it or retire the surface. Non-enforcement is now stated in docs and warned in the UI, so nobody can author a deny rule believing it works — but reads are still ungated. | §3.1 | -| **#521** `IHostConnectivityProbe` / `DriverHostStatus` dead surface | Decision: build the publisher or delete it. The table was deliberately re-created in the v3 initial migration, so deleting on inference would be wrong. | §3.2 | -| **#522** driver stability tiers inert | Decision: pass real tiers or delete the machinery. Docs now say every driver runs Tier A. | §3.3 | +| **#521** `IHostConnectivityProbe` / `DriverHostStatus` dead surface ✅ **CLOSED** `abda6f9e` | Resolved by changing the *transport*, not by either option as filed — the publisher as designed was unbuildable after Phase 4. Host status now rides `DriverHealthChanged` to `/hosts`; table dropped. | §3.2 | +| **#522** driver stability tiers inert ✅ **CLOSED** `abda6f9e` | Deleted. The inertness was broader than filed (nothing constructed `MemoryTracking` either), and the model's premise — an out-of-process Host to recycle — no longer exists. `DriverTier` kept. | §3.3 | | ~~**#523** remove the periodic 5-min device re-browse~~ | ✅ **Done + closed on the tracker.** **AbCip and FOCAS now have no tag-change signal at all**; that is the accepted consequence, not an oversight. | §9 (2026-07-30, #523) | | **G-7** `EquipmentTagConfigInspector` coverage | ◐ **Narrowed + guarded** (2026-07-28): MQTT wired (it shipped an `Inspect` nobody called), and a reflection guard now fails the build if a reachable driver ships one and is not mapped. **Residual:** Sql / MTConnect / Calculation / OpcUaClient have no Contracts-side `Inspect` at all, so the deploy gate stays blind for them while the AdminUI validates them — see §1.2. | §1.2 | | ~~**13 `EquipmentTagsDarkBatch4` skipped tests**~~ | ✅ **Done** — 6 revived onto the raw/UNS shape, 3 folded into a widened live parity corpus, 4 deleted as retired. The reason constant is gone. **Skips now: `Runtime.Tests` 13 → 3, `OpcUaServer.Tests` 4 → 1** — all remaining are deliberate `EquipmentDeviceBindingRetired` tombstones. | §9 (2026-07-28, skips) | @@ -64,8 +64,13 @@ change: | **#507** | **Superseded, not migrated** — the requested migration was impossible, since both of the path's inputs are structurally empty in v3. | | **#523** | Done, with the consequence carried forward: **AbCip and FOCAS now have no tag-change signal at all.** | -**17 issues remain open**, all genuine: #519–#522 (four judgement calls + a design consequence), #517, -the eight MQTT follow-ups (#508–#515), #491, #489, #481, #468. +**17 issues remain open** (verified against the tracker API, not derived): #519, #520 (two judgement +calls), #524 + #525 (both split out of the #521/#522 work rather than folded in), #517, the eight MQTT +follow-ups (#508–#515), #491, #489, #481, #468. + +The count is unchanged at 17 but the *membership* is not — **#521 and #522 closed, #524 and #525 opened.** +Both new ones are residuals their parent issue's decision did not cover: a second dead table +(`DriverInstanceResilienceStatus`) and two now-consumerless `IDriver` members. --- @@ -212,9 +217,20 @@ highest-risk doc error found. > ✅ **`IRediscoverable` half FIXED** (`09a401b8`) — consumed by `DriverInstanceActor` and surfaced as a > `/hosts` re-browse prompt. Advisory: the served address space is not rebuilt, because v3 authors raw tags > through `/raw` browse-commit. -> ⏳ **`IHostConnectivityProbe` half UNRESOLVED** (Gitea **#521**) — `GetHostStatuses()` still has zero -> production call sites and nothing writes a `DriverHostStatus` row. Not deleted on inference: the table was -> deliberately re-created in the v3 initial migration. +> ✅ **`IHostConnectivityProbe` half RESOLVED** (`abda6f9e`, Gitea **#521** closed) — but **not as this +> register or the issue framed it.** The choice was never "build the publisher or delete it": the publisher +> as designed — driver nodes upserting `DriverHostStatus` rows — is **unbuildable**, because per-cluster mesh +> Phase 4 gates `AddOtOpcUaConfigDb` on the `admin` role, so a driver-only node has no ConfigDb connection to +> write with. The design predates Phase 4 and nobody revisited it; "deliberately re-created in the v3 initial +> migration" turned out to mean *carried forward mechanically*, not *intended*. +> So the capability was kept and the **transport** changed: `DriverHealthChanged.HostStatuses` carries the +> probe result to `/hosts` over the Phase 5 telemetry stream, which needs no DB and survives the mesh split. +> The table is dropped (`DropDriverHostStatusTable`). Live-gated on docker-dev, **including the cross-mesh +> gRPC path** — site-a first showed `—`, which is also what a broken mapper produces, so it was rebuilt to +> prove the `has_host_statuses` presence flag round-trips rather than assuming version skew. +> ⏳ **A third table, same defect, found en route:** `DriverInstanceResilienceStatus` also has no writer and +> no reader — only its DbSet declaration — while the live data rides the `driver-resilience-status` channel. +> Documented in place, filed as Gitea **#524** rather than widening the schema change beyond the ask. Gitea #518/#507. Nine drivers raise; nothing consumes. `DriverHostStatus` table exists (`OtOpcUaConfigDbContext.cs:48`, migration `20260715230637_V3Initial.cs:108`) with a doc-comment @@ -225,11 +241,23 @@ per-host connectivity table is permanently empty. ### 3.3 `DriverTypeRegistry` is vestigial -> ◐ **Still true; documented** (`88ce8df0`, Gitea **#522**). `docs/v2/driver-stability.md` now states its -> tier table is aspirational. A second staleness the audit missed is corrected there too: the -> **separate-Windows-service hosting** that document describes for Tier C no longer exists either (Galaxy -> moved to the mxaccessgw sidecar in PR 7.2; FOCAS went in-process with its managed wire client). No -> runtime change — enabling recycle on two live drivers wants its own live gate. +> ✅ **RESOLVED — DELETED** (`abda6f9e`, Gitea **#522** closed). `DriverTypeRegistry`, `MemoryTracking`, +> `MemoryRecycle`, `ScheduledRecycleScheduler`, `IDriverSupervisor` and the operator-authorable +> `RecycleIntervalSeconds` knob are gone. +> +> ⚠️ **This register understated the inertness, exactly as the issue did.** Both said the *Tier-C-only* +> protections were dormant, implying the Tier A/B parts ran. They did not: **nothing constructed +> `MemoryTracking` at all** outside its own unit tests, so the whole `Core/Stability` recycle layer was dead. +> That changed the decision — "pass real tiers" was never a flag flip, it meant writing the wiring that never +> existed *and* arming it on two live drivers at once. Deletion won because the premise is gone, not merely +> unused: Tier C meant an out-of-process Host a supervisor could restart, and `IDriverSupervisor` had zero +> implementations because there is nothing left to implement against. +> +> **`DriverTier` itself survives and is load-bearing** — `GetTierDefaults` supplies the real per-capability +> timeout/retry/breaker policies. Only the isolation-and-recycle layer above it went. +> `WedgeDetector` shared the folder, is equally dead, and is **not** recycle machinery — restored rather than +> swept up in a decision that was not about it. `IDriver.GetMemoryFootprint`/`FlushOptionalCachesAsync` lose +> their only consumer here; documented and filed as Gitea **#525** rather than buried in a 12-driver sweep. Independently verified for this report: `src/Core/…Core.Abstractions/DriverTypeRegistry.cs:20` is referenced **only** by `tests/Core/…/DriverTypeRegistryTests.cs`. Nothing registers metadata at @@ -484,6 +512,31 @@ also `--no-ff`) carrying the items §8 did not cover. | §7.2 `Phase7*` → `AddressSpace*` rename | ✅ **Done** — 4 live docs | `4624141a` | | §7.2 missing `Sql.md` / `Calculation.md` | ✅ **Done** | `f3cd685d` | +**A third round merged 2026-07-30 as `abda6f9e`** (branch `fix/521-522-host-status-and-tiers`, 3 commits, +`--no-ff`) closing the two keep-or-delete decisions §8 deliberately left to the user. + +| Round-3 item | Status | Commit | +|---|---|---| +| **#521** `IHostConnectivityProbe` | ✅ **Done — resolved differently from how it was filed.** Neither "build the publisher" nor "delete": the publisher as designed was **unbuildable** after Phase 4, so the capability was kept and the transport changed to the Phase 5 telemetry stream. Table dropped. | `30d0697c` | +| **#522** driver stability tiers | ✅ **Done — deleted.** The inertness was broader than either the issue or this register said: nothing constructed `MemoryTracking` either, so "pass real tiers" was never a flag flip. | `cbb88229` | +| Live gate on docker-dev | ✅ **Passed**, one fix (`1 hosts` → `1 host`) | `ce589569` | + +**Both closures produced a residual that was filed rather than folded in** — a second dead table +(#524 `DriverInstanceResilienceStatus`) and two now-consumerless `IDriver` members (#525). Neither was +in scope; both would have widened a schema change or a 12-driver sweep past what was asked. + +**Three things this round got right by not trusting the register:** + +- §3.2 recorded that `DriverHostStatus` was *"deliberately re-created in the v3 initial migration, so + deleting on inference would be wrong."* Checking Phase 4 showed the publisher it was waiting for + **cannot be written at all** — a driver-only node has no ConfigDb. "Deliberately re-created" meant + *carried forward mechanically*. +- §3.3 (and #522) said the Tier-C protections were dormant, implying Tier A/B ones ran. Nothing + constructed the trackers at all. +- The live gate treated an ambiguous observation as ambiguous: site-a showed `—` for host status, which + is what version skew **and** a broken cross-mesh mapper both produce. Rebuilding site-a distinguished + them rather than assuming the benign reading. + ⚠️ **This file was destroyed and restored during round 2 — see the 2026-07-30 entry at the end of §9.** It is the second time in two rounds that the register's own bookkeeping step damaged the register.