diff --git a/.github/workflows/wizrd-review.yml b/.github/workflows/wizrd-review.yml index b25faed..4b5d03f 100644 --- a/.github/workflows/wizrd-review.yml +++ b/.github/workflows/wizrd-review.yml @@ -4,12 +4,17 @@ on: workflow_call: inputs: review_style: - description: 'concise | thorough — appended to the plugin prompt as guidance.' + description: 'concise | thorough' required: false type: string default: 'concise' + confidence_threshold: + description: 'Minimum confidence (0-100) to include an issue. Lower = noisier.' + required: false + type: number + default: 80 extra_instructions: - description: 'Optional extra prompt text appended after the plugin invocation (e.g. point at REVIEW_RULES.md / CLAUDE.md).' + description: 'Optional extra prompt text appended to the review prompt.' required: false type: string default: '' @@ -32,30 +37,108 @@ jobs: steps: - uses: actions/checkout@v5 with: - fetch-depth: 1 + fetch-depth: 0 - uses: anthropics/claude-code-action@v1 with: claude_code_oauth_token: ${{ secrets.claude_token }} - plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' - plugins: 'code-review@claude-code-plugins' + additional_permissions: | + actions: read + claude_args: >- + --allowed-tools + "Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*),Bash(gh issue view:*),Bash(gh api:*),Bash(git log:*),Bash(git diff:*),Bash(git show:*),Bash(git blame:*),Bash(grep:*),Bash(find:*),Bash(ls:*),Bash(cat:*),Bash(head:*),Bash(tail:*),Bash(wc:*),Read,Glob,Grep,Task" prompt: | - /code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }} + You are the Wizrd code reviewer for PR ${{ github.event.pull_request.number }} in **${{ github.repository }}**. + + ## Step 1 — Should we review? + + Run `gh pr view ${{ github.event.pull_request.number }} --json state,isDraft,title,body,comments,additions,deletions,files`. + + Skip (exit without posting anything) if any of: + - PR is closed or merged. + - PR is draft. + - PR is trivial: <10 changed lines, OR only touches lockfiles / generated files / docs typos. + - A previous Wizrd review comment already exists (look for `` marker in existing comments). If one exists, update plan: post a fresh comment only if there are NEW commits since the last review — otherwise skip. + + If skipping, log the reason and stop. Do NOT post anything. + + ## Step 2 — Load review rules + + Read the FIRST file that exists (in this order). Treat its content as the canonical review checklist: + + 1. `REVIEW_RULES.md` — repo-specific checklist. May use rule codes (e.g. B1, R3, A2). Reference codes verbatim in findings. + 2. `CODE_REVIEW.md` — same idea, alternate name. + 3. `CLAUDE.md` — prose project rules. Extract the relevant ones. + 4. `.claude/ci-agent-context.md` — additional CI agent context. + + If none exist, apply standard senior-engineer judgement: correctness, security, simplicity, tests, performance, error handling, type safety. + + ## Step 3 — Read the diff + + `gh pr diff ${{ github.event.pull_request.number }}` — focus only on changed lines. + + For non-trivial PRs (>50 changed lines OR >5 files), spawn parallel sub-agents via the Task tool: + - **Agent A: Rules compliance** — verify every changed file against the loaded review rules. Reference rule codes if available. + - **Agent B: Bug detector** — look for obvious bugs IN THE CHANGES (not pre-existing). Off-by-one, null deref, race conditions, missing await, wrong API, broken happy path. + - **Agent C: Context analyzer** — for any suspicious change, run `git blame` / `git log -p` on surrounding lines to understand why it was that way before. Flag refactors that silently change behaviour. + + For small PRs, do it inline. + + ## Step 4 — Score findings + + Each finding gets a confidence score 0-100: + - 0-24: false positive / not confident → DROP + - 25-49: might be real → DROP + - 50-74: probably real but minor → DROP + - 75-100: real and important → KEEP + + Threshold: **${{ inputs.confidence_threshold }}**. Drop anything below. + + Filter out: + - Pre-existing issues not introduced in this PR. + - Pedantic style nitpicks the linter would catch. + - Auto-generated files, lockfiles, migration boilerplate. + - Issues with `lint-disable` / `eslint-disable` / `# noqa` comments nearby. + + ## Step 5 — Format the review + + ``` + + ## Wizrd review + + <2-sentence PR overview based on the diff> + + ### 🔴 BLOCKING (must fix before merge) + + + ### 🟡 REQUIRED (should fix before merge) + + + ### 🟢 ADVISORY (reviewer discretion) + + + ### ✅ What's Good + <2-3 specific things> + + --- + Style: ${{ inputs.review_style }} · Threshold: ${{ inputs.confidence_threshold }} · ${{ github.sha }} + ``` + + For each finding cite `file:line` and link to the line on GitHub: + `https://github.com/${{ github.repository }}/blob/${{ github.event.pull_request.head.sha }}/#L` + + Be concise. Max ~30 lines combined for BLOCKING + REQUIRED. Group repeated patterns into one finding. - Review style: ${{ inputs.review_style }}. + ## Step 6 — POST THE REVIEW - Before reviewing, read these if present (auto-discovery order): - REVIEW_RULES.md → CODE_REVIEW.md → CLAUDE.md → .claude/ci-agent-context.md. - Apply rule codes from REVIEW_RULES.md if it uses them (B/R/A). Otherwise apply - standard senior-engineer judgement: correctness, security, simplicity, tests. + This is the critical step. Use: - Categorise findings: - 🔴 BLOCKING (must fix before merge) - 🟡 REQUIRED (should fix before merge) - 🟢 ADVISORY (reviewer discretion) - ✅ What's Good (2-3 specific things) + ``` + gh pr comment ${{ github.event.pull_request.number }} \ + --repo ${{ github.repository }} \ + --body-file /tmp/wizrd-review.md + ``` - Be concise. Cite `file:line` for every code finding. Group repeated patterns. - Skip auto-generated files, lockfiles, migration boilerplate. + Write the formatted review to `/tmp/wizrd-review.md` first (heredoc), then post. Do NOT skip this step. Do NOT just print the review to stdout — it MUST land on the PR. ${{ inputs.extra_instructions }}