Repository navigation
cmux guards: run merge guard hooks from the feat-cmux-next tip - #23316
Conversation
…request's checkout Red on fc8a36d: .claude/settings.json runs scripts/ci/*-hook.sh from $CLAUDE_PROJECT_DIR, so a pull request's own edit of the guard judges its merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
…ession's checkout .claude/settings.json ran scripts/ci/merge-compile-guard-hook.sh and base-merge-warning-hook.sh from $CLAUDE_PROJECT_DIR, so a session in a pull request's worktree ran that branch's guard: a branch made before a guard fix kept the old one, and a pull request could edit the guard that judges its own merge (palette-audit). The hook now reads scripts/ci/guards-from-base.sh from origin/feat-cmux-next (fetched first for a merge) and that runs both guards and their hooks from the same commit, out of a temporary directory. Commands that mention neither a merge nor update-branch exit before git runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
… origin is fetched first Red on 648e6f7 (review): both failed open with only a stderr line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
… one it can't judge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
|
Owned by land-and-ci on huge-blue · session |
|
Review (subagent, correctness first): SHIP at b73989b I re-reviewed the whole diff at b73989b and the merge fail-open from my earlier BLOCK is fixed. The four tests all pass:
Nothing else changed from my earlier pass: no checkout code runs, and the filters, timeouts and output order are unchanged. Two limits remain, and neither blocks:
|
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
red: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: |
|
Found 3 test failures on Blacksmith runners: Failures
|
|
Bead |
#23316 added tests/test_guard_hooks_from_base.py without a tests/test-execution.toml entry. The registry check fails on feat-cmux-next, and every branch's pre-commit hook adds the entry on its own, so open PRs conflict with each other on the registry. Its lane is linux-guard, as the hook registers it and like the other guard tests. Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d18-aabc-7850-af29-f0655b1d2a1a&host=cosmic-gray Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Shipped in:
|
The merge guards now run from the feat-cmux-next tip, never from the session's checkout. palette-audit found that
.claude/settings.jsonran"$CLAUDE_PROJECT_DIR"/scripts/ci/merge-compile-guard-hook.shandbase-merge-warning-hook.shfrom the session's checkout. A session in a pull request's worktree therefore ran that branch's copy of the guard: a branch made before a guard fix kept the old guard, and a pull request could edit the guard that judges its own merge.Fix
scripts/ci/guards-from-base.shfromorigin/feat-cmux-nextinto a temporary file and runs it. For a merge, it first fetchesfeat-cmux-next, bounded to 10 s. Commands that mention neither a merge nor update-branch exit before git runs.scripts/ci/guards-from-base.shextracts both hooks and their Python guards from that same commit into a temporary directory, withgit archive, and runs them. The first answer, a refusal or a note, is the answer.merge_compile_guard.pyrefuses one it can't read. The update-branch warning only warns.Known limit:
.claude/settings.jsonitself still loads from the session's checkout, so a branch cut before this change keeps the old hooks until it merges the base. A PR could also delete the hook.Tests:
tests/test_guard_hooks_from_base.pyis new and wired into cmux-next.yml. It builds a local remote and a PR worktree whose branch rewrites both guards and their hook to let everything through. The test checks:origin/feat-cmux-nextis fetched before a merge;$CLAUDE_PROJECT_DIR.Red:
python3 tests/test_guard_hooks_from_base.pyon 284ed32 (base code) failed with "the pull request's own copy of the guard judged its merge", and on 648e6f7 two cases failed (the stale origin and unreadable guards both failed open). Green on the head: 8 OK.Observed / Not run
tests/test_merge_compile_guard.py,tests/test_base_merge_warning.pyandtests/test_format_post_edit.pyall pass (1 skip: webviews packages are not installed).settings.jsonwith bash.Changelog
none
Agent session: huge-blue
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Merge guards now run from the
feat-cmux-nexttip instead of the session's checkout, so a pull request's branch can no longer run its own edited copy of the guard that judges its merge.origin/feat-cmux-next(bounded to 10 s) and runsscripts/ci/guards-from-base.shfrom that commit, which executes both merge guards viagit archiveinto a temporary directory..claude/settings.jsonstill loads from the session's checkout, so a branch cut before this change keeps the old hooks until it merges the base.Tests
tests/test_guard_hooks_from_base.py(wired into cmux-next.yml) covers base-copy judging of merges, guard fixes on the base applying to older branches, stale origin fetching, fail-closed merges, and no hook running a script from the checkout.Written for commit b73989b. Summary will update on new commits.