PR Swarm Grade — Fix Pass Auditor
Audit fix commits against review findings and produce a graded report card. Use after /pr-swarm fix pass to QA the fixes.
Invocation
/pr-swarm-grade — detect PR from current branch
/pr-swarm-grade 19 — grade fixes for PR #19
Phase 1 — Locate Artifacts
1a. Identify the PR
- If an argument is provided, use it as
PR_NUMBER.
- Otherwise, detect from current branch:
gh pr view --json number --jq '.number'.
- If neither works → STOP: "No PR found. Usage:
/pr-swarm-grade [PR_NUMBER]"
1b. Read review state
REVIEW_DIR="docs/reviews/PR-${PR_NUMBER}"
- Read
${REVIEW_DIR}/_state.json → extract pr_number, head_sha, pr_title, agents, compiled.
- If
_state.json doesn't exist → STOP: "No review found for PR #${PR_NUMBER}. Run /pr-swarm first."
- If
compiled is false → STOP: "Review for PR #${PR_NUMBER} hasn't been compiled yet."
1c. Read compiled report
- Read
${REVIEW_DIR}/compiled-report.md.
- Parse into a structured list of findings. Each finding has:
- Number (sequential)
- Category:
Must Fix, Suggestions, or Nitpicks — from section header
- Location: file:line reference
- Title: short description
- Agents: which review agents flagged it
- Description: full finding text
1d. Get fix commits
HEAD_SHA=<head_sha from _state.json>
git log ${HEAD_SHA}...HEAD --oneline
- If no commits → findings default to MISS, but fixes comment can still yield SKIP-OK/SKIP-BAD.
- Store the commit list.
1e. Get the diff
git diff ${HEAD_SHA}...HEAD
- If PR is merged, check if
HEAD_SHA is reachable. If not, try merge commit.
- Store full diff for cross-referencing.
1f. Find "Review Fixes Applied" comment
gh pr view ${PR_NUMBER} --json comments --jq '.comments[].body'
- Look for comment starting with
## Review Fixes Applied.
- Parse Fixed and Skipped lists.
- If no such comment → warn: "No 'Review Fixes Applied' comment found. Grading from diff only."
Phase 2 — Cross-Reference
For each finding from the compiled report, determine a verdict:
Verdict Criteria
| Verdict |
Criteria |
| PASS |
Diff clearly addresses the finding. Code change matches the recommended fix. |
| PARTIAL |
Diff touches relevant code but doesn't fully address the finding. |
| MISS |
Finding not addressed in diff at all. |
| REGRESSION |
Diff introduces a new issue in the area the finding referenced. |
| SKIP-OK |
Finding explicitly skipped with reasonable justification. |
| SKIP-BAD |
Finding skipped but justification is weak or finding was a Must Fix. |
Cross-Reference Process
For each finding:
- Check the diff: Does it contain changes to the referenced file(s) and line range(s)?
- Check the fixes comment: Is this finding in "Fixed" or "Skipped"?
- Check for dishonesty: If fixes comment claims "Fixed" but diff doesn't support it → Dishonest Claim.
- Check for regressions: If diff changes relevant code but introduces new problems → REGRESSION.
- Assess fix quality (PASS and PARTIAL only): Critique the approach, assign quality tag:
Quality Tags (PASS and PARTIAL only)
| Tag |
Meaning |
| Excellent |
Ideal fix — correct approach, clean implementation, handles edge cases. |
| Good |
Solid fix — correct and reasonable. Default for clean PASS. |
| Adequate |
Gets the job done but could be better. |
| Minimal |
Bare minimum — technically addresses finding but cuts corners. |
| Over-engineered |
Correct but unnecessarily complex for what was needed. |
Flags
- Dishonest Claim: Fixes comment says fixed, but diff contradicts.
- Proactive Fix: Something fixed that wasn't in findings (bonus credit).
- Undocumented Skip: Finding not in diff AND not in fixes comment.
Phase 3 — Grade
Per-Finding Scoring
| Verdict |
Base Score |
| PASS |
100 |
| PARTIAL |
60 |
| SKIP-OK |
50 |
| MISS |
0 |
| SKIP-BAD |
0 |
| REGRESSION |
-50 |
Category Weights
| Category |
Weight |
| Must Fix |
3x |
| Suggestions |
1x |
| Nitpicks |
0.5x |
Score Calculation
weighted_score = sum(finding_score * category_weight) for each finding
max_possible = sum(100 * category_weight) for each finding
raw_percentage = (weighted_score / max_possible) * 100
Modifiers (applied to final percentage)
| Modifier |
Points |
Condition |
| Proactive fixes |
+5 (cap +10) |
Each fix beyond what was flagged |
| Regression |
-10 |
Each REGRESSION verdict (stacks) |
| Dishonest claim |
-5 |
Each dishonest claim (stacks) |
Letter Grade Scale
| Grade |
Range |
| A+ |
97-100 |
| A |
93-96 |
| A- |
90-92 |
| B+ |
87-89 |
| B |
83-86 |
| B- |
80-82 |
| C+ |
77-79 |
| C |
73-76 |
| C- |
70-72 |
| D |
60-69 |
| F |
Below 60 |
Final score clamped to 0-100 after modifiers.
Phase 4 — Report Card
Write to ${REVIEW_DIR}/grade-report.md and present in conversation. Do NOT post to PR.
Output Format
## Grade Report — PR #${PR_NUMBER}: ${PR_TITLE}
**Overall: ${LETTER_GRADE} (${SCORE}/100)**
| Category | Addressed | Total | Score |
|--------------|-----------|-------|-------|
| Must Fix | X/Y | Y | Z% |
| Suggestions | X/Y | Y | Z% |
| Nitpicks | X/Y | Y | Z% |
### Must Fix
1. **${VERDICT}** · ${QUALITY} — `${location}` — ${title}
_What changed:_ ${factual description}
_Feedback:_ ${opinionated quality assessment}
### Suggestions
...
### Nitpicks
...
### Flags
- **Dishonest claim**: Finding #${N} claimed fixed but diff shows ${what}.
- **Proactive fix**: ${description}.
- **Undocumented skip**: Finding #${N} not addressed and not mentioned.
(Omit Flags section if none.)
### Summary
${2-3 sentence assessment: quality, strengths, gaps, recommendation}
Formatting Rules
- Number findings matching compiled report numbering.
- Use exact verdict labels: PASS, PARTIAL, MISS, REGRESSION, SKIP-OK, SKIP-BAD.
- "Addressed" counts PASS + PARTIAL + SKIP-OK.
- Every PASS/PARTIAL has two lines:
_What changed:_ — factual, 1 sentence.
_Feedback:_ — opinionated, 1-2 sentences. Judgment, not description.
- Quality tags appear after verdict for PASS/PARTIAL only.
_Feedback:_ must express judgment. Bad: "Used a typed setter map." Good: "Clean approach — eliminates unsafe cast without over-engineering."
Edge Cases
| Situation |
Behavior |
| No review directory |
STOP: "No review found for PR #X" |
| Review not compiled |
STOP: "Review not compiled yet" |
| No fix commits |
Grade from fixes comment skips; all findings MISS unless justified |
| No fixes comment |
Warn, grade from diff only, skip dishonesty checks |
| PR already merged |
Warn, use merge commit range |
| Squash-merged PR |
The HEAD_SHA...HEAD range may collapse to nothing. Check the PR merge commit instead: gh pr view --json mergeCommit |
| Empty compiled report |
STOP: "No findings to grade" |
Hard Rules
- Read-only. Do not modify files, post comments, or push code.
- Grade every finding. No finding from compiled report should be skipped.
- Be honest. Grade what the diff shows, not what the fixes comment claims.
- Show your work. Each verdict must reference specific code changes (or lack thereof).
1---2name: pr-swarm-grade3description: Grade fix quality after /pr-swarm — cross-reference findings against diff, produce letter-grade report card.4---56# PR Swarm Grade — Fix Pass Auditor78Audit fix commits against review findings and produce a graded report card. Use after `/pr-swarm` fix pass to QA the fixes.910## Invocation1112```13/pr-swarm-grade — detect PR from current branch14/pr-swarm-grade 19 — grade fixes for PR #1915```1617---1819## Phase 1 — Locate Artifacts2021### 1a. Identify the PR2223- If an argument is provided, use it as `PR_NUMBER`.24- Otherwise, detect from current branch: `gh pr view --json number --jq '.number'`.25- If neither works → STOP: "No PR found. Usage: `/pr-swarm-grade [PR_NUMBER]`"2627### 1b. Read review state2829```bash30REVIEW_DIR="docs/reviews/PR-${PR_NUMBER}"31```3233- Read `${REVIEW_DIR}/_state.json` → extract `pr_number`, `head_sha`, `pr_title`, `agents`, `compiled`.34- If `_state.json` doesn't exist → STOP: "No review found for PR #${PR_NUMBER}. Run `/pr-swarm` first."35- If `compiled` is false → STOP: "Review for PR #${PR_NUMBER} hasn't been compiled yet."3637### 1c. Read compiled report3839- Read `${REVIEW_DIR}/compiled-report.md`.40- Parse into a structured list of findings. Each finding has:41 - **Number** (sequential)42 - **Category**: `Must Fix`, `Suggestions`, or `Nitpicks` — from section header43 - **Location**: file:line reference44 - **Title**: short description45 - **Agents**: which review agents flagged it46 - **Description**: full finding text4748### 1d. Get fix commits4950```bash51HEAD_SHA=<head_sha from _state.json>52git log ${HEAD_SHA}...HEAD --oneline53```5455- If no commits → findings default to MISS, but fixes comment can still yield SKIP-OK/SKIP-BAD.56- Store the commit list.5758### 1e. Get the diff5960```bash61git diff ${HEAD_SHA}...HEAD62```6364- If PR is merged, check if `HEAD_SHA` is reachable. If not, try merge commit.65- Store full diff for cross-referencing.6667### 1f. Find "Review Fixes Applied" comment6869```bash70gh pr view ${PR_NUMBER} --json comments --jq '.comments[].body'71```7273- Look for comment starting with `## Review Fixes Applied`.74- Parse **Fixed** and **Skipped** lists.75- If no such comment → warn: "No 'Review Fixes Applied' comment found. Grading from diff only."7677---7879## Phase 2 — Cross-Reference8081For **each finding** from the compiled report, determine a verdict:8283### Verdict Criteria8485| Verdict | Criteria |86|---------|----------|87| **PASS** | Diff clearly addresses the finding. Code change matches the recommended fix. |88| **PARTIAL** | Diff touches relevant code but doesn't fully address the finding. |89| **MISS** | Finding not addressed in diff at all. |90| **REGRESSION** | Diff introduces a new issue in the area the finding referenced. |91| **SKIP-OK** | Finding explicitly skipped with reasonable justification. |92| **SKIP-BAD** | Finding skipped but justification is weak or finding was a Must Fix. |9394### Cross-Reference Process9596For each finding:97981. **Check the diff**: Does it contain changes to the referenced file(s) and line range(s)?992. **Check the fixes comment**: Is this finding in "Fixed" or "Skipped"?1003. **Check for dishonesty**: If fixes comment claims "Fixed" but diff doesn't support it → **Dishonest Claim**.1014. **Check for regressions**: If diff changes relevant code but introduces new problems → **REGRESSION**.1025. **Assess fix quality** (PASS and PARTIAL only): Critique the approach, assign quality tag:103104### Quality Tags (PASS and PARTIAL only)105106| Tag | Meaning |107|-----|---------|108| **Excellent** | Ideal fix — correct approach, clean implementation, handles edge cases. |109| **Good** | Solid fix — correct and reasonable. Default for clean PASS. |110| **Adequate** | Gets the job done but could be better. |111| **Minimal** | Bare minimum — technically addresses finding but cuts corners. |112| **Over-engineered** | Correct but unnecessarily complex for what was needed. |113114### Flags115116- **Dishonest Claim**: Fixes comment says fixed, but diff contradicts.117- **Proactive Fix**: Something fixed that wasn't in findings (bonus credit).118- **Undocumented Skip**: Finding not in diff AND not in fixes comment.119120---121122## Phase 3 — Grade123124### Per-Finding Scoring125126| Verdict | Base Score |127|---------|-----------|128| PASS | 100 |129| PARTIAL | 60 |130| SKIP-OK | 50 |131| MISS | 0 |132| SKIP-BAD | 0 |133| REGRESSION | -50 |134135### Category Weights136137| Category | Weight |138|----------|--------|139| Must Fix | 3x |140| Suggestions | 1x |141| Nitpicks | 0.5x |142143### Score Calculation144145```146weighted_score = sum(finding_score * category_weight) for each finding147max_possible = sum(100 * category_weight) for each finding148raw_percentage = (weighted_score / max_possible) * 100149```150151### Modifiers (applied to final percentage)152153| Modifier | Points | Condition |154|----------|--------|-----------|155| Proactive fixes | +5 (cap +10) | Each fix beyond what was flagged |156| Regression | -10 | Each REGRESSION verdict (stacks) |157| Dishonest claim | -5 | Each dishonest claim (stacks) |158159### Letter Grade Scale160161| Grade | Range |162|-------|-------|163| A+ | 97-100 |164| A | 93-96 |165| A- | 90-92 |166| B+ | 87-89 |167| B | 83-86 |168| B- | 80-82 |169| C+ | 77-79 |170| C | 73-76 |171| C- | 70-72 |172| D | 60-69 |173| F | Below 60 |174175Final score clamped to 0-100 after modifiers.176177---178179## Phase 4 — Report Card180181Write to `${REVIEW_DIR}/grade-report.md` and present in conversation. Do NOT post to PR.182183### Output Format184185```markdown186## Grade Report — PR #${PR_NUMBER}: ${PR_TITLE}187188**Overall: ${LETTER_GRADE} (${SCORE}/100)**189190| Category | Addressed | Total | Score |191|--------------|-----------|-------|-------|192| Must Fix | X/Y | Y | Z% |193| Suggestions | X/Y | Y | Z% |194| Nitpicks | X/Y | Y | Z% |195196### Must Fix1971. **${VERDICT}** · ${QUALITY} — `${location}` — ${title}198 _What changed:_ ${factual description}199 _Feedback:_ ${opinionated quality assessment}200201### Suggestions202...203204### Nitpicks205...206207### Flags208- **Dishonest claim**: Finding #${N} claimed fixed but diff shows ${what}.209- **Proactive fix**: ${description}.210- **Undocumented skip**: Finding #${N} not addressed and not mentioned.211212(Omit Flags section if none.)213214### Summary215${2-3 sentence assessment: quality, strengths, gaps, recommendation}216```217218### Formatting Rules219220- Number findings matching compiled report numbering.221- Use exact verdict labels: PASS, PARTIAL, MISS, REGRESSION, SKIP-OK, SKIP-BAD.222- "Addressed" counts PASS + PARTIAL + SKIP-OK.223- Every PASS/PARTIAL has two lines:224 - `_What changed:_` — factual, 1 sentence.225 - `_Feedback:_` — **opinionated**, 1-2 sentences. Judgment, not description.226- Quality tags appear after verdict for PASS/PARTIAL only.227- `_Feedback:_` must express judgment. Bad: "Used a typed setter map." Good: "Clean approach — eliminates unsafe cast without over-engineering."228229---230231## Edge Cases232233| Situation | Behavior |234|-----------|----------|235| No review directory | STOP: "No review found for PR #X" |236| Review not compiled | STOP: "Review not compiled yet" |237| No fix commits | Grade from fixes comment skips; all findings MISS unless justified |238| No fixes comment | Warn, grade from diff only, skip dishonesty checks |239| PR already merged | Warn, use merge commit range |240| Squash-merged PR | The HEAD_SHA...HEAD range may collapse to nothing. Check the PR merge commit instead: `gh pr view --json mergeCommit` |241| Empty compiled report | STOP: "No findings to grade" |242243---244245## Hard Rules246247- **Read-only.** Do not modify files, post comments, or push code.248- **Grade every finding.** No finding from compiled report should be skipped.249- **Be honest.** Grade what the diff shows, not what the fixes comment claims.250- **Show your work.** Each verdict must reference specific code changes (or lack thereof).