From 513c95183f9bf89907b6a395eca9b091d0f293f5 Mon Sep 17 00:00:00 2001 From: Nirupam Bhowmick <48842933+heydryft@users.noreply.github.com> Date: Fri, 21 Aug 2026 16:00:58 +0100 Subject: [PATCH] ci(ArcGate): the base-branch lane refuses the integration branch it should permit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seven open PRs are red for their ADDRESSING, not their quality. The `base-branch` lane hard-fails any PR whose base is not literally `master`, and the PR queue is being restructured so that agents branch off a single integration branch, `release/openrouter-ready`, and PR back into it. The lane's intent is kept intact. It was never really asking "is the base literally master" — it was asking "is the base a stable branch that will itself land on master through a PR this lane has gated". `master` satisfies that. So does exactly one other branch, by construction: `release/openrouter-ready` reaches master through exactly one pull request (#194), whose own base IS `master`, so it takes the `master` arm of this same check and must be green on a tree whose parent is proven master. Master's protection is therefore unchanged: nothing enters master without a full run whose base is master, and `CI complete` still aggregates this lane. The original incident was PRs based on another PR's TRANSIENT branch — a base that can be rebased, force-pushed or abandoned underneath them, so their green described a tree that might never exist. An integration branch is the opposite: long-lived, the tree that will exist, and re-proven against master by #194 before any of it ships. Implementation notes: - Exact-match allowlist via `case`, not a `release/*` glob. A prefix match would let any newly pushed `release/anything` declare itself a landing branch, which is the same unproven-base hole under a new name. - `BASE_REF` still arrives via `env:`, never interpolated into the script. - The job name (`Base branch`) is unchanged, so branch protection and the `ci-complete` needs list keep matching. Verified: the allowlist accepts `master` and `release/openrouter-ready` and refuses `main`, `release/something-else`, `release/openrouter-ready-evil`, `xrelease/openrouter-ready`, `MASTER`, `master*`, `master; echo pwned`, the empty base, and every current PR base branch in the queue. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01UMmjFy8TvsgypxVWNVhhC7 --- .github/workflows/ci.yml | 56 +++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91f8121e0..f14eceb96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,10 +71,40 @@ jobs: # exist. Worse, it is green on code whose parent has not itself been proven — # the stack inherits its base's unreviewed state and reports success anyway. # - # So: refuse. A PR that does not target `master` is red until it is rebased. - # This is deliberately a HARD failure and not a warning — the whole class of - # defect being fixed is "an absence that reads as a pass", and a warning is - # another absence. + # So: refuse. A PR that does not target a LANDING BRANCH is red until it is + # rebased. This is deliberately a HARD failure and not a warning — the whole + # class of defect being fixed is "an absence that reads as a pass", and a + # warning is another absence. + # + # THE ONE EXCEPTION: `release/openrouter-ready` + # --------------------------------------------- + # `master` is not the only branch that satisfies the property this lane + # actually cares about. The property is not "the base is literally master" — + # it is "the base is a stable branch that will itself land on master through a + # PR that this same lane has gated". Exactly one other branch has that + # property, by construction: + # + # * `release/openrouter-ready` is the single integration branch. Agents + # branch off it and PR back into it, so the queue is one merge target + # instead of twenty-two, and a stack's bottom PR is no longer a moving + # base for the ones above it. + # * It reaches master through exactly ONE pull request (#194), and #194's + # base IS `master`, so it hits the `!= master` arm of this very check and + # must be green on a tree whose parent is proven master. Nothing enters + # master without a full run whose base is master. Master's protection is + # therefore UNCHANGED by this widening. + # + # This is why the exception does not reopen the incident. The original defect + # was PRs based on *another PR's transient branch*: a base that can be rebased, + # force-pushed or abandoned under them, so their green described a tree that + # might never exist. An integration branch is the opposite — it is long-lived, + # it is the tree that will exist, and its own contents are re-proven against + # master by #194 before any of it ships. + # + # KEEP THIS LIST AT TWO ENTRIES. Every additional name is another base whose + # own state is not proven by anything, which is precisely the hole this lane + # was built to close. If a second integration branch is ever wanted, the + # honest change is to retire the first one, not to append to this list. # # It is a lane of `ci.yml` rather than its own workflow on purpose: `CI # complete` is the single required status check in branch protection, and it @@ -84,7 +114,7 @@ jobs: name: Base branch runs-on: ubuntu-latest steps: - - name: Refuse a pull request that does not target master + - name: Refuse a pull request that does not target a landing branch # `push`, `schedule` and `workflow_dispatch` have an empty `base_ref`. # The step is skipped for them, but the JOB still succeeds, so # `ci-complete`'s lane count is the same number on every event type. @@ -99,11 +129,17 @@ jobs: set -euo pipefail echo "head: ${HEAD_REF}" echo "base: ${BASE_REF}" - if [ "${BASE_REF}" != "master" ]; then - echo "::error::This PR targets '${BASE_REF}', not 'master'. Its lanes compile the head merged into another PR's branch, which is not the tree that will land. Rebase onto master and retarget the PR. (Stacked PRs used to run ZERO lanes and display only 'comment' — an absence that read as a pass. This lane exists so that state is red instead of blank.)" - exit 1 - fi - echo "Base is master." + # Exact-match allowlist, not a prefix or glob: `release/*` would let + # any newly pushed `release/anything` become a self-declared landing + # branch, which is the same unproven-base hole under a new name. + case "${BASE_REF}" in + master|release/openrouter-ready) ;; + *) + echo "::error::This PR targets '${BASE_REF}', which is neither 'master' nor the integration branch 'release/openrouter-ready'. Its lanes compile the head merged into another PR's branch, which is not the tree that will land. Retarget it at 'release/openrouter-ready' (the single integration branch — it reaches master through PR #194, whose own base is master and which is gated by this same lane), or rebase onto master. (Stacked PRs used to run ZERO lanes and display only 'comment' — an absence that read as a pass. This lane exists so that state is red instead of blank.)" + exit 1 + ;; + esac + echo "Base is '${BASE_REF}' — a landing branch." check: name: Check