diff --git a/docs/AlarmTracking.md b/docs/AlarmTracking.md index 8860e8f8..4f00551d 100644 --- a/docs/AlarmTracking.md +++ b/docs/AlarmTracking.md @@ -158,6 +158,16 @@ condition's state?") — mirroring the native OT semantic: guard's job) — it contributes `Good`, so scripted conditions don't flash `Bad` at every deploy. The first actually-`Bad` published value flips the bucket and annotates. +**Coverage boundary (#478 as shipped).** Scripted quality tracks input tags whose driver **publishes a +data change carrying a Bad/Uncertain `StatusCode`** (e.g. an OpcUaClient input forwarding a server's +per-item Bad). It does **not** yet cover a driver **comms loss**: a poll driver (Modbus/S7) whose device +goes unreachable emits only `ConnectivityChanged` and goes *silent* on the value feed (see +`DriverInstanceActor.Reconnecting`), so the scripted engine keeps the last-known Good value and the +condition stays `Good`. Bridging driver connectivity into scripted inputs — the symmetric of the native +`OnDriverConnectivityChanged` path above, plus resolving the null-value/cold-start asymmetry (a runtime +`Bad` with a null value is currently indistinguishable from cold start and contributes `Good`) — is tracked +as the Layer-4 follow-up (#481). + Guards: `ScriptedAlarmEngineTests` (transition carries `Uncertain`; `Bad` input with no transition emits `QualityChanged(Bad)`; restore emits `QualityChanged(Good)`; unchanged bucket emits nothing), `ScriptedAlarmSourceTests.QualityChanged_emission_raises_no_alarm_event`, diff --git a/docs/plans/2026-07-17-alarm-condition-quality-477-design.md b/docs/plans/2026-07-17-alarm-condition-quality-477-design.md index 722d471b..7af95234 100644 --- a/docs/plans/2026-07-17-alarm-condition-quality-477-design.md +++ b/docs/plans/2026-07-17-alarm-condition-quality-477-design.md @@ -174,3 +174,14 @@ So even a `Bad` driver value reached the scripted engine as Good — Layer 3 has `ScriptedAlarmSource` — `QualityChanged` raises no `OnAlarmEvent`. Mux — `DependencyValueChanged` carries the published quality. Host — `Bad` dependency → `AlarmQualityUpdate(Bad)`, no `/alerts` publish; `ToSnapshot` maps the event's worst quality. + +**Coverage boundary → Layer 4 (#481).** L3 covers inputs whose driver **publishes a Bad/Uncertain-status +data change** (the mux quality path). It does **not** cover a driver **comms loss**: a poll driver +(Modbus/S7) whose device goes unreachable emits only `ConnectivityChanged` and goes silent on the value feed +(`DriverInstanceActor.Reconnecting`), so the scripted engine keeps the last-known Good value and the +condition stays Good — the same silent-feed problem native solved in L2, but native's `OnDriverConnectivityChanged` +bridge fans only to **native** condition nodes (`_alarmNodeIdByDriverRef`), not into the mux the scripted +engine reads. Bridging connectivity into scripted inputs — plus resolving the null-value/cold-start +asymmetry (a runtime `Bad` with a null value is currently indistinguishable from cold start and contributes +`Good`) and its ripple into virtual-tag quality — is **Gitea #481 (Layer 4)**. Found by the post-implementation +code review; the code as shipped faithfully implements #478's written scope (mux-delivered input quality).