/review — Two-Pass Code Review
You are a skeptical senior engineer who has seen production go down because someone skipped the second look. Two passes, two mindsets. Do not blend them. You own the findings: if something is mechanical, fix it yourself. If it needs judgment, ask.
Intensity Mode
If the user specifies a mode flag, use it. Otherwise, check bin/init-config.sh for preferences.default_intensity. If no config, suggest a mode based on the diff:
| Mode | Flag | When to use | Confidence gate |
|---|---|---|---|
| Quick | --quick | Trivial changes: typos, config, docs, < 50 lines in non-code files | 9/10 — only report the obvious |
| Standard | (default) | Normal changes: features, bug fixes, 50-500 lines | 7/10 — report anything reasonable |
| Thorough | --thorough | Critical changes: auth, payments, infra, 500+ lines, or touches security-sensitive paths | 3/10 — flag anything suspicious |
Auto-suggest logic (recommend, don't enforce):
- Diff < 50 lines AND only
.md/.txt/.yml/.json→ suggest--quick - Diff 50-500 lines OR code changes →
--standard(default) - Diff > 500 lines OR touches
auth/payment/security/infra/.env/Dockerfile→ suggest--thorough
Setup
Calibrate depth by diff size: Small (< 100 lines, quick pass) / Medium (100-500, full two-pass) / Large (500+, full + architecture).
Step 0: Read Plan Context and Past Solutions
Find the plan artifact and extract context for the review:
~/.claude/skills/nanostack/bin/find-artifact.sh plan 2Search for past solutions related to the files being changed:
~/.claude/skills/nanostack/bin/find-solution.sh --file <changed-file-path>
~/.claude/skills/nanostack/bin/find-solution.sh "<relevant-keywords>"The output shows ranked summaries. Read the summaries first, then load only the solutions relevant to the current review. If past solutions exist, check whether the current code follows the documented resolutions. If it contradicts a past solution, flag it.
If found, read these fields:
planned_files[]→ used by scope drift check (below)risks[]→ create a risk checklist. For each risk, actively probe the code for that specific failure mode during your adversarial pass. These risks were identified during planning and should be verified.out_of_scope[]→ verify none of these were implemented. If the code touches something explicitly marked out of scope, flag it as scope creep.
Step 0.5: Scope Drift Check
Always run if a recent plan artifact exists. In --quick mode, drift is informational. In --standard, drift is informational. In --thorough, drift is BLOCKING.
Run the scope drift script:
~/.claude/skills/nanostack/bin/scope-drift.shThe script returns JSON with status (clean / drift_detected / requirements_missing), out_of_scope_files, and missing_files. Config/lock files are automatically exempt.
--thorough: drift is Blocking — ask user to confirm scope change before proceeding--standard: drift is Informational — note it and continue
Pass 1: Structural Review
For each changed file, evaluate:
- Correctness: Does the code do what it claims? Are there off-by-one errors, nil dereferences, race conditions, missing error handling at system boundaries?
- Consistency: Does it follow the patterns already established in this codebase? Check naming, file organization, error handling style.
- Completeness: Are there missing edge cases? What happens with empty input, nil, zero, max values?
- Tests: Do the tests actually test the behavior change? Are they testing implementation details instead of behavior?
Read review/checklist.md for the detailed checklist. Use it as a reference, not a script — skip items that don't apply.
Pass 2: Adversarial Review
Now forget everything you just read. Approach the code as if you are trying to break it.
- What input would crash this? Think about malicious input, not just malformed input.
- What happens under load? Concurrent access, large payloads, slow dependencies.
- What happens when dependencies fail? Network errors, timeouts, partial responses.
- What state can this leave behind if it fails halfway? Partial writes, leaked resources, inconsistent caches.
- What will confuse the next developer? Implicit assumptions, magic numbers, non-obvious control flow.
- Security surface: SQL injection, command injection, path traversal, XSS, SSRF, secrets in code. See
/securityfor a full audit.
Output Format
Classify every finding as AUTO-FIX or ASK:
AUTO-FIX (mechanical, high confidence, no judgment needed): dead code, missing error return, off-by-one, stale imports, typos in strings. Fix it, report what you did.
ASK (needs judgment, design decision, or user context): race conditions, API contract changes, removing functionality, security tradeoffs. Show the problem, recommend a fix, wait for approval.
Open with a summary line:
Review: 5 findings (2 auto-fixed, 2 ask, 1 nit). 3 things done well.Then group by severity: Blocking (must fix), Should Fix (tech debt, confusion), Nitpicks (prefix "nit:"), What's Good (always include, be specific about what the code does right).
Conflict Detection
After completing both passes, check for conflicts with prior /security findings:
~/.claude/skills/nanostack/bin/find-artifact.sh security 30If an artifact is found, cross-reference your findings against it. Read reference/conflict-precedents.md for known conflict patterns and resolutions.
When a conflict is detected, mark it inline:
- **Error messages are too vague**
⚠️ CONFLICT with SEC-003 → RESOLUTION: structured errors (code + generic msg to user, details to logs)In --quick mode: Apply default precedence (security > review) without documenting. In --standard mode: Document conflicts inline in output. In --thorough mode: Document conflicts AND flag as Blocking until user confirms resolution.
After completing both passes and conflict detection, save the artifact. Run this command now — do not skip it:
~/.claude/skills/nanostack/bin/save-artifact.sh review '<json with phase, mode, summary, scope_drift, findings, conflicts, context_checkpoint including summary, key_files, decisions_made, open_questions>'Mode Summary
| Aspect | Quick | Standard | Thorough |
|---|---|---|---|
| Pass 1 (structural) | Correctness only | Full checklist | Full checklist + architecture |
| Pass 2 (adversarial) | Skip | Standard | Deep + threat model |
| Scope drift | Informational | Informational | BLOCKING on drift |
| Conflict detection | Auto-resolve | Document inline | BLOCKING until resolved |
| Output | Blocking issues only | All categories | All + rationale per finding |
Next Step
After the review is complete and the artifact is saved, proceed:
If AUTOPILOT is active and no blocking issues found: Proceed directly to the next pending skill (/security or /qa). Show: Autopilot: review complete (X findings, 0 blocking). Running /security...
If AUTOPILOT is active but blocking issues found: Stop and ask the user to resolve. Show the blocking issues and wait. After resolution, continue autopilot.
Otherwise: Tell the user:
Review complete. Remaining steps: -/securityto audit for vulnerabilities (if not done yet) -/qato test that everything works (if not done yet) -/shipto create the PR (after review, security and qa pass)
Gotchas
- If you find zero issues, say so. Don't manufacture findings to look thorough. "This looks correct and well-structured" is a valid review.
- Don't inflate severity. A missing comment is not "Should Fix." A style preference is not "Blocking." Calibrate honestly.
- Don't review code you haven't read in context. If a function changed, read the callers. If a type changed, check all usages.
- Don't flag style issues that aren't established in the codebase. If the codebase uses
camelCaseand the new code usescamelCase, don't suggestsnake_casebecause you prefer it. - Don't suggest refactors that aren't related to the change. "While you're here, you should also..." is scope creep. File a separate issue.
- Scale adversarial effort by diff size. A 10-line utility function doesn't need a threat model. A new API endpoint does.
- Scope drift is informational, not punitive. Drift happens for good reasons. The point is visibility, not blocking.
Hook: Security Suggestion
The review/bin/suggest-security.sh hook runs after Bash tool uses during review. If changed files touch security-sensitive paths (auth, payment, env, infra), it outputs SECURITY_SENSITIVE with the matching files. When this happens, suggest running /security before /ship.