Spec-Driven Development

source-of-truth

A self-maintaining docs/ directory as the project's source of truth: the AI reads first before editing code, syncs after a feature ships. The catalog owns what & why; code owns how.

READ → before coding SYNC → after shipping BOOTSTRAP → run once

Problem

Four failure modes when AI edits a codebase with no reference source

These are the four recurring failures the skill was built to prevent. If you've never hit any of them, you probably don't need it yet.

FailureDescriptionHow the catalog blocks it
Rebuilding what already existsReimplementing a feature that already exists elsewhere.READ checks "Already exists?" before writing code.
Silently removing a featureA refactor drops a capability that no one intended to remove.Specs document live features and their invariants.
Breaking an invariantChanging behavior without knowing the contract callers depend on.The Invariants section in each spec.
Drifting off-trackBuilding something that violates project principles or isn't on the roadmap.Gate chain: constitution → roadmap → spec.

Operation

Three modes, selected automatically by context

The skill looks at whether a catalog exists, whether you're about to edit code, or whether you just shipped — then runs the appropriate mode.

Run once

BOOTSTRAP

docs/overview.md not yet present
  1. Auto-detect stack, test runner, design system (no prompts)
  2. Single interview pass: code quality, performance budget, mission
  3. Confirm → write catalog + update CLAUDE.md
Before editing code

READ

write / modify / delete
  1. Read overview → constitution → roadmap → spec
  2. Print the "Catalog check" for you to review
  3. STOP on conflict; proceed only after you approve
After shipping

SYNC

"done" · "merge" · "shipped"
  1. Read the diff (not the whole repo) → classify changes
  2. Update specs, remove shipped entries from the roadmap
  3. Record removals / renames / contract changes in CHANGELOG
RE-BOOTSTRAP: if a catalog exists but constitution.md or mission.md is missing → rebuild the missing file before allowing code edits. Updating CLAUDE.md in BOOTSTRAP is the highest-leverage step — it causes every future session to read the catalog automatically, even when the skill doesn't trigger.

Mechanism

Gate chain: each layer guards the layer below

No layer can be crossed before the one above permits it. Read top-down to understand why a line of code exists; read bottom-up to understand how far a change can propagate.

Gate chain Five stacked layers — constitution, mission, roadmap, specs, code — where each layer gates the one below. Read top-down to learn why a line of code exists; read bottom-up to see how far a change can propagate. READ TOP-DOWN · WHY a line of code exists READ BOTTOM-UP · HOW FAR a change reaches gates ↓ gates ↓ gates ↓ gates ↓ Constitution principles · stack · testing · performance constitution.md Mission problem · users · value mission.md Roadmap Now / Next / Later roadmap.md Specs Plan · Requirement · Validation spec-<feature>.md Code the only place that says “how” src/…

principles gate plans → mission gates roadmap → roadmap gates specs → specs gate code.

Structure

The catalog lives in docs/

Five project-level files plus one spec per feature. All markdown — human-readable, greppable, and easy to load into AI context.

docs/tree
docs/
├─ overview.md        # index — points to everything
├─ constitution.md    # principles & tech stack
├─ mission.md         # why the project exists
├─ roadmap.md         # Now / Next / Later
├─ CHANGELOG.md       # removals / renames / contract changes
└─ specs/
   └─ spec-<feature>.md # Plan + Requirement + Validation
overview.mdCentral index — summaries only, not a detail dump. Touch it only when adding, removing, or renaming a feature.
constitution.mdChanges require your explicit approval + one CHANGELOG entry.
roadmap.mdDelivery checklist. Once shipped, entries leave the roadmap.
spec-<feature>.mdOne file per feature, kebab-case. Invariants is the most important field.

Heart of the catalog

Anatomy of a spec

One spec-<feature>.md per feature: header metadata + 3 main sections (+ optional Notes). Goal: someone (or an AI) who hasn't seen the code can still understand why it exists and which contracts must not be broken.

docs/specs/spec-jwt-authentication.md
### Feature: jwt-authentication
- Status: active   Roadmap: shipped
- Last verified: 2026-04-30 @ a1b2c3d

## Plan          # why + approach
JWT chosen over sessions — constitution requires
a stateless API tier. Non-goal: SSO.

## Requirement
- Surface: POST /api/auth/login · /refresh
- Invariants:
  - Wrong password → 401 empty body
  - Email comparison is case-insensitive
  - WHEN /refresh with a valid token
    THEN the old token is revoked
    AND a new token is issued in the same transaction

## Validation      # verifiable by reading, no test run needed
- Given wrong password → 401 empty body.
- Given refresh token used a second time → 401.

## Notes         # gotchas the code doesn't document itself
Do not cache decoded JWTs — revocation requires
a DB lookup on every request.

Invariant vs. implementation detail

Invariants describe only externally observable behavior — what a caller can verify without reading source code. Implementation details belong in Notes.

Is an InvariantIs an implementation detail
HTTP status, response shapeLibrary choices (bcrypt, Redis)
Ordering & idempotencyClass/function structure
Input validation rulesCaching/retry strategy
Caller-visible side effectsMicro-optimization
Rule: if rewriting in another language would change a bullet point, it's an implementation detail — move it to Notes. And: if you can't prove it from code or tests, don't write it — a vague invariant is worse than none.
Progressive rigor: a short spec is the right default for ~80% of features. Expand to WHEN/THEN/AND or SHALL/MUST only when: a regression has occurred · there is a race or ordering concern · compliance is involved · ≥2 clients call it · an AI has misread it before. Length is not quality. Every Validation criterion must trace back to an Invariants bullet — no orphan criteria.

READ mode

Print the "Catalog check" — then STOP on conflict

The Catalog check is not internal reasoning — it's printed so you can override. Any of the situations below causes the skill to stop and ask rather than proceed.

catalog checkstdout
Constitution:      <relevant principles / "no conflict">
Roadmap status:   Now|Next|Later|NOT TRACKED
Related features: <list / "none">
Invariants:      <contracts to preserve>
Acceptance:      <acceptance criteria still required to pass>
Already exists?   <yes + feature / no>
Plan:            <what will be done & why it doesn't conflict>
SituationResponse
Feature already existsSTOP. "Already exists at <path>. Modify it, or is this genuinely different?"
Breaking a documented invariant"Breaks invariant X. Confirm (record in CHANGELOG) or reconsider?"
Violates the constitution"Conflicts with <principle>. Update the constitution first, or change your approach."
Not tracked on the roadmapSTOP. Add a roadmap entry (Now/Next) first — unless you explicitly override.
Spec references a missing file"Spec X references a missing file — sync first?" Does not silently self-correct.

SYNC mode

Reconcile diff → update catalog

After shipping, the skill reads the diff (not the entire repo), classifies each change, updates the right files, and always shows you the catalog diff for review before writing.

Change typeCatalog action
New featureCreate spec-<name>.md + remove from roadmap when shipped + add to overview
Feature updateUpdate spec; if Requirements change → record in CHANGELOG
Remove featureStatus: removed + roadmap + CHANGELOG ### Removed
Rename featureRename spec file + roadmap + CHANGELOG ### Renamed
Internal refactorOnly update Source files if files move — do not touch overview/roadmap
Tech stack changeSurface to you → update constitution + CHANGELOG only after you confirm
scripts/sync_helpers.shbash
# changed files + commit hash + today's date
bash scripts/sync_helpers.sh diff
# pre-formatted "Last verified" line ready to paste into a spec
bash scripts/sync_helpers.sh stamp
# find specs pointing to missing files
bash scripts/sync_helpers.sh stale
Commit gate: a commit request is itself a SYNC trigger — when you ask to commit (or the agent is about to), SYNC runs and completes before the commit, so the code and the catalog are committed together. Automatic, not a question.
CHANGELOG records only 4 event types: Removed · Renamed · Contract changed · Constitution change. New features, internal refactors, and bug fixes that preserve contracts do not need an entry (overview + spec are the record). It answers one question: "Was this removed intentionally, or did the AI forget it?"

Hard rule

Iron-rule: every unit of work gets a roadmap entry

Every change — feature, refactor, and bug fix — gets an entry in roadmap.md before any code is written. The rule exists to prevent the AI from rationalizing "too small to record" — because it's precisely those small, untracked changes that cause the roadmap to drift from reality and the gates to decay. It is not here to override you: you own the project.

✗ Violation
  • AI skips it unilaterally because "it seems minor"
  • Silently shipping something not on the roadmap
  • Treating urgency as permission to skip
✓ Valid
  • Add the entry (takes seconds), then proceed quickly
  • You understand the rule & explicitly override it (e.g. live hotfix)
  • → proceed + suggest a follow-up roadmap/CHANGELOG entry

Discipline

No fabrication · No full-repo reads · No silent edits

An AI-maintained catalog is only trustworthy if it refuses to fill in blanks. These are the red flags the skill self-enforces.

Reading the entire codebase. READ reads catalog files; SYNC reads the diff; BOOTSTRAP caps at ~15 files (or 15/package in a monorepo).
Fabricating invariants. If it's not visible in code or tests, don't assert it. Tests are the best source of invariants.
Filling in constitution/mission from imagination. These must come from you; _TBD:_ is fine, fabrication is not.
Updating overview for every change. It's an index — only touch it when adding, removing, or renaming a feature.
Silently editing the constitution. Stack changes require your confirmation; principle changes require an explicit request.
Skipping READ for a "simple" bug fix. Bug fixes break invariants more often than features do.
Slug naming: lowercase kebab-case verb-noun form (jwt-authentication, email-search) · flat namespace, no nested directories · avoid abstract names (util, core, manager) · avoid bare nouns (useruser-creation).

Where it fits

Works well with superpowers & spec-kit

source-of-truth is a catalog skill, not a workflow engine — it sits alongside a development methodology rather than replacing one. The methodology produces the work; the catalog keeps the source of truth honest across sessions. Pairing it with one of these is a great fit.

superpowersDrives how you work — brainstorming → planning → TDD → review. Each cycle READs the catalog before coding and SYNCs it after shipping.
spec-kitGenerates specs & plans up front for a feature. source-of-truth turns those one-off specs into a living catalog that stays in sync with the code as the project evolves.