概念
本指南解释了 OpenSpec 的核心思想及其相互关系。如需了解实际操作,请参阅 入门指南 和 工作流。
理念
OpenSpec 围绕以下四个原则构建:
灵活而非僵化 — 无阶段门禁,按需开展工作
迭代而非瀑布 — 在构建中学习,在过程中完善
简单而非复杂 — 轻量级设置,最小化流程
优先支持遗留系统 — 适用于现有代码库,而不仅限于全新项目这些原则的重要性
灵活而非僵化。 传统的规范系统将用户锁定在固定的阶段中:先规划,再实施,最后完成。OpenSpec 更加灵活——你可以根据工作的实际需要,以任何顺序创建工件。
迭代而非瀑布。 需求会发生变化,理解会不断深化。起初看似合理的方法,在查看代码库后可能不再适用。OpenSpec 拥抱这一现实。
简单而非复杂。 某些规范框架需要大量的设置、严格的格式或重量级的流程。OpenSpec 不会干扰你的工作。只需几秒钟即可初始化,立即开始工作,仅在需要时才进行自定义。
优先支持遗留系统。 大多数软件开发工作并非从零开始构建,而是修改现有系统。OpenSpec 基于差异(delta)的方法使得指定对现有行为的更改变得容易,而不仅仅是描述新系统。
总体概览
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/
规范格式
一个规范包含需求,每个需求都有场景:
# Auth 规范
## 目的
应用程序的身份验证和会话管理。
## 需求
### 需求:用户身份验证
系统应在成功登录时签发 JWT 令牌。
#### 场景:有效凭据
- 给定一个具有有效凭据的用户
- 当用户提交登录表单
- 那么返回一个 JWT 令牌
- 并且用户被重定向到仪表板
#### 场景:无效凭据
- 给定无效凭据
- 当用户提交登录表单
- 那么显示错误消息
- 并且不签发令牌
### 需求:会话过期
系统必须在 30 分钟不活动后使会话过期。
#### 场景:空闲超时
- 给定一个已认证的会话
- 当 30 分钟没有活动
- 那么会话被使无效
- 并且用户必须重新认证关键元素:
| 元素 | 目的 |
|---|---|
## Purpose | 此规范所属领域的高级描述 |
### Requirement: | 系统必须具备的特定行为 |
#### Scenario: | 需求执行的具体示例 |
| SHALL/MUST/SHOULD | 指示需求强度的 RFC 2119 关键字 |
为什么这样组织规范
需求是“什么”——它们陈述系统应该做什么,而不指定实现方式。
场景是“何时”——它们提供可验证的具体示例。好的场景:
- 是可测试的(你可以为它们编写自动化测试)
- 涵盖正常路径和边界情况
- 使用 Given/When/Then 或类似的结构化格式
RFC 2119 关键字(SHALL、MUST、SHOULD、MAY)传达意图:
- MUST/SHALL——绝对要求
- SHOULD——推荐,但存在例外
- MAY——可选
规范是什么(以及不是什么)
规范是行为契约,而不是实现计划。
好的规范内容:
- 用户或下游系统依赖的可观察行为
- 输入、输出和错误条件
- 外部约束(安全、隐私、可靠性、兼容性)
- 可以测试或显式验证的场景
规范中应避免:
- 内部类/函数名称
- 库或框架选择
- 逐步的实现细节
- 详细的执行计划(这些属于
design.md或tasks.md)
快速测试:
- 如果实现可以改变而不影响外部可见行为,那么它很可能不属于规范。
保持轻量:渐进严谨
OpenSpec 旨在避免官僚主义。使用仍然能使变更可验证的最轻量级别。
轻量规范(默认):
- 短的行为优先需求
- 明确的范围和非目标
- 一些具体的验收检查
完整规范(用于较高风险):
- 跨团队或跨仓库的变更
- API/契约变更、迁移、安全/隐私问题
- 模糊性可能导致昂贵返工的变更
大多数变更应保持在轻量模式。
人类与代理协作
在许多团队中,人类进行探索,代理起草工件。预期的循环是:
- 人类提供意图、上下文和约束。
- 代理将其转换为行为优先的需求和场景。
- 代理将实现细节保留在
design.md和tasks.md中,而不是spec.md。 - 验证在实现之前确认结构和清晰度。
这使规范对人类可读,对代理保持一致。
变更
变更是对你的系统的提议修改,打包为一个文件夹,包含理解和实现所需的一切。
变更结构
openspec/changes/add-dark-mode/
├── proposal.md # 为什么和什么
├── design.md # 如何(技术方法)
├── tasks.md # 实现检查清单
├── .openspec.yaml # 变更元数据(可选):schema、created、skip_specs、retire_capabilities
└── specs/ # 增量规范
└── ui/
└── spec.md # ui/spec.md 中正在更改的内容每个变更都是自包含的。它包含:
- 工件——捕获意图、设计和任务的文档
- 增量规范——关于添加、修改或删除的规范
- 元数据——此特定变更的可选配置
为什么变更作为文件夹
将变更打包为文件夹有几个好处:
所有东西在一起。 提案、设计、任务和规范放在一个地方。无需在不同位置寻找。
并行工作。 多个变更可以同时存在而不会冲突。在处理
add-dark-mode的同时也可以进行fix-auth-bug。干净的历史。 归档时,变更移动到
changes/archive/,并保留其完整上下文。你可以回顾并理解不仅发生了什么变化,而且为什么。便于审查。 变更文件夹易于审查——打开它,阅读提案,检查设计,查看规范增量。
工件
工件是变更中的文档,指导工作。
工件流
proposal ──────► specs ──────► design ──────► tasks ──────► implement
│ │ │ │
why what how steps
+ scope changes approach to take工件相互构建。每个工件为下一个工件提供上下文。
工件类型
提案(proposal.md)
提案捕获意图、范围和方法的高级概述。
# 提案:添加深色模式
## 意图
用户已请求深色模式选项,以减少夜间使用时的眼睛疲劳,
并与系统偏好匹配。
## 范围
包含在内:
- 设置中的主题切换
- 系统偏好检测
- 在 localStorage 中持久化偏好
不包含在内:
- 自定义颜色主题(未来工作)
- 逐页主题覆盖
## 方法
使用 CSS 自定义属性进行主题化,使用 React 上下文
进行状态管理。在首次加载时检测系统偏好,
允许手动覆盖。何时更新提案:
- 范围发生变化(缩小或扩大)
- 意图更加明确(对问题的更好理解)
- 方法发生根本性转变
规范(specs/ 中的增量规范)
增量规范描述相对于当前规范正在更改的内容。参见下面的 增量规范。
设计(design.md)
设计捕获技术方法和架构决策。
# 设计:添加深色模式
## 技术方法
主题状态通过 React 上下文管理,以避免属性传递。
CSS 自定义属性支持运行时切换,无需类切换。
## 架构决策
### 决策:采用 Context 而非 Redux
使用 React Context 管理主题状态,因为:
- 简单的二元状态(浅色/深色)
- 无复杂的状态转换
- 避免添加 Redux 依赖
### 决策:CSS 自定义属性
使用 CSS 变量而非 CSS-in-JS,因为:
- 与现有样式表兼容
- 无运行时开销
- 浏览器原生解决方案
## 数据流
```
ThemeProvider (上下文)
│
▼
ThemeToggle ◄──► localStorage
│
▼
CSS 变量(应用于 :root)
```
## 文件更改
- `src/contexts/ThemeContext.tsx`(新建)
- `src/components/ThemeToggle.tsx`(新建)
- `src/styles/globals.css`(修改)何时更新设计:
- 实现揭示方法不会奏效
- 发现更好的解决方案
- 依赖项或约束发生变化
任务(tasks.md)
任务是实现检查清单——带有复选框的具体步骤。
# 任务
## 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 适用于布朗菲德开发的关键概念。它们描述正在更改的内容,而不是重述整个规范。
格式
# Auth 的增量
## 添加的需求
### 需求:双因素身份验证
系统必须支持基于 TOTP 的双因素身份验证。
#### 场景:2FA 注册
- 给定一个未启用 2FA 的用户
- 当用户在设置中启用 2FA
- 那么显示用于认证器应用设置的 QR 码
- 并且用户必须使用验证码验证后才能激活
#### 场景:2FA 登录
- 给定一个已启用 2FA 的用户
- 当用户提交有效凭据
- 那么呈现一个 OTP 挑战
- 并且只有在 OTP 有效后登录才完成
## 修改的需求
### 需求:会话过期
系统必须在 15 分钟不活动后使会话过期。
(之前:30 分钟)
#### 场景:空闲超时
- 给定一个已认证的会话
- 当 15 分钟没有活动
- 那么会话被使无效
## 移除的需求
### 需求:记住我
(已弃用,改用 2FA。用户应在每次会话中重新认证。)增量部分
| 部分 | 含义 | 归档时发生什么 |
|---|---|---|
## 添加的需求 | 新行为 | 追加到主规范 |
## 修改的需求 | 更改的行为 | 替换现有需求 |
## 移除的需求 | 已弃用的行为 | 从主规范中删除;当变更声明 retire_capabilities: true 时,移除最后一个需求将淘汰该能力并删除其规范文件 |
## Purpose | 一个全新能力的目的 | 为正在创建的主规范提供 Purpose 种子;当规范已存在时忽略 |
为什么用增量而不是完整规范
清晰度。 增量准确显示正在更改的内容。读取完整规范时,你必须在心里将其与当前版本进行差异比较。
避免冲突。 两个变更可以触及同一个规范文件而不会冲突,只要它们修改的是不同的需求。
审查效率。 审查者看到的是变更,而不是未更改的上下文。专注重要内容。
布朗菲德适用性。 大多数工作修改的是现有行为。增量使修改成为一等公民,而非事后考虑。
模式 (Schemas)
模式定义了工作流中的工件类型及其依赖关系。
模式的工作原理
# openspec/schemas/spec-driven/schema.yaml
name: spec-driven
artifacts:
- id: proposal
generates: proposal.md
requires: [] # 无依赖,可最先创建
- id: specs
generates: specs/**/*.md
requires: [proposal] # 创建前需要 proposal
- id: design
generates: design.md
requires: [proposal] # 可与 specs 并行创建
- id: tasks
generates: tasks.md
requires: [specs, design] # 创建前需要 specs 和 design工件形成依赖图:
proposal
(根节点)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(requires: (requires:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(requires:
specs, design)依赖关系是启用条件,而非关卡。 它们展示了可以创建什么,而不是你必须接下来创建什么。如果你不需要设计阶段,可以跳过它。你可以在设计之前或之后创建规范——两者都仅依赖于 proposal。
内置模式
spec-driven(默认)
规范驱动开发的标准工作流:
proposal → specs → design → tasks → implement适用场景:大多数功能开发,希望在实施前就规范达成一致。
自定义模式
为你的团队工作流创建自定义模式:
# 从头创建
openspec schema init research-first
# 或基于现有模式分叉
openspec 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] # 跳过规范和设计,直接进入任务有关创建和使用自定义模式的详细信息,请参阅 Customization。
归档 (Archive)
归档通过将其增量规范合并到主规范中并保留更改以供历史记录查阅,从而完成一个更改。
归档时发生的情况
归档前:
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归档过程
合并增量。 每个增量规范部分(ADDED/MODIFIED/REMOVED)都会应用到相应的主规范中。
移动到归档区。 更改文件夹移至
changes/archive/,并带有日期前缀以按时间顺序排列。保留上下文。 所有工件在归档中保持完整。你随时可以回顾以了解为何进行某项更改。
为什么归档很重要
干净的状态。 活动更改 (changes/) 仅显示正在进行的工作。已完成的工作被移走。
审计轨迹。 归档保留了每次更改的完整上下文——不仅仅是改变了什么,还包括解释原因的提案、解释如何实现的設計以及展示所做工作的任务。
规范的演进。 随着更改被归档,规范有机地增长。每次归档都会合并其增量,随着时间的推移构建出全面的规范。
整体流程整合
┌──────────────────────────────────────────────────────────────────────────────┐
│ OPENSPEC FLOW │
│ │
│ ┌────────────────┐ │
│ │ 1. START │ /opsx:propose (核心) 或 /opsx:new (扩展) │
│ │ CHANGE │ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 2. CREATE │ /opsx:ff 或 /opsx:continue (扩展工作流) │
│ │ ARTIFACTS │ 创建 proposal → specs → design → tasks │
│ │ │ (基于模式依赖关系) │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 3. IMPLEMENT │ /opsx:apply │
│ │ TASKS │ 处理任务,逐一勾选完成 │
│ │ │◄──── 在学习过程中更新工件 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 4. VERIFY │ /opsx:verify (可选) │
│ │ WORK │ 检查实现是否符合规范 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
│ │ 5. ARCHIVE │────►│ 增量规范合并到主规范中 │ │
│ │ CHANGE │ │ 更改文件夹移至 archive/ │ │
│ └────────────────┘ │ 规范现在是更新的唯一事实来源 │ │
│ └──────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘良性循环:
- 规范描述当前行为
- 更改提议修改(作为增量)
- 实施使更改变为现实
- 归档将增量合并到规范中
- 规范现在描述新行为
- 下一个更改基于更新的规范进行构建
术语表
| 术语 | 定义 |
|---|---|
| Artifact (工件) | 更改内的文档(提案、设计、任务或增量规范) |
| Archive (归档) | 完成更改并将其增量合并到主规范的过程 |
| Change (更改) | 对系统的提议修改,打包为包含工件的文件夹 |
| Delta spec (增量规范) | 相对于当前规范描述更改(ADDED/MODIFIED/REMOVED)的规范 |
| Domain (领域) | 规范的逻辑分组(例如 auth/、payments/) |
| Requirement (需求) | 系统必须具备的特定行为 |
| Scenario (场景) | 需求的具体示例,通常采用 Given/When/Then 格式 |
| Schema (模式) | 工件类型及其依赖关系的定义 |
| Spec (规范) | 描述系统行为的规范,包含需求和场景 |
| Source of truth (唯一事实来源) | openspec/specs/ 目录,包含当前商定的行为 |
后续步骤
- Getting Started - 实用的第一步
- Workflows - 常见模式及使用场景
- Commands - 完整的命令参考
- Customization - 创建自定义模式并配置项目