本指南解释了 OpenSpec 背后的核心思想以及它们如何协同工作。关于实际使用,请参阅入门指南和工作流。
OpenSpec 围绕四个原则构建:
灵活而非僵化 — 无阶段门限,按需工作
迭代而非瀑布 — 边构建边学习,逐步完善
简单而非复杂 — 轻量级设置,最小化仪式感
棕地优先 — 适用于现有代码库,不限于绿地项目
灵活而非僵化。 传统的规范系统将你锁定在阶段中:先规划,再实施,然后完成。OpenSpec 更加灵活——你可以按工作需求以任何顺序创建制品。
迭代而非瀑布。 需求会变化。理解会加深。开始时看似不错的方法在查看代码库后可能不再适用。OpenSpec 拥抱这一现实。
简单而非复杂。 一些规范框架需要大量设置、严格格式或重量级流程。OpenSpec 不会妨碍你的工作。几秒钟内初始化,立即开始工作,仅在需要时自定义。
棕地优先。 大多数软件工作不是从零开始构建——而是修改现有系统。OpenSpec 基于增量的方法使得指定对现有行为的更改变得容易,而不仅仅是描述新系统。
OpenSpec 将你的工作组织为两个主要区域:
┌────────────────────────────────────────────────────────────────────┐
│ openspec/ │
│ │
│ ┌─────────────────────┐ ┌───────────────────────────────┐ │
│ │ specs/ │ │ changes/ │ │
│ │ │ │ │ │
│ │ 单一事实来源 │◄─────│ 提议的修改 │ │
│ │ 描述系统当前的 │ 合并 │ 每个变更 = 一个文件夹 │ │
│ │ 工作方式 │ │ 包含制品 + 增量 │ │
│ │ │ │ │ │
│ └─────────────────────┘ └───────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────┘
规范(Specs) 是单一事实来源——它们描述系统当前的行为方式。
变更(Changes) 是提议的修改——它们存在于独立的文件夹中,直到你准备好合并它们。
这种分离是关键。你可以并行处理多个变更而不会产生冲突。你可以在变更影响主规范之前进行审查。当你归档变更时,其增量会干净地合并到单一事实来源中。
规范使用结构化的需求和场景来描述系统的行为。
openspec/specs/
├── auth/
│ └── spec.md # 认证行为
├── payments/
│ └── spec.md # 支付处理
├── notifications/
│ └── spec.md # 通知系统
└── ui/
└── spec.md # UI 行为和主题
按领域组织规范——为你的系统创建有意义的逻辑分组。常见模式:
- 按功能区域:
auth/、payments/、search/ - 按组件:
api/、frontend/、workers/ - 按限界上下文:
ordering/、fulfillment/、inventory/
一个规范包含需求,每个需求都有场景:
# 认证规范
## 目的
应用程序的认证和会话管理。
## 需求
### 需求:用户认证
系统应在成功登录时发放 JWT 令牌。
#### 场景:有效凭据
- 给定具有有效凭据的用户
- 当用户提交登录表单时
- 则返回 JWT 令牌
- 并且用户被重定向到仪表板
#### 场景:无效凭据
- 给定无效凭据
- 当用户提交登录表单时
- 则显示错误消息
- 并且不发放令牌
### 需求:会话过期
系统必须在 30 分钟不活动后使会话过期。
#### 场景:空闲超时
- 给定已认证的会话
- 当 30 分钟过去且没有活动时
- 则会话失效
- 并且用户必须重新认证关键元素:
| 元素 | 目的 |
|---|---|
## 目的 |
此规范领域的高级描述 |
### 需求: |
系统必须具有的特定行为 |
#### 场景: |
需求在行动中的具体示例 |
| SHALL/MUST/SHOULD | RFC 2119 关键词,表示需求强度 |
需求是"做什么"——它们说明系统应该做什么而不指定实现。
场景是"何时"——它们提供可验证的具体示例。好的场景:
- 是可测试的(你可以为它们编写自动化测试)
- 涵盖正常路径和边缘情况
- 使用 Given/When/Then 或类似结构化格式
RFC 2119 关键词(SHALL、MUST、SHOULD、MAY)传达意图:
- MUST/SHALL——绝对需求
- SHOULD——推荐,但存在例外
- MAY——可选
规范是行为契约,而不是实施计划。
好的规范内容:
- 用户或下游系统依赖的可观察行为
- 输入、输出和错误条件
- 外部约束(安全性、隐私、可靠性、兼容性)
- 可以测试或明确验证的场景
规范中应避免的内容:
- 内部类/函数名称
- 库或框架选择
- 逐步实施细节
- 详细的执行计划(这些属于
design.md或tasks.md)
快速判断:
- 如果实现方式可以改变而不影响外部可见行为,那它很可能不属于规范。
OpenSpec 旨在避免官僚主义。使用能使变更可验证的最轻量级别即可。
轻量规范(默认):
- 简短的行为优先需求
- 清晰的范围和非目标
- 少量具体的验收检查
完整规范(适用于较高风险):
- 跨团队或跨仓库的变更
- API/契约变更、迁移、安全/隐私问题
- 模糊性可能导致高成本返工的变更
大多数变更应保持轻量模式。
在许多团队中,人类负责探索,Agent 负责起草制品。预期的协作循环是:
- 人类提供意图、上下文和约束条件。
- Agent 将其转化为行为优先的需求和场景。
- Agent 将实施细节保留在
design.md和tasks.md中,而不是spec.md中。 - 验证在实施之前确认结构和清晰性。
这使规范对人类可读,对 Agent 保持一致。
变更是对系统的提议修改,打包为一个包含理解和实施所需所有内容的文件夹。
openspec/changes/add-dark-mode/
├── proposal.md # 为什么和做什么
├── design.md # 如何做(技术方案)
├── tasks.md # 实施清单
├── .openspec.yaml # 变更元数据(可选)
└── specs/ # 增量规范
└── ui/
└── spec.md # ui/spec.md 中的更改内容
每个变更都是自包含的。它包含:
- 制品——捕获意图、设计和任务的文档
- 增量规范——对添加、修改或删除内容的规范
- 元数据——此特定变更的可选配置
将变更打包为文件夹有几个好处:
-
一切在一起。 提案、设计、任务和规范位于同一位置。无需在不同位置查找。
-
并行工作。 多个变更可以同时存在而不会冲突。在
fix-auth-bug进行时,可以同时处理add-dark-mode。 -
清晰历史。 归档时,变更会移动到
changes/archive/并保留完整上下文。你可以回顾并理解不仅发生了什么变化,还有为什么变化。 -
便于审查。 变更文件夹易于审查——打开它,阅读提案,检查设计,查看规范增量。
制品是变更中的文档,用于指导工作。
proposal ──────► specs ──────► design ──────► tasks ──────► implement
│ │ │ │
为什么 改变什么 如何做 实施步骤
+ 范围 变化 方法 要执行
制品相互构建。每个制品为下一个提供上下文。
提案在高级别捕获意图、范围和方法。
# 提案:添加深色模式
## 意图
用户要求提供深色模式选项,以在夜间使用时减少眼睛疲劳并匹配系统偏好。
## 范围
包含:
- 设置中的主题切换
- 系统偏好检测
- 在 localStorage 中持久化偏好
不包含:
- 自定义颜色主题(未来工作)
- 每页主题覆盖
## 方法
使用 CSS 自定义属性进行主题化,配合 React context 进行状态管理。在首次加载时检测系统偏好,允许手动覆盖。何时更新提案:
- 范围变化(缩小或扩大)
- 意图明确(对问题有更好理解)
- 方法发生根本性变化
增量规范描述相对于当前规范的变化内容。详见下面的增量规范。
设计捕获技术方法和架构决策。
# 设计:添加深色模式
## 技术方法
通过 React Context 管理主题状态以避免属性传递。CSS 自定义属性支持运行时切换而无需类切换。
## 架构决策
### 决策:Context 优于 Redux
使用 React Context 管理主题状态的原因:
- 简单的二元状态(浅色/深色)
- 无复杂状态转换
- 避免添加 Redux 依赖
### 决策:CSS 自定义属性优于 CSS-in-JS
使用 CSS 变量而非 CSS-in-JS 的原因:
- 与现有样式表配合使用
- 无运行时开销
- 浏览器原生解决方案
## 数据流
```
ThemeProvider (context)
│
▼
ThemeToggle ◄──► localStorage
│
▼
CSS Variables (应用于 :root)
```
## 文件变更
- `src/contexts/ThemeContext.tsx`(新建)
- `src/components/ThemeToggle.tsx`(新建)
- `src/styles/globals.css`(修改)何时更新设计:
- 实施显示方法不可行
- 发现更好的解决方案
- 依赖项或约束条件变化
任务是实施清单——带有复选框的具体步骤。
# 任务
## 1. 主题基础设施
- [ ] 1.1 创建具有浅色/深色状态的 ThemeContext
- [ ] 1.2 添加 CSS 自定义属性用于颜色
- [ ] 1.3 实现 localStorage 持久化
- [ ] 1.4 添加系统偏好检测
## 2. UI 组件
- [ ] 2.1 创建 ThemeToggle 组件
- [ ] 2.2 在设置页面添加切换器
- [ ] 2.3 更新 Header 包含快速切换
## 3. 样式
- [ ] 3.1 定义深色主题调色板
- [ ] 3.2 更新组件使用 CSS 变量
- [ ] 3.3 测试可访问性的对比度比率任务最佳实践:
- 将相关任务分组在标题下
- 使用分层编号(1.1、1.2 等)
- 保持任务足够小,可在一个会话中完成
- 完成任务时勾选复选框
增量规范是使 OpenSpec 适用于棕地开发的关键概念。它们描述正在变化的内容,而不是重述整个规范。
# 认证增量
## 新增需求
### 需求:双因素认证
系统必须支持基于 TOTP 的双因素认证。
#### 场景:2FA 注册
- 给定未启用 2FA 的用户
- 当用户在设置中启用 2FA 时
- 则显示用于认证器应用设置的二维码
- 并且用户在激活前必须用代码验证
#### 场景:2FA 登录
- 给定已启用 2FA 的用户
- 当用户提交有效凭据时
- 则显示 OTP 挑战
- 并且只有在有效 OTP 后登录才完成
## 修改需求
### 需求:会话过期
系统必须在 15 分钟不活动后使会话过期。
(之前:30 分钟)
#### 场景:空闲超时
- 给定已认证的会话
- 当 15 分钟过去且没有活动时
- 则会话失效
## 删除需求
### 需求:记住我
(已弃用,支持 2FA。用户应在每个会话重新认证。)| 部分 | 含义 | 归档时发生什么 |
|---|---|---|
## 新增需求 |
新行为 | 附加到主规范 |
## 修改需求 |
改变的行为 | 替换现有需求 |
## 删除需求 |
已弃用的行为 | 从主规范中删除 |
清晰性。 增量明确显示正在变化的内容。阅读完整规范时,你必须与当前版本进行心理差异比较。
避免冲突。 只要修改不同的需求,两个变更可以接触同一个规范文件而不会冲突。
审查效率。 审查者看到的是变更,而不是未改变的上下文。专注于重要内容。
棕地适应性。 大多数工作都是修改现有行为。增量使修改成为一等公民,而不是事后考虑。
模式定义工作流的制品类型及其依赖关系。
# openspec/schemas/spec-driven/schema.yaml
name: spec-driven
artifacts:
- id: proposal
generates: proposal.md
requires: [] # 无依赖,可首先创建
- id: specs
generates: specs/**/*.md
requires: [proposal] # 需要提案后才能创建
- id: design
generates: design.md
requires: [proposal] # 可与规范并行创建
- id: tasks
generates: tasks.md
requires: [specs, design] # 需要规范和设计后才能创建制品形成依赖图:
proposal
(根节点)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(需要: (需要:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(需要:
specs, design)
依赖是赋能者,不是门限。 它们显示可以创建什么,而不是必须创建什么。如果不需要,可以跳过设计。可以在设计之前或之后创建规范——两者都只依赖于提案。
spec-driven(默认)
规范驱动开发的标准工作流:
proposal → specs → design → tasks → implement
最适合:大多数功能工作,希望在实施前就规范达成一致。
为团队工作流创建自定义模式:
# 从零开始创建
openspec-cn schema init research-first
# 或从现有模式派生
openspec-cn schema fork spec-driven research-first示例自定义模式:
# openspec/schemas/research-first/schema.yaml
name: research-first
artifacts:
- id: research
generates: research.md
requires: [] # 首先进行研究
- id: proposal
generates: proposal.md
requires: [research] # 提案基于研究
- id: tasks
generates: tasks.md
requires: [proposal] # 跳过规范/设计,直接进入任务有关创建和使用自定义模式的完整详情,请参阅自定义。
归档通过将增量规范合并到主规范中来完成变更,并保留变更用于历史记录。
归档前:
openspec/
├── specs/
│ └── auth/
│ └── spec.md ◄────────────────┐
└── changes/ │
└── add-2fa/ │
├── proposal.md │
├── design.md │ 合并
├── tasks.md │
└── specs/ │
└── auth/ │
└── spec.md ─────────┘
归档后:
openspec/
├── specs/
│ └── auth/
│ └── spec.md # 现在包含 2FA 需求
└── changes/
└── archive/
└── 2025-01-24-add-2fa/ # 为历史保留
├── proposal.md
├── design.md
├── tasks.md
└── specs/
└── auth/
└── spec.md
-
合并增量。 每个增量规范部分(新增/修改/删除)应用到相应的主规范。
-
移动到归档。 变更文件夹移动到
changes/archive/,带有日期前缀以便按时间顺序排序。 -
保留上下文。 所有制品在归档中保持完整。你总是可以回顾以理解为什么进行变更。
清洁状态。 活动变更(changes/)仅显示进行中的工作。已完成的工作移出视线。
审计追踪。 归档保留每个变更的完整上下文——不仅是发生了什么变化,还有解释为什么的提案、解释如何的设计以及显示所做工作的任务。
规范演进。 随着变更被归档,规范有机地增长。每个归档合并其增量,随着时间的推移构建全面的规范。
┌──────────────────────────────────────────────────────────────────────────────┐
│ OPENSPEC 流程 │
│ │
│ ┌────────────────┐ │
│ │ 1. START │ /opsx:propose (core) or /opsx:new (expanded) │
│ │ CHANGE │ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 2. 创建 │ /opsx:ff 或 /opsx:continue (expanded workflow) │
│ │ 制品 │ 创建提案 → 规范 → 设计 → 任务 │
│ │ │ (基于模式依赖关系) │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 3. 实施 │ /opsx:apply │
│ │ 任务 │ 处理任务,勾选完成项 │
│ │ │◄──── 学习时更新制品 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 4. 验证 │ /opsx:verify(可选) │
│ │ 工作 │ 检查实施是否匹配规范 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
│ │ 5. 归档 │────►│ 增量规范合并到主规范 │ │
│ │ 变更 │ │ 变更文件夹移动到 archive/ │ │
│ └────────────────┘ │ 规范现在是更新的单一事实来源 │ │
│ └──────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
良性循环:
- 规范描述当前行为
- 变更提议修改(作为增量)
- 实施使变更成为现实
- 归档将增量合并到规范中
- 规范现在描述新行为
- 下一个变更基于更新的规范构建
| 术语 | 定义 |
|---|---|
| 制品(Artifact) | 变更中的文档(提案、设计、任务或增量规范) |
| 归档(Archive) | 完成变更并将其增量合并到主规范的过程 |
| 变更(Change) | 对系统的提议修改,打包为包含制品的文件夹 |
| 增量规范(Delta spec) | 描述相对于当前规范的变更(新增/修改/删除)的规范 |
| 领域(Domain) | 规范逻辑分组(例如 auth/、payments/) |
| 需求(Requirement) | 系统必须具有的特定行为 |
| 场景(Scenario) | 需求的具体示例,通常采用 Given/When/Then 格式 |
| 模式(Schema) | 制品类型及其依赖关系的定义 |
| 规范(Spec) | 描述系统行为的规范,包含需求和场景 |
| 单一事实来源(Source of truth) | openspec/specs/ 目录,包含当前商定的行为 |