概念
本指南解释了 OpenSpec 背后的核心理念以及它们如何结合在一起。关于实际用法,请参阅 [[[[新手入门]]]] 和 [[[[工作流]]]]。
哲学
OpenSpec 建立在四个原则之上:
fluid not rigid — 没有阶段门,做有意义的事
iterative not waterfall — 边构建边学习,边进行边完善
easy not complex — 轻量级设置,最少的仪式
brownfield-first — 适用于现有代码库,不仅仅是新建项目为什么这些原则很重要
流畅不僵化 (Fluid not rigid)。 传统的规格系统将您锁定在阶段中:首先计划,然后实施,然后完成。OpenSpec 更灵活 —— 您可以按任何对您的工作有意义的顺序创建工件。
迭代不瀑布 (Iterative not waterfall)。 需求会变化。理解会加深。开始时看起来不错的方法,在看到代码库后可能就不适用了。OpenSpec 拥抱这一现实。
简单不复杂 (Easy not complex)。 一些规格框架需要大量设置、僵化的格式或繁琐的流程。OpenSpec 不会妨碍您。几秒钟内初始化,立即开始工作,仅在需要时进行自定义。
Brownfield-first。 大多数软件工作不是从头开始构建,而是修改现有系统。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/
规格格式
规格包含需求,每个需求都有场景:
# Auth Specification
## Purpose
Authentication and session management for the application.
## Requirements
### Requirement: User Authentication
The system SHALL issue a JWT token upon successful login.
#### Scenario: Valid credentials
- GIVEN a user with valid credentials
- WHEN the user submits login form
- THEN a JWT token is returned
- AND the user is redirected to dashboard
#### Scenario: Invalid credentials
- GIVEN invalid credentials
- WHEN the user submits login form
- THEN an error message is displayed
- AND no token is issued
### Requirement: Session Expiration
The system MUST expire sessions after 30 minutes of inactivity.
#### Scenario: Idle timeout
- GIVEN an authenticated session
- WHEN 30 minutes pass without activity
- THEN the session is invalidated
- AND the user must re-authenticate关键要素:
| 要素 | 目的 |
|---|---|
## Purpose | 此规格领域的高层描述 |
### Requirement: | 系统必须具备的具体行为 |
#### Scenario: | 需求在实际中的具体示例 |
| SHALL/MUST/SHOULD | 指示需求强度的 RFC 2119 关键字 |
为什么要这样构建规格
需求是“什么” —— 它们陈述系统应该做什么,而不指定实施。
场景是“何时” —— 它们提供可验证的具体示例。好的场景:
- 可测试(您可以为它们编写自动化测试)
- 涵盖快乐路径和边缘情况
- 使用 Given/When/Then 或类似的结构化格式
RFC 2119 关键字 (SHALL, MUST, SHOULD, MAY) 传达意图:
- MUST/SHALL — 绝对要求
- SHOULD — 推荐,但存在例外
- MAY — 可选
变更 (Changes)
变更是对系统的提议修改,打包为一个包含理解和实施所需一切的文件夹。
变更结构
openspec/changes/add-dark-mode/
├── proposal.md # 原因和内容
├── design.md # 如何做(技术方法)
├── tasks.md # 实施清单
├── .openspec.yaml # 变更元数据(可选)
└── 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)
提案在高层面上捕捉 意图、范围 和 方法。
# Proposal: Add Dark Mode
## Intent
Users have requested a dark mode option to reduce eye strain
during nighttime usage and match system preferences.
## Scope
In scope:
- Theme toggle in settings
- System preference detection
- Persist preference in localStorage
Out of scope:
- Custom color themes (future work)
- Per-page theme overrides
## Approach
Use CSS custom properties for theming with a React context
for state management. Detect system preference on first load,
allow manual override.何时更新提案:
- 范围变更(缩小或扩大)
- 意图阐明(更好地理解问题)
- 方法根本转变
规格 (增量规格在 specs/ 中)
增量规格描述相对于当前规格 正在变更的内容。请参阅下面的 增量规格。
设计 (design.md)
设计捕捉 技术方法 和 架构决策。
# Design: Add Dark Mode
## Technical Approach
Theme state managed via React Context to avoid prop drilling.
CSS custom properties enable runtime switching without class toggling.
## Architecture Decisions
### Decision: Context over Redux
Using React Context for theme state because:
- Simple binary state (light/dark)
- No complex state transitions
- Avoids adding Redux dependency
### Decision: CSS Custom Properties
Using CSS variables instead of CSS-in-JS because:
- Works with existing stylesheet
- No runtime overhead
- Browser-native solution
## Data FlowThemeProvider (context) │ ▼ ThemeToggle ◄──► localStorage │ ▼ CSS Variables (applied to :root)
## File Changes
- `src/contexts/ThemeContext.tsx` (new)
- `src/components/ThemeToggle.tsx` (new)
- `src/styles/globals.css` (modified)何时更新设计:
- 实施显示该方法行不通
- 发现了更好的解决方案
- 依赖关系或约束发生变化
任务 (tasks.md)
任务是 实施清单 — 带有复选框的具体步骤。
# Tasks
## 1. Theme Infrastructure
- [ ] 1.1 Create ThemeContext with light/dark state
- [ ] 1.2 Add CSS custom properties for colors
- [ ] 1.3 Implement localStorage persistence
- [ ] 1.4 Add system preference detection
## 2. UI Components
- [ ] 2.1 Create ThemeToggle component
- [ ] 2.2 Add toggle to settings page
- [ ] 2.3 Update Header to include quick toggle
## 3. Styling
- [ ] 3.1 Define dark theme color palette
- [ ] 3.2 Update components to use CSS variables
- [ ] 3.3 Test contrast ratios for accessibility任务最佳实践:
- 将相关任务分组在标题下
- 使用分层编号(1.1, 1.2 等)
- 保持任务足够小,以便在一个会话中完成
- 完成任务后将其勾选
增量规格 (Delta Specs)
增量规格是使 OpenSpec 适用于 brownfield 开发的关键概念。它们描述 正在变更的内容,而不是重述整个规格。
格式
# Delta for Auth
## ADDED Requirements
### Requirement: Two-Factor Authentication
The system MUST support TOTP-based two-factor authentication.
#### Scenario: 2FA enrollment
- GIVEN a user without 2FA enabled
- WHEN the user enables 2FA in settings
- THEN a QR code is displayed for authenticator app setup
- AND the user must verify with a code before activation
#### Scenario: 2FA login
- GIVEN a user with 2FA enabled
- WHEN the user submits valid credentials
- THEN an OTP challenge is presented
- AND login completes only after valid OTP
## MODIFIED Requirements
### Requirement: Session Expiration
The system MUST expire sessions after 15 minutes of inactivity.
(Previously: 30 minutes)
#### Scenario: Idle timeout
- GIVEN an authenticated session
- WHEN 15 minutes pass without activity
- THEN the session is invalidated
## REMOVED Requirements
### Requirement: Remember Me
(Deprecated in favor of 2FA. Users should re-authenticate each session.)增量部分
| 部分 | 含义 | 归档时发生什么 |
|---|---|---|
## ADDED Requirements | 新行为 | 追加到主规格 |
## MODIFIED Requirements | 更改的行为 | 替换现有需求 |
## REMOVED Requirements | 弃用的行为 | 从主规格中删除 |
为什么用增量而不是完整规格
清晰度。 增量确切显示的变更内容。阅读完整规格,您必须在脑海中将其与当前版本进行比较。
避免冲突。 两个变更可以触及同一个规格文件而不发生冲突,只要它们修改不同的需求。
审查效率。 审查者看到的是变更,而不是未变更的上下文。关注重要事项。
Brownfield 适用。 大多数工作修改现有行为。增量使修改成为一等公民,而不是事后诸葛亮。
Schemas
Schemas 定义工作流的工件类型及其依赖关系。
Schemas 如何工作
# openspec/schemas/spec-driven/schema.yaml
name: spec-driven
artifacts:
- id: proposal
generates: proposal.md
requires: [] # No dependencies, can create first
- id: specs
generates: specs/**/*.md
requires: [proposal] # Needs proposal before creating
- id: design
generates: design.md
requires: [proposal] # Can create in parallel with specs
- id: tasks
generates: tasks.md
requires: [specs, design] # Needs both specs and design first工件形成依赖图:
proposal
(root node)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(requires: (requires:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(requires:
specs, design)依赖是推动者,不是门槛。 它们显示可以创建什么,而不是必须接下来创建什么。如果您不需要设计,可以跳过它。您可以在设计之前或之后创建规格 —— 两者都只依赖于提案。
内置 Schemas
spec-driven (默认)
规格驱动开发的标准工作流:
proposal → specs → design → tasks → implement最适合:大多数功能工作,您希望在实施之前就规格达成一致。
自定义 Schemas
为您的团队工作流创建自定义 Schemas:
# 从头开始创建
openspec schema init research-first
# 或 fork 现有的
openspec schema fork spec-driven research-first自定义 Schema 示例:
# openspec/schemas/research-first/schema.yaml
name: research-first
artifacts:
- id: research
generates: research.md
requires: [] # Do research first
- id: proposal
generates: proposal.md
requires: [research] # Proposal informed by research
- id: tasks
generates: tasks.md
requires: [proposal] # Skip specs/design, go straight to tasks有关创建和使用自定义 Schemas 的完整详细信息,请参阅 [[[[自定义]]]]。
归档 (Archive)
归档通过将其增量规格合并到主规格并保留变更历史记录来完成变更。
归档时发生什么
Before archive:
openspec/
├── specs/
│ └── auth/
│ └── spec.md ◄────────────────┐
└── changes/ │
└── add-2fa/ │
├── proposal.md │
├── design.md │ merge
├── tasks.md │
└── specs/ │
└── auth/ │
└── spec.md ─────────┘
After archive:
openspec/
├── specs/
│ └── auth/
│ └── spec.md # Now includes 2FA requirements
└── changes/
└── archive/
└── 2025-01-24-add-2fa/ # Preserved for history
├── proposal.md
├── design.md
├── tasks.md
└── specs/
└── auth/
└── spec.md归档过程
合并增量。 每个增量规格部分 (ADDED/MODIFIED/REMOVED) 应用于相应的主规格。
移动到归档。 变更文件夹移动到
changes/archive/,带有日期前缀以便按时间顺序排列。保留上下文。 所有工件保留在归档中。您总是可以回顾以理解为什么进行变更。
为什么归档很重要
干净的状态。 活动变更 (changes/) 仅显示进行中的工作。已完成的工作移开。
审计跟踪。 归档保留每个变更的完整上下文 —— 不仅仅是变更了什么,还有解释原因的提案,解释如何做的设计,以及显示已完成工作的任务。
规格演变。 规格随着变更归档而有机增长。每个归档合并其增量,随时间建立全面的规范。
一切如何结合在一起
┌─────────────────────────────────────────────────────────────────────────────┐
│ OPENSPEC FLOW │
│ │
│ ┌────────────────┐ │
│ │ 1. START │ /opsx:new creates a change folder │
│ │ CHANGE │ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 2. CREATE │ /opsx:ff or /opsx:continue │
│ │ ARTIFACTS │ Creates proposal → specs → design → tasks │
│ │ │ (based on schema dependencies) │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 3. IMPLEMENT │ /opsx:apply │
│ │ TASKS │ Work through tasks, checking them off │
│ │ │◄──── Update artifacts as you learn │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 4. VERIFY │ /opsx:verify (optional) │
│ │ WORK │ Check implementation matches specs │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
│ │ 5. ARCHIVE │────►│ Delta specs merge into main specs │ │
│ │ CHANGE │ │ Change folder moves to archive/ │ │
│ └────────────────┘ │ Specs are now the updated source of truth │ │
│ └──────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘良性循环:
- 规格描述当前行为
- 变更提议修改(作为增量)
- 实施使变更成为现实
- 归档将增量合并到规格中
- 规格现在描述新行为
- 下一个变更建立在更新的规格之上
词汇表
| 术语 | 定义 |
|---|---|
| 工件 (Artifact) | 变更中的文档(提案、设计、任务或增量规格) |
| 归档 (Archive) | 完成变更并将其增量合并到主规格的过程 |
| 变更 (Change) | 对系统的提议修改,打包为带有工件的文件夹 |
| 增量规格 (Delta spec) | 描述相对于当前规格的变更(新增/修改/移除)的规格 |
| 领域 (Domain) | 规格的逻辑分组(例如 auth/, payments/) |
| 需求 (Requirement) | 系统必须具备的具体行为 |
| 场景 (Scenario) | 需求的具体示例,通常采用 Given/When/Then 格式 |
| Schema | 工件类型及其依赖关系的定义 |
| 规格 (Spec) | 描述系统行为的规范,包含需求和场景 |
| 事实来源 (Source of truth) | openspec/specs/ 目录,包含当前商定的行为 |
下一步
- [[[[新手入门]]]] - 实际的第一步
- [[[[工作流]]]] - 常见模式以及何时使用
- [[[[命令]]]] - 完整命令参考
- [[[[自定义]]]] - 创建自定义 Schemas 并配置您的项目