Acceptance runs for #799 (owner scope 2026-11-12: Windows x64 + Linux) on current master. Fixture: since #808 an UNS folder the authority snapshot does not place is denied under enforcement (fail closed). The canonical soak creates its own "SoakEquipment" folder but never placed it, so on master the very first cycle's UNS monitored item came back bad (retained failed Linux launch onb61f3e05, cycle 1). The rig gains AdditionalFolderScopes (merged into FolderScopes by Enforce) and the soak places its folder there, as a deployed generation does - the same fixture gap #888 fixed for the SDK matrix. No server authorization code, cap, baseline or canonical operation changed; the soak test bodies are otherwise byte-identical tob18f9723. Windows port (test/harness only, opt-in): - DescriptorCountsAsync gains a Windows branch: total = every handle in the process handle table, PKI = disk file/directory handles whose GetFinalPathNameByHandle path lies under a canonicalised PKI root; dedicated thread under the same 5 s bound as the macOS lsof probe. - Descriptor controls enabled on Windows (symlink alias; timeout control via cmd.exe + ping). - LateSlopeRun.ValidateRequest accepts Linux ARM64 or Windows x64; duration/runtime/leak tracking unchanged. - late-slope/analyze.py: expected architecture is a module constant (Linux default Arm64 unchanged). - windows/: prepare.py (win-x64 self-contained 10.0.14 bundle + manifest), launch.ps1 (container.sh equivalent: bundle re-verification, 2/2 controls first, PID/apphost/coreclr verification, external sampler, 7440 s outer deadline), analyze.py (Linux row/window logic, X64), README with every adaptation. Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
Linux late-slope diagnostic
The protocol fixes 7,200 seconds of canonical cycling from
startup completion, with the existing active restart every fourth cycle. The
cycle-three baseline and resource caps remain in force. A latched rejection
keeps the original failing test and container exit. The result records
acceptance=false even when the diagnostic completes its duration and shutdown.
The analyzer requires an ordered active, recovered-stall, resource-observation, quiescent and complete-cycle ledger. It checks the 25-second restart helper bound, 30-second complete cycle bound and 60-second shutdown bound. It recomputes the first cold rejection and verifies its assertion against the actual TRX. It checks each fixed time window and the entire 1,800–7,200 second range before reporting RSS and retained-managed slopes in bytes per hour. The report includes sample counts, quiescent peaks, final values and coverage. It identifies whether the earlier saturation workload had completed by 1,800 seconds, which bounds any interpretation relative to the previously observed restart step. The raw JSONL keeps every sample and the first assertion stack.
Certificate allocation stack tracking remains enabled and contributes to the measured process. The slope report is descriptive and carries no resource pass threshold. Quiescent peaks refer to the sampled points.
Offline controls and artifact preparation
The synthetic controls exercise the parser, receipts and bundle manifest with temporary files. Run them with Python 3.11 or later.
python3 scripts/validation/opcua-lifecycle-memory/late-slope/test_offline.py
Prepare from the reviewed clean commit containing the canonical test and tools. The image argument is the immutable ID of a locally cached Linux ARM64 SDK image. The explicitly selected Docker context must use a local Unix socket. The preparation command publishes the self-contained .NET 10.0.14 app and records the exact SDK 2.0.1 and HistorianGateway 1.0.0 graph, source hashes, file hashes and managed module MVIDs. It uses the repository's read-only PE metadata inspector. Preparation completes before any descriptor or lifecycle test runs.
python3 scripts/validation/opcua-lifecycle-memory/late-slope/prepare.py \
--source-revision "$reviewedRevision" --docker-context "$localContext" \
--image "$cachedImageId" --output "$bundle"
python3 "$bundle/tools/launch.py" --bundle "$bundle" \
--receipt-sha256 "$reviewedBundleReceiptHash" --verify-only
Reviewed run and analysis
Root owns launch after review of the exact bundle receipt and controls. The
bundled launcher uses the pinned Unix endpoint, immutable image, network-none
container, read-only root filesystem and read-only application and tools mounts.
A fresh private task directory holds results and fixture files. The launcher
creates its temporary subdirectory with mode 0700 and binds the same storage
at /tmp for NuGet's named mutex. TMPDIR continues to point at /task/tmp.
The container checks both paths identify the same private directory before
starting VSTest. The two descriptor controls must execute successfully before
the canonical test starts. The launcher verifies
the actual test process's apphost, mapped CLR and CLR hash. Its outer deadline
is 7,440 seconds, with cleanup limited to the uniquely labeled container.
python3 "$bundle/tools/launch.py" --bundle "$bundle" \
--receipt-sha256 "$reviewedBundleReceiptHash" --output "$run"
python3 "$bundle/tools/analyze.py" --run "$run" \
--bundle-receipt "$bundle/receipt.json" --bundle-receipt-sha256 "$reviewedBundleReceiptHash"
A completed diagnostic with a cold-cap rejection has a nonzero launcher exit. Its receipt records diagnostic completion separately from the actual test and container status. The offline analyzer verifies the reviewed bundle receipt, raw evidence hashes, test identities and outcomes, fixed duration and verified shutdown before emitting a report. It can run from copies of the small bundle receipt and run evidence on a machine without Docker.