Cause. A red main holds every pull check of its repository for up to RED_HOLD_MS (20 min, src/checks/red_main.ts). Main only turns green again when its own check finishes ok, and that check is queued only by a push event to the default branch (src/checks/service.ts, case "push"). Landing a pull emits pull.merged instead (src/actions/pulls.ts around line 421), and the checks service's pull.merged handler only cancels that pull's checks. So once main is red, landing pulls never re-checks main. It stays red until someone pushes to main directly (a release commit), and every pull check waits the full 20 minutes. That is longer than the lane's 10-minute budget (BUDGETS.laneWait).
Evidence, 2026-10-15: main@9927fdd failed at 21:57:49 (#1881). #1162 and #1870 landed at 22:02:50 and 22:02:58, and main got no check after either. 15 pull checks sat queued from 21:59. Between 21:36 and 21:57 none of the lands was followed by a main check either; the only main checks were release commits.
Mechanical fix. In src/checks/service.ts, on pull.merged, when the pull's base is the repository's default branch and the payload carries mergeOid, call request(repo, repo.defaultBranch, mergeOid, "push", undefined, actor). Keep the existing cancel. request already supersedes a queued main check and skips a commit it has already checked.
Test (src/checks/*.test.ts): main's last check is failed; land a pull onto main; a queued check run exists with env = main, issue_id IS NULL and commit_oid = mergeOid. When it finishes ok, redMain is undefined and a held pull check is picked. The test must fail without the change.
Done when: after a land on a red main, queue:check and red:<repo> clear within one check's time, not 20 minutes.
Split off #1880 (queue:check past its budget).
Cause. A red main holds every pull check of its repository for up to
RED_HOLD_MS(20 min,src/checks/red_main.ts). Main only turns green again when its own check finishesok, and that check is queued only by apushevent to the default branch (src/checks/service.ts,case "push"). Landing a pull emitspull.mergedinstead (src/actions/pulls.tsaround line 421), and the checks service'spull.mergedhandler only cancels that pull's checks. So once main is red, landing pulls never re-checks main. It stays red until someone pushes to main directly (a release commit), and every pull check waits the full 20 minutes. That is longer than the lane's 10-minute budget (BUDGETS.laneWait).Evidence, 2026-10-15: main@9927fdd failed at 21:57:49 (#1881). #1162 and #1870 landed at 22:02:50 and 22:02:58, and main got no check after either. 15 pull checks sat queued from 21:59. Between 21:36 and 21:57 none of the lands was followed by a main check either; the only main checks were release commits.
Mechanical fix. In
src/checks/service.ts, onpull.merged, when the pull's base is the repository's default branch and the payload carriesmergeOid, callrequest(repo, repo.defaultBranch, mergeOid, "push", undefined, actor). Keep the existing cancel.requestalready supersedes a queued main check and skips a commit it has already checked.Test (
src/checks/*.test.ts): main's last check is failed; land a pull onto main; a queuedcheckrun exists withenv = main,issue_id IS NULLandcommit_oid = mergeOid. When it finishes ok,redMainis undefined and a held pull check is picked. The test must fail without the change.Done when: after a land on a red main,
queue:checkandred:<repo>clear within one check's time, not 20 minutes.