跪拜 Guibai
← Back to the summary

AI Writes Code Faster Than You Can Think — That's the Problem SDD Fixes

Foreword

As of July 2026, on GitHub, the SDD library spec-kit has over 120,000 stars, and OpenSpec has over 60,000 stars. Earning such high star counts on GitHub must mean there's something to it. AI coding is already so fast and so powerful, so why do we still need SDD? This article aims to discuss that.

How Do We Usually Develop with AI?

Our usual AI development process looks something like this:

Propose a requirement
↓
Let AI read the project
↓
Let AI start writing code
↓
yes, yes, yes, don't ask me again
↓
Run and test
↓
There's a bug, the requirement wasn't understood correctly
↓
Whip the AI: "You wrote this part wrong, what I meant was xxxxx"
↓
AI continues to fix it
↓
After N rounds, it's finally done
↓
I'm the best

For example, if we want to add a reminder feature to a Todo App, we just need to tell the AI:

Add a task reminder feature to the Todo App.

The AI can quickly modify the data model, add a time selection page, and then call the system notification interface.

After running it, you can indeed receive notifications.

But when you actually start testing, you might discover many issues that weren't clearly stated:

So we continue to supplement the prompts, and the AI continues to modify the code.

But it's not that the AI can't write code; it's that before writing, we didn't clearly explain the result we truly wanted. For the parts we didn't articulate, the AI can only guess. If it guesses right, the feature is completed quickly; if it guesses wrong, we have to keep modifying.

In actual development, we certainly don't just have a single requirement sentence; there's usually a requirements document. A requirements document lets us know what the feature is, but it doesn't necessarily specify clearly how it should behave or interact in every situation.

When writing test cases, testers often think of scenarios like permission failures, repeated operations, state changes, or abnormal data. This part of the thinking should be completed before code implementation; otherwise, the AI might not notice these details.

Of course, this doesn't mean writing all test cases at this stage. If the expected results are already clear and only need verification by changing devices, system versions, or data combinations, then that can be left for the testing phase.

SDD is here to solve this problem.

What is SDD?

SDD stands for Specification-Driven Development.

Simply put, before letting the AI write code, you first organize what needs to be done into a clear specification, and then generate a technical plan, tasks, and code based on that specification.

A typical process looks like this:

Propose requirement
↓
Specification: AI asks what you want to do, what conditions count as completion
↓
Plan: AI describes how it intends to implement it
↓
Tasks: AI breaks down its plan into executable tasks
↓
Implement: AI implements code according to the tasks
↓
Verify: Go back to the original specification and check if the results meet the requirements

If you've used plan mode, this process should feel familiar.

More formally:

Why Do We Need SDD?

It's because AI is too fast. It writes code so fast that before you've truly clarified the requirements, it has already finished writing. Then you look back and find that this part is wrong, that part is missing something, and you have to patch things up.

sdd_咻.png

So the problem it solves is:

The code is already written, but the requirements haven't been truly thought through.

What it does is move the problems that were originally discovered after coding to be resolved as much as possible before coding.

Before:

  1. Write code first
  2. Discover requirement omissions after running
  3. Modify requirements and code

SDD:

  1. Organize requirements first
  2. Discover omissions and confirm
  3. Then generate code

It doesn't eliminate all rework, but modifying requirements when there are only a few paragraphs of text is usually simpler than modifying them after the code has already spread across multiple modules.

Additionally, it incidentally solves another important problem, which is the context problem.

When developing directly with AI, many decisions are scattered across your chat history with the AI. If you switch sessions, switch Agents, come back after some time, or accidentally close the session, you might forget why something was implemented that way.

But Spec, Plan, and Tasks can be saved in the project alongside the code. Subsequent AIs can read them directly, without us needing to re-explain everything each time.

What Happens After Using It?

Let's use the Todo App reminder feature as an example again.

This time, we won't let the AI write code immediately. Instead, we first tell it:

Add a task reminder feature to the Todo App.

Don't modify the code yet. Help me organize the feature scope, user behavior, and acceptance criteria. For anything unclear, ask me first; don't decide on your own.

After several rounds of confirmation, we might get a simple specification:

## Goal

Users can set a reminder time for unfinished tasks.

## Acceptance Criteria

- Users can create tasks without reminders;
- After modifying the reminder time, only the new notification is kept;
- After completing or deleting a task, cancel the corresponding notification;
- After the user denies notification permissions, the page needs to show a prompt;
- After clicking a notification, open the corresponding task.
  
## Not Included

- Does not support recurring reminders;
- Does not support server-side push.

After the specification is confirmed, let the AI generate a technical plan based on the project:

Based on the confirmed specification and the current project structure, generate a technical plan. Explain which modules need to be modified and what each module is responsible for.

After the plan is confirmed, break it down into tasks:

Break down tasks based on the specification and technical plan. Each task needs clear completion conditions and verification methods.

Finally, enter the code implementation phase, and after completion, verify item by item according to the specification.

So after using SDD, the development process hasn't magically changed; you still need to write code, run tests, and check results.

What has truly changed is that the AI no longer relies solely on a single ad-hoc prompt, but works based on a set of confirmed content.

So, chat-driven coding has become specification-driven coding.

How to Use It?

It doesn't require you to install any tools; it's just a set of rules. The simplest way is to add a few files to your project and start using it:

docs/
└── specs/
  └── task-reminder/
	  ├── spec.md
	  ├── plan.md
	  └── tasks.md

Then set a few rules for yourself:

  1. Don't start design and implementation before the Spec is confirmed.
  2. Don't start breaking down tasks before the Plan is confirmed.
  3. Each task needs to explain how to verify it.
  4. If new requirements are discovered during implementation, update the Spec first.
  5. After completion, verify item by item according to the Spec.

Also, you don't need to go through the full process for every task.

The focus of SDD isn't on generating many documents, but on deciding how much content needs to be clarified in advance based on the task's complexity.

Those SDD Libraries on GitHub

Spec Kit

The full capabilities provided by spec-kit are roughly as follows. For ease of understanding, the complete process is listed here, but not every requirement must execute all steps sequentially:

Constitution (Project-level)
↓
Specify
↓
Clarify (Optional)
↓
Plan
↓
Checklist (Optional)
↓
Tasks
↓
Analyze (Optional)
↓
Implement
↓
Converge

Among these, Constitution is mainly used to define the long-term principles the project adheres to and generally doesn't need to be re-executed for every requirement.

Clarify, Checklist, and Analyze are optional commands used as needed.

Let's see what each step does.

Its entire process can be summarized as:

  1. First, determine project rules.
  2. Clarify the requirements.
  3. Find ambiguities in the requirements.
  4. Design an implementation plan.
  5. Break it down into executable tasks.
  6. Implement the code.
  7. Return to the original requirements for verification.

OpenSpec

The difference between OpenSpec and Spec Kit is that OpenSpec doesn't emphasize going through multiple stages sequentially. Instead, it treats each requirement as a change to the project.

Two types of specifications are saved simultaneously in the project:

openspec/specs/

Records the currently confirmed behavior of the system.

openspec/changes/

Records the changes currently under development.

OpenSpec provides six core Workflows by default: Explore, Propose, Apply, Update, Sync, and Archive.

Verify is not in the default Core Profile but can be enabled as needed. Their usage is roughly as follows:

sdd_openspec_流程_v3.png

For the specific process, refer to the OpenSpec OPSX documentation.

Let's see what each step does:

Explore

Explores the requirement before formally creating a change:

If the requirement is already clear, this can be skipped.

Propose

Creates an independent change directory for the requirement:

openspec/
└── changes/
  └── change-name/
	  ├── proposal.md
	  ├── specs/
	  ├── design.md
	  └── tasks.md

Where:

Specifications describe changes in the following ways:

design.md is not required for all requirements. If a change involves multiple modules, data models, external dependencies, or important technical choices, a Design needs to be written first; simple modifications can omit it.

Apply

Implements code according to the documents in the change:

This is also where OpenSpec differs from fixed-stage processes: if requirements or plans change during implementation, you can use Update to go back to previous artifacts, then continue with Apply.

Update

If requirements, technical plans, or tasks change, uses Update to modify existing change artifacts:

Update is not a fixed step that must be executed after Apply, but is used as needed when requirements or plans change.

If code has already been implemented according to the old plan, after updating the artifacts, Apply needs to be run again to align the code with the new plan.

Verify

Checks if the code conforms to the change content:

Verify is not in the Core Profile by default and needs to be manually enabled:

openspec config profile
openspec update

After checking verify in the configuration, the specific entry point depends on the Agent and Delivery used.

If using Commands Delivery, it's typically:

/opsx:verify

If using Codex's Skills Delivery, it's:

$openspec-verify-change

Complex features or cross-module modifications are suitable for executing Verify; simple, well-tested modifications can be skipped. For specific configuration methods, refer to OpenSpec Commands.

Sync

Merges the specifications from the current change into the project's main specifications:

openspec/changes/change-name/specs/ -> openspec/specs/

Sync can be actively executed during development, allowing other changes to read the latest specifications in advance.

If the feature is archived immediately after implementation, this can also be skipped and synced together during Archive.

Archive

Ends and archives the current change:

The structure after archiving is roughly:

openspec/
├── specs/
│   └── Currently valid specifications
└── changes/
  └── archive/
	  └── Completed changes

So OpenSpec's entire process can be summarized as:

  1. Understand the requirement.
  2. Establish an independent change.
  3. Describe what changes have occurred in system behavior.
  4. Implement code according to the change.
  5. When requirements or plans change, update existing artifacts.
  6. Check if the code conforms to the change content as needed.
  7. Merge the changes into the current specifications.
  8. Archive the complete development history.

cc-sdd

cc-sdd focuses most on two things:

The overall process of cc-sdd is as follows:

ssd_cc-sdd_流程.png

For the specific process, refer to cc-sdd Workflow.

Let's also see what each of its steps does:

Steering

Records the long-term context of the entire project:

Steering is mainly used for existing projects. If the Agent can already obtain complete project rules from other files, it can be used as needed.

Discovery

Determines what development approach should be taken for the current requirement:

Discovery saves a brief.md so that subsequent Agents don't need to re-understand the requirement. If it needs to be broken into multiple Specs, it also generates a roadmap.md.

So Discovery is not just about clarifying requirements; it's also responsible for judging whether this piece of work needs to enter the full SDD process.

Spec Init

Creates an independent workspace for the feature:

.kiro/
└── specs/
  └── feature-name/

The subsequent Requirements, Design, and Tasks will all be saved in this directory.

Design

Generates the technical design:

design.md will contain a File Structure Plan, used to delineate the scope of files that subsequent tasks can modify.

cc-sdd calls this step Boundary-First, meaning boundaries are determined first, then multiple Agents can work independently.

Tasks

Breaks the Design down into tasks:

Markers like the following will appear in tasks:

_Boundary: What this task can modify
_Depends: What this task depends on

This way, when an Agent executes a task, it won't arbitrarily modify modules outside its scope.

Spec Batch

If Discovery determines the requirement is too large, you can use:

/kiro-spec-batch

It will:

Implementation

After the specification is confirmed, use:

/kiro-impl

cc-sdd supports two implementation modes.

Automatic mode:

Manual mode:

For specific execution methods, refer to cc-sdd Skill Reference.

Validation

Checks the final result after multiple tasks are combined:

The correctness of individual tasks is mainly checked by the Reviewer Agent; Validation focuses more on whether the combination of multiple tasks can still work correctly.

The Core of cc-sdd

cc-sdd doesn't view Spec as a master document controlling all implementation details.

It tends to view Spec more as a contract between modules:

The specific implementation can still be freely decided by the Agent, but it cannot cross the confirmed boundaries. cc-sdd's design explanation also explicitly states that code is still the final running truth, and Spec is responsible for making responsibilities and boundaries clear.

So cc-sdd's entire process can be summarized as:

  1. First, determine if a Spec is needed.
  2. Break the requirement into independently deliverable scopes.
  3. Clarify module boundaries and dependencies.
  4. Break it down into individual tasks.
  5. Have different Agents implement and review.
  6. Finally, verify that the tasks can correctly collaborate with each other.

What Are Their Differences?

After looking at the flurry of processes above, you'll find they all do the same thing: first turn the requirement into a Spec, then generate a design, tasks, and code.

The difference lies in the problems they focus on.

Spec Kit focuses more on whether the requirements, plan, and tasks are complete and consistent.

It provides a full set of capabilities around requirements, design, and tasks, and uses Clarify, Checklist, and Analyze as needed based on task complexity.

It's asking:

Has this requirement been completely specified and implemented?

OpenSpec focuses more on what changes have occurred in the project.

It records each requirement as an independent change, merges it into the project's current specifications after completion, and preserves a complete change history.

It's asking:

What did this development add, modify, or delete from the existing system?

cc-sdd focuses more on how tasks should be broken down and how Agents should execute them.

It first clarifies module boundaries and task dependencies, then lets different Agents be responsible for implementation, review, and verification respectively.

It's asking:

How can the work be divided so that Agents can execute for a long time without interfering with each other?

So simply put:

What is TDD?

After talking about SDD, let's talk about TDD.

TDD stands for Test-Driven Development. It's not about writing tests after the code is finished, but developing iteratively according to the following process:

First write a test and confirm it fails (Red)
↓
Write just enough code to make the test pass (Green)
↓
Refactor the code while the tests still pass (Refactor)
↓
Continue implementing the next behavior

For example, SDD first specifies:

After completing a task, the corresponding reminder needs to be cancelled.

At the TDD stage, you would first write a test for this behavior, then implement the code to cancel the reminder, until the test passes.

It and SDD are not an either/or relationship; the problems they solve are different:

SDD first decides which behaviors should be implemented, and TDD then uses tests to implement these behaviors one by one.

They are not on the same level. You can understand TDD as an optional development method within the Implement stage of SDD:

SDD tools handle the outer process

Specification
↓
Design
↓
Tasks
↓
Implementation
↓
Verification

In the "Implementation" step,
you can choose to use TDD

Let's use the Todo reminder feature as an example again.

Initially, we discovered a problem:

After the user completes a task, should the reminder still trigger?

This problem should be handled by SDD, because at this point, we don't even know what the correct result is. After confirmation, the specification states:

After the user completes a task, the corresponding reminder needs to be cancelled.

Next, entering the implementation phase, TDD starts to play its role:

  1. First write a test: After completing a task, the method to cancel the reminder should be called.
  2. Run the test; because the code hasn't been implemented yet, the test fails.
  3. Write the code to cancel the reminder, making the test pass.
  4. Refactor the code, then continue implementing the next behavior.

Therefore:

TDD won't decide for you whether the reminder should be cancelled after completing a task. If the requirement doesn't mention permission failure, TDD won't magically supplement that scenario for you. It can only, after the expected result is determined, turn that result into a test and then drive the code implementation.

Also, SDD does not require the use of TDD. Among the libraries just mentioned, cc-sdd explicitly puts TDD into the implementation process; Spec Kit can generate test-first tasks as needed; OpenSpec does not restrict the specific implementation method. TDD is a development method that can be adopted when SDD enters the code implementation phase.

Do You Need to Build Your Own SDD?

Actually, after reading this, you might find that they are all very powerful, but they might not perfectly fit your usual development process. Fortunately, we can build our own custom SDD.

The key here is what you care about, what you hope the AI can help you achieve, and to standardize this process.

Taking myself as an example, what I care about is:

But after listing these, I found that OpenSpec actually fits my needs quite well, so the grand undertaking of building my own SDD has been put on hold for now. This is just a sharing of an idea to spark discussion. I might introduce the TDD process later, but we'll see.

Comments

Top 1 from juejin.cn, machine-translated. The original thread is authoritative.

用户3353606041416

Very well written.