cmux guards: a merge goes to the landing gate installed from cmuxterm-hq; the repository keeps no merge guard
After hq#2830, #23472 at 7e688473 still got "could not read #23472". Its hook already runs scripts/ci/guards-from-base.sh from origin/feat-cmux-next (#23316), but the merge guard it runs is a copy in this repository. A copy here reaches a worktree only through a fetch or a base merge, so a fix in it can lag behind. Decision (deputy-2, 2026-10-21): every merge guard runs from the copy guards-sync installs from cmuxterm-hq main (every 10 minutes), never from a copy in a worktree.
The installed landing gate (require-cmux-guards, cmuxterm-hq tools/agent-guards) already enforces every rule merge_compile_guard.py did, on the exact head of a feat-cmux-next PR that changes Swift:
- It requires a green
cmux-next Release compile (Xcode 26), using the same Swift file set. - Its gh reads bypass the PATH guard's repeat throttle (
CMUX_GH_GUARD_DISABLE=1). - All its reads share one bounded budget.
Any merge merge_compile_guard.py refused, the gate refuses too, so its rules have nothing left to move.
So this PR:
- Merges go to the installed gate.
guards-from-base.shno longer runs a merge guard from the repo. For a merge it does one of three things:- Gate registered in this account's settings (
${CLAUDE_CONFIG_DIR:-~/.claude}/settings.json, checked the same wayinstall.pychecks): it defers, because Claude Code runs the gate itself. That avoids a second set of GitHub reads. - Gate file installed but not registered: it runs
~/.claude/hooks/require-cmux-guards.shitself. - Gate not installed (no file, or a registration with no file behind it): the merge goes ahead with a warning that names
guards-syncandinstall.py. That follows #24265: no guard blocks a merge it can't judge, only a compile that finished red. A gate that crashes or exits non-zero is a warning too.
- Gate registered in this account's settings (
- Refusals and warnings are combined as #24265 does: a refusal from the gate is printed right away, before the update-branch warning runs. Otherwise every warning is joined into one answer, so a merge warning never hides the update-branch warning in the same command.
- The update-branch warning is unchanged. It still runs from origin/feat-cmux-next.
- Removed:
scripts/ci/merge_compile_guard.py, its hook, and its test. The CI step and the test-execution entry for them go too. - Workflow comments: the fleet workflows' comments now say what gates the merge.
- Reach: every worktree whose settings include #23316 gets this on its next merge-time fetch. A worktree cut before #23316 keeps running its own copy until its next base merge.
Not carried over: merge_compile_guard let a fleet compile-check pass stand in for a queued Release compile. Neither the installed gate nor next-autoland ever accepted that, so it was already dead wherever the gate is installed. Accepting it would loosen the gate, and that is a separate decision.
Takes back #22947: it added the in-repo merge guard and its CI test entries; this PR removes that guard on purpose, since the installed landing gate from cmuxterm-hq judges every merge.
Takes back #23423: only its edit to tests/test_merge_compile_guard.py, which goes with the guard.
Takes back #23827: only its edit to tests/test_merge_compile_guard.py, which goes with the guard.
Takes back #24265: only its edits to the removed guard and its test; its rules (only a red compile refuses, everything else warns) are kept in guards-from-base.sh.
Base merge (2026-10-26, adopted by the stall reconciler): the merge with feat-cmux-next conflicted with #24265, which had loosened the repository guard this PR removes. I resolved it toward both: the repository still keeps no merge guard, and guards-from-base.sh follows #24265's rules (above). #24265's tests were ported to the installed gate. tests/test_guard_hooks_from_base.py passes 22/22 and tests/test_base_merge_warning.py passes at aa848609.
Earlier tests (cmux16; the test needs timeout on PATH, which Linux CI has and macOS lacks):
- Red at 476c4538: 10 of 15 failed.
- Green at a8230d0a:
tests/test_guard_hooks_from_base.pypasses 15/15 on Python 3.13 and on /usr/bin/python3 3.9, andtests/test_base_merge_warning.pypasses 10/10.
Agent session: agent session
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Merges are now judged by the landing gate installed from cmuxterm-hq (require-cmux-guards), never by a copy of the merge guard in this repository.
For a merge, guards-from-base.sh defers to the gate when registered in this account's settings, runs the installed gate file when present but not registered, and refuses the merge with install instructions when the gate is missing. The update-branch warning still runs from origin/feat-cmux-next.
Removed: scripts/ci/merge_compile_guard.py, its hook, tests, and the CI step that ran them. The old guard let a fleet compile-check pass stand in for a queued Release compile; the installed gate never accepted that, so that behavior is dropped too.