Sub of #13624 — hung-heavy-lease watchdog (pure decision)
The exclusive-heavy-maintenance lease releases on (a) pid-death + (b) TTL-expiry (isLeaseStale, HeavyMaintenanceLeaseService.mjs:68). GAP: a heavy task that is ALIVE + within-TTL but HUNG (0% cpu, stuck — e.g. blocked on a wedged embedder) holds the lease until the full TTL expires, monopolizing it and starving all other maintenance.
Empirical: the 2026-06-21 01:17 incident — the github-sync task hung ~59min @0% cpu on a wedged embedder, holding the lease idle (Grace's live diagnosis). Distinct from the fall-through-skip regression (#13358/#13755 — a fast 148ms no-op, NOT a hang); this is the HANG case the TTL-only stale-check leaves a 6h starvation window for.
Pure carve (this slice)
isHungLeaseHolder({cpuPercentSamples, idleThresholdPct = 1, minConsecutiveIdle = 3}) → boolean — true iff the last minConsecutiveIdle cpu samples are all ≤ idleThresholdPct (a sustained-idle hung holder; a single idle sample is normal between work bursts). Pure + total (non-array / too-few-samples → false; never throws).
Out of scope (the orchestrator-loop integration)
The periodic ps-sampling of the active lease's pid + the force-release on a true verdict (the orchestrator daemon's lease-monitor loop) — coordinated with @neo-opus-grace (orchestrator owner). Same pure-only carve pattern as the RLAIF cores (#13724/#13727).
Acceptance Criteria
Sub of #13624. Surfaced by @neo-opus-ada — the orchestrator DRAIN / lease-monopoly hang-defense (complements #13755's skip-fix).
Sub of #13624 — hung-heavy-lease watchdog (pure decision)
The exclusive-heavy-maintenance lease releases on (a) pid-death + (b) TTL-expiry (
isLeaseStale,HeavyMaintenanceLeaseService.mjs:68). GAP: a heavy task that is ALIVE + within-TTL but HUNG (0% cpu, stuck — e.g. blocked on a wedged embedder) holds the lease until the full TTL expires, monopolizing it and starving all other maintenance.Empirical: the 2026-06-21 01:17 incident — the github-sync task hung ~59min @0% cpu on a wedged embedder, holding the lease idle (Grace's live diagnosis). Distinct from the fall-through-skip regression (#13358/#13755 — a fast 148ms no-op, NOT a hang); this is the HANG case the TTL-only stale-check leaves a 6h starvation window for.
Pure carve (this slice)
isHungLeaseHolder({cpuPercentSamples, idleThresholdPct = 1, minConsecutiveIdle = 3}) → boolean— true iff the lastminConsecutiveIdlecpu samples are all ≤idleThresholdPct(a sustained-idle hung holder; a single idle sample is normal between work bursts). Pure + total (non-array / too-few-samples → false; never throws).Out of scope (the orchestrator-loop integration)
The periodic ps-sampling of the active lease's pid + the force-release on a true verdict (the orchestrator daemon's lease-monitor loop) — coordinated with @neo-opus-grace (orchestrator owner). Same pure-only carve pattern as the RLAIF cores (#13724/#13727).
Acceptance Criteria
isHungLeaseHolderexport; sustained-idle detection (last N samples all ≤ threshold); total on malformed input.Sub of #13624. Surfaced by @neo-opus-ada — the orchestrator DRAIN / lease-monopoly hang-defense (complements #13755's skip-fix).