Repository navigation
Report PA-DIM engineering metadata changes - #5029
Draft
marcschier wants to merge 22 commits into
Draft
marcschier wants to merge 22 commits into
marcschier wants to merge 22 commits into
Conversation
# Description Implements OPC 10000-21 registrar and device workflows, including ticket validation, pull and push provisioning, typed client and fluent host APIs, device lifecycle and reset, connected samples, and tests. Runtime-backed managed applications can expose independent Part 12 ConfigurationFile providers. The managers recover pending transactions before publishing applications. File operations and deferred apply or revert effects use each application's authorization and deployment lifetime. The typed client retains the namespace-URI application address across reconnect and confirms only the returned update identifier. Managed certificate selection uses the per-application type or the configured registrar default. The selected type must appear in the advertised group and be supported by the local authority before a CSR is created. The standard enrollment provider retains it throughout journal recovery. Legacy custom enrollment providers reject nondefault selections before registration or CSR creation. The managed-application verifier supports UA-TCP and HTTPS. HTTPS uses OS TLS trust and revocation or an exact TLS leaf pin, with hostname and validity checks on every handshake. It separately verifies the pinned OPC UA application certificate, expected application URI, and application proof before sending user credentials. The TLS terminator is part of the trust boundary; legacy application signatures do not cryptographically bind it. The optional external-authentication handoff accepts an externally installed DCA certificate through an injectable provider. The default provider validates a dedicated managed CA trust list and exact ProductInstanceUri and application-URI approval before entering the shared registrar lifecycle. Typed external pull skips ProvideIdentities. Registrar push retains external evidence through enrollment recovery without fabricating a ticket. Ticket checkpoints remain version 1; external-only checkpoints use version 2. This PR adds no FDO SDK dependency or FDO protocol implementation. Device authentication, TO0/TO1/TO2, ownership vouchers, service-info/fdo.csr exchange, and initial credential installation remain external. The external service must arrange credential trust with the deployment's Registrar, SoftwareUpdateManager, and CertificateManager. No FDO interoperability result is asserted. **Open integration gap:** Part 22 Resources support from #4990 is merged, but the connected Part 21 regression finds two `0:ProvisionableDevice` references: the standard `i=29878` and the onboarding manager's custom instance. The standard node is owned by the diagnostics manager. A lifecycle-aware binding must preserve generation-specific routing and references across publication, replacement, cancellation, and retirement. Part 21 remains `Partial` until this integration works. Shared Part 12/20 ConfigurationFile transfer and open-handle limitations also remain. ### Focused CI repairs and validation The certificate-manager ownership changes and cancellation handling at `af0abdd44` have not been locally validated. Shared application configurations still need a manager-lifetime fix. The trust-list partial-write fix at `b1aa6c17c` passed 16 focused tests before the subsequent ownership changes. The macOS WoT integration shard split at `ae1862881` was checked against recorded selectors, but the new shards' duration and the C# matrix tests are unverified. The subscription readiness change at `2f516afe9` is also unverified. The following earlier run at `c673ee6cf06504a9badc1ebae9efb1296f1943dc` used `TEMP` and `TMP` set to `D:\temp`, under `Local\OpcUaSpecSupportBuildGate`: ```powershell dotnet test tests\Opc.Ua.Gds.Tests\Opc.Ua.Gds.Tests.csproj -f net10.0 -p:CustomTestTarget=net10.0 -m:1 --no-restore --filter 'FullyQualifiedName~Onboarding|FullyQualifiedName~ManagedApplicationPushTests' --logger 'trx;LogFileName=onboarding-final.trx' --results-directory D:\temp\onboarding-4998 ``` **Passed:** 1,291 tests, zero failed or skipped, exit code 0. The TRX reported no nonpassing counters or fixture setup or teardown failures. This result predates the changes listed above and does not validate the current head. Coverage has not been measured. The full local `UA.slnx` net48 and net10.0 test runs have not been completed. Local builds and tests are paused because shared-host memory is below the agreed threshold. The SDK 10 VSTest runner also has a known incompatibility with the three TUnit AOT projects; a different runner would not satisfy the checklist's exact command requirement. Hosted CI is in progress. ## Related Issues - Relates to #4973; this reference does not close the tracking issue while documented gaps remain. - Part 22 Resources dependency [#4990](#4990) merged to master at `bc91e23725f6ba05b6e20639c5b74b960dc85160`. ## 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.
Code coverage✅ Coverage gate passed.
Uncovered changed lines
Coverage is above the recorded baseline - consider ratcheting Thresholds live in |
# Description Since #4982, about half of master CI runs fail in `test-macos-net10.0 (17/18) - wot-other-integration`. The tests don't hang. The leg runs `Opc.Ua.WotCon.Tests` with `TestCategory=Integration`, excluding `Materialization`, sequentially, and the 45-minute per-project ceiling (`$PerProjectTimeoutMinutes`) kills it while tests are still passing. Each live test creates new RSA, P256 and P384 certificates, which is slow on macOS. Measured macOS test time per class (TRX of passing run 42394584570 on a1a3d48, 385 tests, 2486 s test time): | Class | Tests | Seconds | |---|---:|---:| | WotLegacyNativeAdmissionLiveTests | 123 | 615 | | WotRegistryIdentityLiveTests(False) | 57 | 551 | | WotRegistryIdentityLiveTests(True) | 57 | 491 | | WotRegistryProjectionLiveTests | 66 | 403 | | WotSelectedDependenciesLiveTests | 24 | 131 | | WotConfiguredOptionsTests | 21 | 118 | | everything else | 37 | ~140 | #4991 moved `WotRegistryIdentityLiveTests` into `wot-other-identity-integration`. On its own master run (42476750357), the remaining `wot-other-integration` still took **1782 s (29.7 min) of test time plus 856 s of build**: 271 tests, with `WotLegacyNativeAdmissionLiveTests` at 816 s. That leaves little margin on a slow runner. This PR moves `Opc.Ua.WotCon.Tests.WotLegacy*` (`WotLegacyNativeAdmissionLiveTests`, `WotLegacyTypeBindingLiveTests`, `WotLegacyMaterializationLiveTests`) into a new macOS-only entry, `wot-other-legacy-integration`. Windows, Linux and net48 are unchanged. Expected macOS test time per entry, from the 42476750357 TRX (the a1a3d48 numbers are in parentheses): | Entry | Tests | Expected | |---|---:|---:| | wot-other-integration | 144 | ~14 min (~13 min) | | wot-other-identity-integration | 114 | ~17–20 min (17.4 min) | | wot-other-legacy-integration | 127 | ~14 min (10.6 min) | ## Verification - `dotnet test --list-tests` on each filter: original = 385, and other 144 + identity 114 + legacy 127 = 385. The unique-name union equals the original set, and no name appears in two parts. - `get-ci-matrix.ps1`: 102 PR entries and 210 full entries, both under the 256 limit. The macOS WotCon entries are now `wot-materialization-core`, `-integration`, `-live-events`, `wot-other-core`, `wot-other-integration`, `wot-other-identity-integration` and `wot-other-legacy-integration`. - `CiMatrixScriptTests` (35 tests) pass, extended to require the new shard and to check that each `WotLegacy*` class is routed to exactly one shard. I didn't add per-fixture certificate caching: it would change the setup of every live test, which goes beyond this CI fix. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
marcschier
marked this pull request as ready for review
November 8, 2026 19:39
marcschier
marked this pull request as draft
November 8, 2026 19:42
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
Targeted PA-DIM results cover the regression, but required full-solution validation for net48 and net10.0 remains unrun, leaving cross-component validation outstanding.
No open issues 🎉
What changed in this PR
This PR updates PA-DIM analog bindings to report engineering metadata changes after registration, allowing clients to receive semantic-change notifications while preserving initial materialization behavior.
Changes:
- Report
EngineeringUnitsandEURangechanges through the node manager’s existing property-change handling. - Extend the client/server regression to verify semantic-change events identify the affected measurement for both range and unit updates.
| File | Description |
|---|---|
tests/Opc.Ua.PADIM.Tests/PadimClientServerTests.cs |
Adds event subscriptions and assertions for post-registration range and unit changes. |
src/Opc.Ua.PADIM.Server/PadimValueBinding.cs |
Captures previous metadata values and reports property changes for registered analog variables. |
Review effort: Balanced
…led projections) (#5005) Part of #5003: fewer client bytes per event notification. ## Changes **1. Types: reuse repeated short strings in `BinaryDecoder.ReadString`** (net6+) Every event of a Publish response carries the same `SourceName`, and real event sources usually repeat the message text and locale too. Requests repeat the identifiers of string node ids. The decoder allocated a new string each time. `DecodedStringCache` is a per-thread, direct-mapped cache with 128 entries for strings of at most 32 UTF-8 bytes. It returns the instance decoded last for the same characters, and only after comparing them, so the decoded value never changes. Invalid UTF-8 gets the same replacement characters as before. A miss costs one hash of the decoded characters on top of the allocation. netstandard2.0 and net48 keep the existing path. **2. Client: rent the notification projection when notifications are pooled** With `PoolNotifications` on, the V2 `Subscription` already recycled `MonitoredItemNotification` and `EventFieldList` after the handler returns. It still allocated the `DataValueChange[]` / `EventNotification[]` projection passed to `ISubscriptionNotificationHandler` for every message. For events, the recycled `EventFieldList` shell is small, so pooling did not reduce event allocation at all (table below). The projection is now rented from `ArrayPool<T>.Shared` and returned, cleared, after the handler returns, at the same point where the payload is recycled. Whether to pool is read once per dispatch. The pooled-mode contract already said handlers must copy the values they retain. The docs of `PoolNotifications`, `DataValueChange` and `EventNotification` now say explicitly that this includes the memory itself; copying the structs out stays safe. The whole-message path (`ISubscriptionNotificationMessageHandler`) is unchanged: its `SubscriptionNotificationMessage` may be kept by handlers. ## Results Paired harness runs alternating master 621c7f5 and this branch, 3 rounds; runs with competing load on the host were discarded. Scenario: `events`, 10 sessions × 15 subscriptions, 1000 events/s requested, encrypted, Server GC on both sides. The server is the same build on both sides. | Client bytes per notification | master | this PR | |---|---:|---:| | events, managed client | 484–490 | 409–411 (−16 %) | | events, classic client | 460–463 | 385–391 (−16 %) | | events, managed client, `--pool-notifications 1` | 468–469 | **350–352 (−25 %)** | | data change 10 × 15 × 600, `--pool-notifications 1` | 143–199 | 139 | - Client CPU per notification is unchanged (within noise). - Read 1 / Read 100 / Write 100 and the unpooled data change line show no change in client or server bytes, or in CPU beyond run-to-run noise. The harness server's event `Message` contains a counter (`Load event N`), so here only `SourceName` repeats. Event sources with templated messages save more. Neither change removes the Workstation GC limit described in #5003: the in-flight notifications are still larger than the default gen0 budget. They lower the allocation rate that drives it. ## Tests - New `BinaryDecoderTests`: - distinct strings (including colliding cache slots), both sides of the 32-byte limit, multi-byte and invalid UTF-8, and zero-terminated input all decode exactly as `Encoding.UTF8.GetString` does; - repeated short strings share one instance; long ones do not. - New `SubscriptionTests.PooledNotificationMemoryIsReturnedAfterHandlerAsync`: with pooling, the memory is cleared after the handler returns while values the handler copied stay valid. Without pooling, the memory stays intact. - net10.0 runs: `Opc.Ua.Types.Tests` 13,971 passed; `Opc.Ua.Core.Encoders.Tests` 2,947 passed; `Opc.Ua.Client.Tests` 3,635 passed, 2 skipped. - `Opc.Ua.Types` and `Opc.Ua.Client` build for all target frameworks. net48 tests were not run locally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Marc Schier <marcschier@users.noreply.github.com>
…ghtly sample-core debug hang) (#5027) ## Summary The nightly `sample-core` net10.0-debug legs (Windows and Linux) crash with a blame hang dump in `WotSampleEndToEndTests.BadTargetMappingFailsRefreshAsync` (nightly run [42436716335](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/42436716335)). It is not a deadlock, and it is not Debug-only. Loading the full 535-document WoT sample set makes the xRegistry projection reconcile quadratically, and Coverlet in the Debug legs pushes the first E2E test past the 10-minute blame hang timeout. ## Root cause `XRegistryProjectionEngine` reconciles the entire registry projection on every registry change. The sample set projects 535 documents (about 70k nodes), and upload plus refresh cause about 2,700 reconciles. Each reconcile walked every Resource and re-cleared its change masks, several times over: - a recursive `ClearChangeMasks` of every existing group (all of its Resources), - for every logical Resource: two recursive clears of the logical subtree plus one per Version node, - since #4806 (10-17), a registry-wide `ClearChangeMasksAsync(includeChildren: true)` to publish `Registry.Epoch`. At the end of a run one reconcile took about 130 ms, which adds up to about 5 of the 7.5 minutes this test takes. Release CI shows the same: the three full-load E2E tests take 7.5–8.7 min in the Release legs of the same nightly. Their durations went up at the 10-18 nightly, after #4806. The 11-01 nightly already has a hang dump in the same test. The dumps show the reconcile pool thread busy in `ClearChangeMasks` / `ApplyWotResourceProperties`, not blocked. The bad-mapping error path itself works: the test passes and the `ServiceResultException` reaches the client. ## Fix - **Clear each node once per reconcile.** The group and registry levels now clear only their own state and non-Resource / non-group children. Each logical Resource subtree (which contains its Versions) is cleared once, after its Versions are reconciled. - **Skip unchanged Resources.** The new optional `IXRegistryProjectionResourceChangeToken` lets a strategy supply an immutable token per logical Resource. The engine skips a Resource whose token is reference-equal to the one it last applied. The WoT adapters return the immutable `WotResource`, which every registry commit replaces when anything about that Resource changes. Strategies without the interface behave as before. - The three full-sample-load E2E tests now use a 6-minute CTS instead of 30 minutes. A future slowdown then fails as a test timeout, below the CI blame hang timeout (10 min). ## Measurements (local, Debug, net10.0) | | before | after | |---|---|---| | `BadTargetMappingFailsRefreshAsync` alone | 7 m 22 s | 2 m 11 s | | time spent in reconcile (same run) | ~5 min | ~3 s | What remains is per-commit registry persistence (`FileWotRegistryStore` write-through and manifest replace) and materialization, spread across many call sites with no single hotspot left. ## Other notes - The three `SubscriptionManager.ConditionRefreshWorker` threads in the hang dump belong to the three servers that were still running (SourceA, SourceB, Aggregation). Locally all three log `Exited Normally` on teardown, so they are not a leak. ## Tests - New `XRegistryProjectionEngineTests.UnchangedChangeTokenSkipsTheVersionedResourceReconcileAsync`. It fails with the skip disabled. - All local runs on net10.0, one after another (no parallel test runs): | Project | Debug | Release | |---|---|---| | Opc.Ua.WotCon.Samples.Tests | 75/75 (2 runs) | 75/75 (2 runs, 11m53 / 11m44) | | Opc.Ua.XRegistry.Tests | 550/550 | 550/550 | | Opc.Ua.WotCon.Tests | 3321/3321 | 3321/3321 | - Full-load E2E tests after the fix: BadTargetMapping 1m44 Debug / 1m23 Release; RealSamplesRouteManagement 2m25 / 1m43; UnavailableUpstream 2m09 / 1m35. In CI Release before the fix they took 7m36 / 8m41 / 8m23. - `Opc.Ua.WotCon.Server` builds for net48. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
# 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.
…ite-side socket close (#5031) ## Problem `ClientTest.GetEndpointsOnDiscoveryChannelAsync(False)` sends an oversized GetEndpoints request (10000 profile URIs) on a discovery channel. The server rejects it with `BadSecurityPolicyRejected` and closes the socket. If the close happens while the client is still writing the multi-chunk request, the client sees a transport error instead of the rejection. The test already treated `BadSecureChannelClosed` as inconclusive. On macOS CI (run 42531694552, job 128887208396) the same race showed up as `BadTcpInternalError` ("Unexpected error during write operation."), and the test failed. That status comes from `UaSCBinaryChannel.WriteSingleChunkAsync`/the gathered and buffer-collection write paths. They wrap any non-`ServiceResultException` thrown by `IUaSCByteTransport.SendChunkAsync` (the raw `SocketException` for EPIPE/ECONNRESET) as `BadTcpInternalError`. ## Change Test-only. The test now also treats these transport-close codes as `Assert.Inconclusive`: - `BadTcpInternalError`: the failed socket send. - `BadConnectionClosed`: `TcpByteTransport.RequireConnectedSocket` after close. - `BadNotConnected`: the client channel is already shut down. Every other status must still be `BadSecurityPolicyRejected`. ## Verification Ran `--filter "FullyQualifiedName~ClientTest.GetEndpointsOnDiscoveryChannelAsync|FullyQualifiedName~ClientTest.ReadOnDiscoveryChannelAsync"` three times on net10.0 (Windows). There was no failure; locally the race takes the `BadSecureChannelClosed` path, so the test is inconclusive. ## Possible follow-up (not in this PR) The write path could map a `SocketException`/`IOException` from a peer reset (EPIPE, ECONNRESET, ConnectionAborted) to `BadConnectionClosed` instead of `BadTcpInternalError`. That would be more accurate for callers, but it changes product behaviour, so it is left out here. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.
PA-DIM analog bindings copy engineering metadata before replacing either published property. Caller mutations to
EUInformation,Range, translation dictionaries, or supported formatting arguments do not alter retained metadata. Unsupported copy inputs are rejected before either property changes. RegisteredEngineeringUnitsandEURangechanges use existing semantic-event and monitored-value status reporting; initial configuration remains unchanged.The PA-DIM-local comparator checks retained translations, selected text, fallback formatting and argument contents without changing global
LocalizedText.Equals. Dictionary reorders are equivalent only when they preserve the first available locale, first case-insensitive full-locale match, first locale for each language, and retained fallback information. This includes ordinal dictionaries with distincten-GBanden-gbentries. Undecodablemultext still uses selected-text equality; encoded-entry reordering can change the first-entry fallback.LocalizedText.Copy()retains enumeration order.The user approved extending shared localization, multidimensional values, and the shared envelope-clone correction.
ResourceManager.TranslateValueselectsEUInformation.DisplayNameandDescriptionfor exact scalars and elements of mixedExtensionObjectarrays/matrices. Translated copies preserve original TypeIds and dimensions without changing stored metadata. Null-ID, unsupported and derived structures remain unchanged. A shared internal routing check preserves legacy LocalizedText routing without newly invoking custom overrides for unrelated structures. This is not a general nested-structure visitor.Hosted mixed-container regressions exposed
CoreUtils.Clone(ExtensionObject)normalizing envelope IDs through its body-only constructor. The successor uses an internal copy constructor that retains the original ID, including null, while preserving the previous decoded-bodyClone()ownership behavior and retaining undecoded raw bodies. Existing array/matrix Variant construction reuses this shared clone path; no public API or obsolete production calls were added.Current published head:
92860d417b53dd3bdfec632950b3de9a09ccb3c5, based on integration masterf8aa7a62f42b8664f64d33c015f69c0fc0da6e51. Source publication was explicitly authorized. Earlier successors preserve envelopes (a59150199), add matrices/narrow routing (1c57ac313), compare language/default fallback ordering (02ef75b05) and case-insensitive full-locale ordering (fb3156d3f).docs/PADIM.mddocuments the contracts; only the PA-DIM section ofdocs/Profiles.mdchanges. Earlier compile corrections use explicitTryGetStructure<EUInformation>(out EUInformation? decoded)to avoid CS8631 and scalar/array CS0121 ambiguity. This PR stays draft; current-head hosted evidence includes candidate analyzer failures, and matched coverage acceptance remains pending.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)).
Checklist
Put an
xin the boxes that apply. You can complete these step by step after opening the PR.Validation
Local validation is suspended. The ISA-95 run retained the shared hold after an identity-mismatch cleanup uncertainty. The coordinator subsequently reported that the hold file was unexpectedly absent; the global safety hold remains in force regardless. Do not recreate, remove or alter any hold file. No local validation, restore/build/test, semantic/metadata or parser check,
git apply --check,git diff --check, formatter, analyzer or gate admission is permitted until explicit clearance.opcua-contained-gate-v1.ps1is suspended pending separate requalification; clearing the hold alone does not authorize reuse. Earlier PA-DIM gate evidence is historical. No hold was changed and no shared process was stopped by this follow-up. Hosted/source-publication permissions do not lift these restrictions.Current head: partial hosted evidence, analyzer failures
CI 42615773871 targets
92860d417b53dd3bdfec632950b3de9a09ccb3c5. Its initial observed status was pending with null conclusion; later captured evidence contains completed failures and incomplete jobs. It is not a passing full-run verdict. The user separately authorized monitoring this exact successor at five-minute intervals through completion, inspecting completed artifacts, and updating this evidence. No support-rating or coverage-nondecrease conclusion is established.Canonical current-head reports retained under
D:\temp\padim-hosted-92860d417:129161532916136767569641291615334471367509977712916153388413675931913All ten multilingual cases pass in those reports. All three
TranslateValueSelectsEngineeringUnitsInMixedArray(1/2/3)cases also pass in each completed server report: Windows net48 server-other job129161533114, artifact13676730644, 1,127 passed/0 failed; Windows net10 artifact13678480055, 11,018 passed/0 failed, total 11,123; Linux net10 artifact13676112175, 10,896 passed/0 failed, total 11,005. The three predecessor envelope regressions are no longer failing in those reports; this does not establish a passing full run.Candidate-caused build failures: CA1861 at
CoreUtilsTests.cs:359-360flags the two constant dimension arrays passed toIs.EqualTo. All seven build-UA jobs fail: Linux net8 Release129161530597, Linux net9 Release129161530598, Linux net10 Release129161530616, Windows net48 Debug129161530622, Windows net10 Release129161530623, Windows net48 Release129161530635, Windows net10 Debug129161530792. Types batches 15 fail compilation on Windows net48129161533169, Windows net10129161533763, and Linux net10129161540892. The new direct clone regressions therefore have no execution verdict. An uncommitted source-only correction uses one private static readonly expected[1, 2]shape and independently checks the input, cloned and Variant-wrapped dimensions against it. It has not been validated, committed or pushed; another publication/run requires user consent.Windows net48 Client job
129161532881, artifact13677750637, reports 3,778 passed/1 failed, total 3,784 and executed 3,779. Exact failed case:TryCompleteTransferAsyncShouldUseKnownServerIdsWhenResponseWrong1Async, duration00:00:00.0270000,System.AccessViolationException. The retained stack namesSubscription.DeleteCoreAsyncline 1505,MessageProcessor.ResetMessageGenerationAsyncline 1397,Subscription.StateManagerAsyncline 1427,DisposeAsynclines 841/852/858, and test line 2541. Source line 1505 is the catch boundary during subscription deletion; the stack does not identify a corrupting operation. The test reaches disposal after the transfer assertions. This differs from the predecessor reverse-connect timeout. Neither a candidate cause nor a baseline reproduction is established; no speculative Client patch is included.Finished Linux/Windows net10 PA-DIM-project coverage at current head, using exact package/class-line filters: Client 170/202 lines and 95/116 branches; Server 1555/1686 lines and 868/1034 branches. These are single-project reports, not matched aggregate current-head qualification.
Prepared regression evidence:
HostedEngineeringUnitsHonorsPreferredLocalesAndReportsTranslationChangescases passed on current head in Windows48/Windows10/Linux10 reports.en-AUDisplayName/Description cases passed on current head in all three reports.en-GB/en-gb, plus equivalent reorderEN-gbDisplayName/Description cases passed on current head in all three reports.TranslateValueSelectsEngineeringUnitTexts; included in completed passing server reports.TranslateValueSelectsEngineeringUnitsInMixedArraycases pass on current head in Windows48/Windows10/Linux10 reports.TranslateValuePreservesUnrequestedAndUnrelatedStructures; included in completed passing server reports.PublishSelectsTranslationOfLocalizedTextValueand twoPublishSelectsTranslationOfEngineeringUnitEventFieldcases; included in completed passing server reports.CloneExtensionObjectPreservesEnvelopeAndBodyOwnershipcases; blocked by Types compilation failures.CloneExtensionObjectPreservesEncodedBodies; blocked by Types compilation failures.Predecessor fb3156d: PA-DIM passed, shared-server regressions failed
CI 42605987105 targets
fb3156d3fc556e8824a44802e0046dd750f2b908, not current head. Initially pending with zero jobs/artifacts; later captured evidence contains completed failures and incomplete jobs. It is not a passing full-run verdict. Its watcher was stopped after successor publication. Hosted artifact parsing did not run local validation.129123124010136690387051291231241831366942367712912312441213669334118All ten multilingual cases pass in those three reports. These results validate that predecessor's semantic/fallback controls, not the new shared clone implementation.
Windows net48 server-other job
129123124546, artifact13669017029: 1,124 passed, 3 failed, total 1,127. Failures areTranslateValueSelectsEngineeringUnitsInMixedArray(1),(2),(3): expected alternative IDsnsu=urn:alternative;s=unitsandother-units, actuali=887; the null-ID unit element was also translated instead of preserved. Windows net10 server job129123124217repeats these same three failures (11,015 passed, 6 skipped, total 11,024); Linux net10 server job129123124264repeats them (10,893 passed, 10 skipped, total 10,906). Trace: array/matrix Variant constructors callCoreUtils.Clone, whose body-only envelope construction discards original IDs. The new shared correction addresses this mechanism, and these cases pass in the three current-head reports above; direct clone regressions remain blocked by compilation.Independent Windows net48 Client job
129123123771failsReverseConnectFailoverUsesMemberSourceAsync(False,True,False)with TaskCanceledException after 2 minutes: 3,778 passed, 1 failed, 3 skipped. No baseline reproduction or candidate cause is established; no speculative patch is included.Downloaded reports:
D:\temp\padim-hosted-fb3156d3. Finished Linux/Windows net10 PA-DIM-project coverage at fb3156d: Client 170/202 lines and 95/116 branches; Server 1555/1686 lines and 868/1034 branches. These are predecessor single-project reports, not matched aggregate current-head qualification.Predecessor b416307: six multilingual failures and independent Core failure
CI 42593478435 targets
b416307d1ab7a778a533a30817ef6d0be408e774. At its recorded follow-up snapshot, 4 jobs failed and 51 remained incomplete; it was not passing or complete.Three completed PA-DIM jobs each report 384 passed, 6 failed, 0 skipped, total 390: Windows net48 job
129085002307/artifact13664720950; Windows net10 job129085002528/artifact13664209210; Linux net10 job129085002750/artifact13664077745.All failures are
HostedEngineeringUnitsHonorsPreferredLocalesAndReportsTranslationChanges:SemanticsChanged.SemanticsChanged.SemanticsChanged.SemanticsChanged.Linux TRX progress shows
German event/status=False/Falseanddefault control event/status=True/Truein all six. This separates dictionary change notification from nested unit locale selection.EngineeringMetadataDetachesCallerValues(False/True),EngineeringMetadataCopyFailurePreservesPropertiesandHostedDeviceSupportsTypedDiscoverySimulationAndGeneratedOperationspass in predecessor Linux10/Windows48 reports. Predecessor macOS PA-DIM was queued at the recorded snapshot.Independent Linux Core job
129085002850failsResponseAfterChannelClosedIsDroppedQuietlyAsync: expectedTcpTransportListener + 21dropped-response log absent after 10 seconds; 6,727 passed, 1 failed, 93 skipped. Exact integration-base f8aa CI42577864883, job129029722931, artifact13657092238, records the same case passed in00:00:00.1056680, with Core 6,728 passed/0 failed. No Core source/test files change here. A shared-baseline reproduction or timing cause is not established. Source suggests a possible distinction between queuing on Faulted and rejecting on Closed channels; evidence does not establish which path occurred. No speculative Core patch is included.Historical local/compile evidence
git diff --checkpassed before the earlier follow-up commits and suspension; not rerun. Current local net10/net48 tests/analyzers remain pending. Predecessor b416 multilingual SHA256:23C47EE9287C45A1800C83001BE1B53591EFC6087B85E7B0CFE0FA43224B4A93.On
27c6120b9dcfd048fd1bf4d22e7050d614fea22d, this historical command exited 1 in compilation, CS0121 at multilingual test line 176. No tests/TRX; net48 not launched. Do not reuse this suspended wrapper.Result:
ROOT_EXIT=1 TOTAL_PROCESSES=41 JOB_EMPTY=true,OWNED_JOB_EMPTY=true. Both hold files were absent immediately afterward; this does not describe the later ISA-95 hold. Logs:D:\temp\opcua-contained-ce6a8faf7e4248af84a0a2fe48399abd\stdout.logandstderr.log. Tested fixture SHA2560AAAE0DC8BC3F5308ED080F8C89899DCB010E8FAA09C91DDFD8303989B7867A9.CI 42589029747, head 27c6120, had 8 failed/57 incomplete jobs at November 9, 2026 09:24:27 UTC. All eight inspected failures were candidate CS0121: Windows48 Release
129065972950, Windows48 Debug129065972953, Linux10 Release129065973037, Linux8 Release129065973052, Linux9 Release129065973212, Windows10 shard8129065974212, Windows48 shard8129065974337, Linux10 shard8129065974620. Shards failed compilation, not test cases. The new fixture is absent from integration base f8aa.Full local
dotnet test UA.slnx -p:CustomTestTarget=net48 -m:1 --no-restoreanddotnet test UA.slnx -p:CustomTestTarget=net10.0 -m:1 --no-restorewere not run. Approved shared-host plan uses focused local projects and hosted full-matrix validation.Withdrawn-wrapper run
dotnet test tests\Opc.Ua.PADIM.Tests\Opc.Ua.PADIM.Tests.csproj -f net10.0 -p:CustomTestTarget=net10.0 -m:1 -nr:false --filter "FullyQualifiedName~EngineeringMetadataDetachesCallerValues|FullyQualifiedName~EngineeringMetadataCopyFailurePreservesProperties|FullyQualifiedName~HostedDeviceSupportsTypedDiscoverySimulationAndGeneratedOperations|FullyQualifiedName~HostedEngineeringUnitsHonorsPreferredLocalesAndReportsTranslationChanges" --logger "trx;LogFileName=focused.trx" --results-directory D:\temp\padim-followup-results\focus10 --nologo -v:qwas stopped without a verdict. The first report that its waiter stopped before launch was wrong: gate PID28952 survived the parent shell; dotnet PID29028 started at09:58:11 local. The09:01:56Z memory sample was11.094528GiB, below12GiB. Positively identified owned dotnet then gate PIDs were stopped; retained process handle exit -1, no TRX, fresh snapshot both absent. No shared compiler stopped. The withdrawn wrapper lacked job containment, so escaped/unobserved descendants cannot be excluded. Evidence:D:\temp\padim-followup-results\existing-run-monitor.jsonlandexisting-run-verdict.json.Coverage comparison
Requested pre-#4993 baseline
bc91e23725f6ba05b6e20639c5b74b960dc85160, CI42380925376, artifact13583240260, has no matching PA-DIM components: 0/0 lines/branches, undefined, not 0%.Approved substitute #4993 merge
b9d5a2c3ccea48352ed8147bfa723437c37ccdc7/CI42384004060/artifact13582789779; master9eca587bdec449be97684da5c1c25af50b5e9bba/CI42562371225/artifact13654110477; exact integration masterf8aa7a62f42b8664f64d33c015f69c0fc0da6e51/CI42577864883/aggregate artifact13663800997all have identical counts using the same exact package/class-line filters:Finished b416 Linux10 artifact
13664077745and Windows10 artifact13664209210each report Client170/202 lines,95/116 branches; Server1498/1626 lines(92.1279%),801/960 branches(83.4375%). These are single-project/single-matrix reports from failed predecessor runs. The newer fb3156d and current-head provisional counts are recorded above. Baselines aggregate hosted matrices and other test projects. A finished matched aggregate current-head report is unavailable; current coverage nondecrease is not established. Higher predecessor rates do not qualify failing shared-server behavior.Earlier evidence: not validation of current source
Old head
846b16dee9feac7d7302377b749308b47e1f8b82passedHostedDeviceSupportsTypedDiscoverySimulationAndGeneratedOperationsin all four PA-DIM CI reports, each381 passed/0 failed/0 skipped: Windows48 job128794106951/artifact13625643996; Windows10 artifact13625723803; Linux10 artifact13626137770; macOS job128794109837/artifact13630273873.Historical local commands on that old head:
dotnet test tests\Opc.Ua.PADIM.Tests\Opc.Ua.PADIM.Tests.csproj -p:CustomTestTarget=net10.0 -f net10.0 -m:1 --nologo -v:q: passed381/381.dotnet test tests\Opc.Ua.PADIM.Tests\Opc.Ua.PADIM.Tests.csproj -p:CustomTestTarget=net48 -f net48 -m:1 --nologo -v:q: passed380/381;HostedRuntimeFacetChangesRequireExplicitPublicationtimed out after30s atPadimClientServerTests.cs:789through857.dotnet test tests\Opc.Ua.PADIM.Tests\Opc.Ua.PADIM.Tests.csproj -p:CustomTestTarget=net48 -f net48 --no-build --nologo --logger "trx;LogFileName=padim48.trx" --results-directory D:\temp\padim-trx: repeated380/381.dotnet test tests\Opc.Ua.PADIM.Tests\Opc.Ua.PADIM.Tests.csproj -p:CustomTestTarget=net48 -f net48 --no-build --nologo --filter "FullyQualifiedName~HostedRuntimeFacetChangesRequireExplicitPublication": reproduced timeout. Same test passed hosted exact-head; local cause unestablished.CI
42500925357completed127 successful/2 failed jobs. macOS128794110010failedSharedFileBindingReleasesClosedSessionHandlesAsync(True)with BadNotReadable; aggregate summary failed. Abandoned writer retained provider token during reopen. Merged #4999/9eca587bdec449be97684da5c1c25af50b5e9bbachanges binding toCloseSession(session.Id, defer: false)and adds lifetime regressions; already in this branch ancestry, not duplicated. Historical results do not validate new ownership/locale/clone source.