1. Executive summary

Start with a short summary that says what will change and why now. The summary should be specific enough that someone scanning the spec can decide whether they are the right reviewer. Avoid product theater. A good summary names the system, the user-facing or operator-facing behavior, and the boundary of the change.

Weak summary: "Improve onboarding." Stronger summary: "Add an email-verification gate to account creation so unverified users cannot create shared workspaces until they confirm the address used at signup." The second version identifies the surface, the new rule, and the moment where behavior changes.

2. Problem and goal

The problem explains the current pain or risk. The goal states the desired outcome in observable terms. If the problem is "people are confused," the spec is already in trouble; confusion must be unpacked into evidence such as support tickets, failed tasks, analytics drop-off, or repeated implementation mistakes.

A goal is not a solution detail. "Ship a modal" is a design choice. "Prevent users from deleting a workspace without seeing the impacted projects" is a goal. This distinction keeps the spec from prematurely locking the implementer into a UI mechanism that may not survive engineering review.

3. Context and current behavior

Current behavior is the part many specs skip, and it is often the part an agent needs most. Name the modules, routes, APIs, database tables, event names, queue jobs, or files that matter. Record the real behavior before describing the desired behavior. If the current system has quirks, write them down instead of assuming implementation will rediscover them.

For agent work, this section should include local conventions and nearby examples. Link to existing components, tests, request handlers, migrations, or docs. The goal is not to paste the codebase into the spec; it is to point at the canonical places where the implementer should look first.

4. Scope and non-goals

Scope defines the allowed blast radius. Non-goals define tempting adjacent work that must not be included. This is especially important for AI coding agents, because a model can interpret a broad product phrase as permission to refactor or redesign parts of the system that were only context.

Good non-goals are concrete: "Do not change billing-plan calculation," "Do not migrate legacy projects," "Do not redesign the dashboard navigation," or "Do not introduce a new background job framework." A vague non-goal like "avoid unnecessary changes" does not create a useful fence.

5. Requirements

Requirements should be individually testable. Use stable identifiers when the spec is large enough to review line by line: REQ-1, REQ-2, and so on. Each requirement should express one obligation. If a sentence contains several verbs joined by "and," it probably needs to be split.

Standards language is useful when readers understand it. RFC 2119 gives teams a compact vocabulary for requirement levels: MUST for mandatory behavior, SHOULD for expected behavior with known exceptions, and MAY for optional behavior. Use those words sparingly and define them once.

"absolute requirement of the specification"
RFC 2119

6. Design and interface changes

This is where the spec describes the technical shape of the change: APIs, data models, UI states, permissions, jobs, events, error paths, and dependencies. The best version is specific without becoming a transcript of future code. It tells the implementer which contracts must exist and which decisions are intentionally left to local code patterns.

Include diagrams or tables when prose gets slippery. For APIs, document method, route, authentication, request shape, response shape, error statuses, and backwards compatibility. For UI, document states and transitions. For data, document ownership, migration, retention, and privacy implications.

7. Acceptance criteria

Acceptance criteria translate requirements into pass/fail examples. They should be written from the perspective of observable behavior: what input or state exists, what action occurs, and what result must be true. If a reviewer cannot manually or automatically verify a criterion, it is not done yet.

The AI-executable version of acceptance criteria should include examples for edge cases, invalid states, and permission failures. Happy-path-only criteria create false confidence.

8. Verification

Verification is where the spec stops being aspirational. Name the commands, test files, browser flows, API calls, migration checks, telemetry checks, or manual review steps that prove the implementation satisfies the spec. If the system has no test coverage, the spec should say what lightweight test or check will be added.

9. Rollout, migration, and failure modes

Many specs stop at implementation and forget operation. If the change touches persisted data, user permissions, billing, notifications, search indexes, analytics, or external integrations, the spec needs a rollout section. Include migration order, feature flags, backfill plans, rollback behavior, and support visibility.

NASA's systems engineering guidance frames technical requirements as a transformation from stakeholder expectations into validated technical requirements. That idea is useful even for web software: the spec should make validation possible before and after release.

"transform the stakeholder expectations"
NASA Systems Engineering Handbook Appendix

10. Open questions

Open questions are allowed. Hidden open questions are not. List unresolved decisions with owners and the impact of leaving them unresolved. If a question blocks implementation, say so. If it can be answered during implementation without changing scope, mark it as non-blocking.

A spec is not better because it pretends all uncertainty is gone. It is better because uncertainty is visible and contained.

Copy-ready spec template

# Technical Spec: [Feature or Change]

Status: Draft | In review | Approved | Implemented
Owner:
Reviewers:
Last updated:

## Summary
[One paragraph naming the system, behavior change, and reason.]

## Problem
[Evidence of the current problem. Link tickets, analytics, incidents, or user research.]

## Goal
[Observable outcome. Avoid implementation details unless they are constraints.]

## Non-goals
- [Adjacent work explicitly out of scope.]
- [Refactors or migrations not included.]

## Current behavior
- [Current user/system behavior.]
- [Relevant modules, routes, APIs, jobs, tables, or files.]

## Proposed behavior
- REQ-1: [One testable requirement.]
- REQ-2: [One testable requirement.]
- REQ-3: [One testable requirement.]

## Design
[API, UI, data model, permissions, state transitions, migrations, events.]

## Edge cases
- [Invalid input]
- [Empty state]
- [Permission failure]
- [Retry or idempotency]

## Acceptance criteria
- Given [state], when [action], then [observable result].
- Given [edge state], when [action], then [safe result].

## Verification
- Automated:
- Manual:
- Telemetry/logging:

## Rollout
[Feature flag, migration, backfill, rollback, support notes.]

## Open questions
- [Question] — owner, blocker/non-blocker, deadline.

For a guided first draft, use the Spec Builder. For an existing draft, run the Ambiguity Checker before review.