如何在复杂业务系统中有效落地 SDD(Spec-Driven Development)

本文介绍了 Spec-Driven Development (SDD) 以及 OpenSpec 工具的使用,对比了两种 SDD 方案,并分享了在落地 SDD 过程中可能遇到的问题及解决方案。

原文标题:SDD 如何在复杂业务系统中真正落地?

原文作者:阿里云开发者

冷月清谈:

本文深入探讨了如何在复杂业务系统中落地 Spec-Driven Development (SDD),并以 OpenSpec 为例,详细介绍了其 CLI 工具的使用方法、目录结构以及与 AI 辅助编程的结合。文章剖析了传统系分文档在敏捷开发中的局限性,阐述了 SDD 如何借助 AI 解决上下文窗口限制、项目规范理解和代码 Review 等问题。通过实际案例,展示了 OpenSpec 在需求分析、任务拆解和规格定义方面的应用,并对比了 OpenSpec 与 GitHub Spec Kit 的设计哲学和适用场景,为读者提供了选择 SDD 工具的参考。此外,文章还分享了在 OpenSpec 使用过程中可能遇到的问题及解决方案,以及作者根据自身经验总结的提示词和完整流程,旨在帮助读者更好地理解和应用 SDD。

怜星夜思:

1、在你的团队中,你认为推广 SDD (Spec-Driven Development) 的最大阻力会是什么?你会如何克服这些阻力?
2、OpenSpec 和 GitHub Spec Kit 适用于不同的场景,你认为在什么情况下,选择轻量级的 OpenSpec 会比重量级的 GitHub Spec Kit 更有优势?反之呢?
3、文章提到了 AI 在 SDD 中的作用,你认为未来 AI 还能在 SDD 的哪些环节发挥更大的作用?

原文内容

发展历史

全称:spec-driven develop,spec 是 specification 的缩写,代表规范,我们以 OpenSpec 这个库为例。

CLI 基础使用

项目初始化 (Setup)

  • openspec init
  • 作用在当前目录下初始化 OpenSpec。
  • 行为
  • 创建 .openspec/  openspec/ 目录结构。
  • 生成 project.md(项目上下文)和 AGENTS.md(AI 说明书)。
  • 询问你使用的 AI 工具(Cursor, Copilot 等)并生成对应的配置文件。
  • 何时用刚把 OpenSpec 引入项目时。
  • openspec update
  • 作用更新 OpenSpec 的配置和 Agent 文档。
  • 行为如果你升级了 npm 包,或者想重新生成 AGENTS.md,运行此命令。它会确保你的 AI 提示词是最新的。
  • 何时用感觉 AI 变笨了,或者升级了 OpenSpec 版本后。

日常开发流 (Workflow)

  • openspec list
  • 作用列出当前所有“进行中”的变更(Active Changes)。
  • 显示会显示变更 ID(Change ID)、状态、以及 tasks.md 里的任务完成进度(例如 [2/5])。
  • 何时用想知道现在有哪些活儿没干完时。
  • 参数
  • --specs: 列出已归档的 Specs(查看现在的系统“真理”)。
  • openspec show <change-id>
  • 作用输出某个变更的详细信息(通常以 JSON 格式)。
  • 行为这个命令主要是给 AI 看的。当 AI 需要读取某个 Spec 的全部细节时,它会在后台运行这个命令。
  • 参数
  • --json: 强制输出 JSON 格式。
  • --deltas-only: 只看变更的部分。
  • openspec view (部分版本支持)
  • 作用启动一个终端内的可视化界面(TUI)。
  • 行为以更图形化的方式展示任务进度条。

质量控制 (Quality Control)

  • openspec validate <change-id>
  • 作用检查你的 Spec 文档格式是否标准。
  • 行为它会检查:
  • Markdown 的 Frontmatter 是否正确。
  • tasks.md 里是否有未完成的任务。
  • proposal.md 结构是否完整。
  • 参数
  • --strict: 开启严格模式,任何小格式错误都会报错(推荐 AI 使用)。

结束与归档 (Finish)

  • openspec archive <change-id>
  • 作用将一个变更“合并”到主 Specs 库中。
  • 行为
  •  changes/<id> 目录移动到 changes/archive/<id>
  • 关键动作把该变更中 spec.md 的内容,合并/更新到 openspec/specs/ 目录下的长期文档中。
  • 参数
  • --yes / -y: 自动确认,不询问(AI 自动执行时通常带这个)。

其他 (Utility)

  • openspec version
  • 查看当前安装的版本。
  • openspec help
  • 查看帮助文档。
💡 核心区别:CLI 命令 vs. AI 指令

初学者容易混淆 终端命令  Cursor 斜杠命令,它们的关系如下:

总结

  • AI (Prompt) 负责:创造(写文档、写代码)。
  • CLI (Terminal) 负责:管理(初始化、列出、验证、移动文件)。

平时你最常用的 CLI 命令应该只有两个:openspec list (看进度) 和 openspec update (维护)。其他的通常都由 AI 代劳了。

目录结构

一看这个 spec 的描述是不是很像我们要求的系分文档?从我的角度上看,他比系分更全面,也更符合当前的实际开发流程。

openspec/
├── project.md              # Project conventions
├── specs/                  # Current truth - what IS built
│   └── [capability]/       # Single focused capability
│       ├── spec.md         # Requirements and scenarios
│       └── design.md       # Technical patterns
├── changes/                # Proposals - what SHOULD change
│   ├── [change-name]/
│   │   ├── proposal.md     # Why, what, impact
│   │   ├── tasks.md        # Implementation checklist
│   │   ├── design.md       # Technical decisions(optional; see criteria)
│   │   └── specs/          # Delta changes
│   │       └── [capability]/
│   │           └── spec.md # ADDED/MODIFIED/REMOVED
│   └── archive/            # Completed changes

系分存在的问题

  • 工期紧张下无法考虑周全;
  • 在实际开发中可能存在变动,但系分已经过时;
  • 作为一个研发标准,对研发更多是一种负担?(OS:我已经想清楚了,为什么还要我写个文档)毕竟大部分人都不爱写很规范的文档。

为什么我们又开始重视它

大家应该都知道,在目前这个阶段,claude 写的代码足以覆盖任何我们碰到的场景(或者对我来说足够了),我们原先的旧有的提效方式,组件库、动态表单、低代码搭建,他是稳定的提效方案,但对于 AI 来说,他们具有的上手成本、研发体验也都是负担。对于 AI 来说,如果都是开源的内容,他一天就可以帮我构建出一个系统,在旧有的提效方案上仍然不是一个级别。

但 AI 存在上下文窗口限制导致的幻觉;不理解项目规范、旧有实现,变更都在破坏旧有结构;代码 review 的负担(我一直觉得这是一个伪命题,你除非自己已经在脑子中完全构建了一遍细节,要不然怎么可能能发现一些细节的问题)。

所以社区又重新开始用它来作为 AI 辅助编程的一种开发范式,之前是 TDD,通过测试来保证,因为我们只用对功能负责,如果他的功能是正常的,那实现复杂一些或者丑陋一些是历史债务,总会有个幸运儿来接手的,或者我们称他为 AI 善后工程师。

解决一个 bug 的最好时机永远是引入的阶段,所以 TDD 这种后驱黑盒的方式并不能给你带来安全感。因为你知道实际你在把赌注押在 AI 没有幻觉。但很可惜他有。

传统的 SDD 之所以让人讨厌,是因为写 Spec 的是人,写 code 的也是人。

因为 AI 把我们的生产关系变了,现在写 spec 的是 AI,review 的是人,写 code 的还是 AI,我们从 review 代码变成了 review 设计。

实际需求

我们来看一个待开发的的目录结构和文件。

./
├── proposal.md // 代表的是我们的草案内容,他里面存放的是我们给到 LLM 的需求总结。
├── specs
│   └── artifact-notification
│       └── spec.md // 我们事实对应的规格文件
└── tasks.md // 拆分的任务 TODO LIST
# Change: 移动端支持 PPT 大纲生成完成通知

Why

目前 PC 端已实现在 PPT 大纲生成完成时的全局通知功能,但在移动端该功能被明确禁用。为了提供一致的用户体验,需要在移动端也支持该通知,但考虑到移动端屏幕尺寸和交互习惯,需要采用底部的 Snackbar 样式而非 PC 端的右上角通知。

What Changes

- 修改 showPPTOutlineNotification 逻辑,移除对移动端的禁用限制。
- 新增移动端专用的 Snackbar 通知组件/样式。
- 移动端通知显示在页面底部。
- 移动端通知内容和交互逻辑("去查看"按钮)与 PC 端保持一致。

Impact

Affected Specsartifact-notification
Affected Code
  - src/xxx/Chat.tsx
  - 新增 Mobile Snackbar 组件 (待定位置,可能在 src/components 或就在 Chat.tsx 内部实现)

## 1. Implementation

 1.1 设计并实现移动端 Snackbar 组件
  -  1.1.1 创建 MobileSnackbar 组件 (或复用现有组件库的类似组件)
  -  1.1.2 实现底部弹出动画和样式
  -  1.1.3 支持自定义内容和操作按钮
 1.2 修改通知触发逻辑
  -  1.2.1 在 xxx.tsx 中修改 showPPTOutlineNotification
  -  1.2.2 移除 if (isMobileDevice()) return; 判断
  -  1.2.3 根据设备类型分发不同的通知展示方式 (PC 使用 notification.info, Mobile 使用新 Snackbar)
 1.3 验证与测试
  -  1.3.1 验证移动端触发时机是否正确
  -  1.3.2 验证移动端样式是否符合设计 (底部 Snackbar)
  -  1.3.3 验证"去查看"按钮在移动端是否正常工作

## MODIFIED Requirements

Requirement: PPT 大纲生成完成通知

系统 SHALL 在检测到智能体中断并首次生成 PPT 大纲时,如果用户当前未选中该产物,自动显示通知提醒用户。

Scenario: 触发通知显示

GIVEN 用户在使用智能体对话(PC 端或移动端)
AND 系统接收到中断消息
AND 用户当前选中的内容不是该产物
WHEN 系统处理中断消息完成
THEN 系统显示一个通知
AND PC 端显示为右上角全局通知,移动端显示为底部 Snackbar 通知
AND 通知标题为"大纲生成完成"
AND 通知内容为"{产物名称} 大纲内容已生成,请确认大纲内容"
AND 通知包含一个"去查看"按钮
AND 通知不会自动关闭(需要用户手动关闭)

Scenario: 点击"去查看"按钮

GIVEN PPT 大纲生成完成通知已显示
WHEN 用户点击通知中的"去查看"按钮
THEN 系统调用 xxx 方法
AND 传入参数包含:
  - id: 当前产物的 artifactId
AND 工作面板切换到所有文件面板并选中对应产物
AND 通知自动关闭

Scenario: 移动端显示底部 Snackbar 通知

GIVEN 用户在移动端使用智能体对话
AND 触发了 PPT 大纲生成完成通知
WHEN 通知显示时
THEN 通知以 Snackbar 形式出现在屏幕底部
AND 样式区别于 PC 端通知,适配移动端屏幕

Scenario: 用户已选中该产物时不显示通知

GIVEN 用户在 PC 端或移动端使用智能体对话
AND 智能体处于中断状态并生成了 PPT 大纲
AND 用户当前选中的内容就是该产物
WHEN 组件检测到 canEdit 状态变化
THEN 系统不显示通知

Scenario: 避免重复通知

GIVEN PPT 大纲生成完成通知已经显示过一次
WHEN 组件重新渲染但 canEdit 状态未发生实际变化
THEN 系统不再重复显示通知


集成 IDE 使用

cursor 对 openspec 进行了天然的支持,开箱即用。

其他支持自定义命令的可以通过配置自定义命令来实现,提示词咱主打一个直接借鉴(先抄一版 cursor的)。

知易行难

重复需求未被检测到

场景:多人协作或者新人加入时,他想开发一个功能,其实已经在归档里已经有了,但是他输入后仍然触发了新的需求。

Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, 
and inspect related code ordocs(e.g., via `rg`/`ls`) to ground the proposal 
in current behaviour; note any gaps that require clarification.

通过 openspec-propoasl 进行已归档需求测试时,他并没有想象的那么美好,我尝试了两个 AI IDE 都帮我重新生成了一份文档,问题出在哪里?LLM(大模型)Prompt 工程与 IDE 实际执行能力之间的鸿沟。

我们来看他提示词里 steps,第一步他描述了 review openspec 下的内容,但是他是通过 run xxx 这依赖agent 的终端执行能力,如果因为一些原因失败了,他又会给你生成一份新的了。

  • 他觉得他执行了,但实际没执行(非 agent 模式)
  • 他执行了,他失败了

解法:

问题的核心是因为,openspec 本身是一个 cli 命令工具,cursor 似乎也对自己的命令执行很有自信,但真实的环境总是复杂的,就像软件总会有 bug 一样。

那我们就把命令执行的方案改为依赖 IDE 目前的 codebase,让他强制总是先去读目录下的文件(我们已经在最终完整版的命令里添加,这里不再赘述相关代码)。

草案生成后如何修改

直接使用修改对应的文件。

我们可以看到无论是 cursor 天然支持的命令还是他自己的 CLI 好像都没有提供 update 这个场景。

官方针对这个没有任何说明, AI 给了我一个回答,感觉也合理。

这是一个非常深刻的产品设计问题。

你没看错,OpenSpec 的设计哲学里确实故意“遗漏”了 update 这个动作。
这并不是开发者忘了做,而是基于 “文档即真理(Docs as Code)” 和 “不可变历史” 这两个核心设计理念。
以下是为什么没有 /openspec-update 的 4 个核心原因:

1. 哲学原因:编辑文档不需要“命令”

OpenSpec 把 Markdown 文档看作是代码的一部分。
*   类比 Git:你在修改代码逻辑时,需要运行 git update-code 吗?不需要。你直接打开文件编辑,然后保存。
*   OpenSpec 逻辑
    *   如果你想改需求,直接打开 spec.md 改文字。
    *   如果你想改计划,直接打开 tasks.md 改列表。
    *   “修改”是编辑器的基础功能,不是 CLI 的功能。
引入一个 /openspec-update 命令反而会显得多余:因为 AI 的修改本质上就是“读取文件 -> 覆写文件”,这在自然语言对话中(“把登录改成支持手机号”)已经涵盖了。

2. 流程原因:Proposal 包含了 Update

在 OpenSpec 的定义里,Proposal(提案)是一个持续迭代的过程,而不是一次性的动作。
*   第一次运行 /openspec-proposal = 从 0 到 1 创建文档。
*   第二次运行 /openspec-proposal = 基于现有文档进行修改(迭代)。
在 Cursor 的 Prompt 逻辑里,/openspec-proposal 的定义其实包含了“Review gaps”和“Draft spec deltas”。
如果你对 AI 说:“/openspec-proposal 之前的方案太复杂了,简化一下”,AI 会直接修改现有的文件。所以在 AI 看来,Create 和 Update 是同一个能力的两个面。

3. 架构原因:避免“状态地狱”

如果引入了 update 命令,就会带来状态管理的复杂性:
*   “我是要在 apply 之前 update,还是之后 update?”
*   “Update 是重置任务,还是保留进度?”
OpenSpec 选择了最简单的路径:
*   没有状态锁:文件随时可改。
*   执行驱动/openspec-apply 永远只看当前这一刻的 tasks.md。不管你是刚生成的,还是手动改了 100 次的,Apply 只负责执行当下。

4. 归档逻辑:已完成的不可 Update

对于已经 Archive(归档) 的需求,OpenSpec 严禁使用 update
*   历史不可篡改:归档等于“合同已结案”。
*   新变更:如果你要改旧功能,必须发起一个新的 new (Proposal)。
*   CLI 里的 openspec update
    *   注意,CLI 确实有一个 openspec update 命令,但它的作用是更新 AGENTS.md 和配置文件(升级库本身),而不是更新你的业务 Spec。

最佳实践:当你真的想 “Update” 时该怎么办?

虽然没有这个命令,但在实际操作中,你可以通过以下三种方式达成 “Update” 的目的:

方式 A:手动修改(最推荐,最快)

直接在编辑器里打开 openspec/changes/xxx/spec.md,删掉不想要的,加上想要的。
*   优势:人类改文档比跟 AI 废话要快得多,且精准。

方式 B:复用 Proposal 命令

直接再次输入:
> /openspec-proposal 需求有变,请把数据库改成 MongoDB,并更新 spec 和 tasks。
*   效果:AI 会覆写当前目录下的文档。

方式 C:在 Apply 时“挟持”

在执行前临时变卦:
> /openspec-apply 注意:在执行前,请先更新 tasks.md,去掉所有关于 Redis 的步骤。

总结

OpenSpec 没有 update,因为 Markdown 文件本身就是可变的接口。
它鼓励你:
1.  Draft (起草/迭代) -> 复用 /openspec-proposal 或直接编辑。
2.  Apply (执行) -> 照着文档做。
3.  Archive (归档) -> 封存,下次再来请开新单。

这种“少即是多”的设计,反而避免了在复杂的命令参数中迷路。

他提供的核心能力其实是文档管理功能,而文档本身就是可编辑的。考虑极端一些的场景,他其实只是给我们对已有功能进行归档。我如果抛开 AI,他的逻辑也是成立的,只是他的存在正好可以让大模型从搜索代码到先搜索总结后的功能。

手动进行修改是他的哲学设计,但基于此也会延伸出来一个问题。

没有特殊的 prompt 约束,模型并不知道一个 change 下的文件是需要联动更新的,但是实际上他们是依赖关系。

我们还是需要自定义一个 openspec-update 命令,来处于需求变更的场景,让 prompt 只专注在修改changes 下的文件内容。当用户调用它时,他会查询当前还未归档的变更,如果存在多个需要跟用户手动确认是作用于哪一个变更。我们已经在最终完整版的命令里添加,这里不再赘述相关代码

当我们运行归档时,他怎么知道要归档到哪里

我们回看标准目录,其实答案已经藏在那里。他是通过 changes/[change-name]/specs/[capability]capability 来决定的,如果你发现有问题,因为这个不涉及到文件的联动更新,直接手动修改即可。

归档错误

我在执行一次之前归档需求的优化时碰到了报错

MODIFIED failed for header "### Requirement: xx" - not found Aborted. No files were changed.

我们看到这个报错写的是变更的时候需求未找到。当处于变更状态下,变更的 specs 文件里会标明原有的需求是什么,我们当前这次 specs 里的需求跟原来归档的需求不一致,所以发生了这个问题。

临时解法:

这时候我们需要做以下几步检查

  • 你当前的变更仍然在 openspec/changes 目录下还是已经被移动了 openspec/changes/archive下,如果是后者,你需要先把文件移动回来;
  • 然后确认你的 spec 的需求已经和归档的保持一致;
  • 重新运行 openspec/archive 命令;

长期解法:

针对命令执行报错的场景,我们需要在提示词中都显式声明,告诉他应该立即停止,然后抛出对应的信息,让用户进行手动验证。(我们已经在最终完整版的命令里添加,这里不再赘述相关代码

不同的编辑器显示可能不同,功能符合我们的预期即可。

变更需求后归档的 spec 被覆盖

场景:当我存在一个已经归档的需求,然后我发现了一个 bug,这时候我告诉他需求变更,他的 specs 文件里标明的是 MODIFIED 的,当我完成归档后,发现初始归档的内容被覆盖了。

核心问题:在 spec 的世界里只有三种动作

  • ADDED
  • MODIFIED
  • REMOVED

而 MODIFIED 对他来说意味的就是需求变更,是文件覆盖操作,与我们的开发心智是存在一些区别的,他提倡的是增量式更新。

解法:

在任意变更前都先明确你的变更预期,检查 changes 下的 spec 文件的 动作。

#### 1. ADDED (追加/新增)
*   **定义**:向 Spec 文件中**插入**新的 `Requirement` 或 `Scenario`。
*   **心智模型**:`Array.push(newScenario)` 或 `File.append(text)`。
*   **典型场景**:
    *   新功能上线(废话)。
    *   **优化需求(扩展型)**:比如“登录增加验证码”、“列表增加筛选功能”。虽然你在“优化”列表,但你在文档里是**加了一段描述**,并没有删改原来的列表查询逻辑。
    *   **边缘情况补全**:比如“增加网络超时的处理逻辑”。

2. MODIFIED (覆盖/修改)

*   定义替换 Spec 文件中已存在的某个 Scenario 的全部内容。
*   心智模型Map.set(existingKey, newValue) 或 Overwrite
*   危险性:warning: 高。因为它会丢弃旧的逻辑。
*   典型场景
    *   业务规则变更:比如“积分获取规则从 10元1分 变成 20元1分”。
    *   Bug 修复(逻辑错误的):原来的 Spec 写错了(比如写成“允许空密码”),现在要修正这个错误。
    *   重构(导致行为变化的):比如“同步处理改为异步处理,用户不再立即收到结果”。

3. REMOVED (删除)

*   定义:从 Spec 文件中移除某个 Scenario
*   心智模型Array.filter(item =&gt; item.id !== id)
*   典型场景
    *   功能下线。
    *   简化产品,砍掉不常用的功能。


顺便一提

大家可以看到一个趋势,目前社区的趋势已经从模型自身的军备竞赛回归到了我们熟悉的工程化,在工程化落地阶段有很多可以做的事情。cc 和 cursor 都是调用 claude,为什么 cc 比 cursor 强。因为他要求你先规划,再执行。现在大家跟进的 plan 模式也是一样。

plan 模式和 spec 在单一对话上很像,他也提供了保存到本地的能力,大家在做的事其实是一样的,都是为了让模型有一个更稳定的输出,帮助我们解决实际的问题。

社区也有很多其他的 spec 方案,颗粒度不一样,这是另一个比较高星的仓库,他的理念和哲学会有一些差别。

**OpenSpec** 和 **GitHub Spec Kit** 都是“规格驱动开发(SDD)”的工具,它们的目标一致(先写文档再写代码),但**设计哲学**和**适用场景**截然不同。

用一个最形象的比喻来概括:
*   GitHub Spec Kit 像是 “建造摩天大楼的总工程师”。严谨、繁琐、流程长,适合从 0 到 1 搞大工程,强调“企业级治理”。
*   OpenSpec 像是 “敏捷开发的装修队长”。轻快、直接、灵活,适合日常修修补补和快速迭代,强调“开发者体验”。

以下是详细的对比分析:

1. 核心差异对比表

特性  OpenSpec (Fission-AI)  Spec Kit (GitHub)
 核心哲学   Agile Renovator(敏捷装修)<br>轻量级,假设你是在一个现有的代码库上工作。  Structured Architect(结构化建筑师)<br>重量级,假设你是从 0 开始构建一个全新的系统。
 工作流   3 步循环 (Draft -> Review -> Apply)<br>只有三个命令,像 Git 一样简单。  4 阶段门控 (Specify -> Plan -> Tasks -> Implement)<br>每一步都有严格的“关卡”,必须通过才能进下一步。
 适用场景   维护/迭代现有项目 (Brownfield)<br>修 Bug、加功能、改逻辑。  全新项目启动 (Greenfield)<br>做 Demo、新开一个微服务。
 文件管理   双文件夹模式<br>specs/ (真理) 和 changes/ (变更) 分离。<br>不仅管“新建”,更擅长管“修改”。  单向流动<br>通过 constitution.md (宪法) 定义原则。<br>通常会为你自动创建 Git 分支。
 Token 消耗   。文档精简(约 200 行),只关注变更部分。  。生成的文档非常详尽(约 800 行),包含大量样板信息。
 上手难度  :star:  (npm install 即可) :star::star::star:  (需理解其四阶段理念)

2. 深度解析:为什么说 OpenSpec 更适合日常?

A. “修改” vs “新建” 的逻辑差异

*   Spec Kit 的思维模型是线性向前的。当你用它做一个新功能时,它非常爽,会生成完美的需求文档、技术方案。但如果你只是想“把登录按钮往左移 10px”,Spec Kit 的那套“需求->计划->任务->实施”的重型流程会让你觉得像在杀鸡用牛刀
*   OpenSpec 专门解决了这个问题。它把变更(Change)作为一个独立的概念。
    *   你可以发起一个“修改按钮位置”的 Change。
    *   你可以发起一个“重构数据库”的 Change。
    *   不论大小,流程都是统一的 Draft -> Apply -> Archive。

B. 此时此刻的“真理” (Source of Truth)

*   Spec Kit 倾向于把生成的 Spec 作为一个阶段性的产物。
*   OpenSpec 引入了 openspec/specs/ 目录作为永久的“真理来源”。
    *   当你把一个功能 Archive(归档)后,它的 Spec 会被合并到主目录。
    *   杀手级特性:下次你让 AI 改代码时,OpenSpec 会先让 AI 读 specs/ 目录,AI 立刻就能知道“哦,这个功能上次是这样设计的”,防止了新代码破坏旧逻辑(Regression)

C. “宪法” vs “项目说明书”

*   Spec Kit 有一个 constitution.md(宪法)的概念,里面写满了不可违背的原则(比如“必须使用 TDD”、“必须写注释”)。这很有企业级风范。
*   OpenSpec 使用 project.md,更像是一个“项目备忘录”。它更务实,通常只包含技术栈、目录结构和关键约定。


3. 如何选择?

:white_check_mark: 选 OpenSpec,如果:

1.  你在维护一个现有的项目:你需要在巨大的代码山上修修补补,而不是每天都在 npm init 新项目。
2.  你追求速度:你不想为了写一个简单的 API 接口而经历漫长的 4 步审批流程。
3.  你是个人开发者或小团队:你们需要规范,但不需要官僚主义。
4.  你在乎 Token 费用:OpenSpec 的 Prompt 更精简。

:white_check_mark: 选 GitHub Spec Kit,如果:

1.  你是 Tech Lead,要开一个新坑:你想在写第一行代码前,逼迫团队把所有细节(API 定义、数据库模型、甚至错误码)都想清楚。
2.  团队很大,水平参差不齐:你需要用 constitution.md 来强制所有人遵守编码规范,不给 AI(或人)自由发挥的空间。
3.  你需要产出非常详尽的文档:Spec Kit 生成的文档可以直接拿去给老板或客户汇报用。

总结

OpenSpec 是 Spec Kit 的“实用主义”进化版。
Spec Kit 像是教科书上的“瀑布流+敏捷”混合体,很理想化;而 OpenSpec 则是那个真正坐在你旁边写代码的同事,懂你需要什么,也懂你不想麻烦。


流程 & 完整提示词

这只是更适合我自己心智的提示词,可能一些错误场景也还没有碰到,你可以基于我的继续去演进或者直接使用。他的优势在于没有任何魔法,完全可以自己控制。

## 描述
Scaffold a new OpenSpec change and validate strictly.

命令

<!-- OPENSPEC:START –>

Guardrails

- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
- Keep changes tightly scoped to the requested outcome.
- Refer to openspec/AGENTS.md (located inside the openspec/ directory—run ls openspec or openspec&nbsp;update if you don’t see it) if you need additional OpenSpec conventions or clarifications.

  • Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
  • Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.

Steps

  1. CRITICAL PRE-CHECK:
       - DO NOT assume context. You MUST perform a codebase search (using your internal search tool) specifically targeting the openspec/specs/ directory for keywords related to the user’s request.
       - STOP AND ASK: If you find any existing spec files that seem related (even remotely), STOP IMMEDIATELY. Do not generate any scaffold. List the found specs and ask the user: “Did you mean to modify [filename] instead?”
       - Only proceed to Step 2if the search returns ZERO relevant results.
    2. (Only if no duplicates found) Choose a unique verb-led change-id and scaffold proposal.md, tasks.md, and design.md (when needed) under openspec/changes/&lt;id&gt;/.
    3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing.
    4. Capture architectural reasoning in design.md when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
    5. Draft spec deltas in changes/&lt;id&gt;/specs/&lt;capability&gt;/spec.md (one folder per capability) using ## ADDED|MODIFIED|REMOVED Requirements with at least one #### Scenario: per requirement and cross-reference related capabilities when relevant.
    6. Draft tasks.md as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
    7. Validate with openspec validate&nbsp;&lt;id&gt;&nbsp;--strict and resolve every issue before sharing the proposal.

Reference

- Use openspec&nbsp;show&nbsp;&lt;id&gt;&nbsp;--json --deltas-only or openspec show &lt;spec&gt; --type spec to inspect details when validation fails.
- Search existing requirements with rg&nbsp;-n "Requirement:|Scenario:" openspec/specs before writing new ones.
- Explore the codebase with rg&nbsp;&lt;keyword&gt;, ls, or direct file reads so proposals align with current implementation realities.
<!-- OPENSPEC:END –>

## 描述
Modify an existing, active OpenSpec draft(proposal, spec, tasks) without creating a new one.

命令

<!-- OPENSPEC:START –>

Guardrails

SCOPE RESTRICTION: This command operates ONLY on files within openspec/changes/. Do NOT create new change folders. Do NOT edit src/ code.
CONSISTENCY: If requirements(spec.md)ordesign(design.md) change, you MUST update tasks.md to reflect these changes immediately.
INTERACTION: If multiple active changes exist, you MUST ask the user to select one before editing any files.

Steps

1.  Discovery & Selection(Context Loading)
    - Run openspec list (orlist directories in openspec/changes/) to identify active drafts.
    - Scenario A(0 Active Changes):
        - STOP and inform the user: “No active drafts found to update. Use /openspec-proposal to start a new one.”
    - Scenario B(1 Active Change):
        - Automatically select thisID(e.g., feature-login).
        - Inform the user: “Updating active draft: feature-login…”
        - Read Files: Read proposal.mdtasks.mddesign.md, and spec.md inside that directory.
    - Scenario C(>1 Active Changes):
        - List all found IDs.
        - STOP and ask: “Multiple active drafts found. Which one do you want to update? (e.g., feature-A or feature-B)”
        - Wait for user confirmation, then read the files of the selected ID.

2.  Intent Analysis & Execution
    - Analyze the user’s update request(e.g., “Extract Modal component”, “Change DB to Mongo”).
    - Step 2.1: Update Truth(Spec/Design/Proposal):
        - Modify spec.md if business requirements change.
        - Modify design.md if technical implementation details change.
        - Modify proposal.md if the high-level goal changes.
    - Step 2.2: Re-align Plan(Tasks):
        - CRITICAL: Rewrite or adjust tasks.md to ensure it matches the new files from Step 2.1.
        - If tasks were partially completed([x]), try to preserve status where possible, but uncheck items if the logic underneath them has fundamentally changed.

3.  Validation
    - Run openspec validate &lt;id&gt; to ensure the update didn’t break the document structure.
    - Present the summary of changes to the user(e.g., “Updated design.md to include SharedModal; Added 2 new steps to tasks.md”).

Reference

- Use openspec list to find targets.
- Always keep tasks.md as the executable plan for the current spec.md.
<!-- OPENSPEC:END –>

## 描述
Implement an approved OpenSpec change and keep tasks in sync.

命令

<!-- OPENSPEC:START –>

Guardrails

- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
- Keep changes tightly scoped to the requested outcome.
- Refer to openspec/AGENTS.md (located inside the openspec/ directory—run ls openspec or openspec update if you don’t see it) if you need additional OpenSpec conventions or clarifications.

Steps Track these steps as TODOs and complete them one by one.

1. Read changes/&lt;id&gt;/proposal.mddesign.md (if present), and tasks.md to confirm scope and acceptance criteria,Strictly follow the tasks.md sequence. Do not skip steps or merge tasks unless explicitly necessary.
2. Work through tasks sequentially, keeping edits minimal and focused on the requested change.
3. Confirm completion before updating statuses—make sure every item in tasks.md is finished.
4. Update tasks.md selectively:
   - Mark implementation tasks (e.g., “Create component”, “Add API endpoint”) as - [x] immediately after writing the code.
   - Do NOT mark verification/validation tasks (e.g., “Verify login works”, “Check responsiveness”, “Run tests”) as completed. Leave them as - [ ] for the user to confirm manually.
5. Reference openspec list or openspec show &lt;item&gt; when additional context is required.

Reference

- Use openspec show &lt;id&gt; --json --deltas-only if you need additional context from the proposal while implementing.

tips
If the user only enters this command, the latest tasks.md and files under the specs/* directory need to be read.

<!-- OPENSPEC:END –>

## 描述
Archive a deployed OpenSpec change and update specs.

命令

Guardrails

- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
- Keep changes tightly scoped to the requested outcome.
- Refer to openspec/AGENTS.md (located inside the openspec/ directory—run ls openspec or openspec update if you don’t see it) if you need additional OpenSpec conventions or clarifications.

Steps

1. Determine the change ID to archive:
   - If this prompt already includes a specific change ID(for example inside a &lt;ChangeId&gt; block populated by slash-command arguments), use that value after trimming whitespace.
   - If the conversation references a change loosely(for example by title or summary), run openspec list to surface likely IDs, share the relevant candidates, and confirm which one the user intends.
   - Otherwise, review the conversation, run openspec list, and ask the user which change to archive; wait for a confirmed change ID before proceeding.
   - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet.

2. PRE-CHECK: Validate the change ID and status:
   - Run openspec list to confirm the ID exists and is not already archived.
   - CRITICAL: Run openspec validate &lt;id&gt; --strict.
   - STOP IF FAILED: If validation reports ANY errors(e.g., unfinished tasks, malformed frontmatter), DO NOT PROCEED. Show the validation errors to the user and ask them to fix the issues first.

3. ARCHIVE: Only if validation passes, run openspec archive &lt;id&gt; --yes.
   - This moves the change to changes/archive/ and applies spec updates without prompts.
   - (Optional) Use --skip-specs only if the user explicitly requested a tooling-only archive.

4. Review the command output to confirm the target specs were updated successfully.

Reference

- Use openspec list to confirm change IDs before archiving.
- Inspect refreshed specs with openspec list --specs after archiving to confirm the merge.
<!-- OPENSPEC:END –>

参考

1、https://openspec.dev/

2、https://github.com/Fission-AI/OpenSpec

3、https://github.com/github/spec-kit

4、https://aistudio.google.com

我觉得不一定非要迁移。OpenSpec 强调敏捷和迭代,即使项目规模变大,核心思路还是可以沿用。可以考虑在 OpenSpec 的基础上,逐步引入 GitHub Spec Kit 的一些企业级治理特性,比如更严格的流程控制、更详尽的文档规范等,实现平滑过渡。

可以尝试使用多个 AI 模型进行交叉验证。如果不同的 AI 模型生成的 Spec 文档或代码差异很大,那么就需要特别注意,很可能其中一个模型出现了幻觉。另外,还可以对 AI 模型进行针对性的训练,让它更好地理解项目的规范和业务逻辑。

文档出错是必然的,关键在于如何应对。我的看法是,不应该把“文档即真理”奉为圭臬,而应该将其视为一种理想状态。在实际开发中,要保持批判性思维,时刻质疑文档的正确性,并结合实际情况进行判断。此外,还可以考虑引入一些辅助工具,例如思维导图、流程图等,帮助更好地理解和验证文档。

我觉得在一些非常小的项目,或者是一些实验性的项目,完全不使用 SDD 可能是更好的选择。因为 SDD 本身需要一定的成本,包括学习成本、工具成本、流程成本等等。如果项目本身很简单,或者只是为了验证一个想法,那么花太多精力在 SDD 上就有点得不偿失了。

文档质量不高或者与代码不符的问题确实很致命,相当于给 AI 提供了错误的“真理”,反而会让它做出错误决策。这就像 GPS 地图数据错误,导航只会把你带到沟里。

我的建议是:

1. Review 机制:文档变更必须经过人工 review,确保其准确性和完整性。可以参考代码 review 的流程。
2. 自动化测试:针对文档中的关键信息,例如 API 接口定义、数据结构等,编写自动化测试,定期检查文档与代码的一致性。
3. 鼓励贡献:建立良好的文档贡献机制,鼓励团队成员积极参与文档的编写和维护,形成“人人为我,我为人人”的氛围。
4. 持续更新:文档不是一劳永逸的,需要随着代码的迭代而持续更新,可以使用一些工具来辅助更新,比如根据代码注释自动生成文档。

我同意楼上的观点,文档的重要性不会降低,反而会更加凸显!

未来,文档可能会朝着以下方向发展:

1. 结构化:文档会更加结构化,采用统一的格式和规范,方便 AI 进行解析和利用。
2. 交互式:文档会更加交互式,可以与代码编辑器、调试器等工具进行联动,提供更丰富的开发体验。
3. 智能化:文档会更加智能化,可以根据代码的变更自动更新,提供更准确的描述。

我觉得 GitHub Spec Kit 更适合我们项目。虽然我们也是在维护一个现有的项目,但是项目比较复杂,代码质量参差不齐。我们需要一个更严格的规范来约束团队成员,保证代码质量。GitHub Spec Kit 的 constitution.md 功能可以帮助我们定义编码规范,强制团队成员遵守。另外,我们需要产出比较详尽的文档,方便后续维护和交接。GitHub Spec Kit 生成的文档更适合我们的需求。

我有一个不同的看法。虽然 AI 辅助编程可以提高效率,但我们不能完全依赖 AI。代码 review 仍然很重要,不能放松警惕。Review 的重点除了设计和逻辑之外,还要关注 AI 的代码质量,看看有没有冗余代码、重复逻辑、性能问题等。毕竟 AI 生成的代码也是需要维护的,如果代码质量太差,以后维护起来会很痛苦。所以,代码 review 的标准不能降低,反而要提高。

这个问题问得好!规范和流程一致性是团队协作的基石。我的经验是,首先要确保所有成员都理解并接受 project.md 中定义的项目约定,可以组织一个线上会议,逐条解读并达成共识。其次,利用 OpenSpec 的 validate 命令进行严格的格式检查,可以在 CI/CD 流程中集成,强制执行规范。另外,远程协作时,可以利用代码 review 工具,重点关注 spec 文件是否符合规范,以及 tasks 是否完整。还可以创建一个共享的知识库,记录常见问题和解决方案,方便团队成员参考。

当然,最重要的一点是,团队成员需要定期沟通,分享经验和遇到的问题,不断改进和完善规范和流程。

OpenSpec 的设计哲学挺有意思的,有点像 Git 的思路。 优点:
1. 简单直接:降低了学习成本,不需要学习额外的命令。
2. 避免状态管理:减少了状态管理的复杂性,不容易出错。

缺点:
1. 缺乏自动化:手动修改需要更多的人工干预,效率较低。
2. 容易出错:手动修改容易出现拼写错误、格式错误等。

在实际项目中,我更倾向于结合使用:对于简单的修改,手动修改;对于复杂的修改,使用 update 命令。

文档即代码的核心在于保证文档与代码的一致性。在快速迭代过程中,可以考虑采用敏捷文档的方法,例如只记录关键决策和接口定义,并在每次迭代后及时更新文档。此外,利用AI工具辅助生成和维护文档,可以有效降低文档编写的负担。

可以把“先写文档”理解为一种“设计先行”的思想。即使需求不明确,也可以通过绘制流程图、设计API接口等方式,对系统进行初步的设计。这有助于理清思路,避免盲目开发。

“文档即真理”听起来很美好,但实际操作中很难实现。文档出错或过时是很常见的事情。我认为,关键是要建立一种“容错机制”,允许文档存在一定的偏差。当发现文档错误时,要及时纠正,并记录下来,避免类似错误再次发生。另外,还可以鼓励团队成员参与文档的维护,形成一种“人人都是文档维护者”的氛围。

我觉得最大的挑战可能是团队成员对编写规范文档的抵触情绪。很多人觉得写文档是浪费时间,不如直接写代码来得快。为了克服这个挑战,可以先从小规模试点开始,选择一些关键但不太复杂的模块,让大家看到 SDD 带来的好处,比如减少沟通成本、提高代码质量等。同时,也可以提供一些模板和示例,降低编写文档的门槛。还可以考虑引入一些激励机制,鼓励大家积极参与到 SDD 的过程中来。

谢邀,人在工位,刚开始用OpenSpec。我觉得这个问题问到了点子上。文档出错是难免的,关键是我们要建立一个快速反馈和纠错的机制。我的想法是,可以在团队内部建立一个“文档勘误”流程,鼓励大家在发现文档错误时及时反馈。另外,可以考虑引入版本控制系统,对文档进行版本管理,方便追溯和回滚。

个人认为,如果项目在开发过程中引入 SDD,OpenSpec 可能是更合适的选择。因为它更轻量级,更注重变更管理,可以更好地适应现有代码库。GitHub Spec Kit 的流程比较重,可能会给现有项目带来较大的改动。不过,具体选择还是要根据项目的实际情况,例如团队规模、项目复杂度等。

我觉得这个问题很有深度,问到了 OpenSpec 的本质。如果没有 AI,OpenSpec 就像一个朴素的农民,Confluence、Notion 就像是现代化的农业公司。

OpenSpec 的优势在于:

1. 更贴近开发流程: OpenSpec 的设计目标是与开发流程无缝集成,Spec 文件可以直接参与到代码评审、自动化测试等环节中,实现 Spec 即代码。

2. 版本控制原生支持: OpenSpec 的 Spec 文件本身就是 Markdown 文件,天然支持 Git 等版本控制工具,能够方便地进行版本管理和协作。

OpenSpec 的劣势在于:

1. 功能简单: 相比于 Confluence、Notion 这样功能丰富的文档管理工具,OpenSpec 的功能相对简单,缺乏一些高级特性,例如权限管理、工作流等。

2. 用户体验不足: OpenSpec 的用户界面主要基于 CLI,用户体验不如 Confluence、Notion 这样基于 Web 的图形化界面。

我的看法是,如果没有 AI 的加持,OpenSpec 的价值会大打折扣。它更像是一个为 AI 量身定制的工具,只有在 AI 的参与下,才能真正发挥其潜力。

不懂就问,OpenSpec 能不能用来管理我的减肥计划?spec 可以是每天的饮食记录和运动计划,tasks 可以是“早上跑步30分钟”、“中午吃keep的减脂餐”… 感觉好像有点意思!

这个问题问得好!OpenSpec 的哲学是“文档即代码”,鼓励手动修改,这确实可能带来冲突。我的理解是,首先要依赖 Git 这样的版本控制系统,每次修改前先 pull,修改后及时 commit 和 push,减少冲突的可能性。其次,团队内部需要建立良好的沟通机制,比如在修改前先在群里同步一下,避免重复劳动或者覆盖彼此的修改。最后,可以考虑使用一些协同编辑工具,比如在线 Markdown 编辑器,允许多人同时编辑同一份文档。