Field guide

The vibe coding iteration wall is four walls, not one

Around prompt fifteen, your AI app builder starts breaking the project instead of fixing it. Layouts you liked are gone. The undo button gives you something close to, but not exactly, the version you remember. The agent keeps repeating a mistake you corrected three turns ago. That is the wall. It is real and it is the same wall everyone hits, but it is not one mechanism. It is four, and knowing which one is firing tells you what to do about it.

M
Matthew Diakonov
7 min
Direct answer (verified 2026-04-30)

Vibe coding iteration stops working when one of four things breaks: the model starts regenerating the project instead of editing it, the session state lives nowhere durable, the undo button is approximate instead of byte-exact, or the agent's conversation buffer fills with stale context. The four are independent. A given builder usually fails on one or two and holds up on the rest. The mk0r mechanisms that address each are named below with the file path you can read in source.

The four walls, side by side

Each wall has a tell, a root cause, and a mechanism that defuses it. The order below is roughly how often each one shows up in practice.

Wall 1 of 4

Regenerate, not edit

Tell: files appear or disappear between turns when you only asked for one small change.

mk0r mechanism: one persistent ACP session per sandbox, reused across every prompt with the same sessionId. The agent edits in place; the route never re-feeds the transcript. See src/core/e2b.ts line 909 onward for session reuse.

Wall 2 of 4

No durable state

Tell: a tab refresh, a phone backgrounding, or an idle timeout loses your project.

mk0r mechanism: real filesystem inside an E2B sandbox, real git repo at /app, every turn committed via commitTurn at src/core/e2b.ts line 1635, history stack persisted to Firestore.

Wall 3 of 4

Approximate undo

Tell: the undo button gives you something close to, but not exactly, the version that existed last turn.

mk0r mechanism: undo runs git checkout <sha> -- . and writes a new commit; result is byte-exact. See undoTurn at src/core/e2b.ts line 1731.

Wall 4 of 4

Stale conversation buffer

Tell: the agent repeats a mistake you corrected several turns ago.

mk0r mechanism: the agent has a memory system installed via /root/.claude/CLAUDE.md (built in src/core/vm-claude-md.ts) that instructs it to write feedback memories on every correction so they survive buffer pressure.

Why regenerate-not-edit is the most common wall

A lot of AI builders save your prompts as the durable thing and re-roll the project on each new turn. That is fine on prompt two. On prompt twelve the model is non-deterministic, the third turn lands on a sibling app, the seventh turn lands on a cousin, and by the twelfth you are debugging an app that does not match the prompt list you saved. The shape of one iteration in mk0r looks different on purpose:

Turn 12 of an iteration

You/api/chatACP in sandbox/app on diskPOST prompt + sessionKey/session/prompt (same sessionId as turn 1)edit specific files (write_file, apply_patch)diff lands on existing treestream tokensgit add -A && git commit -m '<prompt>'version event { sha, message }

The agent is the same agent across turns. Its conversation buffer, its working directory, the git repo on disk are all stateful. The only thing the route adds at the end is the commit. That is what 'editing' as opposed to 'regenerating' looks like in plumbing.

The undo wall, byte by byte

The version sidebar lists every commit. Click Undo and the client POSTs to /api/chat/undo, which calls undoTurn. That function picks the SHA at historyStack[activeIndex - 1] and runs a tiny revert primitive: git checkout the target SHA, stage everything, write a new commit with --allow-empty. The new HEAD has a fresh SHA whose tree matches the target. Old commits stay reachable in git log. The model is not consulted at all.

What happens when you click Undo

The tool drops the latest user prompt, replays the older transcript, and asks the model to produce the project again. Output drifts because sampling is non-deterministic. Files appear and disappear. The 'undo' is approximate, never exact.

  • Result depends on the model's sampling that turn
  • File structure can shift
  • No way to point at the bytes that existed before

The fork-on-undo rule (one line)

The undo behaviour is half the story. The other half is what happens when you undo a few times and then submit a new prompt. The future you abandoned has to go somewhere. mk0r answers that with one line at src/core/e2b.ts line 1676:

if (
  typeof session.activeIndex === "number" &&
  session.activeIndex >= 0 &&
  session.activeIndex < session.historyStack.length - 1
) {
  session.historyStack = session.historyStack.slice(
    0,
    session.activeIndex + 1
  );
}
session.historyStack.push(sha);
session.activeIndex = session.historyStack.length - 1;

If the active pointer is anywhere except the tail when a new commit lands, drop everything past it, then push. This is how editors handle undo. It is not how most AI builders handle it; a lot of them keep both branches alive with no clear current pointer, which is why iteration starts feeling weird around turn fifteen.

Five turns, with one fork on turn 4

The conversation-buffer wall

The persistent ACP session is a feature on turn three. By turn forty it is a liability, because the conversation buffer is now carrying every false start, every reverted detour, every "no, not like that" you wrote since the start of the day. The model has to weigh older corrections against newer ones, and it does not always pick correctly. The mitigation is a memory layer outside the buffer.

Where stale context goes when buffer pressure rises

1

Conversation buffer

Every prompt and every tool call from turn 1 onward, in order. Pressure rises with each turn.

2

Built-in memory

Agent writes feedback memories on every correction. CLAUDE.md instructions for this live in src/core/vm-claude-md.ts.

3

Project CLAUDE.md

Per-project file at /app/CLAUDE.md captures key design decisions and constraints the agent should not relearn.

4

Git log

Every commit is a labelled snapshot of what existed when. The agent can revert to a known-good SHA without re-deriving why.

The four together are the answer to "what does the model know across turns?" The buffer is fast but lossy. Memory is slow but durable. CLAUDE.md is the agent's own memo to itself. Git log is the bytes that existed. When the buffer wall arrives, it usually shows up as an old mistake repeating; the fix is to ask the agent to read its memories, or to save the correction explicitly so it survives the next buffer compaction.

What this honestly does not solve

Three real limits worth saying out loud.

  • Anonymous sessions live on one browser. The session key sits in localStorage. Clear storage and the history is unreachable from the UI even if the underlying repo is briefly still on disk. Signing in moves the key onto your account so it survives device changes.
  • Undo does not unwind the conversation. git checkout rolls back the bytes. The agent's conversation buffer keeps growing across undo and redo, so an "undo, then ask again" can produce a similar attempt at the same fix. A fresh prompt that explicitly redirects works better than retry.
  • The wall does not vanish; it moves. All four mechanisms above push the wall further out, not forever. At some point the requirements (real auth, multi-user real-time state, complex backend invariants) outgrow the HTML/JS-or-Vite envelope mk0r generates into. That is the honest exit point to writing code by hand. It is not the iteration wall; it is a different wall.

Want to walk through the iteration mechanics on your own build?

Happy to compare how mk0r handles the four walls against whatever AI builder you are evaluating. 30 minutes, no pitch.

Frequently asked questions

What is the vibe coding iteration wall, in one sentence?

It is the moment when you have prompted an AI app builder ten or twenty times and every new prompt makes the project worse instead of better. The first prompt produced something close to what you wanted. The next few were fine. Now the model is rewriting things you did not ask it to touch, the layout you liked is gone, and undo brings back a version that does not quite match what you remember. The wall is real. It is also not one phenomenon. Four different mechanisms can produce it, and once you know which one is firing you can route around it.

Why does the AI keep regenerating things instead of editing them?

Because most builders treat your prompt list as the source of truth and re-roll the project from it on each turn. If 'a habit tracker, then add streaks, then make the streak page red' is the saved transcript, the third turn is feeding all three prompts back to the model and asking for a fresh app. The model is non-deterministic, so the file structure shifts between rolls. mk0r does not work that way. The agent runs inside one persistent ACP session that lives for the lifetime of the sandbox; the conversation buffer and the working directory carry forward. The route at src/app/api/chat/route.ts hands each new prompt to the same sessionId, and the agent edits files on disk in /app instead of producing the project again. You can read the session-reuse logic in src/core/e2b.ts around line 909.

What if I refresh the tab mid-iteration, does my project survive?

Yes, in mk0r. The project lives on a real filesystem inside an isolated E2B sandbox, not in browser memory. Every turn writes a real git commit to /app via commitTurn (src/core/e2b.ts line 1635), and the resulting SHA is appended to session.historyStack and persisted to Firestore via persistSession. A tab refresh reattaches to the same sandbox using the session key in localStorage; if the sandbox itself was paused or reaped, the next reattach restores the repo to the head SHA from Firestore. The whole point of putting state on disk and writing it through a version-control primitive is so a refresh, a tab pause, or a Cloud Run restart cannot desync the project from what the model thinks exists.

Why is undo so unreliable in most AI builders?

Because they implement undo as a re-prompt. The tool drops the last user message from the saved transcript, replays the older prompts, and asks the model to produce the project again. The model is non-deterministic, so the 'undone' project is not the project that existed before. File structure shifts. Components reappear. Sometimes new bugs arrive. mk0r does undo as a git checkout. The undoTurn function at src/core/e2b.ts line 1731 reads historyStack[activeIndex - 1], runs git checkout <sha> -- . inside the sandbox, stages, and writes a new commit with --allow-empty. The disk state is byte-exact to the previous turn. The model is not consulted. Zero token cost, zero variance.

What about the moment I undo three times and try a different idea, does the abandoned future come back to bite me?

No. mk0r forks the history. The slice at src/core/e2b.ts line 1676 reads historyStack = historyStack.slice(0, activeIndex + 1), then pushes the new SHA. In English: if the active pointer is anywhere except the tail when a new commit lands, drop everything past it. This is how editors handle undo. It is not how most AI builders handle it; a lot of them keep both branches alive with no clear current pointer, which is why iteration starts feeling weird around turn fifteen. The slice is one line. It is the difference between trying a new direction and being scared to branch.

Does the agent's conversation buffer just keep growing forever?

It grows, but the agent is set up to compensate. The CLAUDE.md installed at /root/.claude/CLAUDE.md inside the sandbox (built in src/core/vm-claude-md.ts) tells the agent to actively write and update memories whenever the user states a preference, corrects a mistake, picks a color scheme, or makes a key design decision. When the buffer gets long and earlier turns fade, the memory file is what keeps the project's intent stable. The default model is Haiku (set on src/lib/acp-chat-store.ts line 191 and re-applied to the session at src/core/e2b.ts line 1275), which has the largest practical headroom on a fixed token budget; that means more iterations before the conversation pressure starts to matter at all.

How can I tell which wall I am hitting before the project is unrecoverable?

Each failure mode has a tell. If the file structure changes between turns when you only asked for one small edit, you are hitting regenerate-not-edit; switch to a tool that holds a real session. If a refresh or a tab pause loses your work, the project state lives nowhere durable; switch to a tool that writes to disk. If the undo button does not bring back the exact bytes that existed last turn, undo is approximate; switch to a tool that uses git checkout. If the agent keeps repeating mistakes you already corrected, the conversation buffer is full of stale context and the agent has no memory layer; ask the agent to read its memories or save the correction yourself. mk0r's symptom set is mostly the fourth one because the first three are foreclosed by the architecture.

Is there a point where I should stop vibe coding and write code by hand?

Yes, and it is not when the wall arrives. It is when the thing you are building genuinely needs production-grade auth, multi-user real-time state, payments, complex data invariants, or a backend story more sophisticated than a single Postgres or a couple of Resend audiences. mk0r generates working HTML/CSS/JS or a Vite + React + Tailwind project; the iteration model holds up well within that envelope. The honest exit point is when the requirements outgrow the envelope, not when iteration starts feeling slow. If iteration is the only thing breaking down, the fix is usually mechanical (clearer prompts, smaller scope per turn, a revert to a known-good SHA) rather than rewriting the project by hand.

Does mk0r need a signup to test this?

No. Open mk0r.com, type a prompt, and you are anonymous Firebase user. The session key lives in localStorage, the sandbox is provisioned on first prompt, and every turn writes a commit to a private repo provisioned to that anonymous identity. Signing in later attaches the same session key to your account so it survives device changes; before then, your work is reachable from the same browser as long as you do not clear storage. The whole iteration model runs without an account, which is what 'no friction' means in the marketing.

mk0r.AI app builder
© 2026 mk0r. All rights reserved.