Repository navigation
v2.5.80 - watchdog recovery and diagnostics corrections
v2.5.80 (2026-09-12)
Closes the gap v2.5.79's "Known limitations" named: a cycle killed mid-pass on a machine that
neither reboots nor logs on again was not resumed until the next logon or boot (-35qb.10,
found by matrix row G on 2026-09-09).
Fixed
- A cycle killed mid-pass on a machine that neither reboots nor logs on again was never
resumed. Every trigger in the resume chain was boot- or logon-scoped, so a pass that died
in between sat idle indefinitely. While a cycle is in flight — armed at the resume checkpoint
before the first update phase — both continuation tasks now also carry a repeating trigger
that starts a watchdog probe everyWatchdogIntervalMinutes(default 15, floor 2, no off
switch). A probe that finds the cycle's mutex held exits at once, unchanged; one that finds it
free or abandoned becomes the recovery pass. This closes #69 (Beads-35qb.10).
Changed
- New
-WatchdogIntervalMinutesparameter onInvoke-BootUpdateCycle.ps1and
Deploy-BootUpdateCycle.ps1(default 15, floor 2 with a logged clamp), passed through in
continuation-task arguments. - A pass resumed after an unobserved stop is now a recovery pass, charging the retry budget
once and recorded in state asUnobservedStops. It is disclosed in the completion banner/log
and in the repair plan, without changing the convergence claim. - Registration verification fails closed in both directions: a deliberate stop (retry-pending,
waiting on a user logon, the restart path) must never carry the repeating trigger, and an
in-flight checkpoint must carry it — either mismatch throws. - The mutex-held log line changed from a Warn "Exiting" to an Info line describing a watchdog
probe exiting without changes, since a probe finding the mutex held is now an expected, routine
outcome rather than a collision worth a warning. - A staged-rollout withhold is now marked as deliberate. Before this, the pass after a staged
target left incomplete logged "Previous run crashed" although nothing had; with the new
accounting it would also have disclosed a false unobserved stop and charged a second retry. - An operator resume after a raised limit is not charged. The pass that follows raising
-MaxRetryPassesor-MaxIterationsre-runs the unfinished phase without spending the retry
it was just granted. WatchdogIntervalMinutesis accepted from remote configuration, with the same floor and a
1440-minute ceiling applied on every path.- Downgrade note. Continuation tasks now pass
-WatchdogIntervalMinutes; an older orchestrator
placed at the install directory by hand would reject that argument and the resume chain would
not run. Roll back withDeploy-BootUpdateCycle.ps1, which re-registers the tasks.
Additional fixes
- Empty cleanup is no longer labeled persistent when both observations are empty. #53 records the exporter defect; only equal nonempty fingerprints establish persistence. Empty-to-empty is false; missing or skipped observations remain unknown.
- The lab CI credential boundary is explicit. #66 records the analyzer correction: required plaintext-to-secure-string conversion is centralized with narrow function-scoped compatibility exceptions.
- Parallel-phase interruptions consume the watchdog retry budget. Release review found that the parallel-cohort sentinel bypassed crash accounting, allowing repeated same-boot interruptions to retry indefinitely. #70 tracks the correction: charge one recovery for the interrupted pass, retain completed provider flags, disclose the stop, and use the existing retry-limit handoff.
Known limitations
- Interruption during final health and convergence verification, after the parallel cohort has finished, does not yet charge the recovery budget. #71 tracks a durable checkpoint for that window; the parallel-cohort fix does not cover it.
- Optional phase hooks may be rejected by the trust check under the standard directory permissions, even when broad groups have only read access. #72 tracks this permission-mask false positive.
Validation
Unit/process behavior: PASS (502 tests, 0 failures or skips; clean CI for 98f72e2)
User/SYSTEM boundary: PASS
Published launcher upgrade: PASS
Live bootstrap: PASS (fresh install and legacy repair from the public release)
Parallel-cohort recovery: PASS (two interruptions; bounded safety stop, not convergence)
Provider integration: NOT RUN
Multi-reboot convergence: PARTIAL (rows A and G PASS; row B PARTIAL with deferred inventory; wider rows NOT RUN)
Release assets: PASS (10 scripts + 10 SHA256 sidecars; uploaded bytes verified)
Candidate CI passed 502 tests, PowerShell parsing, analyzer checks, user/SYSTEM exclusion, and the published-launcher upgrade gate at commit 98f72e2. Four new behavioral regressions cover the parallel-cohort accounting correction. The A/B/G rows below ran before that correction and the version bump; they establish their tested paths, not the new cohort edge case. Live bootstrap VM checks passed for fresh install and legacy repair against the public release. All 20 release assets were downloaded and verified before publication, and v2.5.80 was confirmed as the latest public release. Broader provider coverage and the wider VM matrix remain NOT RUN.
-
Row A — interactive continuation, September 12. PASS. Four user-context passes across three observed reboots; reboot accounting matched the OS evidence, the final Windows Update scope was empty, health checks passed, and state, continuation tasks and cleanup evidence were clear. Evidence:
vm-runs-retry2/A-sep12-boot-upd-matrix-20260912-111434. -
Row B — headless SYSTEM continuation, September 12. PARTIAL. Five SYSTEM passes and two observed reboots completed the cycle with no interactive user. Winget, Scoop and VS Code user work remained deferred, and the Windows Update re-offer was retained as deferred inventory rather than retried; the row therefore does not claim full provider convergence. This is a truthful partial result.
-
Row G — killed-process recovery, September 12. PASS. The intended Deploy process was killed after promotion; the scheduler records recovery PID 5148 and a separate SYSTEM fallback PID 4784 that respected the mutex. The recovered cycle completed with zero reboots, empty Windows Update assessment, passing health checks, and no remaining state or continuation tasks.
-
Row H — bounded parallel-cohort recovery, September 12. PASS for recovery; convergence intentionally stopped. The exact candidate orchestrator ran directly from its installed path. An admin-only fixture directory avoided the separate hook-permission defect (#72); a trusted hook held the cohort entry before provider jobs started. Two distinct processes were killed at persisted cohort checkpoints with retry counts zero and one. Time-triggered continuations charged exactly two recoveries; the third pass retained
RetryLimitReachedstate, exited with code 3, and removed both continuation tasks. Boot timestamps normalized to the same UTC instant and the reboot count remained zero. Scheduler exit-code encoding was independently calibrated. This tests cohort-entry interruption, not termination inside an active provider. Details and fixture limitations: September 12 evidence report.