From sdlc
Use this skill when the user wants a code review — before opening a PR, merging a branch, or shipping to production. Triggers on requests like "review my code", "is this ready to merge", "check my work before I push", "run the quality gates", or "give me a second pair of eyes on this branch". Runs automated quality gate scripts plus manual review for bugs, security, performance, test quality, and plan compliance. Walks through findings interactively and commits fixes. Do NOT use for building features, fixing bugs, or performance auditing outside a review context.
npx claudepluginhub jerrod/agent-plugins --plugin sdlcThis skill is limited to using the following tools:
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Log skill invocation:
Use $PLUGIN_DIR (already detected in Step 1 via find . -name "run-gates.sh"):
CONTEXT="$ARGUMENTS" bash "$PLUGIN_DIR/../scripts/audit-trail.sh" log review sdlc:review started --context="$CONTEXT"bash "$PLUGIN_DIR/../scripts/audit-trail.sh" log review sdlc:review completed --context="<summary>"Correctness is the only measure that matters. Do not rush the review to unblock shipping. Do not downgrade findings to avoid slowing things down. A correct review that takes an hour is infinitely more valuable than a quick review that misses a bug.
Every quality check that CAN be automated IS automated via gate scripts. Manual review focuses on what scripts cannot catch: design, intent, plan compliance, and subtle bugs.
If you noticed it, it is a finding. Fix it.
The reviewer's job is to find problems. Once you identify something — a code smell, an inconsistency, a potential bug, unclear naming — you do NOT get to talk yourself out of it. The following phrases are BANNED during review:
ABSOLUTE BAN — "Pre-existing" framing (NON-NEGOTIABLE):
There is no such thing as a "pre-existing issue." You wrote every line of this codebase (this session or a previous one). When a gate flags a violation, the ONLY correct response is to fix it. Not to classify it. Not to explain when it was introduced. Not to create a separate section for things "on main" or "not introduced by this PR."
If you catch yourself writing "Pre-existing Issues" or "not introduced by this PR" — STOP. Delete it. Fix the violations instead. A gate failure is a gate failure. It does not have an origin story. It has a fix.
The test: After writing a finding, did you conclude with "fix it" or "no issue"? If "no issue," you rationalized. Go back and fix it.
Never self-defer findings. The reviewer NEVER decides to defer on its own. Present every finding with the expectation of fixing it now. Only the user can decide to defer — if they explicitly say so, record it in the ledger and move on.
Never leave a dirty tree. Every fix you apply — commit it immediately. Do not accumulate fixes. Do not ask the user what to do with uncommitted code. Do not wait until the walkthrough is complete. Fix → commit → next finding.
fix: <description> — bug fix or review finding fix
refactor: <description> — restructuring without behavior change
test: <description> — adding or updating tests
After each finding is fixed: Stage the specific files and commit:
git add <changed-files>
git commit -m "$(cat <<'EOF'
fix: <what was fixed and why>
Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)"
After a batch of related fixes in one round: If multiple findings touch the same file and fixing them sequentially would create noise commits, you MAY batch them into one commit per round — but NEVER leave the round with uncommitted changes.
During long reviews, Claude tends to:
head/tail and miss critical dataPrevention:
head -N, no tail -N, no piping through truncation. Read ALL PR comments, ALL CI logs, ALL gate output. Use --jq filters to reduce data server-side, not client-side truncation. Missing one finding because you truncated the output is a critical failure.DEFAULT_BRANCH=$(git remote show origin | grep 'HEAD branch' | awk '{print $NF}')
BASE="${ARGUMENTS:-$DEFAULT_BRANCH}"
CURRENT=$(git branch --show-current)
If on the default branch, STOP — ask which branch to review.
git fetch origin "$BASE" --quiet
git diff "origin/$BASE"...HEAD --stat
git diff "origin/$BASE"...HEAD --name-only
Read every changed file in full. Do not review files you have not read.
REPO_NAME=$(_u=$(git remote get-url origin 2>/dev/null) || _u=""; if [ -n "$_u" ]; then basename "${_u%.git}"; else basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)"; fi)
LEDGER_DIR="$HOME/.claude/reviews/$REPO_NAME"
LEDGER="$LEDGER_DIR/$CURRENT.md"
If $LEDGER exists, read it. Do NOT re-report findings already in the ledger.
Run ALL quality gates and produce proof:
PLUGIN_DIR=$(find . -name "run-gates.sh" -path "*/sdlc/*" -exec dirname {} \; 2>/dev/null | head -1)
if [ -z "$PLUGIN_DIR" ]; then
PLUGIN_DIR=$(find "$HOME/.claude" -name "run-gates.sh" -path "*/sdlc/*" -exec dirname {} \; 2>/dev/null | sort -V | tail -1)
fi
bash "$PLUGIN_DIR/run-gates.sh" review
Read every proof file and incorporate results into the review. The gate scripts catch:
filesize.json)complexity.json)dead-code.json)lint.json)Do NOT re-check what the scripts already checked. Trust the proof files. Focus manual review on what scripts cannot detect.
Save a checkpoint:
bash "$PLUGIN_DIR/checkpoint.sh" save review-gates "Gate scripts completed"
Dispatch 4 specialized review agents simultaneously. Each reads the changed files and produces findings as a JSON array.
CHANGED_FILES=$(git diff "origin/$BASE"...HEAD --name-only)
Launch all agents in a single response using the Agent tool. Each call MUST include both description and prompt parameters.
Check for frontend files first:
FRONTEND_FILES=$(git diff "origin/$BASE"...HEAD --name-only | grep -E '\.(tsx|jsx|css|scss|html)$')
Architect file prioritization (for large PRs):
Before dispatching the architect agent, classify changed files by architectural significance:
| Priority | Category | Detection |
|---|---|---|
| 1 | Interfaces/exports | **/types.*, **/interfaces.*, **/index.*; files with changed export lines |
| 2 | New files | Status A in git diff --name-status |
| 3 | Dependencies | package.json, pyproject.toml, go.mod, Cargo.toml, Gemfile, requirements*.txt |
| 4 | Entrypoints | **/routes.*, **/router.*, **/main.*, **/app.*, **/server.* |
| 5 | Config | **/config.*, **/.env*, **/settings.* |
| 6 | Implementation | All other source files |
| 7 | Skip | **/*.test.*, **/*.spec.*, **/*.md, **/generated/**, **/__snapshots__/** |
Within each tier, sort by diff size (larger first). Send tiers 1-6 to architect, capped at ~12 files. Always skip tier 7 for architect.
If total changed files ≤ 12, send all non-tier-7 files to architect (no prioritization needed).
Sharding for large PRs:
When changed files exceed an agent's per-shard capacity, split into chunks and dispatch multiple agents of the same type in parallel.
| Agent | Max Files/Shard | Shard Threshold |
|---|---|---|
| Architect | N/A (not sharded) | N/A — uses file prioritization |
| Style | 8 | >8 changed files |
| Correctness | 9 | >9 changed files |
| Security | 9 | >9 changed files |
Shard dispatch: Use the same subagent_type with different prompt contents listing different file subsets. All shards run in parallel in a single Agent tool response.
Conservative sizing: Err on smaller shards. 3 shards of 6 is better than 2 shards of 9.
Dispatch all 4 core review agents in a single response. For agents that require sharding, dispatch multiple instances with different file lists. For architect, use the prioritized file list. All 4 core agents (architect, security, correctness, style) must output a JSON object (not a bare array) with status, reviewed, remaining, findings, and needs_continuation fields.
# Architect — prioritized, not sharded
Agent(
subagent_type="sdlc:review-architect",
description="Architecture review",
prompt="Review these files for architecture concerns: <PRIORITIZED_FILES>. Base branch: origin/$BASE. Output a JSON object with status, reviewed, remaining, findings, needs_continuation fields."
)
# Security — shard if >9 files
Agent(
subagent_type="sdlc:review-security",
description="Security review [shard N]",
prompt="Review these files for security vulnerabilities: <SHARD_FILES>. Base branch: origin/$BASE. Output a JSON object with status, reviewed, remaining, findings, needs_continuation fields."
)
# Correctness — shard if >9 files
Agent(
subagent_type="sdlc:review-correctness",
description="Correctness review [shard N]",
prompt="Review these files for correctness and logic bugs: <SHARD_FILES>. Base branch: origin/$BASE. Output a JSON object with status, reviewed, remaining, findings, needs_continuation fields."
)
# Style — shard if >8 files
Agent(
subagent_type="sdlc:review-style",
description="Style review [shard N]",
prompt="Review these files for style and quality: <SHARD_FILES>. Base branch: origin/$BASE. Output a JSON object with status, reviewed, remaining, findings, needs_continuation fields."
)
If $FRONTEND_FILES is non-empty, also dispatch the design-reviewer in the same batch:
# design-reviewer uses legacy bare-array format — separate proof path, not subject to coverage manifest schema
Agent(
subagent_type="sdlc:design-reviewer",
description="Design review",
prompt="Review these changed frontend files for design quality: <FRONTEND_FILES>.
Design context: .claude/design-context.md (if present).
Check: design token compliance, WCAG 2.1 AA accessibility, responsive patterns.
Read skills/design/design-constraints.md and skills/design/a11y-rules.md for rules.
Output findings as JSON array and write proof to .quality/proof/design-review.json."
)
If .claude/design-context.md does not exist, the design-reviewer skips token compliance checks but still checks accessibility and responsive patterns. Note this in the review summary:
Note: No .claude/design-context.md found. Token compliance not checked.
Run `sdlc:design init` to establish design tokens for full design review coverage.
Replace <CHANGED_FILES> and <FRONTEND_FILES> with the actual file lists from the bash commands above.
Design-reviewer is handled separately. If dispatched, collect its bare-array output directly into the findings list. Do NOT feed it through the object-format parsing or coverage/continuation logic below — it uses a separate proof path (.quality/proof/design-review.json) and is excluded from coverage tracking.
For the 4 core agents (architect, security, correctness, style) and their shards:
{...} object in the response text. Read .findings for the findings array, .reviewed for files covered, .remaining for coverage gaps..findings arrays and .reviewed arrays. If any shard has .remaining entries, collect them for the continuation loop..reviewed lists vs the full changed file list dispatched to that agent type.Fallback parsing: If a core agent's output is not valid JSON or is missing the status/reviewed fields, treat the entire dispatch as truncated — set remaining to the full file list for that agent/shard and enter the continuation loop.
After aggregation, check each agent type for incomplete coverage:
remaining is non-empty (from any shard):
a. Re-dispatch the same subagent_type with remaining files as the file list
b. Prompt includes: "Continue reviewing. These files were not covered in a prior pass. Output a JSON object with status, reviewed, remaining, findings, needs_continuation fields."
c. Merge returned findings with prior findings for that agent type
d. Update coverage: add newly .reviewed files, recompute .remainingUser visibility: During continuation, report progress:
↻ Security continuing... (reviewed 6/9, fetching remaining 3)
When done:
✓ Security complete (9/9 files, 2 passes)
After aggregation and continuation, write .quality/proof/review-coverage.json:
{
"sha": "<current HEAD>",
"timestamp": "<ISO 8601>",
"status": "complete",
"agents": {
"architect": {"dispatched": [], "reviewed": [], "remaining": [], "shards": 1, "passes": 1},
"security": {"dispatched": [], "reviewed": [], "remaining": [], "shards": 1, "passes": 1},
"correctness": {"dispatched": [], "reviewed": [], "remaining": [], "shards": 1, "passes": 1},
"style": {"dispatched": [], "reviewed": [], "remaining": [], "shards": 1, "passes": 1}
}
}
Top-level status is "complete" when all agents have empty remaining, "incomplete" otherwise. This file is consumed by the ship skill's review completeness check.
Assume the work does NOT match the plan until proven otherwise.
.claude/plans/, PR description, branch name, linked issue)Summarize:
Plan: <name>
Requirements: N total
- Fully implemented + tested: X
- Implemented but untested: Y
- Partially implemented: Z
- Missing: W
- Unplanned changes: V
Run the test, coverage, and test quality gates:
bash "$PLUGIN_DIR/gate-tests.sh"
bash "$PLUGIN_DIR/gate-coverage.sh"
bash "$PLUGIN_DIR/gate-test-quality.sh"
Read the proof files:
tests.json — are there missing test files? Did tests pass?coverage.json — is any changed file below 95%?test-quality.json — are there disguised mocks in test files?The gate script catches common patterns, but manual review catches what automation misses. For every test file in the diff, verify:
The litmus test: "If I delete the source file, does this test still pass?" If yes, the test is mocking away the module under test. CRITICAL.
Banned patterns — any spyOn() with a .mock*() chain on internal code:
vi.spyOn(module, 'fn').mockImplementation(...) — mock wearing a spy costumevi.spyOn(module, 'fn').mockReturnValue(...) — same thingvi.spyOn(module, 'fn').mockResolvedValue(...) — same thingjest.mock('./internal-module') — replaces entire module with fake@patch('mymodule.fn') without wraps= — Python equivalentThe mechanical check: After spyOn(), is there a .mock*() chained on it? If yes, it's a mock, not a spy. Real spies have NO .mock*() chain.
Acceptable boundary mocks (NOT violations):
fetch, axios, API adapters)Date.now, setTimeout)spyOn() WITHOUT .mock*() — this is a real spy, it observes real codeBefore the interactive walkthrough, present the full picture:
Show per-agent coverage from .quality/proof/review-coverage.json:
Review Coverage
Architect ✓ 12/12 files
Security ✓ 18/18 files (2 shards)
Correctness ✓ 18/18 files (2 shards)
Style ✓ 16/16 files (2 shards)
If any agent has remaining files after all continuation passes:
Review Coverage
Architect ✓ 12/12 files
Security ✓ 18/18 files (2 shards)
Correctness ✓ 18/18 files (2 shards)
Style ⚠ 14/16 files — 2 not reviewed: utils/helpers.ts, lib/format.ts
Incomplete coverage blocks the "review complete" signal. The review cannot reach Step 9 (zero open issues) while any agent has unreviewed files, unless the user explicitly dismisses each unreviewed file with a reason.
When coverage is incomplete after all continuation passes, prompt the user for each unreviewed file:
Style did not review: utils/generated-types.ts
Dismiss? Enter reason (or 'no' to block review): _
For each dismissed file, collect the reason and write .quality/proof/review-dismissals.json:
{
"sha": "<current HEAD>",
"timestamp": "<ISO 8601>",
"dismissals": [
{
"agent": "style",
"file": "utils/generated-types.ts",
"reason": "generated code, not authored",
"dismissed_by": "user"
}
]
}
If the user declines to dismiss any file, the review remains incomplete. The user can re-run /sdlc:review or manually review the skipped files.
Dismissals are SHA-pinned — they expire if HEAD changes (new commits invalidate them).
## Code Review: <branch-name>
### Automated Gates
<paste relevant sections from proof files>
### Manual Findings
Found N issues: X critical, Y high, Z medium, W low
Now walking through each finding...
Walk through each finding ONE AT A TIME, ordered by severity (critical first).
For each finding:
Ask:
git add <changed-files>
git commit -m "$(cat <<'EOF'
fix: <description of what was fixed>
Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)"
Do NOT accumulate fixes. Each fix gets its own commit (or batch related fixes touching the same file into one commit). Never end a walkthrough round with uncommitted changes.
The review is not done when findings are fixed. The review is done when a full re-review finds ZERO issues.
Fixes introduce new code. New code can introduce new bugs, new complexity, new dead code, new violations. A single-pass review that stops after fixes is incomplete by definition.
bash "$PLUGIN_DIR/run-gates.sh" review
If any gate fails, fix and re-run. Do not proceed with gate failures.
This is not a quick "check if fixes look right." This is a full re-review:
Anti-rot note: Do NOT skip this because "I just reviewed it." You reviewed the OLD code. The fixes changed the code. Review the NEW code. If you catch yourself thinking "this is redundant" — that is context rot. Run the review.
Maintain a loop counter to give the user visibility:
## Review Round <N>
Previous rounds: <N-1>
Findings this round: <count>
Cumulative fixes applied: <total>
There is no maximum number of rounds. The review runs until clean. If round 5 still finds issues, run round 6. Correctness is the only measure that matters.
However, if a finding keeps reappearing across rounds (fix introduces regression that reintroduces it), flag it explicitly:
⚠ RECURRING FINDING: <description>
This was found in round <X>, fixed, and reappeared in round <Y>.
The fix approach needs to change — the current fix is introducing a regression cycle.
Stop and discuss the approach with the user rather than looping indefinitely on the same issue.
bash "$PLUGIN_DIR/checkpoint.sh" save "review-round-<N>" "Round <N> complete — <findings_count> findings"
This step is ONLY reached when a full review round (Steps 2–5) produces zero findings.
bash "$PLUGIN_DIR/run-gates.sh" review
bash "$PLUGIN_DIR/collect-proof.sh"
bash "$PLUGIN_DIR/checkpoint.sh" save review-complete "Review complete — zero open issues after <N> rounds"
All fixes should already be committed from the walkthrough. If any uncommitted changes remain (they shouldn't), commit them now:
git status --porcelain | grep -q . && git add -u && git commit -m "$(cat <<'EOF'
fix: address remaining review findings
Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)"
Write ALL findings from ALL rounds to the ledger at $LEDGER.
mkdir -p "$LEDGER_DIR"
Format: Fixed items (with round number and commit SHA), Previously Reported items. Subsequent review runs skip findings already in the ledger.
## Review Complete
Rounds: <N>
Total findings discovered: <total across all rounds>
Total findings fixed: <fixed count>
Deferred by user: <deferred count>
Open: 0
Gate status: ALL PASS
The review is complete when and only when this summary shows Open: 0.
/sdlc:shipZero open issues and all gates pass. Invoke /sdlc:ship to rebase on the default branch, push the feature branch, open (or update) the PR with embedded proof, watch CI, and ask before merge.
The workflow is build → review → ship. Review hands off to ship only after zero open findings — do not ship earlier.