Skip to content

merge-compile-guard: only a compile that finished red refuses; a slow read or a pending compile warns and merges - #24265

Merged
teamleaderleo merged 8 commits into
feat-cmux-nextfrom
gate-rules/merge-guard-only-red
Oct 22, 2026
Merged

teamleaderleo merged 8 commits into
feat-cmux-nextfrom
gate-rules/merge-guard-only-red

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Leo-ask: ask-99c1b0ed16
Leo-ask: ask-265dff2c7c
Leo-ask: ask-bdaebcd48a
Leo-ask: ask-daa4b85426
Leo-ask: ask-4c8d8efef8

Leo, 2026-10-21: "IF THE MERGE HOOK IS WRONG THEN JUST FUCKING MEREG", "WTF ARE YOU DOING WITH FUCKING MERGE HOOKS JUST MERGE!?", "DUDE I FUCJKING HATE YOUR MERGE HOOKS".

This repo's PreToolUse merge hook (.claude/settings.json → scripts/ci/guards-from-base.sh → scripts/ci/merge_compile_guard.py) refused merges it couldn't judge. On cosmic-gray at load ~200, its GitHub reads timed out and refused #23660 and #23371 for hours. Both had a SHIP receipt at the head, green fast gates and a green compile. It also refused every merge whose compile was still queued or running.

HQ's landing gate (require-cmux-guards.py, cmuxterm-hq#2960 and #2976) already refuses only four things:

  • no SHIP receipt at the head;
  • a compile that finished red;
  • --admin;
  • --auto without a pinned head.

A pending compile or a slow read is only a warning there. This PR makes the repo hook agree.

What changes

  • Still refused: a Swift PR whose cmux-next Release compile (Xcode 26) or cmux-next app compile (build fleet) finished red with no passing attempt. A red fleet compile refuses even while a Release compile is queued beside it, and a fleet compile-check pass doesn't clear it.

  • Now a warning (a "Hold"), not a refusal:

    • a compile that is still queued or running, hasn't been created yet, or was cancelled on every attempt;
    • a GitHub read that failed or ran out of time;
    • a merge the guard can't name (a shell variable, a GraphQL mutation);
    • a checkout it can't read.

    The hook prints a systemMessage plus additionalContext, with no permissionDecision. The merge goes ahead, and both the person and the agent see why.

  • A warning never hides a refusal. Every merge in the command is judged, and any red refuses.

  • guards-from-base.sh runs both guards.

    • A refusal is the answer as soon as its guard gives it. It is read as JSON, whatever the spacing.
    • Otherwise the guards' warnings are joined into one, so a merge's warning never hides the update-branch warning in the same command.
    • A guard that crashes or exits non-zero is only a warning. Claude Code treats exit 2 as a block.
  • Guards that can't be loaded: when guards-from-base.sh or the settings hook can't load the guards from origin/feat-cmux-next, it now warns instead of refusing.

  • Launcher failure: if the launcher itself fails, the settings hook exits 1, which doesn't block.

Overlap: #23858 (lane-host) replaces this guard with the installed HQ gate and deletes these files. It conflicts with feat-cmux-next and has been idle since 2026-10-21 23:50Z. Whichever PR lands second takes the other's side; nothing here blocks it.

Review

A Codex reviewer (gpt, xhigh, on cmux16) blocked three rounds. Each finding got a failing test first, then a fix:

  1. A red fleet compile next to a queued Release compile read as a wait. A guard exiting 2 blocked the tool call. A merge warning short-circuited the update-branch warning.
  2. A refusal written with other JSON spacing was merged into a warning.
  3. A known refusal waited behind the slower advisory hook and could be lost to the 120 s timeout.

Round 4: SHIP at the head.

Tests

  • python3 tests/test_merge_compile_guard.py: 54 OK.
  • python3 tests/test_guard_hooks_from_base.py: 17 OK.

Every behaviour change has a failing test committed before its fix (d8d6e2a, 3b19f09 and the two later (red) commits). The new cases:

  • a slow GitHub (gh sleeps past CMUX_MERGE_GUARD_GH_TIMEOUT=1) and an unreadable GitHub let the merge through with a warning;
  • a pending compile warns; a red Release compile or fleet compile refuses;
  • in gh pr merge "$PR" ...; gh pr merge 5 ..., the warning on the first merge doesn't hide the red on the second;
  • a crashing guard or launcher never exits 2;
  • a refusal comes back within 20 s while a 30 s advisory guard is still running;
  • a refusal written with indent=2 and odd separators still refuses.

Observed / Not run

  • Observed: both suites on cmux16. cmux16 has no timeout, which the settings hook uses for its fetch, so a stand-in that runs the command went first on PATH. scripts/cmux-next/prepush-gate.py: no new violations.
  • Not run: a live merge under load. The stop condition is an under-load merge of a gated PR going through, and I'll report that once this is on feat-cmux-next.

Changelog

none

Agent session: Air-Blue

🤖 Generated with Claude Code

teamleaderleo and others added 2 commits October 21, 2026 23:59
…red)

The guard's GitHub reads timed out under load on cosmic-gray and refused #23660 and #23371 for hours with
a SHIP receipt at the head and a green compile. These tests expect a pending compile, an unreadable GitHub,
a merge the guard can't name and guards it can't load to warn and let the merge through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue
…st warns and merges

Under load on cosmic-gray (2026-10-21) the guard's GitHub reads timed out and refused #23660 and
#23371 for hours with a SHIP receipt at the head and a green compile. Leo: "IF THE MERGE HOOK IS
WRONG THEN JUST FUCKING MERGE". HQ's landing gate (require-cmux-guards.py, cmuxterm-hq#2976)
already refuses only a missing SHIP, a failed compile, --admin and an unpinned --auto; this repo
hook now agrees with it.

- A compile still waiting, a GitHub read that failed or ran out of time, a merge the guard can't
  name and a checkout it can't read are a Hold: a systemMessage plus additionalContext, no
  permissionDecision, and the merge goes ahead.
- A red compile still refuses, and a Hold earlier in the command never hides a red later in it.
- guards-from-base.sh and the settings hook warn instead of refusing when they can't load the
  guards from the base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue
@teamleaderleo teamleaderleo added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 22, 2026
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review beeca0b: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr24265 -f ref=gate-rules/merge-guard-only-red -f platform=macos -f backend_mode=local

red: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: red check: Checks job structure (+1 more) is not red on the base a3feffa; do not merge until green; see lane-rules

@blacksmith-sh

blacksmith-sh Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Found 10 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp2gfyf0ui/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmplold6une/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs
test_every_part_of_bun_run_check_runs_in_the_warn_branch (main.WebviewsWarnSplitCov
ersCheck.test_every_part_of_bun_run_check_runs_in_the_warn_branch)/
test_every_part_of_bun_run_check_runs_in_the_warn_branch (main.WebviewsWarnSplitCov
ersCheck.test_every_part_of_bun_run_check_runs_in_the_warn_branch)
View Logs
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules)/
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules)
View Logs
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules) (job='web-bundles')/
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules) (job='web-bundles')
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-n8m90 created for this PR by the cmux coordinator.

teamleaderleo and others added 6 commits October 22, 2026 01:31
…a hidden update-branch warning (red)

From the Codex review of #24265: a failed build-fleet compile next to a queued Release compile read as
a wait; a guard exiting 2 blocks the tool call; a merge warning short-circuited the update-branch warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue
…ase compile; a guard's failure and a merge warning never block or hide

From the Codex review of #24265:
- fleet_red(): a build-fleet compile that finished red with no passing attempt (of it or of the Release
  compile) refuses before any pending state, and compile_wait() no longer reads it as a wait, so neither a
  queued Release compile nor a fleet pass turns it into a warning.
- guards-from-base.sh runs both guards. A refusal is the answer at once; otherwise every warning is joined
  into one answer, so a merge's warning never hides the update-branch warning of the same command. A guard
  that exits non-zero is a warning, never the exit 2 that blocks a tool call.
- The settings hook exits 1 (a non-blocking error) when the launcher itself fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue
The loop matched "permissionDecision": "deny" literally, so a valid refusal written with other spacing was
merged into a warning and lost (Codex review of #24265, round 2). The merger now parses each answer and
passes a refusal through as it is before joining warnings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue
Both guards ran before any refusal was read, so a slow update-branch warning could run the hook past its
120 s timeout with the refusal unprinted, and the merge went through (Codex review of #24265, round 3).
Each answer is read as JSON right after its guard; a refusal is printed and the loop ends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a1602e-bc09-7990-8c75-5c412a66b114&host=Air-Blue
@cursor

cursor Bot commented Oct 22, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex xhigh, correctness first): SHIP at beeca0b

An independent Codex reviewer (xhigh, on cmux16) reviewed four rounds. Each block got a failing test and then a fix:

  1. Round 1 at 89b2e8e, BLOCK.
    • A red build-fleet compile next to a queued Release compile was read as a wait, so it only warned.
    • A guard exiting 2 blocked the tool call.
    • A merge warning short-circuited the update-branch warning.
  2. Round 2 at f86daab, BLOCK. A refusal with other JSON spacing was string-matched, missed, and turned into a warning.
  3. Round 3 at 02026aa, BLOCK. A known refusal waited behind the advisory hook and could be lost to the 120 s timeout.
  4. Round 4 at beeca0b, SHIP. Nothing blocking:
    • refusals are parsed as JSON and printed before the next guard runs;
    • a red fleet compile still refuses beside a queued Release compile;
    • a warning on one merge never hides a red on a later one;
    • a guard's failure never exits 2;
    • compound warnings are joined.

Suites, by the reviewer and on cmux16: tests/test_merge_compile_guard.py 54 OK, tests/test_guard_hooks_from_base.py 17 OK.

@teamleaderleo teamleaderleo added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Oct 22, 2026
@teamleaderleo
teamleaderleo merged commit fae1562 into feat-cmux-next Oct 22, 2026
@teamleaderleo
teamleaderleo deleted the gate-rules/merge-guard-only-red branch October 22, 2026 09:39
teamleaderleo added a commit that referenced this pull request Oct 26, 2026
Conflicts with #24265 (merge-compile-guard: only a compile that finished red refuses) resolved toward
both: the repository still keeps no merge guard, and guards-from-base.sh takes #24265's rules. A gate
that is not installed, crashes or can't be read is a warning and the merge goes ahead; a refusal still
wins and is printed before the update-branch warning runs; every warning is joined into one answer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-707fe4a5f156f632733f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant