From bd72c632a880fceb252a9de22164d32315352d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Tue, 4 Aug 2026 18:36:21 +0200 Subject: [PATCH] ci(gc): gc-native-roots had never completed a run; one arm on PRs Measured today: 40 of 40 runs queued, ZERO completed, oldest sitting nine hours. Every other workflow drained 2-3 runs per 20 in the same window; this one drained none. The cause is the matrix -- four runner classes, two of them the scarcest GitHub offers (macos-14, windows-latest), fanned out on every push to every branch. With ~20 of its own runs competing for those runners it could not drain, and cancelling the backlog refilled it within minutes because merges outpace the drain rate. A gate that never executes is the purest form of CLAUDE.md's fourth failure mode: it cannot fail, because it cannot run. Every PR in the campaign that built this gate showed it "pending" -- an assertion nobody had ever evaluated. Pull requests now run the ubuntu-latest arm only; main and workflow_dispatch keep all four. ubuntu-latest is the PR arm because its runners are plentiful and it exercises the least-redundant path: x86-64 roots resolve through the CFA-derived SP base (#7349), which neither the aarch64 x29 chain walk nor Windows' RtlVirtualUnwind shares. Cost, stated rather than buried: a break confined to macOS, Windows or aarch64-ELF now surfaces on main instead of on the PR. Worth it while the alternative is surfacing nowhere. gc-native-roots-complete reads the matrix job's aggregate result, so it stays a stable context for branch protection whichever arm count ran -- which is what makes promotion to required possible at all. Claude-Session: https://claude.ai/code/session_01EaD6yNwoinzdW1JbYNkMMF --- .github/workflows/gc-native-roots.yml | 42 +++++++++++++------ .../7386-gc-native-roots-never-runs.md | 32 ++++++++++++++ 2 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 changelog.d/7386-gc-native-roots-never-runs.md diff --git a/.github/workflows/gc-native-roots.yml b/.github/workflows/gc-native-roots.yml index bbc352c5de..6df0f07427 100644 --- a/.github/workflows/gc-native-roots.yml +++ b/.github/workflows/gc-native-roots.yml @@ -113,6 +113,11 @@ jobs: # unwinder under it, which is why its arm alone carries the # `--require-locations` telemetry gate below. # + # NOTE: all four shapes run on `main` and on `workflow_dispatch`; a pull + # request runs only the `ubuntu-latest` arm. See the comment on the matrix + # itself for why — the short version is that fanning four runner classes out + # on every push meant the workflow never completed a run at all. + # # ARM64 Linux is the fourth arm, and the note that used to sit here — that # its "two components are each covered above" — was the exact compositional # fallacy `word_width_for` in `gc_map.rs` exists to warn about. `.word` is @@ -135,20 +140,31 @@ jobs: native-roots-rs4gc: strategy: fail-fast: false + # ONE arm on pull requests, all four on `main` and on demand. + # + # Measured 2026-08-04: this workflow had **never completed a single run** + # — 40 of 40 queued, the oldest sitting nine hours. Every other workflow + # in the repo was draining 2–3 runs per 20 in the same window. The cause + # is this matrix: four runner classes, two of them the scarcest GitHub + # offers (macOS and Windows), fanned out on every push to every branch. + # With ~20 of its own runs competing for those runners it could not + # drain, and cancelling the backlog refilled it within minutes. + # + # A gate that never executes is the purest form of CLAUDE.md's fourth + # failure mode: it cannot fail, because it cannot run. One executing arm + # is worth more than four that never start. + # + # `ubuntu-latest` is the PR arm because its runners are plentiful and it + # exercises the path with the least redundancy elsewhere: x86-64 roots go + # through the CFA-derived SP base (#7349), which neither the aarch64 x29 + # chain walk nor Windows' RtlVirtualUnwind shares. The cost is that a + # break confined to macOS, Windows or aarch64-ELF surfaces on `main` + # rather than on the PR — acceptable while the alternative is surfacing + # nowhere. matrix: - include: - - os: macos-14 - arch: aarch64 - format: Mach-O - - os: ubuntu-latest - arch: x86-64 - format: ELF - - os: windows-latest - arch: x86-64 - format: PE - - os: ubuntu-24.04-arm - arch: aarch64 - format: ELF + include: ${{ fromJSON(github.event_name == 'pull_request' + && '[{"os":"ubuntu-latest","arch":"x86-64","format":"ELF"}]' + || '[{"os":"macos-14","arch":"aarch64","format":"Mach-O"},{"os":"ubuntu-latest","arch":"x86-64","format":"ELF"},{"os":"windows-latest","arch":"x86-64","format":"PE"},{"os":"ubuntu-24.04-arm","arch":"aarch64","format":"ELF"}]') }} runs-on: ${{ matrix.os }} # The ubuntu/macos steps were written for bash and windows-latest defaults # to pwsh; one explicit default keeps a single script dialect per step. diff --git a/changelog.d/7386-gc-native-roots-never-runs.md b/changelog.d/7386-gc-native-roots-never-runs.md new file mode 100644 index 0000000000..219ef97cb9 --- /dev/null +++ b/changelog.d/7386-gc-native-roots-never-runs.md @@ -0,0 +1,32 @@ +### Fixed + +**`gc-native-roots` had never completed a single run. It runs one arm on PRs now, all four on `main`.** + +Measured 2026-08-04: **40 of 40 runs queued, zero completed**, the oldest sitting +nine hours. Every other workflow in the repo drained 2–3 runs per 20 in the same +window — `gc-ratchet` 2/20, `gc-root-dominance` 2/20, `test.yml` 3/20, +`gc-native-roots` **0/20**. + +The cause is the matrix: four runner classes, two of them the scarcest GitHub +offers (`macos-14`, `windows-latest`), fanned out on every push to every branch. +With ~20 of its own runs competing for those runners it could not drain, and +cancelling the backlog refilled it within minutes because merges outpace the +drain rate. + +A gate that never executes is the purest form of CLAUDE.md's fourth failure +mode — it cannot fail, because it cannot run. Every green PR that showed this +workflow "pending" was showing an assertion nobody had ever evaluated, including +every PR in the campaign that built it. + +Pull requests now run the `ubuntu-latest` arm only; `main` and +`workflow_dispatch` keep all four. `ubuntu-latest` is the PR arm because its +runners are plentiful and it exercises the least-redundant path: x86-64 roots +resolve through the CFA-derived SP base (#7349), which neither the aarch64 x29 +chain walk nor Windows' `RtlVirtualUnwind` shares. + +The cost, stated rather than buried: a break confined to macOS, Windows or +aarch64-ELF now surfaces on `main` instead of on the PR. That is worth taking +while the alternative is surfacing nowhere. `gc-native-roots-complete` reads the +matrix job's aggregate result, so it stays a stable context for branch +protection whichever arm count ran — which is what makes promoting it to +required possible at all.