cmux-next fast gates: the crash-class rules are the fifth gate, red only for findings the PR adds
The cmux-next crash-class rules become the fifth cmux-next fast gate. They fail a pull request only for findings it adds (coord-deputy, 2026-10-21).
cmux-next-crash-class.yml runs three checks: the crash-class concurrency rules (scripts/ci/crash-class-gate.sh), unrecognized selectors from super calls (check-objc-selectors.py) and the Chromium Objective-C contract (check-cef-objc-contract.py). None of them was a fast gate, so autoland and the merge hook never waited on them. The crash-safety rules chief-sidebar-2 asked about are already covered: the prepush gate runs check-crash-safety.sh on every changed CmuxNext and cmux-tui file and fails only on findings the PR adds.
What it does. New scripts/ci/crash_class_fast_gate.py, run by cmux_next_fast_gates.py on the merge with BASE's exported tree:
- Concurrency:
crash-class-gate.sh --pr, the same as its workflow. It already fails only for findings in files the PR changes, or for a change to its rules. The merge's first parent is BASE on both thepull_requestmerge ref and a dispatch's--no-ffmerge, which is whatpr_owned_findings.pyreads. - Selectors and CEF contract: these check the whole tree. Each runs on the merge. When it fails there, the merge's copy runs again with
--rooton BASE's tree, and only failures the merge adds fail the gate. Failures are keyed without line numbers, so moved code is not new, but a second copy of a base failure is. - Every check runs even after one fails. A check that ends with neither its ok exit nor a failure line (a traceback) is red, because nothing can be compared.
Time. On a real merge of this branch into feat-cmux-next on huge-blue, the gate took 20 s, all green. The fast-gates step was about 40 s (crash ratchet 29 s, web lint 8 s), so it is now about 60 s.
Test
ef14c8a1a266 is the red commit:
python3 tests/test_crash_class_fast_gate.py # FAILED (failures=9, errors=1): the script does not exist
python3 tests/test_cmux_next_fast_gates.py # (at the fix) checks run() passes the fifth gate BASE's tree
Green at the head: test_crash_class_fast_gate.py 10 OK, test_cmux_next_fast_gates.py 25 OK.
tests/test_crash_class_fast_gate.py runs the gate in a temporary repository whose three checks print the findings listed in their tree. Cases:
- all green: the base is not read;
- a concurrency red stands, run with
--pr; - a base failure on another line passes;
- an added failure fails and is named;
- a second copy of a base failure fails;
- a merge or base crash fails;
- every check runs after one fails;
- the gate runs the same three scripts as the workflow.
It is wired into cmux-next-guards.yml's tooling tests.
Observed / Not run
- Observed: the tests above, red then green. The real gate on a local
--no-ffmerge of this branch into feat-cmux-next (20 s, all ok).prepush-gate.py: no new violations. - Not run: a real failure of the selector or contract checks against a real base. The fake-check tests cover the comparison. This PR's own
cmux-next fast gatesrun is the first CI run of the gate.
Changelog
none
Agent session: huge-blue
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Makes the cmux-next crash-class rules the fifth cmux-next fast gate, so autoland and the merge hook now wait on them. The gate fails only for findings the PR adds.
How it gates
- The concurrency rules run via
crash-class-gate.sh --pr, already scoped to files the PR changes. - The selector and CEF contract checks run on the merge; when red there, they rerun against BASE's exported tree and only new findings fail, keyed without line numbers so moved code is not new.
- Every check runs even after a failure; a check ending in a traceback is red because nothing can be compared.
- Adds
crash_class_fast_gate.pyand 10 tests wired intocmux-next-guards.yml; the gate took 20 s on a real merge.