Skip to content

Latest commit

 

History

History
624 lines (461 loc) · 23.2 KB

File metadata and controls

624 lines (461 loc) · 23.2 KB

核心概念

本指南解释了 OpenSpec 背后的核心思想以及它们如何协同工作。关于实际使用,请参阅入门指南工作流

设计哲学

OpenSpec 围绕四个原则构建:

灵活而非僵化         — 无阶段门限,按需工作
迭代而非瀑布       — 边构建边学习,逐步完善
简单而非复杂       — 轻量级设置,最小化仪式感
棕地优先           — 适用于现有代码库,不限于绿地项目

为什么这些原则重要

灵活而非僵化。 传统的规范系统将你锁定在阶段中:先规划,再实施,然后完成。OpenSpec 更加灵活——你可以按工作需求以任何顺序创建制品。

迭代而非瀑布。 需求会变化。理解会加深。开始时看似不错的方法在查看代码库后可能不再适用。OpenSpec 拥抱这一现实。

简单而非复杂。 一些规范框架需要大量设置、严格格式或重量级流程。OpenSpec 不会妨碍你的工作。几秒钟内初始化,立即开始工作,仅在需要时自定义。

棕地优先。 大多数软件工作不是从零开始构建——而是修改现有系统。OpenSpec 基于增量的方法使得指定对现有行为的更改变得容易,而不仅仅是描述新系统。

整体架构

OpenSpec 将你的工作组织为两个主要区域:

┌────────────────────────────────────────────────────────────────────┐
│                        openspec/                                   │
│                                                                    │
│   ┌─────────────────────┐      ┌───────────────────────────────┐   │
│   │       specs/        │      │         changes/              │   │
│   │                     │      │                               │   │
│   │  单一事实来源       │◄─────│  提议的修改                   │   │
│   │  描述系统当前的     │ 合并 │  每个变更 = 一个文件夹        │   │
│   │  工作方式           │      │  包含制品 + 增量              │   │
│   │                     │      │                               │   │
│   └─────────────────────┘      └───────────────────────────────┘   │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

规范(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/

规范格式

一个规范包含需求,每个需求都有场景:

# 认证规范

## 目的
应用程序的认证和会话管理。

## 需求

### 需求:用户认证
系统应在成功登录时发放 JWT 令牌。

#### 场景:有效凭据
- 给定具有有效凭据的用户
- 当用户提交登录表单时
- 则返回 JWT 令牌
- 并且用户被重定向到仪表板

#### 场景:无效凭据
- 给定无效凭据
- 当用户提交登录表单时
- 则显示错误消息
- 并且不发放令牌

### 需求:会话过期
系统必须在 30 分钟不活动后使会话过期。

#### 场景:空闲超时
- 给定已认证的会话
- 当 30 分钟过去且没有活动时
- 则会话失效
- 并且用户必须重新认证

关键元素:

元素 目的
## 目的 此规范领域的高级描述
### 需求: 系统必须具有的特定行为
#### 场景: 需求在行动中的具体示例
SHALL/MUST/SHOULD RFC 2119 关键词,表示需求强度

为什么这样结构化规范

需求是"做什么"——它们说明系统应该做什么而不指定实现。

场景是"何时"——它们提供可验证的具体示例。好的场景:

  • 是可测试的(你可以为它们编写自动化测试)
  • 涵盖正常路径和边缘情况
  • 使用 Given/When/Then 或类似结构化格式

RFC 2119 关键词(SHALL、MUST、SHOULD、MAY)传达意图:

  • MUST/SHALL——绝对需求
  • SHOULD——推荐,但存在例外
  • MAY——可选

规范是什么(以及不是什么)

规范是行为契约,而不是实施计划。

好的规范内容:

  • 用户或下游系统依赖的可观察行为
  • 输入、输出和错误条件
  • 外部约束(安全性、隐私、可靠性、兼容性)
  • 可以测试或明确验证的场景

规范中应避免的内容:

  • 内部类/函数名称
  • 库或框架选择
  • 逐步实施细节
  • 详细的执行计划(这些属于 design.mdtasks.md

快速判断:

  • 如果实现方式可以改变而不影响外部可见行为,那它很可能不属于规范。

保持轻量:渐进式严谨

OpenSpec 旨在避免官僚主义。使用能使变更可验证的最轻量级别即可。

轻量规范(默认):

  • 简短的行为优先需求
  • 清晰的范围和非目标
  • 少量具体的验收检查

完整规范(适用于较高风险):

  • 跨团队或跨仓库的变更
  • API/契约变更、迁移、安全/隐私问题
  • 模糊性可能导致高成本返工的变更

大多数变更应保持轻量模式。

人类 + Agent 协作

在许多团队中,人类负责探索,Agent 负责起草制品。预期的协作循环是:

  1. 人类提供意图、上下文和约束条件。
  2. Agent 将其转化为行为优先的需求和场景。
  3. Agent 将实施细节保留在 design.mdtasks.md 中,而不是 spec.md 中。
  4. 验证在实施之前确认结构和清晰性。

这使规范对人类可读,对 Agent 保持一致。

变更(Changes)

变更是对系统的提议修改,打包为一个包含理解和实施所需所有内容的文件夹。

变更结构

openspec/changes/add-dark-mode/
├── proposal.md           # 为什么和做什么
├── design.md             # 如何做(技术方案)
├── tasks.md              # 实施清单
├── .openspec.yaml        # 变更元数据(可选)
└── specs/                # 增量规范
    └── ui/
        └── spec.md       # ui/spec.md 中的更改内容

每个变更都是自包含的。它包含:

  • 制品——捕获意图、设计和任务的文档
  • 增量规范——对添加、修改或删除内容的规范
  • 元数据——此特定变更的可选配置

为什么变更组织为文件夹

将变更打包为文件夹有几个好处:

  1. 一切在一起。 提案、设计、任务和规范位于同一位置。无需在不同位置查找。

  2. 并行工作。 多个变更可以同时存在而不会冲突。在 fix-auth-bug 进行时,可以同时处理 add-dark-mode

  3. 清晰历史。 归档时,变更会移动到 changes/archive/ 并保留完整上下文。你可以回顾并理解不仅发生了什么变化,还有为什么变化。

  4. 便于审查。 变更文件夹易于审查——打开它,阅读提案,检查设计,查看规范增量。

制品(Artifacts)

制品是变更中的文档,用于指导工作。

制品流程

proposal ──────► specs ──────► design ──────► tasks ──────► implement
    │               │             │              │
   为什么           改变什么      如何做          实施步骤
 + 范围           变化          方法           要执行

制品相互构建。每个制品为下一个提供上下文。

制品类型

提案(proposal.md

提案在高级别捕获意图范围方法

# 提案:添加深色模式

## 意图
用户要求提供深色模式选项,以在夜间使用时减少眼睛疲劳并匹配系统偏好。

## 范围
包含:
- 设置中的主题切换
- 系统偏好检测
- 在 localStorage 中持久化偏好

不包含:
- 自定义颜色主题(未来工作)
- 每页主题覆盖

## 方法
使用 CSS 自定义属性进行主题化,配合 React context 进行状态管理。在首次加载时检测系统偏好,允许手动覆盖。

何时更新提案:

  • 范围变化(缩小或扩大)
  • 意图明确(对问题有更好理解)
  • 方法发生根本性变化

规范(增量规范在 specs/ 中)

增量规范描述相对于当前规范的变化内容。详见下面的增量规范

设计(design.md

设计捕获技术方法架构决策

# 设计:添加深色模式

## 技术方法
通过 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`(修改)

何时更新设计:

  • 实施显示方法不可行
  • 发现更好的解决方案
  • 依赖项或约束条件变化

任务(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 等)
  • 保持任务足够小,可在一个会话中完成
  • 完成任务时勾选复选框

增量规范(Delta Specs)

增量规范是使 OpenSpec 适用于棕地开发的关键概念。它们描述正在变化的内容,而不是重述整个规范。

格式

# 认证增量

## 新增需求

### 需求:双因素认证
系统必须支持基于 TOTP 的双因素认证。

#### 场景:2FA 注册
- 给定未启用 2FA 的用户
- 当用户在设置中启用 2FA 时
- 则显示用于认证器应用设置的二维码
- 并且用户在激活前必须用代码验证

#### 场景:2FA 登录
- 给定已启用 2FA 的用户
- 当用户提交有效凭据时
- 则显示 OTP 挑战
- 并且只有在有效 OTP 后登录才完成

## 修改需求

### 需求:会话过期
系统必须在 15 分钟不活动后使会话过期。
(之前:30 分钟)

#### 场景:空闲超时
- 给定已认证的会话
- 当 15 分钟过去且没有活动时
- 则会话失效

## 删除需求

### 需求:记住我
(已弃用,支持 2FA。用户应在每个会话重新认证。)

增量部分

部分 含义 归档时发生什么
## 新增需求 新行为 附加到主规范
## 修改需求 改变的行为 替换现有需求
## 删除需求 已弃用的行为 从主规范中删除

为什么使用增量而非完整规范

清晰性。 增量明确显示正在变化的内容。阅读完整规范时,你必须与当前版本进行心理差异比较。

避免冲突。 只要修改不同的需求,两个变更可以接触同一个规范文件而不会冲突。

审查效率。 审查者看到的是变更,而不是未改变的上下文。专注于重要内容。

棕地适应性。 大多数工作都是修改现有行为。增量使修改成为一等公民,而不是事后考虑。

模式(Schemas)

模式定义工作流的制品类型及其依赖关系。

模式如何工作

# 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]   # 跳过规范/设计,直接进入任务

有关创建和使用自定义模式的完整详情,请参阅自定义

归档(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

归档过程

  1. 合并增量。 每个增量规范部分(新增/修改/删除)应用到相应的主规范。

  2. 移动到归档。 变更文件夹移动到 changes/archive/,带有日期前缀以便按时间顺序排序。

  3. 保留上下文。 所有制品在归档中保持完整。你总是可以回顾以理解为什么进行变更。

为什么归档重要

清洁状态。 活动变更(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/                      │  │
│   └────────────────┘     │  规范现在是更新的单一事实来源                     │   │
│                          └──────────────────────────────────────────────┘   │
│                                                                             │
└──────────────────────────────────────────────────────────────────────────────┘

良性循环:

  1. 规范描述当前行为
  2. 变更提议修改(作为增量)
  3. 实施使变更成为现实
  4. 归档将增量合并到规范中
  5. 规范现在描述新行为
  6. 下一个变更基于更新的规范构建

术语表

术语 定义
制品(Artifact) 变更中的文档(提案、设计、任务或增量规范)
归档(Archive) 完成变更并将其增量合并到主规范的过程
变更(Change) 对系统的提议修改,打包为包含制品的文件夹
增量规范(Delta spec) 描述相对于当前规范的变更(新增/修改/删除)的规范
领域(Domain) 规范逻辑分组(例如 auth/payments/
需求(Requirement) 系统必须具有的特定行为
场景(Scenario) 需求的具体示例,通常采用 Given/When/Then 格式
模式(Schema) 制品类型及其依赖关系的定义
规范(Spec) 描述系统行为的规范,包含需求和场景
单一事实来源(Source of truth) openspec/specs/ 目录,包含当前商定的行为

下一步