Apply DARE to a Feature
Take one small feature requirement and produce the three DARE artifacts — DESIGN.md, BLUEPRINT.md and TASKS.md — learning the method by doing. Separate strategy (the what/why) from tactics (the how) with explicit human checkpoints.
Problem
You have a small feature you want to build with an AI coding assistant, but every time you just "ask the AI to code it" you get plausible-looking output riddled with stubs, mocks and invented behavior. The AI guessed at the parts you never specified. The DARE method fixes this by making you — the human — own the **strategy** (what and why) while the AI owns the **tactics** (how), with explicit review gates in between. In this lab you will pick one real feature and walk it through the method, producing three concrete artifacts: `DESIGN.md` (the problem and testable success criteria), `BLUEPRINT.md` (an executable, anti-stub contract), and `TASKS.md` (atomic tasks arranged as a dependency graph). By the end you will have a paper trail an AI can execute against without inventing anything — and you will understand *why* each phase exists.
Objectives
- Explain the four DARE phases (Design, Architect, Review, Execute) and who drives each one
- Distinguish strategy (human-owned: what/why) from tactics (AI-owned: how)
- Write a
DESIGN.mdwith testable success criteria, constraints and explicit non-goals - Write a
BLUEPRINT.mdwith a data model and endpoints specified per status code, using an anti-stub contract - Decompose a blueprint into atomic tasks (15–60 min) and arrange them as a dependency graph (DAG) with parallel ranks
- Self-review your artifacts to catch stubs and vague "implement X" phrasing before spending execution tokens
Prerequisites
- One small feature idea of your own (something you could build in a day). If you have none, use the sample provided in Step 2.
- A plain-text editor (any editor that saves Markdown is fine)
- Git installed, so you can commit or share your three artifacts at the end
- No specific programming language required — this lab is stack-agnostic and concept-first
What you will build
You will run one small feature through the entire DARE method and walk away with three files:
DESIGN.md, BLUEPRINT.md and TASKS.md. These are not busywork — they are the exact inputs
an AI coding assistant needs to implement your feature without guessing.
Why DARE exists
Large language models are excellent at tactics (writing code) and terrible at reading your mind
about strategy (what you actually want). When you skip the specification, the model fills the gap
with the most statistically likely answer — which is usually a stub, a mock, or a "TODO". DARE
forces the strategy out of your head and onto the page before any code gets written.
DARE stands for Design, Architect, Review, Execute:
-
Design →
DESIGN.md. The human defines the problem, the context, testable success criteria,
constraints and non-goals. The AI assists (asks clarifying questions), but the human drives. -
Architect →
BLUEPRINT.md. The data model and every endpoint are specified — request and
response per status code — using an anti-stub contract: each function or endpoint is
described executably, never as a generic "implement X". -
Review. An explicit human approval gate. You read the blueprint and say "yes, build this"
before spending tokens on execution. -
Execute →
TASKS.md+ a task graph. The blueprint is decomposed into atomic tasks
(15–60 minutes each) with real, minimal dependencies, arranged as a DAG with parallel ranks.
Each task carries an anti-stub Definition of Done. Then the Ralph Loop implements and
iterates until tests, lint and types all pass.
The core split: strategy vs tactics
| Concern | Owner | Artifact |
|---|---|---|
| What and why | Human (drives) | DESIGN.md |
| The executable contract | Human decides, AI drafts | BLUEPRINT.md |
| Approval to proceed | Human (gate) | Review |
| How, implemented | AI (drives) |
TASKS.md + code |
Keep this table in mind for the whole lab. Every time you are tempted to let the AI decide
what something should do, that is a strategy decision — it belongs to you, in DESIGN.md.
What "anti-stub" means
A stub is a placeholder that looks done but isn't: an empty function, a hardcoded return value,
a // TODO: implement. The anti-stub principle says every specification must be concrete enough
that "did nothing" and "did it correctly" are distinguishable. If a spec could be satisfied by
a mock, the spec is too vague. You will apply this test in Steps 3 and 5.
How to work through this lab
Do the steps in order — each artifact feeds the next. Write real Markdown files as you go; by
Step 6 you will commit all three. Examples are given in a neutral pseudo-notation so you can use
whatever language you like.
Steps
-
Understand the four phases and the human/AI split
Before writing anything, internalize the loop. DARE has four phases, and the whole point is
who is in control at each one.-
Design — human drives, AI assists. You decide the problem, the success criteria and the
boundaries. The AI may ask questions, but it does not decide scope. -
Architect — human decides, AI drafts. Together you produce a precise, executable contract.
You are still the authority on what; the AI helps shape how it will be structured. -
Review — human gate. Nothing proceeds without your explicit "approved". This is the
checkpoint that saves you from paying tokens to implement the wrong thing. -
Execute — AI drives, human supervises. The AI implements the tasks and runs the Ralph
Loop (implement → test → lint → typecheck → fix → repeat) until everything is green.
The one rule to remember
Strategy (what and why) is always human. Tactics (how) is always AI. Every phase is just a
handoff between those two, and Review is the safety gate in the middle.Checkpoint
Answer these three questions for yourself before continuing (write them down):
- Which phase decides whether a feature is worth building? (Design.)
- Which artifact must be concrete enough that a stub would fail it? (BLUEPRINT.md.)
- What happens at Review if you spot a gap? (You go back and fix the blueprint — you do not proceed.)
If any answer felt fuzzy, re-read the overview above. The rest of the lab assumes you can name
who owns each decision. -
Design — human drives, AI assists. You decide the problem, the success criteria and the
-
Pick a feature and write DESIGN.md
Now you own the Design phase. Pick one small feature. Keep it tiny — one endpoint or one
screen's worth of behavior. If you have no idea handy, use this sample:Sample feature: a "shorten a URL" service. A user submits a long URL and gets back a short
code; visiting the short code redirects to the original URL.Create a file named
DESIGN.mdwith these five sections. The job here is strategy, not code.# DESIGN — URL Shortener ## Problem & context Users want to share long URLs in places with length limits (chat, print). We need a service that turns a long URL into a short code and redirects on visit. ## Success criteria (testable) - POST a valid URL returns a short code of 6–8 URL-safe characters. - GET /{code} for a known code responds with an HTTP redirect to the original URL. - GET /{code} for an unknown code responds with 404. - The same long URL submitted twice returns the same code (idempotent). ## Constraints - Codes must be URL-safe (no /, +, or =). - Original URL must be a syntactically valid http/https URL. ## Non-goals - No user accounts or authentication. - No analytics/click tracking. - No custom (vanity) codes.Rules for good success criteria
Each criterion must be testable — a specific input producing a specific, observable output.
"It should be fast" is not testable; "responds in under 200 ms for a known code" is. Write
criteria you could hand to someone else who would then know exactly when the feature is done.Why non-goals matter
Non-goals are the fence around the AI's imagination. If you do not write "no authentication",
the AI may helpfully add a login system you never wanted — that is scope the model invented.
Every non-goal is a token you will not waste later.Deliverable for this step: a
DESIGN.mdwith all five sections filled in for your feature. -
Write BLUEPRINT.md with an anti-stub contract
With Design approved (by you), enter the Architect phase.
BLUEPRINT.mdtranslates your
success criteria into an executable contract: a data model plus every endpoint specified with
its request and its response per status code.The critical discipline is the anti-stub contract. Do not write "implement the create endpoint".
Write exactly what goes in, what comes out, and for which status. Here is the sample:# BLUEPRINT — URL Shortener ## Data model Link: - id: unique identifier - code: string, 6–8 URL-safe chars, unique - original_url: string, valid http/https - created_at: timestamp ## Endpoint: POST /links Request body: { "url": "https://example.com/very/long/path" } Responses: - 201 Created { "code": "Ab3xZ9", "short_url": ".../Ab3xZ9", "original_url": "https://example.com/very/long/path" } - 422 Unprocessable Entity (url missing or not http/https) { "error": "url must be a valid http or https URL" } Behavior: - Normalize the URL (trim whitespace, lowercase the host). - If a Link with the same normalized original_url exists, return its existing code (201, idempotent). - Otherwise generate a random 6-char URL-safe code; on collision, regenerate (max 5 tries). ## Endpoint: GET /{code} Responses: - 302 Found -> Location header = original_url - 404 Not Found (no Link with that code) { "error": "unknown code" }The anti-stub test
Read each endpoint and ask: could a stub that returns a hardcoded value satisfy this spec?
If "generate a code" has no rule for collisions, a stub returning"AAAAAA"every time would pass —
so the spec is too weak. Notice how the sample closes that hole with "on collision, regenerate".
Every behavior line exists to make "did nothing" fail.Checklist for your blueprint
- Data model lists every field with its type and constraints
- Every endpoint lists a request shape and a response shape for each status code (success and errors)
- Every non-trivial behavior (normalization, idempotency, collisions, validation) is spelled out
- No line reads "implement X", "handle Y", or "etc." — those are stubs in disguise
Deliverable for this step: a
BLUEPRINT.mdwhere each endpoint could be implemented by someone
who never saw yourDESIGN.md, with no guessing required. -
Decompose into TASKS and build the DAG
Now the Execute phase begins on paper. Break the blueprint into atomic tasks — each one
15 to 60 minutes of focused work, each with an anti-stub Definition of Done (DoD). Then
connect them with their real, minimal dependencies to form a DAG (directed acyclic graph).Tasks in the same rank have no dependency between them, so they could run in parallel. Ranks
run in sequence.# TASKS — URL Shortener ## T1 — Link data model & storage DoD: A Link with code, original_url, created_at can be created and fetched by code; code is unique at the storage level. Test: create two links, fetch each by code. Depends on: (none) ## T2 — URL validation & normalization DoD: Given a string, returns normalized URL or a validation error; rejects non-http(s). Test: valid URL normalizes; "ftp://x" and "" are rejected. Depends on: (none) ## T3 — Code generator with collision retry DoD: Returns a 6-char URL-safe code; on a simulated collision it regenerates; fails after 5 tries. Test: forced collision path regenerates and eventually returns a unique code. Depends on: (none) ## T4 — POST /links endpoint DoD: Valid URL -> 201 with code (idempotent for repeats); invalid -> 422 with error body. Test: covers 201, idempotent repeat, and 422. Depends on: T1, T2, T3 ## T5 — GET /{code} endpoint DoD: Known code -> 302 to original_url; unknown -> 404 with error body. Test: covers 302 and 404. Depends on: T1The dependency graph (DAG)
Reading the "Depends on" lines gives you ranks:
Rank 0 (parallel): T1 T2 T3 \ | / Rank 1: T4 T5 (T5 needs only T1, so it can also start once T1 is done)- Rank 0: T1, T2, T3 — independent, could be built at the same time.
- Rank 1: T4 depends on T1+T2+T3; T5 depends only on T1.
Rules for good decomposition
-
Atomic: if a task would take more than ~60 minutes, split it. If two tasks are always done
together in under 15 minutes, merge them. -
Minimal real dependencies: only draw an edge if the task genuinely cannot start without the
other. Inventing dependencies kills parallelism; missing a real one causes broken builds. -
Anti-stub DoD: every DoD names a concrete test. "Endpoint works" is a stub-friendly DoD;
"covers 201, idempotent repeat, and 422" is not.
Deliverable for this step: a
TASKS.mdlisting atomic tasks with anti-stub DoDs and their
dependencies, plus the rank grouping (the DAG) written out. -
Self-review: hunt for stubs before spending tokens
This is the Review gate — the checkpoint that makes DARE worth it. Before you hand these
artifacts to an AI, you play the reviewer. Your goal is to find every place where the AI could
legitimately produce a stub and still satisfy your spec. Each one you find is a bug caught for free.The anti-stub audit
Go through your three files and check each item. Fix anything that fails before moving on.
- DESIGN.md — criteria are testable. Read each success criterion. Could you write an
automated test from it as written? If it says "handles errors gracefully", replace it with the
specific inputs and expected outputs. - DESIGN.md — non-goals are explicit. Is there any adjacent feature the AI might "helpfully"
add? Name it as a non-goal. - BLUEPRINT.md — every status code is specified. For each endpoint, do you list the success
response and every error response with its body? A missing 404/422 is where the AI invents behavior. - BLUEPRINT.md — no vague verbs. Search for "implement", "handle", "process", "manage",
"etc.", "and so on". Each is a hole. Replace with the concrete rule. - TASKS.md — every DoD names a test. A DoD without an observable test is a stub magnet.
"It works" → "given X, returns Y". - TASKS.md — dependencies are real. For every edge, confirm the task truly cannot start
without its dependency. Remove invented edges; add any missing real one. - No cycles. Follow your "depends on" links — you must never be able to loop back to a task.
The mock test
For each function or endpoint, ask the killer question:
If someone replaced this with a hardcoded mock, would any of my success criteria or DoD tests fail?
If the answer is "no" for any item, that item is under-specified. Tighten it until a mock would
visibly fail. This single question is the essence of DARE — it is why the method produces working
software instead of convincing-looking stubs.Why this gate exists
Everything up to here cost you minutes of writing. Execution costs tokens, time and review effort.
Catching an under-specified endpoint now is nearly free; catching it after the AI built a stub
around it is not. Approve only when every box above is checked.Deliverable for this step: the same three files, revised — with a short note at the bottom of
TASKS.mdlisting at least one stub-risk you found and how you closed it. - DESIGN.md — criteria are testable. Read each success criterion. Could you write an
-
Submit and know how to execute
You have run one feature through all four DARE phases. Time to submit — and to understand what
happens when a real execution begins.Submission criteria
Put your three artifacts in one place and share it:
- Create a git repository (or a gist) containing exactly three files at its root:
DESIGN.md,BLUEPRINT.mdandTASKS.md. - Confirm each one meets its deliverable from the earlier steps:
-
DESIGN.md: problem, testable success criteria, constraints, non-goals. -
BLUEPRINT.md: data model + every endpoint with request/response per status code, anti-stub behavior. -
TASKS.md: atomic tasks with anti-stub DoDs, real dependencies, the rank/DAG grouping, and your stub-risk note.
-
- Commit and push. Submit the repository or gist URL as your lab deliverable.
git init git add DESIGN.md BLUEPRINT.md TASKS.md git commit -m "DARE artifacts for <my feature>" # push to your remote of choice, then submit the URLWhat execution looks like (next steps)
With approved artifacts, execution is mechanical. For each rank of the DAG, an AI assistant picks
up the tasks and runs the Ralph Loop on each:- Implement the task to satisfy its Definition of Done.
- Run the tests, the linter and the type checker.
- If anything is red, read the failure and fix it.
- Repeat until tests, lint and types are all green.
Because same-rank tasks are independent, they can be executed in parallel; the next rank starts only
after its dependencies are done. Because every DoD names a test, "done" is objective — the loop has a
clear stopping condition, and a stub cannot pass.What you learned
You did not just fill in templates. You practiced the core move of DARE: pushing strategy out of
your head and onto the page, in a form so concrete that the AI has nothing left to invent. That is
the whole method. Every future feature is the same four phases — Design, Architect, Review, Execute —
at whatever scale you need. - Create a git repository (or a gist) containing exactly three files at its root: