From d06e92c631a5b9bfc0b2ccafd3242e6fe55de6bd Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 10 Aug 2026 04:29:49 -0400 Subject: [PATCH] =?UTF-8?q?docs(plans):=20open-plan-task=20sweep=20?= =?UTF-8?q?=E2=80=94=20followups-batch=20T9=20(Modbus-Int64)=20+=20T10=20(?= =?UTF-8?q?S7/AbCip=20probe=20E2E)=20verified=20live=20PASS;=20fixedtree?= =?UTF-8?q?=20T11=20+=20adminui=2010.4=20closed=20obsolete=20(v3=20deleted?= =?UTF-8?q?=20their=20subjects);=20open=20plan=20tasks=207=20->=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deferment.md | 44 +- ...28-adminui-driver-pages-plan.md.tasks.json | 642 ++++++++++++++++-- .../2026-06-19-followups-batch.md.tasks.json | 174 ++++- ...-otopcua-fixedtree-followups.md.tasks.json | 157 ++++- 4 files changed, 919 insertions(+), 98 deletions(-) diff --git a/deferment.md b/deferment.md index 7e832e58..ddcb85e5 100644 --- a/deferment.md +++ b/deferment.md @@ -58,7 +58,7 @@ So everything below is **untracked work**. Nothing in it is a data-loss or outag | ~~**G-7 residual** — Sql / MTConnect / Calculation / OpcUaClient have no Contracts-side `Inspect`~~ ✅ **CLOSED 2026-08-09** (`2947a2b9` + `1469fbb4`, merge `0695f682`). All four now ship a Contracts-side `*TagDefinitionFactory.Inspect` **wrapping the runtime parse, never mirroring the AdminUI model** — Sql wraps the pre-existing `SqlEquipmentTagParser`; the MTConnect / OpcUaClient / Calculation blob readers were **moved** into their Contracts assemblies (the drivers now call them), so never-stricter-than-runtime is structural. `Driver.Calculation.Contracts` was created (no Contracts assembly existed). The reflection coverage guard was falsified (map entry removed → red naming `SqlTagDefinitionFactory`), and `TagConfigAuthoringDeployParityTests` pins authoring-accepts ⇒ deploy-accepts. **Galaxy is now the sole unmapped type, deliberately + symmetrically** (no typed authoring editor either). ~~Found en route, left open: `MTConnectTagConfigModel` reads `dataType` leniently (misspelled name → silently `String`) while the runtime rejects it — authoring weaker than runtime, the *opposite* direction from G-7; documented inline in the parity tests.~~ ✅ Filed and FIXED same day as **#549** — and it was 6 models wide, not 1 (see the "2026-08-09 (later)" §9 entry); residuals **#550**/**#551** are ✅ **CLOSED 2026-08-10** (merges `b50523b1` + `333ea488`, see the 2026-08-10 §9 entry) — their own residuals are **#552** (Sql browse-commit emits a config the gate rejects) / **#553** (CSV typed-column merge silently rewrites typo'd enums pre-gate). | ~~The deploy gate is weaker than the authoring gate.~~ Config arriving by CSV import or API now meets the same checks the modal applies. | §1.2 | | ~~**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** — ~~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*), fixedtree Task 11, 1 manual smoke checklist | Small, and two of the groups are decisions already taken. | §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).** | Small, and two of the groups are decisions already taken. | §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 | | ~~**`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 | @@ -1280,6 +1280,48 @@ drivers), 3 carried-open archreview findings led by 01/S-1 (`AddressSpaceApplier --- +### 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) +against the current tree, then one Opus agent ran the two runnable verifies. No code changed. + +- **followups-batch Task 9 (Modbus-Int64 live authoring) — VERIFIED PASS.** Rig rebuilt to master + `481f4343` first (the running image was 2 days stale; parity asserted across all 6 nodes — the + round-robin trap). Authored `TASK9-INT64` (RawPath `pymodbus/plc/Task9Int64`, HoldingRegisters + address 200, Int64 BigEndian) via ConfigDb + the headless deploy API; deployment sealed. The node + advertises DataType `i=8` (Int64), scalar, Good, **identically on :4840 and :4841**, and the value + is the exact BigEndian decode of HR200–203 — four distinct non-zero words, so a byte-order or span + bug could not coincidentally match. Change propagation proven by driving HR203 via FC06 and + watching the subscribe on both centrals (registers restored after). Fixture caveat recorded: the + standard profile has **no naturally-churning 4-register span** (HR100 is isolated; any span over + it returns ILLEGAL DATA ADDRESS), so churn must be externally driven. Tag row left deployed and + serving, consistent with prior gate rows. +- **followups-batch Task 10 (S7 + AbCip Test-Connect probe E2E) — VERIFIED PASS.** + `DriverProbeHandshakeE2eTests` **12/12, 0 skipped** — S7 green, AbCip green with `"CIP session + OK"` (a real authored-tag read, not the fallback), AbCip no-authored-tags reachability, plus the + Modbus/OpcUaClient/local-rig/Galaxy legs (mxaccessgw on `10.100.0.48` happened to be up). + **Premise correction:** the skip-gating is pure TCP reachability (`DockerFixtureAvailability`), + not env vars, and the checked-in defaults already point at `10.100.0.35` — the task's + "needs Windows-VM fixtures" note had been stale since the Mac migration. S7 fixture started and + removed (net zero); AbCip was already up and left as found. +- **fixedtree Task 11 — CLOSED OBSOLETE.** The FixedTree-under-Equipment injection feature it + gated was deleted wholesale when #507 closed as superseded (`DiscoveredNodesReady`, + `DiscoveredNodeMapper`, the 18 `DiscoveryInjectionDormantV3` tests — all gone). A verification + gate for deleted code verifies nothing. +- **adminui-driver-pages 10.4 (manual smoke checklist) — CLOSED OBSOLETE.** The routed + `/clusters/{id}/drivers` flow it smokes (the 8 `*DriverPage` shells) was retired in v3 Batch 2; + no driver pages exist under `Components/Pages/`. The form bodies live on inside the `/raw` + modals, live-gated repeatedly across the 2026-07/08 rounds. + +**Open plan tasks are now 3**, all deliberate: F10b surgical DataType/IsArray + alarm-severity +`SetSeverity` (reconsider gates — premises re-verified still true on the current tree: +`TagDeltaIsSurgicalEligible` still rebuild-forces DataType/IsArray; the node manager still projects +engine-computed severity) and the device-gated proofs (hardware-blocked; two sub-items possibly +part-covered by the 2026-06-27 historian gate and `dcb0be65`, worth trimming when next touched). +Side effect worth knowing: **the docker-dev rig now runs current master** (`6e7028e0856f`). + +--- + ### 2026-08-10 (fifth round) — #559 closed: MQTT joins the fleet's framing contract; the drift arc ends The fourth round's sole residual, one isolated-worktree Opus agent, fix `621a9e5d` merged to master. diff --git a/docs/plans/2026-05-28-adminui-driver-pages-plan.md.tasks.json b/docs/plans/2026-05-28-adminui-driver-pages-plan.md.tasks.json index 579606b6..d9405934 100644 --- a/docs/plans/2026-05-28-adminui-driver-pages-plan.md.tasks.json +++ b/docs/plans/2026-05-28-adminui-driver-pages-plan.md.tasks.json @@ -1,78 +1,578 @@ { "planPath": "docs/plans/2026-05-28-adminui-driver-pages-plan.md", "designPath": "docs/plans/2026-05-28-adminui-driver-pages-design.md", - "reconciledNote": "RECONCILED 2026-06-18: a seam-by-seam audit confirmed Phases 6-10 are ALL shipped on master (the pre-2026-06-18 'pending' states below were stale). Phase 6 (live DriverStatusPanel) + Phase 8 (Reconnect/Restart) are wired end-to-end (DriverHealthChanged contract, AkkaDriverHealthPublisher invoked at DriverInstanceActor.PublishHealthSnapshot, admin-gated DriverStatusSignalRBridge spawn, snapshot store, hub, panel in all 9 driver pages, AdminOperationsActor/DriverHostActor handlers). Phase 7 probes + Phase 9 typed pickers shipped. Phase 10 E2E tests (DriverTestConnect/DriverReconnect/DriverStatusHub) shipped at 494da22c. The genuine remnant — a deployed-driver Healthy->Reconnecting->Healthy E2E + a production-fidelity harness fix (AddOtOpcUaRuntime) — was added by docs/plans/2026-06-18-driver-pages-reconnect-e2e.md.", + "reconciledNote": "RECONCILED 2026-06-18: a seam-by-seam audit confirmed Phases 6-10 are ALL shipped on master (the pre-2026-06-18 'pending' states below were stale). Phase 6 (live DriverStatusPanel) + Phase 8 (Reconnect/Restart) are wired end-to-end (DriverHealthChanged contract, AkkaDriverHealthPublisher invoked at DriverInstanceActor.PublishHealthSnapshot, admin-gated DriverStatusSignalRBridge spawn, snapshot store, hub, panel in all 9 driver pages, AdminOperationsActor/DriverHostActor handlers). Phase 7 probes + Phase 9 typed pickers shipped. Phase 10 E2E tests (DriverTestConnect/DriverReconnect/DriverStatusHub) shipped at 494da22c. The genuine remnant \u2014 a deployed-driver Healthy->Reconnecting->Healthy E2E + a production-fidelity harness fix (AddOtOpcUaRuntime) \u2014 was added by docs/plans/2026-06-18-driver-pages-reconnect-e2e.md.", "executionState": "COMPLETE", "tasks": [ - {"id": "0.1", "subject": "Create AdminUI test project + slnx entry + placeholder test", "status": "completed", "commit": "dc12c37"}, - - {"id": "1.1", "subject": "Driver.Modbus.Contracts — extract ModbusDriverOptions", "status": "completed", "blockedBy": ["0.1"], "commit": "5058a56"}, - {"id": "1.2", "subject": "Driver.AbCip.Contracts — extract AbCipDriverOptions", "status": "completed", "blockedBy": ["0.1"], "commit": "b474d63"}, - {"id": "1.3", "subject": "Driver.AbLegacy.Contracts — extract AbLegacyDriverOptions", "status": "completed", "blockedBy": ["0.1"], "commit": "4902295"}, - {"id": "1.4", "subject": "Driver.S7.Contracts — extract S7DriverOptions", "status": "completed", "blockedBy": ["0.1"], "commit": "9f62f2c"}, - {"id": "1.5", "subject": "Driver.TwinCAT.Contracts — extract TwinCATDriverOptions", "status": "completed", "blockedBy": ["0.1"], "commit": "a88721c"}, - {"id": "1.6", "subject": "Driver.FOCAS.Contracts — extract FocasDriverOptions", "status": "completed", "blockedBy": ["0.1"], "commit": "d892ab9"}, - {"id": "1.7", "subject": "Driver.OpcUaClient.Contracts — extract OpcUaClientDriverOptions", "status": "completed", "blockedBy": ["0.1"], "commit": "5f0e048"}, - {"id": "1.8", "subject": "Driver.Galaxy.Contracts — extract GalaxyDriverOptions", "status": "completed", "blockedBy": ["0.1"], "commit": "5ffbc42"}, - {"id": "1.9", "subject": "Driver.Historian.Wonderware.Client.Contracts — extract options", "status": "completed", "blockedBy": ["0.1"], "commit": "8c0a320"}, - {"id": "1.10", "subject": "Add ProbeTimeoutSeconds to all 9 Options classes + slnx validation", "status": "completed", "blockedBy": ["1.1","1.2","1.3","1.4","1.5","1.6","1.7","1.8","1.9"], "commit": "f2f6eeb"}, - - {"id": "2.1", "subject": "DriverFormShell.razor", "status": "completed", "blockedBy": ["0.1"], "commit": "85af126"}, - {"id": "2.2", "subject": "DriverIdentitySection.razor", "status": "completed", "blockedBy": ["0.1"], "commit": "1ff3875"}, - {"id": "2.3", "subject": "DriverResilienceSection.razor", "status": "completed", "blockedBy": ["0.1"], "commit": "a008530"}, - {"id": "2.4", "subject": "Wire shared sections into existing DriverEdit.razor", "status": "completed", "blockedBy": ["2.1","2.2","2.3"], "commit": "a28f4cd"}, - - {"id": "3.1", "subject": "DriverTypePicker.razor (route: /drivers/new)", "status": "completed", "blockedBy": ["2.4"], "commit": "c0ce5d0"}, - {"id": "3.2", "subject": "DriverEditRouter.razor with DynamicComponent dispatch","status": "completed", "blockedBy": ["2.4"], "commit": "55e8bf7"}, - {"id": "3.3", "subject": "Hand /drivers/new from DriverEdit to DriverTypePicker","status": "completed", "blockedBy": ["3.1"], "commit": "27b3a01"}, - {"id": "3.4", "subject": "Hand /drivers/{id} from DriverEdit to DriverEditRouter (fallback to DriverEdit)", "status": "completed", "blockedBy": ["3.2","3.3"], "commit": "27b3a01"}, - - {"id": "4.0", "subject": "AdminUI csproj references all 9 Driver.*.Contracts", "status": "completed", "blockedBy": ["1.10","3.4"], "commit": "7014c93"}, - {"id": "4.1", "subject": "ModbusDriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "a3073d1"}, - {"id": "4.2", "subject": "AbCipDriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "dc21cba"}, - {"id": "4.3", "subject": "AbLegacyDriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "059a621"}, - {"id": "4.4", "subject": "S7DriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "5cad9b2"}, - {"id": "4.5", "subject": "TwinCatDriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "dfbf679"}, - {"id": "4.6", "subject": "FocasDriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "8149739"}, - {"id": "4.7", "subject": "OpcUaClientDriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "efcc231"}, - {"id": "4.8", "subject": "GalaxyDriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "a243cfd"}, - {"id": "4.9", "subject": "HistorianWonderwareDriverPage.razor + serialization test", "status": "completed", "blockedBy": ["4.0"], "commit": "2c16062"}, - {"id": "4.10","subject": "Wire all 9 typed pages into DriverEditRouter._componentMap", "status": "completed", "blockedBy": ["4.1","4.2","4.3","4.4","4.5","4.6","4.7","4.8","4.9"], "commit": "5f8fa70"}, - {"id": "4.11","subject": "Fixup: S7 Tags data-loss + missing FormModel tests (post-review)", "status": "completed", "blockedBy": ["4.10"], "commit": "c4086c2"}, - - {"id": "5.1", "subject": "Delete DriverEdit.razor + remove fallback in DriverEditRouter", "status": "completed", "blockedBy": ["4.1","4.2","4.3","4.4","4.5","4.6","4.7","4.8","4.9"], "commit": "a971db3"}, - - {"id": "6.1", "subject": "DriverHealthChanged DPS message contract", "status": "completed", "blockedBy": ["5.1"], "note": "shipped — Commons/Messages/Drivers/DriverHealthChanged.cs (verified 2026-06-18)"}, - {"id": "6.2", "subject": "Publish DriverHealthChanged from each driver actor (IDriverHealthPublisher)", "status": "completed", "blockedBy": ["6.1"], "note": "shipped — AkkaDriverHealthPublisher (DI-bound prod) invoked at DriverInstanceActor.PublishHealthSnapshot"}, - {"id": "6.3", "subject": "DriverStatusHub", "status": "completed", "blockedBy": ["6.1"], "note": "shipped — DriverStatusHub.cs, mapped via MapHub"}, - {"id": "6.4", "subject": "DriverStatusSignalRBridge + InMemoryDriverStatusSnapshotStore", "status": "completed", "blockedBy": ["6.2","6.3"], "note": "shipped — bridge spawned admin-gated (HubServiceCollectionExtensions:69, Program.cs:196); store singleton"}, - {"id": "6.5", "subject": "DriverStatusPanel.razor + wire into all 9 driver pages", "status": "completed", "blockedBy": ["6.4"], "note": "shipped — in-process snapshot-store subscription (dodges Traefik self-hub trap), wired into all 9 driver pages"}, - - {"id": "7.1", "subject": "IDriverProbe interface + TestDriverConnect messages", "status": "completed", "blockedBy": ["5.1"], "note": "shipped — Phase 7 probes (per design note + reconcile)"}, - {"id": "7.2", "subject": "AdminOperationsActor handler for TestDriverConnect", "status": "completed", "blockedBy": ["7.1"], "note": "shipped"}, - {"id": "7.3", "subject": "TCP probes (Modbus, AbCip, AbLegacy, S7)", "status": "completed", "blockedBy": ["7.1"], "note": "shipped — upgraded TCP->protocol handshake (961b2b55 & per-driver)"}, - {"id": "7.4", "subject": "Specialty probes (FOCAS, TwinCAT, OPCUA, Galaxy, Historian)", "status": "completed", "blockedBy": ["7.1"], "note": "shipped"}, - {"id": "7.5", "subject": "AdminProbeService + DriverTestConnectButton.razor + wire into pages", "status": "completed", "blockedBy": ["7.2","7.3","7.4"], "note": "shipped"}, - - {"id": "8.1", "subject": "RestartDriver + ReconnectDriver messages + AdminOperationsActor handlers", "status": "completed", "blockedBy": ["6.5","7.5"], "note": "shipped — Commons/Messages/Admin + AdminOperationsActor + DriverHostActor handlers"}, - {"id": "8.2", "subject": "DriverOperator authorization policy + docs/Security.md update", "status": "completed", "blockedBy": ["6.5"], "note": "shipped — DriverOperator policy gates the panel buttons"}, - {"id": "8.3", "subject": "Wire Reconnect/Restart buttons into DriverStatusPanel", "status": "completed", "blockedBy": ["8.1","8.2"], "note": "shipped — DriverOperator-gated Reconnect/Restart in DriverStatusPanel.razor"}, - - {"id": "9.1", "subject": "DriverTagPicker.razor modal shell", "status": "completed", "blockedBy": ["5.1"], "note": "shipped — Phase 9 typed address pickers for all 9 drivers (reconcile)"}, - {"id": "9.2", "subject": "Modbus address picker body + unit test", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - {"id": "9.3", "subject": "AbCip address picker body + unit test", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - {"id": "9.4", "subject": "AbLegacy address picker body + unit test", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - {"id": "9.5", "subject": "S7 address picker body + unit test", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - {"id": "9.6", "subject": "TwinCat address picker body + unit test", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - {"id": "9.7", "subject": "FOCAS address picker body + unit test", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - {"id": "9.8", "subject": "OpcUaClient picker body (free-text NodeId)", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - {"id": "9.9", "subject": "Galaxy picker body (free-text tag_name.AttributeName)", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - {"id": "9.10","subject": "Historian.Wonderware picker body + unit test", "status": "completed", "blockedBy": ["9.1"], "note": "shipped"}, - - {"id": "10.1", "subject": "DriverTestConnectE2eTests (Modbus/AbCip/S7 vs Docker sims)", "status": "completed", "blockedBy": ["8.3","9.10"], "commit": "494da22c", "note": "shipped (skip-gated on sim reachability)"}, - {"id": "10.2", "subject": "DriverReconnectE2eTests", "status": "completed", "blockedBy": ["8.3","9.10"], "commit": "494da22c", "note": "shipped; deferred deeper deployed-driver Healthy->Reconnecting->Healthy transition CLOSED 2026-06-18 (docs/plans/2026-06-18-driver-pages-reconnect-e2e.md)"}, - {"id": "10.3", "subject": "DriverStatusHubE2eTests", "status": "completed", "blockedBy": ["8.3","9.10"], "commit": "494da22c", "note": "shipped (mock IHubContext + manual bridge spawn)"}, - {"id": "10.4", "subject": "Manual smoke checklist (documented)", "status": "partial", "blockedBy": ["10.1","10.2","10.3"], "note": "design §8.3 checklist authored; automated coverage substantially supersedes it (new deployed-driver reconnect E2E + green driver E2E suite 2026-06-18). Full browser smoke recording NOT executed (deferred — login-disabled docker-dev rig drive)."} + { + "id": "0.1", + "subject": "Create AdminUI test project + slnx entry + placeholder test", + "status": "completed", + "commit": "dc12c37" + }, + { + "id": "1.1", + "subject": "Driver.Modbus.Contracts \u2014 extract ModbusDriverOptions", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "5058a56" + }, + { + "id": "1.2", + "subject": "Driver.AbCip.Contracts \u2014 extract AbCipDriverOptions", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "b474d63" + }, + { + "id": "1.3", + "subject": "Driver.AbLegacy.Contracts \u2014 extract AbLegacyDriverOptions", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "4902295" + }, + { + "id": "1.4", + "subject": "Driver.S7.Contracts \u2014 extract S7DriverOptions", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "9f62f2c" + }, + { + "id": "1.5", + "subject": "Driver.TwinCAT.Contracts \u2014 extract TwinCATDriverOptions", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "a88721c" + }, + { + "id": "1.6", + "subject": "Driver.FOCAS.Contracts \u2014 extract FocasDriverOptions", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "d892ab9" + }, + { + "id": "1.7", + "subject": "Driver.OpcUaClient.Contracts \u2014 extract OpcUaClientDriverOptions", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "5f0e048" + }, + { + "id": "1.8", + "subject": "Driver.Galaxy.Contracts \u2014 extract GalaxyDriverOptions", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "5ffbc42" + }, + { + "id": "1.9", + "subject": "Driver.Historian.Wonderware.Client.Contracts \u2014 extract options", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "8c0a320" + }, + { + "id": "1.10", + "subject": "Add ProbeTimeoutSeconds to all 9 Options classes + slnx validation", + "status": "completed", + "blockedBy": [ + "1.1", + "1.2", + "1.3", + "1.4", + "1.5", + "1.6", + "1.7", + "1.8", + "1.9" + ], + "commit": "f2f6eeb" + }, + { + "id": "2.1", + "subject": "DriverFormShell.razor", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "85af126" + }, + { + "id": "2.2", + "subject": "DriverIdentitySection.razor", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "1ff3875" + }, + { + "id": "2.3", + "subject": "DriverResilienceSection.razor", + "status": "completed", + "blockedBy": [ + "0.1" + ], + "commit": "a008530" + }, + { + "id": "2.4", + "subject": "Wire shared sections into existing DriverEdit.razor", + "status": "completed", + "blockedBy": [ + "2.1", + "2.2", + "2.3" + ], + "commit": "a28f4cd" + }, + { + "id": "3.1", + "subject": "DriverTypePicker.razor (route: /drivers/new)", + "status": "completed", + "blockedBy": [ + "2.4" + ], + "commit": "c0ce5d0" + }, + { + "id": "3.2", + "subject": "DriverEditRouter.razor with DynamicComponent dispatch", + "status": "completed", + "blockedBy": [ + "2.4" + ], + "commit": "55e8bf7" + }, + { + "id": "3.3", + "subject": "Hand /drivers/new from DriverEdit to DriverTypePicker", + "status": "completed", + "blockedBy": [ + "3.1" + ], + "commit": "27b3a01" + }, + { + "id": "3.4", + "subject": "Hand /drivers/{id} from DriverEdit to DriverEditRouter (fallback to DriverEdit)", + "status": "completed", + "blockedBy": [ + "3.2", + "3.3" + ], + "commit": "27b3a01" + }, + { + "id": "4.0", + "subject": "AdminUI csproj references all 9 Driver.*.Contracts", + "status": "completed", + "blockedBy": [ + "1.10", + "3.4" + ], + "commit": "7014c93" + }, + { + "id": "4.1", + "subject": "ModbusDriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "a3073d1" + }, + { + "id": "4.2", + "subject": "AbCipDriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "dc21cba" + }, + { + "id": "4.3", + "subject": "AbLegacyDriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "059a621" + }, + { + "id": "4.4", + "subject": "S7DriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "5cad9b2" + }, + { + "id": "4.5", + "subject": "TwinCatDriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "dfbf679" + }, + { + "id": "4.6", + "subject": "FocasDriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "8149739" + }, + { + "id": "4.7", + "subject": "OpcUaClientDriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "efcc231" + }, + { + "id": "4.8", + "subject": "GalaxyDriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "a243cfd" + }, + { + "id": "4.9", + "subject": "HistorianWonderwareDriverPage.razor + serialization test", + "status": "completed", + "blockedBy": [ + "4.0" + ], + "commit": "2c16062" + }, + { + "id": "4.10", + "subject": "Wire all 9 typed pages into DriverEditRouter._componentMap", + "status": "completed", + "blockedBy": [ + "4.1", + "4.2", + "4.3", + "4.4", + "4.5", + "4.6", + "4.7", + "4.8", + "4.9" + ], + "commit": "5f8fa70" + }, + { + "id": "4.11", + "subject": "Fixup: S7 Tags data-loss + missing FormModel tests (post-review)", + "status": "completed", + "blockedBy": [ + "4.10" + ], + "commit": "c4086c2" + }, + { + "id": "5.1", + "subject": "Delete DriverEdit.razor + remove fallback in DriverEditRouter", + "status": "completed", + "blockedBy": [ + "4.1", + "4.2", + "4.3", + "4.4", + "4.5", + "4.6", + "4.7", + "4.8", + "4.9" + ], + "commit": "a971db3" + }, + { + "id": "6.1", + "subject": "DriverHealthChanged DPS message contract", + "status": "completed", + "blockedBy": [ + "5.1" + ], + "note": "shipped \u2014 Commons/Messages/Drivers/DriverHealthChanged.cs (verified 2026-06-18)" + }, + { + "id": "6.2", + "subject": "Publish DriverHealthChanged from each driver actor (IDriverHealthPublisher)", + "status": "completed", + "blockedBy": [ + "6.1" + ], + "note": "shipped \u2014 AkkaDriverHealthPublisher (DI-bound prod) invoked at DriverInstanceActor.PublishHealthSnapshot" + }, + { + "id": "6.3", + "subject": "DriverStatusHub", + "status": "completed", + "blockedBy": [ + "6.1" + ], + "note": "shipped \u2014 DriverStatusHub.cs, mapped via MapHub" + }, + { + "id": "6.4", + "subject": "DriverStatusSignalRBridge + InMemoryDriverStatusSnapshotStore", + "status": "completed", + "blockedBy": [ + "6.2", + "6.3" + ], + "note": "shipped \u2014 bridge spawned admin-gated (HubServiceCollectionExtensions:69, Program.cs:196); store singleton" + }, + { + "id": "6.5", + "subject": "DriverStatusPanel.razor + wire into all 9 driver pages", + "status": "completed", + "blockedBy": [ + "6.4" + ], + "note": "shipped \u2014 in-process snapshot-store subscription (dodges Traefik self-hub trap), wired into all 9 driver pages" + }, + { + "id": "7.1", + "subject": "IDriverProbe interface + TestDriverConnect messages", + "status": "completed", + "blockedBy": [ + "5.1" + ], + "note": "shipped \u2014 Phase 7 probes (per design note + reconcile)" + }, + { + "id": "7.2", + "subject": "AdminOperationsActor handler for TestDriverConnect", + "status": "completed", + "blockedBy": [ + "7.1" + ], + "note": "shipped" + }, + { + "id": "7.3", + "subject": "TCP probes (Modbus, AbCip, AbLegacy, S7)", + "status": "completed", + "blockedBy": [ + "7.1" + ], + "note": "shipped \u2014 upgraded TCP->protocol handshake (961b2b55 & per-driver)" + }, + { + "id": "7.4", + "subject": "Specialty probes (FOCAS, TwinCAT, OPCUA, Galaxy, Historian)", + "status": "completed", + "blockedBy": [ + "7.1" + ], + "note": "shipped" + }, + { + "id": "7.5", + "subject": "AdminProbeService + DriverTestConnectButton.razor + wire into pages", + "status": "completed", + "blockedBy": [ + "7.2", + "7.3", + "7.4" + ], + "note": "shipped" + }, + { + "id": "8.1", + "subject": "RestartDriver + ReconnectDriver messages + AdminOperationsActor handlers", + "status": "completed", + "blockedBy": [ + "6.5", + "7.5" + ], + "note": "shipped \u2014 Commons/Messages/Admin + AdminOperationsActor + DriverHostActor handlers" + }, + { + "id": "8.2", + "subject": "DriverOperator authorization policy + docs/Security.md update", + "status": "completed", + "blockedBy": [ + "6.5" + ], + "note": "shipped \u2014 DriverOperator policy gates the panel buttons" + }, + { + "id": "8.3", + "subject": "Wire Reconnect/Restart buttons into DriverStatusPanel", + "status": "completed", + "blockedBy": [ + "8.1", + "8.2" + ], + "note": "shipped \u2014 DriverOperator-gated Reconnect/Restart in DriverStatusPanel.razor" + }, + { + "id": "9.1", + "subject": "DriverTagPicker.razor modal shell", + "status": "completed", + "blockedBy": [ + "5.1" + ], + "note": "shipped \u2014 Phase 9 typed address pickers for all 9 drivers (reconcile)" + }, + { + "id": "9.2", + "subject": "Modbus address picker body + unit test", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "9.3", + "subject": "AbCip address picker body + unit test", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "9.4", + "subject": "AbLegacy address picker body + unit test", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "9.5", + "subject": "S7 address picker body + unit test", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "9.6", + "subject": "TwinCat address picker body + unit test", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "9.7", + "subject": "FOCAS address picker body + unit test", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "9.8", + "subject": "OpcUaClient picker body (free-text NodeId)", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "9.9", + "subject": "Galaxy picker body (free-text tag_name.AttributeName)", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "9.10", + "subject": "Historian.Wonderware picker body + unit test", + "status": "completed", + "blockedBy": [ + "9.1" + ], + "note": "shipped" + }, + { + "id": "10.1", + "subject": "DriverTestConnectE2eTests (Modbus/AbCip/S7 vs Docker sims)", + "status": "completed", + "blockedBy": [ + "8.3", + "9.10" + ], + "commit": "494da22c", + "note": "shipped (skip-gated on sim reachability)" + }, + { + "id": "10.2", + "subject": "DriverReconnectE2eTests", + "status": "completed", + "blockedBy": [ + "8.3", + "9.10" + ], + "commit": "494da22c", + "note": "shipped; deferred deeper deployed-driver Healthy->Reconnecting->Healthy transition CLOSED 2026-06-18 (docs/plans/2026-06-18-driver-pages-reconnect-e2e.md)" + }, + { + "id": "10.3", + "subject": "DriverStatusHubE2eTests", + "status": "completed", + "blockedBy": [ + "8.3", + "9.10" + ], + "commit": "494da22c", + "note": "shipped (mock IHubContext + manual bridge spawn)" + }, + { + "id": "10.4", + "subject": "Manual smoke checklist (documented)", + "status": "obsolete", + "blockedBy": [ + "10.1", + "10.2", + "10.3" + ], + "note": "Closed 2026-08-10 as obsolete (was: design \u00a78.3 checklist authored; automated coverage substantially supersedes it (new deployed-driver reconnect E2E + green driver E2E suite 2026-06-18). Full browser smoke recording NOT executed (deferred \u2014 login-disabled docker-dev rig drive).) \u2014 the routed /clusters/{id}/drivers flow this checklist smokes (DriverTypePicker, DriverEditRouter, the 8 *DriverPage shells) was retired in v3 Batch 2; no driver pages exist under Components/Pages/. The form bodies live on inside the /raw modals, which were live-gated repeatedly across the 2026-07/08 issue rounds (see deferment.md \u00a79)." + } ], "lastUpdated": "2026-06-18" -} +} \ No newline at end of file diff --git a/docs/plans/2026-06-19-followups-batch.md.tasks.json b/docs/plans/2026-06-19-followups-batch.md.tasks.json index ac31e679..6e611397 100644 --- a/docs/plans/2026-06-19-followups-batch.md.tasks.json +++ b/docs/plans/2026-06-19-followups-batch.md.tasks.json @@ -12,17 +12,167 @@ "reconsiderGates": "T7 BUILT+SHIPPED (FB-7, master 30c9821f). T8 NOT built (awaiting explicit go-ahead). T9/T10 DONE (FB-9/FB-10, live-verified). T11 PARTIAL: Phase B native-alarm pipeline PROVEN live 2026-06-19 (Galaxy! ConditionId-prefix finding); Phase C HistoryRead + H6 ack->AVEVA + AbLegacy/FOCAS/TwinCAT probes remain AVEVA/hardware/no-local-target deferred." }, "tasks": [ - {"id": 1, "ref": "A1", "subject": "OpcUaClient history session-capture-before-gate race fix", "classification": "standard", "status": "completed", "commits": ["eb328e57","eede0c92"], "parallelizableWith": [2,3,4,5,6], "group": "A-actionable"}, - {"id": 2, "ref": "A2", "subject": "Client.CLI enable/disable command (H4 client path)", "classification": "standard", "status": "completed", "commits": ["88d5ba45","f81fa768"], "parallelizableWith": [1,3,4,5,6], "group": "A-actionable"}, - {"id": 3, "ref": "A3", "subject": "Cert-audit minor review nits (unreachable fallthrough comment + single PkiStoreRoot read)", "classification": "trivial", "status": "completed", "commits": ["6223bc97"], "parallelizableWith": [1,2,4,5,6], "group": "A-actionable"}, - {"id": 4, "ref": "B2", "subject": "AdminUI: preserve edited alarm fields on Galaxy address re-pick", "classification": "small", "status": "completed", "commits": ["2dd723e1","e047af05"], "liveVerify": "substantial (picker+gateway-browse+config-commit confirmed; final pick-and-assert blocked by object-browser href quirk; preservation unit-tested)", "parallelizableWith": [1,2,3,5,6], "group": "B-deferred"}, - {"id": 5, "ref": "B3", "subject": "AdminUI: refresh script dropdown label after inline create", "classification": "small", "status": "completed", "commits": ["da57c307","d8254630"], "liveVerify": "PASS (inline New script -> dropdown label = new script)", "parallelizableWith": [1,2,3,4,6], "group": "B-deferred"}, - {"id": 6, "ref": "B1", "subject": "Write-outcome residuals: Bad-quality blip + AuditWriteUpdateEvent + sync fail-fast", "classification": "standard", "status": "completed", "commits": ["36eb14e8","85afb678"], "note": "production already shipped bb59fd4e 2026-06-15; delivered missing behavioural test coverage + private->internal seam", "parallelizableWith": [1,2,3,4,5], "group": "B-deferred"}, - {"id": 7, "ref": "B4", "subject": "F10b surgical DataType/IsArray in-place writes", "classification": "standard", "status": "pending", "gate": "RECONSIDER — previously decided against (dirty); do NOT build without explicit go-ahead", "group": "B-reconsider"}, - {"id": 8, "ref": "B5", "subject": "Alarm-severity SetSeverity surgical update", "classification": "small", "status": "pending", "gate": "RECONSIDER — operationally invisible (alarm engine overwrites); do NOT build without explicit go-ahead", "group": "B-reconsider"}, - {"id": 9, "ref": "C1", "subject": "Modbus-Int64 full live authoring on docker-dev", "classification": "verify", "status": "pending", "note": "operator/rig verify-only; seed a Modbus driver", "group": "C-verify"}, - {"id": 10, "ref": "C2", "subject": "S7 + AbCip Test-Connect probe happy-path live-verify", "classification": "verify", "status": "pending", "note": "needs lmxopcua-fix fixtures from the Windows VM", "group": "C-verify"}, - {"id": 11, "ref": "C3", "subject": "Device-gated proofs (H6 ack→AVEVA, Phase C T7, Phase B T9, AbLegacy/TwinCAT/FOCAS probe)", "classification": "blocked", "status": "partial", "note": "Live-assessed 2026-06-19 (gateway 10.100.0.48:5120 reachable from this Mac, so the 'all blocked' label was partly stale). OUTCOMES: (Phase B T9) DONE — native-alarm PIPELINE proven end-to-end live on docker-dev: authored a Galaxy alarm tag (FullName=Galaxy!TestArea.TestMachine_001.TestAlarm001, alarm{alarmType:OffNormalAlarm,severity:750}) -> Galaxy driver opened the native-alarm subscription (previously-gated path) -> gateway transition materialised Part 9 condition GalaxyNativeAlarm (ns=2;s=EQ-55297329838d/GalaxyNativeAlarm) carrying the EXACT gateway raise time 2026-05-24T16:04:10.856Z, surfaced via ConditionRefresh. KEY FINDING: ConditionId match REQUIRES the 'Galaxy!' source prefix on the authored FullName (without it every transition is silently dropped). Severity 700 = MapSeverity(750) (MediumHigh bucket), not a bug. Net state Inactive/Unacked because the gateway replays weeks-old historical raises -> a fresh Active-state + live /alerts row needs an alarm triggered on the AVEVA side. (Phase C T7) DEFERRED config+data-gated — confirmed the historized Galaxy node materialises + server HistoryRead path returns GoodNoData/0-values with ServerHistorian.Enabled=false (correct NullHistorianDataSource degrade); live data needs enabling ServerHistorian + Wonderware sidecar on 10.100.0.48 + actual stored history (synthetic ref has none). (H6 ack->AVEVA) DEFERRED — ack SEND reachable but Galaxy AckMsg is write-only/fire-and-forget; confirming it LANDED needs AVEVA-side observation on 10.100.0.48. (AbLegacy/FOCAS/TwinCAT probe) DEFERRED — no local sims running + no live-target probe harness; TwinCAT(ADS) genuinely has no rig target. Rig restored (alarm tag removed, Galaxy back to value-only).", "group": "C-blocked"} + { + "id": 1, + "ref": "A1", + "subject": "OpcUaClient history session-capture-before-gate race fix", + "classification": "standard", + "status": "completed", + "commits": [ + "eb328e57", + "eede0c92" + ], + "parallelizableWith": [ + 2, + 3, + 4, + 5, + 6 + ], + "group": "A-actionable" + }, + { + "id": 2, + "ref": "A2", + "subject": "Client.CLI enable/disable command (H4 client path)", + "classification": "standard", + "status": "completed", + "commits": [ + "88d5ba45", + "f81fa768" + ], + "parallelizableWith": [ + 1, + 3, + 4, + 5, + 6 + ], + "group": "A-actionable" + }, + { + "id": 3, + "ref": "A3", + "subject": "Cert-audit minor review nits (unreachable fallthrough comment + single PkiStoreRoot read)", + "classification": "trivial", + "status": "completed", + "commits": [ + "6223bc97" + ], + "parallelizableWith": [ + 1, + 2, + 4, + 5, + 6 + ], + "group": "A-actionable" + }, + { + "id": 4, + "ref": "B2", + "subject": "AdminUI: preserve edited alarm fields on Galaxy address re-pick", + "classification": "small", + "status": "completed", + "commits": [ + "2dd723e1", + "e047af05" + ], + "liveVerify": "substantial (picker+gateway-browse+config-commit confirmed; final pick-and-assert blocked by object-browser href quirk; preservation unit-tested)", + "parallelizableWith": [ + 1, + 2, + 3, + 5, + 6 + ], + "group": "B-deferred" + }, + { + "id": 5, + "ref": "B3", + "subject": "AdminUI: refresh script dropdown label after inline create", + "classification": "small", + "status": "completed", + "commits": [ + "da57c307", + "d8254630" + ], + "liveVerify": "PASS (inline New script -> dropdown label = new script)", + "parallelizableWith": [ + 1, + 2, + 3, + 4, + 6 + ], + "group": "B-deferred" + }, + { + "id": 6, + "ref": "B1", + "subject": "Write-outcome residuals: Bad-quality blip + AuditWriteUpdateEvent + sync fail-fast", + "classification": "standard", + "status": "completed", + "commits": [ + "36eb14e8", + "85afb678" + ], + "note": "production already shipped bb59fd4e 2026-06-15; delivered missing behavioural test coverage + private->internal seam", + "parallelizableWith": [ + 1, + 2, + 3, + 4, + 5 + ], + "group": "B-deferred" + }, + { + "id": 7, + "ref": "B4", + "subject": "F10b surgical DataType/IsArray in-place writes", + "classification": "standard", + "status": "pending", + "gate": "RECONSIDER \u2014 previously decided against (dirty); do NOT build without explicit go-ahead", + "group": "B-reconsider" + }, + { + "id": 8, + "ref": "B5", + "subject": "Alarm-severity SetSeverity surgical update", + "classification": "small", + "status": "pending", + "gate": "RECONSIDER \u2014 operationally invisible (alarm engine overwrites); do NOT build without explicit go-ahead", + "group": "B-reconsider" + }, + { + "id": 9, + "ref": "C1", + "subject": "Modbus-Int64 full live authoring on docker-dev", + "classification": "verify", + "status": "completed", + "note": "VERIFIED PASS 2026-08-10 on docker-dev (rig rebuilt to master 481f4343, image parity asserted across all 6 nodes). Authored Int64 raw tag TASK9-INT64 (RawPath pymodbus/plc/Task9Int64, TagConfig region=HoldingRegisters address=200 dataType=Int64 BigEndian) via ConfigDb + headless deploy API; deployment b4d7c8be sealed (Status=2). Node advertises DataType i=8 (Int64), ValueRank -1, Good, on BOTH :4840 and :4841; value 347340207162261544 is the exact BigEndian decode of HR200-203=(1234,20,30,40). Value-change propagation proven by driving HR203 via FC06 (observed via subscribe on both centrals; registers restored after). Fixture caveat: the standard profile has NO naturally-churning 4-register span (HR100 is isolated; spans over it return ILLEGAL DATA ADDRESS), so churn was externally driven. No product gap. Tag row left in place, deployed and serving, consistent with prior gate rows.", + "group": "C-verify" + }, + { + "id": 10, + "ref": "C2", + "subject": "S7 + AbCip Test-Connect probe happy-path live-verify", + "classification": "verify", + "status": "completed", + "note": "VERIFIED PASS 2026-08-10: DriverProbeHandshakeE2eTests 12/12 passed, 0 skipped (S7_Green_AgainstSim, AbCip_Green_AgainstSim with 'CIP session OK' proving a real authored-tag read, AbCip_WithNoAuthoredTags_ReportsTheControllerReachable, plus Modbus/OpcUaClient/local-rig/Galaxy legs \u2014 mxaccessgw on 10.100.0.48 happened to be reachable). Correction to the task's premise: skip-gating is pure TCP reachability (DockerFixtureAvailability.IsReachable), NOT env vars, and the checked-in defaults already point at 10.100.0.35 \u2014 runnable from macOS directly; the 'needs Windows-VM fixtures' note was stale. S7 fixture started then removed (net zero); AbCip was already up (5 days) and left as found.", + "group": "C-verify" + }, + { + "id": 11, + "ref": "C3", + "subject": "Device-gated proofs (H6 ack\u2192AVEVA, Phase C T7, Phase B T9, AbLegacy/TwinCAT/FOCAS probe)", + "classification": "blocked", + "status": "partial", + "note": "Live-assessed 2026-06-19 (gateway 10.100.0.48:5120 reachable from this Mac, so the 'all blocked' label was partly stale). OUTCOMES: (Phase B T9) DONE \u2014 native-alarm PIPELINE proven end-to-end live on docker-dev: authored a Galaxy alarm tag (FullName=Galaxy!TestArea.TestMachine_001.TestAlarm001, alarm{alarmType:OffNormalAlarm,severity:750}) -> Galaxy driver opened the native-alarm subscription (previously-gated path) -> gateway transition materialised Part 9 condition GalaxyNativeAlarm (ns=2;s=EQ-55297329838d/GalaxyNativeAlarm) carrying the EXACT gateway raise time 2026-05-24T16:04:10.856Z, surfaced via ConditionRefresh. KEY FINDING: ConditionId match REQUIRES the 'Galaxy!' source prefix on the authored FullName (without it every transition is silently dropped). Severity 700 = MapSeverity(750) (MediumHigh bucket), not a bug. Net state Inactive/Unacked because the gateway replays weeks-old historical raises -> a fresh Active-state + live /alerts row needs an alarm triggered on the AVEVA side. (Phase C T7) DEFERRED config+data-gated \u2014 confirmed the historized Galaxy node materialises + server HistoryRead path returns GoodNoData/0-values with ServerHistorian.Enabled=false (correct NullHistorianDataSource degrade); live data needs enabling ServerHistorian + Wonderware sidecar on 10.100.0.48 + actual stored history (synthetic ref has none). (H6 ack->AVEVA) DEFERRED \u2014 ack SEND reachable but Galaxy AckMsg is write-only/fire-and-forget; confirming it LANDED needs AVEVA-side observation on 10.100.0.48. (AbLegacy/FOCAS/TwinCAT probe) DEFERRED \u2014 no local sims running + no live-target probe harness; TwinCAT(ADS) genuinely has no rig target. Rig restored (alarm tag removed, Galaxy back to value-only).", + "group": "C-blocked" + } ], "lastUpdated": "2026-06-19" -} +} \ No newline at end of file diff --git a/docs/plans/2026-06-26-otopcua-fixedtree-followups.md.tasks.json b/docs/plans/2026-06-26-otopcua-fixedtree-followups.md.tasks.json index 2311cc88..7a980fe8 100644 --- a/docs/plans/2026-06-26-otopcua-fixedtree-followups.md.tasks.json +++ b/docs/plans/2026-06-26-otopcua-fixedtree-followups.md.tasks.json @@ -1,23 +1,152 @@ { "planPath": "docs/plans/2026-06-26-otopcua-fixedtree-followups.md", "tasks": [ - {"id": 1, "subject": "Task 1: Injectable discovery timeout (A)", "status": "completed", "nativeId": 38, "commits": ["c2c368dc"]}, - {"id": 2, "subject": "Task 2: RediscoverPolicy enum + driver overrides (B1)", "status": "completed", "nativeId": 39, "commits": ["a378b572", "efbdaf85"]}, - {"id": 3, "subject": "Task 3: DriverInstanceActor honors policy (B2)", "status": "completed", "blockedBy": [1, 2], "nativeId": 40, "commits": ["ce34816a", "a1a655e6"]}, - {"id": 4, "subject": "Task 4: TriggerRediscovery message + handler (C1)", "status": "completed", "blockedBy": [3], "nativeId": 41, "commits": ["f7358bf4", "e7d5ebe9"]}, - {"id": 5, "subject": "Task 5: EquipmentNode DriverInstanceId/DeviceId/DeviceHost (E projection)", "status": "completed", "nativeId": 42, "commits": ["cb7ce7f1", "915492a7"]}, - {"id": 6, "subject": "Task 6: DriverHostActor cache-as-dict + driver-level resolution (E1)", "status": "completed", "blockedBy": [5], "nativeId": 43, "commits": ["adcd7b57"]}, - {"id": 7, "subject": "Task 7: Re-trigger discovery on rebind drop (C2)", "status": "completed", "blockedBy": [4, 6], "nativeId": 44, "commits": ["53367148", "cde16063"]}, - {"id": 8, "subject": "Task 8: Single SetDesiredSubscriptions per redeploy (D)", "status": "completed", "blockedBy": [7], "nativeId": 45, "commits": ["05c82079", "51721df5"]}, - {"id": 9, "subject": "Task 9: Multi-device-per-driver partition (E2)", "status": "completed", "blockedBy": [5, 8], "nativeId": 46, "commits": ["50f08635", "0074f37a"]}, - {"id": 10, "subject": "Task 10: Docs — follow-up notes + statuses", "status": "completed", "blockedBy": [9], "nativeId": 47}, - {"id": 11, "subject": "Task 11: Build + offline suite + regression gate", "status": "pending", "blockedBy": [2, 4, 9, 10], "nativeId": 48} + { + "id": 1, + "subject": "Task 1: Injectable discovery timeout (A)", + "status": "completed", + "nativeId": 38, + "commits": [ + "c2c368dc" + ] + }, + { + "id": 2, + "subject": "Task 2: RediscoverPolicy enum + driver overrides (B1)", + "status": "completed", + "nativeId": 39, + "commits": [ + "a378b572", + "efbdaf85" + ] + }, + { + "id": 3, + "subject": "Task 3: DriverInstanceActor honors policy (B2)", + "status": "completed", + "blockedBy": [ + 1, + 2 + ], + "nativeId": 40, + "commits": [ + "ce34816a", + "a1a655e6" + ] + }, + { + "id": 4, + "subject": "Task 4: TriggerRediscovery message + handler (C1)", + "status": "completed", + "blockedBy": [ + 3 + ], + "nativeId": 41, + "commits": [ + "f7358bf4", + "e7d5ebe9" + ] + }, + { + "id": 5, + "subject": "Task 5: EquipmentNode DriverInstanceId/DeviceId/DeviceHost (E projection)", + "status": "completed", + "nativeId": 42, + "commits": [ + "cb7ce7f1", + "915492a7" + ] + }, + { + "id": 6, + "subject": "Task 6: DriverHostActor cache-as-dict + driver-level resolution (E1)", + "status": "completed", + "blockedBy": [ + 5 + ], + "nativeId": 43, + "commits": [ + "adcd7b57" + ] + }, + { + "id": 7, + "subject": "Task 7: Re-trigger discovery on rebind drop (C2)", + "status": "completed", + "blockedBy": [ + 4, + 6 + ], + "nativeId": 44, + "commits": [ + "53367148", + "cde16063" + ] + }, + { + "id": 8, + "subject": "Task 8: Single SetDesiredSubscriptions per redeploy (D)", + "status": "completed", + "blockedBy": [ + 7 + ], + "nativeId": 45, + "commits": [ + "05c82079", + "51721df5" + ] + }, + { + "id": 9, + "subject": "Task 9: Multi-device-per-driver partition (E2)", + "status": "completed", + "blockedBy": [ + 5, + 8 + ], + "nativeId": 46, + "commits": [ + "50f08635", + "0074f37a" + ] + }, + { + "id": 10, + "subject": "Task 10: Docs \u2014 follow-up notes + statuses", + "status": "completed", + "blockedBy": [ + 9 + ], + "nativeId": 47 + }, + { + "id": 11, + "subject": "Task 11: Build + offline suite + regression gate", + "status": "obsolete", + "blockedBy": [ + 2, + 4, + 9, + 10 + ], + "nativeId": 48, + "note": "Closed 2026-08-10 as obsolete: the FixedTree-under-Equipment injection feature this gate verified was deleted wholesale when #507 closed as superseded (DiscoveredNodesReady, DiscoveredNodeMapper, HandleDiscoveredNodes, the connect-time discovery loop, and the 18 DiscoveryInjectionDormantV3 tests are all gone in v3). A verification gate for deleted code verifies nothing. ITagDiscovery itself lives on via the /raw browse picker (DiscoveryDriverBrowser), which has its own coverage." + } ], "nativeTaskIds": { - "1": 38, "2": 39, "3": 40, "4": 41, "5": 42, "6": 43, - "7": 44, "8": 45, "9": 46, "10": 47, "11": 48 + "1": 38, + "2": 39, + "3": 40, + "4": 41, + "5": 42, + "6": 43, + "7": 44, + "8": 45, + "9": 46, + "10": 47, + "11": 48 }, "lastUpdated": "2026-06-26T00:00:00Z", "status": "code+docs complete; final build/suite gate pending", "branch": "feat/focas-fixedtree-equipment-injection" -} +} \ No newline at end of file