# Why Code Verification Matters More Than Ever in the Age of AI

> Source: <https://blog.bytebytego.com/p/why-code-verification-matters-more>
> Published: 2026-08-24 15:31:01+00:00

[How to give an agent a task instead of a token (Sponsored)](https://go.bytebytego.com/WorkOS_082426Headline)

Give an agent an access token and it spreads: into the context window, into tool call logs, into notes it keeps between steps. Each copy works from anywhere, long after the fact.

[Relay](https://go.bytebytego.com/WorkOS_082426Relay) keeps the credential at WorkOS. Your agent names the user, WorkOS attaches that token, refreshes it, and releases it only to allowlisted hosts. A hijacked agent session is a live process you can kill.

The gap between code that executes fine and code that is actually safe to trust is growing wider pretty fast. For many years, writing code was the slow, expensive step, whereas reviewing it was a smaller task at the end. With the rise of AI-assisted coding, this balance is shifting.

AI tools can now create a working function in seconds and a full feature in minutes. Teams are able to write more machine-generated code every month. In other words, producing code is now fast and relatively easy, whereas code verification is the harder part. A reviewer still has to read the change, understand it, and decide whether it belongs in production. In fact, more code written simply means more code that should be verified.

We recently got a chance to speak with [Andrea Malagodi](https://www.linkedin.com/in/malagodia/), the CTO of Sonar (the company that has built some of the most used code verification software). He provided deep insights into code verification, especially in the context of AI and how Sonar is adapting to the recent changes.

In this article, we will look at how code verification works, why the rise of AI-generated code puts more pressure on it, along with the extremely useful insights from Andrea on what the future may look like.

## The Shift

The shift with regard to code generation and verification is quite visible when we look at the data. One of the clearest signals comes from Google’s DORA research, a long-running study of how thousands of teams build and ship software. Their recent work found that as teams adopt more AI, delivery stability dipped. Trust in AI-generated code stayed low, with well over a third of developers reporting little confidence in what these tools produced [2]. In other words, more speed in writing code brought more pressure further down the line.

A controlled trial from the research group METR gives a similar indication. Its participants were experienced open-source developers working on their own mature projects, and each task was randomly assigned to allow or disallow AI tools. The developers expected AI to speed them up by roughly a quarter.

However, the result showed a totally different picture. AI-assisted tasks took about 19 percent longer [3]. Moreover, this happened after the developers internally believed that the AI helped them be more productive. Turns out, a lot of extra time went into prompting, waiting, reading the output, and correcting it. To be fair, the same team later reported a more confusing follow-up signal. This was partly because developers preferred to keep their AI tools [4].

Nevertheless, if we consider these results together, it is evident that while AI definitely increases the amount of code written, it also leads to more verification work down the line.

So let us first understand what code verification actually means.

## Earning Trust

Code verification is the umbrella term for every check that ensures whether a piece of code is correct, safe, and maintainable enough to ship to production. In other words, it is the work of earning enough trust to put a change in front of real users. The key term to note here is “earning”. This is because trust arrives in degrees. It is built up one check at a time, rather than granted in a single stroke.

Think of a task of drafting a contract. Writing the words is one part of this task. However, the review, the legal checks, and the signatures are what transform those words into something people can actually rely on. Writing code works in a similar way. The moment a piece of code leaves an editor and is committed to a code repository, it carries an implicit claim about the functionality. Code verification is the process through which that claim gets tested until a team feels safe to use that code in a real production environment.

Some domains push this stage to its limit through rigorous formal verification. In such domains, engineers have to mathematically prove that the code being deployed matches a precise specification. Such a process is standard for critical stuff like flight-control systems and kernels, where a single defect can risk lives. However, for most software, having a similar approach can cost far more than it returns. Therefore, teams opt for lighter checks that are arranged in layers.

## The Filter Stack

Taking the layered analogy further, we can imagine code verification as a stack of filters. As you can see, each filter catches a certain type of problem.

At the top of the stack, we have the cheapest checks. For example:

**Type Checker:** It confirms whether the values moving through your code are the exact type each operation expects. This way it can catch a whole class of mistakes before the code even runs.**Linter:** It scans for suspicious patterns and style problems.

These types of checks can run in an instant and cost almost nothing. Below this stack, we have tests.

A unit test runs a small piece of code with known inputs and confirms whether it returns the expected output. Tests can catch behavioral mistakes in the code that a type checker cannot detect. This is because a piece of code can have perfectly valid types while still computing the wrong answer. For example, consider a simple function that is supposed to add two numbers, but instead multiplies them. In such a case, the type checker and linter would not point out any issues. Only a unit test that compares the result of the operation against a known answer will reveal the mistake.

Below the layer of tests, we have the human review filter. This is basically the case where another developer goes through the change and judges whether it fits the system, solves the right problem, and is readable. This layer catches what machines can miss, such as a solution that works yet takes an approach the team standards don’t recommend.

Beneath all of these layers is the production monitoring setup. The job of this system is to observe the code under real traffic and flag problems that may have passed through every earlier layer.

Real-world filter stacks can also hold more layers than this. This may include security scanners and dependency checks. However, the point is that each filter covers a specific weakness in the one above it. This is why serious teams run several such layers in a specific order before releasing any code into production.

## Static And Dynamic Analysis

The filters in that stack fall into two families:

**Static Analysis:** The filters in this family check the source without executing it, which makes this type of analysis fast and broad. With static analysis, we are able to scan an entire codebase in one pass. Type checkers and linters belong here. The tradeoff is that real behavior at runtime remains partly out of view. Therefore, static analysis can sometimes raise an alarm about a problem that might not exist during live conditions.**Dynamic Analysis:** The filters in this family run the code with real inputs and observe the result. Tests belong here. This family relies on checking actual behavior, but is limited by paths that are exercised. A test suite that only runs the happy path cannot detect a crash that might be waiting to happen on an empty input.

Despite the extensive coverage, a clean scan and a green test suite together can still leave gaps. This is why code verification relies on many filters working together to be effective.

## False Alarms

A tempting conclusion we might make is that more checking is always better. However, there is a tradeoff at the heart of code verification. Every filter can make two kinds of mistakes:

**False Positive:** This means flagging something as a problem when the code is actually fine.**False Negative:** This means staying quiet while a real bug slips through.

If we tune a tool to catch every possible issue, it can flood the developers with false alarms. However, if we tune it to stay quiet unless it is certain, it can start to miss real defects. The two aspects pull against each other.

False alarms carry a pretty steep cost. When a tool raises frequent false alarms, developers start ignoring it. However, this habit can be catastrophic. Even an occasional real warning can get waved away with the rest. Research on static analysis tools describes this pattern, where high false-positive rates erode trust until teams switch the tool off or don’t pay attention to its warnings. However, doing so reopens the door to the very bugs the tool was meant to stop [7].

This is why a good code verification setup cares as much about signal quality as about coverage. Andrea from Sonar described the balancing act as almost a CAP theorem for code verification. This was built from the classic idea that you can push some properties only at the expense of others. The three competing priorities in the case of code verification are speed, accuracy, and coverage, and no tool fully wins all three. Andrea’s team tries to keep the focus on humans with a simple rule that a finding a developer can act on is worth raising.

The positioning of the filter can also change the cost associated with a mistake. This brings us to the overall setup of the code verification pipeline.

## The Pipeline

Filters run at different moments in the lifecycle of a change request. The timing determines their cost. If we spread the moments out in order, we get a pipeline. A change begins in the developer’s editor, moves to a set of automated checks that fire the moment code is committed, then to review, then to a merge, then out to deployment and live monitoring.

The same check becomes more expensive the later it runs. This is because more work piles on top of the mistake as development progresses. For example, catching a flaw in the editor may cost a brief moment of the author’s attention. However, catching that same flaw after it reaches production can result in an incident or a rollback. There might also be user impact. This is the real meaning of the phrase “shift left”: moving checks earlier in the pipeline so problems surface while they remain cheap to fix.

Often, vendors might try to market this approach with precise multipliers. You might come across claims that a bug costs ten times more at each stage. While the exact numbers deserve skepticism, the important takeaway is that the general direction of pushing checks earlier in the pipeline is beneficial from a cost point of view.

## AI Pressure

This stack of filters was built for a setup where developers wrote most of the code. As we have seen, this assumption has weakened over the last few years with the rise of AI-coding tools. This change has an impact on every layer in two distinct ways.

The first pressure is volume.

When an agent writes a thousand lines in the time a person once wrote a hundred, the review burden increases dramatically. There is also a subtle effect on batch size, meaning the amount of change bundled into a single review. AI-based coding tools tend to produce larger changes, which are harder to review. This is because attention spreads thin across a big diff and small mistakes can slip through more easily. Andrea mentioned this failure mode with a line many developers will be familiar with. The reviewer who faces a 5,000-line pull request types “looks good to me,” and figures that things will anyway surface during production.

The second pressure concerns the kind of mistakes that AI can make. A study across more than a hundred models tested the security of AI-generated code and found that it introduced a known security flaw in roughly 45 percent of cases [5].

Over the same period, while these models have become far better at producing code that runs cleanly, their security checks have remained mostly flat. In other words, AI has improved sharply at making the code work, but only a little at making that code truly safe. If anything, the gap between the two aspects has widened. A separate analysis of millions of code changes has also found rising duplication and falling reuse [6].

## Reviewing AI

When there is more code than developers can carefully read and analyze, the natural approach is to hand over some of the code verification to machines. This is why AI-driven code review has gained real momentum over the past few years.

An AI code reviewer offers three main advantages:

**Speed:** It scans a change the moment it appears, before a human has time to look.**Coverage:** It catches a meaningful share of bugs and security issues early.**Consistency:** It applies the same standards across every change and every team member. Due to the probabilistic nature of AI code review, maintaining consistency can be challenging. It’s important to have multiple layers of review that include both AI-driven tools and other deterministic algorithmic tools.

This review process can also run inside the agent’s own loop. The agent writes a draft, the reviewer flags problems, and the agent corrects them before a human developer ever gets a chance to look at the code. This tightens the feedback loop and clears routine work off a human reviewer’s plate, ultimately helping teams handle larger volumes of generated code.

See the diagram below:

However, this approach also has a risk. A reviewer model built from the same kind of model as the code creator tends to work with the same assumptions. It would therefore have the same blind spots. When both the writing of the code and reviewing it depend on similar training and similar patterns, the reviewer can confirm that the code looks right. The key question about whether the code does what was actually intended stays irrelevant. In other words, two similar models can resemble one opinion stated twice more than two completely independent checks.

Consider an agent that turns a ticket into a function. An AI reviewer scans it and reports the code as clean. The code compiles, runs, and matches common patterns. Whether it does what the ticket truly meant cannot be answered by pattern-matching alone. This is where different views exist:

Some argue that the models have grown capable enough to reduce or even remove the human review step.

Others hold that people remain essential for judgment about architecture, context, and accountability.

Both camps make a fair case. The reasonable answer today is that it depends on what you are shipping and the cost of a potential mistake.

## The Modern Stack

Let us now see how these ideas assemble into a real workflow.

Everything starts with the context. Most engineering happens in brownfield code, meaning large existing codebases with history and quirks, rather than greenfield projects that have started from scratch. An agent looking into that code without guidance works out the layout on its own, but it does so differently each time. Andrea called that inconsistency “a box of chocolates”, where the result you get back varies from one run to the next and from one developer to the next.

A mature setup handles this by feeding the agent a shared and consistent picture up front. This includes the real architecture, the coding guidelines for the language, and rules that try to capture the intended design. Three loops take care of the verification part. Here’s a brief breakdown of the loops:

**Agentic Loop - Where agents iteratively build:** It optimizes code generated within the agentic sandbox and improves agent effectiveness. It also reduces token costs, improves output quality, and reduces risk.**CI verification loop - The validation pipeline for all code:** Deals with code review, zero-trust, multi-layered verification, and quality gate at sandbox exit. It also merges fixes at high velocity and volume with confidence.**Code maintenance loop - Background remediation of tech debt:** It continuously patrols to address legacy issues in the background agentically. Cleaner code makes it easier for coding agents to work efficiently.

Andrea also helped sketch what a mature setup in 2026 might look like. In the case of Sonar, the components of the modern stack are as follows:

**Verification Engine:** It consists of thousands of rules doing automated code analysis for reliability, maintainability, and security across more than 40 programming languages, frameworks, and IaC technologies. Sonar’s offerings, SonarQube (what it’s most known for) and Sonar Vortex (a new solution), provide this in the agentic loop.**AI Code Review:** A newer capability built from AI, that came through Sonar’s acquisition of Gitar. It uses carefully written instructions rather than fixed rules. Its real value is making each finding explainable to the reviewer, so that a 5,000-line change becomes something a developer can reason about. This sits in the CI verification loop.**Remediation Agent:** Aimed at the existing backlog, working through old issues progressively to clean up history rather than only guarding new code. This covers the code maintenance loop.

Other companies are more or less converging on a similar idea.

There is also a big advantage to keeping the code clean. The team at Sonar measured what happens when AI-generated code, which is often tangled and rather dense, is left to evolve across many developer sessions over half a year or more. They found that messy code ultimately starts to cost more tokens to work with. This is because the AI model needs to spend more effort understanding it every single time there is a change.

One more aspect sits at the very front of this debate. It concerns secrets, meaning credentials like API keys and passwords. The danger with secrets is rarely intentional sabotage. Most of the time, someone pastes code or loads a configuration file into an AI session. The secret then rides along with the change, and it is usually caught too late, once it has already become part of a commit or a log file.

The fix for this is to run a scanner right at the terminal, before the developer pastes the code. In other words, the goal would be to stop it as early as the process allows. Sonar calls this approach “starting left”. This is one step earlier than the familiar shift left that we talked about. Andrea’s advice is that every developer should run a guard like this to ensure that the secrets remain safe.

## Trust And Risk

All these points lead to one important practical question.

How much code verification does a given change actually need?

The answer is that it depends on what a specific failure would cost. Determining the cost is the real skill that requires insight. For example, a typo on a marketing page and a bug in a payment system deserve very different scrutiny. A developer can probably fix the typo on a marketing page in a minute without much effort. However, the bug in the payment system can move money to the wrong place, break trust, and trigger an unwanted news item.

Mature teams treat verification depth as a dial dependent upon the risk factor. Low-risk changes pass through with light automated checking. However, high-risk changes often get routed to human eyes and undergo heavier scrutiny.

Deciding the exact position of where the line should be drawn is a judgment call that should be made by the team. For example, a comma can be the difference between a working operating system and a crash, so the risk appetite has to be chosen in a deliberate manner. There is no fixed rule that can be applied to all situations.

Agents take a change as far toward a clean and verified state as they can on their own, while staying within guardrails. They can merge low-risk work automatically while routing riskier stuff to a human developer. However, setting these tiers properly so that a change is routed to the right level of checking is an emerging practice that is only going to get more important with time.

## Conclusion

The center of gravity in software development is shifting. Writing code has now become the faster activity. On the other hand, verifying that same code, confirming that it is correct, secure, and worthy of real users, is where the effort seems to be increasing.

As we have seen, code verification works as a stack of filters where each filter trades a bit of cost for a bit of confidence. Each filter covers a weakness in the one above it. Those filters divide into static and dynamic families. Every filter balances false alarms against missed bugs, and moving filters earlier keeps their mistakes cheap.

The flood of AI-generated code has an impact on all of it, raising both the volume and the risk. Also, the tempting shortcut of letting AI review for AI has a real catch, since a machine checking a machine can agree that code looks fine while the more important checks get ignored.

The human side to this shift is that as writing code gets cheap, the developer’s work becomes even more important. Developers need to spend more time orchestrating agents by providing instructions. They might have to focus more on the older and harder problem of knowing what to build at all. Cheaper code generation provides more room for spending time on that kind of judgment rather than removing the need for it.

**References**

[CrowdStrike outage: We finally know what caused it and how much it cost](https://www.cnn.com/2024/07/24/tech/crowdstrike-outage-cost-cause)[Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity](https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/)[We are Changing our Developer Productivity Experiment Design](https://metr.org/blog/2026-02-24-uplift-update/)[AI Copilot Code Quality: 2025 Data Suggests 4x Growth in Code Clones](https://www.gitclear.com/ai_assistant_code_quality_2025_research)[FP-Predictor: False Positive Prediction for Static Analysis Reports](https://arxiv.org/pdf/2603.10558)
