Skip to content

main cannot return to green by itself: diff-scoped gates anchor on the last SUCCESSFUL run, so a red main widens its own range and keeps re-flagging the commits blocking it #1773

Description

@localai-bot

main cannot return to green on its own once it has been red across a commit that any diff-scoped gate flags. The range that decides those gates is anchored to the last successful run, and a successful run is what the gate is blocking.

The cycle, from .github/workflows/ci.yml

last-gated-commit resolves the anchor:

sha="$(gh api \
  "repos/$REPO/actions/workflows/ci.yml/runs?branch=$BRANCH&event=push&status=success&per_page=1" \
  --jq '.workflow_runs[0].head_sha')"

documentation-checkpoint consumes it on a push to main:

base="${LAST_GREEN:-}"
[ -n "$base" ] || base="$PUSH_BASE"
head="$PUSH_HEAD"
python3 scripts/check-now-current.py --base "$base" --head "$head"

So: main goes red → no successful run → LAST_GREEN stays put → every later push widens LAST_GREEN..HEAD → the widening range keeps re-including the commit that is being flagged → the job fails again → still no successful run. The exit condition requires the thing it blocks.

Observed now: documentation-checkpoint on main flags dd8a3b0e1, 8daf58e77 and 38ec0da4a — three commits from 2026-08-18, five days old, each carrying the full protocol paragraph and all three trailers, each with a single parent (the shape of a squash merge, this repository's only landing mode). Two are from external contributors, whose row/<ID> branches live on their forks and can never appear on origin. They cannot be retroactively re-landed, so under the present anchor they will be flagged on every push forever.

Two defects, and the repository already documents both

scripts/main-baseline.py (issue #274, spec .agents/specs/main-verifiability.md) was written to answer exactly "what is the last SHA where main was fully green", and its own header records the two reasons a naive query cannot:

  1. Runs do not finish. "Every expensive job in ci.yml carries a job-level concurrency group keyed on github.ref with cancel-in-progress: true. For a push to main that ref is the constant refs/heads/main, so consecutive pushes cancel each other's long jobs — 26 of the last 40 main runs were cancelled." A cancelled run is not success, so on a busy day the anchor drifts back by many commits even with nothing broken. Confirmed live today: the three newest ci runs on main (15298f033, aa67130cc, 6991b78d2) are all cancelled.

  2. Run-level success is not per-job success. "sanitize-cpu is continue-on-error: true, so its failure does not fail the run... A tool that trusted the run conclusion would publish that SHA as the known-good baseline. The verdict is computed from PER-JOB conclusions, always."

last-gated-commit queries status=success at the run level — precisely what main-baseline.py says must not be trusted — and does not use main-baseline.py at all. The tool built to answer this question is not wired to the job that asks it.

Why this is worth fixing rather than clearing by hand

Clearing it once (landing something that makes a run succeed) resets the anchor and hides the mechanism until the next red. The cost is paid repeatedly and by everyone: a red main blocks every branch, and this week three separate lanes converged on #1731 because a blocking red creates pressure to act before checking ownership, producing a duplicate issue (#1733) and duplicate branches.

Candidate directions, not a prescription

  • Anchor last-gated-commit on scripts/main-baseline.py's per-job verdict rather than a run-level status=success query.
  • Give the anchor a floor, so a range can never widen past a recorded baseline no matter how long main has been red.
  • Decide what a diff-scoped gate should do with a squash merge whose branch is on a fork — teach the checker, or record a bounded exception. Note that whatever is decided must not weaken the rule for work that can use an origin branch.

Whoever takes this should confirm the cycle by construction (a red push, then a second push, and show the range widening) rather than only by reading, since the claim is about a feedback loop.

Refs #1764 (the three current reds), #274.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions