Repository navigation
Feat self healing prs #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Claude Code Improvements | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, ready_for_review, reopened] | |
| # Shared with claude-watcher: both mutate the PR branch (commit + push), so they | |
| # must not run simultaneously. Keying on head branch serializes reviewer and | |
| # watcher runs targeting the same PR into a single queue. | |
| concurrency: | |
| group: claude-pr-${{ github.event.pull_request.head.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| claude-review: | |
| runs-on: self-hosted | |
| if: github.event.pull_request.head.repo.full_name == github.repository | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: read | |
| id-token: write | |
| steps: | |
| - name: Checkout PR branch | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.pull_request.head.ref }} | |
| fetch-depth: 0 | |
| - name: Compute PR diff stats | |
| id: diff | |
| env: | |
| BASE_REF: ${{ github.event.pull_request.base.ref }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| git fetch --no-tags origin "+refs/heads/$BASE_REF:refs/remotes/origin/$BASE_REF" | |
| merge_base=$(git merge-base "origin/$BASE_REF" "$HEAD_SHA") | |
| changed_files=$(git diff --name-only "$merge_base..$HEAD_SHA" | wc -l | tr -d ' ') | |
| changed_lines=$(git diff --shortstat "$merge_base..$HEAD_SHA" | awk '{ ins=0; del=0; for (i=1;i<=NF;i++) { if ($i ~ /insertion/) ins=$(i-1); if ($i ~ /deletion/) del=$(i-1) } print ins + del }') | |
| changed_lines=${changed_lines:-0} | |
| { | |
| echo "files=$changed_files" | |
| echo "lines=$changed_lines" | |
| echo 'file_list<<__EOF__' | |
| git diff --name-only "$merge_base..$HEAD_SHA" | head -50 | |
| echo '__EOF__' | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Classify PR complexity with Haiku | |
| id: classify | |
| uses: ./.github/actions/classify-complexity | |
| with: | |
| oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| prompt: | | |
| Classify this pull request's review complexity. Reply with EXACTLY one lowercase word and nothing else: 'simple' or 'complex'. | |
| simple = typo fix, docs tweak, one-file obvious bug, rename, trivial refactor within a single function, small test-only change | |
| complex = multi-file change, new feature, architecture or API change, deep debugging, performance work, security-sensitive code, anything with unclear scope or touching more than ~3 files | |
| TITLE: ${{ github.event.pull_request.title }} | |
| STATS: ${{ steps.diff.outputs.files }} files, ${{ steps.diff.outputs.lines }} lines changed | |
| FILES: | |
| ${{ steps.diff.outputs.file_list }} | |
| DESCRIPTION: | |
| ${{ github.event.pull_request.body }} | |
| - name: Run Claude Code Review | |
| id: claude-review | |
| uses: anthropics/claude-code-action@v1 | |
| env: | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| REPO: ${{ github.repository }} | |
| HEAD_BRANCH: ${{ github.event.pull_request.head.ref }} | |
| with: | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| plugin_marketplaces: | | |
| https://github.com/anthropics/claude-code.git | |
| https://github.com/abnegate/claudes.git | |
| plugins: | | |
| code-review@claude-code-plugins | |
| skills@claudes | |
| use_sticky_comment: 'false' | |
| use_commit_signing: 'true' | |
| show_full_output: 'true' | |
| claude_args: | | |
| --model ${{ steps.classify.outputs.model }} | |
| --fallback-model ${{ steps.classify.outputs.fallback }} | |
| --dangerously-skip-permissions | |
| prompt: | | |
| You are reviewing and fixing PR #$PR_NUMBER in $REPO. | |
| ## Coordination with the CI watcher | |
| The `claude-watcher` workflow also pushes to this PR branch when CI fails. | |
| We share a concurrency group (branch-keyed), so only one of us runs at a time — | |
| but the OTHER may have pushed between the last event and this job starting. | |
| Before committing in STEP 5, `git fetch origin` and `git pull --rebase origin <branch>`. | |
| If rebase conflicts, resolve them (prefer the other side's changes unless they | |
| contradict a finding you're fixing), then continue. | |
| ## STEP 1 — Analyze | |
| Run `/code-review:code-review` for all CRITICAL/HIGH/MEDIUM findings. Skip low/nits. | |
| ## STEP 2 — Post inline review | |
| Build /tmp/review.json with this structure and post it: | |
| ```json | |
| { | |
| "event": "COMMENT", | |
| "body": "## Code Review\n\n**N finding(s)**\n\nSee inline comments. Fixes incoming.", | |
| "comments": [ | |
| {"path": "file.php", "line": 42, "body": "**[SEVERITY]** ...\n\nExplanation + fix."} | |
| ] | |
| } | |
| ``` | |
| Post: `gh api repos/$REPO/pulls/$PR_NUMBER/reviews --input /tmp/review.json` | |
| If zero findings: post "No critical/high/medium findings." and STOP. | |
| ## STEP 3 — Fix in parallel via isolated worktree subagents | |
| For MAXIMUM speed, launch one Agent per finding using worktree isolation. | |
| Findings in different files run in TRUE parallel — launch them ALL in one message. | |
| Findings in the SAME file go to the SAME agent to avoid conflicts. | |
| Each agent prompt must be self-contained: | |
| - Include the finding: severity, file path, line numbers, what's wrong, how to fix | |
| - Tell it to verify the fix compiles (read CLAUDE.md for the build command) | |
| - Tell it NOT to touch other files or make unrelated changes | |
| Example — 3 findings in 3 files, all launched at once: | |
| Agent({description: "Fix 1", isolation: "worktree", prompt: "Fix [HIGH] ... in file.php line 42 ..."}) | |
| Agent({description: "Fix 2", isolation: "worktree", prompt: "Fix [MEDIUM] ... in other.php line 99 ..."}) | |
| Agent({description: "Fix 3", isolation: "worktree", prompt: "Fix [MEDIUM] ... in third.php line 7 ..."}) | |
| ## STEP 4 — Consolidate | |
| After all agents finish, apply their changes to the main checkout: | |
| - Each worktree agent returns the files it changed | |
| - Cherry-pick or manually apply each agent's diff to the working tree | |
| - If two agents touched the same file, merge carefully | |
| - Verify final result compiles | |
| ## STEP 5 — Commit and push | |
| - `git fetch origin && git pull --rebase origin $HEAD_BRANCH` to absorb any | |
| commits the watcher (or the PR author) pushed while this job was queued | |
| - Capture the pre-commit tip: `BEFORE_SHA=$(git rev-parse HEAD)` | |
| - Stage only fix files | |
| - Commit: `(fix): address review findings — X HIGH, Y MEDIUM` | |
| - Body: one bullet per finding | |
| - Push to PR branch | |
| - Capture the post-push tip: `AFTER_SHA=$(git rev-parse HEAD)` | |
| ## STEP 6 — Post summary comment with compare link | |
| After a successful push, add a follow-up comment linking to a compare view | |
| of everything this run added, so reviewers can see exactly what changed: | |
| COMPARE_URL="https://github.com/$REPO/compare/$BEFORE_SHA...$AFTER_SHA" | |
| gh pr comment $PR_NUMBER --repo $REPO --body "Fixes pushed: $COMPARE_URL | |
| <bulleted list of commits: \`sha\` — subject>" | |
| If BEFORE_SHA equals AFTER_SHA (nothing was actually pushed — e.g. all | |
| fixes were no-ops after rebase), skip this step. | |
| Rules: | |
| - Do NOT skip findings. | |
| - Maximize parallelism — launch as many worktree agents as there are independent file groups. | |
| - Each agent prompt must be fully self-contained (it has no context from this conversation). | |
| - Never push to main. |