Spec-driven workflow

The principle

Non-trivial changes are specified before they are implemented. The agreed .specs/<feature>.md file is the source of truth for the change. If reality contradicts it mid-implementation, work stops and the spec is updated — the code does not quietly diverge.

This is stated in CLAUDE.md / AGENTS.md as a standing decision. See decision D10.

The five phases

      ┌──────────┐    ┌───────────────┐    ┌─────────────┐    ┌────────────────────────┐    ┌─────────────┐
 ──►  │ planner  │──► │ plan-reviewer │──► │ implementer │──► │ implementation-reviewer│──► │ docs-writer │
      └──────────┘    └───────┬───────┘    └──────┬──────┘    └───────────┬────────────┘    └─────────────┘
       writes           critiques the         executes in         reviews the diff          updates the
       .specs/<f>.md    spec BEFORE code      small verified      against the spec          Antora docs
                              │               increments                │                    in docs/
                              │                   │                     │
                              └───────────────────┴─────────────────────┘
                                    kick back on any contradiction

Phases auto-chain with checkpoints: each hands off to the next, but the implementer works incrementally and stops on any failing lint or test, or on any decision that contradicts the spec.

Phase Role Stops and asks when

1

Planner — produce or extend a spec with requirements, design and a file-level task list.

The requirement is ambiguous, or the change needs a decision the user must make.

2

Plan reviewer — critique the spec for correctness, scope, completeness and fit with existing Angular/NgRx patterns. Before any code.

The plan invents architecture, or misses an existing pattern.

3

Implementer — execute the approved spec one task at a time, verifying each step.

Lint or a test fails non-trivially; the spec is wrong; a task needs an unspecced dependency; scope is growing.

4

Implementation reviewer — review the diff against the spec and the correctness properties. Verdict: APPROVED or CHANGES REQUESTED, with numbered findings citing file:line, marked blocking or nit.

Blocking findings route back to the implementer.

5

Docs writer — update the Antora documentation component in docs/ to match what actually shipped.

The code contradicts the spec in a way that changes documented behaviour; a new Antora module or antora.yml change is needed; the implementation is too unclear to document truthfully.

Where the definitions live

Tool Definitions

Claude Code

.claude/agents/{planner,plan-reviewer,implementer,implementation-reviewer,docs-writer}.md and .claude/skills/{planner,plan-reviewer,implementer,implementation-reviewer,docs-writer}/SKILL.md

Cursor

.cursor/rules/{10-planner,20-plan-reviewer,30-implementer,40-implementation-reviewer,50-docs-writer}.mdc, plus .cursor/rules/00-project.mdc (always-on context), .cursor/rules/update-docs.md, .cursor/agents/.md and .cursor/skills//SKILL.md

Shared context

CLAUDE.md (Claude Code) and AGENTS.md (everything else) — mirrored content.

Cursor additionally carries angular-architecture, change-plan-authoring, change-plan-review and post-plan-code-review skills, which predate the five-phase naming.

Operating principles

These shape how each phase works, not just what it produces. From CLAUDE.md, after Andrej Karpathy:

Keep the model on a tight leash

Many small, concrete, verifiable steps over one big speculative diff. Change one thing, prove it, move on.

Optimise the generation→verification loop

Every change should be cheap to check — a small diff, a runnable test, a lint pass. If a human or a reviewer agent cannot verify a step quickly, the step is too big.

Context is RAM

Pull in only the files that matter. Reference exact paths and symbols. Do not dump a whole module into context "just in case".

Spec before code

Do not start editing until the plan exists and survives review.

Never ship code you cannot explain

No "vibe" diffs. Every change is justified against the spec and covered by a test or a clear manual check.

Match the codebase, do not impress it

Concrete and consistent beats clever.

Keep the human at the decision points

Surface trade-offs and ambiguities; never silently choose on anything that changes scope or behaviour.

.specs/ formats

There are two reference formats and a third, longer planning format. All three are live; pick by size of change.

1. Requirements-and-tasks (for new work)

.specs/bank-name-swift-lookup.md:

# <Feature Name>

## Summary        one paragraph: what and why
## Requirements   numbered, testable
## Design         the approach, existing patterns to follow, files involved
## Tasks          - [ ] checkboxes, file-level, in order

The implementer checks off each task (- [x]) as it goes, so the spec doubles as progress.

2. As-built record (for shipped work)

.specs/email-preference-management.md:

# <Feature Name>

## Overview             what it is, where it lives in the UI
## Files Created        each path with a one-line purpose
## Files Modified       each path with what changed
## API Endpoints        method, URL, request/response shape, auth note
## Component Behaviour  loading, error and edge-case behaviour

Note how specific it is — down to “supplierKey` visibility changed from private to `public” and "401/403 → access denied message, 404 → not found message, 5xx/network → generic error + retry button". That level of detail is what makes the review phase cheap.

3. Plan documents (for large changes)

.specs/gar-2149-card-management-airwallex.plan.md and .specs/airwallex_cardholder_registration_72c94cb6.plan.md use a fuller structure:

## Goals / non-goals / done
## Affected surfaces
## Documentation consulted
## Design
   ### API Migration Map
   ### Unified Card Model
   ### Provider Detection Flow
## Implementation sequence
   ### Phase 1: Model & Interfaces
   ### Phase 2: Feature Flag
   ### Phase 3: Service Layer
   ### Phase 4: NgRx Store (minimal additions)
   ### Phase 5: Component Updates
   ### Phase 6: Routing
   ### Phase 7: Module Registration
   ### Phase 8: Tests
## Files and resources
   ### New files / Modified files / Env vars
   ### New `USER_PERMISSION` values
   ### New `FEATURE_FLAG` key
## Risk and scale
## Testing and rollout
   ### Manual QA paths

Two things worth copying from that format:

  • Non-goals are stated explicitly, which is what keeps the implementer’s scope honest.

  • New USER_PERMISSION values, new FEATURE_FLAG keys and new env vars get their own sections — exactly the items that also require a documentation catalogue update. See the blast-radius checklist below.

The result of that particular plan is documented in card programmes.

The documentation phase

Phase 5 is new relative to the original four-phase workflow, and exists because docs/ is a structured Antora component rather than a README.

docs/ is an Antora documentation component named internal-admin, consumed by the central Payability playbook via start_path: docs. Six modules: ROOT, architecture, domains, platform, ops, reference. See docs/README.adoc and the documentation map.

The docs-writer skill carries the AsciiDoc/Antora reference (resource-ID xrefs, nav.adoc upkeep, the page template) and a blast-radius checklist. The short version:

If the change touched… Update

a route, guard or route data

reference/routes.adoc + the owning domains/ page

an NgRx action, reducer or effect

reference/store-actions.adoc

a service or endpoint

reference/services-and-endpoints.adoc + the owning domains/ page

IEnvironment, set-env.ts, a .cfg template

reference/environment-variables.adoc + ops/environments.adoc
architecture/integration-landscape.adoc

FEATURE_FLAGS

reference/feature-flag-catalog.adoc + platform/feature-flags.adoc

USER_PERMISSION

reference/permission-catalog.adoc + platform/authorization.adoc

MESSAGE_TYPE or an event type

reference/event-catalog.adoc + platform/events.adoc or platform/iframe-messaging.adoc

a storage key, cookie or cache

platform/caching-and-persistence.adoc

a new module or shared component

architecture/module-map.adoc, platform/shared-library.adoc, reference/inventory.adoc

a dependency or build config

architecture/tech-stack.adoc + ops/build-and-deploy.adoc

The docs-writer is documentation-only — it never edits src/. Where the code and a page disagree, the code wins and the page is the bug.

Definition of done

A change is done when:

  • the spec’s acceptance criteria are met;

  • npm run lint and npm run test-single pass;

  • new behaviour has a unit test (and a Cypress test if it is a user-facing flow — noting that the E2E suite is unmaintained, see testing);

  • the spec in .specs/ is updated to match what shipped;

  • the Antora docs in docs/ are updated;

  • .github/PULL_REQUEST_TEMPLATE.md is filled in — including the "corresponding changes to the documentation have been added" checkbox;

  • the diff is small enough to review in one sitting.

Using the phases

Invoke by name, or let the chain run:

"plan this"            / "spec this ticket" / a Jira key with no code   → planner
"review this plan"     / "is this plan ready"                          → plan-reviewer
"implement this spec"  / "build the approved plan"                      → implementer
"review this diff"     / "is this ready to merge"                       → implementation-reviewer
"update the docs"      / "document this change"                         → docs-writer

For a trivial fix — a typo, a one-line guard — the full chain is overkill. The bar is "non-trivial": anything that adds a file, changes behaviour, or touches an item in the blast-radius checklist.