LE
LOKI
EVOLVED
Back to The Signal / Home
PILLAR / B1

Vibe coding with judgment: directing a coding agent without losing control

Vibe coding is sold as typing in plain language and watching an app appear. In practice it is directing: you define the problem, the agent writes, you verify. The gap between a useful shortcut and a silent disaster lies in what you do before and after you ask.

By Yenny Astrid Londoño MonrroyReviewed

Key Takeaways of this Analysis

  • Vibe coding does not eliminate engineering: it moves the work to whoever is directing.
  • If you cannot describe the scope in one page, the agent will invent the rest.
  • A specification without acceptance criteria is a suggestion.
  • Review the diff as if a stranger in a hurry had written it.
  • Every shortcut you do not document becomes debt that you pay.
  • If you have gone round twice with the same error, the problem is the context, not the attempt.

Vibe coding is sold as typing in plain language and watching an app appear. In practice it is directing: you define the problem, the agent writes, you verify. The gap between a useful shortcut and a silent disaster lies in what you do before and after you ask.

What vibe coding is and what it is not

Vibe coding means delegating the writing of code to a model, with feedback in natural language, accepting that you will not read every line in the moment. It is a decision about where you put your attention, not an excuse to switch it off.

What it is not: programming without knowing how to program, prototyping with no direction or accepting everything because the tests pass.

The distinction that matters is where the code is going. A prototype can be thrown away: if the error shows up in two minutes, a botch costs little. Production code has a different contract: someone will maintain it and debug a failure at three in the morning. Probably you.

There is an asymmetry almost nobody mentions. Vibe coding works best where errors show up quickly (a screen, a script, a query on a sample) and worst where they are silent: permissions, payments, dates, concurrency. That asymmetry, not fashion, should decide where you use it.

The right order: scope, specification, data, build, verify

The order is what separates directing from reacting.

  • Scope: one sentence describing the outcome and a list of what is out.
  • Specification: states, data and acceptance criteria.
  • Data: the data model before the screen.
  • Build: small blocks, one goal per block.
  • Verify: test and diff before moving on.

When you start by building, the agent decides the product for you and hides it in the code. It chooses names, states and edge cases without telling you. Two hours later you have an app that works and is not the one you wanted.

Data comes first because the data model reveals requirements that prose hides. If a booking can be cancelled, you need an intermediate state, a date and a rule about who can do it. That does not appear in "build me a booking app". It appears when you write the columns.

How to write a specification the agent can execute

A useful specification is not a creative brief: it is an acceptance contract with enough context that nothing has to be guessed.

Minimum content:

  • The expected outcome in one sentence.
  • The files and areas of the repo it may touch.
  • The data contract: fields, types, required or optional, valid states.
  • Acceptance criteria that can be checked.
  • Limits: what not to install, what not to modify, what not to invent.
  • An example of input and output, and how it is verified.

An example for a payment form: "Accept card and bank transfer. Card requires holder, number and expiry date; transfer requires IBAN and holder. Do not invent fields. If a field is missing, show the error next to the field, not an alert. A failed submission does not clear the form. The test covers both methods and one failure."

The part most often forgotten is the states: agents fail more from ambiguity than from logic. If you do not define what pending, confirmed and cancelled mean, the agent will invent a transition and hide it.

An agent does not guess what you did not write: it invents it and hides it.

Ask for the plan before the code: ten lines can be corrected in a minute; a diff across four hundred files takes an afternoon.

Reviewing code you did not write

Reviewing is not reading. It is looking for what the agent did not say.

  1. Read the whole diff once without stopping. Look for the shape of the change, not the details.
  2. Go back to the risk areas: authentication, money, dates, queries, migrations.
  3. Follow the data flow from input to output. That is where lost fields and swallowed errors show up.
  4. Look at the tests. A test that only checks that the function does not crash proves nothing.
  5. Check what ended up outside the scope: new dependencies, global configuration, files nobody asked to touch.

You can ask it why it made a decision. Use that to understand its reasoning, not as proof: its explanation is just more generated text. The truth is in the code.

Warning signs:

  • A new dependency with no justification.
  • An empty catch or errors turned into null.
  • Logic duplicated in two files that should share a function.
  • Changes to global configuration to make a test pass.
  • Names that do not match the domain: booking, slot and seat used as synonyms.
  • A large diff for a small request.

Invisible debt

Normal debt is visible: it is in the backlog and has a ticket. Invisible debt is not: it accumulates with every change accepted without reading and gets paid when someone has to change something.

It shows up in three ways: nobody knows why a function exists, a one-hour bug takes a day, and the next prompt relies on false assumptions. The project looks healthy as long as you do not touch it.

A partial antidote: one line for every non-obvious change. Why this state, this table, this library. And a hard rule: code you do not understand does not stay. It gets rewritten, reduced or documented until you understand it.

When to switch off the agent and write it yourself

Vibe coding is not a moral obligation. There are tasks where the agent is the worst tool available.

  • Internal CRUD screen. Mode: agent. Why: the error shows up when you open the page.
  • One-off script. Mode: agent. Why: disposable, no maintenance.
  • Data migration. Mode: agent with a sample. Why: it can be verified with counts and totals.
  • Payment form. Mode: mixed. Why: you define the structure; the agent fills it in.
  • Permissions and roles. Mode: by hand. Why: an error does not show up until someone gets in where they should not.
  • Concurrency bug. Mode: by hand. Why: the agent tends to patch the symptom.
  • Structural refactor. Mode: plan by hand, assisted execution. Why: the agent loses the map of the repo.

There is one signal: if you have gone round twice fixing the same error, stop. The loop means the agent does not have the right context, not that it needs another attempt. Changing the prompt without changing the context produces the same failure.

Stop when the change is smaller than the explanation: twenty lines in the editor are faster and safer than a paragraph asking someone else to write them.

Minimum security: secrets, permissions, data

  • Secrets: never in the prompt or the repo. Use environment variables and check that the agent does not write them to logs or hard-code them in configuration.
  • Permissions: the agent works with local credentials and fake data. Never with access to production.
  • Data: do not paste customer data into the chat. Anonymise it or use fixtures; whatever goes into a prompt leaves your control.
  • Dependencies: every install is attack and maintenance surface. Demand a reason.
  • Destructive actions: no mass deletions, migrations or force pushes without human confirmation.
  • Output: the agent can invent endpoints and fields. Verify against the real documentation, not against its answer.

The risk is not a malicious agent, but a convincing and wrong one. An invented endpoint with a plausible name gets through review if you do not check it.

A realistic weekly workflow

A workflow that does not turn the week into a demo:

  • Monday: scope and specification for one single thing. Thirty minutes, not three hours.
  • Tuesday and Wednesday: build in small blocks, verifying before moving on.
  • Thursday: diff review, tests and cleaning up anything left half-done.
  • Friday: document decisions and rewrite by hand whatever turned out odd. One hour, no exceptions.

No more than two open fronts: the agent loses context and so do you. At the end of the day, note what was left unreviewed. If the list grows three days in a row, Friday pays for it.

Judgment is not in the prompt. It is in what you accept.

Keep reading

ARTICLE PROMPT / TEMPLATE
Act as a senior engineer on this repo. Before writing any code:
1. Summarise the scope in five lines and list what is out of scope.
2. Point out the files you are going to touch and the acceptance criteria.
3. Wait for my confirmation. Do not install dependencies or touch configuration.
If something is unclear, ask instead of assuming.
LOKI EVOLVED RESEARCH HUB