fix(alarms): native-alarm re-statements no longer duplicate history or hide acked alarms (#656)

- AlarmTransitionKind.ActiveAcknowledged (appended): active AND acked applied as ONE projection.
  Galaxy ActiveAcked snapshot entries and OpcUaClient inactive->(active,acked) use it; the
  projector writes 'Activated' only if not already active, 'Acknowledged' only if not acked.
- AlarmEventArgs.IsRestatement (optional, default false): set only by Galaxy snapshot entries
  and OpcUaClient first sight. A flagged Retrigger on an Active+unacked condition with the same
  message and severity, or a flagged Clear on an inactive condition, writes no /alerts row.
- NativeAlarmProjector reports the history rows per transition; ForwardNativeAlarm writes one
  row per entry. Unflagged sources (FOCAS/MTConnect/AbCip, live Galaxy) are unchanged.
- Tests: projector rules each with a must-write control; OpcUaClient transition table;
  Galaxy feed/driver mapping; Galaxy + OpcUaClient end-to-end through DriverHostActor.

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 23:35:50 -04:00
parent ca17d2cf71
commit b39bb6794d
15 changed files with 973 additions and 81 deletions
@@ -1415,8 +1415,11 @@ public sealed class GalaxyDriver
GalaxyAlarmTransitionKind.Acknowledge => Core.Abstractions.AlarmTransitionKind.Acknowledge,
GalaxyAlarmTransitionKind.Clear => Core.Abstractions.AlarmTransitionKind.Clear,
GalaxyAlarmTransitionKind.Retrigger => Core.Abstractions.AlarmTransitionKind.Retrigger,
GalaxyAlarmTransitionKind.ActiveAcknowledged => Core.Abstractions.AlarmTransitionKind.ActiveAcknowledged,
_ => Core.Abstractions.AlarmTransitionKind.Unspecified,
});
},
// #656: a snapshot entry re-states upstream state — history-only signal for the host.
IsRestatement: transition.IsRestatement);
try
{
OnAlarmEvent?.Invoke(this, args);