.claude/skills/code-review/SKILL.md
Code review checklist covering security, performance, defensive programming, and testing anti-patterns. Use before merging PRs, after implementing features, or when reviewing code quality.
npx skillsauth add awannaphasch2016/jousef-landing code-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.
Tech Stack: Python 3.11+, pytest, AWS Lambda, Aurora MySQL
Source: Extracted from CLAUDE.md code quality principles and testing patterns.
Use the code-review skill when:
DO NOT use this skill for:
What type of change?
├─ Security-sensitive? (auth, permissions, data access)
│ └─ Review SECURITY.md checklist
│
├─ Performance-critical? (Lambda, DB queries, API calls)
│ └─ Review PERFORMANCE.md checklist
│
├─ Distributed system? (Lambda, Aurora, S3, SQS, Step Functions)
│ └─ Review Boundary Verification section + execution-boundaries.md
│
├─ Error handling? (try/catch, validation, failures)
│ └─ Review DEFENSIVE.md checklist
│
├─ Tests added/modified?
│ └─ Check testing-workflow skill anti-patterns
│
└─ General code quality?
└─ Review all sections
From CLAUDE.md:
"Fail fast and visibly when something is wrong. Silent failures hide bugs."
Review Checklist:
# ❌ REJECT: Silent failure
def store_report(symbol, data):
try:
result = db.execute(query, params)
return True # Always returns True!
except Exception as e:
logger.warning(f"DB error: {e}") # Logged at WARNING
return True # ❌ Still returns True!
# ✅ APPROVE: Explicit failure
def store_report(symbol, data):
rowcount = db.execute(query, params)
if rowcount == 0:
logger.error(f"INSERT affected 0 rows for {symbol}")
return False # ✅ Explicit failure signal
return True
Questions to Ask:
From CLAUDE.md:
"Before executing a workflow node, validate that all prerequisite data exists and is non-empty."
Review Checklist:
# ❌ REJECT: Assumes upstream succeeded
def analyze_technical(state: AgentState) -> AgentState:
result = analyzer.calculate_indicators(state['ticker_data'])
state['indicators'] = result # Might be {} if ticker_data was empty!
return state
# ✅ APPROVE: Validates prerequisites
def analyze_technical(state: AgentState) -> AgentState:
# VALIDATION GATE
if not state.get('ticker_data') or len(state['ticker_data']) == 0:
logger.error(f"Cannot analyze: ticker_data is empty for {state['ticker']}")
state['error'] = "Missing ticker data"
return state
# Safe to proceed
result = analyzer.calculate_indicators(state['ticker_data'])
state['indicators'] = result
return state
Questions to Ask:
From CLAUDE.md:
"Functions that return
Noneon failure create cascading silent failures."
Review Checklist:
# ❌ REJECT: Returns None hides failures
def fetch_ticker_data(ticker: str):
hist = yf.download(ticker, period='1y')
if hist is None or hist.empty:
logger.warning(f"No data for {ticker}")
return None # ✗ Caller doesn't know WHY it failed
# ✅ APPROVE: Raises explicit exception
def fetch_ticker_data(ticker: str):
hist = yf.download(ticker, period='1y')
if hist is None or hist.empty:
error_msg = f"No historical data for {ticker}"
logger.error(error_msg)
raise ValueError(error_msg) # ✓ Explicit failure
Questions to Ask:
See SECURITY.md for:
See PERFORMANCE.md for:
See DEFENSIVE.md for:
When: Code changes affect distributed systems (Lambda, Aurora, S3, SQS, Step Functions)
Checklist:
Common boundary failures to catch:
Quick checks:
# Verify Lambda configuration matches code requirements
aws lambda get-function-configuration \
--function-name <name> \
--query '{Timeout:Timeout, Memory:MemorySize}'
# Verify Aurora schema matches code
mysql> SHOW COLUMNS FROM table_name;
# Verify IAM permissions
aws iam get-role-policy --role-name <role> --policy-name <policy>
See: Execution Boundary Checklist for comprehensive verification
Related: Principle #20 (CLAUDE.md) - Execution Boundary Discipline
Symptom: Single class/module with >500 lines doing many things.
# ❌ BAD: God object
class ReportService:
"""1200 lines - does everything!"""
def fetch_data(self): pass
def analyze_technical(self): pass
def analyze_fundamental(self): pass
def fetch_news(self): pass
def generate_report(self): pass
def score_report(self): pass
def send_to_user(self): pass
def log_to_analytics(self): pass
# ... 20 more methods
# ✅ GOOD: Separated concerns
class DataFetcher:
def fetch_ticker_data(self): pass
class TechnicalAnalyzer:
def analyze(self): pass
class ReportGenerator:
def generate(self): pass
Review Action: Request refactoring if class > 500 LOC or > 10 methods.
# ❌ BAD: Magic numbers
if rsi > 70: # What does 70 mean?
return "Overbought"
if len(price_history) < 30: # Why 30?
raise ValueError("Insufficient data")
# ✅ GOOD: Named constants
RSI_OVERBOUGHT_THRESHOLD = 70
MIN_PRICE_HISTORY_DAYS = 30
if rsi > RSI_OVERBOUGHT_THRESHOLD:
return "Overbought"
if len(price_history) < MIN_PRICE_HISTORY_DAYS:
raise ValueError(f"Need {MIN_PRICE_HISTORY_DAYS} days of data")
# ❌ BAD: 7 parameters
def generate_report(ticker, price, sma20, sma50, rsi, macd, volume):
pass
# ✅ GOOD: Parameter object
from dataclasses import dataclass
@dataclass
class MarketData:
ticker: str
price: float
sma20: float
sma50: float
rsi: float
macd: dict
volume: int
def generate_report(data: MarketData):
pass
Review Action: Request refactoring if function has > 4 parameters.
# ❌ REJECT: Test that can't fail
def test_store_report(self):
mock_client = MagicMock()
service.store_report('NVDA19', 'report')
mock_client.execute.assert_called() # Only checks "was it called?"
# ✅ APPROVE: Test that can actually fail
def test_store_report_detects_failure(self):
mock_client = MagicMock()
mock_client.execute.return_value = 0 # Simulate failure
result = service.store_report('NVDA19', 'report')
assert result is False
Review Question: "If I break the code, does this test fail?"
# ❌ REJECT: Only success tested
def test_fetch_ticker(self):
mock_yf.download.return_value = sample_dataframe
result = service.fetch('NVDA')
assert result is not None
# ✅ APPROVE: Both success AND failure
def test_fetch_ticker_success(self):
mock_yf.download.return_value = sample_dataframe
result = service.fetch('NVDA')
assert len(result) > 0
def test_fetch_ticker_handles_empty(self):
mock_yf.download.return_value = pd.DataFrame()
with pytest.raises(ValueError):
service.fetch('INVALID')
Review Question: "Are failure paths tested?"
# Check PR description
# - What problem does this solve?
# - Why this approach?
# - Any breaking changes?
# Check files changed
gh pr diff 123
# Size check
LINES_CHANGED=$(gh pr diff 123 --stat | tail -1)
# If > 500 lines, ask to split PR
Questions:
See SECURITY.md for detailed checklist.
Quick checks:
# Read the code, ask:
# 1. Does it handle errors?
try:
result = risky_operation()
except SpecificException as e: # ✅ Specific exception
logger.error(f"Failed: {e}")
raise # ✅ Re-raise or return False
# 2. Does it validate inputs?
if not ticker or len(ticker) > 10:
raise ValueError("Invalid ticker")
# 3. Does it check outcomes?
rowcount = db.execute(query)
if rowcount == 0:
return False # Explicit failure
# Run tests locally
gh pr checkout 123
pytest
# Check test coverage
pytest --cov=src/module tests/test_module.py
# Review test quality (not just quantity)
Questions:
See PERFORMANCE.md for detailed checklist.
Quick checks:
When to apply: PR modifies Lambda, Aurora, S3, SQS, Step Functions, or cross-service integrations
Quick assessment:
# Check if PR touches distributed system boundaries
git diff main...PR-branch | grep -E "lambda|aurora|s3|sqs|stepfunctions"
If YES, verify boundaries:
Example checks:
# Lambda timeout matches code execution time?
aws lambda get-function-configuration --function-name <name> \
--query 'Timeout'
# Compare with code's longest execution path
# Aurora schema matches INSERT queries?
mysql> SHOW COLUMNS FROM table_name;
# Compare with code's INSERT/UPDATE queries
# IAM permissions allow code's operations?
aws iam get-role-policy --role-name <role> --policy-name <policy>
# Compare with code's aws sdk calls
See: Execution Boundary Checklist for comprehensive verification
Skip if: PR only touches frontend, documentation, or single-process logic
Before approving PR, verify ALL of these:
| PR Size | Review Time | Focus Areas | |---------|-------------|-------------| | < 50 lines | 10 min | Logic, tests | | 50-200 lines | 30 min | All checklists | | 200-500 lines | 60 min | Deep review | | > 500 lines | Request split | Too large |
| Issue | Severity | Action | |-------|----------|--------| | Hardcoded secrets | Critical | Reject immediately | | No error handling | High | Request changes | | No tests | High | Request tests | | Silent failures | High | Request explicit failures | | Magic numbers | Medium | Request refactoring | | Missing docstrings | Low | Request docs |
.claude/skills/code-review/
├── SKILL.md # This file (entry point)
├── SECURITY.md # Security review checklist
├── PERFORMANCE.md # Performance review patterns
└── DEFENSIVE.md # Defensive programming review
tools
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
testing
Write comprehensive tests following project conventions (tiers, patterns, anti-patterns). Use when writing tests, improving test coverage, fixing failing tests, or reviewing test quality.
content-media
Clone and customize existing templates (landing pages, dashboards, admin panels) with style extraction, config-driven content, and theme customization
development
Create high-converting B2B landing pages using psychological section sequencing. Use when building landing pages for services, agencies, consultants, or B2B products. Provides 14-section framework optimized for conversion psychology.