fix(address-space): no UNS value Variable for a reference to an alarm-bearing tag (#896)
v2-ci / unit-tests (push) Has been cancelled

A UnsTagReference to a raw tag that carries an "alarm" object produced a UNS
value Variable that read BadWaitingForInitialData forever (G6 live gate,
TestAlarm002Condition on testmachine-015). BuildUnsReferenceVariables now skips
those references; the equipment gets the alarm only as the raw condition wired
as an event notifier of its folder, which is unchanged (the reference still
feeds RawTagPlan.ReferencingEquipmentPaths).

Why condition-only and not "feed the mirror":
- The raw side has no value node for such a tag: AddressSpaceApplier
  materialises an alarm tag as a condition OR a value variable, never both.
  There is no raw value for the UNS mirror to mirror.
- DriverHostActor skips alarm tags when it builds the value fan-out and write
  routing maps (`continue` before the UNS registration), and the driver leaves
  them out of its value subscription ("subscribed to 5 refs" with 6 tags in
  G6). Feeding the mirror would mean subscribing a value the design says the
  tag does not have.
- Docs already state condition-only: ScriptedAlarms.md ("instead of a value
  variable"), AlarmTracking.md ("only the condition, with no sibling value
  variable"), the v3 design (native alarm = one condition at the raw tag,
  surfaced at equipment via notifiers).
- The composer tests that asserted the mirror were incidental: f4f3e17e
  (v3 B4-WP1) put the alarm on the fixture's Speed tag to test raw alarm
  attachment, and later tests reused Speed for writable / historian / array
  checks of the mirror. No commit or doc chose a value mirror for alarm tags.
- ScadaBridge does not read it: its OtOpcUa alarm path is event subscriptions
  on the equipment/raw folders (v3 alarm B/C live gate), and a node that never
  had a value cannot be a working binding. G6 itself authored the alarm's
  Boolean as a separate value tag (TestAlarm002), which is the supported way to
  read it.

Tests: the composer fixture moves the alarm onto its own HighTemp tag
(Speed is now a plain historized value tag), with a new test asserting no UNS
Variable for the alarm reference, with positive controls (the raw tag still
carries the equipment path; the value references still emit). New real-SDK
test Alarm_bearing_reference_surfaces_as_the_condition_only_against_real_SDK:
no Variable at the UNS path, the Speed mirror present, one condition, the
equipment folder wired as its notifier. Both new tests fail with the skip
removed. Docs: Uns.md, ScriptedAlarms.md, G6 evidence note.

Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
This commit is contained in:
Joseph Doherty
2026-11-12 23:55:49 -05:00
parent d9b2381235
commit 09b373e4db
6 changed files with 147 additions and 14 deletions
@@ -237,9 +237,11 @@ cleanly with it.
never went active, and its ack would dial a reference the gateway refuses. Three unit tests were added to
`GalaxyDriverRawPathKeyingTests`. The main one fails with the fix reverted, which was checked by reverting
the fix and re-running it.
- **#896 (open).** The UNS mirror of an alarm-bearing raw tag gets a value Variable that stays
- **#896 (fixed after this run).** The UNS mirror of an alarm-bearing raw tag gets a value Variable that stays
`BadWaitingForInitialData` forever, against the documented "condition instead of value variable" contract.
It was not fixed here because the composer test fixtures assert that mirror.
Fixed afterwards: the composer no longer emits a UNS Variable for a reference to an alarm-bearing tag, so the
equipment shows only the condition (the `<- #896` Variable in the Step 1 browse is gone).
## Cleanup