AI

AFTER: Your Vibe Code Deserves Better

A methodology for AI-assisted development: Architect First, Test Everything Rigorously. One protocol file agents follow on contact, and a CLI that makes the human gates impossible to skip.

Posted on · by Naomi

The AI writes most of the code. The human makes every decision.

Architect First, because nothing gets generated before the decisions are made. Test Everything Rigorously, because nothing ships on trust. AFTER. The rest is implementation, and the implementation got out of hand in the best way: a protocol file that agents follow on contact, a Go CLI with approval gates you physically can’t skip, and enough surprises along the road that I stopped treating this as a personal quirk and started writing it down.

The honeymoon ends

Like most developers, I went through the honeymoon phase with AI coding tools. You describe what you want, code appears, it mostly works, and the velocity feels incredible. Then you come back two weeks later and realize you can’t explain half of what’s in your own repo.

The failure mode isn’t that AI writes bad code. It often writes decent code. The failure mode is that nobody made the decisions. The storage layer got picked by momentum. The error handling exists where the model felt like adding it. Security got the treatment that the average public GitHub repo gives it, which is to say, not much. And because everything arrived fast and mostly working, no one stopped to ask whether any of it was right.

I spent years doing enterprise compliance work, including a multi-tenant permission system where a single scoping bug would have meant one client seeing another client’s data. That background makes it hard to accept “it seems to work” as a quality bar. So instead of trusting the output less, I started structuring the process more.

Architect First, Test Everything Rigorously

The premise is economic: AI generation is cheap, human judgment is expensive. So the methodology spends the judgment where it counts, at the two ends of the workflow: before the code exists, and after it does. The acronym spelling an actual word is not an accident.

Architect First means no code is generated before the human has made the decisions that matter:

  • Every significant piece of work starts from a written specification: architecture, data schemas, API signatures, and a phased plan.
  • Technology choices are made by the human, with documented reasoning, before any generation begins.
  • Specs include an explicit constraints section covering the decisions an AI would otherwise drift from: storage choices, ID formats, forbidden dependencies, non-negotiable patterns.
  • Work is decomposed into self-contained tasks with acceptance criteria. Each prompt carries all the context it needs. Nothing relies on the AI remembering prior intent.
  • Project-level quality standards live in a standards file loaded into every session, so expectations are enforced structurally instead of repeated manually.

Test Everything Rigorously means nothing ships on trust. Generated output is treated as unverified until proven:

  • Tests are generated alongside production code, never after. Minimum per unit of logic: the nominal case, at least one edge case, at least one error case.
  • Generated code must be explainable line by line by the human. If a line can’t be explained, it doesn’t get merged.
  • Security-sensitive code gets flagged with explicit markers that force human review before merge.
  • Large efforts proceed in phases with human validation gates between them, and version control isolates each phase for safe rollback.
  • The final phase is adversarial: a devil’s advocate review against a checklist, validated by the human, before anything is considered done.

None of this is exotic. It’s what a disciplined senior team already does, translated into a shape that survives contact with an AI that produces code faster than you can casually review it.

Start with one file

Here’s the part that surprised me. While building the tooling, I noticed that agents start following the methodology simply because it’s named and structured in their context. I’ll come back to why, because the reason matters.

So the simplest deployment of AFTER is a single file, AFTER.md, written as direct instructions to the agent. Drop it into your project as a CLAUDE.md or AGENTS.md, paste it into your Cursor rules, or use it as a system prompt. It carries the operating rules (decision markers, assumption markers, tests with every change, output unverified until proven), the phase gates as conversational checkpoints where the agent must stop and wait for your approval, and four workflows covering the actual life of a codebase: greenfield, feature, debug, and refactor.

One of those workflows carries my favorite rule in the whole methodology, so I’ll spoil it now: in debug mode, no fixes are allowed until a failing test reproduces the bug. The failing test is the specification of the bug. The full walkthrough of all four workflows comes below.

One file, any interface, zero installation. For a lot of projects, that’s all the AFTER you need.

Why agents play along

There’s a reason the protocol works on contact, and the reason has little to do with me inventing anything. Models have ingested decades of software development culture: TDD, design docs, RFCs, post-mortems, code review etiquette, the scientific method applied to debugging. Every pattern AFTER formalizes already lives in the corpus, argued for by thousands of senior developers. So the protocol never has to teach a model that spec-first is good; the model already knows. What’s missing in a free-form conversation is a reason to act on it. Left unframed, an agent optimizes for what the conversation superficially rewards, which is producing plausible code quickly. AFTER flips that local reward. Inside its frame, the competent moves are stopping, asking, and writing assumptions down, because the protocol names them as the job.

The markers are the clearest example. DECISION_REQUIRED gives the model an honorable exit. Without it, an uncertain agent guesses, because guessing looks like competence and stopping looks like failure. With it, stopping becomes the competent behavior, with a name and a defined next step: hand the decision to the human. ASSUMPTION works the same way, giving uncertainty a sanctioned place to live instead of hiding inside confident prose. And this only gets better with time. Each model generation follows instructions more faithfully and reasons over protocols more reliably. A methodology that fights the nature of these systems ages badly; one that rides it appreciates.

Instructions erode. Structure doesn’t.

Here’s what I learned applying AFTER by hand, and it applies to the drop-in too: discipline that depends on memory erodes. On a good day the agent respects every gate. Twenty turns into a long session, or on a rushed day when you wave it forward, phases start blurring together. The methodology worked when it was followed, and the whole problem was the word “when.” That’s true for humans, and it’s true for a protocol living in a context window.

For the projects where that’s not acceptable, I built the discipline into a tool where the gates can’t be skipped, because they’re a state machine rather than a suggestion.

YVCDB: gates you can’t skip

YVCDB (Your Vibe Code Deserves Better) is an interactive CLI written in Go that orchestrates AFTER workflows on top of Claude Code, Codex CLI, or OpenCode. Where the drop-in file asks the agent to respect the gates, YVCDB makes them physical: a pipeline of specialized phases, each governed by its own embedded prompt, with a mandatory human approval gate after every single one. It implements all four AFTER workflows: greenfield, feature, debug, and refactor.

The OpenCode provider deserves a word, because it changes who can use this. Through OpenCode, YVCDB works with dozens of model providers, including free-tier APIs and fully local models via Ollama. That means complete AFTER workflows at zero cost, and on the local path, code that never leaves your machine. It also tests a claim I care about: a structured harness raises the floor. Watertight phase scopes, specialized prompts, and a human catching drift at every gate let modest models produce work you could never responsibly accept from them in a free-form conversation. Frontier models get a quality layer; cheap models get a path to being usable at all. That’s a testable claim, and I intend to test it properly in a follow-up: same specs, same workflows, free models against frontier ones, results measured rather than vibed.

The core design decision is an asymmetry. During a phase, the agent has broad powers: it can read, write, edit, and run commands inside its sandbox. Between phases, it has zero power. Every transition goes through a human decision in the TUI: approve, retry, send free-form feedback into a new iteration, or skip. The state machine makes it structurally impossible to advance without a human choice. You cannot forget AFTER while using it, because the tool won’t let you.

The four workflows split into two pairs. Greenfield and refactor are the big moments, a project’s birth and its rescue. Feature and debug are everything in between, which is to say, most of a developer’s actual week. One design note that says a lot: mode detection never guesses intent. An empty directory can only mean greenfield. Anything else, and the TUI asks you to declare what kind of work is about to happen (refactor, feature, or debug), because that’s itself a decision, and decisions belong to the human.

Greenfield implements the Architect First half literally. The first three phases are forbidden from generating product code at all. Phase 0 produces a specification document with goals, non-goals, acceptance criteria, and the constraints section. Phase 1 produces the architecture and the project standards file, and the prompt requires every technology choice to list the alternatives considered and the reasoning, in human-readable form. Phase 2 produces the plan: self-contained tasks, each carrying everything a fresh AI session needs, because each phase runs as a fresh subprocess with no conversational memory. Continuity lives in versioned documents, never in a chat thread. Code only appears in phase 3, and only the scaffold the approved plan calls for.

Refactor applies AFTER to a codebase that already exists, which usually means vibe code. The phase order is itself an argument: diagnostic first (strict read-only, understand before touching), then a safety net of smoke tests on the critical flows, then three passes with watertight scopes (security, structure, readability), and finally the adversarial review. A rule from the safety-net phase captures the philosophy: a test that fails on the current code is an existing bug to document, never something to fix right now. Each phase does one thing.

Feature is greenfield folded onto a living codebase. The same document phases before any code, but every document becomes a delta. The spec splits constraints into inherited and new, because the constraints of an existing project don’t get renegotiated by a new feature. The impact analysis updates the architecture document in place instead of replacing it, so the AFTER documents become the project’s long-term memory, each feature adding a layer. The plan requires every task to list the existing behaviors it could break, which makes regression risk a first-class property of the work rather than a late discovery, and a failure in the pre-existing suite is a blocker. The adversarial review ends on a question tuned to a documented anti-pattern of AI-generated code: does the feature integrate with the existing patterns, or did the agent quietly build a parallel mini-framework next to them? And there’s a stealth bonus in the scoping phase: pointed at a repo that has never used AFTER, it diagnoses the structure and conventions and bootstraps a light set of AFTER documents on the way in. You can adopt the methodology through your first feature, without a migration project.

Debug is the workflow I’d show a skeptic, because it turns the methodology into something close to scientific method. Four of its six phases forbid touching product code. It opens with a bug report artifact, and if no description was provided, the agent stops and asks instead of diagnosing thin air. Then reproduction: the smallest automated test that currently fails, executed and shown failing for the expected reason, before any theorizing. Then a read-only diagnosis that must trace to the root cause, consider alternative hypotheses, and rule them out explicitly, with the human approving the theory before a single line of product code changes. The fix phase is the only one allowed to modify code, constrained to the smallest change addressing the documented root cause. Verification then demands proof in both directions: the reproduction test passes with the fix and demonstrably fails without it, which guards against tests that pass for the wrong reasons. The adversarial review closes on the debug question: genuine root cause, or a symptom patch that masks the bug somewhere else?

A few mechanisms I’m particularly attached to:

Markers instead of silent guesses. Every session runs under injected operating rules: mark unfounded inferences with ASSUMPTION, flag auth/payments/permissions/personal-data code with REQUIRES_REVIEW, and stop with DECISION_REQUIRED when a consequential decision is missing instead of guessing. The adversarial phase then hunts for unresolved markers, and “no unresolved markers” is an item on the final checklist. The markers aren’t decoration; they’re the audit trail of everything the AI wasn’t sure about.

Git as the isolation layer. Snapshot commit before any work, one branch per phase, a commit per iteration so the history of retries is preserved, and worktrees with rebase and fast-forward merges for parallel stages. On a rebase conflict, the tool aborts the rebase, preserves the worktree for manual resolution, and stops with a report instead of pushing through. When something is ambiguous, the human decides. That rule applies to Git operations too.

The final verdict belongs to a human. Both workflows end with an adversarial review prompt playing a demanding senior developer who assumes the previous phases missed something. It has read-only access, must answer a checklist with justified YES or NO per item, and must return exactly one of three verdicts: ready, ready with explicitly accepted risks (each risk named and owned by the human), or not ready with conditions. And above that sits the last layer: a final quality checklist answered by the human, item by item, in the TUI. The ultimate validation is never delegated to the AI.

It built itself

YVCDB was built with AFTER. The specs, architecture decisions, and task decomposition were mine; the implementation was done by AI agents working as directed implementers, across three different harnesses: Claude, Codex, and, for the feature and debug workflows, a budget-tier agent (Devin Lite). That last one matters. The cheapest implementer on the roster delivered complete workflows in a concurrent Go codebase, because the specs it worked from left it no consequential decisions to fumble. It helped that the architecture keeps workflows as data: adding feature and debug meant roughly 360 lines, most of them prompts and tests, with zero changes to the orchestrator, the runner, or the git layer. The floor-raising claim from the OpenCode section has already survived contact with reality inside this very tool. CI rejects any coverage below 93 percent, and the test suite caught real race conditions and real deadlocks during development, which is about the most concrete evidence I can offer that the “Test Everything Rigorously” half earns its keep.

The tool that enforces the methodology is itself the methodology’s reference case. I like that the argument is circular in the way good bootstraps are: if AFTER couldn’t produce a four-thousand-line concurrent Go TUI I can explain line by line, I wouldn’t be writing this article about it. And the recursion doesn’t stop there: the blog you’re reading this on was integrated and published through an AFTER run, human gates included.

When to use it, when to skip it

AFTER won’t make AI code generation safe by magic, and it costs something: writing specs takes time, review gates interrupt flow, and on a throwaway prototype the overhead isn’t worth it. I scale it to the stakes. A weekend experiment gets vibe coded like anyone else’s; anything I intend to maintain, ship, or put my name on goes through the pipeline.

What it gives back is the thing I lost in the honeymoon phase: a codebase where every consequential decision was made by a person, on purpose, with the reasoning written down. The AI writes most of the code. The human makes every decision.

Both tiers are open source. The methodology and the drop-in protocol file live at github.com/Morialkar/after; the enforcement CLI lives at github.com/Morialkar/yvcdb. Start with the one file. If you want the full pipeline without spending a cent, point YVCDB at OpenCode with a local model. And if you try the refactor workflow on a vibe-coded repo, I’d genuinely love to hear what the diagnostic phase digs up.