Guide / Verification

How to verify AI-generated code before it ships

Short answer

To verify AI-generated code, check it against a statement of required behavior that the AI could not edit. Keep that statement outside the test suite, review test changes before code changes, focus effort on high-risk paths, run the relevant tests where the agent cannot skip them, confirm those tests really fail when the behavior breaks, and keep the evidence with the change.

Why AI-generated code needs a different kind of check

Traditional review assumes the tests were written by someone other than the person who changed the code, or at least at a different time. AI coding agents break that assumption. Claude Code, Cursor, Copilot’s agent mode, and Codex can all edit the implementation and the tests that judge it in a single change. When they do, a green test run proves only that the code agrees with its own tests.

The research so far points in the same direction:

  • Google’s 2024 DORA report estimated that every 25% increase in AI adoption was associated with a 7.2% decrease in software delivery stability, even as code review speed and documentation improved.
  • In the 2025 Stack Overflow Developer Survey, more developers said they distrust the accuracy of AI tools (46%) than trust it (33%), and 66% named “AI solutions that are almost right, but not quite” as their top frustration.
  • Veracode’s 2025 GenAI Code Security Report tested more than 100 language models on 80 coding tasks and found security vulnerabilities in 45% of cases.

“Almost right” is the core problem. Code that is obviously broken gets caught. Code that compiles, passes its tests, and quietly changes a business rule does not, unless something independent of the AI knows what the rule was supposed to be.

How to verify AI-generated code in six steps

This process works with any language, test framework, or coding assistant. The tools only change how much of it is automated.

1. Write down what must not change

Before you can check whether an AI broke something, you need a record of what “working” means that the AI cannot quietly rewrite. Tests are a poor place for that record when the same agent edits them. Keep a short, reviewed list of the behaviors that matter, such as “free-plan users can create at most 5 projects” or “users can only read invoices that belong to their own account”, in a file that needs a human owner to approve changes.

Five to twenty statements are enough for most products. Give each one a stable ID so tests and pull requests can refer to it.

2. Read the test diff before the code diff

If a change that was supposed to fix or add a feature also modifies existing tests, review those test edits first. A changed expected value, a deleted test case, a new .skip, or a mock that replaces the code under test is the AI deciding what correct behavior is. That is the decision a human most needs to confirm. Our guide on why agents change tests to make them pass lists the patterns to look for.

3. Scale verification to risk

Not every AI-generated change deserves the same scrutiny. A copy change to a marketing page and a change to the authorization middleware are different risks. Rank the change by what it touches, not by how many lines it has:

Minimum verification by risk level
RiskTypical AI changesMinimum check
CriticalAuth, permissions, billing, data deletion, migrations, secretsHuman review of every line, requirement-linked tests, mutation check, CI gate
HighBusiness rules, shared utilities, API contracts, input validationTargeted tests for affected requirements, test-diff review, CI gate
MediumNew features behind existing boundaries, UI state logicRelevant unit and end-to-end tests, normal review
LowCopy, styles, docs, isolated refactors with unchanged testsType check, lint, existing suite

4. Run targeted tests outside the agent

The agent saying “all tests pass” is not evidence. Run the tests yourself, or better, run them somewhere the agent cannot skip: a CI job on the pull request, or a hook that runs before the agent can finish. Prioritize the tests linked to the requirements the change could affect. If you use Claude Code, a Stop hook can refuse to let a turn end while tests are failing.

5. Test the tests

AI-written tests often execute code without asserting what it should do. Coverage reports count those tests as protection. Mutation testing does not: it deliberately breaks the code, for example by flipping a comparison or deleting a guard, and checks that at least one test fails. A test that keeps passing against broken code is not protecting anything. See mutation testing in TypeScript and JavaScript for a walkthrough.

6. Keep the evidence and make the decision explicit

A release decision should be auditable later. Keep the test output, the list of requirements that were checked, and, when behavior genuinely changed, the name of the person who approved the new behavior. When something breaks in production, that record tells you whether the check was missing, wrong, or skipped.

A checklist for your pull request template

Paste this into your pull request template for any change written mostly by an AI:

Pull request template
## AI-generated change checklist
- [ ] Requirements this change touches are listed (IDs or links)
- [ ] Test changes reviewed before implementation changes
- [ ] No expected values changed without an approved behavior change
- [ ] No tests skipped, deleted, or replaced with mocks of the code under test
- [ ] Auth, billing, and data-access paths reviewed line by line
- [ ] Targeted tests ran in CI (link to run)
- [ ] Mutation check run for critical paths (link to report)
- [ ] Behavior changes approved by: @owner

Automating the process with MaruCheck

Everything above can be done by hand. MaruCheck is a free, open-source CLI that automates it for JavaScript and TypeScript repositories. It runs locally or in your CI runner, so no source code is uploaded. Each step maps to a command:

Verification steps mapped to MaruCheck commands
StepCommand
Record what must not changemaru contract create --from requirements.md, then maru contract approve
Score the diff’s riskmaru risk --diff
Build a requirement-linked test planmaru plan --diff
Run targeted tests and detect behavior driftmaru verify --diff
Test the testsmaru mutate --diff
Gate every pull requestmaru ci init

Frequently asked questions

How do you verify AI-generated code?
Verify AI-generated code by checking it against a requirement the AI could not edit. Write down the approved behavior separately from the tests, review any test changes as carefully as code changes, run targeted tests for the risky paths, confirm the tests actually fail when the behavior breaks, and keep the evidence with the pull request.
Is a passing test suite enough to trust AI-written code?
Not on its own. A coding agent can change the implementation and the tests that judge it in the same change, so a passing suite can only prove the code agrees with its tests. It cannot prove the tests still describe what the product promised before the change.
What are the most common problems in AI-generated code?
Treat AI-generated code like code from a fast, confident contributor who has not read the requirements. Its common failures are plausible-looking logic errors, removed edge-case guards, weakened or rewritten tests, invented APIs, and security mistakes. Veracode's 2025 study found security flaws in 45% of the AI coding tasks it tested.
Can I verify code from Copilot, Cursor, and Claude Code the same way?
Yes. Verification depends on the diff, not on which assistant wrote it. The same process works for code from GitHub Copilot, Cursor, Claude Code, OpenAI Codex, Windsurf, or a human. Open-source tools such as MaruCheck run locally against the Git diff, so they work with any editor or agent.

Last updated