fix(runtime): prune the native-alarm projector on deploy instead of clearing it (#641)

DriverHostActor cleared NativeAlarmProjector's per-condition prior state on
EVERY apply, so after any deploy a driver Acknowledge of a still-active alarm
projected Active=false (writing it inactive) and a Clear of an unacknowledged
alarm projected Acked=true (silently acknowledging it). The projector is now
pruned to the conditions the new composition still carries (RetainOnly).

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 17:05:42 -04:00
parent ddd7678269
commit 11f13f6326
4 changed files with 113 additions and 6 deletions
@@ -24,6 +24,21 @@ public class NativeAlarmProjectorTests
snap.Message.ShouldBe("boom");
}
/// <summary>Gitea #641 — <c>RetainOnly</c> keeps a still-deployed condition's prior state and forgets a removed
/// one's (which then starts from the default inactive + acked).</summary>
[Fact]
public void RetainOnly_keeps_deployed_conditions_and_forgets_removed_ones()
{
var sut = new NativeAlarmProjector();
sut.Project("kept", Evt(AlarmTransitionKind.Raise));
sut.Project("removed", Evt(AlarmTransitionKind.Raise));
sut.RetainOnly(new HashSet<string>(StringComparer.Ordinal) { "kept" });
sut.Project("kept", Evt(AlarmTransitionKind.Acknowledge)).Active.ShouldBeTrue();
sut.Project("removed", Evt(AlarmTransitionKind.Acknowledge)).Active.ShouldBeFalse();
}
[Fact]
public void Retrigger_projects_active_unacked()
{