termroam
TermRoam · field guide

From vibe prompts to specs

An AI coding agent doesn't know what you meant — it knows what you typed, and it fills every gap with the most plausible-looking completion. This page teaches the difference between a prompt and a spec: the four ingredients that turn a hope into something checkable, why five small steps beat one big one, and the checklist pattern that lets an agent work through a real feature without you watching every keystroke.

01

Why "make the dashboard better" fails structurally

An agent generates the next token that best continues everything it has seen — your prompt, the code it can read, and its training. Given a checkable target, that process converges on a checkable answer. Given "make the dashboard better," there is no target to converge on, only a direction. The agent still has to produce something, so it produces the most statistically plausible reading of "better dashboard": probably more whitespace, probably a card layout, probably a color it picked. It is not guessing lazily — it is doing exactly what it was asked, which was to guess.

Three things go wrong at once, and they compound:

None of this is a model failing to understand you. It understood "make it better" perfectly — that phrase simply does not encode a decidable outcome. The fix is not a smarter agent; it's a prompt that does encode one. That's what a spec is.

The mechanism to remember: an agent optimizes for a plausible-looking completion of whatever you actually wrote — not what you meant, not what you'd have said with more time. Vague input reliably produces a plausible-but-wrong output, because "plausible" was the only instruction it was given.
precision notes — why "plausible" and "correct" collapse into one signal

This is a simplified but accurate mechanism, not a claim about any specific model or vendor. Coding agents are trained to produce output that scores well against human preference and, where available, automated checks (tests, linters, compiler errors). When a prompt supplies a checkable target — a failing test, a stated acceptance criterion — "scores well" and "is actually correct" point at the same thing, and the model has a signal to aim at. When a prompt supplies no checkable target, "scores well" collapses to "looks like a good answer to a person skimming it," which is a much weaker property than "does what you needed." The gap between those two is exactly the gap a spec closes.

02

The anatomy of a good brief

A spec is not more words. It is four specific ingredients layered onto the same request, each one closing off a different way for the agent to guess wrong:

Goal.One or two sentences naming the outcome from the user's side, not the implementation. "Returning users can log in and reach their saved data" — not "add an auth library." The goal is the thing you'd check first; everything else narrows how to get there.
Constraints.The boundaries the solution must respect: existing schema, no new dependencies, a performance budget, a deadline, a library you've already standardized on. Constraints don't say what to build — they eliminate entire categories of plausible-but-unwanted answers before the agent considers them.
Acceptance criteria.Observable, checkable statements — sentences with a yes/no answer a stranger could evaluate without reading your mind. "Wrong password returns 401 with an inline error" is acceptance criteria. "Login should feel secure" is not, because nothing can check it.
Non-goals.What you are explicitly not asking for this time. Capable agents scope-creep toward anything adjacent that looks thorough — password reset, 2FA, "while I'm in here." Stating non-goals is the only thing that reliably stops it, because omission reads as an opening.

Try it below. The prompt on the left never changes — it's the same four words a person actually types. Add ingredients on the right and watch the simulated agent's outcome narrow from a plausible guess to something you could actually sign off on.

the transformer — same prompt, growing spec

what you typed

"add auth to my app"

spec (click ingredients above)

nothing added yet
agent outcome: plausible guess
Click an ingredient to add it to the spec — any order. Each one removes a specific way the agent could guess wrong; the narration explains which one.

Notice what each ingredient removes, not just what it adds. The goal removes ambiguity about the target. Constraints remove ambiguity about approach. Acceptance criteria remove ambiguity about what "done" means. Non-goals remove scope the agent would otherwise add on its own initiative. Steps — the fifth ingredient, covered next — remove ambiguity about order, which turns out to matter as much as the other four.

03

Small verifiable steps beat one heroic step

A spec can be perfectly written and still fail in execution if it asks for the whole feature in one motion. The unit that actually matters is the step: an imperative verb plus a check. "Add a login endpoint. Check: a correct password returns 200 and a wrong one returns 401." Not "build the auth system" — that's a goal wearing a step's clothes, still unbounded, still unverifiable until the very end.

The payoff of small steps isn't tidiness. It's where a failure lands. When a five-step feature breaks on step 3, steps 1 and 2 are already committed, already correct, and already out of the blast radius — see how git makes committed work durable. Only step 3 needs attention, and its diff is small enough to read in one pass. When a one-step feature breaks, everything is suspect at once: the migration, the endpoints, the middleware, and the UI are one undifferentiated block of uncommitted change, and nothing in the history tells you which part is wrong.

same feature, one giant step vs. five small ones — watch step 3 fail

1 giant step

Implement the entire auth feature in one uninterrupted pass. Nothing lands until it's all done.

5 small steps

1. users migration + hash column
2. POST /signup + test
3. POST /login + test
4. session middleware on /dashboard
5. POST /logout + test
Same feature, run two ways. Press start.
precision notes — why "commit-sized" is the actual unit

A step is sized correctly when its check can pass or fail on its own, independent of later steps. That's what makes it committable: a commit that passes its own check is safe to leave in history even if step 4 later turns out to need rework. This is the same property that makes git bisect useful for human-written history — a tight sequence of independently-correct commits localizes a bug to one of them by binary search. Steps sized for an agent should have the same property on purpose, not by accident.

04

The PRD pattern for bigger features

Once a feature needs more than two or three steps, write them down as a checklist before the agent starts — a short PRD (product requirements doc), just markdown. The agent works through it top to bottom: read the next unchecked box, implement it, run its check, commit, tick the box, move to the next one. The whole spec, plus which steps are already done, lives in one file the agent can re-read at any point — including a fresh session that has no memory of the last one.

prd.md — a checklist an agent can execute unattended
## Add email/password auth
Goal: returning users log in and reach their saved dashboard.
Constraints: existing users table, no new dependency, 14-day sessions.
Non-goals: social login, password reset, 2FA — later specs.

- [x] 1. users migration + password_hash column. Check: migrates and rolls back clean on a scratch db.
- [x] 2. POST /signup — hash + store. Check: new email returns 201; duplicate returns 409.
- [ ] 3. POST /login — verify + session cookie. Check: correct password → 200 + Set-Cookie; wrong → 401.
- [ ] 4. Session middleware guarding /dashboard. Check: no cookie → redirect; valid cookie → loads.
- [ ] 5. POST /logout — clears session. Check: cookie cleared; /dashboard redirects again.

Two boxes are already checked in the example — that's the point of the pattern, not an accident. Each checked box is a real commit that already passed its own check; an agent resuming this file (or a person reviewing it) can trust everything above the first unchecked box without re-verifying it. Bigger features are just longer versions of this same list — see running several of these checklists across agents without them colliding.

Keep the goal, constraints, and non-goals at the top of the file rather than repeating them per step. They apply to every step equally, and a single shared statement is easier to keep consistent than five slightly different restatements that drift apart as the checklist grows. The per-step lines should be narrow by comparison — an imperative verb and a check, nothing more. A step that needs a paragraph to describe is usually two steps that haven't been split yet.

05

Review gates — and letting the agent ask first

A spec doesn't remove the human from the loop; it tells the human exactly where to stand. Three places are worth actually looking, in this order:

The other half of the gate happens before any code is written: let the agent ask clarifying questions against the spec, and answer them, before it starts. A well-formed spec makes most questions unnecessary by construction — that's what acceptance criteria are for — but the ones that surface are usually the exact ambiguity that would otherwise have been silently guessed. "Should the 401 on wrong password happen after 1 attempt or should there be lockout?" is a five-second answer now and a rebuilt endpoint later.

A question is cheaper than a guess. Every clarifying question an agent asks up front is a plausible-guess branch that never got built and never needed reviewing.

Where you place the gate matters as much as that it exists. A gate at the end of the whole feature only tells you something went wrong, not where — you're back to reading an undifferentiated diff, the same failure mode small steps exist to avoid. A gate after every step keeps each review small enough to actually do carefully instead of skimming, and it catches a wrong assumption after one step's worth of wasted work instead of five.

06

Definition of done: "tests pass," not "I changed the code"

Without acceptance criteria, "done" defaults to the only signal an agent actually has: it produced output and stopped. That's a claim about effort, not correctness — the code changed, which is not the same statement as the feature working.

Weak definition of done: "I edited the login handler and the file compiles." True, and irrelevant to whether login works.
Strong definition of done: "The step's check passes: correct password returns 200 with a session cookie, wrong password returns 401 with an inline error, and both are covered by a test that runs in CI." Checkable by anyone, including a different agent.

Push this all the way down to the step level, not just the feature level. A five-step PRD where only the final step has a check still leaves four steps where "done" means "I changed the code" — exactly the failure mode small steps were supposed to close. Every step needs its own check, or it isn't a step yet; it's an unverified hope with a number in front of it.

The test itself has to earn its place, too. A test that only asserts the endpoint returns a status code, without asserting which one, will pass whether login works or not — it satisfies "tests pass" while proving nothing about the acceptance criterion it's supposed to check. Definition of done is only as strong as the weakest check standing behind it, which is why the review gate in the previous section includes reading the tests, not just running them.

07

How this compounds: specs are documentation for the next session

A spec written for today's agent doesn't expire when the task finishes. Committed to the repo, it becomes a record of what was actually asked for, what was explicitly excluded, and how "done" was defined — read by the next agent session that touches the same code, whether that's tomorrow or six months from now with a different model entirely. That session doesn't start from the vague memory of a Slack message; it starts from a checklist with acceptance criteria already written down, the same way it would read whatever standing context file your agent loads at the start of a session.

This is also why non-goals matter beyond the immediate task: a future agent reading "no password reset in this spec" understands that the omission was a decision, not an oversight, and won't quietly "fix" it by adding scope nobody asked for. A spec without non-goals looks, to a later reader, exactly like a spec that forgot something. A repo with a habit of small, checked, spec-driven steps ends up with a history that reads like documentation — because it effectively is: each commit message and its originating spec together answer "why is this code like this?" without anyone having written a separate wiki page. Compare that to what a coding agent actually does with each instruction it receives — the loop only produces that kind of trail when the instruction it started from was checkable in the first place.

08

How TermRoam handles this

TermRoam's execute workflow is built around this exact pattern: you write a spec as a PRD, a validator machine-checks that every step has an imperative verb and a verifiable acceptance criterion before anything is allowed to run, and a resident agent loop works the checklist step by step — implement, check, commit, push, tick the box, repeat — so the definition of done on this page is enforced structurally rather than trusted on faith.