From 8480e301abb7cc8679e55be6fad4897852d0c252 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 18 Jun 2026 04:35:14 -0400 Subject: [PATCH] chore(plan): mark Galaxy handle-sharing tasks complete + live gate results --- ...8-galaxy-writer-handle-sharing.md.tasks.json | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/plans/2026-06-18-galaxy-writer-handle-sharing.md.tasks.json b/docs/plans/2026-06-18-galaxy-writer-handle-sharing.md.tasks.json index 405ce9ca..d57b00e5 100644 --- a/docs/plans/2026-06-18-galaxy-writer-handle-sharing.md.tasks.json +++ b/docs/plans/2026-06-18-galaxy-writer-handle-sharing.md.tasks.json @@ -4,14 +4,19 @@ "designCommit": "c85c4e5c", "baseMaster": "70e1bde9", "branch": "feat/galaxy-writer-handle-sharing", - "scope": "Galaxy writer borrows live MXAccess item handles from the SubscriptionRegistry so the first write to an already-subscribed tag skips a redundant AddItem round-trip. T1: SubscriptionRegistry.TryResolveItemHandle forward fullRef->handle lookup with a liveness guard. T2: writer optional Func subscribedHandleSource + TryResolveCachedOrBorrowed seam (borrowed handles NOT cached) + AddItemCallCount seam. T3: GalaxyDriver wires _subscriptions.TryResolveItemHandle into the production writer ctor. T4: skip-gated live-gw smoke proving a subscribed-tag write commits with AddItemCallCount==0 (control: ==1). NO Commons/proto/EF/migration change; NO bUnit; AdminUI untouched.", + "scope": "Galaxy writer borrows live MXAccess item handles from the SubscriptionRegistry so the first write to an already-subscribed tag skips a redundant AddItem round-trip. NO Commons/proto/EF/migration change; NO bUnit; AdminUI untouched.", "dependencyGraph": "{T1 ∥ T2} -> T3 -> T4", "tasks": [ - {"id": 1, "subject": "SubscriptionRegistry.TryResolveItemHandle forward lookup + tests", "classification": "small", "status": "pending", "parallelizableWith": [2], "files": ["src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/SubscriptionRegistry.cs", "tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests/Runtime/SubscriptionRegistryHandleResolveTests.cs"]}, - {"id": 2, "subject": "Writer borrow seam + AddItemCallCount + tests", "classification": "small", "status": "pending", "parallelizableWith": [1], "files": ["src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyDataWriter.cs", "tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests/Runtime/GatewayGalaxyDataWriterTests.cs"]}, - {"id": 3, "subject": "Wire registry resolver into the production writer in GalaxyDriver", "classification": "small", "status": "pending", "blockedBy": [1, 2], "files": ["src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs"]}, - {"id": 4, "subject": "Live-gw borrow smoke + build/test + live run + finish", "classification": "small", "status": "pending", "blockedBy": [3], "files": ["tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests/Runtime/GatewayGalaxyLiveReopenAndWriteTests.cs"]} + {"id": 1, "subject": "SubscriptionRegistry.TryResolveItemHandle forward lookup + tests", "classification": "small", "status": "completed", "commit": "14119500 (+ review fix e9da9c29)", "review": "Bundle code-review (sonnet) APPROVE-WITH-MINOR. IMPORTANT finding (cross-ref-same-handle could borrow the wrong tag's handle) FIXED — but NOT via the reviewer's suggested 'unconditional remove' (which would have regressed the legitimate multiple-subscriptions-per-tag borrow). Instead made TryResolveItemHandle AUTHORITATIVE: it confirms a live subscription genuinely binds fullRef->handle via the per-entry reverse index, so a stale forward entry can never hand out a dead/wrong handle, AND a tag stays resolvable while any subscription still binds it. Added cross-ref + same-ref-multi-sub tests (both green; the same-ref test would have failed the reviewer's fix). Dropped a pre-existing duplicate SubscriptionEntry (MINOR)."}, + {"id": 2, "subject": "Writer borrow seam + AddItemCallCount + tests", "classification": "small", "status": "completed", "commit": "2e3f528a (+ doc note e9da9c29)", "review": "Bundle-reviewed. Optional last ctor param Func? subscribedHandleSource (default null = unchanged behavior); TryResolveCachedOrBorrowed (borrowed handle NOT cached in _itemHandles — registry owns its lifecycle, self-heals on reconnect); AddItemCallCount seam (Interlocked/Volatile). Documented the supervisory-advise reconnect lifecycle (MINOR). 5 unit tests. NOTE: T1+T2 implementers ran concurrently on a SHARED tree and raced on the git index — commit boundaries got misattributed (14119500 wrongly bundled T2's writer code; 2e3f528a has the tail). Final tree at HEAD is coherent + verified; boundary cosmetics don't affect the ff-merge artifact."}, + {"id": 3, "subject": "Wire registry resolver into the production writer in GalaxyDriver", "classification": "small", "status": "completed", "commit": "3ffe45db", "review": "Inline (3-line wiring) to avoid another shared-tree race; passes _subscriptions.TryResolveItemHandle as the writer's 4th ctor arg at GalaxyDriver.cs:255. Build clean; full Galaxy suite green."}, + {"id": 4, "subject": "Live-gw borrow smoke + build/test + live run + finish", "classification": "small", "status": "completed", "commit": "15922d84", "review": "Inline test (keeps secret-handling + gate interpretation with the parent). New skip-gated [Fact] subscribes WriteRef, registers its real gateway handle, writes via the registry-wired writer.", + "live": "LIVE GATE PASS — sourced GALAXY_MXGW_API_KEY from container otopcua-dev-central-1-1 WITHOUT echoing; ran filter GatewayGalaxyLiveReopenAndWrite vs MXGW_ENDPOINT=http://10.100.0.48:5120 -> 3/3 passed (59s): the 2 existing reopen/write smokes + the new borrow smoke. The borrow smoke's own assertions (borrowed write Good 0 + AddItemCallCount==0; control AddItemCallCount==1) passed, proving BOTH the load-bearing premise (a subscription handle is usable for a committing no-login supervisory write) AND the optimization (zero AddItem on the borrow path)."} + ], + "executionState": "COMPLETE — Driver.Galaxy 294/294 unit green; full solution build 0 errors; live gate 3/3 PASS. Pending merge to master + push.", + "reviewFollowUps": [ + "PROCESS: parallel implementers on a SHARED (non-worktree) working tree race on the git index + build even when their target FILES are disjoint — T1's build saw T2's half-applied edit (transient CS0649) and T1's `git add` snapshotted T2's in-progress writer code into the wrong commit. For future parallel dispatch of disjoint-file tasks, use isolation:'worktree' OR dispatch serially. Final tree was verified coherent here, but the commit boundaries are misattributed.", + "Deferred (design): reverse direction (subscriber borrowing the writer's AddItem handles) — not needed; subscriber handles come from SubscribeBulk." ], - "executionState": "PENDING — subagent-driven execution, this session.", "lastUpdated": "2026-06-18" }