Skip to content

Writing Your First Feature Spec

A feature spec is the bridge between what the business wants and what developers (and AI agents) build. It is the single source of truth for a feature — capturing intent, acceptance criteria, API contracts, edge cases, and testing strategy in one place.

Every governed PR is checked against the spec that authorises it. This is how SGD provides traceability without adding ceremony.


What Goes in a Spec?

SectionPurposeTypically written by
Business IntentWhy this feature exists, what problem it solves, who benefitsProduct Owner / BA
User StoriesNarrative-form requirements from the user's perspectiveBA / Product Owner
Acceptance CriteriaGherkin-format testable conditions that define "done"BA with developer input
API ContractEndpoints, request/response schemas, status codesDeveloper / Architect
Data ModelNew or changed database entities, relationships, constraintsDeveloper / Architect
Edge CasesBoundary conditions, failure modes, race conditionsDeveloper / QA
Testing StrategyWhat to test, how to test it, what is mocked vs. realQA / Developer

Not every spec needs every section

A small bug fix might only have Business Intent and Acceptance Criteria. A new payment flow needs all seven. Use your judgement — the platform validates what is present, not what is absent.


Example Spec

Here is a realistic spec for a card refund feature in a WealthTech context.

yaml
spec:
  id: PAY-REFUND-001
  title: Process Card Refunds
  capability: Payments / Card Processing / Refunds
  status: approved
  owner: j.singh@wealthtechpros.com
  reviewers:
    - a.chen@wealthtechpros.com
    - m.okafor@wealthtechpros.com

business_intent: |
  Clients who dispute a card transaction need refunds processed
  within 48 hours to meet FCA complaints-handling requirements.
  Currently this is a manual process via the operations team.
  This feature automates refund initiation, validation, and
  processing via the payment gateway.

user_stories:
  - As a client, I can request a refund for a completed card
    transaction from my transaction history.
  - As an operations analyst, I can view pending refunds and
    override automated decisions when needed.
  - As a compliance officer, I can audit the full refund chain
    from client request to gateway settlement.

acceptance_criteria:
  - title: Successful refund within limits
    gherkin: |
      Given a completed card transaction of GBP 500
      And the transaction is less than 90 days old
      And no previous refund exists for this transaction
      When the client requests a full refund
      Then the refund is submitted to the payment gateway
      And the refund status is "pending_settlement"
      And an audit event is recorded with the client ID,
        transaction ID, and refund amount

  - title: Refund exceeds policy limit
    gherkin: |
      Given a completed card transaction of GBP 15,000
      When the client requests a full refund
      Then the refund is flagged for manual review
      And the operations team is notified via the dashboard
      And the refund status is "pending_review"

  - title: Duplicate refund prevention
    gherkin: |
      Given a completed card transaction with an existing
        refund in status "pending_settlement" or "settled"
      When the client requests another refund
      Then the request is rejected with reason "duplicate"
      And no gateway call is made

api_contract:
  - method: POST
    path: /api/v1/refunds
    request:
      transaction_id: string (uuid)
      amount: number (positive, max 2 decimal places)
      reason: string (enum: disputed, error, goodwill)
    response_201:
      refund_id: string (uuid)
      status: pending_settlement | pending_review
      estimated_settlement: ISO 8601 datetime
    response_409:
      error: duplicate_refund
      existing_refund_id: string (uuid)

edge_cases:
  - Gateway timeout — retry with idempotency key, max 3 attempts
  - Partial refund — amount less than original transaction
  - Currency mismatch — refund must match original currency
  - Transaction older than 90 days — reject with clear message
  - Concurrent requests — use database-level locking on transaction ID

testing_strategy:
  unit: Refund validation logic, amount calculations, policy checks
  integration: API endpoint tests with mocked gateway
  contract: Gateway API contract tests (Pact)
  e2e: Full refund flow from client request to settlement callback

Spec Lifecycle

Every spec moves through a defined lifecycle. The platform tracks transitions and enforces rules — for example, a PR cannot reference a spec in Draft status.

StatusMeaningWho transitions
DraftBeing written, not yet ready for reviewAuthor (BA / PO / Developer)
ReviewUnder review by designated reviewersAuthor submits for review
ApprovedAccepted — PRs can now reference this specReviewer(s) approve
ImplementedAll acceptance criteria met, feature deployedPlatform auto-detects or developer marks
DeprecatedNo longer active — replaced or removedProduct Owner

PRs require an approved spec

By default, governed repositories require PRs to reference an approved spec. This is configurable per capability — some teams prefer a lighter-touch model where specs are recommended but not enforced.


How AI Uses Specs

When a developer opens an AI coding tool (Claude Code, Cursor, Copilot) in a governed repository, the spec is part of the context the AI receives. This happens through two mechanisms:

CLAUDE.md / MCP context — The platform generates and maintains context files that include:

  • The active spec(s) for the current repository
  • Acceptance criteria the AI should be aware of
  • API contract details (endpoints, schemas, status codes)
  • Edge cases to handle
  • Related ADRs and design constraints

PR governance checks — When the AI (or developer) opens a PR, the platform checks:

  • Does the PR reference an approved spec?
  • Do the changes align with the spec's API contract?
  • Are the acceptance criteria addressed?
  • Are any edge cases from the spec unhandled?

The result is that AI tools write code that is aware of the spec from the start, rather than generating plausible-looking code that misses requirements. The governance check catches anything that slips through.


What's next?

Powered by RepoSentry