diff --git a/docs/ScriptedAlarms.md b/docs/ScriptedAlarms.md
index 00c18794..f437e58a 100644
--- a/docs/ScriptedAlarms.md
+++ b/docs/ScriptedAlarms.md
@@ -145,8 +145,9 @@ runtime.
#### Severity mapping
The authored `severity` (1–1000) seeds the OPC UA condition node at materialisation
-time. On the **first native transition** the value snaps to one of four fixed buckets
-via `NativeAlarmProjector.MapSeverity`:
+time. Every native transition maps the driver's `AlarmSeverity` to one of four fixed
+buckets via `NativeAlarmProjector.MapSeverity`, overriding the authored `severity` seed
+from the first transition onward:
| `AlarmSeverity` enum | Projected value |
|---|---|
@@ -168,8 +169,8 @@ by `OtOpcUaNodeManager.MapSeverity` on each `AlarmStateUpdate` write:
| ≥ 800 | `High` |
Consequently the four authored buckets land as: Low→`MediumLow`, Medium→`Medium`,
-High→`MediumHigh`, Critical→`High`. The authored `severity` field has no effect after
-the first transition.
+High→`MediumHigh`, Critical→`High`. The authored `severity` field is overridden by
+live driver events on every transition.
### Runtime flow
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverInstanceActorNativeAlarmTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverInstanceActorNativeAlarmTests.cs
index adb0e8dd..b9d2dfcf 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverInstanceActorNativeAlarmTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverInstanceActorNativeAlarmTests.cs
@@ -1,4 +1,5 @@
using Akka.Actor;
+using Akka.Event;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
@@ -94,8 +95,10 @@ public sealed class DriverInstanceActorNativeAlarmTests : RuntimeActorTestBase
///
/// A native alarm transition that races in while the actor is in Reconnecting is silently
/// dropped (debug log only) — it NEVER reaches the parent as
- /// and does NOT dead-letter. The feed
- /// re-delivers active alarms once the actor re-enters Connected, so dropping here is safe.
+ /// AND is NOT dead-lettered (the
+ /// Reconnecting state's explicit Receive<NativeAlarmRaised> handler consumes and
+ /// discards it, so it never becomes unhandled). The feed re-delivers active alarms once the actor
+ /// re-enters Connected, so dropping here is safe.
/// ( line ~345: the Reconnecting state's
/// Receive<NativeAlarmRaised> logs a debug message and discards.)
///
@@ -107,10 +110,27 @@ public sealed class DriverInstanceActorNativeAlarmTests : RuntimeActorTestBase
/// (detaches handler), then processes the queued NativeAlarmRaised in Reconnecting
/// → drops it. The default 10 s reconnect interval ensures no retry fires during the check.
///
+ ///
+ ///
+ /// Both properties are actively asserted: (a) the parent probe receives no
+ /// ; (b) a dead-letter probe subscribed
+ /// to on the also receives
+ /// nothing — proving the drop handler is present (removing it would cause a dead-letter and fail
+ /// this assertion). NativeAlarmRaised is private to the actor, so the dead-letter probe
+ /// subscribes to the unfiltered channel; this is safe because
+ /// exactly one message is injected and the reconnect timer (10 s) cannot fire in the window.
+ ///
///
[Fact]
public void Native_alarm_during_reconnect_is_dropped_not_forwarded()
{
+ // Subscribe a dead-letter probe BEFORE injecting the alarm so we don't miss any early publish.
+ // NativeAlarmRaised is private, so we subscribe to the unfiltered AllDeadLetters channel.
+ // Only one message is injected and the 10 s reconnect timer can't fire in this window, so
+ // a plain "no dead letters at all" assertion is safe and non-flaky.
+ var deadLetters = CreateTestProbe();
+ Sys.EventStream.Subscribe(deadLetters.Ref, typeof(AllDeadLetters));
+
// Long reconnect interval (default 10 s) so the retry doesn't fire during the assertion window.
var driver = new AlarmSourceStubDriver();
var parent = CreateTestProbe();
@@ -134,13 +154,18 @@ public sealed class DriverInstanceActorNativeAlarmTests : RuntimeActorTestBase
SourceTimestampUtc: DateTime.UtcNow,
Kind: AlarmTransitionKind.Raise));
+ // (a) The parent must NOT receive AttributeAlarmPublished from that alarm.
// The actor processes: (1) ForceReconnect → Reconnecting (handler detached);
// (2) NativeAlarmRaised → dropped (debug log, no forward).
- // The parent must NOT receive AttributeAlarmPublished from that alarm.
// Wait generously — the default reconnect interval of 10 s means no retry fires here.
parent.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
- // The actor must still be alive — Watch + no Terminated (not crashed or dead-lettered).
+ // (b) The alarm must also NOT have dead-lettered — the Reconnecting state's explicit
+ // Receive handler must have consumed it. If that handler were removed the
+ // message would become unhandled → AllDeadLetters, and this assertion would catch the regression.
+ deadLetters.ExpectNoMsg(TimeSpan.FromMilliseconds(200));
+
+ // The actor must still be alive — Watch + no Terminated.
Watch(actor);
parent.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
}