docs: record reviewed SDK2 ownership regressions and diagnostic design

This commit is contained in:
Joseph Doherty
2026-11-10 17:33:06 -05:00
parent 2e4905f112
commit 327bbdaab9
3 changed files with 1385 additions and 0 deletions
@@ -549,3 +549,53 @@ configured-store replacement semantics and was not adopted.
These results leave the original cold RSS failures and #799/G4 unchanged. The
[prospective resolution procedure](../../scripts/validation/opcua-lifecycle-memory/RESOLUTION.md)
is explicitly a design draft, not approval to launch a warmed acceptance run.
### Baseline ownership repair and SDK2 follow-through
The [original ownership controls](../../scripts/validation/opcua-lifecycle-memory/baseline-canonical/OWNERSHIP.md)
retain both ordinary exit-1 outcomes. Closed-session/point objects collect while
the same original host remains alive, and old authentication and continuation
tokens are rejected. After normal stop, five original server graph objects
remain. One separate public terminal Dispose releases all five and reduces active
timers from seven to two. The intervention does not rewrite the ordinary failure
or identify a particular measured timer root.
The SDK1 host omitted terminal server disposal. This was repaired independently
on master `efb9197a`; [#807](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/807)
is closed. Five causal RED cases pass after the fix; 1,032 owning tests pass with
one existing skip, and the Release solution builds without warnings. The frozen
`83ed880e` publications and aggregate oracles remain unchanged. The repaired
master has not been selected as a resource denominator.
SDK2 already disposes adopted servers through ApplicationInstance. Follow-on
review found that a second host disposal could return while the owner was still
closing a real session, and configuration/certificate failure before adoption
could strand the host's raw server. One owner now provides shared completion,
retains server/authentication state through shutdown, and directly awaits terminal
disposal only for an unadopted server. A terminally disposed host rejects new
startup. This does not claim general concurrent asynchronous Start/Dispose support.
At integrated source `ce21f5db`, the whole solution builds with **zero warnings
or errors**. The server unit suite has **1,122 passes** and one existing skip;
full wire has **193 passes** and three existing opt-in diagnostic skips. The
seven focused ownership cases, actual encrypted concurrent shutdown and aligned
weak-root control pass; trusted-channel/certificate and same-PKI two-boot checks
are included. [Source hashes and guarded RED/GREEN receipts](evidence/2026-11-10-opcua2/disposal-ownership-integrated.json)
preserve the three intended unit RED failures, the real-session RED, and the
earlier test compilation/assertion attempts separately. Astra independently
verified source, causal failures and integrated results. Earlier full CI, publish
and soak evidence retain their own source revisions and outcomes.
The [pure Apple empty-keychain control](../../scripts/validation/opcua-lifecycle-memory/native-retention/PURE_APPLE.md)
kept AppleDatabase inventory flat across 200 successful create/delete/release
operations with unchanged default/search-list fingerprints. Empty-keychain
lifecycle alone is insufficient to reproduce the native retention. The first
[installed bridge import attempt](../../scripts/validation/opcua-lifecycle-memory/native-retention/NATIVE_IMPORT_ATTEMPT.md)
failed after one partial operation on a diagnostic identity-association
assumption; all owners and private files were cleaned. It is not a repeated
import result or evidence of native retention resolution.
#799 and G4 remain open. The [proposed Linux late-slope diagnostic](../../scripts/validation/opcua-lifecycle-memory/LATE_SLOPE.md)
has implementation design approval only. It retains the cold baseline and first
resource rejection and cannot emit acceptance. No new long run or release is
approved; Windows/live interoperability gates remain separate.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,80 @@
# Proposed fixed-duration late-slope diagnostic
Design draft only. No new mode, artifact or long execution is approved by this
document. Resolve the current ownership/code gates and review native attribution
before deciding whether this experiment supplies a still-needed fact for #799.
The question is whether the canonical Linux process continues to grow well after
the observed generated-code step. This is separate from choosing a warmed
acceptance baseline, a cross-version performance denominator, or resolving macOS
private-key import retention. The existing `profile` allowance stays 60–1800s.
If approved, add a distinct diagnostic mode fixed at **7200 seconds** of canonical
cycling after startup, including its cold and qualification-era cycles. It must
not claim 7200 seconds *after warmup*. Keep every normal operation, the active
restart every fourth cycle, all logical/ownership checks and actual PKI descriptor
checks. Use fresh committed source and immutable self-contained Linux ARM64
.NET10.0.14 artifacts, exact SDK2.0.1 and the landed HG1.0.0 graph. Freeze image,
PKI identity, fixture and instrumentation before launch. Root owns the long run.
Keep the original cycle-3 baseline and +64MiB managed / +128MiB RSS / +32 FD caps.
Record the sample before asserting; catch only the three resource-cap assertions,
latch the first rejection permanently and continue **every canonical cycle and
restart**, with resource sampling. Managed-monotonic, logical/ownership, observer,
operation and shutdown failures remain fatal. After final ownership/shutdown
checks, emit a diagnostic receipt with `acceptance=false` and rethrow the original
cap rejection. Never emit ordinary `complete`/two-hour acceptance or convert an
earlier rejection to success. A duration completion is distinct from test success.
Prospectively report **all** quiescent observations, cold rejection, maximum
observed quiescent RSS and final values. Predeclare these elapsed-time windows:
| Window | Quiescent sample elapsed seconds |
|---|---:|
| Early late phase | 1800–2400 |
| Middle late phase | 3600–4200 |
| Final late phase | 6600–7200 |
Proposed fixed bounds are startup 120s, each complete cycle including its restart
30s, cycle deadline 7230s, independent shutdown owners 20s each and container
deadline 7440s. The final cycle may finish after 7200s, but cannot extend
its 30s bound. Validate these bounds with reviewed short controls before committing
the protocol; hitting one makes the diagnostic incomplete, not grounds to relax it.
The existing quiescent sample precedes the optional restart. Thus two adjacent
bounded cycles allow at most 60s between quiescent samples. Each 600s window must
have at least 10 samples, first sample no later than 60s after its start, last sample
no earlier than 60s before its end, observed span at least 480s, and no internal gap
above 60s. Apply the same 60s maximum gap over the entire 1800–7200s reporting range.
Missing coverage is incomplete evidence; it must not become a favorable slope.
For each window report sample count, first/last/min/max/median RSS and retained
managed bytes, FD range, GC committed range, JIT/timer/thread ranges and elapsed
coverage. Missing windows are incomplete evidence. Also report ordinary least
squares RSS and managed-byte slopes against actual sample elapsed seconds for
all observations in 1800–7200s, with units bytes/hour and the exact sample count.
Do not choose a favorable endpoint/window/statistic after observing results.
These descriptive slopes have **no new pass threshold**. Quiescent maxima are
not continuous process peak measurements, and native MethodSize is not RSS.
Retain certificate allocation StackTrace tracking at the same enabled setting as
the earlier canonical saturation experiment and disclose its overhead. Do not
attach EventPipe to this proposed run or claim generated-factory readiness from
absent counters; earlier traces remain separate source-scoped evidence. This
instrumented diagnostic cannot be relabelled as uninstrumented acceptance or as
one of the required representative-load comparison runs.
Freeze cycle-phase elapsed timestamps before cleanup and retain shutdown duration
separately; no cleanup sample feeds the windows or slopes. The new mode must
reach its explicit post-shutdown checks before rethrowing a latched resource cap;
the generic profile mode currently throws earlier and must keep its old behavior.
Cleanup must attempt both independent owners under their separate deadlines even
when one fails or the operation token is canceled. Preserve the first rejection
alongside any later cleanup failure; neither error may erase the other.
Before execution, implement and review the proposed setup/last-cycle/cleanup and
outer deadlines in the actual harness and launcher; no extension or retry-to-green.
Require negative controls proving a latched first failure cannot disappear,
wrong duration/mode is rejected, no ordinary acceptance receipt can be emitted,
and malformed/missing sample windows fail the summarizer. Review actual source,
control results and every immutable artifact hash with Astra before launch.