docs(xmldoc): fill missing XML docs + strip tracking-ID comments across src
v2-ci / build (push) Failing after 41s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped

Adds <summary>/<param>/<returns>/<inheritdoc> where missing and removes
project bookkeeping IDs (task/tracking refs) from shipped code comments,
so the docs read cleanly and CommentChecker is quiet except for known
false positives (PLC/protocol terms, event/IEqualityComparer inheritdoc).
Doc/comment-only; no logic changed; solution builds clean.
This commit is contained in:
Joseph Doherty
2026-07-07 12:38:39 -04:00
parent 384dbd7d36
commit 9cad9ed0fc
375 changed files with 1899 additions and 2493 deletions
@@ -10,12 +10,12 @@ namespace ZB.MOM.WW.OtOpcUa.Core.OpcUa;
/// <c>UnsArea</c> / <c>UnsLine</c> / <c>Equipment</c> / <c>Tag</c> rows. Runs during
/// address-space build per <see cref="IDriver"/> whose
/// <c>Namespace.Kind = Equipment</c>; non-Equipment namespaces are
/// exempt per decision #120 and reach this walker only indirectly through
/// exempt and reach this walker only indirectly through
/// <see cref="ITagDiscovery.DiscoverAsync"/>.
/// </summary>
/// <remarks>
/// <para>
/// <b>Composition strategy.</b> ADR-001 (2026-04-20) accepted Option A — Config
/// <b>Composition strategy.</b> Accepted Option A — Config
/// primary. The walker treats the supplied <see cref="EquipmentNamespaceContent"/>
/// snapshot as the authoritative published surface. Every Equipment row becomes a
/// folder node at the UNS level-5 segment; every <see cref="Tag"/> bound to an
@@ -26,12 +26,12 @@ namespace ZB.MOM.WW.OtOpcUa.Core.OpcUa;
/// </para>
///
/// <para>
/// <b>Under each Equipment node.</b> Five identifier properties per decision #121
/// <b>Under each Equipment node.</b> Five identifier properties
/// (<c>EquipmentId</c>, <c>EquipmentUuid</c>, <c>MachineCode</c>, <c>ZTag</c>,
/// <c>SAPID</c>) are added as OPC UA properties — external systems (ERP, SAP PM)
/// resolve equipment by whichever identifier they natively use without a sidecar.
/// <see cref="IdentificationFolderBuilder.Build"/> materializes the OPC 40010
/// Identification sub-folder with the nine decision-#139 fields when at least one
/// Identification sub-folder with the nine fields when at least one
/// is non-null; when all nine are null the sub-folder is omitted rather than
/// appearing empty.
/// </para>
@@ -131,7 +131,7 @@ public static class EquipmentNodeWalker
}
/// <summary>
/// Adds the five operator-facing identifiers from decision #121 as OPC UA properties
/// Adds the five operator-facing identifiers as OPC UA properties
/// on the Equipment node. EquipmentId + EquipmentUuid are always populated;
/// MachineCode is required per <see cref="Equipment"/>; ZTag + SAPID are nullable in
/// the data model so they're skipped when null to avoid empty-string noise in the
@@ -152,7 +152,7 @@ public static class EquipmentNodeWalker
/// Emit a single Tag row as an <see cref="IAddressSpaceBuilder.Variable"/>. The driver
/// full reference lives in <c>Tag.TagConfig</c> (wire-level address, driver-specific
/// JSON blob); the variable node's data type derives from <c>Tag.DataType</c>.
/// Unreachable-address behavior per ADR-001 Option A: the variable is created; the
/// Unreachable-address behavior: the variable is created; the
/// driver's natural Read failure surfaces an OPC UA Bad status at runtime.
/// </summary>
private static void AddTagVariable(IAddressSpaceBuilder equipmentBuilder, Tag tag)
@@ -189,6 +189,7 @@ public static class EquipmentNodeWalker
/// wants an opaque non-JSON reference.
/// </remarks>
/// <param name="tagConfig">The tag configuration JSON or string.</param>
/// <returns>The extracted <c>FullName</c> value, or the raw <paramref name="tagConfig"/> if it can't be extracted.</returns>
internal static string ExtractFullName(string tagConfig)
{
if (string.IsNullOrWhiteSpace(tagConfig)) return tagConfig;
@@ -208,7 +209,7 @@ public static class EquipmentNodeWalker
/// <summary>
/// Parse <see cref="Tag.DataType"/> (stored as the <see cref="DriverDataType"/> enum
/// name string, decision #138) into the enum value. Unknown names fall back to
/// name string) into the enum value. Unknown names fall back to
/// <see cref="DriverDataType.String"/> so a one-off driver-specific type doesn't
/// abort the whole walk; the underlying driver still sees the original TagConfig
/// address + can surface its own typed value via the OPC UA variant at read time.
@@ -12,7 +12,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.OpcUa;
/// against <c>CustomNodeManager2</c>.
/// </summary>
/// <remarks>
/// Per <c>docs/v2/plan.md</c> decision #52 + #62 — Core owns the node tree, drivers stream
/// Per <c>docs/v2/plan.md</c> — Core owns the node tree, drivers stream
/// <c>Folder</c>/<c>Variable</c> calls, alarm-bearing variables are annotated via
/// <see cref="IVariableHandle.MarkAsAlarmCondition"/> and subsequent
/// <see cref="IAlarmSource.OnAlarmEvent"/> payloads route to the sink the builder returned.
@@ -41,7 +41,7 @@ public class GenericDriverNodeManager(IDriver driver) : IDisposable
/// If called a second time (e.g. Galaxy redeploy via <c>IRediscoverable.OnRediscoveryNeeded</c>)
/// the previous alarm subscription is torn down and the sink registry is cleared before
/// re-walking, preventing double delivery of alarm transitions.
/// Exception isolation (per decision #12 — marking the driver's subtree Faulted while other
/// Exception isolation (marking the driver's subtree Faulted while other
/// drivers stay available) is the caller's responsibility; exceptions from
/// <see cref="ITagDiscovery.DiscoverAsync"/> propagate unhandled to the caller. The Server
/// project's <c>OpcUaApplicationHost.PopulateAddressSpaces</c> wraps this call in a per-driver
@@ -49,6 +49,7 @@ public class GenericDriverNodeManager(IDriver driver) : IDisposable
/// </summary>
/// <param name="builder">The address space builder to populate.</param>
/// <param name="ct">The cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async Task BuildAddressSpaceAsync(IAddressSpaceBuilder builder, CancellationToken ct)
{
ArgumentNullException.ThrowIfNull(builder);
@@ -111,23 +112,15 @@ public class GenericDriverNodeManager(IDriver driver) : IDisposable
IAddressSpaceBuilder inner,
ConcurrentDictionary<string, IAlarmConditionSink> sinks) : IAddressSpaceBuilder
{
/// <summary>Adds a folder to the address space.</summary>
/// <param name="browseName">The browse name of the folder node.</param>
/// <param name="displayName">The display name of the folder node.</param>
/// <inheritdoc />
public IAddressSpaceBuilder Folder(string browseName, string displayName)
=> new CapturingBuilder(inner.Folder(browseName, displayName), sinks);
/// <summary>Adds a variable to the address space.</summary>
/// <param name="browseName">The browse name of the variable node.</param>
/// <param name="displayName">The display name of the variable node.</param>
/// <param name="attributeInfo">Metadata describing the variable's data type and properties.</param>
/// <inheritdoc />
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo)
=> new CapturingHandle(inner.Variable(browseName, displayName, attributeInfo), sinks);
/// <summary>Adds a property to the address space.</summary>
/// <param name="browseName">The browse name of the property node.</param>
/// <param name="dataType">The OPC UA data type of the property.</param>
/// <param name="value">The initial value of the property, or null.</param>
/// <inheritdoc />
public void AddProperty(string browseName, DriverDataType dataType, object? value)
=> inner.AddProperty(browseName, dataType, value);
}
@@ -136,11 +129,10 @@ public class GenericDriverNodeManager(IDriver driver) : IDisposable
IVariableHandle inner,
ConcurrentDictionary<string, IAlarmConditionSink> sinks) : IVariableHandle
{
/// <summary>Gets the full reference for the variable.</summary>
/// <inheritdoc />
public string FullReference => inner.FullReference;
/// <summary>Marks the variable as an alarm condition and registers its sink.</summary>
/// <param name="info">Configuration for the alarm condition.</param>
/// <inheritdoc />
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info)
{
var sink = inner.MarkAsAlarmCondition(info);
@@ -5,7 +5,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.OpcUa;
/// <summary>
/// Phase 6.4 Stream D: materializes the OPC 40010 Machinery companion-spec Identification
/// sub-folder under an Equipment node. Reads the nine decision-#139 columns off the
/// sub-folder under an Equipment node. Reads the nine documented columns off the
/// <see cref="Equipment"/> row and emits one property per non-null field.
/// </summary>
/// <remarks>
@@ -19,7 +19,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.OpcUa;
/// grant gets BadUserAccessDenied on both the Equipment node + its Identification variables.
/// See <c>docs/v2/acl-design.md</c> §Identification cross-reference.</para>
///
/// <para>The nine fields per decision #139 are exposed exactly when they carry a non-null
/// <para>The nine fields are exposed exactly when they carry a non-null
/// value. A row with all nine null produces no Identification sub-folder at all — the
/// caller can use <see cref="HasAnyFields(Equipment)"/> to skip the Folder call entirely
/// and avoid a pointless empty folder appearing in browse trees.</para>