diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredAddressSpaceSink.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredAddressSpaceSink.cs
index ab7d208c..8f714a31 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredAddressSpaceSink.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredAddressSpaceSink.cs
@@ -73,7 +73,7 @@ public sealed class DeferredAddressSpaceSink : IOpcUaAddressSpaceSink, ISurgical
/// Forwards an in-place tag-attribute update (F10b) to the inner sink when it supports the
/// surgical capability. Returns false otherwise — before the real SdkAddressSpaceSink is
/// swapped in (inner is still the null sink), or any inner sink that isn't surgical — so the caller
- /// (Phase7Applier) falls back to a full rebuild. Without this forward the surgical optimization is
+ /// (AddressSpaceApplier) falls back to a full rebuild. Without this forward the surgical optimization is
/// inert on every driver-role host, because actors inject THIS wrapper, not the inner sink.
/// The node ID of the variable to update in place.
/// Whether the node should be read/write.
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/EquipmentNodeIds.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/EquipmentNodeIds.cs
index f6e1c724..48942008 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/EquipmentNodeIds.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/EquipmentNodeIds.cs
@@ -4,7 +4,7 @@ namespace ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
/// Single source of truth for equipment-namespace OPC UA NodeId strings. The variable NodeId is
/// FOLDER-SCOPED ({parent}/{Name}), NOT the driver-side FullName — a driver wire ref is not
/// unique across identical machines, so FullName-as-NodeId would collide in the sink. Used by the
-/// materialiser (Phase7Applier), the VirtualTag publish map, and the driver live-value router so all
+/// materialiser (AddressSpaceApplier), the VirtualTag publish map, and the driver live-value router so all
/// three agree on the exact NodeId a variable was placed at.
///
public static class EquipmentNodeIds
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/IOpcUaAddressSpaceSink.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/IOpcUaAddressSpaceSink.cs
index 237c5eeb..a7a1dd9a 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/IOpcUaAddressSpaceSink.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/IOpcUaAddressSpaceSink.cs
@@ -31,7 +31,7 @@ public interface IOpcUaAddressSpaceSink
/// Materialise a real OPC UA Part 9 alarm-condition node under its equipment folder so clients
/// can browse it as a proper condition (with basic Active/Ack state). The node id equals the
/// alarm node id (the ScriptedAlarmId) so subsequent calls update
- /// it. Used by Phase7Applier.MaterialiseScriptedAlarms. Idempotent.
+ /// it. Used by AddressSpaceApplier.MaterialiseScriptedAlarms. Idempotent.
///
/// The alarm node ID (== ScriptedAlarmId); becomes the condition's NodeId.
/// The equipment folder node ID the condition parents under.
@@ -44,7 +44,7 @@ public interface IOpcUaAddressSpaceSink
void MaterialiseAlarmCondition(string alarmNodeId, string equipmentNodeId, string displayName, string alarmType, int severity, bool isNative = false);
///
- /// Ensure a folder node exists under the given parent. Used by Phase7Applier to
+ /// Ensure a folder node exists under the given parent. Used by AddressSpaceApplier to
/// materialise the UNS Area/Line/Equipment hierarchy in the address space. When
/// is null the folder is parented under the namespace
/// root. Idempotent: calling twice with the same id is safe.
@@ -58,7 +58,7 @@ public interface IOpcUaAddressSpaceSink
/// Ensure a Variable node exists at , parented under
/// (or the namespace root when null). Created with
/// Bad quality + null value; subsequent calls update both.
- /// Used by Phase7Applier to materialise equipment-namespace tags ahead of any
+ /// Used by AddressSpaceApplier to materialise equipment-namespace tags ahead of any
/// driver-side subscribe so OPC UA clients can browse them. Idempotent.
///
/// The OPC UA node ID for the variable.
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/ISurgicalAddressSpaceSink.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/ISurgicalAddressSpaceSink.cs
index 98e11aa5..6a6f5592 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/ISurgicalAddressSpaceSink.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/ISurgicalAddressSpaceSink.cs
@@ -1,7 +1,7 @@
namespace ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
/// Optional capability on an address-space sink: surgical in-place attribute updates on an
-/// EXISTING variable node, used by Phase7Applier to avoid a full RebuildAddressSpace for pure-property
+/// EXISTING variable node, used by AddressSpaceApplier to avoid a full RebuildAddressSpace for pure-property
/// tag changes (Writable / Historizing). A sink that does not implement it ⇒ caller falls back to a
/// full rebuild (safe default).
public interface ISurgicalAddressSpaceSink
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/EquipmentScriptPaths.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/EquipmentScriptPaths.cs
index 4c9e95ce..e0cd6f2d 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/EquipmentScriptPaths.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/EquipmentScriptPaths.cs
@@ -88,7 +88,7 @@ public static class EquipmentScriptPaths
///
/// Distinct ctx.GetTag("ref") string literals in first-seen order — the
/// dependency refs the VirtualTagActor subscribes to. The single shared copy
- /// formerly duplicated in Phase7Composer + DeploymentArtifact. GetTag
+ /// formerly duplicated in AddressSpaceComposer + DeploymentArtifact. GetTag
/// only (writes are not dependencies).
///
/// The (already substituted) script source.
@@ -112,7 +112,7 @@ public static class EquipmentScriptPaths
/// UNION the distinct {TagPath} token paths referenced in the message template (first-seen
/// order, appended after the predicate reads, trimmed + non-empty). The reserved
/// {{equip}} double-brace form is excluded by the token regex. Deterministic so the live
- /// composer (Phase7Composer) and the artifact-decode mirror (DeploymentArtifact)
+ /// composer (AddressSpaceComposer) and the artifact-decode mirror (DeploymentArtifact)
/// produce the exact same ordered list — the byte-parity contract EquipmentScriptedAlarmPlan
/// equality depends on. Scripted alarms do NOT use {{equip}} substitution (only virtual
/// tags do) — pass the predicate source as-is.
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs
index 6d1432ad..76bdb3f3 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs
@@ -54,7 +54,7 @@ public static class DraftValidator
}
// Minimal reader for the top-level "FullName" string in a tag's schemaless TagConfig JSON
- // (mirrors Phase7Composer.ExtractTagFullName — a small local copy, consistent with this codebase
+ // (mirrors AddressSpaceComposer.ExtractTagFullName — a small local copy, consistent with this codebase
// where the composer keeps its own).
private static string? ExtractTagConfigFullName(string? tagConfig)
{
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Uns/TagModal.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Uns/TagModal.razor
index 0f11fb91..2cd5c3b9 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Uns/TagModal.razor
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Uns/TagModal.razor
@@ -139,7 +139,7 @@
@* Driver-agnostic server-side HistoryRead intent. Distinct from the native-alarm
"Historize to AVEVA" toggle below: THIS gates TAG-VALUE history (root keys
- `isHistorized` / `historianTagname`, read by Phase7Composer.ExtractTagHistorize),
+ `isHistorized` / `historianTagname`, read by AddressSpaceComposer.ExtractTagHistorize),
merged onto the canonical TagConfig via the pure TagHistorizeConfig seam so it
composes with the typed editor's driver-specific fields (both preserve unknown keys).
Shown for EVERY driver once one is picked. *@
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/IScriptTagCatalog.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/IScriptTagCatalog.cs
index 2652fb9c..810febe3 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/IScriptTagCatalog.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/IScriptTagCatalog.cs
@@ -41,15 +41,15 @@ public sealed record ScriptTagInfo(string Path, string Kind, string DataType, st
///
/// Fidelity over breadth. Verified: the live runtime resolves a ctx.GetTag("X")
/// literal against the driver FullName — the resolution chain is
-/// Phase7Composer (via EquipmentScriptPaths.ExtractDependencyRefs) harvesting the ctx.GetTag("…") literals
+/// AddressSpaceComposer (via EquipmentScriptPaths.ExtractDependencyRefs) harvesting the ctx.GetTag("…") literals
/// into EquipmentVirtualTagPlan.DependencyRefs
-/// (src/Server/…OpcUaServer/Phase7Composer.cs); those become
+/// (src/Server/…OpcUaServer/AddressSpaceComposer.cs); those become
/// VirtualTagActor._dependencyRefs, registered with the
/// DependencyMuxActor, whose _byRef map is keyed by
/// DriverInstanceActor.AttributeValuePublished.FullReference
/// (src/Server/…Runtime/VirtualTags/DependencyMuxActor.cs:97) — and that
/// FullReference is the FullName field extracted from Tag.TagConfig
-/// (see Phase7Composer.ExtractTagFullName + EquipmentNodeWalker.ExtractFullName).
+/// (see AddressSpaceComposer.ExtractTagFullName + EquipmentNodeWalker.ExtractFullName).
/// The UNS-path engine (Core.VirtualTags.VirtualTagEngine, keyed by a slash-joined
/// Enterprise/Site/Area/Line/Equipment/TagName) is dormant — it is NOT wired into the
/// host — so UNS browse paths never resolve at runtime and are intentionally NOT suggested.
@@ -175,7 +175,7 @@ public sealed class ScriptTagCatalog(IDbContextFactory d
///
/// Extracts the driver-side full reference from a Tag.TagConfig JSON blob — the
/// top-level FullName string every shipped driver stores. Mirrors
- /// EquipmentNodeWalker.ExtractFullName / Phase7Composer.ExtractTagFullName
+ /// EquipmentNodeWalker.ExtractFullName / AddressSpaceComposer.ExtractTagFullName
/// (AdminUI does not reference those assemblies). Falls back to the raw blob when it is not
/// a JSON object carrying a string FullName.
///
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/ScriptAnalysisService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/ScriptAnalysisService.cs
index 32cf54aa..bff62966 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/ScriptAnalysisService.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/ScriptAnalysisService.cs
@@ -223,7 +223,7 @@ public sealed class ScriptAnalysisService
if (inv.Expression is not MemberAccessExpressionSyntax ma) return false;
// Receiver guard: only ctx.GetTag(...) / ctx.SetVirtualTag(...) are real tag-path calls. Mirrors the
// runtime harvest (EquipmentScriptPaths.GetTagRefRegex is syntactically `ctx`-anchored), so the editor
- // offers tag completions/hover for exactly what Phase7Composer harvests — not an unrelated x.GetTag(...).
+ // offers tag completions/hover for exactly what AddressSpaceComposer harvests — not an unrelated x.GetTag(...).
if (ma.Expression is not IdentifierNameSyntax { Identifier.ValueText: "ctx" }) return false;
var method = ma.Name.Identifier.ValueText;
if (method is not ("GetTag" or "SetVirtualTag")) return false;
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/HistorianWonderwareTagConfigModel.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/HistorianWonderwareTagConfigModel.cs
index 765061b6..f80065bb 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/HistorianWonderwareTagConfigModel.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/HistorianWonderwareTagConfigModel.cs
@@ -7,7 +7,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;
/// the driver reads against). Preserves unrecognised JSON keys across a load→save.
///
/// The FullName key is intentionally PascalCase: the deploy-time composer + node walker
-/// (Phase7Composer.ExtractTagFullName, EquipmentNodeWalker) read it via a
+/// (AddressSpaceComposer.ExtractTagFullName, EquipmentNodeWalker) read it via a
/// case-sensitive TryGetProperty("FullName", …), so the editor MUST persist that exact
/// casing. The driver-agnostic server-side HistoryRead intent keys (isHistorized /
/// historianTagname) are NOT modelled here — they are owned by the TagModal-merge seam
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/NativeAlarmModel.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/NativeAlarmModel.cs
index 0ab3a68e..864581c5 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/NativeAlarmModel.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/NativeAlarmModel.cs
@@ -6,7 +6,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;
/// Typed working model for the optional native-alarm alarm sub-object inside a tag's
/// TagConfig JSON. A tag whose TagConfig carries an alarm object is materialised
/// as an OPC UA Part 9 condition (rather than a value variable); the fields here mirror what the
-/// server's Phase7Composer.ExtractTagAlarm / DeploymentArtifact.ExtractTagAlarm parse.
+/// server's AddressSpaceComposer.ExtractTagAlarm / DeploymentArtifact.ExtractTagAlarm parse.
///
///
/// is the per-condition opt-out of the DURABLE AVEVA historian write
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/OpcUaClientTagConfigModel.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/OpcUaClientTagConfigModel.cs
index c072d731..7066e7ad 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/OpcUaClientTagConfigModel.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/OpcUaClientTagConfigModel.cs
@@ -8,7 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;
/// Preserves unrecognised JSON keys across a load→save.
///
/// The FullName key is intentionally PascalCase: the deploy-time composer + node walker
-/// (Phase7Composer.ExtractTagFullName, EquipmentNodeWalker) read it via a
+/// (AddressSpaceComposer.ExtractTagFullName, EquipmentNodeWalker) read it via a
/// case-sensitive TryGetProperty("FullName", …), so the editor MUST persist that exact
/// casing. The driver-agnostic server-side HistoryRead intent keys (isHistorized /
/// historianTagname) are NOT modelled here — they are owned by the TagModal-merge seam
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/TagHistorizeConfig.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/TagHistorizeConfig.cs
index 586a44fd..9935e679 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/TagHistorizeConfig.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/TagEditors/TagHistorizeConfig.cs
@@ -4,7 +4,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;
/// Pure, driver-agnostic merge helper for the two server-side HistoryRead intent keys at the ROOT of a
/// tag's TagConfig JSON: isHistorized (camelCase bool — omit/false default) and
/// historianTagname (camelCase string override — omit when blank). These map to what the server's
-/// Phase7Composer.ExtractTagHistorize reads (see docs/Historian.md).
+/// AddressSpaceComposer.ExtractTagHistorize reads (see docs/Historian.md).
///
///
/// This is the TagModal-merge seam: the TagModal owns the canonical TagConfig JSON; the driver's typed
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Applier.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceApplier.cs
similarity index 89%
rename from src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Applier.cs
rename to src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceApplier.cs
index 4d405233..17afaedf 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Applier.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceApplier.cs
@@ -4,9 +4,9 @@ using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
///
-/// Side-effecting orchestrator over . Drives an
+/// Side-effecting orchestrator over . Drives an
/// to materialise the diff between two
-/// snapshots:
+/// snapshots:
///
///
/// - RemovedEquipment / RemovedAlarms — write Bad-quality on every removed
@@ -23,15 +23,15 @@ namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
/// production binds a real SDK sink, dev/Mac binds ,
/// and tests can capture every call.
///
-public sealed class Phase7Applier
+public sealed class AddressSpaceApplier
{
private readonly IOpcUaAddressSpaceSink _sink;
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
- /// Initializes a new instance of the Phase7Applier class.
+ /// Initializes a new instance of the AddressSpaceApplier class.
/// The OPC UA address space sink to apply changes to.
/// The logger instance.
- public Phase7Applier(IOpcUaAddressSpaceSink sink, ILogger logger)
+ public AddressSpaceApplier(IOpcUaAddressSpaceSink sink, ILogger logger)
{
ArgumentNullException.ThrowIfNull(sink);
ArgumentNullException.ThrowIfNull(logger);
@@ -44,15 +44,15 @@ public sealed class Phase7Applier
/// callers (OpcUaPublishActor) can correlate the work back to the originating deployment.
///
/// The plan to apply.
- /// A Phase7ApplyOutcome summarizing the applied changes.
- public Phase7ApplyOutcome Apply(Phase7Plan plan)
+ /// A AddressSpaceApplyOutcome summarizing the applied changes.
+ public AddressSpaceApplyOutcome Apply(AddressSpacePlan plan)
{
ArgumentNullException.ThrowIfNull(plan);
if (plan.IsEmpty)
{
- _logger.LogDebug("Phase7Applier: plan is empty; skipping sink writes");
- return new Phase7ApplyOutcome(RemovedNodes: 0, AddedNodes: 0, ChangedNodes: 0, RebuildCalled: false);
+ _logger.LogDebug("AddressSpaceApplier: plan is empty; skipping sink writes");
+ return new AddressSpaceApplyOutcome(RemovedNodes: 0, AddedNodes: 0, ChangedNodes: 0, RebuildCalled: false);
}
var ts = DateTime.UtcNow;
@@ -68,7 +68,7 @@ public sealed class Phase7Applier
removedCount++;
}
// Removed equipment tags / VirtualTags are plain variable nodes (no Part 9 condition to write
- // before tear-down), but they ARE real removals — count them so Phase7ApplyOutcome.RemovedNodes
+ // before tear-down), but they ARE real removals — count them so AddressSpaceApplyOutcome.RemovedNodes
// is accurate on a removed-tag-only deploy, which now reaches the rebuild path below.
removedCount += plan.RemovedEquipmentTags.Count + plan.RemovedEquipmentVirtualTags.Count;
@@ -136,7 +136,7 @@ public sealed class Phase7Applier
try { ok = surgical.UpdateTagAttributes(nodeId, writable, historian); }
catch (Exception ex)
{
- _logger.LogError(ex, "Phase7Applier: surgical UpdateTagAttributes threw for {Node}", nodeId);
+ _logger.LogError(ex, "AddressSpaceApplier: surgical UpdateTagAttributes threw for {Node}", nodeId);
ok = false;
}
if (!ok) { allApplied = false; break; }
@@ -152,10 +152,10 @@ public sealed class Phase7Applier
}
_logger.LogInformation(
- "Phase7Applier: applied plan (added={Added}, removed={Removed}, changed={Changed}, surgicalTags={Surgical}, rebuild={Rebuild})",
+ "AddressSpaceApplier: applied plan (added={Added}, removed={Removed}, changed={Changed}, surgicalTags={Surgical}, rebuild={Rebuild})",
addedCount, removedCount, changedCount, rebuilt ? 0 : surgicalTagDeltas.Count, rebuilt);
- return new Phase7ApplyOutcome(removedCount, addedCount, changedCount, rebuilt);
+ return new AddressSpaceApplyOutcome(removedCount, addedCount, changedCount, rebuilt);
}
private void SafeRebuild()
@@ -166,7 +166,7 @@ public sealed class Phase7Applier
}
catch (Exception ex)
{
- _logger.LogError(ex, "Phase7Applier: sink.RebuildAddressSpace threw");
+ _logger.LogError(ex, "AddressSpaceApplier: sink.RebuildAddressSpace threw");
}
}
@@ -178,7 +178,7 @@ public sealed class Phase7Applier
/// present, so re-applies are cheap.
///
/// The composition result containing the hierarchy to materialise.
- public void MaterialiseHierarchy(Phase7CompositionResult composition)
+ public void MaterialiseHierarchy(AddressSpaceComposition composition)
{
ArgumentNullException.ThrowIfNull(composition);
@@ -198,7 +198,7 @@ public sealed class Phase7Applier
}
_logger.LogInformation(
- "Phase7Applier: hierarchy materialised (areas={Areas}, lines={Lines}, equipment={Equipment})",
+ "AddressSpaceApplier: hierarchy materialised (areas={Areas}, lines={Lines}, equipment={Equipment})",
composition.UnsAreas.Count, composition.UnsLines.Count, composition.EquipmentNodes.Count);
}
@@ -223,7 +223,7 @@ public sealed class Phase7Applier
///
///
/// The composition result containing the equipment tags to materialise.
- public void MaterialiseEquipmentTags(Phase7CompositionResult composition)
+ public void MaterialiseEquipmentTags(AddressSpaceComposition composition)
{
ArgumentNullException.ThrowIfNull(composition);
if (composition.EquipmentTags.Count == 0) return;
@@ -276,7 +276,7 @@ public sealed class Phase7Applier
}
_logger.LogInformation(
- "Phase7Applier: equipment tags materialised (tags={Tags}, equipment={Equipment})",
+ "AddressSpaceApplier: equipment tags materialised (tags={Tags}, equipment={Equipment})",
composition.EquipmentTags.Count,
composition.EquipmentTags.Select(t => t.EquipmentId).Distinct(StringComparer.Ordinal).Count());
}
@@ -294,7 +294,7 @@ public sealed class Phase7Applier
/// Idempotent (per-variable idempotency relies on the sink's own EnsureVariable).
///
/// The composition result containing the equipment VirtualTags to materialise.
- public void MaterialiseEquipmentVirtualTags(Phase7CompositionResult composition)
+ public void MaterialiseEquipmentVirtualTags(AddressSpaceComposition composition)
{
ArgumentNullException.ThrowIfNull(composition);
if (composition.EquipmentVirtualTags.Count == 0) return;
@@ -328,7 +328,7 @@ public sealed class Phase7Applier
}
_logger.LogInformation(
- "Phase7Applier: equipment virtualtags materialised (vtags={Vtags}, equipment={Equipment})",
+ "AddressSpaceApplier: equipment virtualtags materialised (vtags={Vtags}, equipment={Equipment})",
composition.EquipmentVirtualTags.Count,
composition.EquipmentVirtualTags.Select(v => v.EquipmentId).Distinct(StringComparer.Ordinal).Count());
}
@@ -343,7 +343,7 @@ public sealed class Phase7Applier
/// MaterialiseAlarmCondition re-creates cleanly on re-apply).
///
/// The composition result containing the scripted alarms to materialise.
- public void MaterialiseScriptedAlarms(Phase7CompositionResult composition)
+ public void MaterialiseScriptedAlarms(AddressSpaceComposition composition)
{
ArgumentNullException.ThrowIfNull(composition);
if (composition.EquipmentScriptedAlarms.Count == 0) return;
@@ -357,7 +357,7 @@ public sealed class Phase7Applier
}
_logger.LogInformation(
- "Phase7Applier: scripted alarms materialised (alarms={Alarms}, equipment={Equipment})",
+ "AddressSpaceApplier: scripted alarms materialised (alarms={Alarms}, equipment={Equipment})",
materialised,
composition.EquipmentScriptedAlarms.Where(a => a.Enabled)
.Select(a => a.EquipmentId).Distinct(StringComparer.Ordinal).Count());
@@ -366,13 +366,13 @@ public sealed class Phase7Applier
private void SafeEnsureFolder(string nodeId, string? parentNodeId, string displayName)
{
try { _sink.EnsureFolder(nodeId, parentNodeId, displayName); }
- catch (Exception ex) { _logger.LogWarning(ex, "Phase7Applier: EnsureFolder threw for {Node}", nodeId); }
+ catch (Exception ex) { _logger.LogWarning(ex, "AddressSpaceApplier: EnsureFolder threw for {Node}", nodeId); }
}
private void SafeEnsureVariable(string nodeId, string? parentNodeId, string displayName, string dataType, bool writable, string? historianTagname = null, bool isArray = false, uint? arrayLength = null)
{
try { _sink.EnsureVariable(nodeId, parentNodeId, displayName, dataType, writable, historianTagname, isArray, arrayLength); }
- catch (Exception ex) { _logger.LogWarning(ex, "Phase7Applier: EnsureVariable threw for {Node}", nodeId); }
+ catch (Exception ex) { _logger.LogWarning(ex, "AddressSpaceApplier: EnsureVariable threw for {Node}", nodeId); }
}
// A VirtualTag's materialised OPC UA node (MaterialiseEquipmentVirtualTags) is derived ONLY from
@@ -381,7 +381,7 @@ public sealed class Phase7Applier
// so a delta changing ONLY those three leaves a byte-identical node and needs no address-space rebuild.
// Whitelist-of-may-differ via `with` + the record's custom Equals: any OTHER field difference (current
// or future) makes the override unequal → falls back to a full rebuild (safe default).
- private static bool VtagDeltaIsNodeIrrelevant(Phase7Plan.EquipmentVirtualTagDelta d) =>
+ private static bool VtagDeltaIsNodeIrrelevant(AddressSpacePlan.EquipmentVirtualTagDelta d) =>
(d.Previous with
{
Expression = d.Current.Expression,
@@ -394,7 +394,7 @@ public sealed class Phase7Applier
// ISurgicalAddressSpaceSink.UpdateTagAttributes, avoiding a full rebuild (preserving subscriptions).
// DataType / IsArray / ArrayLength / FullName / DriverInstanceId / identity / alarm differences fall
// through to a rebuild — the override-unequal default also covers any future field.
- private static bool TagDeltaIsSurgicalEligible(Phase7Plan.EquipmentTagDelta d) =>
+ private static bool TagDeltaIsSurgicalEligible(AddressSpacePlan.EquipmentTagDelta d) =>
d.Previous.Alarm is null && d.Current.Alarm is null &&
(d.Previous with
{
@@ -418,18 +418,18 @@ public sealed class Phase7Applier
private void SafeWriteAlarmCondition(string nodeId, AlarmConditionSnapshot state, DateTime ts)
{
try { _sink.WriteAlarmCondition(nodeId, state, ts); }
- catch (Exception ex) { _logger.LogWarning(ex, "Phase7Applier: WriteAlarmCondition threw for {Node}", nodeId); }
+ catch (Exception ex) { _logger.LogWarning(ex, "AddressSpaceApplier: WriteAlarmCondition threw for {Node}", nodeId); }
}
private void SafeMaterialiseAlarmCondition(string alarmNodeId, string equipmentNodeId, string displayName, string alarmType, int severity, bool isNative)
{
try { _sink.MaterialiseAlarmCondition(alarmNodeId, equipmentNodeId, displayName, alarmType, severity, isNative); }
- catch (Exception ex) { _logger.LogWarning(ex, "Phase7Applier: MaterialiseAlarmCondition threw for {Node}", alarmNodeId); }
+ catch (Exception ex) { _logger.LogWarning(ex, "AddressSpaceApplier: MaterialiseAlarmCondition threw for {Node}", alarmNodeId); }
}
}
/// Summary of one apply pass. Useful for tests + audit-log entries on the deploy path.
-public sealed record Phase7ApplyOutcome(
+public sealed record AddressSpaceApplyOutcome(
int RemovedNodes,
int AddedNodes,
int ChangedNodes,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Composer.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceComposer.cs
similarity index 97%
rename from src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Composer.cs
rename to src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceComposer.cs
index 535d0ae4..27cfbfff 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Composer.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpaceComposer.cs
@@ -6,11 +6,11 @@ using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
-/// Outcome of — pure value tuple, no side effects.
+/// Outcome of — pure value tuple, no side effects.
/// + carry the UNS topology so the applier can
/// materialise the Area/Line/Equipment folder hierarchy in the address space; equipment carries
/// its parent line id so the applier knows where to hang each equipment folder.
-public sealed record Phase7CompositionResult(
+public sealed record AddressSpaceComposition(
IReadOnlyList UnsAreas,
IReadOnlyList UnsLines,
IReadOnlyList EquipmentNodes,
@@ -21,7 +21,7 @@ public sealed record Phase7CompositionResult(
/// The equipment nodes.
/// The driver instance plans.
/// The scripted alarm plans.
- public Phase7CompositionResult(
+ public AddressSpaceComposition(
IReadOnlyList equipmentNodes,
IReadOnlyList driverInstancePlans,
IReadOnlyList scriptedAlarmPlans)
@@ -32,7 +32,7 @@ public sealed record Phase7CompositionResult(
///
/// Equipment-namespace tags — a with non-null
- /// in an Equipment-kind namespace. Phase7Applier.MaterialiseEquipmentTags
+ /// in an Equipment-kind namespace. AddressSpaceApplier.MaterialiseEquipmentTags
/// materialises each as a Variable under its existing equipment folder. Declared as an
/// init-only member defaulting to empty (rather than a positional parameter) so every existing
/// convenience constructor + call site keeps compiling unchanged; new producers set it via
@@ -66,7 +66,7 @@ public sealed record ScriptedAlarmPlan(string ScriptedAlarmId, string EquipmentI
/// One Equipment-namespace tag from a row whose
/// is non-null and whose owning driver's namespace is Equipment-kind. Carries the stable
/// (diff identity), the parent folder (already
-/// materialised by Phase7Applier.MaterialiseHierarchy) the variable hangs under, the
+/// materialised by AddressSpaceApplier.MaterialiseHierarchy) the variable hangs under, the
/// optional sub-folder, the leaf display, the OPC UA
/// , and the driver-side reference (extracted from
/// Tag.TagConfig) the later values milestone routes reads/writes by. The variable's NodeId
@@ -117,7 +117,7 @@ public sealed record EquipmentTagAlarmInfo(string AlarmType, int Severity, bool?
///
/// One Equipment-namespace VirtualTag from a row (joined to its
/// for the expression). The VirtualTag value analogue of
-/// : Phase7Applier.MaterialiseEquipmentVirtualTags
+/// : AddressSpaceApplier.MaterialiseEquipmentVirtualTags
/// materialises each as a Variable under its equipment folder with a folder-scoped NodeId
/// (EquipmentId/Name, or EquipmentId/FolderPath/Name when a sub-folder is set),
/// and VirtualTagHostActor spawns a VirtualTagActor per plan that evaluates
@@ -252,19 +252,19 @@ public sealed record EquipmentScriptedAlarmPlan(
/// startup (Task 53) consumes the result and hands it to the node-manager factory.
///
/// #85 — the composer now carries UNS topology ( +
-/// ) so Phase7Applier can build the
+/// ) so AddressSpaceApplier can build the
/// Area/Line/Equipment folder hierarchy in the SDK's address space. The legacy
/// EquipmentNodeWalker integration that did this server-side is fully replaced by the
/// (composer → applier → sink → node manager) chain.
///
-public static class Phase7Composer
+public static class AddressSpaceComposer
{
/// Convenience overload for legacy callers + tests that don't supply UNS topology or tags.
/// The equipment.
/// The driver instances.
/// The scripted alarms.
/// The composition result.
- public static Phase7CompositionResult Compose(
+ public static AddressSpaceComposition Compose(
IReadOnlyList equipment,
IReadOnlyList driverInstances,
IReadOnlyList scriptedAlarms) =>
@@ -278,7 +278,7 @@ public static class Phase7Composer
/// The driver instances.
/// The scripted alarms.
/// The composition result.
- public static Phase7CompositionResult Compose(
+ public static AddressSpaceComposition Compose(
IReadOnlyList unsAreas,
IReadOnlyList unsLines,
IReadOnlyList equipment,
@@ -300,7 +300,7 @@ public static class Phase7Composer
/// The Equipment-namespace virtual (calculated) tags. null = none.
/// The scripts joined to by ScriptId for the expression. null = none.
/// The composition result.
- public static Phase7CompositionResult Compose(
+ public static AddressSpaceComposition Compose(
IReadOnlyList unsAreas,
IReadOnlyList unsLines,
IReadOnlyList equipment,
@@ -434,7 +434,7 @@ public static class Phase7Composer
if (!scriptsById.TryGetValue(a.PredicateScriptId, out var s))
{
Trace.TraceWarning(
- "Phase7Composer: scripted alarm '{0}' (equipment '{1}') references predicate " +
+ "AddressSpaceComposer: scripted alarm '{0}' (equipment '{1}') references predicate " +
"script '{2}' which is not in the supplied scripts — skipping.",
a.ScriptedAlarmId, a.EquipmentId, a.PredicateScriptId);
continue;
@@ -458,7 +458,7 @@ public static class Phase7Composer
Enabled: a.Enabled));
}
- return new Phase7CompositionResult(areas, lines, nodes, plans, alarms)
+ return new AddressSpaceComposition(areas, lines, nodes, plans, alarms)
{
EquipmentTags = equipmentTags,
EquipmentVirtualTags = equipmentVirtualTags,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Plan.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpacePlan.cs
similarity index 88%
rename from src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Plan.cs
rename to src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpacePlan.cs
index 0641f75d..e5ecdade 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Plan.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/AddressSpacePlan.cs
@@ -1,7 +1,7 @@
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
///
-/// Pure diff between two snapshots — the
+/// Pure diff between two snapshots — the
/// previous currently-applied composition and the next from a freshly-applied
/// deployment. Three lists per entity class (Equipment / DriverInstance / ScriptedAlarm)
/// captured by stable identity: added items are new, removed items have to be torn down,
@@ -12,22 +12,22 @@ namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
/// nodes that actually changed — full tear-down + rebuild is reserved for first-boot or
/// drastic schema flips.
///
-public sealed record Phase7Plan(
+public sealed record AddressSpacePlan(
IReadOnlyList AddedEquipment,
IReadOnlyList RemovedEquipment,
- IReadOnlyList ChangedEquipment,
+ IReadOnlyList ChangedEquipment,
IReadOnlyList AddedDrivers,
IReadOnlyList RemovedDrivers,
- IReadOnlyList ChangedDrivers,
+ IReadOnlyList ChangedDrivers,
IReadOnlyList AddedAlarms,
IReadOnlyList RemovedAlarms,
- IReadOnlyList ChangedAlarms)
+ IReadOnlyList ChangedAlarms)
{
///
/// Equipment-namespace tag diff sets, keyed by . Added as
/// init-only members (defaulting empty) rather than positional parameters so existing
- /// Phase7Plan construction sites compile unchanged — consistent with how
- /// was added. Without these, an
+ /// AddressSpacePlan construction sites compile unchanged — consistent with how
+ /// was added. Without these, an
/// incremental deploy that changes ONLY equipment tags produced an empty plan and
/// OpcUaPublishActor.HandleRebuild short-circuited before materialising them.
///
@@ -67,7 +67,7 @@ public sealed record Phase7Plan(
public sealed record EquipmentVirtualTagDelta(EquipmentVirtualTagPlan Previous, EquipmentVirtualTagPlan Current);
}
-public static class Phase7Planner
+public static class AddressSpacePlanner
{
///
/// Diff two compositions, emitting Added/Removed/Changed sets per entity class.
@@ -77,7 +77,7 @@ public static class Phase7Planner
///
/// The previous composition result.
/// The new composition result.
- public static Phase7Plan Compute(Phase7CompositionResult previous, Phase7CompositionResult next)
+ public static AddressSpacePlan Compute(AddressSpaceComposition previous, AddressSpaceComposition next)
{
ArgumentNullException.ThrowIfNull(previous);
ArgumentNullException.ThrowIfNull(next);
@@ -85,22 +85,22 @@ public static class Phase7Planner
var (addedEq, removedEq, changedEq) = DiffById(
previous.EquipmentNodes, next.EquipmentNodes,
n => n.EquipmentId,
- (a, b) => new Phase7Plan.EquipmentDelta(a, b));
+ (a, b) => new AddressSpacePlan.EquipmentDelta(a, b));
var (addedDrv, removedDrv, changedDrv) = DiffById(
previous.DriverInstancePlans, next.DriverInstancePlans,
d => d.DriverInstanceId,
- (a, b) => new Phase7Plan.DriverDelta(a, b));
+ (a, b) => new AddressSpacePlan.DriverDelta(a, b));
var (addedAlarm, removedAlarm, changedAlarm) = DiffById(
previous.ScriptedAlarmPlans, next.ScriptedAlarmPlans,
a => a.ScriptedAlarmId,
- (a, b) => new Phase7Plan.AlarmDelta(a, b));
+ (a, b) => new AddressSpacePlan.AlarmDelta(a, b));
var (addedEqTags, removedEqTags, changedEqTags) = DiffById(
previous.EquipmentTags, next.EquipmentTags,
t => t.TagId,
- (a, b) => new Phase7Plan.EquipmentTagDelta(a, b));
+ (a, b) => new AddressSpacePlan.EquipmentTagDelta(a, b));
// VirtualTags diff by VirtualTagId, mirroring the EquipmentTags pass. EquipmentVirtualTagPlan
// overrides record equality to compare ALL fields by value — scalars (Expression/DataType/
@@ -110,9 +110,9 @@ public static class Phase7Planner
var (addedVTags, removedVTags, changedVTags) = DiffById(
previous.EquipmentVirtualTags, next.EquipmentVirtualTags,
t => t.VirtualTagId,
- (a, b) => new Phase7Plan.EquipmentVirtualTagDelta(a, b));
+ (a, b) => new AddressSpacePlan.EquipmentVirtualTagDelta(a, b));
- return new Phase7Plan(
+ return new AddressSpacePlan(
addedEq, removedEq, changedEq,
addedDrv, removedDrv, changedDrv,
addedAlarm, removedAlarm, changedAlarm)
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs
index ee503ef5..0acb5bea 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs
@@ -25,7 +25,7 @@ namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
///
/// Node-id encoding uses the manager's default namespace + the caller-supplied string id
/// as the identifier portion (e.g. "ns=2;s=eq-1/temp"). Equipment-folder hierarchy
-/// and OPC UA type metadata still come from the Phase7Applier / EquipmentNodeWalker
+/// and OPC UA type metadata still come from the AddressSpaceApplier / EquipmentNodeWalker
/// integration (F14b, tracked under #85) — this manager treats every id as a flat
/// under the namespace root.
///
@@ -1252,7 +1252,7 @@ public sealed class OtOpcUaNodeManager : CustomNodeManager2
///
/// Ensure a folder node exists at with the given display
/// name, parented under (or the namespace root when null).
- /// #85 — used by to materialise the UNS Area/Line/Equipment
+ /// #85 — used by to materialise the UNS Area/Line/Equipment
/// folder hierarchy. Idempotent: the second call with the same id returns the cached
/// folder so adding child variables under it still works.
///
@@ -1424,7 +1424,7 @@ public sealed class OtOpcUaNodeManager : CustomNodeManager2
_ => DataTypeIds.BaseDataType,
};
- /// Clear every registered variable + folder from the address space. Phase7Applier
+ /// Clear every registered variable + folder from the address space. AddressSpaceApplier
/// calls this when Equipment/Alarm topology changes; the populator then re-adds via
/// EnsureFolder + WriteValue on the next pass.
public void RebuildAddressSpace()
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DeploymentArtifact.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DeploymentArtifact.cs
index d0dc203c..6116dce7 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DeploymentArtifact.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DeploymentArtifact.cs
@@ -169,8 +169,8 @@ public static class DeploymentArtifact
}
///
- /// Parse the artifact into the projected used by
- /// Phase7Planner + Phase7Applier. Returns an empty composition for empty/
+ /// Parse the artifact into the projected used by
+ /// AddressSpacePlanner + AddressSpaceApplier. Returns an empty composition for empty/
/// malformed blobs so callers can treat parse failure as a no-op deploy.
///
/// The artifact JSON is produced by ConfigComposer.SnapshotAndFlattenAsync in the
@@ -179,7 +179,7 @@ public static class DeploymentArtifact
/// nodes.
///
/// The deployment artifact blob to parse.
- public static Phase7CompositionResult ParseComposition(ReadOnlySpan blob)
+ public static AddressSpaceComposition ParseComposition(ReadOnlySpan blob)
{
if (blob.IsEmpty) return Empty();
@@ -197,7 +197,7 @@ public static class DeploymentArtifact
var equipmentVirtualTags = BuildEquipmentVirtualTagPlans(root, equipmentTags);
var equipmentScriptedAlarms = BuildEquipmentScriptedAlarmPlans(root);
- return new Phase7CompositionResult(areas, lines, equipment, drivers, alarms)
+ return new AddressSpaceComposition(areas, lines, equipment, drivers, alarms)
{
EquipmentTags = equipmentTags,
EquipmentVirtualTags = equipmentVirtualTags,
@@ -224,7 +224,7 @@ public static class DeploymentArtifact
/// This node's identity in "host:port" form.
/// Optional diagnostic callback for cross-cluster orphan bindings; null disables the check.
/// The filtered composition per the node's scoping decision.
- public static Phase7CompositionResult ParseComposition(
+ public static AddressSpaceComposition ParseComposition(
ReadOnlySpan blob, string nodeId, Action? onInconsistency = null)
{
var scope = ResolveClusterScope(blob, nodeId);
@@ -253,7 +253,7 @@ public static class DeploymentArtifact
}
}
- return new Phase7CompositionResult(
+ return new AddressSpaceComposition(
full.UnsAreas.Where(a => sets.AreaIds.Contains(a.UnsAreaId)).ToArray(),
keptLines,
keptEquipment,
@@ -348,7 +348,7 @@ public static class DeploymentArtifact
}
}
- private static Phase7CompositionResult Empty() => new(
+ private static AddressSpaceComposition Empty() => new(
Array.Empty(),
Array.Empty(),
Array.Empty(),
@@ -359,7 +359,7 @@ public static class DeploymentArtifact
/// Cross-reference the artifact's Tags + Namespaces + DriverInstances arrays to find
/// Equipment-namespace tags (non-null EquipmentId, owning namespace Kind == Equipment), then
/// emit one per qualifying tag. The artifact-decode mirror of
- /// Phase7Composer.Compose's equipment filter — so the compose-side + artifact-decode
+ /// AddressSpaceComposer.Compose's equipment filter — so the compose-side + artifact-decode
/// plans agree on the same set of tags. FullName is read from each tag's TagConfig blob
/// (top-level "FullName" field).
///
@@ -421,7 +421,7 @@ public static class DeploymentArtifact
// AccessLevel → Writable. ConfigComposer serialises the TagAccessLevel enum WITHOUT a
// string converter, so it lands as a number (Read = 0, ReadWrite = 1); tolerate the string
// form ("ReadWrite") too — same defensive both-forms parse as the Kind gate above. MUST match
- // Phase7Composer's `AccessLevel == TagAccessLevel.ReadWrite` exactly (byte-parity). A missing
+ // AddressSpaceComposer's `AccessLevel == TagAccessLevel.ReadWrite` exactly (byte-parity). A missing
// field defaults to non-writable (read-only).
var writable = el.TryGetProperty("AccessLevel", out var alEl) && alEl.ValueKind switch
{
@@ -469,7 +469,7 @@ public static class DeploymentArtifact
///
/// Join the artifact's VirtualTags array to its Scripts array (by ScriptId) to emit one
/// per VirtualTag. The artifact-decode mirror of
- /// Phase7Composer.Compose's VirtualTag producer — so the compose-side + artifact-decode
+ /// AddressSpaceComposer.Compose's VirtualTag producer — so the compose-side + artifact-decode
/// plans agree. The reserved {{equip}} token in the joined Script's SourceCode is
/// substituted with the owning equipment's tag base (derived from '
/// FullNames) BEFORE refs are extracted, byte-parity with the composer. Expression = the
@@ -529,14 +529,14 @@ public static class DeploymentArtifact
// Historize: the artifact carries a Pascal-case "Historize" bool (ConfigComposer serialises
// the whole VirtualTag entity with DefaultIgnoreCondition.Never). Robust parse — default
// false; only honoured when the JSON value is an actual boolean — so absent/non-bool ⇒ false,
- // byte-parity with Phase7Composer's entity-default-false behaviour.
+ // byte-parity with AddressSpaceComposer's entity-default-false behaviour.
var historize = el.TryGetProperty("Historize", out var hEl)
&& (hEl.ValueKind == JsonValueKind.True || hEl.ValueKind == JsonValueKind.False)
&& hEl.GetBoolean();
// Substitute the {{equip}} token with the owning equipment's tag base BEFORE extracting
// refs, so both Expression and DependencyRefs are machine-specific — byte-parity with
- // Phase7Composer.Compose.
+ // AddressSpaceComposer.Compose.
var expanded = EquipmentScriptPaths.SubstituteEquipmentToken(
source, baseByEquip.GetValueOrDefault(equipmentId!));
@@ -562,7 +562,7 @@ public static class DeploymentArtifact
///
/// Join the artifact's ScriptedAlarms array to its Scripts array (by PredicateScriptId) to emit
/// one per alarm. The artifact-decode mirror of
- /// Phase7Composer.Compose's scripted-alarm producer — so the compose-side + artifact-decode
+ /// AddressSpaceComposer.Compose's scripted-alarm producer — so the compose-side + artifact-decode
/// plans agree byte-for-byte. An alarm whose PredicateScriptId has no matching Script row is
/// SKIPPED (matching the composer's skip behaviour) to preserve parity. PredicateSource = the
/// joined script source ("" when missing — but such alarms are skipped above); DependencyRefs
@@ -616,7 +616,7 @@ public static class DeploymentArtifact
if (string.IsNullOrWhiteSpace(scriptedAlarmId)) continue;
- // Skip alarms whose predicate script is missing — matching Phase7Composer's skip behaviour
+ // Skip alarms whose predicate script is missing — matching AddressSpaceComposer's skip behaviour
// so both sides emit the same set (byte-parity).
if (predicateScriptId is null || !scriptSourceById.TryGetValue(predicateScriptId, out var source))
continue;
@@ -646,7 +646,7 @@ public static class DeploymentArtifact
///
/// Extract the driver-side full reference from a tag's TagConfig JSON (top-level "FullName"
- /// field). The artifact-decode mirror of Phase7Composer.ExtractTagFullName /
+ /// field). The artifact-decode mirror of AddressSpaceComposer.ExtractTagFullName /
/// EquipmentNodeWalker.ExtractFullName — replicated because Runtime does not reference
/// the Core driver assembly. Falls back to the raw blob when absent or non-JSON.
///
@@ -669,7 +669,7 @@ public static class DeploymentArtifact
/// Parses the optional alarm object from a tag's TagConfig JSON. Returns null
/// when absent, non-object, or non-JSON (the tag is then a plain variable). Never throws. The
- /// live-edit side (Phase7Composer.ExtractTagAlarm) MUST parse identically (byte-parity).
+ /// live-edit side (AddressSpaceComposer.ExtractTagAlarm) MUST parse identically (byte-parity).
private static EquipmentTagAlarmInfo? ExtractTagAlarm(string? tagConfig)
{
if (string.IsNullOrWhiteSpace(tagConfig)) return null;
@@ -683,7 +683,7 @@ public static class DeploymentArtifact
var sev = a.TryGetProperty("severity", out var sEl) && sEl.ValueKind == JsonValueKind.Number
&& sEl.TryGetInt32(out var sv) ? sv : 500;
// historizeToAveva (bool?, absent ⇒ null ⇒ historize): byte-parity with
- // Phase7Composer.ExtractTagAlarm — only an explicit false suppresses the durable AVEVA write.
+ // AddressSpaceComposer.ExtractTagAlarm — only an explicit false suppresses the durable AVEVA write.
bool? historize = a.TryGetProperty("historizeToAveva", out var hEl)
&& hEl.ValueKind is JsonValueKind.True or JsonValueKind.False
? hEl.GetBoolean()
@@ -699,7 +699,7 @@ public static class DeploymentArtifact
/// whitespace-or-empty ⇒ null, meaning the historian tagname defaults to the tag's FullName,
/// resolved later). The raw string value is used — not trimmed — matching ExtractTagFullName /
/// ExtractTagAlarm. Never throws. The live-edit composer side
- /// (Phase7Composer.ExtractTagHistorize) MUST parse identically (byte-parity).
+ /// (AddressSpaceComposer.ExtractTagHistorize) MUST parse identically (byte-parity).
private static (bool IsHistorized, string? HistorianTagname) ExtractTagHistorize(string? tagConfig)
{
if (string.IsNullOrWhiteSpace(tagConfig)) return (false, null);
@@ -727,7 +727,7 @@ public static class DeploymentArtifact
/// arrayLength uint (honoured ONLY when isArray is true AND the prop is a JSON number
/// that fits uint; else null). Mirrors in structure +
/// null/blank/non-object/malformed-JSON tolerance. Never throws. The live-edit composer side
- /// (Phase7Composer.ExtractTagArray) MUST parse identically (byte-parity).
+ /// (AddressSpaceComposer.ExtractTagArray) MUST parse identically (byte-parity).
private static (bool IsArray, uint? ArrayLength) ExtractTagArray(string? tagConfig)
{
if (string.IsNullOrWhiteSpace(tagConfig)) return (false, null);
@@ -764,7 +764,7 @@ public static class DeploymentArtifact
var item = reader(el);
if (item is not null) result.Add(item);
}
- // Match Phase7Composer's natural-key sort so plan diffs are deterministic across
+ // Match AddressSpaceComposer's natural-key sort so plan diffs are deterministic across
// artifact-decode + composer-compose passes.
return result.OrderBy(IdentityOf, StringComparer.Ordinal).ToList();
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
index 9a4d8701..b708339e 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
@@ -939,7 +939,7 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
return;
}
- Phase7CompositionResult composition;
+ AddressSpaceComposition composition;
try
{
composition = DeploymentArtifact.ParseComposition(blob, _localNode.Value);
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
index cf18c778..40259377 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
@@ -63,7 +63,7 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
private readonly bool _subscribeRedundancyTopic;
private readonly NodeId? _localNode;
private readonly IDbContextFactory? _dbFactory;
- private readonly Phase7Applier? _applier;
+ private readonly AddressSpaceApplier? _applier;
private readonly IActorRef? _dbHealthProbe;
private readonly TimeSpan _staleWindow;
private readonly TimeSpan _probeFreshnessWindow;
@@ -77,7 +77,7 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
private DbHealthProbeActor.DbHealthStatus? _lastDbHealth;
private RedundancyStateChanged? _lastSnapshot;
private (bool Ok, DateTime At)? _probeAboutMe;
- private Phase7CompositionResult _lastApplied = new(
+ private AddressSpaceComposition _lastApplied = new(
Array.Empty(),
Array.Empty(),
Array.Empty(),
@@ -116,7 +116,7 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
IServiceLevelPublisher? serviceLevel = null,
NodeId? localNode = null,
IDbContextFactory? dbFactory = null,
- Phase7Applier? applier = null,
+ AddressSpaceApplier? applier = null,
IActorRef? dbHealthProbe = null,
TimeSpan? staleWindow = null,
TimeSpan? probeFreshnessWindow = null,
@@ -157,7 +157,7 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
bool subscribeRedundancyTopic = false,
NodeId? localNode = null,
IDbContextFactory? dbFactory = null,
- Phase7Applier? applier = null,
+ AddressSpaceApplier? applier = null,
IActorRef? dbHealthProbe = null,
TimeSpan? staleWindow = null,
TimeSpan? probeFreshnessWindow = null,
@@ -197,7 +197,7 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
bool subscribeRedundancyTopic,
NodeId? localNode,
IDbContextFactory? dbFactory = null,
- Phase7Applier? applier = null,
+ AddressSpaceApplier? applier = null,
IActorRef? dbHealthProbe = null,
TimeSpan? staleWindow = null,
TimeSpan? probeFreshnessWindow = null,
@@ -308,7 +308,7 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
? DeploymentArtifact.ParseComposition(artifact, ln.Value,
inconsistency => _log.Warning("OpcUaPublish {Node}: cross-cluster binding — {Message}", ln, inconsistency))
: DeploymentArtifact.ParseComposition(artifact);
- var plan = Phase7Planner.Compute(_lastApplied, composition);
+ var plan = AddressSpacePlanner.Compute(_lastApplied, composition);
if (plan.IsEmpty)
{
@@ -321,7 +321,7 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers
_lastApplied = composition;
// #85 — after the plan diff lands, rebuild the UNS folder hierarchy so OPC UA
- // clients see Area/Line/Equipment as proper folders. Idempotent; Phase7Applier
+ // clients see Area/Line/Equipment as proper folders. Idempotent; AddressSpaceApplier
// skips folders that already exist with the same node id.
_applier.MaterialiseHierarchy(composition);
// T14 — scripted alarms get their own pass right after the hierarchy so the equipment
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ServiceCollectionExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ServiceCollectionExtensions.cs
index c0604569..8c873d7a 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ServiceCollectionExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ServiceCollectionExtensions.cs
@@ -206,9 +206,9 @@ public static class ServiceCollectionExtensions
registry.Register(mux);
// OPC UA publish actor — pinned dispatcher, owns the address-space side of the
- // pipeline. Phase7Applier is constructed here so the actor + applier share the
+ // pipeline. AddressSpaceApplier is constructed here so the actor + applier share the
// same sink reference (when DeferredAddressSpaceSink swaps later, both see it).
- var applier = new Phase7Applier(addressSpaceSink, loggerFactory.CreateLogger());
+ var applier = new AddressSpaceApplier(addressSpaceSink, loggerFactory.CreateLogger());
var publishActor = system.ActorOf(
OpcUaPublishActor.Props(
sink: addressSpaceSink,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/VirtualTagHostActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/VirtualTagHostActor.cs
index 61571288..00beb670 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/VirtualTagHostActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/VirtualTagHostActor.cs
@@ -20,7 +20,7 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.VirtualTags;
///
///
/// The published NodeId is computed by the shared —
-/// the single source of truth Phase7Applier.MaterialiseEquipmentVirtualTags also
+/// the single source of truth AddressSpaceApplier.MaterialiseEquipmentVirtualTags also
/// materialises against — so the value always lands on a NodeId that exists.
///
///
@@ -198,7 +198,7 @@ public sealed class VirtualTagHostActor : ReceiveActor
}
/// Folder-scoped NodeId for a VirtualTag plan. The formula now lives in the shared
- /// (the single source of truth that Phase7Applier also
+ /// (the single source of truth that AddressSpaceApplier also
/// materialises against), so the published value always lands on the NodeId that was materialised.
private static string NodeIdFor(EquipmentVirtualTagPlan p) =>
EquipmentNodeIds.Variable(p.EquipmentId, p.FolderPath, p.Name);
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/Phase7ScriptingEntitiesTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ScriptingEntitiesTests.cs
similarity index 99%
rename from tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/Phase7ScriptingEntitiesTests.cs
rename to tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ScriptingEntitiesTests.cs
index 5a9df6be..e0b65a4b 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/Phase7ScriptingEntitiesTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ScriptingEntitiesTests.cs
@@ -15,7 +15,7 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Tests;
/// the plan decisions call for. Introspection only — no SQL Server required.
///
[Trait("Category", "Unit")]
-public sealed class Phase7ScriptingEntitiesTests
+public sealed class ScriptingEntitiesTests
{
private static OtOpcUaConfigDbContext BuildCtx()
{
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/EquipmentNamespaceMaterializationTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/EquipmentNamespaceMaterializationTests.cs
index 37ca48fa..e2167ca2 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/EquipmentNamespaceMaterializationTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/EquipmentNamespaceMaterializationTests.cs
@@ -20,7 +20,7 @@ namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;
/// seam that the OpcUaServer unit tests only approximate with hand-built JSON.
///
/// The OPC UA address-space browse is exercised separately against a real SDK node manager in
-/// Phase7ApplierHierarchyTests.Equipment_namespace_structure_materialises_end_to_end_against_real_SDK,
+/// AddressSpaceApplierHierarchyTests.Equipment_namespace_structure_materialises_end_to_end_against_real_SDK,
/// because the in-process binds the no-op address-space sink.
///
///
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierHierarchyTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/AddressSpaceApplierHierarchyTests.cs
similarity index 93%
rename from tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierHierarchyTests.cs
rename to tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/AddressSpaceApplierHierarchyTests.cs
index 0dbaf7db..c533e184 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierHierarchyTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/AddressSpaceApplierHierarchyTests.cs
@@ -10,13 +10,13 @@ using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests;
///
-/// #85 — verifies builds the UNS
+/// #85 — verifies builds the UNS
/// Area/Line/Equipment folder tree through .
/// One pure unit test (recording sink) confirms ordering + parenting; one boot-verify test
/// drives a real and inspects the resulting predefined-node
/// count to prove the folders land in the SDK address space.
///
-public sealed class Phase7ApplierHierarchyTests : IDisposable
+public sealed class AddressSpaceApplierHierarchyTests : IDisposable
{
private static CancellationToken Ct => TestContext.Current.CancellationToken;
@@ -29,9 +29,9 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable
public void MaterialiseHierarchy_creates_areas_then_lines_then_equipment_with_correct_parents()
{
var sink = new RecordingFolderSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
UnsAreas: new[] { new UnsAreaProjection("area-1", "Plant North") },
UnsLines: new[] { new UnsLineProjection("line-1", "area-1", "Cell A") },
EquipmentNodes: new[] { new EquipmentNode("eq-1", "Pump-1", "line-1") },
@@ -52,9 +52,9 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable
public void MaterialiseHierarchy_orphan_equipment_hangs_under_root()
{
var sink = new RecordingFolderSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
UnsAreas: Array.Empty(),
UnsLines: Array.Empty(),
EquipmentNodes: new[] { new EquipmentNode("eq-orphan", "Orphan", UnsLineId: "") },
@@ -86,9 +86,9 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable
sdkServer.NodeManager.ShouldNotBeNull();
var sink = new SdkAddressSpaceSink(sdkServer.NodeManager!);
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- applier.MaterialiseHierarchy(new Phase7CompositionResult(
+ applier.MaterialiseHierarchy(new AddressSpaceComposition(
UnsAreas: new[] { new UnsAreaProjection("area-A", "Area A"), new UnsAreaProjection("area-B", "Area B") },
UnsLines: new[] { new UnsLineProjection("line-1", "area-A", "Line 1") },
EquipmentNodes: new[] { new EquipmentNode("eq-1", "Eq 1", "line-1"), new EquipmentNode("eq-2", "Eq 2", "line-1") },
@@ -98,7 +98,7 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable
sdkServer.NodeManager!.FolderCount.ShouldBe(5); // 2 areas + 1 line + 2 equipment
// Idempotent: re-applying with the same composition doesn't create duplicates.
- applier.MaterialiseHierarchy(new Phase7CompositionResult(
+ applier.MaterialiseHierarchy(new AddressSpaceComposition(
UnsAreas: new[] { new UnsAreaProjection("area-A", "Area A"), new UnsAreaProjection("area-B", "Area B") },
UnsLines: new[] { new UnsLineProjection("line-1", "area-A", "Line 1") },
EquipmentNodes: new[] { new EquipmentNode("eq-1", "Eq 1", "line-1"), new EquipmentNode("eq-2", "Eq 2", "line-1") },
@@ -132,9 +132,9 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable
sdkServer.NodeManager.ShouldNotBeNull();
var sink = new SdkAddressSpaceSink(sdkServer.NodeManager!);
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
UnsAreas: Array.Empty(),
UnsLines: Array.Empty(),
EquipmentNodes: new[] { new EquipmentNode("eq-1", "filling-eq", UnsLineId: "") },
@@ -157,7 +157,7 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable
///
/// Full structure-materialisation pipeline against a real SDK node manager: real Config
- /// entities (Area / Line / Equipment + an Equipment-namespace Tag) →
+ /// entities (Area / Line / Equipment + an Equipment-namespace Tag) →
/// → MaterialiseHierarchy + MaterialiseEquipmentTags → . Proves
/// an Equipment namespace lands its Area/Line/Equipment folder tree + the equipment-signal
/// Variable in a live OPC UA address space (structure-only; live values are a later milestone).
@@ -192,7 +192,7 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable
var equipment = new Equipment { EquipmentId = "eq-1", DriverInstanceId = "drv-modbus", UnsLineId = "nw-line-1", Name = "station-1", MachineCode = "STATION_001" };
var tag = new Tag { TagId = "tag-speed", DriverInstanceId = "drv-modbus", EquipmentId = "eq-1", Name = "Speed", DataType = "Float", AccessLevel = TagAccessLevel.Read, TagConfig = "{\"FullName\":\"40001\"}" };
- var composition = Phase7Composer.Compose(
+ var composition = AddressSpaceComposer.Compose(
new[] { area }, new[] { line }, new[] { equipment }, new[] { driver },
Array.Empty(), new[] { tag }, new[] { ns });
@@ -202,7 +202,7 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable
planned.FullName.ShouldBe("40001");
var sink = new SdkAddressSpaceSink(sdkServer.NodeManager!);
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
applier.MaterialiseHierarchy(composition);
applier.MaterialiseEquipmentTags(composition);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/AddressSpaceApplierTests.cs
similarity index 89%
rename from tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierTests.cs
rename to tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/AddressSpaceApplierTests.cs
index 8d12249f..b11d80a8 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/AddressSpaceApplierTests.cs
@@ -6,14 +6,14 @@ using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests;
-public sealed class Phase7ApplierTests
+public sealed class AddressSpaceApplierTests
{
/// Verifies that an empty plan does not call the sink or trigger a rebuild.
[Fact]
public void Empty_plan_does_not_call_sink_and_does_not_trigger_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var outcome = applier.Apply(EmptyPlan);
@@ -30,7 +30,7 @@ public sealed class Phase7ApplierTests
public void Removed_equipment_writes_inactive_alarm_state_per_id_and_triggers_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var plan = WithEquipmentRemoval("eq-1", "eq-2");
var outcome = applier.Apply(plan);
@@ -48,18 +48,18 @@ public sealed class Phase7ApplierTests
public void Added_equipment_triggers_rebuild_without_alarm_writes()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var plan = new Phase7Plan(
+ var plan = new AddressSpacePlan(
AddedEquipment: new[] { new EquipmentNode("new", "New", "line-1") },
RemovedEquipment: Array.Empty(),
- ChangedEquipment: Array.Empty(),
+ ChangedEquipment: Array.Empty(),
AddedDrivers: Array.Empty(),
RemovedDrivers: Array.Empty(),
- ChangedDrivers: Array.Empty(),
+ ChangedDrivers: Array.Empty(),
AddedAlarms: Array.Empty(),
RemovedAlarms: Array.Empty(),
- ChangedAlarms: Array.Empty());
+ ChangedAlarms: Array.Empty());
var outcome = applier.Apply(plan);
@@ -74,23 +74,23 @@ public sealed class Phase7ApplierTests
public void Driver_only_changes_do_not_trigger_address_space_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var plan = new Phase7Plan(
+ var plan = new AddressSpacePlan(
AddedEquipment: Array.Empty(),
RemovedEquipment: Array.Empty(),
- ChangedEquipment: Array.Empty(),
+ ChangedEquipment: Array.Empty(),
AddedDrivers: new[] { new DriverInstancePlan("d-new", "Modbus", "{}") },
RemovedDrivers: Array.Empty(),
ChangedDrivers: new[]
{
- new Phase7Plan.DriverDelta(
+ new AddressSpacePlan.DriverDelta(
new DriverInstancePlan("d-1", "Modbus", "{\"v\":1}"),
new DriverInstancePlan("d-1", "Modbus", "{\"v\":2}")),
},
AddedAlarms: Array.Empty(),
RemovedAlarms: Array.Empty(),
- ChangedAlarms: Array.Empty());
+ ChangedAlarms: Array.Empty());
var outcome = applier.Apply(plan);
@@ -103,7 +103,7 @@ public sealed class Phase7ApplierTests
public void Sink_exception_in_WriteAlarmCondition_does_not_propagate_and_rebuild_still_fires()
{
var sink = new ThrowingSink(throwOnAlarmWrite: true);
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var plan = WithEquipmentRemoval("eq-1");
@@ -120,9 +120,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_creates_variable_under_equipment_folder()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
UnsAreas: Array.Empty(),
UnsLines: Array.Empty(),
EquipmentNodes: Array.Empty(),
@@ -151,9 +151,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_nests_FolderPath_subfolder_under_equipment()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -178,9 +178,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_identical_FullName_across_two_equipments_does_not_collide()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -206,9 +206,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_alarm_bearing_tag_becomes_condition_plain_tag_stays_variable()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -241,9 +241,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_alarm_bearing_tag_with_FolderPath_conditions_under_subfolder()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -271,9 +271,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_resolves_historian_tagname_default_override_and_null()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -304,9 +304,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_blank_override_falls_back_to_full_name()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -324,16 +324,16 @@ public sealed class Phase7ApplierTests
}
/// Array-support Task 2 — an with IsArray: true,
- /// ArrayLength: 16 flowing through must
+ /// ArrayLength: 16 flowing through must
/// forward BOTH flags verbatim to the sink's EnsureVariable. Guards against arg-order swaps or
/// accidental drops in the wire-through.
[Fact]
public void MaterialiseEquipmentTags_array_plan_forwards_isArray_and_arrayLength_to_sink()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -358,9 +358,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_scalar_plan_forwards_isArray_false_to_sink()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -387,9 +387,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_array_writable_true_is_forced_read_only()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -417,9 +417,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentTags_scalar_writable_true_stays_writable()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -446,9 +446,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentVirtualTags_creates_variable_under_equipment_folder()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentVirtualTags = new[]
@@ -469,7 +469,7 @@ public sealed class Phase7ApplierTests
/// Golden/parity guard: the materialiser's Variable NodeId for BOTH the equipment-tag and
/// the equipment-VirtualTag pass is byte-identical to — the
- /// single source of truth Phase7Applier + VirtualTagHostActor both point at. Covers null/empty
+ /// single source of truth AddressSpaceApplier + VirtualTagHostActor both point at. Covers null/empty
/// FolderPath (directly under equipment) and a non-empty FolderPath (sub-folder scoped). This test
/// LOCKS the formula against drift: any change to the materialiser NodeId that diverges from the
/// shared helper fails here.
@@ -477,9 +477,9 @@ public sealed class Phase7ApplierTests
public void Materialised_variable_node_ids_match_shared_EquipmentNodeIds_formula()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -512,9 +512,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseEquipmentVirtualTags_two_under_same_equipment_do_not_collide()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentVirtualTags = new[]
@@ -541,9 +541,9 @@ public sealed class Phase7ApplierTests
public void MaterialiseScriptedAlarms_materialises_enabled_and_skips_disabled()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var composition = new Phase7CompositionResult(
+ var composition = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentScriptedAlarms = new[]
@@ -574,7 +574,7 @@ public sealed class Phase7ApplierTests
public void Added_equipment_tags_trigger_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var plan = EmptyPlan with
{
@@ -598,7 +598,7 @@ public sealed class Phase7ApplierTests
public void Added_equipment_virtual_tags_trigger_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var plan = EmptyPlan with
{
@@ -624,7 +624,7 @@ public sealed class Phase7ApplierTests
public void Changed_equipment_tags_only_trigger_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: false, Alarm: null));
@@ -632,7 +632,7 @@ public sealed class Phase7ApplierTests
var next = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Int32", FullName: "40001", Writable: true, Alarm: null));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: ONLY ChangedEquipmentTags is populated.
plan.ChangedEquipmentTags.Count.ShouldBe(1);
@@ -659,7 +659,7 @@ public sealed class Phase7ApplierTests
public void Changed_virtual_tag_expression_only_skips_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithVirtualTags(
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
@@ -669,7 +669,7 @@ public sealed class Phase7ApplierTests
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
Expression: "ctx.GetTag(\"a\") * 120", DependencyRefs: new[] { "a" }));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: ONLY ChangedEquipmentVirtualTags is populated.
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(1);
@@ -690,7 +690,7 @@ public sealed class Phase7ApplierTests
public void Changed_virtual_tag_dependency_refs_only_skips_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithVirtualTags(
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
@@ -703,7 +703,7 @@ public sealed class Phase7ApplierTests
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
Expression: "ctx.GetTag(\"a\")", DependencyRefs: new[] { "a", "b" }));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -719,7 +719,7 @@ public sealed class Phase7ApplierTests
public void Changed_virtual_tag_historize_only_skips_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithVirtualTags(
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
@@ -729,7 +729,7 @@ public sealed class Phase7ApplierTests
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
Expression: "ctx.GetTag(\"a\")", DependencyRefs: new[] { "a" }, Historize: true));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -747,7 +747,7 @@ public sealed class Phase7ApplierTests
public void Changed_virtual_tag_data_type_change_still_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithVirtualTags(
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
@@ -757,7 +757,7 @@ public sealed class Phase7ApplierTests
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Int32",
Expression: "ctx.GetTag(\"a\") * 60", DependencyRefs: new[] { "a" }));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -772,7 +772,7 @@ public sealed class Phase7ApplierTests
public void Changed_virtual_tag_name_change_still_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithVirtualTags(
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
@@ -781,7 +781,7 @@ public sealed class Phase7ApplierTests
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "EfficiencyPct", DataType: "Float64",
Expression: "ctx.GetTag(\"a\")", DependencyRefs: new[] { "a" }));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -796,7 +796,7 @@ public sealed class Phase7ApplierTests
public void Changed_virtual_tag_folder_path_change_still_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithVirtualTags(
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
@@ -805,7 +805,7 @@ public sealed class Phase7ApplierTests
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "Calc", Name: "Efficiency", DataType: "Float64",
Expression: "ctx.GetTag(\"a\")", DependencyRefs: new[] { "a" }));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -822,9 +822,9 @@ public sealed class Phase7ApplierTests
public void Node_irrelevant_vtag_edit_mixed_with_another_change_still_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var previous = new Phase7CompositionResult(
+ var previous = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -838,7 +838,7 @@ public sealed class Phase7ApplierTests
},
};
// Expression-only vtag edit (node-irrelevant) AND a node-affecting tag DataType flip.
- var next = new Phase7CompositionResult(
+ var next = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -852,7 +852,7 @@ public sealed class Phase7ApplierTests
},
};
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Both a node-irrelevant vtag change AND a node-affecting tag change are present.
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(1);
@@ -873,7 +873,7 @@ public sealed class Phase7ApplierTests
public void Changed_virtual_tag_equipment_id_triggers_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithVirtualTags(
new EquipmentVirtualTagPlan("vt-1", "eq-1", FolderPath: "", Name: "Efficiency", DataType: "Float64",
@@ -884,7 +884,7 @@ public sealed class Phase7ApplierTests
new EquipmentVirtualTagPlan("vt-1", "eq-2", FolderPath: "", Name: "Efficiency", DataType: "Float64",
Expression: "ctx.GetTag(\"a\")", DependencyRefs: new[] { "a" }));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: the planner sees this as a changed vtag (same id, different EquipmentId).
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(1);
@@ -907,9 +907,9 @@ public sealed class Phase7ApplierTests
public void Changed_virtual_tags_one_irrelevant_one_structural_triggers_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var previous = new Phase7CompositionResult(
+ var previous = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentVirtualTags = new[]
@@ -922,7 +922,7 @@ public sealed class Phase7ApplierTests
Expression: "ctx.GetTag(\"load\")", DependencyRefs: new[] { "load" }),
},
};
- var next = new Phase7CompositionResult(
+ var next = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentVirtualTags = new[]
@@ -936,7 +936,7 @@ public sealed class Phase7ApplierTests
},
};
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: both vtags are diffed as changed, nothing else.
plan.ChangedEquipmentVirtualTags.Count.ShouldBe(2);
@@ -961,13 +961,13 @@ public sealed class Phase7ApplierTests
public void Changed_alarms_only_trigger_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithAlarms(new ScriptedAlarmPlan("alm-1", "eq-1", "scr-1", "Temp high"));
// Same alarm id, edited message template — the planner classifies this as a change.
var next = CompositionWithAlarms(new ScriptedAlarmPlan("alm-1", "eq-1", "scr-1", "Temp critically high"));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: ONLY ChangedAlarms is populated.
plan.ChangedAlarms.Count.ShouldBe(1);
@@ -991,12 +991,12 @@ public sealed class Phase7ApplierTests
public void Changed_drivers_only_do_not_trigger_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithDrivers(new DriverInstancePlan("d-1", "Modbus", "{\"v\":1}"));
var next = CompositionWithDrivers(new DriverInstancePlan("d-1", "Modbus", "{\"v\":2}"));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: ONLY ChangedDrivers is populated.
plan.ChangedDrivers.Count.ShouldBe(1);
@@ -1017,15 +1017,15 @@ public sealed class Phase7ApplierTests
/// H1a (review follow-up) — a deploy that ONLY removes existing equipment tag / VirtualTag
/// nodes must rebuild AND tally the removals. Removed tags/VirtualTags are plain variable nodes (no
/// Part 9 condition to write), so before the fix they reached the rebuild path but were never added
- /// to removedCount — Phase7ApplyOutcome.RemovedNodes reported 0, a misleading audit
+ /// to removedCount — AddressSpaceApplyOutcome.RemovedNodes reported 0, a misleading audit
/// entry. This pins both the rebuild and the accurate count.
[Fact]
public void Removed_equipment_tags_and_virtual_tags_only_rebuild_and_are_counted()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var previous = new Phase7CompositionResult(
+ var previous = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -1038,10 +1038,10 @@ public sealed class Phase7ApplierTests
Expression: "ctx.GetTag(\"a\")", DependencyRefs: new[] { "a" }),
},
};
- var next = new Phase7CompositionResult(
+ var next = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty());
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: ONLY the two Removed sets are populated.
plan.RemovedEquipmentTags.Count.ShouldBe(1);
@@ -1069,7 +1069,7 @@ public sealed class Phase7ApplierTests
public void Changed_tag_writable_only_skips_rebuild_and_updates_in_place()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: false, Alarm: null));
@@ -1077,7 +1077,7 @@ public sealed class Phase7ApplierTests
var next = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: true, Alarm: null));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
plan.AddedEquipmentTags.ShouldBeEmpty();
plan.RemovedEquipmentTags.ShouldBeEmpty();
@@ -1101,8 +1101,8 @@ public sealed class Phase7ApplierTests
{
// false → true (no override) ⇒ historian defaults to FullName.
var sinkOn = new RecordingSink();
- var applierOn = new Phase7Applier(sinkOn, NullLogger.Instance);
- var planOn = Phase7Planner.Compute(
+ var applierOn = new AddressSpaceApplier(sinkOn, NullLogger.Instance);
+ var planOn = AddressSpacePlanner.Compute(
CompositionWithTags(new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float",
FullName: "T.A", Writable: false, Alarm: null, IsHistorized: false, HistorianTagname: null)),
CompositionWithTags(new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float",
@@ -1117,8 +1117,8 @@ public sealed class Phase7ApplierTests
// true → false ⇒ historian null.
var sinkOff = new RecordingSink();
- var applierOff = new Phase7Applier(sinkOff, NullLogger.Instance);
- var planOff = Phase7Planner.Compute(
+ var applierOff = new AddressSpaceApplier(sinkOff, NullLogger.Instance);
+ var planOff = AddressSpacePlanner.Compute(
CompositionWithTags(new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float",
FullName: "T.A", Writable: false, Alarm: null, IsHistorized: true, HistorianTagname: null)),
CompositionWithTags(new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float",
@@ -1138,7 +1138,7 @@ public sealed class Phase7ApplierTests
public void Changed_tag_historian_tagname_only_skips_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float",
@@ -1147,7 +1147,7 @@ public sealed class Phase7ApplierTests
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float",
FullName: "T.A", Writable: false, Alarm: null, IsHistorized: true, HistorianTagname: "WW.New"));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -1163,7 +1163,7 @@ public sealed class Phase7ApplierTests
public void Changed_tag_data_type_change_rebuilds_and_no_surgical_call()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: false, Alarm: null));
@@ -1171,7 +1171,7 @@ public sealed class Phase7ApplierTests
var next = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Int32", FullName: "40001", Writable: true, Alarm: null));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -1187,7 +1187,7 @@ public sealed class Phase7ApplierTests
public void Changed_tag_is_array_change_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Buffer", DataType: "Int16",
@@ -1196,7 +1196,7 @@ public sealed class Phase7ApplierTests
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Buffer", DataType: "Int16",
FullName: "40001", Writable: false, Alarm: null, IsArray: true, ArrayLength: 16u));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -1212,14 +1212,14 @@ public sealed class Phase7ApplierTests
public void Changed_tag_full_name_change_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: false, Alarm: null));
var next = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40002", Writable: false, Alarm: null));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -1235,14 +1235,14 @@ public sealed class Phase7ApplierTests
public void Changed_tag_name_change_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: false, Alarm: null));
var next = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "SpeedRpm", DataType: "Float", FullName: "40001", Writable: false, Alarm: null));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -1259,7 +1259,7 @@ public sealed class Phase7ApplierTests
public void Changed_tag_alarm_presence_change_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "OverTemp", DataType: "Boolean", FullName: "00001", Writable: false, Alarm: null));
@@ -1267,7 +1267,7 @@ public sealed class Phase7ApplierTests
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "OverTemp", DataType: "Boolean", FullName: "00001", Writable: false,
Alarm: new EquipmentTagAlarmInfo("OffNormalAlarm", 700)));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -1288,7 +1288,7 @@ public sealed class Phase7ApplierTests
public void Changed_alarm_bearing_tag_writable_only_still_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
// Both previous and current carry an identical, non-null alarm — the tag is an alarm-bearing node.
var alarm = new EquipmentTagAlarmInfo("OffNormalAlarm", 700);
@@ -1300,7 +1300,7 @@ public sealed class Phase7ApplierTests
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "OverTemp", DataType: "Boolean",
FullName: "00001", Writable: true, Alarm: alarm));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: the planner sees a changed tag (Writable differs) and nothing else.
plan.ChangedEquipmentTags.Count.ShouldBe(1);
@@ -1323,10 +1323,10 @@ public sealed class Phase7ApplierTests
public void Two_surgical_eligible_tag_deltas_both_apply_in_place_no_rebuild()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
// Two distinct plain (no-alarm) tags, both will flip Writable — both are surgical-eligible.
- var previous = new Phase7CompositionResult(
+ var previous = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -1336,7 +1336,7 @@ public sealed class Phase7ApplierTests
},
};
// Only Writable flips on both tags; everything else is identical.
- var next = new Phase7CompositionResult(
+ var next = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -1346,7 +1346,7 @@ public sealed class Phase7ApplierTests
},
};
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
// Guard the arrange: exactly two changed tags, nothing else.
plan.ChangedEquipmentTags.Count.ShouldBe(2);
@@ -1380,9 +1380,9 @@ public sealed class Phase7ApplierTests
public void Surgical_eligible_tag_delta_mixed_with_added_equipment_rebuilds()
{
var sink = new RecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
- var previous = new Phase7CompositionResult(
+ var previous = new AddressSpaceComposition(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -1391,7 +1391,7 @@ public sealed class Phase7ApplierTests
},
};
// Surgical-eligible Writable flip on the tag AND a brand-new equipment node.
- var next = new Phase7CompositionResult(
+ var next = new AddressSpaceComposition(
new[] { new EquipmentNode("eq-new", "New", "line-1") }, Array.Empty(), Array.Empty())
{
EquipmentTags = new[]
@@ -1400,7 +1400,7 @@ public sealed class Phase7ApplierTests
},
};
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
plan.AddedEquipment.Count.ShouldBe(1);
@@ -1418,14 +1418,14 @@ public sealed class Phase7ApplierTests
public void Surgical_eligible_delta_on_non_surgical_sink_rebuilds()
{
var sink = new PlainRecordingSink();
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: false, Alarm: null));
var next = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: true, Alarm: null));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -1441,14 +1441,14 @@ public sealed class Phase7ApplierTests
public void Surgical_sink_returning_false_node_missing_falls_back_to_rebuild()
{
var sink = new RecordingSink { SurgicalReturns = false };
- var applier = new Phase7Applier(sink, NullLogger.Instance);
+ var applier = new AddressSpaceApplier(sink, NullLogger.Instance);
var previous = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: false, Alarm: null));
var next = CompositionWithTags(
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001", Writable: true, Alarm: null));
- var plan = Phase7Planner.Compute(previous, next);
+ var plan = AddressSpacePlanner.Compute(previous, next);
plan.ChangedEquipmentTags.Count.ShouldBe(1);
var outcome = applier.Apply(plan);
@@ -1458,44 +1458,44 @@ public sealed class Phase7ApplierTests
sink.SurgicalCalls.ShouldHaveSingleItem(); // the surgical update was attempted first
}
- private static Phase7CompositionResult CompositionWithTags(params EquipmentTagPlan[] tags) =>
+ private static AddressSpaceComposition CompositionWithTags(params EquipmentTagPlan[] tags) =>
new(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentTags = tags,
};
- private static Phase7CompositionResult CompositionWithVirtualTags(params EquipmentVirtualTagPlan[] vtags) =>
+ private static AddressSpaceComposition CompositionWithVirtualTags(params EquipmentVirtualTagPlan[] vtags) =>
new(
Array.Empty(), Array.Empty(), Array.Empty())
{
EquipmentVirtualTags = vtags,
};
- private static Phase7CompositionResult CompositionWithAlarms(params ScriptedAlarmPlan[] alarms) =>
+ private static AddressSpaceComposition CompositionWithAlarms(params ScriptedAlarmPlan[] alarms) =>
// ScriptedAlarmPlans is the set the planner diffs into Added/Removed/ChangedAlarms.
new(
Array.Empty(), Array.Empty(), alarms);
- private static Phase7CompositionResult CompositionWithDrivers(params DriverInstancePlan[] drivers) =>
+ private static AddressSpaceComposition CompositionWithDrivers(params DriverInstancePlan[] drivers) =>
new(
Array.Empty(), drivers, Array.Empty());
- private static Phase7Plan EmptyPlan => new(
- Array.Empty(), Array.Empty(), Array.Empty(),
- Array.Empty(), Array.Empty(), Array.Empty(),
- Array.Empty(), Array.Empty(), Array.Empty());
+ private static AddressSpacePlan EmptyPlan => new(
+ Array.Empty(), Array.Empty(), Array.Empty(),
+ Array.Empty(), Array.Empty(), Array.Empty(),
+ Array.Empty(), Array.Empty(), Array.Empty());
- private static Phase7Plan WithEquipmentRemoval(params string[] ids) => new(
+ private static AddressSpacePlan WithEquipmentRemoval(params string[] ids) => new(
AddedEquipment: Array.Empty(),
RemovedEquipment: ids.Select(id => new EquipmentNode(id, id, "line-1")).ToArray(),
- ChangedEquipment: Array.Empty(),
+ ChangedEquipment: Array.Empty(),
AddedDrivers: Array.Empty