| description | Fix-iteration agent. When review.md flags a pull request with the 'agent/fixme' label, this agent reads the reviewer's feedback and pushes follow-up commits to the same branch, closing the code -> review -> fix loop. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| true |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if | github.event.label.name == 'agent/fixme' | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| concurrency |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on | ubuntu-26.04 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imports |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tools |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| safe-outputs |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeout-minutes | 15 |
The agent/fixme label was applied to pull request
#${{ github.event.pull_request.number }} by the review agent (review.md),
meaning it found something that needs to change.
Note: this workflow uses a plain pull_request: types: [labeled] trigger
rather than gh-aw's label_command: trigger to maintain manual label
consumption and prevent duplicate re-triggers. The label must be consumed
manually: this workflow removes agent/fixme itself via remove-labels
(step 1 below) so it can't cause a duplicate re-trigger.
-
Remove the
agent/fixmelabel from this PR via theremove-labelssafe-output, so it's consumed and can't re-trigger this workflow. -
Enforce the iteration cap. Run
gh pr view ${{ github.event.pull_request.number }} --json commits --jq '.commits | length'to count the commits on this PR — comparing the count before and after a fix attempt is how to detect whether a new commit was actually pushed, via the GitHub API rather than a rawgit fetch. Usegh/the API for this, notgit fetch: in the sandboxed agent job, a rawgit fetchagainst this (private) repo is not guaranteed to have working credentials, whereasgh/GH_TOKENis always set up for you. If the count is already 3 or more, the cap has been reached:- Do not make any code changes and do not emit a
push-to-pull-request-branchsafe-output. - Emit an
add-commentsafe-output on this PR whose body says: the automated fix loop has reached its iteration limit (3) and automated fixing has stopped; a human needs to review the PR and either push a fix commit and applyagent/lgtmdirectly once satisfied, or close the PR. Explicitly note that re-applyingagent/fixmewill not give the loop another attempt: this cap is simply the total commit count on the branch, which only grows, so relabeling will immediately hit the same cap again without attempting a fix (the only way to actually continue the automated loop is to reduce the branch's commit count, e.g. by squashing, below 3 first). - Stop here. Do not proceed to the remaining steps.
This caps the loop at 2 fix iterations, on the assumption that
drafter.mdpushes exactly one initial commit before this workflow ever runs. If a drafter ever pushes more than one initial commit, the cap will trip slightly earlier than 2 true fix iterations — an accepted trade-off for not depending ongit fetchcredentials that may not be present in the sandbox. - Do not make any code changes and do not emit a
-
Otherwise (cap not reached), determine the PR's branch name by running
gh pr view ${{ github.event.pull_request.number }} --json headRefName --jq .headRefName. -
Read the reviewer's feedback: run
gh pr view ${{ github.event.pull_request.number }} --json reviews(orgh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews) and use the body of the most recent review to see what needs fixing. -
Check out the PR branch and make the smallest change that addresses the feedback.
-
Validate your change using whatever the repo actually provides (tests, a lint command, or a small ad hoc check) — do not assume tooling that may not exist.
-
If your change edits any
.github/workflows/*.mdfile, recompile the lockfiles: runjust setup && just compile(this recompiles all workflows, not just the one you touched — every.lock.ymlmust stay in sync with its.mdsource). Include the resulting.lock.ymlchanges in your commit.justand the pinned gh-aw CLI are already installed; the sandbox can't install them itself. -
Push your fix as a new commit on the same branch via the
push-to-pull-request-branchsafe-output. Do not open a new PR.
- Only ever modify the existing PR branch via
push-to-pull-request-branch— never push directly tomainand never open a new PR. - Always add a new commit; never
git commit --amendan existing commit on this branch.push-to-pull-request-branchcan only convey new file changes — an amend that only changes a commit message (no file diff) has nothing in it for that mechanism to push, and will silently look successful while the branch stays exactly as it was. (This should be rare in practice: see review.md, which doesn't request fixes purely over commit message wording, since messages don't survive the final squash merge anyway.) - Respect the iteration cap in step 2 without exception.
- Always remove
agent/fixme(step 1), even if the iteration cap causes you to stop before making any code changes. - When the iteration cap is reached, never emit
add-labelsforagent/fixmeoragent/lgtm— an unlabeled PR with the cap-reached comment is the intended "stuck, needs a human" signal. Only emit theadd-commentsafe-output described in step 2.