Guide / Methodology

Story-Driven Development

Give the next developer or coding agent a reliable answer to three questions:

  1. What exists
  2. Where it lives
  3. What proves it works
How the pieces connect
01 Intent Idea and outcome
02 Behavior Epic and Story
03 Contract Requirement and Scenario
04 Evidence Code and verification
When the code changes, the map changes with it.

A developer should not have to reverse-engineer the whole app to find out what is already built.

The Epic says what the product does. Its evidence points to the code and tests. If those disagree, that is work to fix.

01 / Problem

Software changes faster than its explanation.

AI coding agents can build quickly. Coming back a week later and figuring out what they actually built is still harder than it should be.

The annoying part comes later.

Tickets and pull requests tell you what changed. They rarely tell you what the app does now.

A ticket captures a plan. A pull request captures one slice of history. Both can be useful, but neither is a dependable map of the current application.

Then the edge cases show up. The data model shifts. Review finds a better approach. A few patches later, the plan and the code no longer agree, and answering a basic question means reading half the repo.

For a developer

The first hour disappears into routes, services, stale layers, and tests that may prove the wrong thing.

For an agent

The agent burns context and tokens reading half the repo before it can do useful work. That is a weak place to start.

02 / Model

Keep a durable map through every change.

I keep the product's accepted behavior separate from the Change used to modify it. The plan can move when implementation reality shows up. The end state, code ownership, and proof cannot quietly disappear.

  1. Behavior

    Epics and Stories

    Explain what the user or operator can do and why it matters. They are durable current-state records: when that behavior changes, the Story changes with it.

  2. Contract

    Requirements and Scenarios

    Spell out the rules and observable examples that make “done” testable.

  3. Ownership

    Implemented By

    Point the next developer at the routes, services, components, and other code that actually owns the behavior.

  4. Proof

    Verified By

    Name the tests, checks, or manual scenarios that prove the behavior. “The build passed” is not enough.

Durable behavior, temporary work

A Change updates the Story. It does not replace it.

Stories are not tasks that expire after implementation. When accepted behavior evolves, update the existing Story, its Requirements and Scenarios, and its implementation and evidence maps to describe what is true now. Create a new Story only for a genuinely distinct, durable user outcome. Once the work is finished, the Change becomes history; the updated Story remains.

Accepted behavior Code ownership Proof Current truth

Three records, three jobs

These documents age differently, so I keep them separate.

A PRD is a starting direction to revisit deliberately, not a document to synchronize after every outcome. A Change becomes history as soon as the work is done. An Epic has to keep changing with the application. Asking one document to do all three jobs is how the docs stop being useful.

01 / Planning

What are we trying to build?

Planning holds product direction, exploration, open questions, and possible work. It describes the intent and constraints before the team has committed to a delivery path.

It can be broader, older, or phased differently without blocking an accepted Change; revisit it when product learning warrants.

02 / Project

What is true in the application now?

Project records describe the system as it exists. Epics map accepted behavior to implementation and evidence. ADRs preserve durable decisions. Supporting docs explain the system around them.

When behavior changes, its existing Story changes with it. These records are current truth, not completed tasks or snapshots of the original plan.

03 / Changes

How are we moving from here to there?

A Change is the working record for one bounded move. It keeps the scope, intended end state, decisions, work status, and verification together while implementation is still moving.

When delivery ends, it becomes history. Any durable result is reconciled into the project records.

Planning gives a Change its purpose. The Change guides the move. Project records are reconciled to what actually shipped, then the Change becomes history.

03 / Workflow

A tool-neutral workflow

The method does not depend on Markdown, a CLI, a particular tracker, or an agent runtime. What matters is preserving the same outcome at each stage.

  1. 01

    Explore

    Preserve a substantial product, technical, operational, design, or business discussion as a synthesized record. Route mature outcomes to their owning workflow without turning exploration into an automatic build cascade.

  2. 02

    Capture intent

    Write down what should change. Save the technical plan until the work is close enough to begin.

  3. 03

    Plan just in time

    Revisit the current code, then tighten the Stories, Requirements, Scenarios, technical choices, and verification.

  4. 04

    Converge the experience

    If the work has a UI, settle the flow, responsive behavior, states, accessibility, and visual direction.

  5. 05

    Commit to a work scope

    Put the implementation-ready plan where the people and systems doing the work can find it.

  6. 06

    Implement one coherent outcome

    Build one dependency-ready outcome, prove its Scenarios with focused checks, review the exact candidate, and stop after its local commit.

  7. 07

    Review independently

    Read the whole diff. Follow the affected callers and contracts, use the configured analyzers, and keep manual acceptance as a separate gate.

  8. 08

    Reconcile and deliver

    Update the existing Stories and their behavior maps to match what shipped. Add a Story only for a distinct durable outcome. Keep unresolved gaps visible, verify the exact delivery diff, then follow the team's release policy.

04 / Traceability

The specification should tell you where to start

An ID is useful only if it leads from a behavior to the code that owns it and the evidence that proves it.

Epic What durable capability exists? LC-001
Story What can the user accomplish? LC-001/S2
Requirement What behavior must hold? R2
Scenario How is that behavior observed? R2-S1

05 / Example

A small Epic can still answer the important questions.

This fictional note-saving capability has one Story and one Requirement. It shows the full path from product intent to code ownership and proof without burying the shape in a large example.

Illustrative Epic / LC-001 Saved Notes Rendered for readability

LC-001 Saved Notes

Product Context

  • Product brief: Notes
  • Related project doc: Persistence overview
  • Related ADR: ADR-0003 Durable note storage

Writers need their work to survive refreshes and later sessions without wondering whether the last edit reached durable storage.

Outcome

Signed-in writers can save a valid note and load the same content later. A failed save leaves their draft intact and explains what happened.

Current Scope

  • Create and update one writer-owned note.
  • Report save state and reload persisted content.

Deferred Scope

  • Sharing, version history, collaborative editing, and offline conflict resolution.

Candidate Stories

None. Future ideas remain outside accepted Story truth until promoted.

Story Index

Story Implementation Verification Capability Last Verified Notes
S1 implemented verified Save a note. 2026-07-22

Stories

Story S1: Save a note

Implementation: implemented
Verification: verified
Created: 2026-07-01
Modified: 2026-07-22
Last verified: 2026-07-22

As a writer, I want to save my note, so that I can return to the same work later.
Requirements And Scenarios

Requirement R1: Durable save

The application SHALL persist valid note content for the signed-in writer and preserve the current draft when persistence fails.

Scenario R1-S1: Save and reload

  • WHEN the writer saves a valid title and body
  • THEN the note is persisted and the saved state is shown
  • AND reloading returns the same title and body

Scenario R1-S2: Persistence rejects the save

  • WHEN storage rejects the save
  • THEN the unsaved title and body remain in the editor
  • AND the writer sees a retryable error
Implemented By
Requirement / Scenario Location / Anchor Kind Responsibility
S1/R1 src/notes/save-note.ts#saveNote primary Owns validation, persistence, and the returned save state.
S1/R1-S2 src/notes/editor.ts#handleSaveFailure support Preserves the active draft and presents the retryable failure.
Implementation Gaps
  • None.
Verified By
Requirement / Scenario Evidence Proves Status
S1/R1-S1 Automated test test/notes/save-note.test.ts#saves and reloads a note The persisted note is returned after a fresh load. Passing 2026-07-22
S1/R1-S2 Automated test test/notes/save-note.test.ts#keeps edits when save fails An injected failure preserves content and exposes a retry. Passing 2026-07-22
Verification Gaps
  • None.
Story Notes
  • saveNote owns the save contract. The editor is supporting UI behavior, not a second implementation owner.

Cross-Story Concerns

  • The authenticated writer ID scopes ownership. The server assigns modification timestamps.

Open Decisions

  • None for the accepted scope.

Completion Criteria

This Epic is healthy when:

  • Story state matches its implementation and verification maps.
  • Both Scenarios have named proof.
  • No current implementation or verification gap is hidden.
  • Related Changes and documentation do not contradict this Epic.

Notes

  • Paths and test titles are illustrative. The important shape is the path from accepted behavior to implementation ownership and proof.

Real Epics will be bigger. The useful part stays the same: accepted behavior has an owner, observable Scenarios have proof or an explicit gap, and the document describes the application as it exists now.

Part 02 / Reference implementation

How I implemented SDD

Everything above this line is the method. What follows is my current local-first implementation: Markdown artifacts, portable repository contracts, private workspace topology, one central workspace Change store, a deterministic CLI, and workspace-managed agent skills.

06 / Package

A local-first CLI and a set of agent skills

The CLI owns structure, configuration, and deterministic state transitions. The skills handle the contextual work: planning, implementation, review, reconciliation, and release judgment.

Default filesystem layout

Planning, project truth, and Changes have distinct owners.

Planning stays Space-owned and private. Durable project truth lives with the code. Every dated Change lives once under <workspace>/.sdd/changes/. The workspace's <workspace>/.sdd/config.yaml maps private relationships, while each repository commits its portable identity and artifact paths in .sdd/config.yaml. Managed skills default to <workspace>/.agents/skills/.

01 / Planning

Space-owned context

<planning-path>/
  prd.md
  explorations/

<workspace>/.sdd/
  explorations/  # workspace-owned topics without one idea

Substantial discussions usually stay here as synthesized durable records, while local guidance or stronger artifact authority may provide a better home. Explore returns a routed handoff when an outcome matures; Change, ADR, PRD, and implementation remain separate invocations.

02 / Project

Repository-owned truth

<repository>/docs/
  epics/<epic>/epic.md
  adrs/<date>-<decision>.md
  audits/

Epics hold durable behavior and evidence maps. ADRs preserve consequential technical choices only when real alternatives and their tradeoffs would otherwise be hard to reconstruct. ADR returns the confirmed direction to its caller without implementing it. Audits remain point-in-time advisory records.

03 / Changes

Workspace-owned work

<workspace>/.sdd/changes/
  <date>-<change>/
    change.md  # intent, plan, constraints, risks
    tasks.md   # outcome queue and Resume checkpoint
    review.md  # candidate, gates, findings, gaps, commit
  closed/
    <date>-<change>/

sdd change create writes one proposed change.md whose frontmatter owns status, Space, and repository IDs. Planning expands change.md, then adds a compact tasks.md queue and one central review.md. Outcomes describe observable behavior, Scenarios, dependencies, expected risks, and focused proof without predicting files or implementation technique. One Requirement is a useful default, not a universal rule.

Every outcome passes five universal gates: scope and candidate, behavior, fresh verification, independent Spec and Quality review, and integrity and authority. Planning declares expected risks; Review runs concrete behavior-derived checks for those risks and may add material ones it discovers. Required technical gaps remain explicit unless the owner accepts that exact gap with a date. Manual product acceptance stays separate.

Apply handles one outcome, permits one consolidated remediation batch and one fresh final Review, selectively creates one content-identical local commit, records its SHA and tree in review.md, and stops. It does not authorize another outcome, push, PR, merge, release, or deployment. Schema-less and receipt-based Change records are unsupported pre-1.0 history, not a second current profile. The CLI validates deterministic structure and provenance; independent Review judges whether the proof is sufficient. Existing records may retain a compatible design.md.

Pre-1.0 installation and Change formats are unsupported alpha data. Recreate a current workspace with sdd setup and sdd init, then manually preserve only records still worth keeping. sdd update reconciles current managed doctrine and skills; it does not migrate product artifacts.

Two layers share the work

Some work should be deterministic. The rest needs judgment.

Deterministic layer

SDD CLI

  • Install workspace-managed skills and map private topology
  • Initialize portable repository contracts
  • Scaffold canonical Changes and repository-owned Epics
  • Resolve immutable committed or working-tree envelopes with sdd candidate resolve; add Epic-specific validation input with sdd epic update-input
  • Validate current Change structure, outcome dependencies, five universal gates, declared triggers, exact Scenario sets, dated gap treatment, commit reachability, and reviewed-tree/final-tree equality
  • Report central Change status across mapped repositories
  • Reconcile checksum-managed doctrine and skills during update
  • Guard one-record lifecycle transitions
Contextual layer

Agent skills

  • Gather the minimum relevant context
  • Refine outcomes and requirements
  • Compare viable technical paths and confirm consequential decisions
  • Route specialist guidance
  • Implement one coherent outcome against an exact baseline with fresh candidate-bound evidence
  • Review complete diffs through systematic search and validated findings
  • Reconcile durable Epic truth against one exact candidate
  • Write one reviewed candidate's native user/operator release entry when warranted
  • Audit broader codebase health

Method to package

The general workflow maps to concrete entry points.

The commands below are conveniences provided by this package. They implement the stages above; they do not define the methodology.

  1. 00Gather action-specific context/sdd-gather-context
  2. 01Explore/sdd-explore
  3. 02Capture intent/sdd-change
  4. 03Plan coherent outcomes and settle branching decisions
    /sdd-change/sdd-adr
  5. 04Validate, then commit to the planned scope
    sdd validate <space-id> --change <change-id> --workspace <path>/sdd-change
  6. 05Optionally converge the planned experience/sdd-design --plan
  7. 06Deliver, verify, review, reconcile when needed, and commit one outcome
    /sdd-apply/sdd-review --outcome-checkpoint/sdd-epic-update
  8. 07Repeat per outcome, then review the complete Change on current Epic truth
    /sdd-apply/sdd-review/sdd-epic-verify
  9. 08Confirm the final Review and Epic truth share one candidate/sdd-review
  10. 09Write candidate release communication when warranted/sdd-changelog
  11. 10Deliver
    /sdd-pr/sdd-release

/sdd-change returns complete, no-op, needs-user, blocked, or routed, then returns control before Design or Apply begins. Design uses the same statuses, preserves a planned Change during initial convergence, binds revisions to exact repository candidates, keeps prototypes optional, and returns before separately invoked Apply or Review. Apply records an exact baseline, states a transient Scenario proof sketch without creating another durable matrix, implements one coherent outcome, and runs focused behavior-derived verification. Broad suites are reserved for material breadth, project policy, integration, or release risk. Independent Review records five universal gates and only the concrete triggered checks the candidate needs, with separate Spec Adherence and Implementation Quality judgments. Required technical gaps cannot pass as manual acceptance; an accepted technical gap names the exact gap and date, while product acceptance remains independently pending until the owner confirms it. Apply may perform one consolidated remediation batch and one fresh final Review. Epic reconciliation runs immediately when accepted behavior, Story completion, or a consumed contract or gap changes; otherwise it waits for Change completion. Once the exact candidate is ready, Apply stages only outcome-attributable files, creates one content-identical local commit, records the commit and matching tree in central review.md, and stops. Review and Epic Update remain directly callable, and a separate final Review on current Epic truth still owns complete-Change integration readiness. Changelog consumes the same candidate envelope after current final Review and current Epic truth, follows the repository's native release-record policy, returns no-op for internal-only or already accurate work, and stops before versioning, staging, commits, PRs, release, or deployment. Release owns aggregation and version intent. Apply's narrow local outcome-commit authority never implies push, PR, merge, release, deployment, or closeout.

Optional component lifecycle

Standardize patterns after they survive real use.

A shared catalog can incubate reusable patterns without turning them into mandatory application dependencies.

  1. 01CandidateRecord a reusable signal.
  2. 02PreviewExercise the important states.
  3. 03AdoptUse the project's ownership model.
  4. 04ValidateProve it in a real consumer.
  5. 05StandardizePromote only with evidence.

An application can still keep its own component or deliberately diverge. That is a valid outcome.

Install once per workspace, initialize each repository
$ git clone https://github.com/TaylorHuston/sdd-skills.git
$ cd sdd-skills
$ npm install
$ npm link
$ sdd setup /path/to/workspace
$ cd /path/to/workspace/spaces/repository
$ sdd init
$ sdd doctor --workspace /path/to/workspace

Pre-1.0 distribution: install from the GitHub checkout for now. A standard npm registry install is targeted for the 1.0 release. See what changed

The North Star

Keep the map honest.

That is the whole point. If the docs say one thing and the code does another, fix the disagreement. The next developer should know where to begin.

Continue to the repository documentation