The Most Useful Thing You Can Write Has No Code In It
Why Specs Beat Prompts at Scale
The most useful thing you can write before AI-assisted code has no code in it
Day 2 · Session 9
Reconnect — Yesterday → Today
Two questions before any new concept:
1. In Lab 3, you wrote a system prompt before running anything. What happened when you ran without it vs. after?
2. Imagine adding a 4th tool to that pipeline three months from now, after you've forgotten it all. What would you need to not break everything?
Both problems have the same answer: a spec. Your Lab 3 system prompt was a spec — informal, short. Today you write a real one.
Today's Provocation
The most useful thing you can do before writing a line of AI-assisted code is write a document with no code in it at all.
This session makes that feel obvious, not counterintuitive.
Part 1 — The Vibe-Coding Failure Mode
Why "just describe it to the AI" breaks down
What Vibe-Coding Is
Describe what you want in natural language → accept what the AI gives you → repeat until it kind of works.
- The demo looks great.
- You have no idea why it works.
- The moment you add a feature, you find out the hard way.
It's not that it never works. It's that it doesn't survive contact with the second feature.
A Spectrum, Not a Binary
The question isn't "do you use AI?" — everyone does. It's how much structure surrounds the output. (after Karpathy & Osmani)
| Vibe coding | Structured assist | Agentic engineering | |
|---|---|---|---|
| Intent | casual prompts | prompts + some docs | formal specs + memory files |
| Verification | "seems to work?" | manual testing | tests + evals, CI gates |
| You review | maybe not the code | the code | architecture; AI writes impl. |
| Fits | throwaway prototypes | small features | production, team-scale |
The single biggest differentiator is the Verification row — how outputs get checked. What this industry now calls agentic engineering, our Day 2 calls spec-driven. Same discipline.
The Failure Arc (you've probably lived this)
| Stage | What you do | Feels like | The hidden debt |
|---|---|---|---|
| 1 | Describe feature, accept output, it works | "AI is amazing" | no docs, no tests; the AI's guess became the requirement |
| 2 | Add a 2nd feature, re-describe everything | "I'll fix it later" | two contradictory data models, neither written down |
| 3 | Add a 3rd; AI rewrites the 1st to fit | "why did it change that?" | nothing says what must stay stable — everything's negotiable |
| 4 | A teammate asks "what are the requirements?" | paralysed | requirements live only in the code; the AI has no stable context |
| 5 | PM asks "is feature Y done?" | can't answer | "done" was never defined — no acceptance criteria |
Cost grows super-linearly — each feature breaks the last.
The 80% Problem
AI generates the first 80% of a feature in minutes. The last 20% — edge cases, integration, subtle correctness — is where it stalls.
That 20% needs context the model doesn't have: your system's history, the implicit constraints, the why.
And the errors have changed shape:
- Before: syntax typos — the compiler caught them for you.
- Now: conceptual errors — wrong assumptions, missed edge cases, code that looks right and even passes a basic test.
This is why we spec first and review against the spec — to own the 20% that actually decides whether it ships.
The Live Demo — Same Model, Same Task
"Add a search bar to the StackLog entry feed." Run both, back to back.
Prompt A — vibe-coded:
"Add a search bar to the entry feed that filters entries in real time."
The model guesses: component structure, state approach, client vs. server search, styling. Four assumptions you didn't make.
Ask: how would you verify this is correct? What are you testing against?
Prompt B — spec-driven:
"Given this spec: SearchBar renders a controlled
<input type=text>, placeholder 'Search entries…', callsonSearch(trimmedValue)on change, debounced 300ms, propsonSearch: (q:string)=>void, Tailwindw-full border rounded-md px-3 py-2— implement it."
The model produces exactly that. No assumptions. Every decision specified.
Which would you rather review in a PR? Which can you test? Which can a new teammate understand without reading the code?
Vibe-Coded vs. Spec-Driven
| Criterion | Vibe-coded | Spec-driven |
|---|---|---|
| Initial speed | fast — minutes to first version | slower — the spec feels like overhead |
| Iteration speed | slow — re-explain everything each change | fast — new feature = one story + task |
| AI consistency | every session re-interprets the design | the spec is the context, read every time |
| Onboarding | read all the code to grasp intent | hand them the spec — intent is explicit |
| Knowing you're done | "whenever it stops breaking" | when acceptance criteria pass |
| Scope creep | invisible — silently shifts | visible — a spec change is a decision |
| Debugging AI code | no requirements to test against | compare code to spec section, find the deviation |
| Cost at 10+ features | super-linear — each breaks the last | linear — isolated spec sections |
You trade a little upfront speed for everything else.
The Economics — Why Discipline Pays
The trade-off isn't only quality — it's cost structure:
| Up front (CapEx) | Ongoing (OpEx) | |
|---|---|---|
| Vibe-coded | low — just start typing | high — token burn re-fixing, maintenance tax, security clean-up |
| Spec-driven | higher — specs, tests, context | low — sound first time, cheap to extend |
Two levers that move OpEx down:
- Context engineering is a financial lever — a dense, high-signal payload beats a 100k-token dump.
- Model routing — frontier model for architecture; cheap, fast models for tests, review, CI.
"We're vibe-coding the payments service" should alarm a CTO. "Agentic engineering — tests plus reviewed architecture" is a different conversation.
Part 2 — Where SDD Fits
SDD vs. TDD vs. BDD
A Different Question
TDD and BDD answer: how do we know our code is correct? SDD answers: how do we know our AI is building the right thing?
They're not competitors. SDD generates the artifacts that TDD and BDD test against.
The Three, Side by Side
| TDD | BDD | SDD | |
|---|---|---|---|
| Primary artifact | failing unit test | Gherkin scenario | structured spec (PRD + Tech Spec) |
| Scope | one function | one user scenario | entire feature / product |
| When it runs | after the task | after the story | before code generation |
| AI-era role | still valid — runs on output | AC come from the spec | the new foundation layer |
| Relationship | spec's AC → test assertions | spec's stories → Gherkin | generates both as outputs |
SDD doesn't replace TDD/BDD — it sits above them and feeds them. The shift: specs come before generation; tests validate the output.
(Formal spec languages like Z or Alloy exist for safety-critical systems. BMAD is practical: structured English + markdown + JSON Schema, not formal logic.)
Part 3 — BMAD Overview
Four documents, three personas
BMAD Is a Pipeline, Not a Form
Each document feeds the next. PRD → constrains → Tech Spec → generates → Story Map → generates → Task List → drives → code.
Every AI interaction has a document as its context.
That's the difference between a template you fill in and a system that carries intent end to end.
The Four Documents
| # | Document | Contains | Written by | StackLog example |
|---|---|---|---|---|
| 1 | PRD | goals, personas, features, out-of-scope, success metrics | Architect | "users journal dev activity, retrieve by tag; out of scope: multi-user" |
| 2 | Tech Spec | API contracts, data schema, component tree, NFRs | Architect | "GET /entries → Entry[]; SQLite: id, title, content, tags, timestamp" |
| 3 | Story Map | epics → user stories, INVEST-checked, acceptance criteria | Developer | "search entries by tag; AC: results within 200ms" |
| 4 | Task List | file-level tasks: target file, function, I/O, spec ref | Developer | "create routes/entries.ts; GET handler returns Entry[]; satisfies §3.1" |
Notice: the Tech Spec describes
stacklog-entries.json— the file you built yesterday. The spec is about a real system you already half-built.
The Three Personas
| Persona | What it does | Day 1 connection |
|---|---|---|
| Architect | writes PRD + Tech Spec; challenges assumptions, asks "what would a senior engineer ask?" | = the Session-6 system prompt design — same role/constraints/output structure, applied to requirements |
| Developer | turns spec into stories, AC, tasks; generates code from a task | code generation mirrors Lab 3's pipeline — same model, different context |
| Reviewer | compares code diffs to spec; recommends fix code or update spec | mirrors Lab 3's break-and-diagnose — same reasoning, applied to spec compliance |
The Bridge — Personas Are Subagents
Session 2: an orchestrator directing subagents. Switching BMAD personas is exactly that.
You are the orchestrator. Architect, Developer, Reviewer are your subagents.
Yesterday you designed one agent's prompt. Today you direct three — for an entire project. The thinking is identical; the scope is bigger.
Part 4 — Sign-Off
Complete This Sentence
"A spec is better than a prompt at scale because ___."
Good answers:
- "…it gives the AI stable context across sessions."
- "…it defines what done looks like — a prompt never does."
- "…you can onboard a new dev or model without re-explaining."
- "…it makes scope creep visible — a spec change is a decision."
Stuck? Remember Lab 3 — what happened when you ran without the system prompt?
Anchor This
Vibe-coding is fast until the second feature — then it compounds debt. A spec gives the AI stable context, defines "done," and makes change a decision. SDD sits above TDD/BDD and feeds them. BMAD is the pipeline: four documents, three personas — your subagents.
Your Lab 3 system prompt was your first spec. Today you write a better one.
References
- The New SDLC With Vibe Coding — Osmani, Saboo, Kartakis (Google, 2026) · the spectrum, the 80% problem, the economics
- BMAD Method — github.com/bmadcode/BMAD-METHOD
- Karpathy on "vibe coding" (Feb 2025)
- TDD by Example (Beck 2002) · BDD in Action (Smart 2014)
- Anthropic — prompt engineering overview