Turning a prototype into a spec
Turn what a prototype taught you into a buildable spec, with findings, decisions, the first eval cases and the open risks before engineering starts.
On this page
Why this matters
A prototype teaches you things fast: which inputs break the prompt, what users actually ask for, which states confused people, what a good output looks like to them. Most of that knowledge lives in someone’s head, a chat thread and a folder of results files. Two weeks later, it’s gone.
Turning a prototype into a spec is the step that keeps it. It separates what you proved from what you hoped, records the decisions and the reasons behind them, converts prototype inputs into your first eval cases, and names the risks the full build still has to retire. This article walks through each part.
What the prototype proved
Start with an honest list of findings, each backed by evidence. A useful discipline is to sort every claim into one of three buckets:
| Bucket | Example | Evidence |
|---|---|---|
| Proved | The model drafts correct replies for how-to tickets | 17 of 20 real tickets good in prompt test v3 |
| Suggested | Agents trust drafts that cite articles more | 4 of 5 Wizard-of-Oz participants said so; small sample |
| Assumed | Drafts will cut reply time | Not yet measured |
The point isn’t to downplay the prototype. It’s to stop “the demo went well” from being read as “the feature works”. Only the first bucket is safe to build on directly. The other two become open questions in the spec.
Decisions and their reasons
Prototypes force decisions: which model, which prompt, what the UX does when the answer isn’t in the sources. Record each one with its reason, so nobody re-litigates it later without new evidence:
- Decision: drafts only for tickets tagged “how-to”. Because: quality on billing disputes was poor in testing (4 of 10 wrong), and those mistakes are costly.
- Decision: Claude Opus 5.5 at low effort. Because: same pass rate as medium effort on our 20 cases, faster first token.
- Decision: no draft when no article matches. Because: drafts without sources were the main reason testers rewrote replies.
The “because” is what makes this valuable. When someone proposes drafting billing replies next quarter, the record says what evidence would change the decision: a better pass rate on billing cases.
Seeding the eval set
The inputs you tested during prototyping are real, varied and already reviewed. They’re the best possible start for a golden dataset. Don’t let them sit in a results folder.
If your prototype logged reviews as one JSON object per line, as a simple review tool or spreadsheet export can, a short script turns them into eval cases. It keeps the input, what the reviewer said a good output must do, and whether the prototype passed. It removes duplicates and keeps the failures, which are the most valuable cases.
import { readFile, writeFile } from 'node:fs/promises';
/** One reviewed prototype output, as exported from your review sheet. */
interface Review {
input: string;
output: string;
verdict: 'good' | 'fixable' | 'wrong';
reason: string;
promptVersion: string;
}
/** A first eval case: the input, what a good answer must do, and where it came from. */
interface EvalCase {
id: string;
input: string;
criteria: string[];
/** Did the prototype pass? Failing cases are the most valuable: they show what still needs work. */
prototypeVerdict: Review['verdict'];
source: string;
}
const lines = (await readFile('prototype/reviews.jsonl', 'utf8')).split('\n').filter(Boolean);
const reviews = lines.map((line) => JSON.parse(line) as Review);
// Keep the latest review per input, so repeated rounds don't create duplicate cases.
const latest = new Map<string, Review>();
for (const review of reviews) latest.set(review.input.trim(), review);
const cases: EvalCase[] = [...latest.values()].map((review, i) => ({
id: `seed-${String(i + 1).padStart(3, '0')}`,
input: review.input,
// The reviewer's reason becomes a first criterion; refine these by hand before relying on them.
criteria: review.verdict === 'good' ? ['Matches the quality of the approved prototype output'] : [`Avoids: ${review.reason}`],
prototypeVerdict: review.verdict,
source: `prototype ${review.promptVersion}`,
}));
await writeFile('evals/seed-cases.jsonl', `${cases.map((c) => JSON.stringify(c)).join('\n')}\n`);
const failing = cases.filter((c) => c.prototypeVerdict !== 'good').length;
console.log(`Wrote ${cases.length} cases (${failing} that the prototype did not get right).`); The generated criteria are a starting point. Before relying on the set, read each case and write criteria someone else could apply, as described in rubrics and human grading. Check that no personal data survived from the prototype logs.
Risks still open
The last part of the spec update names what the full build must still prove, in order of how likely each is to sink the feature. Each risk gets a way to test it:
- Quality on the full distribution of tickets. The prototype saw 20. Test: grow the eval set to 100 real tickets before launch.
- Reply time actually drops. Assumed, not measured. Test: A/B test against the current workflow with one team.
- Cost at full volume. Estimated from 20 requests. Test: track cost per accepted draft during the staged rollout.
The spec update
Put it together in the one-page spec from earlier, updated with what you learned. The full flow:
Show text descriptionHide text description
A sequence of 5 steps.
- Findings : Sorted into proved, suggested and assumed, with evidence
- Decisions : Each with its reason and what would change it
- Eval seed : Prototype inputs become the first golden cases
- Open risks : Ranked, each with a way to test it
- Updated spec : One page the team can build from
A compact way to write the new sections:
## What the prototype proved (prompt test v3, Wizard-of-Oz x5, 14 Oct)
- Proved: correct drafts for how-to tickets (17/20 good, 0 harmful).
- Suggested: drafts with cited articles are trusted more (4/5 participants).
- Assumed: reply time drops (not measured yet).
## Decisions
- How-to tickets only. Because: billing disputes 4/10 wrong. Revisit if billing pass rate > 85%.
- Opus at low effort. Because: same pass rate as medium on 20 cases, faster.
- No draft without a matching article. Because: unsourced drafts were rewritten most.
## Evals
- 20 seed cases in evals/seed-cases.jsonl (5 the prototype failed). Target: 100 before launch.
## Open risks (ranked)
1. Quality on all how-to tickets → grow eval set to 100.
2. Reply time → A/B test with one team.
3. Cost at volume → track cost per accepted draft during rollout. Common mistakes
- Treating a good demo as proof. Sort findings into proved, suggested and assumed, and only build directly on what’s proved.
- Recording decisions without reasons. Without the “because”, decisions get re-argued every month.
- Throwing away prototype inputs. They’re real, reviewed and varied: your best first eval cases.
- Keeping only the successes. Failing cases show what the build still needs to fix. Keep them in the eval set.
- Building by momentum. Make an explicit build, iterate or stop decision from the evidence.
Try it
Exercise
About 60 min
Write the spec update for a prototype
- List every finding from your prototype and sort each into proved, suggested or assumed, with evidence.
- Write three to five decisions, each with a reason and what would change it.
- Turn your prototype inputs into at least 20 seed eval cases, keeping the failures.
- Rank the open risks and give each a test. End with an explicit build, iterate or stop decision.
Show a hint
If you can’t point to a number, a quote or a log entry for a finding, it isn’t proved. Move it down a bucket.
Show a worked solution
A good spec update fits on one page and lets someone who wasn’t there answer:
- What do we know works, and how do we know?
- What did we decide, and what evidence would change each decision?
- Where are the eval cases, and how many failed in the prototype?
- What’s most likely to sink this, and how will we find out?
- Are we building, iterating or stopping, and why?
Check your understanding
Key takeaways
- Sort prototype findings into proved, suggested and assumed, with evidence.
- Record decisions with reasons and what would change them.
- Turn prototype inputs into seed eval cases, keeping the failures.
- Rank open risks with tests, and make an explicit build, iterate or stop decision.
Progress is saved in this browser and lights up the roadmap.
Related articles
- Writing a one-page AI feature spec Write a one-page spec for an AI feature covering the user and job, success metric, quality bar, failure states, cost estimate and the non-AI alternative. Level: Beginner
- Building golden datasets from real user tasks Build a golden dataset from real user tasks, covering sampling, coverage of hard cases, writing reference answers, privacy, and keeping the set fresh. Level: Advanced
- The AI product lifecycle, from problem to iteration The six-step loop every AI feature goes through, from user problem to shipping and learning, with the artifact and exit criterion for each step. Level: Beginner