ci(cmux-next): feat-cmux-next pull requests run ci-guards.yml's groups routed by path
Summary
ci.yml routes ci-guards.yml's guard groups by path only for pull requests into main, and cmux-next-guards.yml ran only the ci and release-notary groups. About 70 guard tests never ran for feat-cmux-next and sat in tests/pr-lane-exemptions.json. This PR has feat-cmux-next pull requests and pushes run those groups, routed by path and judged against the base.
- Routing (one table):
detect_linux_guard_changes.classify_featpicks the groups, plus the SwiftPM lockfile job and the source-lint job, from the ownership ci.yml already uses (workflow_guard_groups.groups_for_path, andclassifyfor the two jobs). It adds no second path table. - Diff base:
cmux-next guards / cmux-next CI guard groupchecks out withfetch-depth: 2. A pull request diffs its merge commit againstHEAD^1. A push diffs againstgithub.event.before, fetched at depth 1. With no usable base (a new branch, or a zero or unreadable sha), every routed group runs. - Unknown paths (bounded): ci.yml runs every group for any unknown path. On feat-cmux-next that matched 254 of the last 300 first-parent commits (mostly
Packages/,webviews/,cmux-tui/), so it would mean all ten groups on both head and base for almost every PR. On feat, an unknown path in a product source area (FEAT_PRODUCT_AREAS: Packages, webviews, cmux-tui, Native, backend, web, schemas, release-notes, plans, docs, design, skills, ...) adds no group. Any other unknown path (workflows, scripts, tests, Resources, ios, agent-chat, a new top-level area) runs every routed group. Replayed on the same 300 commits, this rule runs everything for 42. - Running them:
run_ci_guards.py --feat-routes FILE(which also runs a group in order when a step callsinit-submodule.sh) runs thecigroup plus the routed groups. The job runs this on the head and on the base checkout (--root .guard-base) with the same file, andguards_new_reds.pyfails only on steps that this change turns red. It also sets up bun 1.3.6 (ci-guards.yml's pin), which preflight-agent-chat needs. The timeout goes from 10 to 25 minutes (the last run took 8 minutes). The job also sets up python3.9 beside python3, excludes.guard-basefrom the head's git status, and takes its base sha from the diff step, so the routing diff, the base checkout andCMUX_GUARDS_BASE_SHAall use the same commit. - PR lanes:
pr_test_lanes.pyreads--feat-routesas "any groupclassify_featcan pick", so the validator counts those tests and their exemption entries are removed. release-ios stays exempt, with a rewritten reason. - Two release-ios steps guard tooling that feat-cmux-next uses: the iOS package conventions diff (test-ios.yml and cmux-next.yml run that lint on feat) and test-ios.yml's dispatch-ref test. Both move to
preflight, and the conventions lint's inputs getPATH_OWNERSentries.
Changelog
none
Testing
Focused commands (CI only, never run locally): python3 tests/test_pr_lane_coverage.py, python3 tests/test_ci_linux_guard_routing.py, python3 tests/test_ci_run_guards.py, python3 tests/test_feat_ci_guard_group.py, and python3 scripts/ci/validate_test_execution_registry.py --pr-lanes feat-cmux-next --base-sha "$(git rev-parse HEAD^1)".
Each fix comes after its red test, in a separate commit:
- 89103763483c (red), then 6dacea0fb1f8: the routing.
- fad4952a85a5 (red), then 6e6abec09e5a: release-tooling runs in order after init-submodule.sh, and python3.9 is set up.
- da642db02c4d and b4dc80e71a66 (red), then 873f13c13aca: the base is one sha, and the Zig installer keeps its GITHUB_ENV to itself.
- 53cef0f1f740 (red), then aaacb37d3505: the base checkout is excluded from the head's git status.
On base, cmux-next guards / tooling-tests passed because nothing routed these groups and the tests above did not exist.
On head aaacb37d3505, run 39638306797:
cmux-next CI guard groupis green: 235 steps over 11 groups, "0 guard steps red on this change, 8 red on the base too, 2 fixed".tooling-testsis green, including the registry check andtest_pr_lane_coverage.py.
Observed / Not run
Observed:
- The CI results above. I read the logs of all three runs of the guard group (39629372978, 39634548627 and 39638306797).
- Locally, static checks only: the registry validator,
run_ci_guards.py --list --feat-routes, YAML parsing and the prepush gate.
Not run: no test file ran locally (the rule on cosmic-gray). The base-red fixes in #23551, #23553, #23554 and #23576 have not run either, because their own pull requests' CI does not route these groups until this PR lands.
ci-guards groups on feat-cmux-next
| Group / job | On feat PRs | Why |
|---|---|---|
| ci | always (already) | guard group job default set |
| release-notary | always (already) | nightly-guards job; nightly-next ships from feat |
| preflight | routed | shared CI tooling (registry validator, merge drivers, localization, build graph, review fabric, pr-media), and now the iOS conventions diff and test-ios.yml dispatch ref |
| preflight-agent-chat | routed | agent-chat and control-plane types are in the feat tree |
| app-host-execution | routed | shared Swift test-execution scripts (run-swift-testing-suites.sh, require_swift_test_execution.py, package-test-lane.sh) |
| app-host-watchdog | routed | shared watchdog and timeout helpers |
| app-host-cache | routed | shared reload and Xcode cache tooling |
| release-tooling | routed | not main-only: guards install-zig-ci.sh, install-cmux-tui-client.sh, prune_nightly_release_assets.py and the GhosttyKit checksums, which cmux-next.yml, nightly(-next) and cmux-tui workflows run and feat edits (2, 11, 2 and 4 feat-only commits) |
| quality-sharding, quality-runtime | routed | cheap; quality-runtime has no steps |
| quality-determinism | routed | Python syntax, shell-integration and determinism lints on tests |
| workflow-guard-history | routed | feat edits Package.resolved |
| workflow-guard-source-lints | routed | DispatchWorkItem lint over Packages/*/Sources |
| release-ios | exempt | guards only main's iOS upload path: ios-testflight.yml and ios-appstore-upload.yml upload only from refs/heads/main; the ios/scripts upload tooling (0 feat-only commits), ios_upload_batch_decision.py and fastlane run in no feat workflow. ci.yml routes this group on PRs into main. |
| workflow-guard-cli-scripts | unchanged (not run) | shell tests, not in the exemption list |
Base reds
These came up once the groups ran. The job counts each one as "red on the base too", so they warn and do not fail.
| Step (group) | Cause | Fixed in |
|---|---|---|
| Validate Python test execution registry blast radius (preflight) | expected tests/test_ui_fuzzer_engine.py, which feat deleted (#15693) | this PR (6e6abec09e5a) |
| Validate retried Ghostty Zig package fetches (release-tooling) | showed up after release-tooling started running in order: the Zig installer test wrote its fake zig into the job's GITHUB_ENV | this PR (873f13c13aca) |
| Validate Ghostty Zig version synchronization (release-tooling) | before ordering: ghostty not checked out yet (this PR). Then: the checker missed init-submodule.sh ghostty-next and could not parse a nightly.yml step | #23576 |
| Validate nightly prune Python compatibility (release-tooling) | no python3.9 in this job (runner fidelity) | this PR (6e6abec09e5a) |
| Run canonical CMUX CI guard profile (ci) | the untracked .guard-base made the head look dirty (red on every run of this job). Underneath: fleet-test-compile.yml uses GitHub-hosted runners | this PR (aaacb37d3505), then #23553 |
| Validate macOS runner guards (preflight) | fleet-test-compile.yml (#23423) uses GitHub-hosted ubuntu-24.04 | #23553 |
| Validate reload shared DerivedData default (preflight) | write_dev_cli_shim moved to scripts/lib/cmux-dev-shim-install | #23553 |
| Test the cmux NEXT media tour's app window capture (preflight) | display_capture() calls use_display() without the pid that #22046 added | #23553 |
| Validate test determinism gate (quality-determinism) | 137 findings of feat test debt that nothing had checked; allowlisted as a ratchet | #23551 |
| Validate Swift Testing suite timeout guard (app-host-execution) | the test's fake swift predates the binary-module guard's swift package resolve (e6c6b4a2a506, a9d9b47dc978) | #23554 |
| Validate signing secrets are read only in protected environments (ci, already routed) | nightly-next-train.yml | #23299 (another lane's, open) |
| Validate iOS package conventions for this change (preflight) | run 2 judged against a stale pull_request.base.sha (ChiefWorkspaceName.swift came from #23391 on base). Not a base red: a base-selection bug | this PR (873f13c13aca) |
Agent session: cosmic-gray
🤖 Generated with Claude Code