ci(nightly-next): the Ghostty helper takes an idle owned Mac while the app build holds the dedicated builder
NEXT nightly fell 3h25m behind feat-cmux-next on 2026-10-30 (the rule is at most 30 minutes). Two causes, the second fixed here:
- A Release compile red from about 23:40Z to 01:23Z:
JoinConsent+App.swift:222:29: error: 'async' call in a function that does not support concurrencyfailedbuild-nightly-appfor every promoted tip from 43303f771ee3 to 00c873b578db. #27758 (cec0a36b8ac6) fixed it. - The first green tip after that, 373ec0cfaa2f (run 40990112293), built its app on the dedicated builder by 02:30Z. Its Ghostty CLI helper then sat queued for 39 minutes on
blacksmith-6vcpu-macos-26, and the run was cancelled unpublished at 02:51Z. The helper reuse lookup had missed (the repoGITHUB_TOKENgot a 403 from the contents API), and the helper never takes the dedicated builder, whose hook admits onlybuild-nightly-app. So the helper'sruns-onfell toblacksmith, even though owned side Macs were idle.
The change: pick-nightly-build-runner now also outputs helper.
helperisownedwhenownedis not the dedicated builder.- When the app build has the dedicated builder,
helpercomes from a freshowned_route()read: an idle side or nightly-slot Mac. The verify jobs already pick their Mac this way. - With no idle Mac,
helperis empty and the helper takes the moving Blacksmith label, as before.
build-nightly-ghostty-cli-helper now reads helper instead of owned, on the same rule: the pick must be for this attempt, and it is never the dedicated builder. The job output stands on the same terms as owned (marker uploaded outside attempt 1 of a push).
Risk: low. The change only affects routing of the helper job on nightly-next. The fallback is still Blacksmith macOS 26, and the dedicated builder is still excluded.
Tests (run on a Linux lane VM):
tests/test_nightly_build_runner.py: 33 tests OK, including a new test, the helper takes an idle owned Mac while the app build holds the builder.tests/test_nightly_trusted_routing.py: 22 tests OK.tests/test_ci_nightly_off_blacksmith.py: 15 tests OK.tests/test_nightly_next_train.py: 38 tests OK.tests/test_nightly_sign_runner.py: OK.tests/test_nightly_universal_build.sh: PASS.test_nightly_next_guard: PASS.test_nightly_workflow_size: PASS.test_ci_workflow_guards_are_wired: PASS.
tests/test_ci_signing_owned_mac.py fails one test (test_every_listed_hook_is_one_glaeda_released_with_the_check) on base too.
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.
Summary by cubic
Fixes a nightly-next CI routing gap where the Ghostty CLI helper queued on Blacksmith while idle owned Macs were available, leaving nightly-next 3h25m behind feat-cmux-next after a Release compile red.
Because the dedicated builder admits only build-nightly-app, the helper previously fell back to the Blacksmith label whenever the app build held the builder, even with idle side Macs. pick-nightly-build-runner now also outputs helper: owned when that isn't the dedicated builder, otherwise a fresh owned-route read for an idle side or nightly-slot Mac, or empty so the helper keeps taking Blacksmith when no Mac is idle. build-nightly-ghostty-cli-helper reads the new output on the same marker terms as owned.