Public: anyone can read this; the crew can change it.
The gate cannot lock itself out: a known-good gate and a break-glass path #7823
Check · Review · Land · Live done — Landed and live in production.
An owner can now land one named pull past a broken gate with a recorded reason, and the forge says when landing has stopped. A new test replays the scenario and passes, as do `tsc`, `scripts/gate.ts` and about 220 related tests. The design lint printed only its pass line. I did not run the full suite; `scripts/fast.ts` named 1258 files, so I picked the covering ones myself.
shipped production is serving it deploy f18c0e5
An owner can now land one named pull past a broken gate with a recorded reason, and the forge says when landing has stopped. A new test replays the scenario and passes, as do tsc, scripts/gate.ts and about 220 related tests. The design lint printed only its pass line. I did not run the full suite; scripts/fast.ts named 1258 files, so I picked the covering ones myself.
- Landing has stopped. When the repository's last 3 merge-queue gates are all red and nothing has landed since the first of them, the flow alarms add one sentence starting "Landing has stopped:". It shows on home and on
/boards, which is the pipeline and where/flowredirects. Like the other flow alarms, it is shown to the owner only. The logic is insrc/checks/gate_stopped.ts, wired throughsrc/flow/alarms.ts. - Break-glass. On a pull waiting on checks, a repository admin who is a person gets a "Land past the gate" form with a reason. The same action is available over MCP as
land_past_gate, which plans first unlessdryRunis false. It needs no hand push.
- What it skips: only the checks requirement. Review, conflicts and the rule that agents never land still apply.
- Trail: the reason (8–500 characters) is posted as a comment on the pull and written to the outbox as pull.bypassed.
- Code: src/checks/bypass.ts, with a pastGate option on mergePull, a route in src/web/pages/pull.ts and the tool in src/http/mcp/tools/land_past_gate.ts.
- Test.
test/gate-bypass.test.tsshows three red gates raise the alarm. The fix pull is refused normally, refused for a non-owner, refused without a reason, then lands past the gate with the reason on its trail. The stop clears, and the next pull lands only with a green check by the usual route. - Docs.
docs/features/gate-bypass.mdand the regenerateddocs/MCP.mdtable.
I did not build running the gate from a pinned earlier release rather than the tree being judged. That is a larger change to the check lane and needs its own pull.
"Same base" is approximated as no pull having merged since the earliest of the three red gates, because gate results don't record the base. A false alarm would need a gate-stopped state with nothing landing, so it self-clears on the next landing.
I did not try it against a running app.
To try it: with the owner signed in, open a pull that has no green check on a repository that requires checks and use "Land past the gate". Or call land_past_gate { repo, number, reason, dryRun: false } over MCP.
🤖 Generated with Claude Code
The failing test is fixed and pushed. The new pull.bypassed event had no audience, so src/core/event_audience.ts now lists it as readers' to see. The reason is already public on the pull's trail comment, so readers is consistent with that.
test/event-audience-coverage.test.ts and test/gate-bypass.test.ts pass (7 tests), and tsc is clean. I did not rerun the full suite. The forge's check will run it on this push.
The pull description stays as before: an owner lands one named pull past a broken gate with a recorded reason, and the forge says when landing has stopped. I did not build running the gate from a pinned earlier release.
One of the two failures was caused by my change, and I fixed it. The other looks like load timing, not my code.
- MCP protocol test:
test/mcp.test.tslists every tool by name, andland_past_gatewas missing from that list. I added it. The file passes now. - "200 branches hold the 50 ms budget": this passes when I run
test/branches-many.test.tshere. It's a timing test, and the check's shard 22 ran it while the machine was busy. My change touches nothing it measures. I haven't confirmed it's a flake. If it fails again on this push, tell me and I'll look at it properly.
I ran test/mcp.test.ts and test/branches-many.test.ts (53 tests, all pass) and pushed. I did not run the full suite. The forge's check will run it on this push.
The pull description is unchanged: an owner can land one named pull past a broken gate with a recorded reason, and the forge says when landing has stopped. I did not build running the gate from a pinned earlier release.
Changes needed (first round, all in one list). I read the diff; I did not drive the preview as an owner session.
- Terminal door missing (fix first). The page and MCP can land past the gate, but
src/tty.tscannot, and the README does not say how. Add the command in tty with the same owner-only, non-agent check, the reason, and a dry-run/confirm step, and document it where the other tty commands are documented. Thelanding_stoppedalarm must also show in the terminal wherever it shows the other flow alarms.
- The break-glass is offered on every pull waiting on checks, not just when landing has stopped. Any admin sees a standing 'Land past the gate' form on an ordinary pull. Show the form (and let
landPastGateand the MCP tool proceed) only whilelandingStopped(db, repo.id)is true for the forge's own repo; otherwise refuse with a clear message. Otherwise this is a permanent bypass of the checks requirement for every repo, which the issue did not ask for. It is also applied to any repo, though the stop is computed only for the forge's own repo.
- Design system. The form hand-rolls markup (
row-fields,sr-only, a bareinputand a second button next to a disabled primary) instead of the named components in docs/DESIGN.md. Use the documented field/form components, make the bypass a clearly secondary/danger action (one accent per page), and name any new class in docs/design/areas/<area>.md. Check it works with JavaScript off (it should, but show it in the preview).
- Tests do not cover the doors. Only the core function is tested. Add tests that fail without the change for: the web route
/land-past(403 for a guest, non-admin and agent; CSRF/same-origin refusal; the flash on a short reason; success), the MCP tool (agent refused, dryRun default changes nothing, dryRun:false lands, outsider/unseen pull is not found), the tty command, the alarm being owner-only (not shown to guests /publicOnly), and that review and conflicts still hold when bypassing. The stop test should also show that three red gates followed by a landing do not alarm, and that the stop does not fire with fewer than three gates of mixed state.
- Clean.
mergeFailure(e.message as never)is a type escape; giveBypassErrora proper union ({kind:'merge', error}) instead ofstring | {message}and map it without a cast. The MCP plan (dryRun) does not validate the reason length, so a plan can succeed for a reason the apply would refuse; validate in both. Inbypass.tsthe pull is merged before the trail comment and event are written; if the comment fails the bypass leaves no record, so record the intent first or do both in one transaction.
- 'Same base' is approximated by 'nothing merged since the first red gate'; three reds on different bases (e.g. three unrelated broken pulls) with no landing would raise a false 'landing has stopped' and unlock the bypass. Record the base on the gate result or compare the gates' tip/base, or say in the docs why the approximation is safe once item 2 is in place.
All six review items are addressed in eaffbedf. bun scripts/gate.ts and bun x tsc --noEmit are clean. bun scripts/design-lint.ts reported no violations. I ran 110 tests across the files that cover the change, and all passed. scripts/fast.ts named 1,262 files, which is too broad, so I picked the covering files myself. I did not drive the preview as an owner session.
- Terminal door.
- L on the terminal's pull screen, offered only to an owner who is a person while landing has stopped.
- It asks for the reason, shows it back in a confirm that defaults to Cancel, then lands through landPastGate.
- It is documented in the README and docs/features/gate-bypass.md.
- The landing_stopped alarm already reaches the terminal's Flow dialog through firedAlarms.
- The alarm is now owner-only: publicOnly readers never see it, which the first round got wrong.
- Offered only while stopped. The form, the page route, the MCP tool and the terminal all go through one check. The stop must hold, and the repo must be the forge's own (
ownLandingStopped). Otherwise the answer isnot_stopped: the page flashes a message and the MCP tool refuses, soelsewherecannot be bypassed. - Design. The form uses
field()with a hint and a.form-actionsrow holding adangerbtn. It sits under the disabled primary Merge button, so there is one accent.row-fieldsandsr-onlyare gone, and the area note is indocs/design/areas/forms.md. It is a plain post, so it works without JavaScript. - Tests.
test/gate-bypass.test.tsnow has 12 tests:
- Web: the route gives 403 to a guest, a non-admin and an agent, refuses a cross-origin post, flashes on a short reason, and succeeds for an owner. The form appears only while landing has stopped.
- MCP: an agent is refused, a dry run changes nothing and checks the reason, dryRun:false lands, and an unseen pull is not found.
- Terminal: L is hidden from an outsider and while landing runs, and the reason, confirm and landing steps all work.
- Alarm and stop rules: the alarm is owner-only, three reds then a landing do not alarm, and unrelated or mixed gates do not make a stop.
- Core: review and conflicts still hold when bypassing.
- Clean.
- BypassError is now a union with {kind:"merge", error}, so the cast is gone.
- planBypass runs the same checks for the MCP dry run and the apply.
- The intent comment is written before the merge, and a refused merge leaves a second comment saying so.
- pull.bypassed is appended only after a successful landing. If that append failed after the merge, the landing would have its comment but no event.
- "Same base". The gate result keeps no base, so I replaced the approximation with "one cause". The three red gates must share a failing test name, or name none and share a reason. Three unrelated broken pulls fail different tests and no longer raise the alarm. This is documented in
gate_stopped.tsand the feature doc.
Decision for you. The form is on the pull's Files step (/pulls/N/files), where the merge box lives, not on the studio change page, which only says "Not ready to ship". I did not add it there. The change page is the more visible place, so say if you want it there too.
Not done: running the gate from a pinned earlier release.
All earlier asks are met in eaffbedf. The terminal door L goes through landPastGate, as the page and MCP do. The break-glass is offered and accepted only while landing has stopped, and only on the forge's own repo. The alarm is owner-only. The form uses field() and a danger btn in .form-actions, with no new class. "Same base" is replaced by "one cause". The route checks who before reading the form, and readForm enforces same-origin. Review and conflicts still hold, and the tests cover every door. I did not drive the preview as an owner session.
Non-blocking: landPastGate writes the intent comment before it checks that the pull is open. A call on an already-merged or closed pull leaves a stray "Landing past the gate" comment on its trail. Refuse such a pull in bypassRefusal.
An owner can now land one named pull past a broken gate with a recorded reason, and the forge says when landing has stopped. A new test replays the scenario and passes, as do
tsc,scripts/gate.tsand about 220 related tests. The design lint printed only its pass line. I did not run the full suite;scripts/fast.tsnamed 1258 files, so I picked the covering ones myself./boards, which is the pipeline and where/flowredirects. Like the other flow alarms, it is shown to the owner only. The logic is insrc/checks/gate_stopped.ts, wired throughsrc/flow/alarms.ts.land_past_gate, which plans first unlessdryRunis false. It needs no hand push.- What it skips: only the checks requirement. Review, conflicts and the rule that agents never land still apply. - Trail: the reason (8–500 characters) is posted as a comment on the pull and written to the outbox as
pull.bypassed. - Code:src/checks/bypass.ts, with apastGateoption onmergePull, a route insrc/web/pages/pull.tsand the tool insrc/http/mcp/tools/land_past_gate.ts.test/gate-bypass.test.tsshows three red gates raise the alarm. The fix pull is refused normally, refused for a non-owner, refused without a reason, then lands past the gate with the reason on its trail. The stop clears, and the next pull lands only with a green check by the usual route.docs/features/gate-bypass.mdand the regenerateddocs/MCP.mdtable.I did not build running the gate from a pinned earlier release rather than the tree being judged. That is a larger change to the check lane and needs its own pull.
"Same base" is approximated as no pull having merged since the earliest of the three red gates, because gate results don't record the base. A false alarm would need a gate-stopped state with nothing landing, so it self-clears on the next landing.
I did not try it against a running app.
To try it: with the owner signed in, open a pull that has no green check on a repository that requires checks and use "Land past the gate". Or call
land_past_gate { repo, number, reason, dryRun: false }over MCP.🤖 Generated with Claude Code
Closes #7790