AI-built apps arrive looking finished: working screens, smooth animations, and a confident "Done!" from the agent. None of that reveals whether the software actually does what it's supposed to do. Builders who can't read code have exactly one line of defense, and it's the same one professionals rely on: using the product deliberately and demanding evidence before trusting any claim of success.
This lesson turns that defense into habits. It separates running from working and working from correct, explains why an agent's success message carries no information by itself, and shows how defining success before building converts vague impressions into checks anyone can run. It closes with the case that real testing never required reading code in the first place.
What is verification?
Verification means confirming that software actually does what its builder intended, by using it rather than trusting how it looks. For someone who can't read code, verification is entirely behavioral: the builder interrogates the running product by clicking through it, feeding it inputs, and comparing what happens against what was supposed to happen.
The distinction matters because vibe coding removes the traditional safety net. A developer might catch a mistake while reading a diff; a non-coder never gets that chance. Anthropic's guidance for AI-assisted building states the fix plainly: "Give Claude a check it can run: tests, a build, a screenshot to compare" [1].
Not being able to read code doesn't excuse anyone from testing. It makes testing the only line of defense, which is why this lesson treats the running product, not the AI's narration, as the source of truth.
The happy path

The happy path is the ideal journey through a product: every input is valid, every step happens in order, and nothing goes wrong. A signup flow's happy path is a real email, a strong password, and one clean click on submit. It's also the only path most builders ever test, because it's the flow they built for and the one that delivers the demo dopamine.
Everything off that path splits into two families. Edge cases are rare but possible extremes, like a 400-character name or an enormous profile photo. Unhappy paths are ordinary behaviors the builder didn't plan for: submitting an empty form, hitting the back button mid-flow, or double-clicking a payment button. The second family is the dangerous one precisely because it isn't exotic; real people do these things constantly.
AI-generated code fails disproportionately off the happy path. Anthropic describes the typical output as "a plausible-looking implementation that doesn't handle edge cases" [2]. A build that survives only its happy path hasn't been tested; it's been demonstrated.
The trust-then-verify gap
The trust-then-verify gap is Anthropic's name for a common failure pattern in AI-assisted building: accepting output because it looks plausible, and verifying it only after something breaks. The pattern's official fix is blunt: "Always provide verification (tests, scripts, screenshots). If you can't verify it, don't ship it" [3].
The gap has a famous origin story. Andrej Karpathy's post that coined vibe coding described his own habit: "I 'Accept All' always, I don't read the diffs anymore" [4]. He scoped that habit to throwaway weekend projects, but the caveat traveled far less well than the habit did. Accepting everything feels productive because progress is instant and friction disappears.
The gap closes the moment anything matters: real users, real money, or real data. Verification doesn't need to happen after every prompt, but it must happen before trust, and shipping is an act of trust.
"Works" vs. "correct"
An app works when it runs and responds; it's correct when it does the right thing. Andrej Karpathy hit the difference while vibe coding MenuGen: he caught the AI matching Stripe payments to user credits by email address, an approach that runs perfectly and silently fails whenever a customer checks out with a different email than they signed up with [5]. Nothing errored, yet paying customers would've received nothing.
The gap between the two isn't closing on its own. Veracode found that as models improved at producing functional, syntactically valid code, they did not improve at producing secure code, with roughly 45 percent of generated samples introducing known vulnerability types [6]. Correctness also covers content: a New York Times columnist's vibe-coded shopping demo invented fake product reviews, so the app loaded fine while lying to its users.
The implication for verification is direct. An app that runs has passed the easiest test it'll ever face; checking correctness means checking outcomes, including what the app says, computes, and stores.
Pro Tip! Any build that touches money, credits, or scores deserves a manual check of the actual numbers before anyone relies on it.
When the AI says "Done!"
An AI agent's success message describes how the work looks to the agent, not how the software behaves. Anthropic states the mechanism directly: "Claude stops when the work looks done. Without a check it can run, 'looks done' is the only signal available, and you become the verification loop: every mistake waits for you to notice it" [7].
Product discovery coach Teresa Torres documented what accepting those messages looks like. Working in Replit, she described "an endless cycle of asking the agent to fix something and it would report back that it fixed it, even though it hadn't" [8]. The agent's claim carried zero information; only her own re-check did.
The habit that fixes this is demanding evidence instead of assurances: the test output, the exact command the agent ran and what it returned, or a screenshot of the result. An agent that really verified its work can show the receipts; one that can't produce them hasn't verified anything.
Defining "works" before building
Deciding what "works" means after seeing the output is grading on vibes. The alternative is writing success criteria before building, as concrete example cases in plain language. Anthropic's canonical illustration: instead of asking for a function that validates email addresses, specify the cases up front, such as "[email protected] is valid, invalid is not, [email protected] is not," then have the agent run those checks after implementing [9].
No code is required to make this move. Three sentences of the form "this input should produce that output" work for almost any build: a tip calculator, a signup form, or a document summarizer. Design taste can legitimately wait until the output appears; correctness never can, because an undefined "works" can't fail and every result looks like success.
Defined criteria also change what the agent does. Given a check it can run, the agent tests and iterates on its own instead of stopping at "looks done," which shrinks the number of mistakes that ever reach the human.
Breaking it on purpose
Trying to break a build is the fastest way to learn whether it deserves trust. A demo proves an app can work; a break-it pass probes whether it does work when treated the way real people treat software. AI output makes this pass more necessary, not less, because it arrives with real UI, smooth animations, and professional typography, so it looks shipped long before it's solid.
Break-it moves that need no code:
- Submit a form with every field empty
- Paste the wrong thing: letters in a number field, a huge block of text, an unexpected file type
- Hit the back button in the middle of a flow, then continue
- Double-click buttons that should only fire once
- Refresh the page right after an action and check what survived
Nielsen Norman Group's evaluation of AI prototyping tools found outputs that are "good from afar, but far from good": visually polished results that pattern-match common solutions while missing contextual requirements. Its guidance is to evaluate outcomes for usability and clarity, not visual polish [10]. Polish used to loosely signal effort and care; AI makes polish free, so it now signals nothing.
Pro Tip! Five minutes of deliberate sabotage catches bugs that an hour of happy-path demos never will.
Running without errors
A clean run is a precondition of working, not evidence of it. Error messages feel like the natural failure signal because, for the first few minutes of any build, they are: broken code that crashes announces itself immediately. That's exactly why Simon Willison argues that AI-generated code that crashes is the least dangerous kind of mistake, while the real danger lies in errors that no compiler, interpreter, or error message will ever surface [11].
Silent failures are the shape to fear. Karpathy's Stripe bug ran without a single error while setting up paying customers to receive nothing [12]. A summary tool can run cleanly while summarizing the wrong document; a calculator can run cleanly while rounding in the wrong direction. In each case the absence of errors reads as reassurance and means nothing.
The corrected mental model: "no errors" moves a build from broken to plausible. Only behavioral checks, comparing actual outcomes against intended ones, move it from plausible to verified.
Does testing require code?
Testing sounds technical, so non-coders often assume it sits behind the same wall as the code itself. It doesn't. The professional discipline at work here is manual quality assurance (QA), and it's behavioral from end to end: clicking, typing, probing, and comparing outcomes against intent. Simon Willison lists it among the human skills that AI amplifies rather than replaces: "Really good manual QA," including "predicting and digging into edge-cases" [13].
Designers and researchers already hold the adjacent skill. Usability testing asks whether people can understand and operate a product; verification points the same observational habit at correctness instead of comprehension. Watching for confusion becomes watching for wrong numbers, missing records, and states that don't survive a refresh.
Some practitioners argue verification itself is becoming the AI's job, with reviewer agents checking builder agents; Vercel's CEO framed the antidote to AI mistakes as more AI [14]. That position concedes the deeper principle: even the automation camp insists on an independent check, because the maker can't be the grader. Who runs the check will keep shifting; demanding one, and deciding what "works" means, stays human.
Topics
References
- Best practices for Claude Code - Claude Code Docs | Claude Code Docs
- Best practices for Claude Code - Claude Code Docs | Claude Code Docs
- Best practices for Claude Code - Claude Code Docs | Claude Code Docs
- Andrej Karpathy (@karpathy) on X | X (formerly Twitter)
- Vibe coding MenuGen | karpathy
- https://www.veracode.com/wp-content/uploads/2025_GenAI_Code_Security_Report_Final.pdf
- Best practices for Claude Code - Claude Code Docs | Claude Code Docs
- Context Rot: Why AI Gets Worse the Longer You Chat (And How to Fix It) | Product Talk
- Best practices for Claude Code - Claude Code Docs | Claude Code Docs
- Good from Afar, But Far from Good: AI Prototyping in Real Design Contexts | Nielsen Norman Group
- Hallucinations in code are the least dangerous form of LLM mistakes | Simon Willison’s Weblog
- Vibe coding MenuGen | karpathy

