Repository navigation
Description
What
Drop Mergify entirely and restore pr-monitor (CI Gate) as the merge gate, per the maintainer's call after #946 proved Option A of #943 deadlocks.
Why Mergify is structurally insufficient here
#943's requirement — pending while any check runs, green when all complete, red on failure, zero-check PRs mergeable — is unsatisfiable in Mergify's check-run-based condition vocabulary. Every option was tried and eliminated:
#check-failure = 0alone (ci: reduce the Mergify gate to a single failure count #881): vacuously true before dispatch and mid-run. Merge gate reports green while checks are still running #943 measured the gate green 2m21s before the last check finished — a gate that does not gate.- Add
#check-pending = 0(ci: block merge while checks are still running #945, Option A): Mergify Merge Protections counts its own in-progress check, so the count never reaches zero. Deadlock — first diagnosed in CI:#check-pending = 0deadlocks the Mergify gate (it counts its own check) #832, doubted in Merge gate reports green while checks are still running #943, confirmed deliberately by canary 🚨 DO NOT MERGE — canary for merge-gate timing (#943) #946 (emptyWaiting checkslist, condition still unsatisfied). The deadlocked gate then blocked its own revert (Revert "ci: block merge while checks are still running" #947 needs an admin merge). - Named anchors (Replace pr-monitor with Mergify for merge gating #830's original config): path filtering (Epic — CI: run only the checks relevant to the changed paths #834, 9 of 15 workflows) killed this — an anchor on a workflow that doesn't run pends forever, and anchors are blind to
startup_failureand break silently on job renames.
There is no fourth option in that vocabulary. Operationally, Mergify also reads its config from main only, so every experiment required a land → canary → revert cycle on main — which is exactly how the repo ended up wedged.
pr-monitor polls workflow runs, which sidesteps all three: path-filtered workflows need no enumeration, in-flight runs hold the gate, startup_failure / cancelled / timed_out fail it, and it excludes itself by run ID. The dispatch race is bounded by pre-sleep (observed fan-out ~2s on #946; setting 30s) and zero-check PRs pass via minimum-checks: 0 (#943's scope ruling: a check that should have existed but doesn't is the workflow's defect, not the gate's).
Timeout, corrected against measured history: the accessible Actions history (the API serves the most recent 1,000 PR runs) tops out at Release Precheck taking 22m21s under multi-PR contention (2026-08-12), past the old gate's 20-minute timeout — the old "regular" timeout firings were CI legitimately outrunning the gate, not hangs (path filtering did not yet exist in the pr-monitor era, so the minimum-checks floor was never the cause). Setting timeout: 45 — double the observed maximum — so a firing means a hung job.
Changes
- Restore
.github/workflows/pr-monitor.yml(recovered fromf714f37^, updated:minimum-checks: 0,pre-sleep: 30,timeout: 45, drop deprecatedjob-name,actions: readpermission) - Delete
.mergify.yml - Rewrite AGENTS.md's "PR Monitoring" section (also resolves item 2 of Docs: post-#834 pass #932; items 1, 3–5 remain)
Maintainer actions required (cannot be done from a PR)
- Admin-merge the PR — the deadlocked Mergify gate on
mainblocks it like everything else (it supersedes revert Revert "ci: block merge while checks are still running" #947) - Branch protection: require
CI Gate, stop requiringMergify Merge Protections - Repo settings: enable Allow auto-merge (native auto-merge replaces the Mergify
auto-mergelabel) - Uninstall the Mergify GitHub App (also removes CI Insights auto-retry — flaky jobs go back to manual re-runs)
- Close 🚨 DO NOT MERGE — canary for merge-gate timing (#943) #946 (canary, served its purpose) and Revert "ci: block merge while checks are still running" #947 (superseded)
Acceptance (carried over from #943)
- Gate is pending, not green, while any check is running
- Gate goes green once all checks complete with none failed
- Gate goes red if any check fails
- A PR matching no path filter still merges (zero checks is a pass)
- No deadlock: the gate resolves on a normal PR
Activity
ci: raise the gate timeout to double the longest observed run
ci: remove Mergify, restore pr-monitor as the merge gate
ci: raise the gate timeout to double the longest observed run
ci: remove Mergify, restore pr-monitor as the merge gate
ci: raise the gate timeout to double the longest observed run
ci: remove Mergify, restore pr-monitor as the merge gate
ci: raise the gate timeout to double the longest observed run