Measured 2026-08-07 against the live branch protection (18 required contexts) and
.github/workflows/*.yml.
Across the repo, 28 of 36 jobs declare no timeout-minutes. Restricted to the
jobs that actually gate the merge:
| required context |
timeout |
Lean proof typecheck (lake build) |
90 min |
Mutation Testing |
240 min |
Verification Gate (rivet-driven) |
60 min |
| the other 15 |
(none — inherits GitHub's 360 min default) |
The 15: Bench compile smoke, Cargo Deny, Clippy, Code Coverage, Codegen compile
oracle, Detect changed paths, Detect changed paths (proofs), Format, Fuzz smoke
(60s/target), Miri, Proptest (extended), Rivet validate (artifacts), Security
Audit (RustSec), Supply Chain (cargo-vet), Test.
Why it matters
This is not a wrong-green — it is an indefinite block with no signal. A wedged
job leaves the PR showing "Expected — waiting for status to be reported", which
looks identical to "still running", for six hours. Meanwhile it holds a
self-hosted runner the whole time, and with strict = true every other open PR
queues behind it.
Several of these are seconds of real work (Detect changed paths, Format),
so a 360-minute ceiling is four orders of magnitude off. Detect changed paths
is the worst of the set: it gates 10 of the other 17, so wedging it stalls the
entire suite.
Precedent: the same defect was fixed for the fixture-VM workflows, where a hung
guest produced exactly this 6-hour blind wait before both jobs were bounded.
Suggested fix
Give every required-context job a timeout-minutes sized to a few multiples of
its observed p95, e.g. classifier/format/deny in single digits, Test / Clippy /
Miri / Coverage in the 30-60 range. Observed durations are in the run history;
these should be measured, not guessed.
Worth a guardrail in the same family as check_required_contexts.py: every job
backing a required context must declare timeout-minutes. That is a pure YAML
check with no build, and it fails closed if the workflow set cannot be read.
NOT claimed: that any job currently hangs. This is about the blast radius when
one does.
🤖 Generated with Claude Code
Measured 2026-08-07 against the live branch protection (18 required contexts) and
.github/workflows/*.yml.Across the repo, 28 of 36 jobs declare no
timeout-minutes. Restricted to thejobs that actually gate the merge:
Lean proof typecheck (lake build)Mutation TestingVerification Gate (rivet-driven)The 15: Bench compile smoke, Cargo Deny, Clippy, Code Coverage, Codegen compile
oracle, Detect changed paths, Detect changed paths (proofs), Format, Fuzz smoke
(60s/target), Miri, Proptest (extended), Rivet validate (artifacts), Security
Audit (RustSec), Supply Chain (cargo-vet), Test.
Why it matters
This is not a wrong-green — it is an indefinite block with no signal. A wedged
job leaves the PR showing "Expected — waiting for status to be reported", which
looks identical to "still running", for six hours. Meanwhile it holds a
self-hosted runner the whole time, and with
strict = trueevery other open PRqueues behind it.
Several of these are seconds of real work (
Detect changed paths,Format),so a 360-minute ceiling is four orders of magnitude off.
Detect changed pathsis the worst of the set: it gates 10 of the other 17, so wedging it stalls the
entire suite.
Precedent: the same defect was fixed for the fixture-VM workflows, where a hung
guest produced exactly this 6-hour blind wait before both jobs were bounded.
Suggested fix
Give every required-context job a
timeout-minutessized to a few multiples ofits observed p95, e.g. classifier/format/deny in single digits, Test / Clippy /
Miri / Coverage in the 30-60 range. Observed durations are in the run history;
these should be measured, not guessed.
Worth a guardrail in the same family as
check_required_contexts.py: every jobbacking a required context must declare
timeout-minutes. That is a pure YAMLcheck with no build, and it fails closed if the workflow set cannot be read.
NOT claimed: that any job currently hangs. This is about the blast radius when
one does.
🤖 Generated with Claude Code