diff --git a/docs/plans/2026-05-29-native-alarms.RESUME.md b/docs/plans/2026-05-29-native-alarms.RESUME.md index 3e6e65d8..caada7ec 100644 --- a/docs/plans/2026-05-29-native-alarms.RESUME.md +++ b/docs/plans/2026-05-29-native-alarms.RESUME.md @@ -8,10 +8,15 @@ - Do all work here; `main` checkout stays untouched. Build: `dotnet build ZB.MOM.WW.ScadaBridge.slnx`. - The shared MS SQL container `scadabridge-mssql` is up (the ConfigDB MsSql migration-fixture tests use it). -## Progress: Tasks 1–18 done & committed; 19–28 pending -Commits (oldest→newest): `696da92` T1, `edc2dac` T2, `ea14ace` T3, `9134419` T4, `63f1ec2` T5, `aedd17c` T6, `fc05ba1` T7, `e5392d2` T8, `ba27873` T9, `d3b3d15` T10, `1fbb814`+`0d30b7d` T11, `c741170` T12, `b44a844` T13, `24fd7be` T14, `fda7ac9` T15, `6d31858` T16, `bca21ff` T17, `20b41b8` T18. +## Progress: Tasks 1–21 done & committed; 22–28 pending +Commits (oldest→newest): `696da92` T1 … `20b41b8` T18, `0c6f9a9` T19, `b1df6d5` T20, `3bf1d26` T21. (Full list in git log.) -**Cadence is batches of 3 (user choice on resume).** Batch 4 = T13–15 ✅, Batch 5 = T16–18 ✅. Full SiteRuntime.Tests green (313/313); Communication.Tests green (200/200). Next: **Batch 6 = T19–21** (gRPC mapping → mgmt command contracts → ManagementActor handlers). Then 22 (CLI), 23–25 (UI), 26 (seed), 27 (docs), 28 (live integration). +**Cadence is batches of 3 (user choice on resume).** Batch 4 = T13–15 ✅, Batch 5 = T16–18 ✅, Batch 6 = T19–21 ✅. Greens: SiteRuntime.Tests 313/313, Communication.Tests 200/200, ManagementService.Tests 111/111, Commons.Tests registry 8/8. Next: **Batch 7 = T22 (CLI) → T23 (DebugView UI) → T24 (Template editor UI)**. Then 25 (instance UI), 26 (seed), 27 (docs), 28 (live integration). + +## Decisions / deviations — Batch 6 (T19–21) +- **T19:** `AlarmShelveStateCodec` (string↔enum, default Unshelved). Server `StreamRelayActor` maps `msg.Condition.*` + `Kind.ToString()` + nullable `OriginalRaiseTime` out; client `ConvertToDomainEvent` rebuilds `Condition` (severity = wire `Priority`) + `ParseAlarmKind` back. **Gotcha:** client imports `Google.Protobuf.WellKnownTypes`, so `Enum` is ambiguous — used `System.Enum.TryParse`. `confirmed` proto bool → domain `bool?` (false, never null after round-trip). +- **T20:** `ManagementCommandRegistry` is **reflection-based** (auto-discovers `*Command` records in the Management namespace) — no manual registry edit needed; just added the 7 records to TemplateCommands.cs / InstanceCommands.cs. +- **T21:** Handlers call `ITemplateEngineRepository` **directly** + `SaveChangesAsync` (per plan's "call the Task 6 repo methods"), NOT through TemplateService/InstanceService. **Trade-off:** this skips the service-layer `IAuditService` logging that the existing template/instance alarm CRUD gets. Acceptable for the read-only-mirror authoring commands and matches the plan's Files scope (ManagementService only), but flag if audit parity is wanted later. Roles: template mutations = Design, instance-override mutations = Deployment, lists = any authenticated. Update = fetch-then-mutate (preserves TemplateId for the unique index). Set-override = upsert (Add if absent else Update). ## Decisions / deviations — Batch 5 (T16–18) - **T16:** Connection protocol IS in `FlattenedConfiguration.Connections[name].Protocol` → `ResolveNativeKind` maps protocol-contains-"Mx" → `NativeMxAccess` else `NativeOpcUa`; passed into NativeAlarmActor. Added `_latestAlarmEvents` (enriched event per AlarmName) + extracted `BuildAlarmStatesSnapshot()` used by both `HandleSubscribeDebugView` and `HandleDebugSnapshot` (enriched events ∪ Normal-projection fallback for computed alarms that haven't fired). Native actors skipped when `_dclManager == null` (isolated tests). **Beyond the plan's Files list (justified):** redeploy/undeploy clear — added `native_alarm_state` DELETE to `SiteStorageService.RemoveDeployedConfigAsync` transaction (undeploy) + `ClearNativeAlarmsForInstanceAsync` next to `ClearStaticOverridesAsync` in `DeploymentManagerActor` redeploy path. Native state survives failover (rehydrate) but resets on redeploy — mirrors static-override semantics. diff --git a/docs/plans/2026-05-29-native-alarms.md.tasks.json b/docs/plans/2026-05-29-native-alarms.md.tasks.json index cbc6d727..8678acbd 100644 --- a/docs/plans/2026-05-29-native-alarms.md.tasks.json +++ b/docs/plans/2026-05-29-native-alarms.md.tasks.json @@ -19,9 +19,9 @@ {"id": 16, "subject": "Task 16: InstanceActor wiring", "status": "completed", "blockedBy": [15]}, {"id": 17, "subject": "Task 17: Enrich computed AlarmActor emit", "status": "completed", "blockedBy": [2]}, {"id": 18, "subject": "Task 18: Extend sitestream.proto + regenerate", "status": "completed", "blockedBy": [2]}, - {"id": 19, "subject": "Task 19: gRPC alarm mapping (server + client)", "status": "pending", "blockedBy": [2, 18]}, - {"id": 20, "subject": "Task 20: Management command contracts + registry", "status": "pending", "blockedBy": [4]}, - {"id": 21, "subject": "Task 21: ManagementActor handlers", "status": "pending", "blockedBy": [6, 20]}, + {"id": 19, "subject": "Task 19: gRPC alarm mapping (server + client)", "status": "completed", "blockedBy": [2, 18]}, + {"id": 20, "subject": "Task 20: Management command contracts + registry", "status": "completed", "blockedBy": [4]}, + {"id": 21, "subject": "Task 21: ManagementActor handlers", "status": "completed", "blockedBy": [6, 20]}, {"id": 22, "subject": "Task 22: CLI commands", "status": "pending", "blockedBy": [20]}, {"id": 23, "subject": "Task 23: DebugView alarm table enrichment", "status": "pending", "blockedBy": [2, 19]}, {"id": 24, "subject": "Task 24: Template editor Native Alarm Sources subsection", "status": "pending", "blockedBy": [20]}, @@ -30,5 +30,5 @@ {"id": 27, "subject": "Task 27: Documentation sync", "status": "pending", "blockedBy": [16, 19, 22, 23, 24, 25]}, {"id": 28, "subject": "Task 28: Integration / live verification", "status": "pending", "blockedBy": [10, 11, 12, 16, 19]} ], - "lastUpdated": "2026-05-31 batch-5-complete" + "lastUpdated": "2026-05-31 batch-6-complete" }