fix(opcua): equipment-tag planner diff + folder-scoped NodeIds (review findings)

Two bundle-review fixes + idempotency coverage:
- CRITICAL: the planner ignored EquipmentTags, so an incremental deploy changing only
  equipment tags produced an empty plan and HandleRebuild short-circuited before
  materialising them. Add TagId to EquipmentTagPlan + Added/Removed/ChangedEquipmentTags
  to Phase7Plan (diffed by TagId, in IsEmpty, driving Apply's needsRebuild) — mirroring
  the GalaxyTags treatment.
- IMPORTANT: equipment variable NodeId was the raw driver FullName, which collides across
  identical machines (e.g. two PLCs both exposing register 40001) — the second variable
  was silently dropped. NodeId is now folder-scoped (parent/Name); FullName stays on
  EquipmentTagPlan for the later values-routing milestone.
- Task 4: SDK-backed idempotency test (double-apply -> single variable); restart-safety
  confirmed (RestoreApplied reuses the same RebuildAddressSpace -> HandleRebuild path).
- Minor: align composer equipment-tag sort with the artifact decoder (coalesce FolderPath).
This commit is contained in:
Joseph Doherty
2026-06-06 15:02:50 -04:00
parent 08cddfe128
commit aaf869145a
9 changed files with 192 additions and 28 deletions
@@ -167,6 +167,7 @@ public sealed class DeploymentArtifactTests
var c = DeploymentArtifact.ParseComposition(blob);
var tag = c.EquipmentTags.ShouldHaveSingleItem();
tag.TagId.ShouldBe("tag-eq");
tag.EquipmentId.ShouldBe("eq-1");
tag.DriverInstanceId.ShouldBe("drv-modbus");
tag.Name.ShouldBe("Speed");