Story-Driven Development
Jul 1, 2026
I have been circling the same problem for a while now. AI coding agents can write code very quickly. And they write good code now, with a lot less handholding.
That changes the shape of the problem. My earlier attempts were much more about control: give the AI a rigid plan, make it follow every step, review constantly, keep it from wandering off. There is still a place for that, but rigid plans get brittle once implementation reality shows up. The model may find a cleaner path than the one I wrote down. It may discover that the original plan missed a constraint. It may need to change the order of operations.
The harder problem now is defining the end state clearly enough that I can trust the AI to work toward it. “Done” needs to be testable, concrete, and not just vibes. Something that an AI can determine for itself, without having to ask me. Then, after the work happens, I still need to know what changed, which code owns the behavior, and what evidence proves it works.
That was the big lesson from my vibe coding experiment. The AI built fast, but the codebase got harder to reason about. Then I wrapped the process in more structure with an AI coding template, which eventually turned into an AI coding toolkit. Then I started pulling more of the work into a meta-repo workflow, because I wanted the AI to see the planning context around the apps I was building.
All of those attempts helped. None of them fully solved the thing I kept wanting: a durable map of the codebase. A single source of truth for what had actually been implemented.
The Problem
The problem is not “how do I get AI to write good code?”
The problem is what happens later. A feature gets built. Tests get added. A few edge cases get patched. The UI changes. The data model shifts. A review finds something. The agent fixes it. A week later you come back and ask, “Wait, what is actually implemented here? What still needs to be implemented?”
This is bigger than AI. We have all had the experience of being onboarded into a large codebase and having no idea where anything is. There is a bug in billing, or auth, or notifications, or some weird edge case in the settings page, and the first hour is just archaeology. Which route owns this? Which service actually does the work? Is this still the current implementation, or is it an old layer nobody deleted? Is there a test for this, and if there is, does it prove the real behavior or just some helper function?
That is annoying for humans. It is also expensive for LLMs. If the agent has to burn thousands of tokens reading half the repo just to figure out where a behavior lives, you are starting from a weak place.
Traditional project management tools do not really solve this. Jira tickets and Linear issues can tell you what someone intended to do. Confluence pages can explain what people thought the system did at some point. Pull requests show the code that changed, which can be useful if you know when a bug was introduced. But none of those are a canonical, durable map of the current codebase.
That map is what I wanted SDD to become:
- What behavior exists?
- Why does it exist?
- Which code implements it?
- Which tests or checks prove it?
- Where should a human or agent start when it breaks or needs to be tweaked?
SDD, But Not The SDD You’re Thinking Of
The next version of the experiment is Story-Driven Development, or SDD for short.
I just tagged 0.3.0, which sounds more official than it really is, but I have been stress testing it on a few different repos, some created from scratch and some adapted into it. The biggest improvement so far is that cold-starting a repo feels less like archaeology.
The basic model is:
- Epic: the durable map for a product capability. It explains the current behavior, the Stories inside that capability, the important code pointers, and the evidence that proves it works.
- Story: the durable user or operator journey. This is not a Jira task. It is the behavior the application should preserve even if the implementation changes.
- Requirement: a concrete rule under a Story. This is where “what done means” starts getting precise.
- Scenario: a testable example of a Requirement, usually including the state, action, and expected result you would prove with a test or manual check.
- Implemented By: the code map. It points to the files, routes, services, components, tests, or other artifacts that matter when someone needs to understand or change the behavior of that Story.
- Verified By: the evidence map. It points to the tests, checks, review artifacts, or manual scenarios that prove the behavior of that Story works.
- Change: the temporary work record. A Change can touch one Story, several Stories, or no accepted Story yet. When the work is done, the durable map should be updated.
So the short version is: Epics map behavior to code, Stories explain the user journey, Requirements/Scenarios make that journey testable, and Implemented By / Verified By keep the map tied to reality.
This is how SDD is supposed to solve the map problem. Implemented By and Verified By are not paperwork for the sake of paperwork. They are the record of how the AI got from the intended end state to the actual implementation. If the end state is clear, the model gets room to solve the problem. If the code map is kept current, future humans and future agents can understand what it did without rediscovering the whole thing from scratch.
Why “Story”?
Yes, I know I am walking directly into naming confusion here.
I have spent about a decade as a Jira SME, so I have seen a lot of the “Agile” way of doing software up close. Some of it is useful. A lot of it, at this point, feels like theatre. Process for process’s sake. A different vocabulary for the same status meeting.
And in Agile-land, a “Story” often just means “a task wearing a little agile hat.” It gets moved across a board, maybe it survives long enough to be referenced in a sprint report, and then it disappears into the ether of completed work, never to be read again. That is not what I mean here.
I chose “Story” on purpose because the old user-story format still does one thing well:
As a <actor>, I want to <action>, so that I can <outcome>.
Yes, it has been abused into corporate Agile wallpaper. But the shape is useful because it captures the why, not just the what. It forces the document to say who the behavior is for, what they are trying to do, and why that path matters.
I have found that framing useful outside software too. One example that stuck with me was helping someone clean up a JSM space. They knew it was in bad shape. Too noisy, too confusing, too much accumulated process. But they did not know where to begin. They knew they needed to “improve” it, but what did “improve” actually mean? So instead of starting with fields, queues, request types, workflows, or automations, I had them write stories:
As the tech lead, I want to...
As an employee, I want to...
The point was not to make Jira happy. The point was to codify what would make the tech lead’s life easier and what would make the employee experience easier. Once we had that, we could work backward into the implementation: which SLAs mattered, which queues and reports were useful, what request types should exist, what information should be collected, what approvals mattered, what notifications were noise, and what workflow states were actually useful.
That is the part I do not want to lose. A Story should not just say “implemented chat provider abstraction.” It should say what user or operator path that abstraction enables. You could rewrite half the app and still preserve the same Story if the user journey is the same.
From Specs to Stories to Changes
This is where SDD connects back to Spec Driven Development.
In the AI Toolkit version, I already had project briefs, ADRs, specs, tasks, worklogs, code review phases, and TDD loops. That worked better than pure vibe coding. A lot better. But the specs were too change-shaped, and the worklogs were useful mostly while the work was happening. Nothing gave me an easy way to see the current state.
My first attempt at fixing that was to treat each Story as its own Markdown file. The skills were about creating a Story, refining it, implementing it, and moving on to the next Story. On paper, that sounded clean. In practice, it was too rigid.
Some changes were smaller than an entire Story. Some changes only affected an existing Story. Some changes cut across multiple Stories. I was slowly rebuilding an issue tracker in Markdown, which was not exactly the point.
Then I came across OpenSpec, and the part that clicked for me was the generic idea of a Change. Not necessarily their exact structure or naming, but the separation between durable specs and temporary change records.
That helped me split the model:
- Stories and Epics represent the durable state of the application.
- Changes represent the temporary work needed to move that state forward.
An Epic is not just a plan. It should include the Stories, the requirements and scenarios under those Stories, the important code pointers, and the evidence that proves the behavior. Implemented By is not meant to list every file that happens to be imported somewhere down the stack. It is meant to answer the practical onboarding question: “if I need to understand or change this behavior, where do I start?”
The code can change. The framework can change. The internal shape can change. If the user’s path and outcome have not changed, the Story probably has not changed either.
Where It Is Right Now
I have this packaged as a set of Codex skills in a public repo:
github.com/TaylorHuston/sdd-skills
That repo is the canonical place to look if you want to see how it works right now. I am intentionally not turning this post into a command-by-command manual, partly because that would be boring, and partly because the details are still changing.
I am actively testing it against several apps and refining it as I run into problems. Some of those refinements are tiny naming things. Some are bigger workflow questions, like how strict the skills should be, when to use subagents, how much review is enough, and how to keep the docs useful without creating process sludge.
A few things have already changed because of real use:
- Globally unique Story IDs sounded useful until they started feeling like ceremony.
- Verification evidence needed to be more than “the build passed.”
- ADRs came back because some decisions should not be buried in a task ledger.
Subagents are still part of the workflow, but I am less interested in creating a tiny committee for every task than I used to be. One agent implementing and another reviewing can help. It genuinely catches things. But the main agent still has to verify important claims before updating the durable map. A confident little subagent report is not truth.
The repo is truth. Or at least, that is the goal.
What Still Feels Messy
This is still a lot of process.
For small changes, SDD can feel like overkill. The skills have also been through a few rounds of me over-constraining them, because I have a tendency to add rules when something goes wrong. Sometimes that is the right move. Sometimes it turns the skill into a giant instruction document trying to control every possible path.
The thing I am trying to move toward is:
- Be strict about the outcome.
- Be flexible about the method.
- Never let Epic truth drift from implementation reality.
That last one is the non-negotiable part.
I also do not think this is automatically the right fit for teams. A solo developer and a small group of AI agents can tolerate a file-based workflow that might annoy a larger engineering org. Merge conflicts in Markdown planning files are real. Public vs private planning context is real. There are reasons Jira, Linear, Confluence, GitHub Issues, and PRs exist.
But for my current workflow, where I am building side projects with AI agents and trying to preserve context across sessions, this is working better than anything else I have tried.
The Bottom Line
My current answer to “how do you keep AI coding agents honest?” is:
- Make product behavior explicit.
- Map that behavior to code.
- Map that behavior to proof.
- Review the change like a pull request.
- Keep the map updated when reality changes.
That is Story-Driven Development, at least as I am using the term right now.
Maybe it gets simpler over time. Maybe it turns into something else.
But the operating principle feels right: if the AI changes the code, it also has to update the story of what the code does.