ci(cmux-tui): pick a mini only when the macOS targets may build

TE
4d ago
+61-29

The manaflow-glaeda-route App installation's REST bucket (5000/h) ran dry in the hour of 2026-11-02 03:06Z and on 2026-11-01. While it is empty, every runner picker loses its runner list (GET /actions/runners answers 403), and nightly signing falls back to a slow Blacksmith label (run 41383305465, job pick-nightly-sign-runner).

What drains it (measured, 2026-11-02)

The bucket reset at 03:06:13Z. The GitHub API spend lines (#31307) on the routing token read: 4896 left at 03:06:57, 4117 at 03:11:39, 3016 at 03:16:47, 1478 at 03:24:11, 483 at 03:30:24 and 0 by 03:32:51. That is about 190 requests a minute, roughly 11,000 an hour of demand against 5000.

The run counts below are runs created between 02:45 and 03:45Z. Requests per run come from sampled jobs' spend lines, and from the code where a caller prints none.

rankcallerruns/hrouting reads per runreads/h (est.)do the reads change a decision?
1cmux-next.yml (portable placement 4; macOS placement 10, via the routing token and the glaeda read token)228 (~107 PR, ~52 push, ~70 dispatch)4-14~1,500yes
2cmux-tui-artifacts.yml tree preflight mini pick (4) plus owner-wait status curls (~1-2)322~5~1,450mostly not: in 9 of 10 sampled runs nothing was built
3cmux-next-guards.yml portable placement1994~720yes
4nightly.yml pickers (the sign picker alone made 33)1125-50~300-500yes
5ci-owned-pool-rescue.yml348 (~24% not skipped)2-3~210yes
6ci.yml, test-ios.yml pickers198, 102~0 (they decide without a read)~0-

That table covers about half the measured drain. The other half isn't pinned down yet. Possible sources: the token revoke at the end of each mint, about one request each and roughly 1,000 an hour (not yet confirmed to count against the bucket); callers that print no spend line; and readers outside cmux's own workflows.

The cut

The tree preflight picked a mini for the macOS targets, spending 4 routing App reads and 2 workflow-token reads, before the inspect step had decided whether the run builds. The build job needs run_macos == 'true' and either owns_key or an owner-wait takeover. So in a run whose tree is published, whose push is stale, or that defers to a live owner, the pick changed nothing. Of 10 sampled runs, all 10 picked and 9 built nothing.

The mint and the pick now run after the inspect step, and only when the inspect step's new place_macos output is true. That needs run_macos true and either this run owning the key, or a feat-cmux-next or main push, the only runs that take a key over from a live owner. Any other run that later takes over (its owner ended unpublished) builds on the Linux cross build, the same as when no mini is free, or when the bucket is empty as it was for half of this hour. Risk: such a takeover skips a free mini once.

Performance

metricbeforeafterdeltaharness or run link
routing App reads/h by the tree preflight pick~1,160 (322 runs/h x ~90% that pick x 4)~260 (2 of 10 sampled runs keep the pick)-900/h (-18% of the 5000 budget)spend lines in runs 41381244225, 41384707377, 41380145293 and 10 sampled runs from 03:28-03:44Z
routing App mints/h (token revoke each)~290~65~-225/hsame
workflow-token reads/h (snapshot)~580~130~-450/hsame

Tests: tests/test_ci_portable_job_placement.py (new case: the pick runs after inspect, and only on place_macos), plus every tests/test_cmux_tui_* and tests/test_ci_* that reads cmux-tui-artifacts.yml, which pass at head and base alike. tests/test_cmux_tui_superseded_push.py fails the same way at base on the agent host (its git push fixture), so it is left to CI.

Overlap: #30622 (open, conflicting) adds a second pick in the same preflight; it would want the same gate.

Agent session: agent session

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Gates the cmux-tui mini runner pick on the new place_macos output from the inspect step, so the pick's routing App reads (4 per pick) are only spent when the macOS targets may actually build. Previously the pick ran in every run before the inspect step decided whether the run builds; most runs built nothing, and the routing App's 5000/h budget ran out.

  • Runs that take over from a live owner (other than feat-cmux-next or main pushes) will skip a free mini once and fall back to the Linux cross build.
  • Adds a test covering the new gate, with all existing cmux-tui and CI workflow tests passing.