chrismdp / fix-review-findings
A failed review is fixed
workflow.yaml
workflow.yaml is AWML 0.6, as it was pushed. The registry draws, checks and fits it converted to AWML 0.8.
# When a Bug review or Security review check fails on a pull request, because the review found
# something Important, a fresh Claude session fixes its findings, Nits included, and the
# repository's app pushes the fix to the pull request's branch as one more commit. It reacts only to
# the failed check, and its only contract is the check's result and the findings the review posted
# in it: it knows nothing of builds, and nothing calls it or waits for it, so every pull request
# whose review fails is fixed the same way, whoever opened it. The push runs CI and the reviews
# again. It stops after two tries on a pull request, never changes Claude Code's own files, and does
# nothing if anyone has pushed since the review. The app can't push a change to a workflow, so a fix
# that touches one is posted on the pull request for a person to apply.
awml: "0.6"
title: A failed review is fixed
scopes:
- { id: public, label: "public: anyone who reads the repository", processing: any }
parts:
- { id: failed, kind: trigger, label: "Bug review or Security review fails on a pull request from a branch of this repository, opened by someone with write access or by the app", wait: PT1H }
- { id: token, kind: connector, label: "The repository, through its own Actions token", in: public, ref: chrismdp/issue-to-pull-request#token }
- { id: app, kind: connector, label: "The repository, through its own GitHub App", in: public, ref: chrismdp/issue-to-pull-request#app }
- { id: bring, kind: code, op: bring-in, label: "Bring in the failed check's findings, the pull request's patch against main, and the commit the review read", in: public }
- { id: asked, kind: context, label: "The findings, the patch and the commit they were found on", in: public }
- { id: tries, kind: code, op: sort, label: "Sort by rule: has anyone pushed since the review, and has the factory already tried twice on this pull request?", in: public }
- { id: giveup, kind: code, op: do, label: "Comment on the pull request that its findings need a person", in: public }
- { id: note, kind: outside, label: "Comment on the pull request: Allow", in: public }
- { id: started, kind: code, op: do, label: "Post or edit the fix's status comment on the pull request", in: public }
- { id: status, kind: outside, label: "Post or edit the fix's status comment: Allow", in: public }
- { id: repo, kind: context, label: "The spec, guide, code, AGENTS.md and REVIEW.md, from the pull request's branch", in: public }
- { id: fix, kind: ai, op: draft, label: "Fix the findings, Important ones and Nits, test first, changing none of Claude Code's own files", in: public }
- { id: change, kind: context, label: "The fix, as a patch, with its message", in: public }
- { id: gate, kind: code, op: check, label: "Run the tests, vet, the examples and wasm parity on the fix", in: public }
- { id: guard, kind: code, op: sort, label: "Sort by rule: does the fix touch Claude Code's own files or a workflow, and is the branch still at the commit the review read?", in: public }
- { id: push, kind: code, op: do, label: "Add the fix to the pull request's branch as one more commit, fast-forward only", in: public }
- { id: offer, kind: code, op: do, label: "Post the fix on the pull request as a patch for a person to apply, since the app may not change a workflow", in: public }
- { id: suggested, kind: outside, label: "Comment the fix on the pull request: Allow", in: public }
- { id: pushed, kind: outside, label: "Push one more commit to the pull request's branch: Allow", in: public }
- { id: contract, kind: comment, label: "Loosely coupled: it reads only the failed check and the findings the review posted in it. Builds and landing don't call it or wait for it" }
- { id: rerun, kind: comment, label: "The app's push starts CI and the reviews again on the new commit, so a fix that brings its own Important finding fails its check and comes back here, up to two tries. The fix is always a new commit, never a rewrite of the branch" }
- { id: same, kind: comment, label: "The session runs as the build's draft does: in a sandbox, keeping the login token from its commands, loading no settings or servers from the tree, with a token that only reads" }
- { id: theirs, kind: comment, label: "A person's push since the review means the branch has moved on, so the fix would be for old code: it stops, saying so" }
lines:
- { from: failed, to: bring, kind: start, label: "the failed check" }
- { from: token, to: bring, kind: data, label: "the check's findings, the patch and the branch's commits" }
- { from: bring, to: asked, kind: data }
- { from: bring, to: tries, kind: start }
- { from: tries, to: giveup, kind: start, label: "[pushed since, or tried twice]" }
- { from: giveup, to: note, kind: data }
- { from: note, to: token, kind: data }
- { from: tries, to: started, kind: start, label: "[otherwise]" }
- { from: started, to: status, kind: data }
- { from: status, to: token, kind: data }
- { from: started, to: fix, kind: start }
- { from: asked, to: fix, kind: data, label: "the findings and the patch" }
- { from: repo, to: fix, kind: data }
- { from: fix, to: change, kind: data }
- { from: fix, to: gate, kind: start, label: "the fix" }
- { from: change, to: gate, kind: data }
- { from: gate, to: giveup, kind: start, label: "[a check fails]" }
- { from: gate, to: guard, kind: start, label: "[all pass]" }
- { from: change, to: guard, kind: data }
- { from: asked, to: guard, kind: data, label: "the commit the review read" }
- { from: guard, to: giveup, kind: start, label: "[touches Claude's files, or the branch moved]" }
- { from: guard, to: offer, kind: start, label: "[touches a workflow]" }
- { from: change, to: offer, kind: data }
- { from: offer, to: suggested, kind: data }
- { from: suggested, to: token, kind: data }
- { from: guard, to: push, kind: start, label: "[none of these]" }
- { from: change, to: push, kind: data }
- { from: push, to: pushed, kind: data }
- { from: pushed, to: app, kind: data }
- { from: contract, to: failed, kind: tie }
- { from: rerun, to: pushed, kind: tie }
- { from: same, to: fix, kind: tie }
- { from: theirs, to: tries, kind: tie }
implementations:
actions:
label: "GitHub Actions, fix.yml"
blocks:
- { id: github, label: "GitHub: pull requests, checks and comments", parts: [failed, token, app, asked, repo, change, note, status, suggested, pushed] }
- { id: readjob, label: "Actions job: bring in the findings and decide, with a token that only reads", platform: actions-code, parts: [bring, tries] }
- { id: statusjob, label: "Actions job: post the status, running nothing from the pull request", platform: actions-code, parts: [started] }
- { id: draftjob, label: "Actions job: fix and check, with a token that only reads", platform: actions-code, parts: [gate] }
- { id: agent, label: "Claude Code, claude-opus-5-5, on the maintainer's subscription", platform: actions-agent, in: draftjob, parts: [fix] }
- { id: pushjob, label: "Actions job: push or comment, running nothing from the change", platform: actions-code, parts: [guard, push, offer, giveup] }