概念
本指南将介绍 OpenSpec 背后的核心理念及其相互关系。如需了解实际使用方法,请参阅入门指南和工作流。
设计哲学
OpenSpec 围绕四项原则构建:
灵活而非僵化 — 无阶段门禁,按需开展合理工作
迭代而非瀑布 — 边构建边学习,逐步优化完善
轻量而非复杂 — 极简初始化,最小化流程仪式
优先适配现有系统 — 适配现有代码库,而非仅支持从零新建的项目这些原则的意义
灵活而非僵化。 传统的规范系统会强制将工作划分为固定阶段:先规划,再实现,最后结束。OpenSpec 更加灵活——你可以根据实际工作需要,按任意顺序创建相关产物。
迭代而非瀑布。 需求会不断变化,对问题的理解也会逐步深入。初始阶段看似合理的方案,在接触实际代码库后可能并不适用。OpenSpec 拥抱这一现实。
轻量而非复杂。 部分规范框架需要大量配置、固定格式或繁重的流程要求。OpenSpec 不会给你增添额外负担:数秒即可完成初始化,立即开始工作,仅在需要时进行自定义。
优先适配现有系统。 大部分软件开发工作并非从零开始构建,而是对现有系统进行修改。OpenSpec 基于增量的设计思路,让你可以轻松定义对现有行为的变更,而不仅仅是描述新系统。
整体概览
OpenSpec 将你的工作划分为两个核心区域:
┌────────────────────────────────────────────────────────────────────┐
│ openspec/ │
│ │
│ ┌─────────────────────┐ ┌───────────────────────────────┐ │
│ │ specs/ │ │ changes/ │ │
│ │ │ │ │ │
│ │ Source of truth │◄─────│ Proposed modifications │ │
│ │ How your system │ merge│ Each change = one folder │ │
│ │ currently works │ │ Contains artifacts + deltas │ │
│ │ │ │ │ │
│ └─────────────────────┘ └───────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────┘规范(Specs) 是唯一事实来源——用于描述系统当前的运行行为。
变更(Changes) 是待提出的修改项——在合并前会存放在独立的文件夹中。
这种分离机制是核心设计。你可以在无冲突的情况下并行处理多个变更;可以在变更影响主规范之前完成评审;归档变更时,其增量内容会干净地合并到唯一事实来源中。
规范(Specs)
规范通过结构化的需求与场景描述系统行为。
结构
openspec/specs/
├── auth/
│ └── spec.md # 认证行为
├── payments/
│ └── spec.md # 支付处理
├── notifications/
│ └── spec.md # 通知系统
└── ui/
└── spec.md # UI 行为与主题按领域组织规范——即符合系统逻辑的分组方式,常见模式包括:
- 按功能领域划分:
auth/、payments/、search/ - 按组件划分:
api/、frontend/、workers/ - 按限界上下文划分:
ordering/、fulfillment/、inventory/
规范格式
一个规范包含需求,每个需求下对应若干场景:
markdown
# 认证规范
## 目的
负责应用的认证与会话管理。
## 需求
### 需求:用户认证
用户成功登录时,系统须颁发 JWT 令牌。
#### 场景:有效凭据
- 假如(GIVEN)用户持有有效凭据
- 当(WHEN)用户提交登录表单
- 那么(THEN)返回 JWT 令牌
- 并且(AND)用户被重定向到控制台
#### 场景:无效凭据
- 假如(GIVEN)凭据无效
- 当(WHEN)用户提交登录表单
- 那么(THEN)显示错误提示
- 并且(AND)不颁发任何令牌
### 需求:会话过期
系统须在 30 分钟无操作后使会话失效。
#### 场景:空闲超时
- 假如(GIVEN)存在已认证的会话
- 当(WHEN)30 分钟无任何操作
- 那么(THEN)会话被作废
- 并且(AND)用户需要重新认证核心要素:
| 要素 | 作用 |
|---|---|
## 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。 - 实施前通过校验确认结构与表述清晰。
这种方式既保证规范对人类可读,也保证对智能体的表述一致性。
变更(Changes)
变更是对系统的待实施修改,被打包为包含所有理解与实施所需内容的文件夹。
变更结构
openspec/changes/add-dark-mode/
├── proposal.md # 变更原因与内容
├── design.md # 技术方案
├── tasks.md # 实施清单
├── .openspec.yaml # 变更元数据(可选):schema、创建时间、是否跳过规范校验
└── specs/ # 增量规范
└── ui/
└── spec.md # ui/spec.md 的变更内容每个变更都是自包含的,包含以下内容:
- 产物:记录意图、设计方案与实施任务的文档
- 增量规范:描述新增、修改或移除内容的规范文档
- 元数据:针对该变更的可选配置项
为何将变更打包为文件夹
将变更打包为文件夹有以下优势:
- 所有内容集中存放。提案、设计、任务与规范都放在同一位置,无需在多个地方查找。
- 支持并行工作。多个变更可以同时存在且互不冲突,比如可以在处理
add-dark-mode的同时推进fix-auth-bug变更。 - 历史记录清晰。归档时变更会被移动到
changes/archive/目录,完整上下文得以保留。后续回溯时不仅能知道做了什么变更,还能了解变更原因。 - 便于评审。变更文件夹易于评审:打开文件夹,阅读提案,查看设计,检查规范增量即可。
产物(Artifacts)
产物是变更内部用于指导工作的文档。
产物流转流程
proposal ──────► specs ──────► design ──────► tasks ──────► implement
│ │ │ │
why what how steps
+ scope changes approach to take产物之间层层递进,每个产物都为下一个产物提供上下文。
产物类型
提案(proposal.md)
提案用于在高层级记录意图、范围与方案。
markdown
# 提案:新增深色模式
## 意图
用户反馈希望增加深色模式选项,以减少夜间使用时的眼部疲劳,同时适配系统主题偏好。
## 范围
范围内:
- 设置页的主题切换开关
- 系统偏好检测
- 偏好设置持久化存储到 localStorage
范围外:
- 自定义配色主题(后续迭代实现)
- 单页主题覆盖能力
## 方案
使用 CSS 自定义属性实现主题切换,通过 React Context 管理状态。首次加载时检测系统偏好,同时支持用户手动切换。提案更新时机:
- 范围发生变更(收缩或扩张)
- 意图进一步明确(对问题的理解更清晰)
- 方案发生根本性调整
规范(specs/ 目录下的增量规范)
增量规范用于描述相对于当前规范的变更内容,详见下文 增量规范 部分。
设计文档(design.md)
设计文档用于记录技术方案与架构决策。
markdown
# 设计文档:新增深色模式
## 技术方案
主题状态通过 React Context 管理,避免属性透传。
CSS 自定义属性支持运行时切换,无需切换类名。
## 架构决策
### 决策:选用 Context 而非 Redux
选用 React Context 管理主题状态的原因如下:
- 状态仅为简单的二元值(亮色/暗色)
- 无复杂的状态流转逻辑
- 无需引入 Redux 依赖
### 决策:选用 CSS 自定义属性
选用 CSS 变量而非 CSS-in-JS 的原因如下:
- 与现有样式表兼容
- 无运行时开销
- 浏览器原生支持方案
## 数据流
```
ThemeProvider (context)
│
▼
ThemeToggle ◄──► localStorage
│
▼
CSS Variables (applied to :root)
```
## 文件变更
- `src/contexts/ThemeContext.tsx`(新增)
- `src/components/ThemeToggle.tsx`(新增)
- `src/styles/globals.css`(修改)设计文档更新时机:
- 实施过程中发现当前方案不可行
- 发现更优的解决方案
- 依赖项或约束条件发生变更
任务清单(tasks.md)
任务清单是实施核对表,包含带复选框的具体实施步骤。
markdown
# 任务清单
## 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)
- 任务粒度足够小,可在单个工作周期内完成
- 完成任务后及时勾选对应复选框
增量规范(Delta Specs)
增量规范是 OpenSpec 适配存量(brownfield)开发的核心概念,用于描述变更内容,而非重复陈述整个规范。
格式规范
markdown
# 认证模块增量规范
## 新增需求
### 需求:双因素认证
系统须支持基于 TOTP 的双因素认证。
#### 场景:2FA 注册
- 假如(GIVEN)用户未开启 2FA
- 当(WHEN)用户在设置页开启 2FA
- 那么(THEN)显示用于验证器应用配置的二维码
- 并且(AND)激活前用户需通过验证码校验
#### 场景:2FA 登录
- 假如(GIVEN)用户已开启 2FA
- 当(WHEN)用户提交有效凭据
- 那么(THEN)弹出 OTP 校验挑战
- 并且(AND)仅当 OTP 校验通过后登录流程才完成
## 修改需求
### 需求:会话过期
系统须在 15 分钟无操作后使会话失效。
(此前为 30 分钟)
#### 场景:空闲超时
- 假如(GIVEN)存在已认证的会话
- 当(WHEN)15 分钟无任何操作
- 那么(THEN)会话被作废
## 移除需求
### 需求:记住我
(因双因素认证替代而废弃。用户每次会话需重新认证。)增量章节说明
| 章节 | 含义 | 归档后处理逻辑 |
|---|---|---|
## ADDED Requirements | 新增行为 | 追加到主规范中 |
## MODIFIED Requirements | 变更行为 | 替换原有对应需求 |
## REMOVED Requirements | 废弃行为 | 从主规范中删除 |
为何采用增量规范而非完整规范
更清晰。增量规范直接展示具体变更内容;若阅读完整规范,则需要 mentally 对比当前版本才能找出差异。
避免冲突。只要两个变更修改的是不同需求,就可以同时修改同一规范文件而不会产生冲突。
提升评审效率。评审者只需关注变更内容,无需阅读未修改的上下文,聚焦核心变更即可。
适配存量开发。绝大多数工作都是对现有行为的修改,增量规范将修改行为作为一等公民对待,而非事后补充。
模式
模式定义了工作流中的产物类型及其依赖关系。
模式的工作原理
yaml
# 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
(依赖: (依赖:
提案) 提案)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(依赖:
规格、设计)依赖是前提条件,而非强制门槛。 它们表示可以创建哪些产物,而非必须接下来创建什么。如果不需要设计,你可以跳过该步骤;你可以在设计之前或之后创建规格——两者都仅依赖提案。
内置模式
spec-driven(默认)
面向规格驱动开发的标准工作流:
proposal → specs → design → tasks → implement适用场景:大部分功能开发工作,你希望在实现前先确认规格。
自定义模式
可根据团队工作流创建自定义模式:
bash
# 从头创建
openspec schema init research-first
# 或基于现有模式分支创建
openspec schema fork spec-driven research-first自定义模式示例:
yaml
# 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 # 现已包含双因素认证需求
└── changes/
└── archive/
└── 2025-01-24-add-2fa/ # 保留用于历史追溯
├── proposal.md
├── design.md
├── tasks.md
└── specs/
└── auth/
└── spec.md归档流程
合并增量内容
增量规格的每个分区(ADDED/MODIFIED/REMOVED)都会被应用到对应的主规格中。移入归档区
变更文件夹会被移动到changes/archive/目录下,并添加日期前缀以保证按时间顺序排列。保留上下文
所有产物都会完整保留在归档区,你可以随时回溯查看某项变更的缘由。
归档的价值
状态清晰
进行中的变更(changes/目录)仅展示未完成的工作,已完成的工作会被移出该区域。
可追溯的审计记录
归档区会保留每一项变更的完整上下文:不仅包含变更内容本身,还包含解释变更原因的提案、说明实现方案的设计,以及记录已完成工作的任务清单。
规格的有机演进
随着变更不断被归档,规格会自然生长。每次归档都会合并对应的增量内容,逐步构建出完整的规格体系。
整体流程
┌──────────────────────────────────────────────────────────────────────────────┐
│ OPENSPEC 流程 │
│ │
│ ┌────────────────┐ │
│ │ 1. 启动变更 │ /opsx:propose(核心模式)或 /opsx:new(扩展模式) │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 2. 创建产物 │ /opsx:ff 或 /opsx:continue(扩展工作流) │
│ │ │ 按照模式依赖关系生成提案 → 规格 → 设计 → 任务 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 3. 执行任务 │ /opsx:apply │
│ │ │ 逐项完成并勾选任务 │
│ │ │◄──── 学习过程中更新产物 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 4. 验证工作 │ /opsx:verify(可选) │
│ │ │ 检查实现是否符合规格要求 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
│ │ 5. 归档变更 │────►│ 增量规格合并到主规格中 │ │
│ │ │ │ 变更文件夹移入archive/目录 │ │
│ └────────────────┘ │ 规格成为最新的权威依据 │ │
│ └──────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘正向循环:
- 规格描述当前系统行为
- 变更以增量形式提出修改方案
- 实现将变更落地
- 归档将增量内容合并到规格中
- 规格更新为描述新的系统行为
- 下一次变更基于更新后的规格开展
术语表
| 术语 | 定义 |
|---|---|
| 产物 | 变更内的文档(包括提案、设计、任务清单或增量规格) |
| 归档 | 完成变更并将增量内容合并到主规格的流程 |
| 变更 | 对系统的修改提案,以包含若干产物的文件夹形式打包 |
| 增量规格 | 描述相对于当前规格的变更内容(新增/修改/删除)的规格文档 |
| 领域 | 规格的逻辑分组(例如auth/、payments/) |
| 需求 | 系统必须具备的特定行为 |
| 场景 | 需求的具体示例,通常采用“前提/当/那么”格式编写 |
| 模式 | 产物类型及其依赖关系的定义 |
| 规格 | 描述系统行为的规范文档,包含需求和场景 |
| 权威依据 | openspec/specs/目录,存储当前各方确认的系统行为规范 |