skills/pr-review/SKILL.md
Automated PR review producing a `## Automated review` comment, applying risk label and `reviewed` on completion. Use when reviewing a pull request — fetches PR metadata and linked issue ACs, traces data flow, verifies AC coverage, classifies findings by exposure, and posts findings via gh pr comment.
npx skillsauth add paulund/ai pr-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Single reasoning pass that produces (a) a ## Automated review comment with findings and AC coverage, (b) a risk-low/risk-medium/risk-high label that decides whether humans must review, and (c) a reviewed label on completion.
The skill accepts an optional variables block. CI mode appends one after the slash command; human mode omits it. The skill must handle both.
--- VARIABLES ---
PR_NUMBER=<pr number>
PR_CONTEXT_FILE=<path to pr-context.json>
LINKED_ISSUES_FILE=<path to linked-issues.json>
When the block is present, read the values directly. The workflow has already fetched the JSON files — don't re-fetch.
When the variables block is absent (human invocation):
gh pr view --json number,headRefName,baseRefName against the current branch. If a PR is open, use its number.gh pr view $PR_NUMBER --json title,body,closingIssuesReferences.gh issue view <N>.PR_CONTEXT_FILE and LINKED_ISSUES_FILE — fetch everything via gh directly.A --- VARIABLES --- marker line in the prompt indicates CI mode. Absence indicates human mode.
PR_CONTEXT_FILE in CI; from gh pr view in human mode).LINKED_ISSUES_FILE in CI; from gh issue view in human mode).gh pr diff $PR_NUMBER.Five steps. Run them in order. Skip none.
Read enough surrounding code to answer: what system does this diff touch and what role does it play? Read the file the diff modifies, plus its public callers, plus the test file. Do not skim — the diff hunks alone don't reveal intent.
For each file in the diff, identify the trace: entry → action → service → sink. Read the full path, not just the diff hunk. A missing try/catch that the caller already provides is not a finding. A console.log of an unredacted value is.
For each candidate finding, write the strongest case against the change. If the strongest case is weak, drop it. Findings survive only when the strongest version is concrete.
Read each linked issue's acceptance criteria. For each AC, locate the diff line(s) that implement it; identify the test that proves it works through a public interface. Flag "AC not addressed" or "AC test gap" as findings. See references/intent-check.md.
Replace the rigid 4-level table with two axes. See references/severity-classification.md.
/api/v1/posts is high exposure.A finding is one of: critical (reachable + severe), high (reachable + significant), medium (reachable + moderate, or unreachable + significant), low (anything else). Drop findings that are neither reachable nor significant.
Every reported finding must include: file:line + trace (entry → sink) + concrete failure or exploit path. Findings that don't meet this bar get dropped. No exceptions.
This is the discipline that kills checklist-mimicry. If you can't write the trace, you don't have a finding.
Compute the PR's risk label. Three dimensions, summed into a single label.
| Dimension | What to score | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | Blast radius | Count of production modules touched. Sensitive systems (auth, payments, scheduling, data deletion, encryption) are floor High. | | Reversibility | Pure additive → -1 level. One-way (data backfill, schema change, drop column) → +1 level. | | Invariant breakage | Signature changes, schema changes, env changes, error-semantic flips, authz check changes. Each is +1 level. |
Take the highest floor; apply reversibility and invariant adjustments. Output the level with a one-sentence justification. See references/categorization.md.
Labels and merge semantics:
risk-low — agent-only review. Comment + label. No human review required.risk-medium — comment + label. Human reviews the agent's flagged concerns, then merges.risk-high — comment + label. Full human review of the diff is mandatory.Always this exact structure — ## Automated review, ### Findings, ### Acceptance criteria coverage, ### Security, ### Risk. No findings → fill with None. / All criteria addressed. / No security-relevant changes. See references/comment-template.md.
Fix every finding by editing code in this run. Commit grouped by concern:
git add <files>
git commit -m "Address review: <one-line summary>"
# For security: git commit -m "Security review: <one-line summary>"
# Push any committed fixes (independent step — failures here must not block the comment).
if git log --oneline origin/HEAD..HEAD 2>/dev/null | grep -q .; then
git push origin HEAD || true
fi
# Post the comment (this is the contract — must run regardless of push outcome).
gh pr comment <N> --body "$(cat <<'EOF'
## Automated review
### Findings
- [severity | file:line | trace → impact] — fixed in commit <sha>
- ...
### Acceptance criteria coverage
- [criterion verbatim] — covered by `<test-file>:<test-name>`
- [criterion verbatim] — **NOT COVERED** — see #N
### Security
- [severity | file:line | trace → impact] — fixed in commit <sha>
- (No security-relevant changes.)
### Risk
<low|medium|high> — <one-sentence justification>
EOF
)"
# Apply labels (each independent — never let one failure block the next).
gh pr edit <N> --remove-label reviewing --add-label reviewed || true
gh pr edit <N> --add-label "risk-<low|medium|high>" || true
| File | When to load |
| --------------------------------------- | ------------------------------------------------ |
| references/categorization.md | When deciding the risk label |
| references/severity-classification.md | When classifying a finding's severity |
| references/intent-check.md | When verifying AC coverage from the linked issue |
| references/security-data-flow.md | When security findings are possible |
| references/comment-template.md | When composing the ## Automated review comment |
PR_CONTEXT_FILE if present (CI mode) or via gh pr view (human mode) — these are the source of truth.LINKED_ISSUES_FILE if present (CI mode) or via gh issue view <N> (human mode) for each Closes #N.risk-<level> label and transition reviewing → reviewed after the comment posts.references/comment-template.md.references/security-data-flow.md handles these with proper exploit-path analysis).development
Use when implementing any logic, fixing any bug, or changing any behaviour. Use when you need to prove code works, when a bug report arrives, or when modifying existing functionality. Do NOT use for config changes, data migrations, or dependency updates.
development
Use when starting a new feature, when requirements are unclear, when asked to write code without a clear spec, or before any non-trivial implementation. Do NOT use for trivial bug fixes or one-line changes.
development
Use when you want authoritative, source-cited code free from outdated patterns. Use when building with any framework or library where correctness matters. Detects the stack from dependency files, fetches official documentation, implements following documented patterns, and cites sources for every framework-specific decision.
development
Use when preparing to ship a feature, release, or deployment. Use before merging to main, creating a release, or deploying to production. Do NOT use for CI-only changes or internal refactors that don't reach production.