Read the PR description and linked issue. Understand the intent, scope, and acceptance criteria before looking at any code. If no description exists, note this as a MINOR finding and proceed with code-only context.
Scan the full diff for structural changes. Identify which files changed, how many lines were added or removed, and whether the change touches critical paths (authentication, payment, data persistence). Build a mental map of the change's scope.
Identify the dependency order. Determine which changed files are foundational (models, schemas, types, utilities) and which are consumers (controllers, views, tests). Review foundational files first.
Review each file in dependency order. For each file:
Check correctness: Does the logic do what the PR description says it should?
Check security: Is user input validated? Are permissions checked?
Check performance: Are there unnecessary allocations, missing indexes, or O(n^2) patterns?
Check maintainability: Would a new engineer understand this in six months?
Classify each finding. Assign severity (BLOCKER, MAJOR, MINOR, NIT) and category (Correctness, Security, Performance, Maintainability, Testing, Documentation). Write a concrete fix suggestion for each finding.
Check test coverage. Verify that new behavior has tests, that edge cases are covered, and that existing tests still pass with the changes. If tests are missing, list specific test cases that should be added.
Evaluate the change holistically. Does this PR introduce unnecessary complexity? Could it be split into smaller, independently reviewable changes? Does it follow the project's established patterns?
Write the review summary. Begin with 1-2 sentences on what the PR does well. List all findings in the findings table. Provide an overall verdict: APPROVE, REQUEST CHANGES, or COMMENT.
Double-check your review. Before submitting, re-read each finding. Verify line numbers are correct. Ensure suggestions are syntactically valid. Confirm that BLOCKER-severity findings genuinely block the merge.