Repository navigation
Description
This was generated by AI during triage.
What happened
The Architect run on 2026-10-01 dispatched #253 and ended as a Failed run with CI red on 76a8a15 and the Repair found nothing to fix on the branch (PR #258).
- The
testcheck failed on76a8a15because of a flaky test in the suite, unrelated to the branch (run 36844055894). - Repair 1 diagnosed it correctly as flaky, made no commit, and added a "CI notes" section to the PR body, as the CI-fix Repair prompt asks.
- The head was still the commit whose CI had failed, so the Run ended as a Declined CI fix.
- The Failed-run marker commit that was pushed next triggered CI again, and every check passed on the same code.
One re-run of the failed check would have let the Run finish. #102, which introduced the Declined CI fix, left re-running CI on an unchanged head out of scope; this issue takes it up.
Agent Brief
Category: enhancement
Summary: When a CI-fix Repair leaves the head unchanged, re-run the failed checks once and watch CI again before failing the Run as a Declined CI fix.
Current behavior:
In the Repair loop, red CI on the head starts a CI-fix Repair for the branch's own failed checks. If, after the Repair and the Base branch merged in again, the head is still the commit whose CI failed, the Run is a Failed run with the cause CI red on <short sha> and the Repair found nothing to fix on the branch. A check that failed for a reason that would not repeat (a flaky test, a runner or network fault) therefore fails the Run even though the same commit would pass.
Desired behavior:
At the point where the Run would today fail as a Declined CI fix, thirdshift first asks GitHub to re-run the branch's own failed checks on that head, says so in a progress line, and watches CI on that head again.
- Trigger: the head being unchanged after a CI-fix Repair, and nothing else. What the Repair concluded or wrote is never read; this is a deterministic check, in line with ADR 0008.
- Order: the CI-fix Repair runs first, as today. No check is re-run before a Repair has been given the failure.
- Green after the re-run: the Run carries on exactly as it does for any head whose CI was found green (Base branch moved while CI ran, Foreign commits in a Merge run, and so on).
- Red after the re-run: the Run is a Failed run with the Declined CI fix cause, as today. No second Repair is started for that head and nothing is re-run a second time.
- One re-run per head. A later head (a Repair that committed, the Base branch merged in again) may get its own. A re-run starts no Repair and does not count against the Repair budget.
- Checks that can't be re-run: if any of the branch's own failed checks cannot be re-run (a commit status, or a check run that does not belong to a GitHub Actions workflow run), the head cannot go green, so nothing is re-run and the Run fails as a Declined CI fix straight away, as today. The same holds if GitHub refuses the re-run request (for example, missing permission): the refusal shows in a progress line and the Run fails with the Declined CI fix cause, not with the refusal as its cause.
- Inherited failures are never re-run and are handled as they are today. Only the branch's own failed checks are.
- No stale result: the watch after the re-run must not take the failed result of the attempt before the re-run for the result of the re-run. It waits for the new attempt to appear and finish, within the same waiting rules as any other CI watch.
- This applies everywhere the Repair loop runs: a Run, a Merge run, and the Spec PR's Repair loop.
Key interfaces:
- The Repair loop's head-unchanged check after a CI-fix Repair (where the Declined CI fix cause is raised): it gains the one re-run per head before failing.
- The failed checks the CI watch returns (
FailedChecks, itsownandinheritedlists): each own check needs enough to tell whether it can be re-run and which workflow run it belongs to. The check run's details URL, already read, names the Actions run. - GitHub's "re-run failed jobs" for a workflow run (
gh run rerun <run-id> --failed, orPOST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs). Several failed checks may share one workflow run: ask once per run. - The fake
ghin the test harness: it needs to accept the re-run request, record it, and let a scenario say what the re-run comes to. CONTEXT.md: the Declined CI fix term now ends a Run only after the re-run. Give the re-run a glossary term if it needs one to be talked about.- The Failed-run cause string stays as it is.
Acceptance criteria:
- A test where CI fails, the CI-fix Repair makes no commit, and the re-run passes: exactly one Repair, exactly one re-run request, and the Run reaches its goal (ready for review; merged in a Merge run).
- A test where the re-run fails again: exactly one Repair, exactly one re-run request, and a Failed run with the cause
CI red on <short sha> and the Repair found nothing to fix on the branch. - A test where one of the branch's own failed checks is a commit status (or otherwise can't be re-run): no re-run request, and the Run fails as a Declined CI fix as it does today.
- A test where GitHub refuses the re-run request: the Run fails with the Declined CI fix cause, and stderr shows the refusal.
- A test where the head has both an own failure and an Inherited failure: only the own check's workflow run is re-run.
- A CI-fix Repair that commits is followed by no re-run request (existing tests still pass unedited, apart from those asserting the old Declined CI fix path).
- stderr has a progress line naming the head when checks are re-run.
- After the re-run, the old attempt's failed result is never reported as the re-run's result.
-
CONTEXT.md, the README and the help text describe the re-run wherever they describe the Declined CI fix or how a Run fails. - An ADR records the decision and the options turned down: re-running before any Repair (adds a full CI cycle to every real failure), and re-running only when the Repair calls the failure flaky (leaves the outcome to the agent's judgement).
Out of scope:
- Re-running checks before a CI-fix Repair has run, or more than once per head.
- Reading the Repair's verdict, or the "CI notes" section of the PR body, to decide anything. The note stays in the PR body even when the re-run passes.
- Changing the CI-fix Repair prompt.
- Re-running or triggering CI on the Base branch, and any change to Inherited failures or the Base fix.
- Changing
MAX_REPAIRSor the upstream-move budget. - Fixing the flaky test that prompted this; that is separate work.
Activity