Writing Specs | Specwright
Description: AI-native enterprise documentation platform. Living specs, agent-maintained docs, repo-native knowledge.

Skip to content

# Writing Specs ​

This guide covers how to write effective specs that Specwright can parse, track, and verify. A well-structured spec becomes a living document that generates tickets, tracks implementation, and verifies itself against code.

## Start from the Template ​

Every repo with Specwright includes a template at `docs/specs/_template.md`:

markdown

    ---
    title: "Feature Title"
    status: draft
    owner: your-name
    team: team-name
    ticket_project: null
    created: YYYY-MM-DD
    updated: YYYY-MM-DD
    tags: []
    ---

    # Feature Title

    Brief overview of this feature.

    ## 1. Background

    Why this feature exists and what problem it solves.

    ## 2. Requirements

    <!-- specwright:system:2 status:todo -->

    ### 2.1 Functional Requirements

    - Requirement one
    - Requirement two

    ### 2.2 Non-Functional Requirements

    - Performance target
    - Availability target

    ## 3. Design

    <!-- specwright:system:3 status:draft -->

    Describe the technical approach.

    ### Acceptance Criteria

    - [ ] Criterion one
    - [ ] Criterion two
    - [ ] Criterion three

    ## 4. Rollout Plan

    <!-- specwright:system:4 status:draft -->

    How this will be deployed and validated.

    ## 5. Open Questions

    - Question one?
    - Question two?

Create a new spec with the Claude Code plugin:

    /sw:new

Or copy the template manually:

bash

    cp docs/specs/_template.md docs/specs/my-feature.md

## Frontmatter ​

The YAML frontmatter is required. At minimum, include `title` and `status`:

yaml

    ---
    title: "Payments Overhaul"
    status: in_progress
    owner: sarah-chen
    team: payments
    ticket_project: PAY
    created: 2025-11-15
    updated: 2026-01-28
    tags: [payments, infrastructure, q1-priority]
    ---

See the Spec Format reference for all fields.

## Section Structure ​

Use numbered h2 headings for top-level sections and h3 for subsections:

markdown

    ## 2. Stripe Migration
    ### 2.1 API Integration
    ### 2.2 Webhook Handler
    ## 3. Idempotency Layer

Each section can have a status comment. You don't need to add these manually — the agent manages them. But if you want to set an initial status:

markdown

    ## 2. Stripe Migration
    <!-- specwright:system:2 status:in_progress -->

## Writing Good Acceptance Criteria ​

Acceptance criteria are the key to Specwright's value. The agent evaluates code against ACs to determine realization status, so make them specific and verifiable.

### Do ​

markdown

    ### Acceptance Criteria

    - [ ] All checkout flows use Stripe PaymentIntents API
    - [ ] Webhook signature verification using HMAC SHA-256
    - [ ] Rate limit: max 10 emails per user per hour
    - [ ] Idempotency keys stored in Redis with 24-hour TTL

Each criterion is:

- Specific — mentions concrete technology, API, or threshold
- Verifiable — an agent can check code for evidence
- Independent — can be evaluated in isolation

### Don't ​

markdown

    ### Acceptance Criteria

    - [ ] Payments work correctly
    - [ ] Good error handling
    - [ ] Performance is acceptable
    - [ ] Users are happy

These are too vague for the agent to evaluate against code.

## Example: Complete Spec ​

Here's a complete example showing all the patterns:

markdown

    ---
    title: "Auth Migration to OAuth 2.0 + PKCE"
    status: todo
    owner: alex-kumar
    team: identity
    ticket_project: ID
    created: 2026-01-10
    updated: 2026-01-20
    tags: [auth, security, q1-priority]
    ---

    # Auth Migration to OAuth 2.0 + PKCE

    Replace our custom session-based auth with OAuth 2.0 + PKCE flows,
    enabling SSO and improving security posture.

    ## 1. Background

    <!-- specwright:system:1 status:done -->

    Current auth is a custom session-cookie system built in 2020.
    It doesn't support SSO, has no refresh token rotation, and
    session fixation was patched twice last year. We need
    standards-based auth before SOC2 audit in Q2.

    ## 2. OAuth Provider Integration

    <!-- specwright:system:2 status:todo -->
    <!-- specwright:ticket:linear:ID-301 -->

    Integrate with Auth0 as the OAuth provider. Support Google
    Workspace and Microsoft Entra ID as identity providers.

    ### Acceptance Criteria

    - [ ] Auth0 tenant configured for production
    - [ ] Google Workspace SSO working end-to-end
    - [ ] Microsoft Entra ID SSO working end-to-end
    - [ ] PKCE flow implemented for all client types

    ## 3. Token Management

    <!-- specwright:system:3 status:draft -->
    <!-- specwright:ticket:linear:ID-302 -->

    Implement secure token storage and refresh flows.

    Access tokens: 15-minute expiry, stored in memory only.
    Refresh tokens: 7-day expiry, rotated on each use,
    stored in httpOnly cookie.

    ### Acceptance Criteria

    - [ ] Access tokens never persisted to storage
    - [ ] Refresh token rotation on every use
    - [ ] Revocation endpoint clears all active sessions
    - [ ] Token introspection endpoint for service-to-service auth

## Tips ​

- Start with Background — Section 1 should explain why. The agent uses this to understand context.
- One concern per section — Each h2 section should cover one logical area. This maps cleanly to tickets.
- Use subsections for detail — h3 subsections let you break complex sections into trackable units.
- Tag thoughtfully — Tags are used for ticket routing and filtering. Use consistent tag names across specs.
- Update the date — Keep the `updated` frontmatter field current. The agent uses it for staleness detection.
- Link related specs — Reference other specs with relative links: `See [Auth Hardening](auth-hardening.md)`.