From 35ef08d49733b74b8c0c8fd486d6916c22202afd Mon Sep 17 00:00:00 2001 From: garrytan Date: Mon, 2 Nov 2026 23:45:51 +0000 Subject: [PATCH] fix(pregate): a failed CPU read waits for the next sample; docs wording (fix-check) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- docs/pregate.md | 2 +- lib/pregate/supervise.ts | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/pregate.md b/docs/pregate.md index 9a962cf8e..b6610fe5e 100644 --- a/docs/pregate.md +++ b/docs/pregate.md @@ -448,7 +448,7 @@ test-tier command: runner. Other runners (node --test, vitest, jest, pytest, playwright test, flutter test, dart test, cargo test) get heartbeats only. A heartbeat follows each 60 s with no progress line; - is killed as **stalled** when its log does not grow and its process group - uses no CPU for the stall timeout (`--stall-timeout `, else + stays under a tenth of one CPU for the stall timeout (`--stall-timeout `, else `stall_timeout_s`, else 300; `0` disables): the check is `incomplete` with `PREGATE_STALLED` and names the last file started; the next serial file still runs. The group counts as busy when its CPU time, sampled each second, diff --git a/lib/pregate/supervise.ts b/lib/pregate/supervise.ts index 3c4c3412e..37cc3210e 100644 --- a/lib/pregate/supervise.ts +++ b/lib/pregate/supervise.ts @@ -220,10 +220,8 @@ export function supervise(o: SuperviseOptions): Promise { if (now >= o.deadline) { stop('timeout'); return; } if (o.stallMs > 0 && process.platform !== 'win32' && now - cpu.at >= CPU_SAMPLE_MS) { const used = groupCpuMs(child.pid!); - if (used !== null) { - if (used - cpu.ms >= CPU_BUSY_SHARE * (now - cpu.at)) lastBusy = now; - cpu = { at: now, ms: used }; - } + if (used !== null && used - cpu.ms >= CPU_BUSY_SHARE * (now - cpu.at)) lastBusy = now; + cpu = { at: now, ms: used ?? cpu.ms }; } if (o.stallMs > 0 && now - Math.max(lastGrowth, lastBusy) >= o.stallMs) { stop('stalled'); return; } if (now - lastProgress < heartbeatMs) return;