Skip to content
Back to all field notes vibe · 7 min

Vibe coding vs AI-assisted engineering: the line that matters

Same tools, same models, same speed. The line between the two is not the code you generate. It is whether you accept it without verifying it.

vibe coding

  • accepts what runs
  • trusts the output
  • no contract
  • pays later

engineering

  • accepts vs a contract
  • shows evidence
  • contract up front
  • pays as it goes
Same tools, same models. The only line that matters is whether you accept the code on faith or against a contract.
field note 7 min

The term vibe coding started as a description of a genuine, useful thing: letting an agent write code while you steer on feel, barely reading the output, chasing an idea at the speed of conversation. Addy Osmani drew the useful distinction that has stuck with me, between that mode and something he calls AI-assisted engineering. Both use the same models and the same editors. They are not the same activity, and confusing them is behind a lot of grief.

I want to make that line concrete, because “engineering” can sound like a scold, like the answer is just to be more serious and write more tests. It is not about seriousness. It is about one specific thing you either do or do not do, and everything else follows from it.

The line is not where people think

People try to locate the difference in the wrong places, and each wrong location leads to a bad conclusion.

It is not the tools. The same Cursor session can produce either mode. It is not the speed. AI-assisted engineering is not slower vibe coding with more ceremony bolted on, and treating it that way just makes you resent the ceremony. It is not even whether you write tests, because you can write tests that prove nothing and still be vibe coding with extra steps.

The line is acceptance. Vibe coding accepts the generated code because it appears to work. Engineering accepts the generated code because it has been shown to meet a contract you defined. That is the whole distinction, and it is smaller and sharper than the usual framing suggests. One trusts the output. The other verifies it against something stated in advance.

Everything people associate with the two modes falls out of that single difference. Vibe coding feels fast and free because trusting is faster than verifying. Engineering feels more deliberate because a contract exists and the code has to clear it. Same generation step, different gate at the end.

Why vibe coding is not the enemy

I am not building toward “vibe coding bad, engineering good.” That framing is both wrong and useless.

Vibe coding is the right mode for a large and legitimate set of work. Exploring an idea, building a prototype to see if something is worth doing, throwaway scripts, anything where being wrong is cheap and learning fast is the goal. In that zone, stopping to define contracts and verify against them is pure overhead. You would be engineering a thing you are about to delete, which is its own kind of waste. The speed of trusting the output is exactly what you want when the stakes of the output are near zero.

The failure is not vibe coding. The failure is vibe coding past its expiry date: staying in trust-the-output mode after the output started mattering. That is the exact transition I try to map in going from vibe coding to production. The mode that was correct for the prototype becomes dangerous for the product, and nobody sends you a notification when you cross the line.

What changes when you cross

The moment the code starts mattering, the cheapest thing you can add is not tests or types. It is a contract: a statement, before the agent builds, of what the change must do and how you will recognize a correct result. That is the core of spec-driven development, and it is the smallest possible thing that turns vibe coding into engineering, because it gives acceptance something to check against.

With a contract in place, verification stops being vibes. “It works” becomes “it meets the contract, and here is the evidence.” Without one, even a passing test suite is just a more elaborate vibe, because the tests describe whatever the code happened to do rather than what it was supposed to do. The contract is what gives the word “done” any meaning at all.

This is also why the engineering mode is more expensive, and why that expense is the point. Defining the contract is real work. It is the work AI did not eliminate. Generating the code got cheap, so the scarce, valuable activity moved to deciding what correct means and proving the code meets it. In the engineering mode you are doing that scarce work. In the vibe mode you are skipping it, which is fine until it is not.

The two modes and the debt

The clearest practical difference shows up later, in what each mode leaves behind. Vibe coding accumulates debt in three layers, comprehension, verification, and architecture, precisely because nothing was verified against a contract as it went. Engineering pays a small cost up front, the contract and the evidence, and carries much less of that debt forward.

So the choice between the modes is really a choice about when you pay. Vibe coding defers everything to a future reckoning. Engineering pays a little continuously. Neither is universally right. On a prototype, deferring is correct. On a product, the deferred bill is the 90-day collapse everyone eventually meets. Knowing which mode you are in is knowing which payment schedule you signed up for.

And it explains a fear I have written about elsewhere. The reason people get scared to touch their own code is almost always that they stayed in vibe mode too long. There is no contract to check a change against and no evidence that anything works, so every edit is a leap. The fear is the felt experience of having accepted a lot of code without verifying any of it.

You are still the one deciding

Here is the part that neither mode removes. Whether you trust or verify, whether you vibe or engineer, you are the one making that call, change by change. The agent does not know if this code matters. It cannot tell whether you are prototyping or shipping. That judgment is yours, and it is the actual job now.

That is what I mean when I say you are the runtime. The agent generates. You decide which mode the moment calls for, define the contract when one is needed, and hold the line on evidence when it matters. The line between vibe coding and engineering is not drawn by your tools. It is drawn by you, every time you decide whether “it works” is enough.

Where PaellaDoc fits

The hard part of living on the right side of this line is that the contract and the evidence have to exist somewhere durable, or the engineering mode quietly decays back into vibe coding. A contract in a closed chat is not a contract. Evidence you did not keep is not evidence.

PaellaDoc exists to make the engineering mode the path of least resistance: a place to state the contract before the agent builds, a link from that contract to the code that implements it, and the evidence that it was met, held together locally instead of scattered. It does not stop you from vibe coding when vibe coding is right. It makes crossing into engineering cheap enough that you actually do it when the code starts to matter.

FAQ

Is vibe coding bad? No. It is the right mode for exploration, prototypes, and any work where being wrong is cheap. It becomes a problem only when you stay in it after the code starts mattering, which turns skipped verification into accumulated risk.

What actually separates vibe coding from AI-assisted engineering? Acceptance. Vibe coding accepts generated code because it appears to work. Engineering accepts it because it has been shown to meet a contract defined in advance. The tools, models, and speed are the same.

Do I have to choose one mode for the whole project? No. The mode is a per-change decision. Prototype a feature on vibes, then switch to engineering when that feature becomes load-bearing. The skill is knowing which the moment calls for.