fix(core): resolve Low code-review findings (Core-004,008,009,010,011,012)

- Core-004: add ConfigureAwait(false) to DriverHost.RegisterAsync /
  UnregisterAsync / DisposeAsync.
- Core-008: rewrite the BuildAddressSpaceAsync XML doc to correctly name
  the caller (OpcUaApplicationHost.PopulateAddressSpaces) that owns the
  per-driver isolation.
- Core-009: snapshot DriverResilienceOptions once per non-idempotent write
  in CapabilityInvoker.ExecuteWriteAsync.
- Core-010: switch DriverResilienceOptions.Resolve to TryGetValue with a
  diagnostic error message when a tier table is missing a capability.
- Core-011: add an optional diagnostic callback to PermissionTrieBuilder
  so production callers can surface scope-path mismatches.
- Core-012: correct the stale WedgeDetector ctor summary and add the
  Reconnecting row to DriverHealthReport's state matrix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-05-23 05:38:09 -04:00
parent ff2e75ab98
commit 8be6afbda4
15 changed files with 656 additions and 28 deletions

View File

@@ -109,4 +109,40 @@ public sealed class WedgeDetectorTests
new DemandSignal(0, 0, 1, Now).HasPendingWork.ShouldBeTrue();
new DemandSignal(0, 0, 0, Now).HasPendingWork.ShouldBeFalse();
}
/// <summary>
/// Core-012 regression: the XML <c>&lt;summary&gt;</c> on the <see cref="WedgeDetector"/>
/// constructor must accurately describe what the constructor does (take + clamp the
/// threshold). The previous text — "Whether the driver reported itself Healthy at
/// construction" — referenced behaviour the constructor doesn't perform.
/// </summary>
[Fact]
public void Doc_Constructor_Summary_Describes_Threshold_Clamp()
{
var xmlPath = Path.Combine(
AppContext.BaseDirectory,
"ZB.MOM.WW.OtOpcUa.Core.xml");
File.Exists(xmlPath).ShouldBeTrue($"expected XML doc file at {xmlPath}");
var content = File.ReadAllText(xmlPath);
var ctorSummary = ExtractSummaryFor(content,
"M:ZB.MOM.WW.OtOpcUa.Core.Stability.WedgeDetector.#ctor(System.TimeSpan)");
ctorSummary.ShouldNotBeNullOrWhiteSpace();
ctorSummary.ShouldNotContain("reported itself");
ctorSummary.ShouldContain("threshold");
}
private static string ExtractSummaryFor(string xml, string member)
{
var memberStart = xml.IndexOf($"<member name=\"{member}\"", StringComparison.Ordinal);
if (memberStart < 0) return string.Empty;
var memberEnd = xml.IndexOf("</member>", memberStart, StringComparison.Ordinal);
if (memberEnd < 0) return string.Empty;
var slice = xml.Substring(memberStart, memberEnd - memberStart);
var sumStart = slice.IndexOf("<summary>", StringComparison.Ordinal);
if (sumStart < 0) return string.Empty;
var sumEnd = slice.IndexOf("</summary>", sumStart, StringComparison.Ordinal);
return sumEnd < 0 ? string.Empty : slice.Substring(sumStart, sumEnd - sumStart);
}
}