You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CI watch reads checks cancelled by a newer push as a failure and starts a Repair #839
On 2026-10-19, two Runs worked #812 at once: stephens was on 0.12.0, which has no Pickup reservation (ADR 0017). Both pushed to issue-812 and PR #834.
This host's Run merged the other's commits and pushed b97872e.
GitHub then cancelled the CI run already going on the earlier head, 9f546fe.
stephens' CI watch read the cancelled checks as red: CI failed on 9f546fe: test-macos, announce, host, build-global-artifacts, …. It started Repair 1 of 5 for failures that never happened, and spent about 10 minutes running the test suite.
When stephens' copy was then Stopped, its failed-run handling had two effects:
It pushed an empty salvage commit, 1b54f53, with the same tree as b97872e.
This host's Run then ended failed: PR … is a draft, mid-CI watch, and left the Claim and its worktree behind.
Wanted
A head that's no longer the pull request's head is superseded, not failed. CI watch should treat checks cancelled because a newer commit arrived on the branch as superseded. It should watch the new head, or stop watching if someone else's push took the head, but never start a Repair for them.
Cancelled checks need a careful reading in general. Concurrency cancellation reports cancelled, not failure, so it can be told apart from a red check.
A failing or stopped Run shouldn't draft a PR that another live Run is watching, or at least the other Run should be told why, rather than failing on "is a draft". With the Pickup reservation this needs two Runs on one issue, which shouldn't happen any more, but a Run started by hand on an Issue URL can still overlap one.
Evidence
stephens: commands/pickup/812-20261019T162801+0000.log, 17:13:47 to 17:13:48.
thirdshift host: commands/pickup/812-20261019T122802-0400~yURugvGDBDen3mFb.log, 13:23:39 to 13:23:40.
gh run list --branch issue-812: CI on 9f546fe completed cancelled.
Category: bug Summary: CI watch treats checks superseded by a newer CI run as superseded, not red, and starts no Repair for them
This brief also covers #927, which is closed into this issue.
Current behavior:
CI watch reads every check run and commit status on the head it watches, from every check suite on that commit. It waits until none is pending, and reads any cancelled conclusion as a failure. The Repair loop then starts a CI-fix Repair for the branch's own failures.
Two kinds of cancellation are not failures of the head:
Same head. When one GitHub Actions workflow has more than one workflow run on the watched head, only the most recent run's checks count. The earlier runs' checks are superseded and ignored, whatever their conclusion. CI watch waits for the most recent run's pending checks as usual. A Check re-run's new attempt belongs to the same workflow run, so this rule never supersedes it, and Check re-run behavior is unchanged.
Moved Issue branch. When the watched head's CI is red and the Issue branch on origin no longer points at that head, the head's cancelled checks are superseded, not failures. If nothing else failed, the Repair loop starts no CI-fix Repair for that head and consumes no Check re-run for it. It says so in a progress line, e.g. CI on <sha> was superseded by a newer push, and goes round again, counted as an upstream move. In a Merge run, the next round takes in the new commits as it already does. A Run left ready for review keeps its existing handling of a moved Issue branch: this change only removes the CI-fix Repair for the superseded head. A check that genuinely failed on that head is handled as today.
Inherited failures. The same supersession applies when CI watch reads the Base branch commit's checks for Inherited failures.
Unchanged. A cancelled check with no newer run of its workflow on the head, on an Issue branch that hasn't moved, still reads as failed.
Key interfaces:
CI watch's reading of conclusions (reading, Ci) and the checks it lists for a commit (checks_on). ActionsJob gives a check run's workflow run. GitHub's workflow-run listing for a head gives each run's workflow and creation time.
The Repair loop's rounds, its upstream-move budget, and its view of new commits on the Issue branch on origin (new_commits_on_origin).
Checks that aren't GitHub Actions jobs, and commit statuses, are read as today.
Acceptance criteria:
On one head, an older run's cancelled test beside a newer run's pending test makes CI watch wait, then pass when the newer one succeeds. No Repair starts.
On one head, an older run's failed check is ignored when a newer run of the same workflow succeeds.
A cancelled check with no newer run of its workflow, on an Issue branch that hasn't moved, still fails CI as today.
A Merge run whose watched head's checks are cancelled after another writer's push starts no CI-fix Repair and consumes no Check re-run. It takes in the new commits and watches the new head.
The Inherited failure comparison ignores superseded checks on the Base branch commit.
Existing CI watch, Check re-run, Abandoned job and Inherited failure tests pass.
Activity
JacobStephens2 commentedon Oct 21, 2026
Agent Brief
Category: bug
Summary: CI watch treats checks superseded by a newer CI run as superseded, not red, and starts no Repair for them
This brief also covers #927, which is closed into this issue.
Current behavior:
CI watch reads every check run and commit status on the head it watches, from every check suite on that commit. It waits until none is pending, and reads any
cancelledconclusion as a failure. The Repair loop then starts a CI-fix Repair for the branch's own failures.Two kinds of cancellation are not failures of the head:
CI failed on 9f546fe: test-macos, announce, …from such cancelled checks. It started Repair 1 of 5 and spent about ten minutes on failures that never happened.labeledorreopenedevent starts a new run of the same workflow on the same head, and concurrency cancels the older one. Its cancelled check runs stay on the head beside the new run's. On PR Run the full macOS suite on main and nightly, with a one-job macOS gate on PRs into main #925,testwas listed three times on one head:cancelledfrom the cancelled run,successfrom an earlier run, andin_progressfrom the new one.Desired behavior:
cancelledchecks are superseded, not failures. If nothing else failed, the Repair loop starts no CI-fix Repair for that head and consumes no Check re-run for it. It says so in a progress line, e.g.CI on <sha> was superseded by a newer push, and goes round again, counted as an upstream move. In a Merge run, the next round takes in the new commits as it already does. A Run left ready for review keeps its existing handling of a moved Issue branch: this change only removes the CI-fix Repair for the superseded head. A check that genuinely failed on that head is handled as today.cancelledcheck with no newer run of its workflow on the head, on an Issue branch that hasn't moved, still reads as failed.Key interfaces:
reading,Ci) and the checks it lists for a commit (checks_on).ActionsJobgives a check run's workflow run. GitHub's workflow-run listing for a head gives each run's workflow and creation time.new_commits_on_origin).Acceptance criteria:
testbeside a newer run's pendingtestmakes CI watch wait, then pass when the newer one succeeds. No Repair starts.Out of scope: