ci: cmux_next_ daemon tests take a free owned Mac, else Blacksmith macOS 15
Merged
TE
10d ago+167+167+012345678901234567890123456789-5-5-0123456789
The cmux_next_ daemon tests (macOS) job gates nightly-next promotion. Attempt 1 of a feat-cmux-next push sent it to the owned side lane glaeda-side-std-xcode-26.6, and it queued there behind everything else on that label.
Evidence (2026-10-26)
- Run 40397154574 (4881e357): the daemon tests have been queued on
glaeda-side-std-xcode-26.6since 22:19Z, 75+ minutes and counting. - Run 40419603252 (tip 23802b0a): its daemon tests are queued the same way.
- Promotion tick 40420216032 at 23:33Z refused 22 commits, 10 of them with "daemon tests have not passed". nightly-next is still on 76b6e0de, promoted at 21:20Z.
Change
- A new job,
cmux-next-daemon-tests-runner, runs on Blacksmith Linux 2 vCPU, has a 5-minute timeout andcontinue-on-error. It carries the sameif:as the tests, so the tests are never skipped for want of it. For a feat-cmux-next push it picks the label at queue time withscripts/ci/e2e_runner_pool.py --requested auto, the pickercmux-next-dev-daily.ymlalready uses. That picker names an owned Mac only when one is free now; otherwise the job falls back to Blacksmith macOS 15, never the nightly's macOS 26 labels. cmux-next-daemon-teststakes that pick first on attempt 1 of a feat-cmux-next push. The declaredCI_NEXT_DAEMON_POOL/CI_NEXT_PROMOTE_POOLslot and the rest of the existing chain stay as the fallback when the pick fails (empty output). Every other context routes exactly as before.- Routing order: Linux is not possible yet, because a Linux run writes no daemon marker. #25758 moves the tests to Linux and will rebase onto this PR. Until then the order is a free owned Mac, then Blacksmith macOS last.
Before / after
- Before: daemon tests queued 75+ minutes on one saturated owned label, and promotion was blocked.
- After: a free owned Mac or Blacksmith macOS 15 is chosen when the job queues, so the tests start within minutes.
Tests
tests/test_ci_tui_routes_avoid_nightly_label.pygainstest_daemon_tests_take_the_pickers_free_runner_first. It covers every owner, event, ref and attempt, with the pick both owned and Blacksmith and the declared pool both set and unset, and checks the route never hits the nightly label.tests/test_tui_publish_workflow_security.pygets the exact route string with the pick slot, plus checks on the pick job's shape.- These pass locally:
test_tui_publish_workflow_security,test_ci_tui_routes_avoid_nightly_label,test_cmux_tui_publisher_testing,test_cmux_tui_daemon_tests_linux,test_ci_nightly_off_blacksmith,test_supplychain_security,test_ci_runs_on_fallback,test_runner_label_policy,test_ci_check_repo_variables. test_ci_fork_runner_routingshows the same 3 failures as base, with none in this file. actionlint reports nothing new.
Risk
- Low. If the pick job fails or times out, the label is empty and the route is exactly today's.
- The pick job uses the existing
ci-routing-agentenvironment and glaeda-route App token (read-only runner scopes), which other jobs in this workflow already use. cmux_tui_publisher_testing.pystill compares against DAEMON_POOL only when it is set, and DAEMON_POOL is unset today.
Agent session: agent session
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.