← Back to Blog

Verification Becomes a First-Class Engineering Discipline

ai craft code-review testing

It's obvious to see that more and more developers are working with AI to build software, and that more and more of the software being built and shipped was produced by AI. But it comes with a cost that is harder to talk about: we are slowly losing trust in what code does — our own code as much as someone else's.

Losing trust

You see it inside development teams, and you see it publicly in the community. Codeberg changed their terms of use in July 2026 to exclude mostly AI-written code:

You must not share projects that mostly consist of code written by "generative AI"-tools (including services such as Claude, OpenAI Codex). Such projects having an unclear copyright status (see requirements § 2 (1) 1 and § 2 (1) 3) and furthermore have little safeguards to ensure that they do not include harmful code (c.f. § 2 (1) 5).

Section 2.7

That created enough tension that they felt the need to explain themselves in a blog post. To be fair: their concerns are broader than mine. Copyright status and license laundering are legal problems, and I am not going to discuss all of those in a blog post.

Why the mistrust?

One of their arguments is squarely a technical one:

"little safeguards to ensure that they do not include harmful code"

"without any meaningful human oversight"

That is the part I want to talk about, because it is the part we control.

It all comes down to one question: "Who built this code? Really you, or the AI provider you used?"

And that's a really good question because more and more developers are quietly pushing the weight of responsibility onto the AI. And that transfer does not actually work. Accountability requires someone who can be held to it. The model does not get paged at 3am. It does not sit in the retro when customer data leaked. It does not lose a client, get sued, or have to look a colleague in the eye and explain why production was down for six hours. It has no stake in the outcome, which means it cannot carry responsibility for the outcome — no matter how confidently it writes.

So the responsibility never actually moves. It stays with you. The only thing that moves is your awareness of holding it.

That gap is what the mistrust is really about. When someone reads your merge request, they are not asking "was a model involved?" They are asking "did anybody with something at stake actually check this?"

How do we maintain trust?

Does this mean I argue against using AI? Definitely not. But if the answer to "who built this code" is only "AI did", that is not trustworthy. If it ends with "...and I tested it, read it, and verified that it does what it should", the trust comes back — because now there is a person attached to the claim.

So verification of code must be the discipline that is our first-class skill.

But that is a nice sentence and it forces exactly nothing. Even in professional environments, developers get away with pushing code that nobody but a model has ever read or run. There is no license board for this and no inspector coming. So what does it actually mean in practice?

1. You cannot verify against nothing

Verification is a comparison. You compare what the code does against what it was supposed to do. If the second half of that sentence only exists as a vague feeling in your head, you are not verifying — you are reading code and nodding.

So it starts before any code exists, with how you write the ticket. Mine contain three parts:

  1. Current situation — Where are we? Which part of the software are we talking about? This already scopes the blast radius of the change.
  2. Problem statement — And I mean a real one. Not "yeah, that's a problem." Fill in the sentence: "X is the problem, and it is a problem because Y." If you cannot finish it, you do not have a ticket yet.
  3. Solution — This one varies, because it depends on how much I actually care about the how. Do I have a concrete technical expectation, or do I just want the problem gone? The answer decides what goes here. What almost always helps: acceptance criteria that state the behaviour you expect to see.

Those acceptance criteria are the thing you verify against later. Write them badly and every step after this one is theatre.

2. Don't let the judge judge their own case

Remember when the tests folder of a hobby project — or, let's be honest, a client project — was nearly or completely empty? Some of us were passionate test-driven developers chasing 100% coverage, most of us were somewhere in the middle.

One of the first things AI changed is that those empty folders filled up. Which sounds like a straight win. But look at what actually happened: the model wrote the code, then wrote tests for what it believed the code should do. Its own expectations, checked against its own implementation, both green. That is the judge ruling on their own case, and a passing suite is exactly what you would expect either way — whether the behaviour is right or the misunderstanding is just consistent.

Christoph Rumpel put it well in one of the videos on the Laravel YouTube channel:

If you are a skilled agentic coder, you let AI write tests and that's easy. But if you really want to influence the quality of the output, writing the test yourself first is the way to go.

His point after that: as tools like Claude Code and OpenCode become essential to our workflow, TDD is what keeps our intentions explicit instead of inferred.

You do not have to go full TDD on everything. But the test that matters most — the one encoding the behaviour from your acceptance criteria — should be written by the person who is accountable for that behaviour.

3. Actually run it

This is the step that gets skipped most, and the one nobody admits to skipping.

A green suite is not evidence that the feature works. It is evidence that the assertions you wrote pass. The gap between those two things is where the embarrassing bugs live: the button that does the right thing but is off-screen on mobile, the migration that works locally and locks a table in production, the API call that succeeds and returns the wrong currency, the email that sends and renders as raw HTML in Outlook.

So open the browser. Click the thing. Run the command. Send the request. Look at what actually landed in the database. It takes two minutes and it is one of the best verification steps available to you, because it is the only one that checks the whole path instead of the parts you thought to assert on.

If you did not run it, you did not verify it. You reviewed it.

4. Four eyes are better than two

In the hype phase of AI we all preached code review. And then, as results got better, it quietly became a ceremony. Open the diff view, scroll, "looks fine", merge. The unspoken justification is that the model's failure rate keeps dropping, so the review can shrink to match.

Two problems with that.

First, the premise is shakier than it feels. DORA's research points the same way two years running. The 2024 report found that AI adoption "significantly increases individual productivity, flow, and job satisfaction" but that "it also negatively impacts software delivery stability and throughput." The 2025 report found the throughput problem had resolved — teams genuinely do ship faster now — while the stability problem had not: more change failures, more rework. Faster output, same or worse defect rate. More code, produced faster, with review effort scaled down, is not obviously a lower-defect pipeline. It just feels like one, because the defects surface later and somewhere else.

Second, even if the premise were true, the conclusion does not follow. Imagine a food inspector at a processing plant reasoning like this: "90% of what I look at is fine. I can lower the effort and skip the next few inspections." Would you eat what comes out of that plant? The food industry genuinely does improve — better machines, better conditions, better processes. Nobody concluded from that improvement that inspection should stop. Why do we keep reaching the opposite conclusion in our industry?

And here is the uncomfortable difference: the food inspector is externally regulated. Somebody licenses them, audits them, and can take their job away. Nobody does that for us. There is no board revoking your right to merge. Which means this is the one form of quality control that only exists if we impose it on ourselves.

Conclusion

We are heading in a direction where development becomes faster and bigger every day, but at the same time it automatically introduces more bugs, more security holes, and more expectation mismatches shipped per week. The bottleneck moved. It used to be writing the code. Now it is knowing whether the code is right. Staying on top of that — and keeping the trust that lets us use each other's code at all — is a discipline, not a tool.

And none of that is new. That is sort of the point. What changed is that skipping it now scales.