{
  "planPath": "docs/plans/2026-06-10-script-log-and-scripted-alarm-runtime.md",
  "designPath": "docs/plans/2026-06-10-script-log-and-scripted-alarm-runtime-design.md",
  "branch": "feat/scriptlog-alarm-runtime",
  "baseBranch": "master",
  "baseSha": "df4c2657",
  "status": "merged-to-master",
  "mergedNote": "T17-T24 (inbound alarm ack/shelve) COMPLETE + merged to master 2026-06-11 on branch feat/scriptlog-alarm-ack. All review-approved (high-risk tasks: spec+code serial; standard: parallel). Full solution builds; every affected unit suite green (OpcUaServer 103, Runtime 137, ControlPlane 56, Core.ScriptedAlarms 67, Commons 25, Client.Shared 173, Client.CLI 93, Security 60, AdminUI 363). Pre-existing macOS/integration failures (OpcUaServer.IntegrationTests PKI store-path; Host.IntegrationTests deploy-Rejected confirmed failing on base; AbLegacy/AbCip fixture tests) are NOT from this work. Live-verified on docker-dev: real Part 9 condition materialises; AdminUI Shelve round-trips end-to-end (singleton->alarm-commands->host->engine->Shelved on /alerts) with operator identity threaded; anonymous OPC UA read/subscribe works. FOLLOW-UPS: (1) alerts-topic double-emit — both warm-redundant central nodes evaluate+emit the same alarm (pre-existing Layer-1/redundancy, only active node should emit or dedup at consumer); (2) T21 Timed-shelve datetime-picker UI deferred (backend wired+tested); (3) T21 auto-clear result chip + CorrelationId-wrapper consistency (minor); (4) docker-dev rig DB cleanup (t12-overheat/SC-ba675b168a85/layer0-logcheck) intentionally LEFT in place for further testing.",
  "note": "Layers 0+1 complete + live-verified; Layer 2 PARTIAL — T13-T16 (Part 9 nodes/state/events) done + reviewed, merged to master. RE-SCOPED 2026-06-11: the single underscoped T17 ('Inbound method dispatch + ack plumbing', ~5min) was a deep dive shown to be FOUR hard problems — now T17 (roles on session identity), T18 (node-manager router + AlarmAck veto + alarm-commands DPS topic), T19 (host-actor inbound handler), T20 (delta-gate double-emit). Old T18->T21 (AdminUI), old T19 split into T22 (Client.CLI ack/confirm/shelve feature work) + T23 (live-verify), old T20->T24 (docs+cleanup+finish). All DEFERRED; start a fresh branch feat/scriptlog-alarm-ack off CURRENT master. T17 step-1 SDK-identity-round-trip spike is the go/no-go gate.",
  "rescopeBranch": "feat/scriptlog-alarm-ack",
  "tasks": [
    {"id": 200, "planTask": 0, "subject": "T0: Branch + test-project check", "status": "completed"},
    {"id": 201, "planTask": 1, "subject": "T1: IScriptLogPublisher + ScriptLogTopicSink", "status": "completed", "commit": "14fe88fc"},
    {"id": 202, "planTask": 2, "subject": "T2: Root script logger + DpsScriptLogPublisher + Host wiring", "status": "completed", "commit": "73014258, bf86b3de"},
    {"id": 203, "planTask": 3, "subject": "T3: Rewire Roslyn evaluators to root logger", "status": "completed", "commit": "bd2dd05a, 788bb68d"},
    {"id": 204, "planTask": 4, "subject": "T4: Live-verify Layer 0", "status": "completed", "commit": "b5748288 (E2E test); live-verified /script-log 2026-06-10"},
    {"id": 205, "planTask": 5, "subject": "T5: EquipmentScriptedAlarmPlan + Phase7Composer enrichment", "status": "completed", "commit": "b28c6bd, 55101baa"},
    {"id": 206, "planTask": 6, "subject": "T6: DeploymentArtifact parity for alarm plan", "status": "completed", "commit": "8e8ca9ef, c9590c03"},
    {"id": 207, "planTask": 7, "subject": "T7: DependencyMuxTagUpstreamSource", "status": "completed", "commit": "945ccd0b, 55101baa"},
    {"id": 208, "planTask": 8, "subject": "T8: EfAlarmConditionStateStore", "status": "completed", "commit": "1c96fe0b, 55101baa"},
    {"id": 209, "planTask": 9, "subject": "T9: ScriptedAlarmHostActor", "status": "completed", "commit": "3b418a54, dafaf2fa"},
    {"id": 210, "planTask": 10, "subject": "T10: Spawn + apply in DriverHostActor", "status": "completed", "commit": "52567613, a8640a93"},
    {"id": 211, "planTask": 11, "subject": "T11: Retire orphaned actor + F9b evaluator", "status": "completed", "commit": "fc0d43a3"},
    {"id": 212, "planTask": 12, "subject": "T12: Live-verify Layer 1", "status": "completed", "commit": "live-verified end-to-end 2026-06-10 (alarm flips active/clear on /alerts, predicate logs on /script-log)"},
    {"id": 213, "planTask": 13, "subject": "T13: SDK research spike (DeepWiki)", "status": "completed", "commit": "4217b213"},
    {"id": 214, "planTask": 14, "subject": "T14: Real condition-node materialisation", "status": "completed", "commit": "60d48a2a, b31d7cb0"},
    {"id": 215, "planTask": 15, "subject": "T15: Richer alarm-state bridge", "status": "completed", "commit": "4eb1d65e, ab5d0752"},
    {"id": 216, "planTask": 16, "subject": "T16: Event firing on transition", "status": "completed", "commit": "295bb55d, 4c417f7f"},
    {"id": 217, "planTask": 17, "subject": "T17: Carry LDAP roles onto the OPC UA session identity", "status": "completed", "classification": "high-risk", "blockedBy": [], "note": "RoleCarryingUserIdentity : UserIdentity + OpcUaApplicationHost.cs:292 swap. STEP 1 = SDK-identity-round-trip spike (go/no-go: does a custom IUserIdentity survive back to context.UserIdentity in a method handler? fallback = GrantedRoleIds). Parallelizable with T22."},
    {"id": 218, "planTask": 18, "subject": "T18: Node-manager command router + AlarmAck veto gate + alarm-commands topic", "status": "completed", "classification": "high-risk", "blockedBy": [217], "note": "AlarmCommand record (Commons); settable Action<AlarmCommand> router on OtOpcUaNodeManager; wire OnAcknowledge/OnConfirm/OnAddComment/OnShelve/OnTimedUnshelve veto delegates in MaterialiseAlarmCondition (gate on AlarmAck from RoleCarryingUserIdentity, route to engine, return Good); pass-through in OtOpcUaSdkServer; publish onto alarm-commands DPS topic from OtOpcUaServerHostedService. Serialize with T20 (same file)."},
    {"id": 219, "planTask": 19, "subject": "T19: ScriptedAlarmHostActor inbound command handler", "status": "completed", "classification": "standard", "blockedBy": [218], "parallelizableWith": [220], "note": "Subscribe alarm-commands in PreStart; Receive<AlarmCommand> async-void switch -> engine.<Op>Async; ownership-filter unknown AlarmIds (multi-node broadcast); NO explicit re-projection (engine OnEvent -> existing OnEngineEmission)."},
    {"id": 220, "planTask": 20, "subject": "T20: Delta-gate event firing (kill inbound double-emit)", "status": "completed", "classification": "high-risk", "blockedBy": [218], "parallelizableWith": [219], "note": "ConcurrentDictionary<string,AlarmConditionSnapshot> _lastAlarmState; WriteAlarmCondition fires ReportConditionEvent only on a delta. Resolves SDK-auto-fire (E2) + engine-re-projection (E3) double-emit. Serialize after T18 (same file OtOpcUaNodeManager.cs)."},
    {"id": 221, "planTask": 21, "subject": "T21: AdminUI ack/shelve control", "status": "completed", "classification": "standard", "blockedBy": [219], "note": "Acknowledge/ShelveAlarmCommand (Commons); AdminOperationsActor singleton handlers publish onto alarm-commands (singleton solves cross-node for AdminUI); AdminOperationsClient methods; Alerts.razor per-row buttons. No bUnit."},
    {"id": 222, "planTask": 22, "subject": "T22: Client.CLI ack/confirm/shelve commands", "status": "completed", "classification": "standard", "blockedBy": [], "parallelizableWith": [217, 218, 219, 220, 221], "note": "NET-NEW client feature (why old T19 wasn't just a verify): IOpcUaClientService Confirm/Shelve (+ wire existing AcknowledgeAlarmAsync); Acknowledge/Confirm/Shelve CLI commands. Only Client.* files -> parallel with the whole server chain."},
    {"id": 223, "planTask": 23, "subject": "T23: Live-verify Layer 2 end-to-end", "status": "completed", "classification": "verification", "blockedBy": [218, 219, 220, 221, 222], "note": "Use deployed t12-overheat. Client.CLI + AdminUI ack round-trip (AckedState flips, ONE event, persists across restart); AlarmAck gate denies without role. User drives sign-in."},
    {"id": 224, "planTask": 24, "subject": "T24: Docs + cleanup + finish branch", "status": "completed", "classification": "small", "blockedBy": [223], "note": "Docs (ScriptedAlarms/VirtualTags/Runtime/AlarmTracking) + fix stale phase-7-status + CLAUDE.md; clean up rig artifacts (t12-overheat, SC-ba675b168a85, layer0-logcheck, revert filler-02 cycle-time-s); delete resume.md+pending.md; finishing-a-development-branch merge."}
  ],
  "lastUpdated": "2026-06-11"
}
