Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c5ac4f4
ci: keep cmux-next fast tier off dead side queues
teamleaderleo Oct 30, 2026
93cd38d
Rescue queued cmux-next jobs independently
teamleaderleo Oct 30, 2026
5369404
Fail over full owned macOS labels
teamleaderleo Oct 30, 2026
d25a6e2
Route saturated labels through health contract
teamleaderleo Oct 30, 2026
bf35c37
Fail over saturated owned labels from health
teamleaderleo Oct 30, 2026
e590e63
Reserve gateway fallback for dead macOS pools
teamleaderleo Oct 30, 2026
be77727
Guard fleet gateway routing and isolate rescue read failures
teamleaderleo Oct 30, 2026
377b652
Merge current base and reserve gateway outputs without job wiring
teamleaderleo Oct 30, 2026
a5987f2
Validate fast-tier allocation and stale-route fallback behavior
teamleaderleo Oct 30, 2026
a20fe76
ci: honor fresh owned allocation on bot fast-tier retry
teamleaderleo Oct 30, 2026
992e09b
ci: require live role runner before accepting health admission
teamleaderleo Oct 30, 2026
d44acc5
ci: fail closed on stale health and blacksmith outages
teamleaderleo Oct 30, 2026
f03f8e7
ci: treat stale pool readings as overflow
teamleaderleo Oct 30, 2026
e19528e
ci: preserve live routes for empty legacy health
teamleaderleo Oct 30, 2026
d3289ff
ci: consume fleet gates and watch full side lanes
teamleaderleo Oct 30, 2026
66b5118
ci: keep nightly health alarms on their queue budget
teamleaderleo Oct 30, 2026
7b07dff
ci: redispatch stuck PR jobs without cancelling runs
teamleaderleo Oct 30, 2026
e845d48
ci: preserve active PR runs instead of unsupported queued-job retries
teamleaderleo Oct 30, 2026
fc40ea6
ci: use authoritative listener timestamps independently of pool artif…
teamleaderleo Oct 30, 2026
14861ac
ci: discover unmarked PR side runs beyond the first page
teamleaderleo Oct 30, 2026
eec4190
ci: retain local fleet gates when runner reads exhaust the budget
teamleaderleo Oct 30, 2026
a48889c
ci: bound placement and skip fast tier without a safe route
teamleaderleo Oct 30, 2026
4988033
Merge feat-cmux-next into lane/fast-tier-rescue-28140
teamleaderleo Oct 30, 2026
2337a03
ci: preserve fork routes and nightly rescue boundaries
teamleaderleo Oct 30, 2026
d35807f
ci: require queued work for stale overflow and report missing fast-ti…
teamleaderleo Oct 30, 2026
8c6c1c2
ci: preserve required fast-tier execution when every overflow target …
teamleaderleo Oct 30, 2026
6662bad
ci: expire Blacksmith health independently of owned gates
teamleaderleo Oct 30, 2026
7d085f9
ci: use the observation clock throughout Mac placement
teamleaderleo Oct 30, 2026
de29dbf
Merge feat-cmux-next into fast-tier rescue
teamleaderleo Oct 30, 2026
d934530
ci: treat corrupt pool artifacts as unavailable health
teamleaderleo Oct 30, 2026
397a11e
ci: keep later rescue retries off owned queues
teamleaderleo Oct 30, 2026
97e3894
test: cover guarded retry fallback
teamleaderleo Oct 30, 2026
d10072e
test: align fast-tier later retry expectations
teamleaderleo Oct 30, 2026
5cc499a
test: cover fast-tier retry fallback paths
teamleaderleo Oct 30, 2026
9161731
test: align human retry fast-tier fallback
teamleaderleo Oct 30, 2026
d9f7c20
Merge feat-cmux-next and retain nightly visual-gate rescue boundary
teamleaderleo Oct 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions .github/workflows/ci-owned-pool-rescue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ run-name: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow
# pr_runner_pool.py may put a pull request run's macOS jobs on a persistent
# pool (owned Macs). GitHub never re-routes a queued job, so when that pool is
# busy the run would wait for it indefinitely. This workflow watches such a run
# and, when one of its jobs has waited past the five-minute queue alarm (or the
# longer configured allowance for a picker-managed pool), cancels the run and
# re-runs it. For cmux-next, the retry is admitted through fast checks, a free
# owned Mac, then Blacksmith macOS; other workflows keep their existing retry
# policy. A job an owned runner refused at job start
# (it failed in seconds, before any step succeeded) gets its failed jobs re-run
# instead, which moves them to the picker's retry_runner on Blacksmith.
# and reports a queue alarm when the pool is full or starts no work. Active
# current-head PR runs remain intact: Actions cannot re-run them yet. Completed
# runner refusals retry failed jobs; eligible non-PR runs retain the cancel and
# re-run policy. Placement for new runs chooses free owned Macs, then Blacksmith.
# scripts/ci/owned_pool_rescue.py has the rules.
#
# One sweeper watches the busy sources (SWEEP=1, owned_pool_rescue.sweep()).
Expand Down Expand Up @@ -105,6 +102,7 @@ on:
permissions: {}

env:
CI_FLEET_GATES: ${{ vars.CI_FLEET_GATES }}
# Renaming the source workflow silently stops every `workflow_run` consumer
# of it; tests/test_ci_workflow_run_sources.py derives the expected name from
# this path. The script confirms the run's own `path` again before acting.
Expand Down
25 changes: 19 additions & 6 deletions .github/workflows/cmux-next.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,9 @@ jobs:
if: ${{ !cancelled() && ((inputs.same_tree_sha == '' && needs.push-head-preflight.outputs.current == 'true' && needs.path_route.outputs.macos == 'true') || (inputs.same_tree_sha != '' && inputs.same_tree_state == 'ready')) && github.repository_owner == 'manaflow-ai' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && vars.CI_PR_POOL_OWNED == '1' && (github.run_attempt == 1 || (github.run_attempt == 2 && contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor))) }}
name: cmux-next macOS placement
runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'ubuntu-24.04' || vars.CI_CLOUD_OVERFLOW_SAVED && 'blacksmith-16vcpu-ubuntu-2404' || 'blacksmith-4vcpu-ubuntu-2404' }}
timeout-minutes: 4
# Checkout (1m), three bounded token mints (3m), placement (2m),
# marker upload (1m), plus time for runner setup and action cleanup.
timeout-minutes: 8
# The workflow's CMUX_NEXT_SIDE_ROUTE, with the rescue's full re-run (attempt 2 by
# github-actions[bot]) placed too: its steps read what is free when it starts, and the
# cascade jobs take a free Blacksmith slot instead of the end of the side queue they waited
Expand All @@ -1257,9 +1259,14 @@ jobs:
# label below). Read from free_retry_runner, which a placement script
# predating the free-slot rule never writes.
retry_runner: ${{ steps.place.outputs.free_retry_runner }}
# Preserve the existing queue only when the cascade has no admissible target.
deferred_runner: ${{ steps.place.outputs.deferred_runner }}
# The Blacksmith labels a feed's compile counts as full (next_macos_cascade.fresh_stalled()): a feat-cmux-next
# push's Release compile never falls back to one of them.
fresh_stalled: ${{ steps.place.outputs.fresh_stalled }}
# Tiers with no live owned or Blacksmith macOS target are handed to the
# thin cmux-ci gateway once the matching client steps are enabled.
fleet_jobs: ${{ steps.place.outputs.fleet_jobs }}
# vars.CI_FAST_LANE_RUNNER while one of its runners is idle, else empty
# (side_lane_placement.fast_route()): the fast tier never queues on it.
fast_runner: ${{ steps.place.outputs.fast_runner }}
Expand All @@ -1274,6 +1281,7 @@ jobs:
gateway_runner: ${{ steps.place.outputs.gateway_runner }}
gateway_attempt: ${{ steps.place.outputs.gateway_attempt }}
fallback_jobs: ${{ steps.place.outputs.fallback_jobs }}
owned_jobs: ${{ steps.place.outputs.owned_jobs }}
# The attempt this placement ran in. A re-run of failed jobs carries the placement job, and its
# outputs, from an earlier attempt: a job output is evaluated when its job runs, so this stays that
# attempt's number. Every Mac job reads blacksmith_12_jobs, blacksmith_6_jobs and
Expand Down Expand Up @@ -1302,6 +1310,7 @@ jobs:
steps:
# The placement code from the base branch, as ci-macos.yml's admission-placement uses it.
- name: Check out the trusted placement
timeout-minutes: 1
if: startsWith(env.CMUX_NEXT_SIDE_ROUTE, 'glaeda-')
continue-on-error: true
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down Expand Up @@ -1364,6 +1373,8 @@ jobs:
ROUTE_TOKEN: ${{ steps.route-token.outputs.token }}
ROUTE_TOKEN_FALLBACK: ${{ steps.route-token-fallback.outputs.token }}
SNAPSHOT_TOKEN: ${{ steps.snapshot-read-token.outputs.token || github.token }}
# Glaeda's authoritative per-label gate reading; this avoids a second API request.
CI_FLEET_GATES: ${{ vars.CI_FLEET_GATES }}
# The cascade's jobs that run on this route at all (next_macos_cascade.py):
# not a job that path routing or the pull request's labels skip (a job
# missing here only stays on the minis' queue). The fast tier is always
Expand Down Expand Up @@ -1439,7 +1450,7 @@ jobs:
# running push run once a newer push exists.
- name: Mark a run on the minis
id: marker
if: startsWith(env.CMUX_NEXT_SIDE_ROUTE, 'glaeda-') && steps.place.outputs.watch != 'false' && github.event_name != 'push' && github.run_attempt == 1
if: startsWith(env.CMUX_NEXT_SIDE_ROUTE, 'glaeda-') && github.event_name != 'push' && github.run_attempt == 1
continue-on-error: true
run: |
set -euo pipefail
Expand All @@ -1453,6 +1464,7 @@ jobs:
# twice on 2026-10-21. The refusals marker has the sweeper re-run what a
# mini refuses and leave a long queue alone.
- name: Upload the owned-pool watch marker
timeout-minutes: 1
if: ${{ steps.marker.outputs.path != '' }}
continue-on-error: true
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand Down Expand Up @@ -2797,10 +2809,11 @@ jobs:
# (glaeda-fast-<class>-xcode-26.6). The tier takes it only through the
# placement's fast_runner, set while one of its runners is idle, and only on
# attempt 1: a re-run reuses attempt 1's placement, whose idle reading is stale.
# Otherwise the tier takes the cascade (Blacksmith) and then the side
# route, so it never waits on that one small pool. The fork clause stays first, so a fork
# pull request never reaches it.
runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || needs.macos-placement.outputs.fast_runner != '' && github.run_attempt == 1 && needs.macos-placement.outputs.fast_runner || (github.run_attempt == 1 || github.run_attempt == 2 && contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && needs.macos-placement.outputs.placed_attempt == format('{0}', github.run_attempt) && contains(needs.macos-placement.outputs.blacksmith_12_jobs, ' fast-tier ') && 'blacksmith-12vcpu-macos-26' || (github.run_attempt == 1 || github.run_attempt == 2 && contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && needs.macos-placement.outputs.placed_attempt == format('{0}', github.run_attempt) && contains(needs.macos-placement.outputs.blacksmith_6_jobs, ' fast-tier ') && 'blacksmith-6vcpu-macos-26' || (github.run_attempt == 1 || !contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && needs.macos-placement.outputs.runner || github.repository_owner != 'manaflow-ai' && 'macos-26' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || vars.CI_PR_POOL_OWNED == '1' && contains(fromJSON('["pull_request","push","workflow_dispatch"]'), github.event_name) && (github.run_attempt == 1 || !contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && vars.CI_SIDE_LANE_RUNNER || needs.macos-placement.outputs.placed_attempt == format('{0}', github.run_attempt) && needs.macos-placement.outputs.retry_runner || vars.CI_PR_POOL_OWNED == '1' && contains(fromJSON('["pull_request","push","workflow_dispatch"]'), github.event_name) && (github.run_attempt <= 3 || !contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && vars.CI_SIDE_LANE_RUNNER || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}
# Otherwise the tier takes the current cascade allocation. With every
# alternative excluded, deferred_runner preserves the base owned queue;
# it never bypasses Blacksmith outage/nightly exclusions or skips tests.
# The later fleet-client integration replaces that deferred case.
runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || needs.macos-placement.outputs.fast_runner != '' && github.run_attempt == 1 && needs.macos-placement.outputs.fast_runner || (github.run_attempt == 1 || github.run_attempt == 2 && contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && needs.macos-placement.outputs.placed_attempt == format('{0}', github.run_attempt) && contains(needs.macos-placement.outputs.blacksmith_12_jobs, ' fast-tier ') && 'blacksmith-12vcpu-macos-26' || (github.run_attempt == 1 || github.run_attempt == 2 && contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && needs.macos-placement.outputs.placed_attempt == format('{0}', github.run_attempt) && contains(needs.macos-placement.outputs.blacksmith_6_jobs, ' fast-tier ') && 'blacksmith-6vcpu-macos-26' || (github.run_attempt == 1 || github.run_attempt == 2 && contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && needs.macos-placement.outputs.placed_attempt == format('{0}', github.run_attempt) && contains(needs.macos-placement.outputs.owned_jobs, ' fast-tier ') && needs.macos-placement.outputs.runner || needs.macos-placement.outputs.placed_attempt == format('{0}', github.run_attempt) && needs.macos-placement.outputs.retry_runner || needs.macos-placement.outputs.placed_attempt == format('{0}', github.run_attempt) && needs.macos-placement.outputs.deferred_runner || ((github.run_attempt == 1 || github.run_attempt == 2 && contains(fromJSON('["github-actions[bot]","cmux-bot[bot]"]'), github.triggering_actor)) && vars.CI_PR_POOL_OWNED == '1' && vars.CI_SIDE_LANE_RUNNER || vars.MACOS_RUNNER_26 || 'blacksmith-6vcpu-macos-26') }}
permissions:
# The reuse lookup lists artifacts.
actions: read
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/nightly-next-launch-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ jobs:
env:
ROUTE_TOKEN: ${{ steps.route-token.outputs.token }}
SNAPSHOT_TOKEN: ${{ steps.route-token.outputs.token }}
CI_FLEET_GATES: ${{ vars.CI_FLEET_GATES }}
SIDE_LABEL: ${{ github.repository_owner != 'manaflow-ai' && 'macos-26' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'blacksmith-6vcpu-macos-26' || vars.CI_PR_POOL_OWNED == '1' && vars.CI_SIDE_LANE_RUNNER || '' }}
JOBS: launch-smoke
CASCADE_JOBS: launch-smoke
Expand Down
Loading
Loading