Skip to content

cmux-next gate: a stale hook install refuses; never fall back to the pushed checks - #34237

Merged
lawrencecchen merged 7 commits into
feat-cmux-nextfrom
fix/prepush-stale-install-refuses
Nov 3, 2026
Merged

lawrencecchen merged 7 commits into
feat-cmux-nextfrom
fix/prepush-stale-install-refuses

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Its base #34219 has merged (c874cb9), and #34197 merged first (884c330), so feat-cmux-next was merged into this branch (a6ad589, no force push). Neither touches this PR's lines: feat's prepush-gate.py is byte-identical to #34219's head, and #34197 changed only web_lint_prepush.py. This PR's own change over feat is two files.

The pre-push hook must never run code that the push controls (docs/contributor-verification.md, trust boundary). When the installed hook was older than a check, the cmux-next gate fell back to the pushed head's copy:

  • of check-leo-bans.py and check-ghostty-reserved-keys.py, which it then ran;
  • of scripts/swift_source_mask.py, which it wrote into the check trees, where check-package-dependency-lists.py imports it.

Now, on a hook run (--trusted-scripts-dir), a check that the pushed head has but the install lacks refuses the push with:

the installed hook is older than the checks this push needs: rerun scripts/install-git-hooks.sh

The pushed copy is never run or written. A head older than the check skips it, as before. A manual run, with no --trusted-scripts-dir, still reads the checkout's copy. A current install has all three files, so it is not affected.

Folded in, per the earlier review of #34219:

  • The perf cron comment no longer says the push runs the tests.
  • The refusal message no longer names the perf cron tests.
  • The dead guarded = perf_cron_tests(...) or guarded line is gone.

Testing

Red on e2550b6 (#34219's head; the tests are in their own commit), green on the head:

(cd tests && python3 -m unittest -k stale_install -k refuse_an_install_without_the_masker test_cmux_next_prepush_gate)
  • On the base: 3 failures. The hook ran a pushed check-leo-bans.py and a pushed check-ghostty-reserved-keys.py (each writes a marker file), and build_trees did not refuse an install without the masker.
  • On the head: all pass. The push is refused with the message above, nothing pushed runs, and the check trees hold only the installed masker.

Observed / Not run

Observed:

  • python3 tests/test_cmux_next_prepush_gate.py: 91 tests OK, including the stale-install lint-tools.lock test added after review.
  • python3 scripts/cmux-next/prepush-gate.py: no new violations.

Not run:

  • A real push from a stale install on a Mac. The test uses the real installer and a real git push, with the file removed from the installed copy.

Changelog

none

Proof

No capture: hook tooling only.

…tests in the hook (red)

The pre-push hook never runs code the push controls (docs/contributor-
verification.md, trust boundary). perf_cron_tests runs the pushed head's own
test_perf_cron.py (git archive, then unittest), so a pushed branch's test file
runs on the machine that pushes it. This test pushes one that writes a marker.

Red on 18753d8:
  (cd tests && python3 -m unittest -k perf_cron_never test_cmux_next_prepush_gate)
… its code in the hook

The pre-push hook never runs code the push controls (docs/contributor-
verification.md, trust boundary). perf_cron_tests ran the pushed head's own
test_perf_cron.py (git archive, then unittest), so a pushed branch's test file,
or the perf-cron.py it imports, ran on the machine that pushes it. Running the
reviewed copy of the tests would still import the pushed perf-cron.py.

The gate now names the changed perf cron files and the command to run its tests
on code the person trusts, and never refuses the push for them. CI does not run
them either (no new CI tests), as before this gate step was added (9d483d2).

Red on 18753d8 (tests in 6d8a01f), green here:
  (cd tests && python3 -m unittest -k perf_cron_never test_cmux_next_prepush_gate)
python3 tests/test_cmux_next_prepush_gate.py: 88 tests OK.
… check (red)

Review of e2550b6 (#34219): on a hook install older than a check, the gate
fell back to the pushed head's check-leo-bans.py and check-ghostty-reserved-
keys.py, and the check trees took the pushed scripts/swift_source_mask.py. The
hook never runs code the push controls, so these tests expect a refusal that
says to rerun scripts/install-git-hooks.sh, and no pushed code run.

Red on e2550b6:
  (cd tests && python3 -m unittest -k stale_install -k refuse_an_install_without_the_masker test_cmux_next_prepush_gate)
  3 failures.
…he pushed checks

Review of e2550b6 (#34219): on a hook install older than a check, the gate
ran the pushed head's check-leo-bans.py and check-ghostty-reserved-keys.py, and
the check trees took the pushed scripts/swift_source_mask.py. The hook never runs
code the push controls.

- check_script(): on a hook run (--trusted-scripts-dir), a check the pushed head
  has but the install lacks refuses the push with "the installed hook is older
  than the checks this push needs: rerun scripts/install-git-hooks.sh". A head
  older than the check skips it, as before; a manual run reads the checkout's.
- build_trees(): on a hook run the masker comes only from the install; an install
  without it refuses the same way, and the pushed copy is never written.
- Folded cleanups: the perf cron comment, the refusal message no longer names the
  perf cron tests, and the dead `guarded = perf_cron_tests(...) or guarded` line.

Red on 8b66cd3^ (tests in 8b66cd3), green here.
python3 tests/test_cmux_next_prepush_gate.py: 90 tests OK.
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

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

Review a6ad589: 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=pr34237 -f ref=fix/prepush-stale-install-refuses -f platform=macos -f backend_mode=local

red: cmux-next page strings generate; base red: the same failure on the base d668dcf; does not block

Shipped in:

@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Nov 3, 2026
…e checkout (red)

Review of 9b89be5: an install with no lint-tools.lock read the checkout's
lock (the pushed branch) and downloaded and ran the binary it names; the sha256
check proves nothing, as it comes from the same lock. This test pushes a lock
that names a marker binary and removes the installed lock.

Red on 9b89be5:
  (cd tests && python3 -m unittest -k tool_pins_from_the_checkout test_cmux_next_prepush_gate)
… checkout

Review of 9b89be5: on a hook run with an install that has no
lint-tools.lock, the gate read the lock and lint configs from the checkout (the
pushed branch) and downloaded and ran the binary the lock named; its sha256
proved nothing, as it comes from the same file. A hook run now takes the pins
only from the installed reviewed copy and refuses an install without them with
the stale-install message. A manual run reads the head's, else the checkout's,
as before. Also: check_script's docstring says a manual run reads HEAD's copy.

Red on ae1e761^ (test in ae1e761), green here.
python3 tests/test_cmux_next_prepush_gate.py: 91 tests OK.
@blacksmith-sh

blacksmith-sh Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Found 36 test failures on Blacksmith runners:

Failures

Test View Logs
main.DeveloperIdAppTests.test_download_prints_the_active_profile_only/
test_download_prints_the_active_profile_only
View Logs
stubs: /System/Library/Frameworks/Security.framework/Versions/A/Security has no stub/
Security has no stub
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_CFRetain']/
CoreFoundation, missing 1: ['_CFRetain']
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_log2']/
CoreFoundation, missing 1: ['_log2']
View Logs
test_a_build_host_runs_every_piece_niced_and_capped (main.WebLintPrePushTests.test_
a_build_host_runs_every_piece_niced_and_capped)/
test_a_build_host_runs_every_piece_niced_and_capped (main.WebLintPrePushTests.test_
a_build_host_runs_every_piece_niced_and_capped)
View Logs
test_a_clean_pushed_commit_passes_whatever_the_working_tree_holds (main.WebLintPreP
ushTests.test_a_clean_pushed_commit_passes_whatever_the_working_tree_holds)/
test_a_clean_pushed_commit_passes_whatever_the_working_tree_holds (main.WebLintPreP
ushTests.test_a_clean_pushed_commit_passes_whatever_the_working_tree_holds)
View Logs
test_a_clean_swift_only_push_runs_only_the_pieces_that_read_it (main.WebLintPrePush
Tests.test_a_clean_swift_only_push_runs_only_the_pieces_that_read_it)/
test_a_clean_swift_only_push_runs_only_the_pieces_that_read_it (main.WebLintPrePush
Tests.test_a_clean_swift_only_push_runs_only_the_pieces_that_read_it)
View Logs
test_a_clone_with_no_reviewed_remote_lints_no_check_code (main.WebLintPrePushTests.
test_a_clone_with_no_reviewed_remote_lints_no_check_code)/
test_a_clone_with_no_reviewed_remote_lints_no_check_code (main.WebLintPrePushTests.
test_a_clone_with_no_reviewed_remote_lints_no_check_code)
View Logs
test_a_dry_run_lists_exactly_what_a_run_spawns (main.WebLintPrePushTests.test_a_dry
_run_lists_exactly_what_a_run_spawns)/
test_a_dry_run_lists_exactly_what_a_run_spawns (main.WebLintPrePushTests.test_a_dry
_run_lists_exactly_what_a_run_spawns)
View Logs
test_a_file_in_a_folder_above_a_package_is_check_code (main.WebLintPrePushTests.tes
t_a_file_in_a_folder_above_a_package_is_check_code)/
test_a_file_in_a_folder_above_a_package_is_check_code (main.WebLintPrePushTests.tes
t_a_file_in_a_folder_above_a_package_is_check_code)
View Logs

...and 26 more test failures. View all on Blacksmith

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

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Review (independent-subagent): SHIP at 092d020

Two rounds. The BLOCK at 9b89be5 found one more fallback of the same kind: an install with no lint-tools.lock read the checkout's lock and downloaded and ran the binary it named. That is now fixed with a red test first (ae1e761).

On a hook run, when the installed hook lacks a check, the masker or the tool pins, the gate refuses with "the installed hook is older than the checks this push needs: rerun scripts/install-git-hooks.sh". It never runs or writes the pushed copy.

  • The lock and the lint/ configs come only from the installed copy. read_lock and ensure_tool have no other callers.
  • A head older than a check still skips it.
  • A manual run behaves as before.
  • A current install refuses nothing: install-git-hooks.sh and refresh_checks.py copy all of these files.
  • The three cleanups from cmux-next gate: never run the pushed perf cron tests in the pre-push hook #34219's review are correct.
  • python3 tests/test_cmux_next_prepush_gate.py: 91 tests OK. It merges cleanly with feat-cmux-next.
  • risk:high, so this SHIP is on the exact head.

Nit: import hashlib and zipfile sit inside the test body.

@lawrencecchen lawrencecchen 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 Nov 3, 2026
…-stale-install-refuses

# Conflicts:
#	scripts/cmux-next/prepush-gate.py
@lawrencecchen lawrencecchen removed the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Nov 3, 2026
@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Review (independent-subagent): SHIP at a6ad589

Renewed after #34219 merged as a squash (c874cb9) and #34197 merged first (884c330). This is a merge of feat-cmux-next into the earlier SHIP head 092d020; no force push.

  • The only conflict came from the squash: feat's prepush-gate.py is byte-identical to cmux-next gate: never run the pushed perf cron tests in the pre-push hook #34219's head e2550b6. This branch's side was kept.
  • prepush-gate.py and its test file are identical to 092d020. Over feat, the PR changes only those two files.
  • feat's newer web_lint_prepush.py runs before the gate in the hook. The full suite passes at the merge head: python3 tests/test_cmux_next_prepush_gate.py, 91 tests OK (run by the reviewer and by the author).
  • risk:high, so this SHIP is on the exact head.

@lawrencecchen lawrencecchen 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 Nov 3, 2026
@lawrencecchen
lawrencecchen merged commit 9b2b57f into feat-cmux-next Nov 3, 2026
206 of 219 checks passed
@lawrencecchen
lawrencecchen deleted the fix/prepush-stale-install-refuses branch November 3, 2026 23:25
teamleaderleo added a commit that referenced this pull request Nov 4, 2026
…eam in the Chromium page fake (#34430)

* tests: web lint hook fixture pins stand-in lint tools for the cmux-next gate

#34237 made the installed gate refuse an install with no lint-tools.lock.
The web lint fixture copied no lock, so all 32 fixture pushes failed with
"the installed hook is older than the checks this push needs". The fixture
now commits a lock pinning no-op stand-ins and puts them in
CMUX_LINT_TOOLS_DIR, so the gate runs and nothing is downloaded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* cmux-next: the hanging Chromium page fake's stream has a buffer cap

#34250 added an AsyncStream.makeStream() with the default unbounded buffer,
which the Main-thread concurrency check refuses. Nothing yields to it, so
.bufferingNewest(1) changes no behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — a6ad5896 Deployed Nov 3, 2026 by lawrencecchen via wait for same-key tree publisher #107844
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:high Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant