# The Story-Driven Spec Workflow (SDSW) **Target Audience:** Large Language Models (LLMs) acting as Senior Engineers. **Goal:** To maintain long-term project coherence, prevent context window exhaustion, and ensure high-quality, testable code generation in large software projects. --- ## 1. The Philosophy We treat the codebase as the implementation of a **"Living Specification."** Instead of ephemeral chat prompts ("Fix this", "Add that"), we work through persistent artifacts. * **Stories** define the *Change*. * **Specs** define the *Truth*. * **Code** defines the *Reality*. **The Golden Rule:** You are not allowed to write code until the Spec reflects the new reality requested by the Story. --- ## 2. Directory Structure When initializing a new project under this workflow, create the following structure immediately: ```text project_root/ .living_spec |-- README.md # This document ├── stories/ # The "Inbox" of feature requests. ├── specs/ # The "Brain" of the project. │ ├── README.md # Explains this workflow to future sessions. │ ├── 00_CONTEXT.md # High-level goals, domain definition, and glossary. │ ├── tech/ # Implementation details (Stack, Architecture, Constraints). │ │ └── STACK.md # The "Constitution" (Languages, Libs, Patterns). │ └── functional/ # Domain logic (Platform-agnostic behavior). │ ├── 01_CORE.md │ └── ... └── src/ # The Code. ``` --- ## 3. The Cycle (The "Loop") When the user asks for a feature, follow this 4-step loop strictly: ### Step 1: The Story (Ingest) * **User Input:** "I want the robot to dance." * **Action:** Create a file `stories/XX_robot_dance.md`. * **Content:** * **User Story:** "As a user, I want..." * **Acceptance Criteria:** Bullet points of observable success. * **Out of scope:** Things that are out of scope so that the LLM doesn't go crazy * **Git:** Make a local feature branch for the story, named from the story (e.g., `feature/story-33-camera-format-auto-selection`). You must create and switch to the feature branch before making any edits. ### Step 2: The Spec (Digest) * **Action:** Update the files in `specs/`. * **Logic:** * Does `specs/functional/LOCOMOTION.md` exist? If no, create it. * Add the "Dance" state to the state machine definition in the spec. * Check `specs/tech/STACK.md`: Do we have an approved animation library? If no, propose adding one to the Stack or reject the feature. * **Output:** Show the user the diff of the Spec. **Wait for approval.** ### Step 3: The Implementation (Code) * **Action:** Write the code to match the *Spec* (not just the Story). * **Constraint:** adhere strictly to `specs/tech/STACK.md` (e.g., if it says "No `unwrap()`", you must not use `unwrap()`). ### Step 4: Verification (Close) * **Action:** Write a test case that maps directly to the Acceptance Criteria in the Story. * **Action:** Run compilation and make sure it succeeds without errors. Consult `specs/tech/STACK.md` and run all required linters listed there (treat warnings as errors). Run tests and make sure they all pass before proceeding. Ask questions here if needed. * **Action:** Do not accept stories yourself. Ask the user if they accept the story. If they agree, move the story file to `stories/archive/`. Tell the user they should commit (this gives them the chance to exclude files via .gitignore if necessary). * **Action:** When the user accepts: 1. Move the story file to `stories/archive/` (e.g., `mv stories/XX_story_name.md stories/archive/`) 2. Commit both changes to the feature branch 3. Perform the squash merge: `git merge --squash feature/story-name` 4. Commit to master with a comprehensive commit message 5. Delete the feature branch: `git branch -D feature/story-name` * **Important:** Do NOT mark acceptance criteria as complete before user acceptance. Only mark them complete when the user explicitly accepts the story. **CRITICAL - NO SUMMARY DOCUMENTS:** * **NEVER** create a separate summary document (e.g., `STORY_XX_SUMMARY.md`, `IMPLEMENTATION_NOTES.md`, etc.) * **NEVER** write terminal output to a markdown file for "documentation purposes" * The `specs/` folder IS the documentation. Keep it updated after each story. * If you find yourself typing `cat << 'EOF' > SUMMARY.md` or similar, **STOP IMMEDIATELY**. * The only files that should exist after story completion: * Updated code in `src/` * Updated specs in `specs/` * Archived story in `stories/archive/` --- ## 3.5. Bug Workflow (Simplified Path) Not everything needs to be a full story. Simple bugs can skip the story process: ### When to Use Bug Workflow * Defects in existing functionality (not new features) * State inconsistencies or data corruption * UI glitches that don't require spec changes * Performance issues with known fixes ### Bug Process 1. **Document Bug:** Create `bugs/bug-N-short-description.md` with: * **Symptom:** What the user observes * **Root Cause:** Technical explanation (if known) * **Reproduction Steps:** How to trigger the bug * **Proposed Fix:** Brief technical approach * **Workaround:** Temporary solution if available 2. **Fix Immediately:** Make minimal code changes to fix the bug 3. **Archive:** Move fixed bugs to `bugs/archive/` when complete 4. **No Spec Update Needed:** Unless the bug reveals a spec deficiency ### Bug vs Story * **Bug:** Existing functionality is broken → Fix it * **Story:** New functionality is needed → Spec it, then build it * **Spike:** Uncertainty/feasibility discovery → Run spike workflow --- ## 3.6. Spike Workflow (Research Path) Not everything needs a story or bug fix. Spikes are time-boxed investigations to reduce uncertainty. ### When to Use a Spike * Unclear root cause or feasibility * Need to compare libraries/encoders/formats * Need to validate performance constraints ### Spike Process 1. **Document Spike:** Create `spikes/spike-N-short-description.md` with: * **Question:** What you need to answer * **Hypothesis:** What you expect to be true * **Timebox:** Strict limit for the research * **Investigation Plan:** Steps/tools to use * **Findings:** Evidence and observations * **Recommendation:** Next step (Story, Bug, or No Action) 2. **Execute Research:** Stay within the timebox. No production code changes. 3. **Escalate if Needed:** If implementation is required, open a Story or Bug and follow that workflow. 4. **Archive:** Move completed spikes to `spikes/archive/`. ### Spike Output * Decision and evidence, not production code * Specs updated only if the spike changes system truth --- ## 4. Context Reset Protocol When the LLM context window fills up (or the chat gets slow/confused): 1. **Stop Coding.** 2. **Instruction:** Tell the user to open a new chat. 3. **Handoff:** The only context the new LLM needs is in the `specs/` folder. * *Prompt for New Session:* "I am working on Project X. Read `specs/00_CONTEXT.md` and `specs/tech/STACK.md`. Then look at `stories/` to see what is pending." --- ## 5. Setup Instructions (For the LLM) If a user hands you this document and says "Apply this process to my project": 1. **Analyze the Request:** Ask for the high-level goal ("What are we building?") and the tech preferences ("Rust or Python?"). 2. **Git Check:** Check if the directory is a git repository (`git status`). If not, run `git init`. 3. **Scaffold:** Run commands to create the `specs/` and `stories/` folders. 4. **Draft Context:** Write `specs/00_CONTEXT.md` based on the user's answer. 5. **Draft Stack:** Write `specs/tech/STACK.md` based on best practices for that language. 6. **Wait:** Ask the user for "Story #1". --- ## 6. Code Quality Tools **MANDATORY:** Before completing Step 4 (Verification) of any story, you MUST run all applicable linters and fix ALL errors and warnings. Zero tolerance for warnings or errors. ### TypeScript/JavaScript: Biome * **Tool:** [Biome](https://biomejs.dev/) - Fast formatter and linter * **Check Command:** `npx @biomejs/biome check src/` * **Fix Command:** `npx @biomejs/biome check --write src/` * **Unsafe Fixes:** `npx @biomejs/biome check --write --unsafe src/` * **Configuration:** `biome.json` in project root * **When to Run:** * After every code change to TypeScript/React files * Before committing any frontend changes * During Step 4 (Verification) - must show 0 errors, 0 warnings **Biome Rules to Follow:** * No `any` types (use proper TypeScript types or `unknown`) * No array index as `key` in React (use stable IDs) * No assignments in expressions (extract to separate statements) * All buttons must have explicit `type` prop (`button`, `submit`, or `reset`) * Mouse events must be accompanied by keyboard events for accessibility * Use template literals instead of string concatenation * Import types with `import type { }` syntax * Organize imports automatically ### Rust: Clippy * **Tool:** [Clippy](https://github.com/rust-lang/rust-clippy) - Rust linter * **Check Command:** `cargo clippy --all-targets --all-features` * **Fix Command:** `cargo clippy --fix --allow-dirty --allow-staged` * **When to Run:** * After every code change to Rust files * Before committing any backend changes * During Step 4 (Verification) - must show 0 errors, 0 warnings **Clippy Rules to Follow:** * No unused variables (prefix with `_` if intentionally unused) * No dead code (remove or mark with `#[allow(dead_code)]` if used conditionally) * Use `?` operator instead of explicit error handling where possible * Prefer `if let` over `match` for single-pattern matches * Use meaningful variable names * Follow Rust idioms and best practices ### Build Verification Checklist Before asking for user acceptance in Step 4: - [ ] Run `cargo clippy` (Rust) - 0 errors, 0 warnings - [ ] Run `cargo check` (Rust) - successful compilation - [ ] Run `cargo test` (Rust) - all tests pass - [ ] Run `npx @biomejs/biome check src/` (TypeScript) - 0 errors, 0 warnings - [ ] Run `npm run build` (TypeScript) - successful build - [ ] Manually test the feature works as expected - [ ] All acceptance criteria verified **Failure to meet these criteria means the story is NOT ready for acceptance.**