fix(virtualtags): a disabled VirtualTag keeps its node and reads BadOutOfService (lmxopcua#787, owner decision)
v2-ci / unit-tests (push) Has been cancelled

Revises 963b0d66, which dropped a disabled VirtualTag from the runtime plan so a
bound client got BadNodeIdUnknown. Now the plan carries Enabled (part of value
equality): AddressSpaceComposer.Compose and DeploymentArtifact.BuildEquipmentVirtualTagPlans
keep the row with Enabled=false (byte-parity), the applier materialises the node as
normal, and VirtualTagHostActor spawns no VirtualTagActor for it but publishes
BadOutOfService (new OpcUaStatus constant) with a null value stamped at deploy, on
every apply. Enabled flips are node-irrelevant to the change classifier; enabled->disabled
stops the child, disabled->enabled resumes evaluation. Validator exemption and name
uniqueness unchanged. Scripted alarms keep their not-materialised convention.
Tests updated; new wire test DisabledVirtualTagWireTests. docs/VirtualTags.md updated.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-11-10 04:48:56 -05:00
parent 8582ce91bc
commit f201f16fd4
10 changed files with 238 additions and 30 deletions
@@ -53,6 +53,11 @@ public static class OpcUaStatus
/// ScadaBridge, can tell a sick node from a broken script. Only produced under <c>Scripting:Runner=OutOfProcess</c>.</summary>
public const uint BadResourceUnavailable = 0x80040000;
/// <summary>The item was deliberately taken out of service. The status a disabled VirtualTag
/// (<c>VirtualTag.Enabled = false</c>) publishes, with a null value, on its still-present node
/// (lmxopcua#787) — distinct from <see cref="BadInternalError"/>, which means the tag's own script failed.</summary>
public const uint BadOutOfService = 0x808D0000;
/// <summary>Part 4 severity bucket of <paramref name="statusCode"/>: the top two bits.</summary>
/// <param name="statusCode">The status code to classify.</param>
/// <returns>0 for Good, 1 for Uncertain, 2 or 3 for Bad.</returns>