Specroot Waitlist open

Spec-driven development example

A spec-driven development example has to go past the first build: much of what goes wrong with a spec happens after the code is merged, when the requirement changes. This one follows a single feature — a payment reminder in a customer portal — from its first spec through the plan, the tasks and the tests to the merge, then through a change request months later to version 2 of the spec, what that version touches, and what the agent is given. At the end, the same spec is written for Spec Kit, Kiro and OpenSpec.

I propose updating the spec then do the implementation. This will most likely show that a few assumptions were wrong forcing some major or minor updates to the spec.

— Hacker News, in a thread on plan mode and specs, 2026

The feature

The customer portal used across this site lets a client’s customers see their invoices and pay them by card. Its business objective is to shorten the time invoices stay unpaid (BR-03). One of the first requirements was a payment reminder, FR-016. The supplier’s developers build with an AI coding agent; the client’s finance lead decides what the reminder must do.

Step 1: the spec, version 1

Written in January, reviewed and agreed by the finance lead on 28 January:

SPEC: Payment reminder
FR-016, version 1, 28 January

Why: invoices stay unpaid too long
(BR-03); the accounts team chases them
by hand.

FR-016  The portal must send one
        reminder, seven days after the
        due date, for every open
        invoice, to the company's
        billing contact.

Acceptance cases
1. Due 1 March, unpaid on 8 March:
   one reminder that day.
2. The same invoice on 9 March: no
   second reminder.
3. Paid in full on 5 March: none.

Security: the email links to the
invoice in the portal (sign-in
required); no attachment.

Touches: the nightly reminder job and
the email templates.

Must not change: the receipt email
(FR-015); invoice statuses.

Out of scope: a second reminder (can
come later).

Agreed: finance lead, 28 January (D-1)

Every line follows one of the rules for writing a spec for an agent: one change, why first, “must”, cases with real dates, security, where it touches, what must not change, what is out of scope. The decision behind it is D-1 in the decision log.

Step 2: the plan

The agent derives the plan from the spec, in plan mode or its tool’s planning step. The developer reads it before anything is built:

PLAN (FR-016, version 1)
- A nightly job selects open invoices
  whose due date was seven days ago.
- Each reminder sent is recorded, so an
  invoice is never reminded twice.
- One email template, linking to the
  invoice page.

The plan says how; the spec does not. That is what lets the finance lead agree the spec without reading the plan, and lets the plan change without reopening the agreement.

Step 3: the tasks

TASKS
1. Select open invoices seven days
   past due  (FR-016; cases 1, 3)
2. Record reminders; skip invoices
   already reminded  (case 2)
3. Email template and sending
   (FR-016; security line)
4. A test for each acceptance case

Each task names the requirement or the case it comes from. When the spec changes, that is how you find the tasks it touches.

Step 4: the tests

One test per acceptance case, named after it:

test_reminder_seven_days_after_due
  case 1
test_no_second_reminder      case 2
test_no_reminder_when_paid   case 3

The agent runs them after each task, and the build is not done until they pass. More on writing the cases in acceptance criteria.

Step 5: review and merge

The reminder went out with the rest of phase 1. The release passed acceptance testing on 16 May, and the client signed off phase 1 on 23 May — see the project sign-off. The spec stayed in the repository as version 1: what the reminder does, and why.

Step 6: the change request

On 10 June, after phase 1 went live, the finance lead asked for part payments: some customers pay large invoices in two or three goes (CR-10). The impact analysis two days later listed six requirements. For the reminder it found a question, not an answer: should a partly paid invoice get a reminder too?

The spec could not answer it — version 1 said “every open invoice”, written when part payments were out of scope. On 16 June the finance lead decided: yes, because otherwise a partly paid invoice would never be chased (D-7). Requirements version 1.4 followed on 17 June.

Step 7: the spec, version 2

The whole spec again, not a note about what changed:

SPEC: Payment reminder
FR-016, version 2, 17 June

Why: invoices stay unpaid too long
(BR-03); the accounts team chases them
by hand.

FR-016  The portal must send one
        reminder, seven days after the
        due date, for every invoice not
        paid in full, to the company's
        billing contact.

Acceptance cases
1. Due 1 March, unpaid on 8 March:
   one reminder that day.
2. The same invoice on 9 March: no
   second reminder.
3. Paid in full on 5 March: none.
4. Partly paid by 8 March: one
   reminder.

Security: the email links to the
invoice in the portal (sign-in
required); no attachment.

Touches: the nightly reminder job and
the email templates.

Must not change: the receipt email
(FR-015); invoice statuses.

Out of scope: a second reminder;
push notifications (CR-8).

Open question: should the reminder
show the amount still due? (finance
lead)

Changes since version 1
- 17 June: "every open invoice" became
  "every invoice not paid in full";
  case 4 added. CR-10, decided by the
  finance lead (D-7, 16 June).

Two lines changed, one case was added, and one question appeared that version 1 never had to ask: part payments made “the amount still due” a thing a reminder could show. Writing it down as an open question stops the agent from deciding it alone. The history of both versions, side by side, is in how to track changes to requirements.

Step 8: what the change touches

The links from step 3 find it:

What What happens
Task 1, selecting invoices Changed: “not paid in full” instead of “open”
Task 2, the reminder record Unchanged
Task 3, the email Waits for the open question
A test for case 4 New
Tests for cases 1 to 3 Run again
RULE-06, the business rule behind it Version 2, from the same decision (D-7)

Without those links, someone has to read the code to find out. With them, the change is a list, and the finance lead can see it before the agent starts.

Step 9: give the agent version 2, then merge

The agent gets version 2 — the whole spec — and the list above. Not the conversation that led to it, and not version 1 with a note: in one 2026 study, of 100 cases where agents succeeded from a final spec, 35 failed on at least one history of revisions that ended in the same spec (SpecPath, preprint). The history is for people.

The work went into phase 2, a week later than first planned. After the merge, version 2 is what the reminder does; version 1 stays in the history, marked as replaced. If the open question is answered with a yes, that is version 3.

The same spec in Spec Kit, Kiro and OpenSpec

Version 2 in each tool’s own format, as their documentation describes it.

Spec Kit — a spec.md per feature, with user stories, Given/When/Then scenarios, numbered requirements and a marker for what is unclear:

# Feature Specification: Payment reminder

### User Story 1 - Reminder (Priority: P1)

**Acceptance Scenarios**:
1. **Given** an invoice due 1 March
   and partly paid, **When** it is
   8 March, **Then** one reminder is
   sent to the billing contact.

- **FR-016**: System MUST send one
  reminder, seven days after the due
  date, for every invoice not paid in
  full. [NEEDS CLARIFICATION: show the
  amount still due?]

Kiro — requirements.md in EARS, in the pattern Kiro’s documentation gives: WHEN [condition/event] THE SYSTEM SHALL [expected behavior]:

WHEN an invoice not paid in full is
seven days past its due date THE
SYSTEM SHALL send one payment reminder
to the billing contact.

WHEN a reminder has been sent for an
invoice THE SYSTEM SHALL NOT send
another.

OpenSpec — the change is a delta against the current spec, merged into it when the change is archived:

# Delta for Payment reminders

## MODIFIED Requirements

### Requirement: Payment reminder
The system SHALL send one reminder,
seven days after the due date, for
every invoice not paid in full.
(Previously: every open invoice)

#### Scenario: Partly paid invoice
- GIVEN an invoice due 1 March, partly
  paid
- WHEN it is 8 March
- THEN one reminder is sent

The tools keep versions differently. In the words of the largest study of how they are used: “OpenSpec keeps both a living spec and an accumulated change record, Kiro keeps a living spec for each feature, and Spec Kit documented the choice only in June 2026” (Agarwal et al., preprint). With a living spec, version 2 replaces version 1 in place, and git keeps the old one. How to set each tool up is in spec-driven development with Claude Code.

What the example shows

  • The second version is where the work is. Version 2 needed a change request, an impact analysis, a decision, a new case and a question that version 1 never had to ask.
  • The links do the finding. Tasks and tests that name their requirement turn “what does this change touch?” into a list.
  • The agent gets the current spec, whole, with the open questions marked.
  • Someone other than the developer decides, and the spec says who and when.

Start your own from the spec template.

Where Specroot fits

This is the problem Specroot works on: the second version of a spec — what changed, who decided it, and everything it touches — kept with the first, so that the agent and the client read the same current version. Specroot for teams using AI coding agents.

What Specroot is