Pick by the failure you actually have

Day 3: Choose your adventure · Lesson 4 of 5 · 15 min

Choose a spec framework by naming the failure your team keeps hitting, then take the first framework built to answer it. Ask first whether your specs should live or expire, then four questions in order: the first yes that answer allows wins, and "none" is a real answer. Compare the failure you hit in Exercise 2 with the failure each question names.

Watch first · 5 min

Lessons from Spec-driven Development — Simon Martinelli

AI Native Dev, 2026-07-22. Segment 0:00 to 5:00. Listen for the failure Martinelli opens with: a system he built fast with an AI tool for his sports club, which he could neither explain nor adapt when a second customer asked for the same thing, because nothing recorded what had been built. Then decide which of this lesson's four questions his failure would answer yes to, and whether his specs are meant to live or to expire.

Start from the failure, not the feature list

Side by side, the three feature lists blur, as Lessons 1 and 2 showed: each gives you a spec file, a command that moves it forward, and somewhere for it to go after the code ships. Failures do not.

Write one sentence about the last change that went wrong for a reason that was not a bug: the diff sent back for touching the networking layer, the module nobody knew another screen depended on, the ticket three people read three ways. That sentence usually names one of three failures; question four covers one that names none. Answer the live-or-expire question (its section follows question four) first. Its answer overrides the four, not just ties: if your specs expire, a yes to question one does not get you LID; if they live, a yes to question three does not get you BMAD. Then ask these in order and stop at the first yes it allows.

Question one: does your team need to say which requirement a line of code serves?

If the recurring pain is "we changed this and did not know what depended on it", the failure is traceability, and LID is built for it. Every requirement gets a semantic ID that reads as its path through the design tree, flat as FEATURE-NNN and one segment longer per level. LID's format marks each requirement [x] implemented, [ ] a gap, or [D] deferred. The Change C checkpoint, LK-PERIOD-001 to LK-PERIOD-022, uses none: every spec is marked (no test yet), so if you ran the LID track in Exercise 2, check which form your run used. The link into code is a line comment on the topmost function that owns the behavior:

Swift lane
// @spec LK-PERIOD-007, LK-PERIOD-013
public static func periods(for transactions: [Transaction], cycle: StatementCycle) -> [StatementPeriod]
Kotlin lane
// @spec LK-PERIOD-007, LK-PERIOD-013
fun periods(transactions: List<Transaction>, cycle: StatementCycle): List<StatementPeriod>

Search for the ID and you reach the requirement and the code that serves it. The price is daily: someone writes the annotation on every change, and on the build machine the two LID plugins at commit 831c1959 added about 1,090 tokens to every session before anything was typed. If your team would not write the annotations, answer no.

Question two: is the codebase already large, already shipping, and changing in small increments?

If every spec attempt turns into a document about the whole system, the failure is scope, and OpenSpec's unit answers it: a change folder whose delta spec says only what the change adds, modifies, or removes, under ## ADDED Requirements, ## MODIFIED Requirements, and ## REMOVED Requirements. Archiving applies the delta to the live specs and moves the folder into changes/archive/ under a date-prefixed name; Exercise 3 runs that path. A ticket that reworks one screen's pagination owes nobody a description of the app.

Question three: is what is missing the planning, not the traceability?

If work starts before anyone has decided scope, sequence, or who reviews it, the failure is planning roles, and BMAD ships that structure: a spec broken into an ordered story set, planned before anything is built. Adopt the shape, not the command names. BMAD needs uv and permission to run shell commands; if your environment blocks either, BMAD does not start, and Lesson 5 covers what survives a locked-down network.

Question four: none of the above

With no yes, two answers are honest. One is OpenSpec for its light footprint: on the build machine, choosing Claude Code, OpenSpec 1.13.1's init wrote fifteen files where BMAD 6.12.0's installer wrote 235, and each change stays in one folder until you archive it. The other, if specs expire, is no framework: the Day 1 spec template, ../day-1-from-chat-to-spec/starter/specs/TEMPLATE.md (the starter's, not the lane's own specs/TEMPLATE.md), in your team's specs/ folder; the .claude/settings.json from Day 2, committed so it applies to everyone in the project; and Day 2's run-spec runner skill, shared with the team. Most such teams should start with a month of no framework, to learn which failure recurs.

The cross-axis: do you want your specs to live or expire?

One preference overrides all four questions: whether a spec lives on after its change ships or expires with it. If your team will re-read a requirement in six months, when an auditor asks about a declined attempt on a statement, you need a living spec tree: OpenSpec's archive-and-fold into openspec/specs/, or LID's design tree.

If nobody will re-read it, a per-change document is fine and the lightest option that answers your failure wins: BMAD's spec folder when planning is what is missing, OpenSpec or no framework otherwise. Böckeler calls the two positions spec-anchored, a spec kept and evolved beside the code, and spec-first, a spec that serves the change in front of it.

Choosing a spec framework by failure A band across the top asks first: will anyone re-read the spec in six months. If specs live, the choice is OpenSpec or LID; if they expire, the lightest option that answers the failure wins, which for a planning failure is BMAD. It overrules every branch. Below it, four questions stacked top to bottom, joined by arrows labelled no. Question one: does the team need to trace code to its requirement; yes exits right to LID. Question two: large, shipping, small increments; yes exits right to OpenSpec. Question three: planning missing, not traceability; yes exits right to BMAD, with a note that BMAD needs uv and shell access. Question four: none of the above; it exits right to OpenSpec, or no framework. First: will anyone re-read the spec in six months? live: OpenSpec or LID expire: lightest that fits then 1. Need to trace code to its requirement? yes LID no 2. Large, shipping, small increments? yes OpenSpec no 3. Planning missing, not traceability? yes BMAD needs uv and shell access no 4. None of the above then OpenSpec, or no framework
Answer the band first: it overrules the questions below it. Then ask them in order and stop at the first yes it allows.

Write the decision down where it survives you

Whatever you pick, put the decision in a committed file: the date, the failure it was chosen to fix, and the signal Lessons 1 and 2 asked you to pick. Exercise 3's comparison card is this file.

A choice held only in someone's head gets relitigated by the next person who reads a blog post. A useful norm: whoever proposes switching frameworks brings that signal, counted.

When the tree gives the wrong answer

The tree assumes you already run Days 1 and 2's habits. If your acceptance criteria still cannot fail a command, every branch is wrong: LID gives each unfalsifiable criterion an ID, OpenSpec archives it, and BMAD marks it ready-for-dev. The fix is upstream, in Day 1's criteria; no framework applies it.

The tree also assumes one team. A framework chosen for five people and imposed on fifty is a different decision, which this course does not cover. Take your card to your team, not to your organization.

And for a one-line fix, a throwaway script, or an exploratory spike, skip any framework and any spec: the change is done before a spec would pay for itself.

Quick check

Two engineers on the same team complain about the same module. One says "every spec attempt turns into a document about the whole system." The other says "we changed this and had no idea what depended on it." A delta-shaped spec unit answers one of them. Which, and why does it do nothing for the other?

The first. A delta says only what this change adds, modifies, or removes, so the part of the system that is not changing never has to be re-described. The second is a traceability failure: a delta records what changed, not which requirement a given line of code serves. That one wants semantic IDs on requirements and annotations in the code.

Two teams give the same answers to all four questions but pick differently and both are right. What did they disagree about?

The cross-axis: whether their specs are meant to live or to expire. The team that will re-read its requirements in six months chooses between OpenSpec's archive-and-fold and LID's tree; the team that will not takes the lightest option that answers its failure: BMAD when planning is missing, otherwise OpenSpec or no framework.

Sources

Framework documentation accessed 2026-09-22. Versions pinned for Day 3: openspec-04, OpenSpec 1.13.1, released 2026-09-17, from the OpenSpec releases; lid-obs-01, LID commit 831c1959, still the tip of its main branch; bmad-obs-01, BMAD 6.12.0, the npm package's latest tag. Entries marked observed were recorded on the build machine on 2026-09-22 in a scratch copy of the Swift lane.