Skip to content

Complete standalone PackML runtime and native async transition support - #4995

Draft
marcschier wants to merge 55 commits into
masterfrom
marcschier-packml-full-support
Draft

marcschier wants to merge 55 commits into
masterfrom
marcschier-packml-full-support

Conversation

@marcschier

@marcschier marcschier commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Add a standalone OPC 30050 PackML runtime, administration, typed clients, and a simulated client/server sample while retaining the Scales and Lens compositions. Provider acceptance remains separate from equipment completion. Modes define concrete state subsets; state Reset does not reset production counters.

Support status: The published head is not yet full PackML 1.01 support. A real-session browse found that the standalone unit is not organized under PackMLObjects as required by OPC 30050 §6.2. The folder fix and its regression are not yet published or validated.

Native async state-machine operations deliver each transition's events and change masks before the next transition. While async notifications are being delivered, overlapping synchronous writes return BadInvalidState or throw ServiceResultException for void setters. Composite operations coordinate parent and nested machines; hierarchical completion and fluent lifecycle observers use native async paths. Callbacks must not await reentrant operations that require the same owner. Legacy synchronous callers retain their behavior outside async notification delivery.

Parentless units register as Server event roots, and deletion removes their registrations. During candidate preparation, Server HasNotifier references remain private. Reference cleanup resolves the registered facade without changing generation ownership. The published PackML subscriber test passed for Direct, Adapted, and Forwarded managers, but separate Server forwarding and lifetime tests still fail. The routing and ownership changes are in progress and have not been validated. Those fixes are being developed in #5011, and this PR will align with the shared implementation before qualification.

PackML evidence on published head 4f7a4ca68

The PackML test project passed 220 of 220 cases on each of four platform and framework combinations. These results are for the published head and do not validate the unpublished lifecycle draft.

Hosted job PackML test result
Windows net48 220 passed
Windows net10.0 220 passed
Linux net10.0 220 passed
macOS net10.0 220 passed

ConfiguredUnitAdvertisesEveryDefinedServerConformanceUnit checks 40 distinct Table 63 server titles and the completion path. It does not establish each unit's full behavior. Passing real-session tests cover state-command acceptance and equipment completion, optional base properties, configured operations, and administration reads. Both PackMLMonitoredItemSupportsQueueSizeOfAtLeastFive cases and the optional Hold-transition cases also pass.

The tests do not yet map every companion conformance requirement to executable evidence. In particular, PackML tests do not directly assert the typed-client available-state and transition arrays or read CurMachSpeed engineering units over the wire. These are qualification gaps, not evidence that the features are absent. Inherited Core, Data Access, Method, transport, subscription, and time-synchronization requirements require separate qualification. The results are not OPC Foundation certification.

Outstanding validation and limitations

  • PackMLObjects: OPC 30050 v1.01 §6.2 requires the folder under Objects to contain PackML units. In the isolated real-session diagnostic, StandaloneUnitIsOrganizedBelowPackMLObjectsAsync found the folder but its Organizes browse was empty. Diagnostic head 32ff1f21e2895c61afe68f35e174758593196d62 has published head 4f7a4ca68dd924de3dcd82d6a6a71146da7575bc as its ancestor and changes only the diagnostic test and workflows. The one selected test failed; this establishes a functional gap, not certification or a result for the unpublished draft.
  • Hosted Server tests still fail on Windows net48, Windows net10.0, Linux net10.0, and macOS net10.0. They include forwarding and private-facade lifetime failures. The published PackML Forwarded subscriber pass does not resolve these failures. Windows net48 node management and macOS node management each failed 11 tests. Windows net48 node lifecycle and macOS node lifecycle each failed both PrivateForwardedRawBindingFollowsCandidateLifetimeAsync cases. The full Server project failed 13 tests on Windows net10.0 and Linux net10.0.
  • The Linux sample-core first attempt stopped after 10 minutes without test activity while UnavailableUpstreamEndpointFailsMappedReadAsync was active; its 64 completed tests passed. The same-head retry passed 72 of 72, including that case in 6 minutes 48 seconds. The retry does not explain the earlier timeout or validate the unpublished draft.
  • A replacement installed under the same NodeId while a serving-reference removal is pending may be captured as the deleted incarnation when the removal is queued. A diagnostic test for an identical reference remains unrun, so this scenario is not resolved.
  • A removal that continues to fail remains queued and is retried when a later deletion or publication requests a drain. Permanent-failure retention has not been validated.
  • The ReferenceBatch run stopped during compilation without producing test results. The focused net10 startup regression and deferred-replacement diagnostic have not run.
  • Full local dotnet test UA.slnx runs on net48 and net10.0 have not been performed. The shared host has not provided a conflict-free validation window. A previous SDK 10 solution run reported VSTest errors for the three TUnit NativeAOT projects before the job was cancelled; CI publishes and runs those executables separately. No alternative runner is represented as a full-solution result.
  • The macOS net10 server-other job at c779de3d failed NetworkModelIntegrationTests.RemovedInterfaceDisappearsAndOldNodeReturnsUnknown with BadNodeIdUnknown during discovery. The other 1,197 tests passed. The failure did not record the NodeId. Master also removes nodes from lookup before cleaning references, and the unchanged client traverses in separate browse calls. The cause and PR attribution are not established. A between-browse diagnostic is drafted but has not been built or run against either base or this head.
  • The macOS WoT integration shard reached its 45-minute project limit twice at 7700c759 and again at c779de3d. The matched cases slowed across several fixtures compared with master; the data does not establish whether the PR caused the slowdown. See the earlier CI run at c779de3d for its results.
  • The merged coverage job passed its recorded thresholds and reported project line coverage of 89.12%, branch coverage of 79.60%, and patch coverage of 91.21%. The job warned that some changed C# files were absent from the coverage report, so its patch percentage is incomplete. In the Windows net10.0 PackML shard, model, server, and client line coverage was 84.95%, 94.44%, and 94.55%, respectively. These figures do not establish a comparison with the current master branch.
Hosted test commands and results

These are the runner's dotnet test arguments, with quotes added around arguments containing spaces or shell operators. The commands use hosted runner paths and are not local-solution runs.

Windows net10.0 isolated PackMLObjects diagnostic on 32ff1f21, one failed:

dotnet test 'tests\Opc.Ua.PackML.Tests\Opc.Ua.PackML.Tests.csproj' --no-restore --configuration Debug --framework net10.0 -p:CustomTestTarget=net10.0 -m:1 -nr:false --filter 'FullyQualifiedName~StandaloneUnitIsOrganizedBelowPackMLObjectsAsync' --logger 'trx;LogFileName=packml-folder.trx' --results-directory 'D:\temp\packml-folder-results' --blame-hang-timeout 2m

Windows net48 PackML, 220 passed:

dotnet test tests/Opc.Ua.PackML.Tests/Opc.Ua.PackML.Tests.csproj --no-build --configuration Release --framework net48 /p:CustomTestTarget=net48 --logger trx --results-directory D:\a\UA-.NETStandard\UA-.NETStandard\TestResults\Opc.Ua.PackML.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini --filter 'TestCategory!=LongRunning&TestCategory!=Stress'

Windows net10.0 PackML, 220 passed:

dotnet test tests/Opc.Ua.PackML.Tests/Opc.Ua.PackML.Tests.csproj --no-build --configuration Release --framework net10.0 /p:CustomTestTarget=net10.0 --logger trx --results-directory D:\a\UA-.NETStandard\UA-.NETStandard\TestResults\Opc.Ua.PackML.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini /p:CollectCoverage=true '--collect:XPlat Code Coverage' --settings ./tests/coverlet.runsettings.xml --filter 'TestCategory!=LongRunning&TestCategory!=Stress'

Linux net10.0 PackML, 220 passed:

dotnet test tests/Opc.Ua.PackML.Tests/Opc.Ua.PackML.Tests.csproj --no-build --configuration Release --framework net10.0 /p:CustomTestTarget=net10.0 --logger trx --results-directory /home/runner/work/UA-.NETStandard/UA-.NETStandard/TestResults/Opc.Ua.PackML.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini /p:CollectCoverage=true '--collect:XPlat Code Coverage' --settings ./tests/coverlet.runsettings.xml --filter 'TestCategory!=LongRunning&TestCategory!=Stress'

macOS net10.0 PackML, 220 passed:

dotnet test tests/Opc.Ua.PackML.Tests/Opc.Ua.PackML.Tests.csproj --no-build --configuration Release --framework net10.0 /p:CustomTestTarget=net10.0 --logger trx --results-directory /Users/runner/work/UA-.NETStandard/UA-.NETStandard/TestResults/Opc.Ua.PackML.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini /p:CollectCoverage=true '--collect:XPlat Code Coverage' --settings ./tests/coverlet.runsettings.xml --filter 'TestCategory!=LongRunning&TestCategory!=Stress'

Windows net48 Server node management, 11 failed, 3,104 passed, one skipped:

dotnet test tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj --no-build --configuration Release --framework net48 /p:CustomTestTarget=net48 --logger trx --results-directory D:\a\UA-.NETStandard\UA-.NETStandard\TestResults\Opc.Ua.Server.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini --filter 'TestCategory!=LongRunning&TestCategory!=Stress&FullyQualifiedName!~Opc.Ua.Server.Tests.NodeManager.NodeManagerLifecycleTests.Prepared&FullyQualifiedName!~Opc.Ua.Server.Tests.NodeManager.NodeManagerLifecycleTests.&(FullyQualifiedName~NodeManager|FullyQualifiedName~SamplingGroup|FullyQualifiedName~SamplingInterval|FullyQualifiedName~NodeState|FullyQualifiedName~MonitoredNode)'

Windows net48 Server node lifecycle, two failed, 467 passed:

dotnet test tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj --no-build --configuration Release --framework net48 /p:CustomTestTarget=net48 --logger trx --results-directory D:\a\UA-.NETStandard\UA-.NETStandard\TestResults\Opc.Ua.Server.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini --filter 'TestCategory!=LongRunning&TestCategory!=Stress&FullyQualifiedName!~Opc.Ua.Server.Tests.NodeManager.NodeManagerLifecycleTests.Prepared&(FullyQualifiedName~Opc.Ua.Server.Tests.NodeManager.NodeManagerLifecycleTests.)'

Windows net10.0 Server, 13 failed, 10,985 passed, six skipped:

dotnet test tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj --no-build --configuration Release --framework net10.0 /p:CustomTestTarget=net10.0 --logger trx --results-directory D:\a\UA-.NETStandard\UA-.NETStandard\TestResults\Opc.Ua.Server.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini /p:CollectCoverage=true '--collect:XPlat Code Coverage' --settings ./tests/coverlet.runsettings.xml --filter 'TestCategory!=LongRunning&TestCategory!=Stress'

Linux net10.0 Server, 13 failed, 10,863 passed, 10 skipped:

dotnet test tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj --no-build --configuration Release --framework net10.0 /p:CustomTestTarget=net10.0 --logger trx --results-directory /home/runner/work/UA-.NETStandard/UA-.NETStandard/TestResults/Opc.Ua.Server.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini /p:CollectCoverage=true '--collect:XPlat Code Coverage' --settings ./tests/coverlet.runsettings.xml --filter 'TestCategory!=LongRunning&TestCategory!=Stress'

macOS net10.0 Server node management, 11 failed, 3,104 passed, one skipped:

dotnet test tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj --no-build --configuration Release --framework net10.0 /p:CustomTestTarget=net10.0 --logger trx --results-directory /Users/runner/work/UA-.NETStandard/UA-.NETStandard/TestResults/Opc.Ua.Server.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini /p:CollectCoverage=true '--collect:XPlat Code Coverage' --settings ./tests/coverlet.runsettings.xml --filter 'TestCategory!=LongRunning&TestCategory!=Stress&FullyQualifiedName!~Opc.Ua.Server.Tests.NodeManager.NodeManagerLifecycleTests.Prepared&FullyQualifiedName!~Opc.Ua.Server.Tests.NodeManager.NodeManagerLifecycleTests.&(FullyQualifiedName~NodeManager|FullyQualifiedName~SamplingGroup|FullyQualifiedName~SamplingInterval|FullyQualifiedName~NodeState|FullyQualifiedName~MonitoredNode)'

macOS net10.0 Server node lifecycle, two failed, 467 passed:

dotnet test tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj --no-build --configuration Release --framework net10.0 /p:CustomTestTarget=net10.0 --logger trx --results-directory /Users/runner/work/UA-.NETStandard/UA-.NETStandard/TestResults/Opc.Ua.Server.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini /p:CollectCoverage=true '--collect:XPlat Code Coverage' --settings ./tests/coverlet.runsettings.xml --filter 'TestCategory!=LongRunning&TestCategory!=Stress&FullyQualifiedName!~Opc.Ua.Server.Tests.NodeManager.NodeManagerLifecycleTests.Prepared&(FullyQualifiedName~Opc.Ua.Server.Tests.NodeManager.NodeManagerLifecycleTests.)'

Linux net10.0 WoT sample-core: first attempt stopped after 64 passed; same-head retry passed 72:

dotnet test tests/Opc.Ua.WotCon.Samples.Tests/Opc.Ua.WotCon.Samples.Tests.csproj --no-build --configuration Release --framework net10.0 /p:CustomTestTarget=net10.0 --logger trx --results-directory /home/runner/work/UA-.NETStandard/UA-.NETStandard/TestResults/Opc.Ua.WotCon.Samples.Tests --blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash --blame-crash-dump-type mini /p:CollectCoverage=true '--collect:XPlat Code Coverage' --settings ./tests/coverlet.runsettings.xml --filter 'TestCategory!=LongRunning&TestCategory!=Stress&FullyQualifiedName!~Opc.Ua.WotCon.Samples.Tests.WotSampleEndToEndTests.RealSamplesAggregateSubscribeAndReplaceGenerationAsync&FullyQualifiedName!~Opc.Ua.WotCon.Samples.Tests.WotPumpAddressSpaceComparisonTests.WotPumpInstanceMatchesNativePumpSubsetAsync&FullyQualifiedName!~Opc.Ua.WotCon.Samples.Tests.WotPumpAddressSpaceComparisonTests.CompanionTypeDefinitionsMatchNativePumpServerAsync'

Related Issues

Checklist

  • I have signed the CLA and read the CONTRIBUTING doc.
  • I have added tests that prove my fix is effective or that my feature works and increased code coverage.
  • I have added all necessary documentation.
  • I have verified that my changes do not introduce (new) build or analyzer warnings.
  • If this PR changes C# source files, I ran all tests locally using the UA.slnx solution against at least .NET Framework and .NET 10, and all passed. PRs changing only non-C# files do not require these .NET test runs.
  • I fixed all failing and flaky tests in the CI pipelines and all CodeQL warnings.
  • I have addressed all PR feedback received.

Implement configurable modes, administration, fluent hosting, simulated sample and regression tests. Track completion in #4964. Server net10 build is verified; client/test execution and full validation remain pending.
Remove the cross-owner admission lease and execute complete operations inside the lifecycle owner. Reject same-owner asynchronous callback reentry before admission, including shutdown, and add deterministic regression scenarios. Validation awaits an individually cleared shared-host slot.
Complete the unit create lifecycle before the controller publishes its
first state so state NodeIds use the PackML namespace that OnAfterCreate
selects. Register PackML encodeable types in the node manager so method
arguments decode to typed structures. Add the PackML namespace to the
test context, and expect BadNotExecutable for non-executable wire
commands as the Call service reports.
…dard into marcschier-packml-full-support

# Conflicts:
#	docs/Profiles.md
Copilot AI balanced review requested due to automatic review settings November 5, 2026 07:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical issues risk unauthorized administration access, incomplete or inconsistent shutdown, and lost timed transitions, while missing assembly attributes cause analyzer-enabled build failures.

5 open issues
What changed in this PR

Adds standalone OPC 30050 PackML hosting and typed clients alongside the existing Scales and Lens compositions. It also extends state-machine infrastructure with native asynchronous transition delivery. PackML remains Partial, with execution evidence and architectural sign-off pending.

Changes:

  • Adds provider-backed runtime composition, configurable modes, administration accounting and client APIs.
  • Adds async transition coordination, hierarchical synchronization and lifecycle notification handling.
  • Adds a simulated client/server sample, regression coverage, package registration and documentation.
File Description
UA.slnx Registers PackML projects, tests and sample.
tests/​Opc.Ua.Server.TestFramework/​MonitoredNodeSamplingFence.cs Adds a notification-drain test helper.
tests/​Opc.Ua.Scales.Tests/​ScalesNodeManagerTests.cs Adds controller compatibility and publication regressions.
tests/​Opc.Ua.PackML.Tests/​PackMLTestSupport.cs Adds provider, clock and persistence test doubles.
tests/​Opc.Ua.PackML.Tests/​PackMLStateMachineControllerTests.cs Covers async delivery, admission and customization.
tests/​Opc.Ua.PackML.Tests/​PackMLAdministrationTests.cs Covers timers, persistence, counters and validation.
tests/​Opc.Ua.PackML.Tests/​Opc.Ua.PackML.Tests.csproj Defines the PackML test project.
tests/​Opc.Ua.Aot.Tests/​PackMLAotTests.cs Adds NativeAOT codec, runtime and factory coverage.
tests/​Opc.Ua.Aot.Tests/​Opc.Ua.Aot.Tests.csproj References PackML assemblies for AOT tests.
src/​Opc.Ua.Server/​StateMachines/​StateMachineBuilder.cs Adds async hierarchy and lifecycle coordination.
src/​Opc.Ua.Server/​StateMachines/​FluentFiniteStateMachineState.cs Adds native async transitions and suspension handling.
src/​Opc.Ua.Server/​Fluent/​IStateMachineBuilder.cs Adjusts XML documentation references only.
src/​Opc.Ua.PackML/​NugetREADME.md Links standalone PackML guidance.
src/​Opc.Ua.PackML.Server/​PackMLUnitOptions.cs Defines and validates unit configuration.
src/​Opc.Ua.PackML.Server/​PackMLServerOptions.cs Configures hosted units and startup callbacks.
src/​Opc.Ua.PackML.Server/​PackMLRuntime.cs Composes units and manages runtime shutdown.
src/​Opc.Ua.PackML.Server/​PackMLProvider.cs Defines equipment requests and provider contracts.
src/​Opc.Ua.PackML.Server/​PackMLNodeManager.cs Hosts the model and standalone units.
src/​Opc.Ua.PackML.Server/​PackMLLifetime.cs Serializes operations and coordinates shutdown.
src/​Opc.Ua.PackML.Server/​Opc.Ua.PackML.Server.csproj Defines the server package.
src/​Opc.Ua.PackML.Server/​NugetREADME.md Describes hosting and equipment completion.
src/​Opc.Ua.PackML.Server/​Hosting/​OpcUaPackMLServerBuilderExtensions.cs Adds fluent server registration.
src/​Opc.Ua.PackML.Server/​Administration/​PackMLAdministrationData.cs Defines administration and persistence contracts.
src/​Opc.Ua.PackML.Server/​Administration/​PackMLAdministration.cs Implements administration projection and timer accounting.
src/​Opc.Ua.PackML.Client/​Properties/​AssemblyInfo.cs Declares client assembly CLS compliance.
src/​Opc.Ua.PackML.Client/​PackMLValue.cs Represents typed values and discovery results.
src/​Opc.Ua.PackML.Client/​PackMLSnapshots.cs Defines status and administration read snapshots.
src/​Opc.Ua.PackML.Client/​PackMLFields.cs Adds typed field paths and decoders.
src/​Opc.Ua.PackML.Client/​PackMLClientFactory.cs Creates clients over borrowed sessions.
src/​Opc.Ua.PackML.Client/​PackMLClient.cs Implements discovery, reads and observation.
src/​Opc.Ua.PackML.Client/​PackMLClient.Commands.cs Routes commands through generated proxies.
src/​Opc.Ua.PackML.Client/​Opc.Ua.PackML.Client.csproj Defines the client package.
src/​Opc.Ua.PackML.Client/​NugetREADME.md Summarizes client capabilities and ownership.
src/​Opc.Ua.PackML.Client/​Hosting/​OpcUaPackMLClientBuilderExtensions.cs Registers the typed-client factory.
src/​Opc.Ua.Core.Types/​Opc.Ua.Core.Types.csproj Grants internal access to PackML and core tests.
samples/​README.md Lists the PackML sample.
samples/​PackML/​README.md Documents sample execution and security boundaries.
samples/​PackML/​PackMLSample/​SampleEquipment.cs Implements simulated equipment behavior.
samples/​PackML/​PackMLSample/​Program.cs Demonstrates hosting and typed-client operations.
samples/​PackML/​PackMLSample/​PackMLSample.csproj Defines the sample application.
README.md Introduces standalone PackML support.
docs/​StateMachines.md Documents native async transition semantics.
docs/​Scales.md Clarifies standalone versus Scales composition.
docs/​README.md Adds the PackML guide entry.
docs/​Profiles.md Updates PackML capabilities while retaining Partial status.
.azurepipelines/​expected-packages.txt Adds expected client and server packages.

Review effort: Balanced

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Code coverage

✅ Coverage gate passed.

Check Result Threshold
✅ Project line rate 89.20% (495887/555909 lines) >= 70.00%
✅ Project branch rate 79.68% >= 60.00%
✅ Patch coverage 91.21% (3020/3311 changed lines) >= 75.00% (> 100 changed lines)
ℹ️ Baseline delta (advisory) +15.60 pp 73.60% recorded
Uncovered changed lines
  • src/Opc.Ua.PackML.Server/PackMLRuntime.cs: 214, 216, 217, 226, 228, 229, 236, 297
  • src/Opc.Ua.Types/Nodes/TypeTable.cs: 861, 880
  • src/Opc.Ua.Server/NodeManager/AsyncCustomNodeManager.cs: 704, 742, 766, 779, 780, 1593, 1595, 1597, 8319, 8320, 8451, 8469
  • src/Opc.Ua.PackML.Server/PackMLUnitOptions.cs: 142, 151, 160, 166, 174, 219, 221, 227
  • src/Opc.Ua.PackML.Server/Hosting/OpcUaPackMLServerBuilderExtensions.cs: 49, 64, 68
  • src/Opc.Ua.PackML.Server/Administration/PackMLAdministration.cs: 52, 95, 99, 200, 243, 247, 260, 337, 385, 399, 423, 443
  • src/Opc.Ua.PackML.Client/PackMLClient.cs: 100, 105, 133, 177, 272, 293, 297, 301, 315, 316, 323, 341, 365, 371, 400, 422, 452
  • src/Opc.Ua.PackML.Server/PackMLNodeManager.cs: 112
  • src/Opc.Ua.PackML.Server/PackMLServerOptions.cs: 55, 57, 59, 61, 63, 64, 74, 75, 76, 92
  • src/Opc.Ua.Server/StateMachines/StateMachineBuilder.cs: 940, 941, 942, 944, 946, 949, 951, 952, 953, 955, 958, 960, 964, 965, 967, 998, 1000, 1001, 1002, 1948, 1949, 1953, 1989, 1990, 1991, 1992, 1996, 1997, 2000, 2002, 2003, 2008, 2009, 2010, 2012, 2013, 2019, 2166, 2168, 2174, 2176, 2177, 2182, 2184, 2187, 2188, 2189, 2193, 2195, 2201, 2203, 2204, 2218, 2231, 2233, 2234, 2244, 2245, 2246, 2248, 2249, 2250, 2388, 2395, 2397, 2398, 2429, 2443
  • src/Opc.Ua.PackML.Server/PackMLUnit.cs: 202, 206, 210, 260, 262, 263, 313, 317, 322, 323, 459, 585, 613, 653, 869
  • src/Opc.Ua.Server/NodeManager/MasterNodeManager.cs: 442, 444, 445, 976, 977, 987, 988, 1004, 1005, 1018, 1101, 1129, 1131, 1132, 1134, 1160, 1161, 1207, 1259, 1289, 1291, 1292, 1294, 1295, 1297, 1298, 1302, 1305, 1306, 1307, 1308, 1309, 1311, 1350, 1351, 1359, 1377, 1379, 1388, 1397, 1405, 1445, 1452, 1464, 1467, 1469, 1470, 1496, 1504, 1513, 1514, 1622, 1678, 1701, 1728, 1764, 1772, 1776, 1797, 1801
  • src/Opc.Ua.PackML/PackMLStateMachineController.cs: 300, 301, 302, 317, 318, 319, 320, 321, 338, 339, 340, 347, 351, 352, 353, 358, 359, 363, 504, 505, 506, 593, 674, 769, 770, 771, 775, 799, 1050, 1159, 1264, 1404, 1420, 1665, 1748
  • src/Opc.Ua.Server/StateMachines/FluentFiniteStateMachineState.cs: 125, 126, 151, 170, 188, 190, 192, 193, 207
  • src/Opc.Ua.PackML.Server/PackMLLifetime.cs: 47, 95, 111, 115, 141, 167, 171, 324, 326, 332, 334
  • src/Opc.Ua.PackML.Client/PackMLClient.Commands.cs: 107, 162, 163, 164, 165, 166, 276
  • src/Opc.Ua.Types/Utils/NodeReferencesReservedException.cs: 56, 58, 66, 68
  • src/Opc.Ua.Server/NodeManager/Lifecycle/ChangePreparer.cs: 856, 857, 897, 902, 904, 920, 1068, 1095, 1193

Coverage is above the recorded baseline - consider ratcheting coverage-thresholds.json.

Thresholds live in coverage-thresholds.json. Whole report before exclusions: line 88.53%, branch 79.03%.

@CLAassistant

CLAassistant commented Nov 5, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical issues remain: the default localhost endpoint can expose anonymous equipment commands beyond loopback while accepting untrusted certificates, and callback-triggered disposal can leave the runtime partially shut down and permanently unable to add units.

2 open issues
5 resolved since last review

Review effort: Balanced

Comment thread samples/PackML/PackMLSample/Program.cs Resolved
A WoT mutation that holds admission or a decision window can await a node
deletion on another flow. Deletion now removes a published owner's serving
references without waiting and queues contribution pruning for the next
admission holder or publication callback. Adds a facade-matrix regression
that deletes a PackML unit from a decision callback.
…drains

Queue contribution pruning before any await, retry serving removals rejected by a source node reserved for a pending publication, and drain both queues in the background once the decision window closes so retired owners are released. Adds a facade-matrix regression for reserved source references.
…rain

A dedicated NodeReferencesReservedException separates reserved-source rejections from other provider failures. A non-reservation failure withdraws the pending contribution prune, or queues the unremoved references when publication already applied it. The drain clears its scheduled flag on every exit, keeps failed retries queued, and publication restarts it. Adds regressions for an unrelated provider failure and a drain fault.
A deletion or publication that requests a drain while one is running records the request. The running drain then makes another pass instead of stopping after a faulted pass, and an exit through an unexpected exception starts a new drain for the recorded request.
Avoid CA1508 on the nullable retry accumulator assigned only in catch blocks by creating the collection eagerly and checking its count. No analyzer suppression is added.

Add a barrier-controlled regression that pauses a drain retry, completes another deletion while admission is held, and then faults the paused retry. Assert that the recorded request causes a second attempt and removes the retained reference without any further mutation. Local .NET validation remains on hold.
Retain type registration identities across publication and retry removals after the decision. Cover adapted source admission and the exact reservation exception.
…ull-support

# Conflicts:
#	tests/Opc.Ua.Aot.Tests/Opc.Ua.Aot.Tests.csproj
@marcschier
marcschier marked this pull request as draft November 8, 2026 09:16
@marcschier
marcschier marked this pull request as ready for review November 8, 2026 13:13
…ull-support

# Conflicts:
#	tests/Opc.Ua.Aot.Tests/Opc.Ua.Aot.Tests.csproj

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical source-identity checks can reject valid facade-bound events and let emitters bypass hidden-facade gates, while the full PackML support claim lacks required executable conformance evidence.

2 open issues

Review effort: Balanced

for (int ii = 0; ii < routing.NodeManagers.Length; ii++)
{
IAsyncNodeManager facade = routing.NodeManagers[ii];
if (!ReferenceEquals(NodeManagerGenerationRegistry.GetIdentity(facade), resource))
Comment thread docs/Profiles.md Resolved
marcschier added a commit that referenced this pull request Nov 9, 2026
# Description

_Describe the changes here to communicate to the maintainers why they
should accept this pull request. By default - this will become the
Commit message after merging and thus define history._

Extend OPC 40200 Weighing Technology through the existing Scales
runtime, typed client, fluent builders, DI/direct construction, and
samples. Catchweigher and price-labeler processing accepts
equipment-acquired items and equipment-supplied or injectable prices.
Totalizing-hopper completed fills update statistics and TipCounter.
Analog and Boolean-edge recipe waits are opt-in. Ordinary
hopper/checkweigher behavior, manual recipes, PackML, source quality,
and product locks remain supported. Physical sorter, printer and motor
operation, fiscal certification, and optional MCP/UA Lens additions are
excluded.

**Support remains Partial. Do not merge.** Published successor
`ce01effa15cea555c31561d4ab59d39948d6b19b` includes the reviewed
four-file FileSystem lifecycle correction
(`849223eda7ae03d500825dc3cc49183b1285eb46`) and merges current master
`ab5fddad9ab8ba162f10766b0e685c882db31ba9`. [Exact-head CI
42531450874](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42531450874)
completed successfully on this commit, including the code-coverage job.
The matched master-to-ce01 coverage comparison still shows decreases in
the Scales.Server and Scales.Client components; see the coverage results
below. A separate scoped recovery patch remains unrun and unmeasured,
and is not part of this PR head. The existing ready state and merge
settings are unchanged. The retained 299-line notification diagnostic
block is neither committed nor pushed and is not treated as a regression
suite for the selected ordinary-notification policy. The unapproved
FileSystem documentation paragraph is excluded.

**FileSystem lifecycle correction.** Session close previously marked an
idle writer closing while deferred cleanup retained its write
reservation. FileTypeBinder now starts idle memory-stream cleanup
without provider-thread deferral. FileHandle signals completed
asynchronous open only after its linked provider token is detached; it
skips lifetime cancellation only for detached, idle asynchronous opens,
while synchronous compatibility, pending opens, active operations and
disposal retain cancellation. Active work keeps its reservation until it
drains. No synchronous provider callback is introduced into the
asynchronous path.

**Paired Windows candidate evidence.** [Green diagnostic
42529482112](https://github.com/marcschier/UA-.NETStandard/actions/runs/42529482112),
diagnostic head `9aea971fab7d4895306d5bce91060101a8bf8951` with
immutable source parent `4ef034ae635d636a1db3b3c72964bc2ef24ad1a2`,
passed `InlineSessionClosureWaitsForProviderTokenDetachmentAsync` 1/1 on
native Windows net48 and net10.0. Full
FileHandleLifetimeRegressionTests/FileTypeBinderLifetimeTests passed
53/53 net48 and 54/54 net10.0, with no fixture/RunInfo errors. [Red
diagnostic
42529488811](https://github.com/marcschier/UA-.NETStandard/actions/runs/42529488811),
diagnostic head `135523b6964029e75926eaa26206a03dcf074ef1` with source
`0734c09cff268288a94c6dbdd3fc16e68c53ee87`, failed 0/1 on each TFM at
the intended `Assert.That(stream.CanRead, Is.True)` assertion (actual
False), not a timeout or build failure. Both red TRXs and all four green
TRXs were independently inspected. These paired Windows candidate runs
are separate from the completed exact-ce01 CI listed above and do not
establish local full-solution validation.

**User-selected category policy:** preserve existing mixed-category
reporting and measured-only TotalPackagesWeighed totals; retain Partial
until category participation is clarified. OPC 40200
[§7.20.1](https://reference.opcfoundation.org/specs/OPC-40200/7.20.1)
and
[§7.20.3](https://reference.opcfoundation.org/specs/OPC-40200/7.20.3)
define Weighed as category participation, while
[§7.19.3](https://reference.opcfoundation.org/specs/OPC-40200/7.19.3)
permits rejections before or after weighing. The current dynamic Boolean
describes measurement completeness and cannot represent the measured
subset of a mixed category. No new split categories or
incompatible-report rejection is imposed. Ordinary enum-notification
reentry is preserved.

**Validation on immutable fa65 code head.** Opc.Ua.Scales.Tests passed
616/616, zero failed/skipped, on [Windows
net48](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42499377576/job/128792906071),
[Windows
net10.0](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42499377576/job/128792906131),
[Linux
net10.0](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42499377576/job/128792906205),
and [macOS
net10.0](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42499377576/job/128792909555),
excluding LongRunning and Stress. All ten
unit/currency/registered-reading ownership cases and six
unsupported-copy cases passed.

**Historical exact d6 outcome.** [CI
42513278502](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42513278502)
completed with failure on `d6e0a03f3fed85ac84a6e61f4382aaea36cc7024`.
Completed logs verify Scales 616 passed, 0 failed, 0 skipped on [Windows
net48](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42513278502/job/128830867436),
[Windows
net10.0](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42513278502/job/128830867459),
[Linux
net10.0](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42513278502/job/128830867805),
and [macOS
net10.0](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42513278502/job/128830870585).
The sole failed test shard, Linux job 128830870599, failed
`MachineVisionRuntimeTests.SharedFileBindingReleasesClosedSessionHandlesAsync(True)`
with `BadNotReadable`: the file was locked for writing. Vision recorded
712 passed, 1 failed, 1 skipped; aggregate summary 128863789556 also
failed. Both parameter cases passed on preceding fa65 Linux job
128792909544/TRX artifact 13627626176. Those differing outcomes alone do
not establish a cause; the separate lifecycle investigation reproduced
deferred cleanup retaining an idle writer reservation. The correction is
published in ce01; the integrated exact-head CI completed successfully
as linked above.

**Coverage on historical d6.** [Coverage job
128863789514](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42513278502/job/128863789514)
completed successfully and reported "Coverage is above the recorded
baseline" and "Coverage gate passed." Windows net10.0 Scales coverage
was 793/827 covered lines for Scales.Client (95.89%), 186/186 for Scales
(100%), and 6567/7021 for Scales.Server (93.53%). Line counts and branch
rates matched fa65; this comparison establishes no decrease across the
documentation successor, not against a pre-feature baseline. The passing
coverage gate does not change d6's failed overall result. Exact-ce01 CI
and matched component-coverage results are reported separately above;
local full-solution validation remains unrun.

**Matched Scales component coverage: master ab5 versus exact ce01.**
Master run 42530395411 (artifact 13640808392) compared with exact-ce01
run 42531450874 (artifact 13642293626) shows Scales.Server line coverage
decreasing from 3635/3833 (94.834%) to 6568/7021 (93.548%), while branch
coverage rises from 1474/1842 (80.022%) to 2962/3595 (82.392%).
Scales.Client line coverage decreases from 612/633 (96.682%) to 797/827
(96.372%), and branch coverage decreases from 214/273 (78.388%) to
263/341 (77.126%). Root combined coverage increased from 510227/576601
to 513513/580204 lines and from 219732/278244 to 221408/280233 branches;
that aggregate increase does not erase the component-level decreases.
The separate scoped regression recovery patch has not been run or
measured and does not qualify as restored Scales coverage.

**Overall fa65 CI failed.** macOS job 128792909513 failed
QuietSubscriptionAcknowledgementSurvivesConcurrentPublishesAsync(4):
BadPublishRequestCount was 1 instead of 0. A server BadTimeout was
recorded during that interval, but its relation to the counter increment
is unproven; the acknowledgement assertion passed. Separate
immutable-fa65 hosted controls passed 12/12 in run 42513134265, and an
instrumented full fixture passed 30/30 in run 42514537147. Neither
reproduced the failure. A traced BadNoSubscription/counter increment
occurred after a passing assertion during cleanup and does not explain
the original failure. The zero assertion is retained. This failure is
not attributed to weighing or dismissed as pre-existing.

Checkweigher reports commit selected-product and generic-scale statistic
caches before observers run. Synchronous observers remain inline before
asynchronous observers; exceptions propagate without rolling back
committed counts. Recorder initialization succeeds before caching, and
successful product removal retires captured associations without
independently retaining removed subtrees. Native nominal service writes
recompute GiveAway within writer admission and transfer admission to
derived-value notification delivery. Direct assignments remain
application-serialized and refresh derived values on the next report.

Sample deviation uses n-1; FullCheck uses n. Empty statistics and
one-item samples publish zero placeholders with BadNoData; singleton
FullCheck publishes computed zero with Good quality. GiveAway is
`(acceptedMean - currentNominalWeight) * acceptedCount`, including
negative results. Bad or uncertain nominal quality propagates. Infinite
inputs reject before counters change. Mixed measured/unmeasured
aggregates use the measured subset with UncertainSubNormal; overflow
retains the previous finite value with BadOutOfRange. The equations were
verified against the [VDMA 40200:2025-04
co-publication](https://www.vdma.eu/en/catalog-detail/-/catalog/14137),
identified as identical to OPC 40200 Release 2.00, sections 7.19.3 and
7.20.3. The PDF and excerpts are not redistributed.

Optional notification metadata includes AuxParameters, HelpSource and
VendorNotificationId with absent-versus-empty behavior. Accepted
lower-tolerance percentages use all accepted items, independently of
optional counter nodes; each report refreshes percentages. NaN items do
not increment TotalPackagesWeighed. Mixed-category Weighed remains the
documented conformance limitation under the selected compatibility
policy.

Correlated initialization, reset and acquisition publication rejects
same-flow nested writes with BadInvalidState rather than waiting for the
publisher. External asynchronous writers wait. Initialization failure
remains uncached and retryable before counting. Catchweigher
product-period reset includes zone counters, StartTime/ResetCondition
and percentages without resetting other products, scale totals or
acquisition sequence ownership. No UA Reset method is added.

**User-selected acquisition contract:** publication retains
setter-by-setter ordering. Catchweigher consumes the sequence before the
first output counter changes, or before product counting if no output
statistic exists. Totalizing hopper consumes it before TipCounter
changes. A late observer exception can leave partial published state,
suppresses WeightRegistered, and rejects same-sequence retry with
BadEntryExists without replaying counters. Early catchweigher LastItem
observer failures before counting remain retryable. Applications
reconcile partial state; no rollback or atomic acquisition snapshot is
promised.

**Ordinary enum notification reentry remains separate.** A write
originating in any active ordinary notification flow may run while
another callback is active; external writers wait. Preset notifications
remain inline after the preset lock is released, with CurrentProducts
before product subtrees and CurrentProductsChanged last. Exceptions
propagate and failed change masks are restored without undoing preset
mutation. No deferred peer-drain policy is implemented. The preserved
reentry behavior does not isolate writes from overlapping callbacks;
that limit and mixed-category Weighed retain the Partial rating.

Native async Value writes preserve async-handler precedence and sparse
enum validation. Unsupported custom/synchronous-only paths return
BadNotSupported without calling synchronous handlers or changing the
cache. UInt64 enum values above Int64.MaxValue reject before
callbacks/cache mutation, following the recommendation in [Part 8
section
5.3.3.4](https://reference.opcfoundation.org/specs/OPC-10000-8/v1.05.07/5.3.3.4);
the legacy synchronous fallback remains.

**Breaking change:** public WriteAttributeAsync is non-virtual.
Overrides move to protected WriteAttributeCoreAsync to run inside
admission and call the protected base hook rather than reentering the
public entrypoint. The user accepted this deviation from 1.5.378
compatibility; docs/MigrationGuide.md contains examples. Recipe starts
retain product reservations without controller locks; replacing a
pending release check, including A-to-B-to-A replacement, rejects start.
Without PackML, explicit application release or an allowing check is
required.

**Metadata ownership.** CopyUnit detaches the unit's LocalizedText
display name and description, and CopyCurrency detaches the currency
text, preserving locale and translation fallback. RegisteredReading
receives a separate engineering-unit value from the pending acquisition;
scalar registration is unchanged.
UnsupportedMetadataCopyDoesNotConsumeAcquisitionAsync covers unsupported
formatting arguments and comparers across unit, equipment-currency, and
provider-returned currency sources. All six cases passed:
BadNotSupported propagates before publication, counts remain zero, and
the same sequence with supported metadata counts once. Earlier 1e55
passed 600 compatibility cases and failed ten controls on all four
platforms: six failures demonstrated aliases, while four were
multilingual-fixture defects corrected explicitly with AsMultiLanguage.
The corrected multilingual cases are passing controls, not previously
established alias failures.

See docs/Scales.md and docs/Profiles.md for APIs, ownership, publication
and remaining limits. README/style changes from other sessions are
untouched.

## Related Issues

_Reference all GitHub issues this PR addresses. If there is no issue
yet, open one and link it here._

_If this is a relatively large or complex change, a design must have
been discussed in the related tracking issue and signed off (which
becomes the Architectural Decision Record (ADR))._

- Fixes #4969.
- Prerequisite #4960 is merged.
- Shared condition/alarm setters are reviewed in #4992 and the
PackML/FSM seam in #4995. Scales reuses ClearChangeMasksAsync rather
than duplicating those implementations.

## Checklist

_Put an `x` in the boxes that apply. You can complete these step by step
after opening the PR._

- [ ] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [ ] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [ ] I have added all necessary documentation.
- [ ] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] If this PR changes C# source files, I ran **all** tests locally
using the **UA.slnx** solution against at least .NET **Framework** and
.NET **10**, and all passed. PRs changing only non-C# files do not
require these .NET test runs.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.

## Validation commands

Candidate diagnostics used Windows Server 2025, Debug. For each
framework, the exact regression and full fixtures were separate
successful invocations in green run 42529482112:

- `& .\.github\scripts\run-dotnet-tests.ps1 -Projects
'tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj' -CustomTestTarget
'net48' -Framework 'net48' -Configuration Debug -Filter
'FullyQualifiedName~Opc.Ua.Server.Tests.FileSystem.FileHandleLifetimeRegressionTests.InlineSessionClosureWaitsForProviderTokenDetachmentAsync'
-HangTimeout '3m' -PerProjectTimeoutMinutes 10 -ResultsDirectory
'artifacts\vision-token\exact' -QuietOutput` — passed 1/1. Same command
on red run 42529488811 failed 0/1 at the intended stream.CanRead
assertion.
- `& .\.github\scripts\run-dotnet-tests.ps1 -Projects
'tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj' -CustomTestTarget
'net10.0' -Framework 'net10.0' -Configuration Debug -Filter
'FullyQualifiedName~Opc.Ua.Server.Tests.FileSystem.FileHandleLifetimeRegressionTests.InlineSessionClosureWaitsForProviderTokenDetachmentAsync'
-HangTimeout '3m' -PerProjectTimeoutMinutes 10 -ResultsDirectory
'artifacts\vision-token\exact' -QuietOutput` — passed 1/1. Same command
on red run 42529488811 failed 0/1 at the intended stream.CanRead
assertion.
- `& .\.github\scripts\run-dotnet-tests.ps1 -Projects
'tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj' -CustomTestTarget
'net48' -Framework 'net48' -Configuration Debug -Filter
'FullyQualifiedName~Opc.Ua.Server.Tests.FileSystem.FileHandleLifetimeRegressionTests|FullyQualifiedName~Opc.Ua.Server.Tests.FileSystem.FileTypeBinderLifetimeTests'
-HangTimeout '3m' -PerProjectTimeoutMinutes 10 -ResultsDirectory
'artifacts\vision-token\full' -QuietOutput` — passed 53/53.
- `& .\.github\scripts\run-dotnet-tests.ps1 -Projects
'tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj' -CustomTestTarget
'net10.0' -Framework 'net10.0' -Configuration Debug -Filter
'FullyQualifiedName~Opc.Ua.Server.Tests.FileSystem.FileHandleLifetimeRegressionTests|FullyQualifiedName~Opc.Ua.Server.Tests.FileSystem.FileTypeBinderLifetimeTests'
-HangTimeout '3m' -PerProjectTimeoutMinutes 10 -ResultsDirectory
'artifacts\vision-token\full' -QuietOutput` — passed 54/54.

The following exact commands appear in completed fa65 and d6 CI logs.
Their historical Scales results are not the exact-ce01 CI result linked
above and do not establish local full-solution validation.

- Windows net48: `dotnet test
tests/Opc.Ua.Scales.Tests/Opc.Ua.Scales.Tests.csproj --no-build
--configuration Release --framework net48 /p:CustomTestTarget=net48
--logger trx --results-directory
D:\a\UA-.NETStandard\UA-.NETStandard\TestResults\Opc.Ua.Scales.Tests
--blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash
--blame-crash-dump-type mini --filter
TestCategory!=LongRunning&TestCategory!=Stress` — fa65 passed 616/616,
4m40s; d6 passed 616/616, 4m40s.
- Windows net10.0: `dotnet test
tests/Opc.Ua.Scales.Tests/Opc.Ua.Scales.Tests.csproj --no-build
--configuration Release --framework net10.0 /p:CustomTestTarget=net10.0
--logger trx --results-directory
D:\a\UA-.NETStandard\UA-.NETStandard\TestResults\Opc.Ua.Scales.Tests
--blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash
--blame-crash-dump-type mini /p:CollectCoverage=true --collect:XPlat
Code Coverage --settings ./tests/coverlet.runsettings.xml --filter
TestCategory!=LongRunning&TestCategory!=Stress` — fa65 passed 616/616,
3m44s; d6 passed 616/616, 3m26s.
- Linux net10.0: `dotnet test
tests/Opc.Ua.Scales.Tests/Opc.Ua.Scales.Tests.csproj --no-build
--configuration Release --framework net10.0 /p:CustomTestTarget=net10.0
--logger trx --results-directory
/home/runner/work/UA-.NETStandard/UA-.NETStandard/TestResults/Opc.Ua.Scales.Tests
--blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash
--blame-crash-dump-type mini /p:CollectCoverage=true --collect:XPlat
Code Coverage --settings ./tests/coverlet.runsettings.xml --filter
TestCategory!=LongRunning&TestCategory!=Stress` — fa65 passed 616/616,
3m11s; d6 passed 616/616, 3m22s.
- macOS net10.0: `dotnet test
tests/Opc.Ua.Scales.Tests/Opc.Ua.Scales.Tests.csproj --no-build
--configuration Release --framework net10.0 /p:CustomTestTarget=net10.0
--logger trx --results-directory
/Users/runner/work/UA-.NETStandard/UA-.NETStandard/TestResults/Opc.Ua.Scales.Tests
--blame-hang-timeout 10m --blame-hang-dump-type mini --blame-crash
--blame-crash-dump-type mini /p:CollectCoverage=true --collect:XPlat
Code Coverage --settings ./tests/coverlet.runsettings.xml --filter
TestCategory!=LongRunning&TestCategory!=Stress` — fa65 passed 616/616,
14m36s; d6 passed 616/616, 17m11s.

Local full-solution commands `dotnet test UA.slnx
-p:CustomTestTarget=net48 -m:1` and `dotnet test UA.slnx
-p:CustomTestTarget=net10.0 -m:1` remain unrun. Admission attempts
either stopped before mutex acquisition because RAM was below 12 GiB, or
passed sustained memory checks but found the shared gate occupied on
nonblocking acquisition. No local .NET command or mutex waiter started.
Latest ce01 admission probe found 11.03 GiB available, below the
required floor. The local-solution checklist remains unchecked; passing
hosted candidate tests and historical coverage do not substitute for it.
No local full-suite, all-warning clearance, or passing overall ce01 CI
result is asserted.
@marcschier
marcschier marked this pull request as draft November 10, 2026 07:26

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants