Skip to main content

Implementation-Ready Specifications

A specification is ready when scope, actors, terms, behavior, state, NFRs, edge cases, dependencies, non-goals, ownership, rollout, and evidence are sufficient for independent review. Readiness does not mean every technical choice belongs in requirements.


Preserved Long-Form Material: markdown the language of ai

Pattern-library note: The restored examples below preserve useful teaching depth from the earlier manuscript. Their bookmark, chat, password-reset, or other sample domains are secondary exercises. TaskFlow audit export is the canonical running system, and the current definitions and policies earlier in this guide take precedence over tool-specific legacy wording.


Learning Objectives

By the end of this chapter, you will be able to:

  • Explain why Markdown is the specification language of AI-native development
  • Use headings, lists, tables, code blocks, and links to create structured documents
  • Write specifications that AI agents can parse and implement accurately
  • Understand the three-layer model: Intent Layer (Markdown) → Reasoning Layer (AI) → Implementation Layer (Code)
  • Create a complete feature specification using Markdown

Why Markdown Matters

Imagine you want to build a mobile app. You write a long paragraph to an AI agent:

"Hey, I need an app for tracking tasks. Users should be able to add tasks and see them and delete them. When they open the app there should be a menu. The menu should let them pick what to do. It should have options for adding, viewing, and deleting. Also it should save tasks so they don't lose them when they close the app."

The AI has to guess:

  • What are the main features?
  • What should the menu look like?
  • What order should things appear in?

Now organize the same request with structure:

# Task Tracker App

## Features
- Add new tasks
- View all tasks
- Delete tasks
- Save tasks between sessions

## Menu Options
1. Add Task
2. View Tasks
3. Delete Task
4. Exit

Same information. But now the AI can instantly see four distinct features, four menu options in specific order, and clear interaction patterns. That structured format is Markdown — and it's the difference between confused AI and accurate code generation.


What Is Markdown?

Markdown is structured text that humans can read easily and machines can parse perfectly. Created by John Gruber in 2004 and standardized as CommonMark in 2014, it has become the universal format for developer documentation, specifications, and AI communication.

Why Every Developer Uses It

  1. Developers can read it — No special software needed, just plain text
  2. AI can parse it — The structure tells AI what each section means
  3. It renders beautifully — GitHub, documentation sites, and AI tools display it formatted
  4. It's universal — Every major AI tool (Claude, ChatGPT, Gemini) uses Markdown as its native format

When you write in Markdown, you're using the format that millions of developers use to communicate with both humans and AI.


The Five Essential Markdown Skills

Skill 1: Headings — Creating Document Hierarchy

Headings create the hierarchy that AI uses to understand your specification's structure.

# Main Title (Level 1)
## Section (Level 2)
### Subsection (Level 3)
#### Detail (Level 4)

For specifications, use headings to create a consistent structure:

# Feature: User Authentication

## Problem
Users cannot access the system without verified credentials.

## User Stories
### Story 1: Login with email and password
### Story 2: Password reset via email

## Acceptance Criteria

## Constraints

## Non-Goals

AI agents use heading hierarchy to understand scope. A requirement under ## User Stories is interpreted differently from one under ## Constraints. The heading structure provides semantic meaning.

Skill 2: Lists — Organizing Requirements

Unordered lists (-) for features and requirements where order doesn't matter:

## Features
- User registration with email verification
- Password reset via secure token
- Session management with JWT
- Account deletion with data export

Ordered lists (1.) for sequential steps or prioritized items:

## User Registration Flow
1. User enters email, password, and display name
2. System validates email format and password strength
3. System creates account with "pending" status
4. System sends verification email with 24-hour token
5. User clicks verification link
6. System activates account

For AI agents, the distinction matters. Ordered lists imply sequence — the AI understands step 3 must happen before step 4. Unordered lists imply independence — the AI understands each feature can be implemented separately.

Skill 3: Code Blocks — Showing Examples and Contracts

Fenced code blocks with language tags provide executable context:

## API Contract

```json
POST /api/auth/register
Content-Type: application/json

{
"email": "user@example.com",
"password": "SecureP@ss123",
"display_name": "Alice"
}
```

### Expected Response

```json
HTTP/1.1 201 Created

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"display_name": "Alice",
"status": "pending",
"created_at": "2026-03-09T12:00:00Z"
}
```

Inline code (single backticks) for field names, commands, and values within text:

The `email` field must be a valid email format. The `status` field 
defaults to `"pending"` until the user completes verification.

Skill 4: Tables — Structured Data

Tables organize structured information that AI needs to reference:

## Error Responses

| Status Code | Error Type | Description |
|-------------|-----------|-------------|
| 400 | validation_error | Request body failed validation |
| 401 | unauthorized | Missing or invalid authentication |
| 403 | forbidden | Authenticated but lacking permission |
| 404 | not_found | Resource does not exist |
| 409 | conflict | Resource already exists (duplicate) |
| 429 | rate_limited | Too many requests |

Tables are particularly powerful for:

  • Data model definitions (field, type, constraints, default)
  • API endpoint summaries (method, path, auth, description)
  • Error catalogs (code, type, message)
  • Configuration options (parameter, type, required, default)

Links connect specification documents to each other and to external resources:

## Related Specifications
- [Password Reset](./password-reset-spec.md) — depends on user lookup
- [Email Service](#) — used for verification emails
- [JWT Authentication](./jwt-auth-spec.md) — session management after login

## External References
- [RFC 7807: Problem Details](https://tools.ietf.org/html/rfc7807)
— error response format
- [OWASP Password Guidelines](https://owasp.org/guidelines)
— password strength requirements

Cross-references help AI understand dependencies between features and trace requirements to authoritative sources.


The Three-Layer Model

In AI-native development, every feature moves through three layers:

Your job is Layer 1 — the Intent Layer. The clearer and more structured your Markdown specifications, the better AI performs in Layer 2, and the higher quality the output in Layer 3.

This is why Markdown skills matter for SDD. You're not just formatting text — you're writing the input to an AI code generation pipeline.


Tutorial: Write a Complete Feature Specification

Let's write a complete specification using all five Markdown skills.

The Feature: Notification Preferences

# Feature: Notification Preferences

## Problem
Users receive all notification types by default and cannot control
which notifications they receive. This leads to notification fatigue
and reduced engagement. Users who feel overwhelmed by notifications
disable all notifications, missing important updates.

## User Stories
- As a user, I can view my current notification preferences on a
settings page
- As a user, I can enable or disable each notification category
independently
- As a user, I can choose the delivery channel (email, in-app,
or both) for each category
- As a user, my preferences are applied immediately to all future
notifications

## Notification Categories

| Category | Default State | Description |
|----------|--------------|-------------|
| security_alerts | Always on (cannot disable) | Login attempts, password changes |
| project_updates | On (email + in-app) | New comments, status changes |
| mentions | On (in-app only) | Direct @mentions in comments |
| weekly_digest | On (email only) | Weekly summary of activity |
| marketing | Off | Product updates, feature announcements |

## API Contract

### GET /api/users/me/notification-preferences

```json
{
"preferences": [
{
"category": "security_alerts",
"enabled": true,
"locked": true,
"channels": ["email", "in_app"]
},
{
"category": "project_updates",
"enabled": true,
"locked": false,
"channels": ["email", "in_app"]
}
]
}

PATCH /api/users/me/notification-preferences

{
"preferences": [
{
"category": "project_updates",
"enabled": true,
"channels": ["in_app"]
}
]
}

Acceptance Criteria

  • Given I am authenticated, When I GET my preferences, Then I see all 5 categories with their current state
  • Given I update project_updates to in_app only, When a project update occurs, Then I receive an in-app notification but NOT an email
  • Given I try to disable security_alerts, When I send the PATCH, Then I receive a 400 error with message "Security alerts cannot be disabled"
  • Given I disable marketing, When a marketing notification is triggered, Then I receive nothing

Constraints

  • Security alerts (security_alerts) cannot be disabled — locked: true must be enforced server-side
  • Preferences must be applied within 30 seconds of update (eventual consistency acceptable)
  • At least one channel must be selected for enabled categories

Non-Goals

  • No notification scheduling (e.g., "only notify between 9am-5pm")
  • No per-project notification preferences (global only)
  • No notification history or read/unread tracking (separate feature)

---

## Try With AI

### Prompt 1: Markdown Specification Review

> "I'm going to give you a feature specification I wrote in Markdown. Evaluate it on five criteria: (1) hierarchy — is the heading structure logical? (2) completeness — are problem, user stories, acceptance criteria, constraints, and non-goals all present? (3) precision — could you implement this without asking questions? (4) testability — can each acceptance criterion be turned into an automated test? (5) structure — are tables, lists, and code blocks used effectively? Score each criterion 1-10."

### Prompt 2: Structured vs. Unstructured

> "I'm going to describe a feature in a single paragraph. First, implement it from my paragraph. Then, I'll rewrite it as a structured Markdown specification and you'll implement again. We'll compare. Here's the paragraph: [describe a feature in loose prose]."

### Prompt 3: The AI Readability Test

> "Tell me: when you read a Markdown specification, what elements help you most? What heading structure is most useful? Do numbered lists vs. bullet lists change how you interpret requirements? How do code blocks in a spec affect your implementation? I want to optimize my Markdown for AI comprehension."

---

## Practice Exercises

### Exercise 1: Restructure a Paragraph

Take this unstructured feature description and convert it to a complete Markdown specification with all five elements (headings, lists, tables, code blocks, links):

*"We need a way for users to search for articles. They should be able to type in a search box and see results. Results should show the title and a snippet. If there are no results, show a message. Search should be fast."*

**Expected outcome**: A structured specification with user stories, acceptance criteria (including "fast" defined as a measurable SLA), and constraints.

### Exercise 2: Specification Peer Review

Write a specification for a feature of your choice. Then ask your AI assistant to implement it. Review the implementation against your spec. Every gap in the implementation reveals a gap in your specification.

**Expected outcome**: 2-5 specification gaps discovered through implementation, leading to a revised, more complete specification.

### Exercise 3: Table-Driven Specification

Create a feature specification where the core requirement is best expressed as a table (e.g., permission matrix, error response catalog, state machine transitions). Use tables as the primary specification mechanism.

**Expected outcome**: A specification where tables convey complex relationships more clearly than prose.

---

## Key Takeaways

1. **Markdown is the specification language** of AI-native development. AI agents parse headings, lists, tables, and code blocks as semantic structure.

2. **Five essential skills** — headings, lists, code blocks, tables, and links — give you complete control over specification structure.

3. The **three-layer model** (Intent → Reasoning → Implementation) places your Markdown specifications as the input to AI code generation.

4. **Ordered vs. unordered lists** carry semantic meaning for AI: sequence vs. independence.

5. Well-structured Markdown specifications **consistently produce better AI output** than unstructured prose, even with the same content.

---

## Chapter Quiz

1. Why is Markdown particularly well-suited as a specification format for AI agents?

2. What's the semantic difference between an ordered list and an unordered list in a specification?

3. Name the five essential Markdown skills for specification writing.

4. In the three-layer model, what is the "Intent Layer" and who is responsible for it?

5. How do code blocks in a specification improve AI implementation accuracy?

6. Write a table that defines a data model with four fields, including types and constraints.

7. Why are cross-reference links important in specification documents?

8. A specification uses `####` (level 4 heading) for a major feature. What's wrong?


---

## Preserved Long-Form Material: anatomy of a perfect specification

<!-- merged-from: docs/part-iv/anatomy-of-a-perfect-specification.md -->

> **Pattern-library note:** The restored examples below preserve useful teaching depth from the earlier manuscript. Their bookmark, chat, password-reset, or other sample domains are secondary exercises. TaskFlow audit export is the canonical running system, and the current definitions and policies earlier in this guide take precedence over tool-specific legacy wording.

---

## Learning Objectives

By the end of this chapter, you will be able to:

- Identify and apply the fifteen components of a complete specification
- Write each component with sufficient precision for AI implementation
- Produce a complete specification for a feature from problem statement through security requirements
- Recognize and avoid common specification anti-patterns
- Evaluate specification quality using a structured scoring rubric
- Understand how AI agents use each specification section differently

---

## Why Specification Anatomy Matters

Imagine you're commissioning a custom house. You could tell the builder: *"I want a nice house with a kitchen and bedrooms."* The result would depend entirely on the builder's interpretation. Or you could provide blueprints: foundation dimensions, room layouts, electrical schematics, material specifications, load-bearing requirements, and finish schedules. The blueprints eliminate interpretation — the builder knows exactly what to construct.

A specification is the blueprint for software. The more complete and precise it is, the less the implementer (human or AI) must guess. In Spec-Driven Development, where AI generates implementation from specifications, the quality of the specification directly determines the quality of the output.

This chapter teaches you the anatomy of a perfect specification — the fifteen components that, when present and well-written, produce implementations that match intent.

---

## The Fifteen Components of a Complete Specification

Every complete specification includes these fifteen components. Some features may have minimal content in certain sections (e.g., a simple feature might have few dependencies), but the structure ensures nothing is forgotten.

| # | Component | Purpose |
|---|-----------|---------|
| 1 | Problem Statement | Why this feature exists; who experiences the pain |
| 2 | User Journeys | Concrete scenarios from the user's perspective |
| 3 | Glossary / Domain Terms | What important words mean in this feature |
| 4 | Functional Requirements | What the system must do (capabilities) |
| 5 | State / Lifecycle | Valid states, transitions, expiry, multi-step behavior |
| 6 | Non-Functional Requirements | How well it must do it (quality attributes) |
| 7 | Acceptance Criteria | Testable conditions that define "done" |
| 8 | Edge Cases | Boundary conditions, error paths, unusual inputs |
| 9 | Constraints | What the system must NOT do; hard limits |
| 10 | Dependencies | What this feature requires from other systems |
| 11 | Assumptions and Open Questions | What is still unknown or temporarily assumed |
| 12 | Decision Log | Important product and domain decisions already made |
| 13 | Observability | What to log, measure, and alert on |
| 14 | Security Requirements | Authentication, authorization, data protection |
| 15 | Ownership, Approval, and Release Safety | Who signs off and how the change ships safely |

We'll walk through each component in detail, then assemble a complete example.

---

## Component 1: Problem Statement

The problem statement answers: *Why does this feature exist? Who experiences the problem? What is the cost of not solving it?*

### Why It Matters

AI agents that understand the *why* produce better solutions than those that only know the *what*. When an AI understands that a password reset flow exists because users forget passwords and need a secure, low-friction recovery path, it can make better decisions about token expiry, rate limiting, and error messaging than an AI that only knows "implement password reset."

### Structure

```markdown
## Problem

[1-3 sentences describing the problem]
- **Who**: [User role or persona]
- **Pain**: [What they experience]
- **Impact**: [Consequence of not solving]

Example

## Problem

Users who forget their passwords have no self-service recovery path. They must contact support,
which creates support ticket volume and delays account access. Support-assisted resets also
introduce security risk (social engineering) and poor user experience.

- **Who**: Any authenticated user who has forgotten their password
- **Pain**: Cannot log in; must wait for support; no 24/7 recovery option
- **Impact**: Support costs, user churn, security incidents from manual resets

Anti-Pattern: Solution Disguised as Problem

Bad: "We need a password reset feature." (This is a solution, not a problem.)

Good: "Users who forget passwords cannot recover access without support intervention." (This describes the problem.)


Component 2: User Journeys

User journeys are narrative descriptions of how a user accomplishes a goal. They ground the specification in real usage and prevent building features that are technically correct but don't match how users actually work.

Why It Matters

User journeys provide context that acceptance criteria alone cannot. They describe the emotional arc (frustration → relief), the sequence of steps, and the decision points. AI uses this to prioritize UX considerations and handle "soft" requirements like messaging tone.

Structure

## User Journeys

### Journey 1: [Name]
[2-5 sentence narrative of the user's path from start to goal]

### Journey 2: [Name]
[Alternative or error path]

Example

## User Journeys

### Journey 1: Successful Password Reset

Maria tries to log in but realizes she's forgotten her password. She clicks "Forgot password?"
on the login form. She enters her email and receives a reset link within a minute. She clicks
the link (valid for 1 hour), enters a new password twice, and is redirected to the dashboard.
She can now log in with her new password.

### Journey 2: Expired or Invalid Link

David requests a password reset but doesn't check his email for several hours. When he clicks
the link, it has expired. He sees a clear message: "This link has expired. Request a new one."
He can request a new link without leaving the page. No confusing error; no dead end.

### Journey 3: Rate-Limited Request

An attacker (or forgetful user) requests resets repeatedly. After 3 requests in 15 minutes,
the system shows: "Too many requests. Try again in 15 minutes." The user understands the
wait; the attacker is throttled.

Component 3: Glossary / Domain Terms

Glossary terms give shared meaning to words that might otherwise be interpreted differently by different readers.

Why It Matters

Many feature bugs are language bugs. "Active", "member", "submitted", "export", or "settled" can mean one thing to product and another to engineering. AI will pick one interpretation unless you pin it down.

Structure

## Glossary / Domain Terms

| Term | Meaning in this feature |
|------|-------------------------|
| [TERM] | [Plain-language definition] |

Example

## Glossary / Domain Terms

| Term | Meaning in this feature |
|------|-------------------------|
| Active invitation | Invitation that is sent, unexpired, and not yet accepted or declined |
| Team member | User who already has access to the team workspace |
| Resend | Generate a new invite token and invalidate the previous one |

Component 4: Functional Requirements

Functional requirements are the capabilities the system must provide. They answer: What can the user or system do?

Why It Matters

Functional requirements are the primary input for AI implementation. They define the feature surface — the APIs, UI elements, and behaviors. Vague requirements ("user can reset password") force guessing. Precise requirements ("user can request reset by email; receives time-limited link; can set new password via link") enable direct implementation.

Structure

## Functional Requirements

### FR-1: [Capability Name]
[Precise description of the capability]

### FR-2: [Capability Name]
...

Example

## Functional Requirements

### FR-1: Request Password Reset
User can request a password reset by submitting their registered email address. System validates
that the email exists in the user table. If it exists, system generates a cryptographically
secure token, stores it with expiry (1 hour), and sends an email containing a link with the
token. If email does not exist, system returns the same generic response (no email enumeration).

### FR-2: Validate Reset Token
User can access the reset link. System validates the token: exists, not expired, not already
used. If valid, system displays the password reset form. If invalid, system displays the
expired/invalid message and offers "Request new link" action.

### FR-3: Set New Password
User can submit a new password (with confirmation) from the reset form. System validates
password strength (min 12 chars, complexity rules). If valid, system updates the password,
invalidates the token, invalidates all existing sessions for that user, and redirects to
login with success message. If invalid, system shows validation errors.

### FR-4: Rate Limiting
System limits password reset requests to 3 per email per 15 minutes. System limits token
validation attempts to 5 per token per IP per 15 minutes. Exceeding limits returns 429
with Retry-After header.

Component 5: State / Lifecycle

Some features are not just "input -> output". They move through states over time: invited, accepted, expired; draft, scheduled, published; queued, running, failed, completed.

Why It Matters

State bugs are common because teams specify screens and endpoints but not the allowed transitions. AI will happily implement a happy path and leave invalid transitions undefined unless you make them explicit.

Structure

## State / Lifecycle

| State | Entry Condition | Allowed Transitions | Invalid Transitions | Timeout / Expiry |
|-------|-----------------|---------------------|---------------------|------------------|
| [STATE] | [Condition] | [Next states] | [Forbidden moves] | [If any] |

Example

## State / Lifecycle

| State | Entry Condition | Allowed Transitions | Invalid Transitions | Timeout / Expiry |
|-------|-----------------|---------------------|---------------------|------------------|
| Pending | Invitation created and email sent | Accepted, Declined, Expired, Cancelled | Accepted twice | Expires after 7 days |
| Accepted | Invitee joined team | None | Declined, Cancelled | N/A |
| Declined | Invitee rejects invitation | None | Accepted after decline | N/A |
| Expired | 7 days elapsed without action | Resent -> Pending | Accepted directly | 7 days |

Component 6: Non-Functional Requirements

Non-functional requirements define quality attributes: performance, security, availability, scalability. They answer: How well must the system perform?

Why It Matters

Without NFRs, AI will implement "correct" behavior that may be too slow, insecure, or fragile. NFRs guide architectural decisions (caching, rate limiting, encryption) and provide measurable success criteria.

Structure

## Non-Functional Requirements

### NFR-1: [Attribute] — [Measurable target]
[Description]

### NFR-2: ...

Example

## Non-Functional Requirements

### NFR-1: Latency — Email sent within 30 seconds
Password reset email must be queued and sent within 30 seconds of request. User-facing
confirmation shown immediately; email delivery is async.

### NFR-2: Security — Token entropy
Reset tokens must be at least 256 bits of entropy. Use cryptographically secure random
generation (e.g., `crypto.randomBytes(32)`).

### NFR-3: Availability — No single point of failure
Reset flow must work if email service is temporarily unavailable. Queue the email; retry
with exponential backoff. User sees "Check your email" regardless; no user-facing failure
for transient email issues.

Component 7: Acceptance Criteria

Acceptance criteria are testable conditions that define "done." They are the primary input for test generation and validation.

Why It Matters

Acceptance criteria are the contract between specification and implementation. Each criterion should be verifiable: Given X, When Y, Then Z. AI uses these to generate tests; they also serve as the validation checklist.

Structure

## Acceptance Criteria

- **AC-1**: Given [precondition], When [action], Then [expected result]
- **AC-2**: ...

Example

## Acceptance Criteria

- **AC-1**: Given a valid registered email, When user submits reset request, Then user sees
"Check your email" message and receives email within 60 seconds
- **AC-2**: Given an unregistered email, When user submits reset request, Then user sees
"Check your email" message (no enumeration; same UX as valid email)
- **AC-3**: Given a valid reset token, When user clicks link and submits new password, Then
password is updated and user is redirected to login with success message
- **AC-4**: Given an expired token, When user clicks link, Then user sees "Link expired"
message with option to request new link
- **AC-5**: Given 4 reset requests in 15 minutes for same email, When user submits 4th
request, Then user sees rate limit message and receives 429
- **AC-6**: Given user completes password reset, When user attempts to use old password,
Then login fails; when user uses new password, Then login succeeds

Component 8: Edge Cases

Edge cases are boundary conditions, error paths, and unusual inputs that the system must handle correctly. They are often the source of bugs when omitted.

Why It Matters

AI tends to implement happy paths well. Edge cases are where implementations often fail. Explicitly listing edge cases ensures they are considered during implementation and testing.

Structure

## Edge Cases

| Case | Condition | Expected Behavior |
|------|-----------|-------------------|
| EC-1 | [Condition] | [Behavior] |
| EC-2 | ... | ... |

Example

## Edge Cases

| Case | Condition | Expected Behavior |
|------|-----------|-------------------|
| EC-1 | User submits empty email | Validation error: "Email is required" |
| EC-2 | User submits invalid email format | Validation error: "Enter a valid email" |
| EC-3 | User requests reset for email with special chars | Normalized and processed; no injection |
| EC-4 | Token used twice (double-click, back button) | Second use fails with "already used" |
| EC-5 | User changes password mid-session | All other sessions invalidated; user logged out |
| EC-6 | User submits password that doesn't match confirmation | Validation error: "Passwords must match" |
| EC-7 | User submits weak password | Validation error with strength requirements |
| EC-8 | Token in URL logged or shared | Token single-use; expires after use |
| EC-9 | User has no email (legacy account) | Reset not available; show "Contact support" |

Component 9: Constraints

Constraints define what the system must NOT do; hard limits; inviolable rules.

Why It Matters

Without constraints, AI may add features (e.g., "remember me" on reset page, social login) that weren't requested. Constraints prevent scope creep and enforce architectural boundaries.

Structure

## Constraints

- **C-1**: [Constraint]
- **C-2**: ...

Example

## Constraints

- **C-1**: Must not reveal whether an email is registered (no user enumeration)
- **C-2**: Must not allow password reset without email verification (no phone-based reset)
- **C-3**: Must not allow token reuse (single-use only)
- **C-4**: Must not persist reset tokens beyond 24 hours (cleanup job)
- **C-5**: Must not allow password reset for accounts without verified email
- **C-6**: Must not allow concurrent reset flows for same user (invalidate previous on new request)

Component 10: Dependencies

Dependencies define what this feature requires from other systems, services, or features.

Why It Matters

AI needs to know what exists (email service, user table, auth system) to implement correctly. Dependencies also surface integration risks and ordering requirements.

Structure

## Dependencies

### Internal
- [Dependency name]: [What is required]

### External
- [Service/system]: [What is required]

Example

## Dependencies

### Internal
- **User Service**: Must provide `getUserByEmail(email)` and `updatePassword(userId, hash)`
- **Auth Service**: Must provide `invalidateSession(userId)` for session invalidation
- **Token Store**: Must provide `createToken(userId, type, ttl)` and `consumeToken(tokenId)`

### External
- **Email Service**: Must send transactional emails; template `password-reset` with
`{reset_link, expires_at}`; must support queue/retry

Component 11: Assumptions and Open Questions

This section records what is still undecided and what the team is temporarily assuming so work can continue safely.

Why It Matters

Ambiguity markers help, but teams also need one place to list unresolved questions, owners, and temporary assumptions. Otherwise the uncertainty gets scattered across bullets and is easy to miss.

Structure

## Assumptions and Open Questions

### Assumptions
- **A-1**: [Assumption]

### Open Questions
| ID | Question | Owner | Needed By | Status |
|----|----------|-------|-----------|--------|
| OQ-1 | [Question] | [Role] | [Date/phase] | [Open/Resolved/Deferred] |

Example

## Assumptions and Open Questions

### Assumptions
- **A-1**: Invite emails continue to use the existing transactional email provider

### Open Questions
| ID | Question | Owner | Needed By | Status |
|----|----------|-------|-----------|--------|
| OQ-1 | Can owners assign roles during invite, or only after acceptance? | Product | Before planning | Open |
| OQ-2 | Is resend limited per team or per invite? | Engineering | Before contract draft | Deferred |

Component 12: Decision Log

The decision log records important product and domain calls that are already settled.

Why It Matters

Specifications get revised. A short decision log prevents "why is it like this?" from turning into archaeology. It also separates resolved choices from still-open questions.

Structure

## Decision Log

| Date | Decision | Why | Owner |
|------|----------|-----|-------|
| [DATE] | [Decision] | [Reason] | [Name/Role] |

Example

## Decision Log

| Date | Decision | Why | Owner |
|------|----------|-----|-------|
| 2026-03-10 | Invitation expiry is 7 days | Matches existing email campaign window | Product |
| 2026-03-10 | Default invited role is Member | Keeps admin escalation explicit | Security lead |

Component 13: Observability

Observability defines what to log, what to measure, and what to alert on.

Why It Matters

AI implementations often omit logging and metrics. Explicit observability requirements ensure production systems are debuggable and monitorable.

Structure

## Observability

### Logs
- [Event]: [What to log]

### Metrics
- [Metric name]: [Description]

### Alerts
- [Condition]: [Action]

Example

## Observability

### Logs
- **Reset requested**: userId (hashed), timestamp, rate limit status
- **Token consumed**: userId, timestamp, success/failure
- **Rate limit exceeded**: email (hashed), IP, timestamp

### Metrics
- `password_reset_requests_total`: Counter of reset requests
- `password_reset_success_total`: Counter of successful resets
- `password_reset_rate_limited_total`: Counter of rate-limited requests
- `password_reset_email_delivery_seconds`: Histogram of email send latency

### Alerts
- **High rate limit rate**: If >50% of requests rate-limited in 5 min, alert
- **Email delivery failure**: If email delivery fails 3 consecutive times, alert

Component 14: Security Requirements

Security requirements define authentication, authorization, data protection, and audit requirements.

Why It Matters

Security is often an afterthought. Explicit security requirements ensure AI implements proper token handling, encryption, and access control.

Structure

## Security Requirements

- **SEC-1**: [Requirement]
- **SEC-2**: ...

Example

## Security Requirements

- **SEC-1**: Reset tokens must be stored hashed (e.g., SHA-256) — never store plaintext
- **SEC-2**: Reset link must use HTTPS only
- **SEC-3**: Reset form must use CSRF token
- **SEC-4**: Password must be hashed with bcrypt (cost factor 12) before storage
- **SEC-5**: No sensitive data in logs (no plaintext tokens, passwords, or emails)
- **SEC-6**: Audit log: password reset completed (userId, timestamp, IP)

Complete Example: Password Reset Specification

Here is the full specification assembled from the components above:

# Feature: Password Reset

## Problem

Users who forget their passwords have no self-service recovery path. They must contact support,
which creates support ticket volume and delays account access. Support-assisted resets also
introduce security risk (social engineering) and poor user experience.

- **Who**: Any authenticated user who has forgotten their password
- **Pain**: Cannot log in; must wait for support; no 24/7 recovery option
- **Impact**: Support costs, user churn, security incidents from manual resets

## User Journeys

### Journey 1: Successful Password Reset
Maria tries to log in but realizes she's forgotten her password. She clicks "Forgot password?"
on the login form. She enters her email and receives a reset link within a minute. She clicks
the link (valid for 1 hour), enters a new password twice, and is redirected to the dashboard.

### Journey 2: Expired or Invalid Link
David requests a reset but doesn't check his email for hours. When he clicks the link, it
has expired. He sees "This link has expired. Request a new one." He can request a new link.

### Journey 3: Rate-Limited Request
After 3 requests in 15 minutes, the system shows "Too many requests. Try again in 15 minutes."

## Glossary / Domain Terms

| Term | Meaning in this feature |
|------|-------------------------|
| Reset token | Single-use secret sent by email that proves password reset authority |
| Registered email | Email address already attached to an existing account |

## Functional Requirements

### FR-1: Request Password Reset
User submits registered email. System validates existence. If exists: generate secure token,
store with 1-hour expiry, send email. If not exists: same generic response (no enumeration).

### FR-2: Validate Reset Token
User accesses link. System validates: exists, not expired, not used. Valid → show form.
Invalid → show expired message + "Request new link."

### FR-3: Set New Password
User submits new password. System validates strength. If valid: update password, invalidate
token, invalidate all sessions, redirect to login. If invalid: show validation errors.

### FR-4: Rate Limiting
3 requests per email per 15 min. 5 validation attempts per token per IP per 15 min. 429 + Retry-After.

## State / Lifecycle

| State | Entry Condition | Allowed Transitions | Invalid Transitions | Timeout / Expiry |
|-------|-----------------|---------------------|---------------------|------------------|
| Requested | User submits email | Token Issued, Rate-Limited | Completed | Immediate |
| Token Issued | Valid token stored and email queued | Completed, Expired, Replaced | Reused | 1 hour |
| Completed | Password updated successfully | None | Reused, Expired | N/A |
| Expired | Token lifetime elapsed | Requested | Completed directly | 1 hour |

## Non-Functional Requirements

### NFR-1: Latency — Email queued within 30 seconds
### NFR-2: Security — Token entropy ≥256 bits
### NFR-3: Availability — Queue and retry on email failure

## Acceptance Criteria

- **AC-1**: Valid email → "Check your email" + email within 60s
- **AC-2**: Invalid email → same "Check your email" (no enumeration)
- **AC-3**: Valid token + new password → password updated, redirect to login
- **AC-4**: Expired token → "Link expired" + request new link
- **AC-5**: 4th request in 15 min → rate limit message, 429
- **AC-6**: After reset → old password fails, new password succeeds

## Edge Cases

| Case | Condition | Expected Behavior |
|------|-----------|-------------------|
| EC-1 | Empty email | "Email is required" |
| EC-2 | Invalid format | "Enter a valid email" |
| EC-3 | Token used twice | "Already used" |
| EC-4 | Weak password | Show strength requirements |
| EC-5 | No verified email | "Contact support" |

## Constraints

- **C-1**: No user enumeration
- **C-2**: Email verification only (no phone)
- **C-3**: Token single-use
- **C-4**: Token cleanup after 24h
- **C-5**: Must have verified email
- **C-6**: New request invalidates previous token

## Dependencies

### Internal
- User Service: getUserByEmail, updatePassword
- Auth Service: invalidateSession
- Token Store: createToken, consumeToken

### External
- Email Service: send transactional, template password-reset

## Assumptions and Open Questions

### Assumptions
- **A-1**: Existing auth service supports session invalidation by userId

### Open Questions
| ID | Question | Owner | Needed By | Status |
|----|----------|-------|-----------|--------|
| OQ-1 | Should admins be notified after repeated reset abuse? | Security | Before planning | Deferred |

## Decision Log

| Date | Decision | Why | Owner |
|------|----------|-----|-------|
| 2026-03-10 | No email enumeration in reset flow | Prevent account discovery | Security |

## Observability

### Logs
Reset requested, token consumed, rate limit exceeded

### Metrics
password_reset_requests_total, password_reset_success_total, password_reset_rate_limited_total

### Alerts
High rate limit rate, email delivery failure

## Security Requirements

- **SEC-1**: Tokens stored hashed
- **SEC-2**: HTTPS only
- **SEC-3**: CSRF token on form
- **SEC-4**: bcrypt (cost 12) for password
- **SEC-5**: No sensitive data in logs
- **SEC-6**: Audit log for completed resets

## Ownership, Approval, and Release Safety

- **Spec Owner**: Auth team
- **Engineering Approver**: Staff engineer, identity
- **Product Approver**: Product manager, authentication
- **Release shape**: Direct release behind existing auth surface
- **Rollback trigger**: Spike in reset failures or login failures after completion

How AI Uses Each Section Differently

Understanding how AI uses each section helps you prioritize and write more effectively:

SectionAI Usage
ProblemInforms UX decisions, error messaging; helps prioritize edge cases
User JourneysGuides flow implementation; suggests UX patterns
GlossaryRemoves domain ambiguity; standardizes language
Functional RequirementsPrimary implementation source; defines APIs, UI, logic
State / LifecyclePrevents invalid transitions and timeout bugs
Non-Functional RequirementsDrives architecture (caching, rate limiting, encryption)
Acceptance CriteriaGenerates tests; validation checklist
Edge CasesEnsures error handling; boundary conditions
ConstraintsPrevents scope creep; enforces boundaries
DependenciesDetermines imports, service calls; integration points
Assumptions / Open QuestionsFlags uncertainty instead of hiding guesses
Decision LogPreserves why settled choices were made
ObservabilityAdds logging, metrics, instrumentation
SecurityAdds auth checks, encryption, validation
Ownership / Release SafetyClarifies approvals and shipping plan

Reasoning-Capable Models vs. Faster General Models

The industry has seen a massive shift toward reasoning models that use reinforcement learning during inference. These models "think" before they type.

In Spec-Driven Development, reasoning models require a slightly different approach:

  • Standard Models: Need step-by-step instructions. They do well with the Functional Requirements and User Journeys.
  • Reasoning Models: Thrive on constraints and validation. They perform exceptionally well with robust Acceptance Criteria, Edge Cases, and hard Constraints. They don't need you to hold their hand through the how—they just need an airtight specification of the what and what not to do.

When writing specs for reasoning models, over-invest in Component 5 (Acceptance Criteria) and Component 7 (Constraints).


Tutorial: Write a Complete "Team Invitation" Specification

Let's write a complete specification for a "Team Invitation" feature step-by-step. This feature allows users to invite others to join a team in the collaboration platform.

Step 1: Problem Statement

# Feature: Team Invitation

## Problem

Team owners need to grow their teams by inviting new members. Without an invitation system,
they must manually add users (requiring admin access) or share credentials (insecure).
Invitations provide a controlled, auditable way to onboard new team members.

- **Who**: Team owners and admins
- **Pain**: No way to invite users; must use workarounds
- **Impact**: Slow onboarding; security risks; poor scalability

Step 2: User Journeys

## User Journeys

### Journey 1: Successful Invitation
Alice (team owner) invites bob@example.com. Bob receives an email with an invite link.
Bob clicks the link, creates an account (or logs in), and accepts the invitation. Bob
appears in the team member list with "Member" role.

### Journey 2: Invitation Expired
Bob receives an invite but doesn't act for 7 days. The link expires. Bob sees "Invitation
expired" and can request a new invitation from Alice.

### Journey 3: Invitation Declined
Bob clicks the link but chooses "Decline." The invitation is removed. Alice is notified
(optional). Bob can be invited again later.

### Journey 4: Already a Member
Alice invites bob@example.com, but Bob is already a team member. System shows "Already
a member" and does not send duplicate email.

Step 3: Functional Requirements

## Functional Requirements

### FR-1: Send Invitation
Team owner/admin can invite by email. System validates: email format, not already member,
not already invited (pending). If valid: create invitation record, send email with link,
show "Invitation sent." If invalid: show specific error.

### FR-2: Accept Invitation
User clicks link with valid token. If not logged in: redirect to signup/login, then back
to accept. If logged in: show "Join [Team Name]?" with Accept/Decline. On Accept: add
user to team with default role (Member), invalidate token, redirect to team.

### FR-3: Decline Invitation
User clicks Decline. System invalidates token, records decline. Optionally notify inviter.

### FR-4: Resend Invitation
Team owner can resend invitation to pending invite. New token generated; previous invalidated.
Same 7-day expiry.

### FR-5: Cancel Invitation
Team owner can cancel pending invitation. Token invalidated; invitation removed.

Step 4: Non-Functional Requirements

## Non-Functional Requirements

### NFR-1: Latency — Invitation email within 60 seconds
### NFR-2: Invitation limit — 50 pending invitations per team
### NFR-3: Rate limit — 10 invitations per team per hour

Step 5: Acceptance Criteria

## Acceptance Criteria

- **AC-1**: Given valid email, When owner sends invite, Then user receives email within 60s
- **AC-2**: Given user clicks valid link and accepts, When user clicks Accept, Then user
joins team and sees team dashboard
- **AC-3**: Given user clicks valid link and declines, When user clicks Decline, Then
invitation is removed
- **AC-4**: Given expired invitation link, When user clicks, Then "Invitation expired" shown
- **AC-5**: Given email already in team, When owner invites, Then "Already a member" shown
- **AC-6**: Given 51st pending invitation, When owner invites, Then "Limit reached" shown
- **AC-7**: Given owner cancels invitation, When invitee clicks link, Then "Invalid invitation"

Step 6: Edge Cases

## Edge Cases

| Case | Condition | Expected Behavior |
|------|-----------|-------------------|
| EC-1 | Invite own email | "Cannot invite yourself" |
| EC-2 | Invite duplicate pending | "Already invited" |
| EC-3 | User already in team | "Already a member" |
| EC-4 | Token used twice (double-click) | Second use fails gracefully |
| EC-5 | Inviter removed from team | Pending invites remain; new owner can cancel |
| EC-6 | Team deleted | All pending invites invalidated |

Step 7: Constraints

## Constraints

- **C-1**: Only team owners and admins can invite
- **C-2**: Invitation expires in 7 days
- **C-3**: Must not reveal whether email is registered (accept flow shows team name)
- **C-4**: Default role: Member (no admin invite via this flow)
- **C-5**: One invitation per email per team at a time

Step 8: Dependencies

## Dependencies

### Internal
- **Team Service**: getTeam, addMember, getMemberByEmail
- **User Service**: getUserByEmail, createUser (if signup)
- **Invitation Store**: create, getByToken, consume, cancel

### External
- **Email Service**: send transactional, template team-invitation

Step 9: Observability

## Observability

### Logs
- Invitation sent: teamId, inviterId, inviteeEmail (hashed), timestamp
- Invitation accepted: teamId, userId, timestamp
- Invitation declined: teamId, inviteeEmail (hashed), timestamp

### Metrics
- team_invitations_sent_total
- team_invitations_accepted_total
- team_invitations_declined_total
- team_invitations_expired_total

### Alerts
- High decline rate (>50% in 24h): possible UX issue

Step 10: Security Requirements

## Security Requirements

- **SEC-1**: Invitation tokens hashed; 256-bit entropy
- **SEC-2**: HTTPS only for invitation links
- **SEC-3**: CSRF token on Accept/Decline forms
- **SEC-4**: Audit log: invitation sent, accepted, declined, cancelled
- **SEC-5**: No enumeration: same response for invalid/expired token

Common Specification Anti-Patterns

Anti-Pattern 1: Premature Implementation Detail

Bad: "Use a REST API with POST to /api/invitations and validate with a JWT middleware."

Why it's bad: Specifies how instead of what. Ties the spec to a specific technology. AI may over-constrain or conflict with other constraints.

Good: "User can send an invitation by email. System validates and sends invite. API must be authenticated."

Anti-Pattern 2: Missing Edge Cases

Bad: "User can reset password by email." (No mention of expired links, rate limiting, invalid tokens.)

Why it's bad: AI implements happy path only. Edge cases cause bugs in production.

Good: "See Edge Cases section" with explicit EC-1 through EC-9.

Anti-Pattern 3: Untestable Criteria

Bad: "The system should be fast and user-friendly."

Why it's bad: "Fast" and "user-friendly" are not testable. AI cannot validate.

Good: "p95 latency < 200ms" and "Error messages use plain language, no technical jargon."

Anti-Pattern 4: Vague Requirements

Bad: "Handle errors appropriately."

Why it's bad: No guidance. AI invents behavior.

Good: "On validation error: return 400 with field-level errors. On server error: return 500 with generic message. Log full error server-side."

Anti-Pattern 5: Implicit Dependencies

Bad: (No Dependencies section; assumes AI will infer.)

Why it's bad: AI may miss integrations or use wrong services.

Good: Explicit Dependencies section listing internal and external requirements.

Anti-Pattern 6: No Non-Goals

Bad: (No explicit scope; AI may add "related" features.)

Why it's bad: Scope creep. AI adds bulk invite, invite by link, role selection, etc.

Good: "Non-Goals: Bulk invite, invite by shareable link, role selection at invite time."


Specification Quality Scoring Rubric

Use this rubric to evaluate specification quality. Score each dimension 1-10. Total score is the average.

Dimension1-3 (Poor)4-6 (Adequate)7-10 (Excellent)
CompletenessMissing 4+ componentsMissing 1-3 componentsAll 15 components present
PrecisionVague; requires guessingSome ambiguityImplementable without questions
TestabilityAcceptance criteria untestableSome testableAll criteria testable
Edge CasesNone or trivialSome coveredComprehensive list
ConstraintsNone or implicitSome statedExplicit; prevents scope creep
ConsistencyContradictionsMinor inconsistenciesInternally consistent
AI ReadabilityUnstructured prosePartial structureClear headings, structure

Scoring Guide

  • 70-100: Excellent. Ready for AI implementation.
  • 50-69: Good. Review weak dimensions before implementation.
  • 30-49: Adequate. Significant gaps; expect implementation questions.
  • 0-29: Poor. Rewrite before implementation.

Self-Assessment Checklist

Before handing a spec to AI, verify:

  • Problem statement explains why
  • User journeys cover happy path and key error paths
  • Functional requirements are precise (no "appropriate," "properly")
  • NFRs are measurable
  • Domain terms are defined where ambiguity exists
  • Every acceptance criterion is Given/When/Then testable
  • State/lifecycle is specified for async or multi-step features
  • Edge cases cover boundaries, errors, empty inputs
  • Constraints explicitly state what NOT to do
  • Dependencies listed (internal and external)
  • Assumptions and open questions are explicit
  • Decision log captures important settled calls
  • Observability: logs, metrics, alerts
  • Security: auth, encryption, audit
  • Ownership, approval, and release safety are documented

Spec Quality Gate

For each major requirement, ask:

  • Is it clear?
  • Is it measurable?
  • Is it testable?
  • Is it traceable?
  • Is it feasible?
  • Is it scoped?
  • Is it owned?
  • Is it free of hidden implementation detail?

Try With AI

Prompt 1: Specification Gap Analysis

"I'm going to give you a feature specification. Evaluate it against these components: Problem, User Journeys, Glossary, Functional Requirements, State/Lifecycle, Non-Functional Requirements, Acceptance Criteria, Edge Cases, Constraints, Dependencies, Assumptions/Open Questions, Decision Log, Observability, Security, Ownership/Release Safety. For each component, rate 1-10 and explain what's missing or what could be improved. Then run the spec quality gate: clear, measurable, testable, traceable, feasible, scoped, owned, no hidden HOW."

Prompt 2: Anti-Pattern Detection

"Review this specification for anti-patterns: premature implementation detail, missing edge cases, untestable criteria, vague requirements, implicit dependencies, missing non-goals. List each anti-pattern you find with the exact text and a suggested replacement."

Prompt 3: Specification Expansion

"I have a minimal specification with [list components]. Expand it into a complete specification using the full structure: Problem, User Journeys, Glossary, Functional Requirements, State/Lifecycle, Non-Functional Requirements, Acceptance Criteria, Edge Cases, Constraints, Dependencies, Assumptions/Open Questions, Decision Log, Observability, Security, Ownership/Release Safety. Do not add implementation details — keep it at the 'what' level."

Prompt 4: Rubric Self-Check

"Score this specification using the rubric: Completeness, Precision, Testability, Edge Cases, Constraints, Consistency, AI Readability. Give a score 1-10 for each and an overall average. Suggest specific improvements to raise each dimension by at least 1 point."


Practice Exercises

Exercise 1: Component Audit

Take an existing specification from your project (or a public one). For each of the 10 components, either (a) extract it if present, or (b) write it if missing. Document what you found vs. what you added.

Expected outcome: A complete specification with all 10 components. You will discover gaps in most existing specs.

Exercise 2: Anti-Pattern Rewrite

Take a poorly written specification (e.g., "Build a login form" as a single sentence). Rewrite it to include all 10 components and avoid all 6 anti-patterns. Compare the two versions.

Expected outcome: The rewritten spec should be 5-10x longer and unambiguous. You will see how much implicit content exists in "simple" features.

Exercise 3: Rubric Scoring

Write a specification for a feature of your choice. Then score it using the rubric. For any dimension scoring below 7, revise the spec until it reaches 7+. Repeat until all dimensions are 7+.

Expected outcome: A specification that scores 70+ on the rubric. You will internalize the quality bar for "production-ready" specs.


Key Takeaways

  1. Fifteen components define a complete specification: Problem, User Journeys, Glossary, Functional Requirements, State/Lifecycle, Non-Functional Requirements, Acceptance Criteria, Edge Cases, Constraints, Dependencies, Assumptions/Open Questions, Decision Log, Observability, Security, and Ownership/Release Safety.

  2. Each component serves a distinct purpose for AI. Problem provides context; Functional Requirements drive implementation; Acceptance Criteria generate tests; Constraints prevent scope creep.

  3. Precision over brevity. A specification that is long but precise produces better implementations than a short, vague one.

  4. Edge cases are where bugs hide. Explicitly listing them ensures AI implements error handling.

  5. Anti-patterns undermine quality: premature implementation detail, missing edge cases, untestable criteria, vague requirements, implicit dependencies, no non-goals.

  6. The rubric provides a structured way to evaluate and improve specification quality before implementation.


Chapter Quiz

  1. What are the ten components of a complete specification, and in one sentence each, what is the purpose of each?

  2. Why is it important to avoid "solution disguised as problem" in the Problem Statement? Give an example of bad vs. good.

  3. What is the difference between Functional Requirements and Non-Functional Requirements? Give one example of each for a login feature.

  4. Why are Edge Cases a separate component rather than being folded into Acceptance Criteria?

  5. Name three specification anti-patterns and explain why each is harmful.

  6. How does the Dependencies section help AI implement a feature correctly?

  7. What is the purpose of the Observability section, and what three sub-elements does it typically include?

  8. Using the rubric, how would you score a specification that has all 10 components but uses vague language like "handle errors appropriately" and "should be fast"?