test: harden the drain-timeout upgrade timing assertion - #19
Merged
Merged
Conversation
Capture the total upgrade duration immediately on return, keep every existing functional and safety assertion ahead of the unchanged ten-second guard, and include the actual duration and diagnostic phase data in any timing panic. A test-only watcher samples the admission marker at a configured ten-millisecond interval. It records initial state, sample count, observed maximum gap, effective resolution, marker-presence phases and explicit reasons for every missing value. Shutdown waits at most one second and joins only a finished thread; Drop uses the same bounded path. Qualification receipts now retain the timing data before the final assertion. No product upgrade code, retry behavior, threshold or resource semantics change.
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.
Summary
Harden the timing-sensitive drain-timeout upgrade test without changing product upgrade behavior or weakening its existing 10-second guard.
This is a test-only, independent CI-hardening change. It is not CS-RG implementation, changes no DevGuard resource semantics, and does not modify or amend #17.
Base:
9e21cc8f707f16b7da98490293b5ea7e4548916dHead:
92a0611e442baf277b9b578c087c8028984da1f1Changed file:
crates/daemon/tests/upgrade.rsonly.Motivation
#17 is a one-file historical-document change. Its pull-request macOS run 36408760157 nevertheless ran the full workspace and failed only here:
The expected
ResourceUnavailableresult anddid not finishmessage had already been produced. The same branch tree passed push run 36408700221 on the samemacos-14-arm64image. The failed workspace test prevented all later DG1 suites from running.This PR does not treat that as a product regression. It makes the assertion diagnostic and ensures a busy-host timing failure no longer suppresses the test's later safety assertions and qualification receipt.
What changes
upgrade()returns.elapsed < 10 sguard unchanged and run it last.drain-timeout.jsonbefore the timing assertion, then print the exact capturedDuration, milliseconds and phase diagnostics in any timing panic.Diagnostic marker sampling
A test-only watcher samples the admission-closure marker every 10 ms. It is explicitly not an exact latency clock: server marker creation precedes the complete in-memory close operation, marker removal precedes the complete reopen response, and scheduling can widen sampling gaps.
The receipt records:
upgrade()duration;nullplus a field-specific reason for every missed/unorderable transition; andStartup waits at most one second for the first sample. Shutdown sets a stop flag, waits at most one second, joins only a finished thread, and otherwise detaches after recording the failure;
Dropuses the same bounded path. A post-stop observation reduces the final transition race.The marker-present interval combines the one-second drain/polling period with the early part of reopen. It distinguishes that work from pre-close package/path/hash/selection/recovery-copy preparation; it does not claim to measure logical admission latency exactly.
Baseline and local evidence
Read-only baseline preserved both #17 runs before this branch was created. The failing run was in
validate.py'scargo test --workspace, notdg1-upgrade; later suites were skipped.At unmodified base
9e21cc8…, ten sequential warm exact-test runs all passed. Whole-test time was 21.99–22.26 s (median 22.055 s); the original test did not expose the firstupgrade()duration, so those runs cannot localize the delay.At exact head
92a0611…:python3 scripts/qualify.py dg1-upgrade --offline --output target/qualification/pr2-dg1-upgrade-92a0611: passed all stages (3 + 1 + 3 + 3 + 1 + 15 tests). Its timing receipt: total 5.948 s, marker first present 4.882 s, marker observed present 1.070 s, 425 samples, 15 ms effective resolution.python3 scripts/validate.py --offline --output target/qualification/pr2-full-92a0611: passed source/docs/dependency, fmt, workspace Clippy and 318 workspace test results.git diff --check origin/main HEAD: passed.Frozen hosted-observation protocol and decision rule
This protocol is recorded before reading any hosted result from this head.
initial_marker_presentis false; marker presence, later absence and the marker-present interval are non-null; watcher diagnostics are empty; and effective resolution is at most 250 ms. A null return-tail caused only by the final absence sample following the captured return is acceptable because it has an explicit reason and does not prevent phase separation.No internal retry, average or rerun can turn an individual failed job into a pass.
Hosted results and decision
All three prescribed macOS jobs completed successfully on
macos-14-arm64image20260831.0302.1with Rust 1.95.0:92a0611…c58950d…c58950d…The merge source's parents are the base and exact branch head, and its Git tree equals the branch head's tree. In every sample the complete workspace validator and
dg1-upgradepassed; initial marker state was false; the essential presence/absence fields were present; diagnostics were empty; and resolution was under the frozen 250 ms ceiling. The nullable return-tail had only the pre-accepted, field-specific reason that its final marker-absence sample followed the already-captured return instant.No job failed, no essential evidence was ambiguous, all totals were below 10 seconds, and all marker-present intervals were below 3 seconds. Therefore the protocol does not escalate to five jobs. It retains the unchanged
elapsed < 10 sguard. No product defect or evidence for a new timing value was found; the new diagnostic remains so a future outlier preserves whether time accumulated before the marker or during drain/reopen.Compatibility and scope
No product source, wire/capability, manifest, lock, dependency, service, credential, journal, release or host setting changes. The installed user service is not involved; tests use an isolated fixture authority and fake service manager. Existing internal idempotent control-call behavior is unchanged.
Rollback
Revert this test-only commit. Product behavior and persisted state require no rollback.
Evidence
Ignored local evidence:
evidence/ci-hardening-2026-09-28/, including the two #17 runs, 10-run base observations, forced-final-assertion probe, exact-head qualification and full-validation hashes, all three hosted attempts andpr2/hosted-observations.json. Every hosted attempt was preserved before a rerun; no earlier failure was erased.