You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The gate merged a PR while its required checks were still running — and they failed
#10177, from the GitHub check-runs API on its head SHA:
merged: 2026-07-31T11:20:43Z
validate-code success completed 11:14:00 (before the merge)
validate-tests FAILURE completed 11:23:59 (3 min AFTER the merge)
validate FAILURE completed 11:26:32 (6 min AFTER the merge)
validate is the required aggregator. It had not completed when the merge happened, and it subsequently failed. The PR was merged on an incomplete check set.
This is the cause of today's three main outages
main went red on dead-exports:check three times today — #9944, #10109, #10194 — each blocking every open PR until someone noticed by hand. Each was assumed to be an independent slip. They are the same failure: a PR merged before its checks finished, so the breakage landed on main and only surfaced afterwards.
For #10194 specifically: MCP_SERVER_NAME was dead in #10177's own tree — git grep MCP_SERVER_NAME 2cafde31b finds no reference outside src/mcp/server.ts. So this was catchable pre-merge. It was not caught because the merge did not wait.
Why this matters more than the individual breakages
The gate's entire safety argument is "green CI + passing gate + mergeable-clean ⇒ auto-merge". If merge can fire while required checks are still pending, that argument does not hold — the PR was never actually green. Every guard the repo has (the exhaustiveness checkers, the drift tests, the invariant suites) is downstream of a merge that waits for them.
It also silently undermines #10146: that escalation notices a workflow red across consecutive runs, but here the first red arrives after the merge that caused it, so by the time anything escalates the damage is already on main.
What to investigate
Does the disposition treat "check not yet reported" as satisfied? assessMergeableState maps GitHub's unstable (checks failing OR still running) — and gate: an unstable merge state summons a human and then latches the manual-review label #10116 deliberately stopped that from holding. That change is correct for the manual-review label, but merge eligibility must still require the required checks to have COMPLETED, not merely to be non-failing. Worth confirming wouldMerge's mergeable === "clean" is actually sufficient here: GitHub reports clean when required checks pass, but the aggregate may be evaluated from a stale snapshot.
Is the executor's live re-check reading a cached check-run set? refreshLiveCiAggregate and the durable CI-state cache are both in this path, and the cache is invalidated per check_suite.completed — a merge decision taken between the invalidation and the refetch would see the pre-completion snapshot.
The 11:14 → 11:20 gap between validate-code succeeding and the merge suggests the decision was made on a partial set that looked complete.
Priority
P0 in effect: it is the mechanism by which broken code reaches main, and it has fired three times in one day. Every other guard in the repo assumes it does not happen.
Found while investigating why #10194's dead export was not caught pre-merge.
The gate merged a PR while its required checks were still running — and they failed
#10177, from the GitHub check-runs API on its head SHA:
validateis the required aggregator. It had not completed when the merge happened, and it subsequently failed. The PR was merged on an incomplete check set.This is the cause of today's three
mainoutagesmainwent red ondead-exports:checkthree times today — #9944, #10109, #10194 — each blocking every open PR until someone noticed by hand. Each was assumed to be an independent slip. They are the same failure: a PR merged before its checks finished, so the breakage landed onmainand only surfaced afterwards.For #10194 specifically:
MCP_SERVER_NAMEwas dead in #10177's own tree —git grep MCP_SERVER_NAME 2cafde31bfinds no reference outsidesrc/mcp/server.ts. So this was catchable pre-merge. It was not caught because the merge did not wait.Why this matters more than the individual breakages
The gate's entire safety argument is "green CI + passing gate + mergeable-clean ⇒ auto-merge". If merge can fire while required checks are still pending, that argument does not hold — the PR was never actually green. Every guard the repo has (the exhaustiveness checkers, the drift tests, the invariant suites) is downstream of a merge that waits for them.
It also silently undermines #10146: that escalation notices a workflow red across consecutive runs, but here the first red arrives after the merge that caused it, so by the time anything escalates the damage is already on
main.What to investigate
assessMergeableStatemaps GitHub'sunstable(checks failing OR still running) — and gate: an unstable merge state summons a human and then latches the manual-review label #10116 deliberately stopped that from holding. That change is correct for the manual-review label, but merge eligibility must still require the required checks to have COMPLETED, not merely to be non-failing. Worth confirmingwouldMerge'smergeable === "clean"is actually sufficient here: GitHub reportscleanwhen required checks pass, but the aggregate may be evaluated from a stale snapshot.refreshLiveCiAggregateand the durable CI-state cache are both in this path, and the cache is invalidated percheck_suite.completed— a merge decision taken between the invalidation and the refetch would see the pre-completion snapshot.validate-codesucceeding and the merge suggests the decision was made on a partial set that looked complete.Priority
P0 in effect: it is the mechanism by which broken code reaches
main, and it has fired three times in one day. Every other guard in the repo assumes it does not happen.Found while investigating why #10194's dead export was not caught pre-merge.