What should a reviewer check when a pull request arrives from a contractor or a builder tool? Not style first. A code review checklist that works has eight groups, security first, and a test for every line, because at least 18 of the 21 third-party apps I audited had no working test anywhere.

The code review checklist: eight groups, a test per line

A code review checklist has eight groups with a test for every line: correctness, security, data, errors, tests, performance, readability and structure, and documentation and dependencies. A line without a test is only a label. I put security first because it is the group the author is least likely to have checked.

The 21 apps in that opening line are the third-party apps I audited in June and July 2026: 11 public vibe-coded apps audited exhaustively across all 12 pillars, and a held-out set of 10 more, audited blind. Seventeen had no tests at all, and in the eighteenth, a retail POS, the checkout “test suite” never executed the actual checkout code. I chose those apps for audit; they were not sampled at random, so “at least 18 of 21” describes them and is not a rate for AI-built apps in general. This checklist is one of the engineering standards for AI assisted teams I hold a codebase to.

The list is simple on purpose, so the same code review checklist template serves a developer reviewing a teammate’s change and a founder reading a contractor’s source code. The code review criteria are the lines themselves: each one is a check, then the test that settles it, and a line nobody can test comes off the list.

Correctness is listed first because it is the question the ticket asks: does the change do what was asked? I still read it after security.

  • Does what the ticket says. Test: run the happy path and one wrong input, and compare both results with the ticket’s wording.
  • Handles the empty case. Test: run it with no rows, no file or a blank field, and read what the user sees.
  • Leaves the rest alone. Test: open the screens next to the change and use each of them once.

I read security before anything else. The full secure pass needs its own list, a secure code review checklist; these are the lines no review skips.

  • Every route checks the session and the role on the server. Test: call the route signed out and then as the wrong role, and confirm no data comes back.
  • No secret in the diff. Test: search the changed files for keys, tokens and connection strings, config files included.
  • Input is validated on the server. Test: send the endpoint a value the form would never send.
  • No query can return another tenant’s rows. Test: find the query that filters by tenant, change the tenant id in the request, and confirm you get a refusal or nothing, never the other tenant’s rows.

A small pull request can do lasting damage through one migration, so the data lines come next; the deeper list is the data consistency checklist for SaaS.

  • The migration can be reversed. Test: run it forward and back on a copy of the database.
  • Constraints live in the database, not only in the form. Test: insert a bad row directly and expect the database to refuse it.
  • Deleting a parent leaves no orphan rows. Test: delete one parent record on a copy and look for its children.

Errors and edge cases get three lines in a review; how failures should be handled across a whole app is part of hardening SaaS applications.

  • Failures are handled and logged with context. Test: make the external call fail and read the log line; it should say which action failed and for whom.
  • No swallowed exception. Test: search the diff for empty catch blocks and catches that only print.
  • A retry cannot repeat a side effect. Test: run the action twice with the same input and check that one charge, one email or one row came out.

A test proves something only if it can fail. Writing the ones that matter most is covered in how to write end to end smoke tests.

  • A test exists for the change. Test: find it in the diff and run it.
  • The test has been seen to fail once. Test: break the code it covers, run the test, watch it go red, then undo the break.
  • The test touches the real code. Test: check that it does not mock the very query or function the change adds.

In a review, performance problems show in the shape of the code, before anyone measures anything.

  • No query per row. Test: load a list page with query logging on and count the database calls.
  • No unbounded list. Test: find every endpoint that returns a list and look for a limit or a page size.
  • The expensive path has a limit. Test: call it again and again and see whether anything stops you.
  • Slow work stays out of the request. Test: time the slowest call in the change and ask whether a user waits for all of it.

Lint and types, the automated half of readability and structure, belong in code quality checks; the lines below are the judgment a reviewer adds.

  • Names say what things are. Test: read a function’s name and guess what it returns before you open it.
  • No duplicate logic. Test: search the repository for a distinctive line of the new code.
  • Boundaries are typed. Test: look at what enters and leaves the new module for untyped JSON or a loose any.
  • The change lives where the repository keeps that kind of code. Test: find the module that already owns the job and compare.

Read at module level, that last line is the whole architectural code review checklist: does each new piece sit in the module that owns its job, and does anything now depend on something it should not?

Last come documentation and dependencies, where a new package is also a license question (license scanning covers it).

  • The README is still true. Test: follow its setup steps on a clean checkout.
  • A new dependency is justified. Test: ask what it does that the repository could not already do.
  • A new dependency’s license is checked. Test: read the package’s license and compare it with what your project allows.
  • Changed behavior is written down. Test: find the note in the pull request description or the docs.

Nothing here is a download. To use it as a code review template in Word, Excel or a shared document, paste the lines in as rows with a pass or fail column; to keep a code review checklist as a PDF, print that sheet. A sample code review checklist, filled in on one pull request, is the export example further down. The same list works as a software peer review checklist between two engineers. What a reviewer looks at, in plain words for an owner, is in what a code reviewer actually looks at.

How to fill it in: running the checklist on a pull request you did not write

Running the checklist on code you did not write takes six steps: read the ticket, run the change before reading it, read the diff group by group with security first, write each finding with a severity and a location, split must-fix from should-fix, then decide.

  1. 01 Read the ticket first and write down what "done" means before you open the diff.
  2. 02 Run the change before you read it: start the app, run the tests, and walk through the feature once yourself.
  3. 03 Read the diff in the order of the groups, security first, and note every line a group fails.
  4. 04 Write each finding as one line with a severity and a location (the file and the function), not as a comment thread.
  5. 05 Separate must-fix from should-fix and nits; only must-fix lines block the merge.
  6. 06 Decide: approve, request changes, or reject, and send the report with the decision.

If the second step stalls because the project will not start on your machine, that is a finding in its own right, and the way through is in cannot run the project locally. Of the code review best practices on GitHub, I hold to two before any of the others: a pull request small enough to read in one sitting, and a review requested from the person who owns the code rather than whoever is free.

When the pull request for an outsourced feature is subpar (too large to read, no tests, secrets in a config file, a query per row), the answer is the report, not a rewrite. If you rewrite it yourself, the author never sees what went wrong and the next pull request looks the same; the report lists it and the author fixes it. The code review example in the next section runs the six steps on one feature.

For AI-generated code, one habit matters more than the rest: check that each generated test asserts something real. A founder reviews a contractor’s pull request against a list of headings and sees that it includes tests and that they pass. The tests call a mocked database and assert what the mock returns, so the feature’s real query never runs; “tests included” was ticked, and “the test has been seen to fail” was never on the list. The lesson I take from it: a checklist line passes only when its test could have failed. Why a green suite written by the same tool proves so little is the subject of tests pass but the app is still broken.

What changes when nobody on the team wrote the code is covered in the code reviewer article linked above. If you own the app and do not read code, start with code review for non-developers; if you are paying someone to review a vibe-coded app, what a code review of AI code should check sets out what their review should cover.

A filled example: an AI-generated “export to CSV” feature

The assumptions come first. The app is Next.js on Supabase. A contractor used an AI tool to add an endpoint that exports a tenant’s records to CSV, and the pull request includes tests, which pass. Every finding below belongs to this example; none is from a real review.

GroupFindingSeverityLocationFix
CorrectnessNone: the file has the columns the ticket listsnoneexport routenone needed
SecurityThe route reads every row for the tenant id sent in the request bodymust-fixexport route, tenant lookupTake the tenant from the server-side session and ignore the body
DataThe migration adds a column with no default and says nothing about existing rowsshould-fixnew migration fileSet a default or backfill in the same migration
Errors and edge casesA failed query returns an empty file instead of an errorshould-fixexport route, error branchReturn an error the screen can show, and log it with the tenant
TestsThe generated test mocks the database and asserts the mockmust-fixexport testRun it against a test database, and watch it fail once with the tenant check removed
PerformanceThe export endpoint has no limit on rows or on callsmust-fixexport routeCap rows per export, page the rest, and rate-limit the endpoint
Readability and structureGood names; the structure follows the repositorynonewhole diffnone needed
Documentation and dependenciesA new CSV library added without a license checkshould-fixpackage manifestCheck its license against the project’s policy, or use what the repository already has

Read as a code review report example, the table is the findings half of the one-page report in the next section: one row per group, so the passes are on record next to the failures.

The security and performance lines are in the example on purpose. Of the 21 third-party apps I audited in June and July 2026, 10 trusted the client: the server accepted whatever the browser asserted. In the same audits, 13 of the 21 had no rate limiting on their most expensive endpoint. Those apps were picked for audit rather than drawn at random, so the counts tell you what to look for, not how often it happens in apps I have not read.

The decision is request changes, with three must-fix lines: the tenant lookup, the missing limit and the test that only checks a mock. The should-fix lines go into the same report, and the author gets all of it at once.

How to verify the result: the code review report template

The code review report is one page: the scope and commit, the decision, must-fix findings with severity, location, evidence and fix, should-fix findings and nits, what was not reviewed, and the retest line. The owner keeps it, and the retest closes it.

SectionWhat goes in it
ScopeWhat was reviewed, the commit, and the date
DecisionApprove, request changes or reject, in one line
Must-fix findingsSeverity, location, evidence and the fix, one line each
Should-fix findings and nitsThe same fields; these do not block the merge
Not reviewedWhat was out of reach: files skipped, services that would not run
RetestWho re-reviews after the fixes, and when

As a source code review report template it stays at one page on purpose: the owner can read it at a glance, and the author can work straight down it. The “not reviewed” row is what stops a partial review being read as a full one.

Verification is the retest. Each must-fix line is closed by a commit the report names, the tests are green, each new test has been seen to fail once, and the reviewer signs off with a date. Until all of that is true, the report stays open. A code audit report is a different document at the scale of a whole repository, and what a code audit’s final report should contain is covered there.

Running the review in your tool: a code review template in GitHub, GitLab, Bitbucket and VS Code

A code review template only runs when the repository makes it run: a pull request template (a merge request template on GitLab) with the eight groups as checkboxes, a CODEOWNERS file that requests the right reviewer, branch protection that requires a code owner’s review where your plan offers it, and automated checks that finish before a human reads.

The steps follow GitHub’s, GitLab’s and Atlassian’s own docs as of September 2026; on GitHub, every code review tool the steps need is built in: the template file, CODEOWNERS, the review and the branch rule.

  1. 01 Add a pull request template: on GitHub, a file named pull_request_template.md in the repository root, in docs/ or in .github/; on GitLab, a Markdown file in .gitlab/merge_request_templates/.
  2. 02 Add a CODEOWNERS file in .github/, the root or docs/, so GitHub requests a review from the owner of the code a pull request changes.
  3. 03 Protect the main branch with Require pull request reviews before merging, and turn on the option to require reviews from code owners.
  4. 04 Add required status checks, so lint, types, tests and the dependency scan must pass before collaborators can merge.
  5. 05 Record the decision in the review itself (approve, request changes or comment) and attach the report.

To write a pull request template, follow GitHub’s pull request template guide: once the file is in, “project contributors will automatically see the template’s contents in the pull request body”, and templates reach collaborators when they are merged into the default branch. On GitHub the code review template is that one file, and the checklist inside it is the eight groups as checkboxes; here is my version, saved as .github/pull_request_template.md:

## What this pull request does
Ticket:
Done means:

## Review checklist (every line needs its test)
- [ ] Correctness: happy path and one wrong input both tried
- [ ] Security: session and role checked on the server; no secret in the diff
- [ ] Data: migration reversible; constraints in the database
- [ ] Errors: failures logged with context; nothing swallowed
- [ ] Tests: a test covers the change and was seen to fail once
- [ ] Performance: no query per row; every list has a limit
- [ ] Readability and structure: clear names; no duplicate logic
- [ ] Documentation and dependencies: README true; new packages license-checked

## Decision
Approve / Request changes / Reject, with the report linked

For a code review template on GitLab, save the same content as a Markdown file in .gitlab/merge_request_templates/; it then shows in the Choose a template dropdown, and a template named Default.md in that folder sets the default description template for merge requests, per GitLab’s description templates. Code review in GitLab happens on the merge request: a reviewer selects Start a review, adds comments that stay unpublished until the review is submitted, and chooses Approve, Comment or Request changes. On the Premium and Ultimate tiers, GitLab’s merge request reviews page says “A reviewer requesting changes blocks a merge request from merging.”

GitHub’s CODEOWNERS file lives in .github/, the root or docs/, and code owners “are automatically requested for review when someone opens a pull request that modifies code that they own”, though not on draft pull requests. In GitHub’s protected branches, the setting is Require pull request reviews before merging; with the option to require reviews from code owners on, a pull request that touches owned code must be approved by that code owner before it can merge. When a merge sits waiting on a code owner review, check two things: the required reviewers need write access to the repository, and the CODEOWNERS file has to be on the pull request’s base branch.

The second, third and fourth steps depend on your plan. GitHub says you can define code owners “in public repositories with GitHub Free and GitHub Free for organizations, and in public and private repositories with GitHub Pro, GitHub Team, GitHub Enterprise Cloud, and GitHub Enterprise Server”, and its protected branches page states the same condition. In my reading, then, none of those three is available on a private repository on GitHub Free, and there the template, the report and the written decision are the whole setup.

Code review for GitHub pull requests ends in one of three decisions, as GitHub’s pull request reviews lists them: Comment “Leaves general feedback without explicitly approving or requesting changes”, Approve “Signals that the changes are ready to merge”, and Request changes “Flags feedback that the author should address before merging”.

For a Bitbucket code review checklist, save the same list as .bitbucket/pull_request_template.md: Atlassian’s support article on pull request templates in Bitbucket Cloud says that file sets the default pull request description, read from the pull request’s source branch. Bitbucket’s pull request reviews page documents Default Reviewers, set in the repository’s settings, and a CODEOWNERS file in a .bitbucket directory, and a reviewer finishes with the Approve button. Blocking a merge on approvals has a plan condition, in Atlassian’s words: “If your workspace is on a Premium plan, repository admins can prevent pull requests that don’t have a certain number of approvals from being merged.”

Of the code review tools for VS Code, GitHub publishes the GitHub Pull Requests extension, which “allows you to review and manage GitHub pull requests and issues in Visual Studio Code”, with in-editor commenting. For C# teams, the code review tools start in the IDE: code review in Visual Studio runs through Visual Studio’s pull requests view, where you can open a pull request, “understand whether it’s ready, and act on it all in one place”, and comment on lines in the diff; with GitHub as the provider, those comments are limited to lines within 3 lines of a change.

The automated checks that should finish before a human reads (lint, types, tests, the dependency scan) are covered in the code quality checks article linked in the checklist above, and the rules for AI coding tools inside the repository are guardrails for AI coding agents. That repository side is where the sprint’s deliverable 10.8 sits: we provide CLAUDE.md, AGENTS.md, Cursor rules, or equivalents describing conventions and protected patterns, and add CI checks for enforceable rules. An AI reviewer can take a first pass before a human reads; which one is worth using is covered in best AI code reviewer.

Language and framework inspection checklists

The eight groups hold in every language. A Java inspection checklist or a Python or C# code review checklist is the same list plus one line for what that language makes easy to get wrong, and the table gives that line and the tool that checks it, as my working rules. Most code review best practices for Java, Python or C# that I would add are already in the eight groups; the rows hold what is left.

Language or frameworkThe one line its review addsThe tool that checks it
Java and SpringNull handling, and every resource closed after useThe project’s linter
PythonType hints at the boundaries; no mutable default argumentsA type checker
C# and VB.NETAsync all the way down; every disposable object disposedThe .NET analyzers
SQLA migration that can be reversed; an index for each new filterThe query plan
React and AngularWho owns each piece of state; in React, Effects that survive running twiceThe framework’s lint rules
Selenium and other test codeEvery assertion can failA red run: break the code, watch the test fail
SAP ABAPThe same eight groups, nothing extraThe ABAP Test Cockpit, where your system has it

For Java and Spring, the code review checklist line is about resources: a connection, stream or file opened in the change is closed on every path, the error path included. Python’s own tutorial warns that a default value “is evaluated only once”, which makes a difference when the default is a mutable object, and that is why mutable defaults are the line I add to any Python code review.

The C# row carries VB.NET too, so a VB.NET code review checklist gets the same async and disposal line. Microsoft says its .NET analyzers “are included with the .NET SDK”, and code analysis is enabled by default for projects that target .NET 5 or later. If you want a Microsoft code review checklist to start from, Microsoft’s engineering playbook keeps C#-specific review items that include asynchronous programming and disposable objects.

A SQL code review checklist adds two lines, and the query plan settles the second: run the new query with its filter and check that the plan uses the index you expect. A Selenium code review checklist is about the test code itself, since every assertion has to be able to fail and a red run is the only proof.

On the front end, the React and Angular code review best practices I add are about state: which component owns each piece of it. React’s Strict Mode re-runs Effects an extra time in development “to find bugs caused by missing Effect cleanup”, so an Effect that breaks when run twice shows itself there. Angular developers use the same code review checklist, with the framework’s lint rules as the tool.

A code review checklist in SAP ABAP keeps the eight groups, and SAP’s ABAP guidelines supply the tool: “If ABAP Test Cockpit is available in your system, make sure that an ATC run is performed on all involved development objects and that no messages are displayed before you release the objects for transport.”

Where the sprint does this

In the sprint, deliverable 10.5 automates smoke tests for signup, login, the core product action, and payment flows, and it is verified this way: run the suite in CI and demonstrate that an intentional regression fails it. Each result goes into the production readiness report, which accounts for all 123 IDs, keeps failures visible until resolved and explains genuine non-applicable items. Post-handover support is 14 calendar days of fixes for defects in the delivered sprint work. Every deliverable, with how it is verified, is in the published scope.

Common questions about reviewing a pull request

What are some good checklists for code review?

A good checklist for code review groups its lines and gives each line a test. Mine has eight groups: correctness, security, data, errors and edge cases, tests, performance, readability and structure, and documentation and dependencies, with security read first. A line with nothing to run or look at behind it will be ticked whether or not the code is right.

What should be included in a code review?

A code review should cover all eight groups in one pass, security first, and end in a written decision: approve, request changes or reject, with each must-fix finding listed by severity and location.

What are common code review mistakes?

In my reading, four mistakes do the most harm: reviewing style before behavior, trusting generated tests without seeing one fail, approving a pull request too large to read, and leaving a trail of comments instead of a report the owner keeps.

How do I enable code review on GitHub?

Protect the branch with Require pull request reviews before merging, add a CODEOWNERS file, and turn on the option to require reviews from code owners. GitHub’s docs list code owners and protected branches for public repositories with GitHub Free and GitHub Free for organizations, and for public and private repositories with GitHub Pro, GitHub Team, GitHub Enterprise Cloud and GitHub Enterprise Server.

What does code review mean in GitHub?

In GitHub, code review means a pull request review: a reviewer reads the changes and submits one of three decisions, Comment, Approve or Request changes, before the code is merged.