with one click
code-review
// Two-stage code review: spec compliance then code quality. Trigger: When reviewing code for correctness and quality.
// Two-stage code review: spec compliance then code quality. Trigger: When reviewing code for correctness and quality.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | code-review |
| description | Two-stage code review: spec compliance then code quality. Trigger: When reviewing code for correctness and quality. |
| license | Apache 2.0 |
| metadata | {"version":"1.1","type":"behavioral","skills":["critical-partner"]} |
Two-stage code review: verify spec compliance FIRST, then assess code quality. Never reversed.
Don't use for:
Stage 1: Spec Compliance (MUST come first)
Stage 2: Code Quality (ONLY after Stage 1 passes)
# ā
CORRECT: Two-stage order
## Stage 1: Spec Compliance ā
- ā
POST /users creates user with email/password
- ā
Returns 201 status with user object
- ā
Email validation enforced
- ā
Password hashed before storage
**Result**: Spec compliance PASSED
## Stage 2: Code Quality
- ā ļø Password hashing uses deprecated bcrypt.hashSync (use async bcrypt.hash)
- ā ļø No input sanitization for XSS prevention
- ā
Error handling present
- ā
TypeScript strict mode enabled
# ā WRONG: Quality feedback before spec check
"The code uses var instead of let" ā irrelevant if spec not met
Why this order?
Review each file separately with clear structure.
## File: src/services/UserService.ts
### Spec Compliance
- ā
Implements registerUser as specified
- ā
Returns Promise<User>
- ā Missing validateEmail method (required in spec)
- ā Password strength check missing (spec requires 8+ chars)
**Result**: FAIL - Fix spec issues before quality review
---
## File: src/repositories/UserRepository.ts
### Spec Compliance
- ā
All CRUD methods present
- ā
Returns correct types
### Code Quality (reviewed AFTER spec passed)
- Line 23: Use const instead of let (value never reassigned)
- Line 45-50: Extract validation logic to separate function
- Line 67: Add error handling for unique constraint violation
Benefits:
Provide line numbers and specific examples.
# ā WRONG: Vague feedback
"Error handling could be better"
# ā
CORRECT: Specific with evidence
**Line 34-38**: Error swallowed without logging or user feedback
```typescript
try {
await updateUser(id, data);
} catch (error) {
// Silent failure - user doesn't know what happened
}
Fix: Log error and provide user-friendly message
try {
await updateUser(id, data);
return { success: true };
} catch (error) {
console.error('Failed to update user:', error);
return {
success: false,
error: 'Unable to update user. Please try again.',
};
}
**Evidence includes:**
- Line numbers (file.ts:34-38)
- Code snippets (what's wrong)
- Suggested fix (how to improve)
- Rationale (why it matters)
### ā
REQUIRED: Stage 2 Quality Dimensions
Check these four dimensions when Stage 1 passes. Always cite file and line number.
**Security** (flag immediately ā does not wait for Stage 2 order):
- Injections: SQL, NoSQL, command injection (parameterized queries? user input in queries?)
- XSS: `innerHTML`/`dangerouslySetInnerHTML` with user input not sanitized
- Auth: missing authentication checks, broken authorization, exposed credentials/secrets in code
- CSRF: missing tokens on state-changing endpoints
- Path traversal / SSRF: user-controlled file paths or URLs passed to `fetch`/`fs`
**Performance**:
- N+1 queries: loops that trigger individual DB calls
- Algorithmic complexity: O(n²) or worse in hot paths (nested loops over unbounded data)
- Resource leaks: unclosed files, connections, streams, event listeners
- Unbounded operations: queries/loops without pagination or size limits
**Correctness** (beyond spec ā catches runtime failures):
- Null/undefined/empty input: are edge cases handled before use?
- Off-by-one: array bounds, pagination offsets, inclusive/exclusive ranges
- Race conditions: shared mutable state, concurrent writes without locking
- Type coercion: implicit conversions that may produce `NaN`, `undefined`, or `"0"`
**Maintainability**:
- Single responsibility: functions/classes doing more than one thing
- Test quality: tests are deterministic, independent, named descriptively
- Dead code / commented-out code: remove, don't archive in code
- Magic numbers/strings: extract to named constants
---
### ā NEVER: Review Quality Before Spec
If spec is not met, STOP. Do not proceed to quality review.
```markdown
# ā WRONG: Reviewing quality when spec fails
## Spec Compliance
- ā Email validation missing (required)
- ā Password not hashed (critical security issue)
- ā Missing error handling for duplicate emails
## Code Quality ā SHOULD NOT EXIST
- Use const instead of let
- Add JSDoc comments
- Extract magic numbers to constants
# ā
CORRECT: Stop after spec failure
## Spec Compliance
- ā Email validation missing (required in spec section 2.1)
- ā Password not hashed (critical security issue - spec section 3.2)
- ā Missing error handling for duplicate emails (spec section 2.3)
**Result**: STOP
**Action Required**: Fix all 3 spec compliance issues. Code quality review will follow after spec passes.
**Priority**:
1. CRITICAL: Hash passwords before storage (security)
2. HIGH: Add email validation (data integrity)
3. HIGH: Handle duplicate email errors (user experience)
Reviewing code?
ā Stage 1: Check spec compliance
ā Spec PASSED? ā Proceed to Stage 2 (quality)
ā Spec FAILED? ā STOP, provide spec feedback only
Reviewing a PR?
ā File-by-file analysis
ā Two-stage per file
Multiple files changed?
ā Review critical files first (core logic, security)
ā Then supporting files (tests, docs)
Need general critical feedback on approach?
ā Use critical-partner (not code-review)
Debugging an error in existing code?
ā Use systematic-debugging (not code-review)
Reviewing architectural decisions?
ā Use critical-partner or brainstorming
Spec is ambiguous: Flag ambiguity before review. Ask: "Spec says X, but could mean Y or Z. Which is correct?"
Partial implementation: Review completed parts only. Note: "Reviewed implemented features. Features X, Y not yet implemented."
Breaking changes: Check if intentional and documented. Flag unintentional breaks.
Performance regressions: If spec includes performance requirements, verify with benchmarks.
Security issues: Always flag security issues regardless of stage. Security > process.
# Code Review: User Registration Feature
## Summary
4 files reviewed ā spec compliance PASS ā
, code quality PASS with 3 minor suggestions ā ļø
---
## File: src/services/UserService.ts
### Stage 1: Spec Compliance ā
- ā
registerUser accepts email/password (spec 2.1)
- ā
Returns User object without password (spec 2.2)
- ā
Email validation enforced (spec 2.3)
- ā
Password hashed with bcrypt (spec 3.1)
- ā
Duplicate email returns 409 error (spec 2.4)
**Result**: Spec compliance PASSED
### Stage 2: Code Quality
**Line 23-25**: Use async bcrypt.hash instead of deprecated hashSync
```typescript
// Current (deprecated)
const hashed = bcrypt.hashSync(password, 10);
// Recommended
const hashed = await bcrypt.hash(password, 10);
Line 45: Extract magic number to constant
// Current
if (password.length < 8) throw new Error('Password too short');
// Recommended
const MIN_PASSWORD_LENGTH = 8;
if (password.length < MIN_PASSWORD_LENGTH) throw new ValidationError('Password too short');
Line 67-70: Add JSDoc for public method
/**
* Registers a new user with email and password
* @param email - User email address (validated)
* @param password - Plain text password (will be hashed)
* @returns User object without password
* @throws ConflictError if email already exists
* @throws ValidationError if input invalid
*/
export async function registerUser(email: string, password: string): Promise<User>
Spec Compliance: ā PASS (all requirements met)
Code Quality: ā ļø PASS with minor improvements (3 non-blocking suggestions; production-ready as-is)
Security: ā No issues (passwords hashed, inputs validated, no sensitive data leaked)
Recommendation: ā APPROVE with suggestions
---
## Resources
- [output-format.md](references/output-format.md) - Canonical output structure: verdict, self-contained findings, merge checklist
- [critical-partner](../critical-partner/SKILL.md) - General critical feedback
- [code-conventions](../code-conventions/SKILL.md) - Code standards and organization
- [typescript](../typescript/SKILL.md) - Type safety review
- [systematic-debugging](../systematic-debugging/SKILL.md) - Debugging methodology
- [verification-protocol](../verification-protocol/SKILL.md) - Evidence-based verification