Skip to content

OpenSpec 规范驱动开发(SDD)详解

规范驱动开发的核心在于权力的反转:规范驱动需求迭代,代码只是规范的实现。 规范是需求实现的第一等公民。

在上文中, 我们介绍了 SDD 的诞生背景和核心理念, 强调了规范驱动开发的核心是使用规范来生成代码从而实现需求。

在这篇文章中我们将介绍 OpenSpec 如何在存量代码中接入 SDD 流程, 并实现规范驱动开发。

在理解 OpenSpec 之前,我们先理解规范驱动开发的本质(上下文维护):在代码工程中同时维护一套结构化的规范文档,AI 编程工具在和 LLM 交互时,向这些文档中提取合适的内容作为 prompt 向 LLM 提问,从而实现需求。 所以不管是 OpenSpec 还是其他 SDD 工具,都需要在项目中维护一套结构化的规范文档, 且不需要收费、API 密钥等。

OpenSpec 工作流和文档结构

OpenSpec 会在项目中生成 openspec/ 来维护项目的规范文档, 为了更好的理解 openspec/ 目录, 先看一下 OpenSpec 提供的AI 编程工作流程:

  1. 描写需求:首先起草一份包含你想要的规格更新的变更提案。
  2. 验证需求:让 AI 助手审查并澄清你的变更提案。
  3. 实现需求:让 AI 助手根据你的变更提案生成代码。
  4. 如果实现不满足需求,就更新需求描述,然后再次实现需求并验证, 知道满足需求为止。
  5. 归档需求:将满足需求的变更提案归档到规范文档中。

当在项目中初始化一个 OpenSpec 项目时, 会生成一个 openspec/ 目录, 目录结构如下:

openspec/
├── changes/
├── specs
├── AGENTS.md
├── project.md
AGENTS.md

最外侧的 AGENTS.md 文档, 用来针对参与本项目的 AI 助手, 例如 cursor、Claude Code 等, 告诉这些 AI 助手使用 openspec/ 目录接管规范驱动开发。

openspec/ 目录是规范文档的目录, 用来维护项目的规范文档。其中:

  1. AGENTS.md 用来告诉 AI 助手使用 openspec/ 目录接管规范驱动开发工作流, 例如 /openspec-proposal, /openspec-apply, /openspec-archive 等命令。
  2. project.md 用来定义项目级别的规范、标准、架构模式和其他应在所有变更中遵循的指南。
  3. changes/ 目录用来存储变更提案, OpenSpec 工作流关于变更提案 评审对齐任务实施 都会在这个目录进行,下面实践时会详细介绍。
  4. specs/ 目录用来存储已经被验证通过的规范文档,这个就是我们提到的权利反转中的规范文档。

OpenSpec 的接入和初始化流程

OpenSpec 支持市面上大部分 AI 编程工具的接入, 结合上面对规范驱动开发的本质的理解,和 OpenSpec 的工作流和文档结构, 我们可以很容易在任何你熟悉的 AI 编程工具中接入 OpenSpec 进行规范驱动开发。

下面以在 Cursor 中接入 OpenSpec 为例, 介绍如何使用 OpenSpec 进行规范驱动开发。

1. 安装与初始化

全局安装 CLI, 要求: Node.js >= 20.19.0

bash
# npm
npm install -g @fission-ai/openspec@latest

# pnpm
pnpm add -g @fission-ai/openspec@latest

# bun
bun install --g @fission-ai/openspec@latest

验证安装

bash
openspec --version

2. 在项目中初始化 OpenSpec

运行初始化

bash
# /my-project 
openspec init

初始化过程中会发生什么:

  1. 被提示选择任何原生支持的 AI 工具,并在项目根目录产生一个 AGENTS.md,该文件的作用上面已做了说明。
  2. 在项目中创建一个新的 openspec/ 目录
  3. .cursor/commands 目录下创建 openspec-apply openspec-archive openspec-proposal 三个命令文件, 用来触发 OpenSpec 的工作流。

设置完成后:AI 工具无需额外配置即可触发 /openspec 工作流

3. 填充项目上下文

openspec init 完成后,您将收到一个建议提示,以帮助填充您的项目上下文:

Please read openspec/project.md and help me fill it out
with details about my project, tech stack, and conventions

我们直接把这段话丢给 Cursor 来生成项目级别的规范、标准、架构模式和其他应在所有变更中遵循的指南 并填充到 openspec/project.md , 我们也可以手动调整生成的内容。

OpenSpec 驱动的开发流程实践

完成了 OpenSpec 的全部准备工作, 下面开始进入到日常的 规范驱动开发 环节, 我们以 新增一个 API 为例, 介绍如何使用 OpenSpec 进行规范驱动开发。

1.创建需求提案

上面提到在使用 openspec init 初始化过程中, 会创建 .cursor/commands/openspec-xxx.md 文件, 用来触发 OpenSpec 的工作流。

/openspec-proposal.md 用来注册 OpenSpec 的命令, 当我们使用 /openspec-proposal 命令时, Cursor 会调用这个命令来创建需求提案。

使用 /openspec-proposal 命令创建需求提案:

2. 验证与审查

先跳过AI 工具的整个生成提案的过程,看一下 OpenSpec 生成的提案文件, 验证提案的正确性。

changes/ 目录下, 会生成一个以AI工具根据提案需求命名的提案目录,用来提案的相关文件。

specs/ 目录用来存储还没有被验证通过的规范文档,可以看成是需求文档

proposal.md 有点类似于技术方案,会根据 project.md 中定义的全局规范生成一个包含需求背景、需求改动点、影响范围等方面描述整个需求的实施方案。

tasks.md 是对 proposal.md 方案中的任务分解,会列出每一个步骤要做的事情和完成情况。

在实际的开发中, 每次提案我们都要通过查看并修改 spec.md proposal.md tasks.md 文件来分别了解需求是否描述正确、技术方案是否满足需求和任务指定、完成情况, 确保每次提案的正确性。

OpenSpec 提供了一套命令行工具, 能协助更快验证 openspec list(确认更改文件夹是否存在)、 openspec validate xxx(验证规范格式)、openspec show xxx(审查提案、任务与规格差异) 等命令。

3. 实现变更

当对提案反复修改确保提案的正确性后, 我们就可以使用 /openspec-apply 变更名称 命令来实现变更。

使用 openspec list 命令查看变更列表

OpenSpec 会读取 proposal.mdtasks.md 和相关代码,开始实施,实施过程中持续验证实现并更新任务清单,直到实现满足需求为止。

当实施完成后我们可以查看更新的代码和任务完成情况, 可以看到所有步骤已经标记为 [x](已完成状态)

4. 调整提案和任务(可选)

当发现实现不满足需求时, 我们可以修改对应的 proposal.mdtasks.md 来调整或补充需求。

例如下面是生成的 api 定义, 我们发现对返回结果未做定义

ts
/**
 * 查询样板间类型列表
 * @param params - 查询参数
 * @returns 分页结果
 */
export const getShowroomTypeList = (params: { pageSize: number; pageNum: number; name?: string }) =>
  useApi<Record<string, unknown>>("/platform/v1/fullLink/showRoomType/pageList", {
    params,
  });

通过查看 proposal.mdtasks.md 后发现是在 tasks.md 中关于类型定义和处理设置了可选, 不强制

## 3. 类型定义处理

- [x] 3.1 检查 `ShowroomTypeListParam` 和 `ShowroomTypeItem` 类型是否已在全局类型文件中定义
- [x] 3.2 如果未定义,考虑是否需要迁移到 `@/types/` 目录(可选,本次不强制)

我们对这个任务进行调整,并更新任务状态

## 3. 类型定义处理

- [x] 3.1 检查 `ShowroomTypeListParam` 和 `ShowroomTypeItem` 类型是否已在全局类型文件中定义
- [ ] 3.2 如果 `ShowroomTypeItem` 未定义,在 `@/types/` 目录中定义,  api 中引用, 并调整对应的返回值

使用 /openspec-apply 重新实现变更

5. 归档需求

当需求实现满足需求时, 我们可以使用 /openspec-archive 命令来归档需求。

OpenSpec 会验证变更状态,然后把 /changes/xxx/specs/xx/spec.md 提案变更规范移动到 specs/ 目录下, 作为后续开发相关功能的指导规范。 同时 OpenSpec 也会把本次提案作为变更历史存放到 changes/archive/ 目录下存档,使用 YYYY-MM-DD-xxx/ 命名作为后续追溯的依据。

OpenSpec 最终的项目规范结构如下:

整个驱动开发的过程遵循 提出变更 -> 验证与审查 -> 实现变更 -> 调整提案和任务(可选) -> 归档需求 的流程

并且随着规范文档的积累, 对于重复性需求有相关性的需求基于历史规范文档,OpenSpec 提案环节对于生成的 specs 会越来越符合需求(尤其是对于复杂性需求)、 对 proposal 的指定会更加准确和符合当前项目架构、 对 tasks 的拆分会更加合理和符合当前项目实际情况。

OpenSpec 使用总结

  1. 初始化: 使用 openspec init 初始化项目
  2. 提供一套完整的规范驱动开发工作流, 包括提出变更 -> 验证与审查 -> 实现变更 -> 调整提案和任务(可选) -> 归档需求
  3. 对于支持 OpenSpec 的大部分 AI 工具, 提供 @openspec-proposal, @openspec-apply @openspec-archive 三个命令, 分别执行提案实现变更归档需求 来支持 OpenSpec 工作流。
  4. 配合现在主流的 AI 工具提供的任务并发能力, 我们可以提出多个变更并在审查后,并行实现变更, 从而提高开发效率。
  5. 规范驱动开发并非银弹, 需要结合实际情况和团队实际情况进行调整和优化, 例如只是一个很小的改动, 比如例子中的添加接口 🤣, 直接在代码中修改即可, 没必要使用规范驱动开发。
  6. 在团队开发中:
    1. 需要把 openspec/ 目录纳入到版本管理中, 并且每次提交时, 需要提交 openspec/ 目录下的所有文件。
    2. 统一AI 工具和 LLM, OpenSpec 只是提供了一套 prompt 和规范文档结构,准确性还是需要依赖 AI 工具底层的 LLM

公众号会持续输出,欢迎关注。 如果对你有帮助,欢迎点赞、收藏、关注。