Repository navigation
cmux-next: the fast tier runs as a build-fleet client when every macOS label is full or dead - #28391
Conversation
841b2e2 to
00ba87a
Compare
|
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); base red: the same failure on the base 87b4c90; does not block Shipped in:
|
|
Owned by an agent session · session |
|
Found 13 test failures on Blacksmith runners: Failures
...and 3 more test failures. View all on Blacksmith
|
b22621c to
acef212
Compare
Bugbot needs on-demand usage enabledBugbot 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. |
Bugbot needs on-demand usage enabledBugbot 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. |
d4686a7 to
82a6d88
Compare
|
Review (codex gpt-6-astra high, next-review): BLOCK at 82a6d88
|
82a6d88 to
362d53b
Compare
362d53b to
3307180
Compare
Resolve the fast-tier runs-on conflict (keep the fleet branches and base's retry_jobs gate), pass CMUX_SWIFT_PACKAGE_TEST_TIMEOUT_SECONDS=60 to the fleet suite step, declare fast-tier-fleet's warm source, and let the fork routing guard accept a mixed macOS/Linux selector whose first clause is a hosted fork branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fc739fd2f4e557ae7189
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fc739fd2f4e557ae7189
… the gateway guard allows Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fc739fd2f4e557ae7189
There was a problem hiding this comment.
2 issues found across 9 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tests/test_ci_next_macos_cascade.py">
<violation number="1" location="tests/test_ci_next_macos_cascade.py:2195">
P2: This fixture does not test the fresh listener case it claims to cover. Because `generated_at` is newer than the fixed `NOW`, placement treats the snapshot as unreadable and the assertion passes for the wrong reason; derive the timestamp from `NOW` instead.</violation>
</file>
<file name="tests/test_ci_fork_runner_routing.py">
<violation number="1" location="tests/test_ci_fork_runner_routing.py:1067">
P2: This exception validates only the hosted branch for a fork's own repository, not a fork PR targeting `manaflow-ai`. Require the existing fork-PR gate before allowing `vars.LINUX_RUNNER`, otherwise this guard can approve a selector that queues fork PRs on self-hosted Linux.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| self.assertEqual(self.place(shot=shot, live={LARGE: 1, SMALL: 10}, FLEET_CLIENT_JOBS="fast-tier").fleet_jobs, | ||
| ()) | ||
| # The side label has a listener, by a fresh health record (a stale record or snapshot reads full). | ||
| fresh = dt.datetime.now(dt.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") |
There was a problem hiding this comment.
P2: This fixture does not test the fresh listener case it claims to cover. Because generated_at is newer than the fixed NOW, placement treats the snapshot as unreadable and the assertion passes for the wrong reason; derive the timestamp from NOW instead.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At tests/test_ci_next_macos_cascade.py, line 2195:
<comment>This fixture does not test the fresh listener case it claims to cover. Because `generated_at` is newer than the fixed `NOW`, placement treats the snapshot as unreadable and the assertion passes for the wrong reason; derive the timestamp from `NOW` instead.</comment>
<file context>
@@ -2148,6 +2158,64 @@ def test_the_sign_runner_reads_the_same_rule(self):
+ self.assertEqual(self.place(shot=shot, live={LARGE: 1, SMALL: 10}, FLEET_CLIENT_JOBS="fast-tier").fleet_jobs,
+ ())
+ # The side label has a listener, by a fresh health record (a stale record or snapshot reads full).
+ fresh = dt.datetime.now(dt.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
+ listening = self.shot(listening=1, held_offline={"units": 0, "cpu": 0, "livelock": 0}, as_of=fresh)
+ listening["generated_at"] = fresh
</file context>
| fresh = dt.datetime.now(dt.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") | |
| fresh = (NOW - dt.timedelta(minutes=1)).strftime("%Y-%m-%dT%H:%M:%SZ") |
| saw_linux += 1 | ||
| self.assertTrue( | ||
| hosted_linux, | ||
| hosted_linux or (fork_short_circuits and hosted_macos), |
There was a problem hiding this comment.
P2: This exception validates only the hosted branch for a fork's own repository, not a fork PR targeting manaflow-ai. Require the existing fork-PR gate before allowing vars.LINUX_RUNNER, otherwise this guard can approve a selector that queues fork PRs on self-hosted Linux.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At tests/test_ci_fork_runner_routing.py, line 1067:
<comment>This exception validates only the hosted branch for a fork's own repository, not a fork PR targeting `manaflow-ai`. Require the existing fork-PR gate before allowing `vars.LINUX_RUNNER`, otherwise this guard can approve a selector that queues fork PRs on self-hosted Linux.</comment>
<file context>
@@ -1050,11 +1050,21 @@ def test_every_fork_exercised_runner_has_a_hosted_path(self) -> None:
saw_linux += 1
self.assertTrue(
- hosted_linux,
+ hosted_linux or (fork_short_circuits and hosted_macos),
f"{path.name}:{number} has no GitHub-hosted Linux fork branch",
)
</file context>
| hosted_linux or (fork_short_circuits and hosted_macos), | |
| hosted_linux or ( | |
| fork_short_circuits | |
| and hosted_macos | |
| and fork_pull_request_gate_error(line) is None | |
| ), |
|
Review (codex, router-review): SHIP at cc11800 Reviewer: codex gpt-6.1-sol xhigh, fast tier. Follow-ups: 4. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward. SHIP at cc11800 Visual verdict: no images; Leo tries the build. Focused tests passed except the same pre-existing webviews test failure reported for the base.
Follow-ups:
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review (codex, router-review): SHIP at 40a4d4e Reviewer: codex gpt-6.1-sol xhigh, fast tier. SHIP at 40a4d4e Visual verdict: no images; Leo tries the build No findings. Focused workflow, placement, cascade, and routing checks passed. Broader failures traced to unchanged code or omitted fixtures. Follow-ups: none |
A newer verdict blocks 40a4d4e (no independent SHIP at the head).
A cmux-next swift test job log on #28391 was about 40 MB, past the 32 MiB evidence cap, so its red could not be compared with the base. Agent-Session: https://cmux.com/deeplink/agent?id=aid-fc739fd2f4e557ae7189 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A newer verdict blocks 2944b6f (no independent SHIP at the head).
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Builds on #28249 (merged as 38c2c9a). This branch is this PR's own 7 commits rebased onto current feat-cmux-next; none of #28249's commits remain in its diff.
What
When every owned and Blacksmith macOS label the fast tier could take is full or dead, the tier no longer waits: it runs as a thin
cmux-ciclient on the build-fleet gateway, andcmux-next fast tierkeeps its check name and exit code.#28249 added
fleet_jobsto the placement (filtered toFLEET_CLIENT_JOBS, which it left unset, and read only throughlabel_full_or_dead) and reserved the gateway outputs without wiring any job to them. This PR wires the fast tier with the client + report patternswift-canary-fleet/swift-canaryalready use:fast-tier-fleet(new, namecmux-next fast tier (build fleet)): runs onneeds.macos-placement.outputs.gateway_runneronly whenfleet_jobslistsfast-tierand placement saw an idle gateway in this attempt.permissions: {}, no checkout, no action, no secret. One step:cmux-ci run --class light --script scripts/ci/package-test-lane.sh --ref <REF> --arg=suite ...for each package offast-tier.json's Swift entries (CmuxHomeRender: MotionTokenTests, IntentMappingTests; CmuxNext: ModelMatrixTests, PaneZoomMotionTests, CEFProfileStorageLogTests, AgentSubagentPanesFocusTests), in parallel,--no-supersede. REF is the exact commit fast-tier itself checks out:github.sha, a pull request's merge commit (asswift-canary-fleetdoes), so a head that breaks against the current base is still caught. On a push it is the pushed sha. It then readscmux-ci status <step>and requires everyrefin the record (andsource_digest) to equal REF. Outputverdictis pass, fail or unavailable. The controller's record decides: pass needs statedonewithexit_code0 (and a client exit 0). A step that ended with a nonzero exit is a fail even if the client exited 0. Step ids are read as 6 to 64 hex, as the fleet tools read them. Fail, no verdict, or a step at another commit all fail the job; only a pass at REF exits 0.fast-tier: needsfast-tier-fleet. When that job ran (success, failure or cancelled), it runs onblacksmith-2vcpu-ubuntu-2404(4 vCPU underCI_CLOUD_OVERFLOW_SAVED, as swift-canary does) with a 5 minute timeout. Its first step reports the client's verdict (pass + success: exit 0; fail: exit 1; anything else: exit 1 with "no verdict"), and every other step is off (CMUX_FAST_TIER_FLEET). Its runs-on no longer namesgateway_runner. When the client job skipped, nothing changes.fast-tier-fleethonoursneeds.path_route.outputs.fast_tieron pushes as well as pull requests, so a push whose diff since the last finished fast tier reaches no Mac tier skips the client as it skips the tier.test_the_client_runs_only_when_placement_listed_its_tier_with_an_idle_gatewaychecks the two gates agree on both events (red without the gate).FLEET_CLIENT_JOBS: fast-tierin the place step.next_macos_cascade.pyis unchanged.side_lane_placement.fleet_gateway()): the client runs ongateway_runnerbesideGATEWAY_JOBS(app-compile-fleet, swift-canary-fleet, release-compile-fast), and the gateway is judged for those alone. Placement now keepsfleet_jobsonly while the gateway has an idle runner for each listed job beyondGATEWAY_JOBSand the run's own jobs (counted asgateway_route()counts them). Otherwise it lists nothing and fast-tier keeps its route, rather than its client queueing behind another gateway job until its timeout. A re-run emits no gateway, so it lists none. Tests:GatewayRoute.test_a_fleet_client_needs_its_own_idle_gateway_runner,test_main_lists_a_fleet_job_only_with_a_gateway_runner_for_its_client(caught when the call inmain()is removed),test_a_rerun_lists_no_fleet_job. No label is hard-coded for the gateway;gateway_runnercomes from placement.FleetGateway.test_gateway_output_is_reserved_without_wiring_raw_mac_jobsbecomestest_no_tier_runs_on_the_gateway_itself: no tier's runs-on namesfleet_jobsorgateway_runner, or resolves to the gateway when placement lists it. Its check thatFLEET_CLIENT_JOBSis unset is dropped, since this PR sets it.Tiers with and without a client
fast-tier: client added. Its Swift entries map one to one topackage-test-lane.sh suitefilters, the allowlisted light script. One difference: fast-tier.py runs a failed entry once more to label it FLAKY; suite mode fails on the first failure. Both are red, so the gate is the same.swift-test: no client. It is not a cascade job (CASCADE_JOBSis fast-tier, swift-canary, cmux-scheme-compile, release-compile), soplace()never leaves it unplaced andfleet_jobscan never list it. Its route-selected suites and side steps need a checkout to plan.daemon-test: no client. It is not a cascade job either, and it needs the same-tree cmux-tui daemon. A fleet suite step without that daemon reports "no result", so a client could never honestly pass..github/runners.jsonclassifiescmux-next.yml#fast-tier-fleetasapple-swift-tests, beside the other gateway clients (the routing table reads the gateway label as macOS).Gateway label allowlist
The client job's id is
fast-tier-fleetand its name iscmux-next fast tier (build fleet). The glaeda gateway allowlist for cmux-next.yml needs this id (the reporting jobfast-tiernever runs on the gateway).Guard tests
GatewayRunsOnlyTheFleetClientintests/test_cmux_next_checks_workflow.py:gateway_runnerthroughfleet_jobshas runs-on equal to the gateway output,permissions: {}, no container, services, environment or secrets, and onlyrunsteps. Every command word is the client or a shell builtin (a shlex-based parse), with no absolute path and no eval, exec, source, command, builtin or env.ifwith every earlier step skipped.PATHempty against a fakecmux-ci. It passes only on a pass at REF, and fails with the right verdict for: a suite failed, a step at another commit, a queue timeout, no worker, no client, and a REF that is not a full sha. Any non-builtin it ran would show as "command not found".FLEET_CLIENT_JOBSand the<tier>-fleetjobs match one to one. The tier never namesgateway_runner, reports on Linux only when the client ran, and has every other step off. The report step's exit matches the client's.fast-tier.json's gating Swift entries by package.BuildFleetGatewayJobsFallBack.FALLBACKSnow includesfast-tier-fleet→fast-tier.FleetClientJobsintests/test_ci_next_macos_cascade.py: with every label full or dead,FLEET_CLIENT_JOBSputs exactly the listed jobs infleet_jobs(writtenfast-tier). Nothing is listed when no client is configured, when a Blacksmith label is under its cap, when the side label has a live listener, or when there is no snapshot. The workflow lists only cascade jobs that have their<job>-fleet.Red/green: with these test files on #28249's earlier head (d3289ff),
GatewayRunsOnlyTheFleetClient+BuildFleetGatewayJobsFallBackfail (7 failures, 12 errors) andFleetClientJobsfails (1 failure, 1 error). On this branch they pass. On an earlier #28249 head (be77727), whose runs-on sent whole Mac jobs to the gateway,test_a_client_job_runs_nothing_but_the_clientfailed for each of those seven jobs. Two mutations of this branch are also caught: an ungatedRun the fast tierstep, and agit fetchadded to the client step.Same-host runs, this branch vs its base (330eebb):
test_cmux_next_checks_workflow.py173 OK (base 165 OK),test_ci_next_macos_cascade.py125 OK (base 121 OK),test_ci_side_lane_placement.py81 OK (base 78 OK).test_ci_runs_on_fallback.py,test_cmux_next_checkout_retry.py,test_ci_macos_xcode_selection.py,test_ci_fork_runner_routing.pyandtest_ci_fast_tier_anchor.pypass on both.test_ci_change_areas.pyfails the same one test (test_repository_helpers_route_by_where_they_run) on both.test_ci_self_hosted_guard.shand actionlint give the same output on both. Every test file thatci-guards.ymlor the cmux-next CI groups run (502 files naming cmux-next.yml, placement, cmux-ci or runners.json) gives the same result by name on this branch and on its base.Risk
Low. Behaviour changes only when placement lists
fast-tierinfleet_jobs, which needs the placement script from the base (after #28249) and every macOS label full or dead. With no idle gateway the client skips and fast-tier takes its usual route. No new permission, secret or runner label. The client job holds no token.Agent session: agent session
🤖 Generated with Claude Code