
📖 写在前面
在 AI 编程快速发展的 2025 年,一种新的开发范式正在崛起:SDD(Specification-Driven Development,规范驱动开发)。
传统开发中,我们与 AI 的对话往往是随意的、模糊的,导致 AI 生成"幻觉代码"或偏离需求。SDD 的核心思想是:在写代码之前,先让 AI 和人类对"要构建什么"达成明确的共识。
本文将深入介绍 SDD 领域的两个核心工具:GitHub SpecKit 和 Fission-AI OpenSpec,帮助您理解如何在 AI 编程中实现真正的"意图锁定"。
🎯 一、什么是 SDD(规范驱动开发)?
1.1 核心定义
SDD(Specification-Driven Development) 是一种"规范优先"的软件开发方法论,其核心原则是:
go
┌─────────────────────────────────────────────────────────────────┐
│ SDD 开发流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 【锁定意图】先写规范(Specification) │
│ └─ 明确定义"构建什么"(What) │
│ │
│ 2. 【生成计划】AI 根据规范创建实现计划 │
│ └─ 规划"如何实现"(How) │
│ │
│ 3. 【生成任务】将计划拆解为可执行任务 │
│ └─ 具体的实施步骤 │
│ │
│ 4. 【实现代码】AI 按照任务生成代码 │
│ └─ 代码只是"最后一公里" │
│ │
│ 5. 【测试验证】验证是否符合规范 │
│ └─ 确保实现与规范一致 │
│ │
└─────────────────────────────────────────────────────────────────┘
1.2 SDD vs 传统开发
| 维度 | 传统 AI 编程 | SDD 规范驱动开发 |
|---|---|---|
| 沟通方式 | 随意对话、模糊指令 | 结构化规范文档 |
| 核心资产 | 代码 | 规范(Specification) |
| 意图锁定 | ❌ 容易偏离 | ✅ 先达成共识 |
| 可追溯性 | ❌ 难以回溯 | ✅ 规范即文档 |
| AI 幻觉 | ❌ 高风险 | ✅ 约束明确 |
| 质量保证 | 事后修复 | 事前验证 |
1.3 SDD 的核心价值
go
┌─────────────────────────────────────────────────────────────────┐
│ SDD 的四大价值 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 【锁定意图】 │
│ └─ 在写代码前,你和 AI 先对"要做什么"达成共识 │
│ │
│ 2. 【减少幻觉】 │
│ └─ 规范约束了 AI 的输出范围,避免胡乱发挥 │
│ │
│ 3. 【可审计性】 │
│ └─ 每次变更都有明确的规范记录,便于审查和回溯 │
│ │
│ 4. 【可维护性】 │
│ └─ 规范成为活的文档,与代码同步演进 │
│ │
└─────────────────────────────────────────────────────────────────┘
🛠️ 二、GitHub SpecKit:结构化的 SDD 工具
2.1 什么是 SpecKit?
定义:SpecKit 是 GitHub 官方开源的规范驱动开发工具包,提供了一套完整的命令行工具,帮助开发者通过结构化的规范文档与 AI 协作。
官方仓库:github.com/github/spec-kit
核心特点:
-
✅ 官方出品,GitHub 背书
-
✅ 结构化工作流(7个标准命令)
-
✅ 内置 TDD 测试框架
-
✅ 适合从零开始的新项目(Greenfield)
-
✅ 开源免费,43.7k+ GitHub Stars
2.2 SpecKit 的七个核心命令
go
# SpecKit 标准工作流(7个命令)
命令 1:/speckit.constitution - 创建项目治理原则
作用:定义项目的开发准则、技术栈选择、代码规范等元规则。
示例:
go
# 项目 Constitution
## 技术栈
- 语言: Python 3.11+
- 框架: FastAPI
- 数据库: PostgreSQL
- 测试: pytest
## 开发准则
- 遵循 PEP 8 代码规范
- 所有函数必须有类型注解
- 测试覆盖率不低于 80%
- 提交前必须通过 lint 检查
## 架构原则
- 分层架构: Handler → Service → Repository
- 依赖注入: 使用 fastapi.Depends
- 错误处理: 统一异常处理器
命令 2:/speckit.specify - 描述需求
作用:明确描述"要构建什么",包括功能需求、非功能需求、约束条件。
示例:
go
# 用户认证功能 Specification
## 功能概述
实现基于 JWT 的用户认证系统,支持登录、注册、令牌刷新。
## 功能需求
1. 用户注册
- 输入: email, password, username
- 输出: 用户 ID + JWT access token
- 验证: email 格式、密码强度(8位以上+大小写字母+数字)
2. 用户登录
- 输入: email, password
- 输出: JWT access token (15分钟有效) + refresh token (7天有效)
3. 令牌刷新
- 输入: refresh token
- 输出: 新的 access token
## 非功能需求
- 性能: 登录响应时间 < 200ms
- 安全: 密码使用 bcrypt 哈希(cost=12)
- 可用性: 99.9% SLA
## 约束条件
- 不支持第三方登录(Google/GitHub)
- 不支持密码找回功能(后续版本)
命令 3:/speckit.clarify - 需求澄清
作用:AI 主动提问,澄清需求中的模糊点,确保规范完整无歧义。
示例输出:
go
# 澄清问题
以下问题需要明确:
1. [登录失败] 登录失败时是否返回具体原因("密码错误" vs "用户不存在")?
推荐答案: 返回通用错误信息,防止用户枚举
2. [令牌存储] 客户端应如何存储 refresh token?
选项: A) localStorage B) httpOnly cookie C) 内存
推荐答案: B) httpOnly cookie(更安全)
3. [并发登录] 是否允许同一用户多个设备同时登录?
选项: A) 允许 B) 仅允许一个活跃令牌
推荐答案: A) 允许(第一阶段)
命令 4:/speckit.plan - 创建技术实现计划
作用:AI 根据规范生成详细的技术实现方案。
示例输出:
go
# 技术实现计划
## 架构设计
### 数据模型
User 表:
-
id: UUID (PK)
-
email: VARCHAR(255) UNIQUE
-
password_hash: VARCHAR(255)
-
username: VARCHAR(50)
-
created_at: TIMESTAMP
-
updated_at: TIMESTAMP
RefreshToken 表:
-
id: UUID (PK)
-
user_id: UUID (FK)
-
token_hash: VARCHAR(255)
-
expires_at: TIMESTAMP
go
### API 设计
POST /api/v1/auth/register POST /api/v1/auth/login POST /api/v1/auth/refresh POST /api/v1/auth/logout
go
### 安全措施
- 密码: bcrypt (cost=12)
- JWT: HS256 算法,密钥从环境变量读取
- Rate Limiting: 每个 IP 每分钟最多 10 次登录尝试
实现顺序
-
搭建项目骨架(FastAPI + SQLAlchemy)
-
实现数据模型和数据库迁移
-
实现密码哈希工具函数
-
实现 JWT 工具函数
-
实现 /register 端点
-
实现 /login 端点
-
实现 /refresh 端点
-
编写集成测试
go
#### 命令 5:`/speckit.tasks` - 生成可执行任务
**作用**:将实现计划拆解为具体的、可执行的任务列表。
**示例输出**:
```markdown
# 任务列表
## Phase 1: 基础设施 (30分钟)
- [ ] Task 1.1: 初始化 FastAPI 项目结构
- [ ] Task 1.2: 配置 SQLAlchemy 和 PostgreSQL 连接
- [ ] Task 1.3: 创建 Alembic 迁移配置
## Phase 2: 数据层 (1小时)
- [ ] Task 2.1: 定义 User 模型
- [ ] Task 2.2: 定义 RefreshToken 模型
- [ ] Task 2.3: 创建数据库迁移脚本
- [ ] Task 2.4: 编写 Repository 基类
## Phase 3: 业务逻辑 (2小时)
- [ ] Task 3.1: 实现密码哈希服务
- [ ] Task 3.2: 实现 JWT 令牌服务
- [ ] Task 3.3: 实现注册服务
- [ ] Task 3.4: 实现登录服务
- [ ] Task 3.5: 实现令牌刷新服务
## Phase 4: API 层 (1.5小时)
- [ ] Task 4.1: 实现 /register 端点
- [ ] Task 4.2: 实现 /login 端点
- [ ] Task 4.3: 实现 /refresh 端点
- [ ] Task 4.4: 添加全局异常处理器
## Phase 5: 测试 (1.5小时)
- [ ] Task 5.1: 编写单元测试(服务层)
- [ ] Task 5.2: 编写集成测试(API 层)
- [ ] Task 5.3: 配置 CI/CD 流水线
命令 6:/speckit.implement - 实现代码
作用:AI 根据任务列表逐个生成代码实现。
示例:
go
# Task 3.1: 实现密码哈希服务
# src/services/password_service.py
import bcrypt
from typing import str
class PasswordService:
@staticmethod
def hash_password(password: str) -> str:
"""使用 bcrypt 哈希密码"""
salt = bcrypt.gensalt(rounds=12)
return bcrypt.hashpw(password.encode('utf-8'), salt).decode('utf-8')
@staticmethod
def verify_password(password: str, hashed: str) -> bool:
"""验证密码"""
return bcrypt.checkpw(password.encode('utf-8'), hashed.encode('utf-8'))
命令 7:/speckit.test - 运行测试
作用 :SpecKit 独有的 TDD 支持,自动生成测试代码并验证实现。
特点:
-
✅ 内置测试框架
-
✅ 自动生成测试用例
-
✅ 强制测试驱动开发(TDD)
2.3 SpecKit 安装与使用
环境要求
go
- Python ≥ 3.11
- uv 包管理器
- Linux / macOS / Windows WSL2
安装步骤
go
# 1. 安装 uv 包管理器
curl -LsSf https://astral.sh/uv/install.sh | sh
# 2. 安装 SpecKit
uv tool install specify-cli --from git+https://github.com/github/spec-kit
# 3. 验证安装
specify --help
# 4. 初始化项目
specify init
快速开始
go
# 创建新项目
mkdir my-sdd-project
cd my-sdd-project
specify init
# 按照工作流执行
/speckit.constitution # 创建项目准则
/speckit.specify # 描述需求
/speckit.clarify # 澄清需求(可选)
/speckit.plan # 生成实现计划
/speckit.tasks # 生成任务列表
/speckit.implement # 实现代码
/speckit.test # 运行测试
2.4 SpecKit 最佳实践
DO(应该做的):
go
✓ 严格按照 7 个命令的顺序执行
✓ 在 `/speckit.specify` 阶段尽可能详细地描述需求
✓ 重视 `/speckit.clarify` 阶段,回答 AI 的所有问题
✓ 每个任务完成后运行 `/speckit.test` 验证
✓ 将规范文档纳入版本控制
DON'T(不应该做的):
go
✗ 跳过 `/speckit.clarify` 阶段
✗ 在 `/speckit.specify` 阶段就开始写代码
✗ 忽略测试直接进入实现
✗ 规范文档不同步代码变更
✗ 使用 SpecKit 维护遗留代码(应使用 OpenSpec)
🚀 三、Fission-AI OpenSpec:轻量级的 SDD 框架
3.1 什么是 OpenSpec?
定义:OpenSpec 是由 Fission-AI 团队开发的轻量级、便携式规范驱动开发框架,专为 AI 编程助手设计。
官方资源:
-
GitHub: github.com/Fission-AI/OpenSpec
-
官网: openspec.dev
核心特点:
-
✅ 轻量级便携(单个 npm 包)
-
✅ 无需 API 密钥
-
✅ 适合现有项目(Brownfield)
-
✅ 活文档架构(每次变更自动归档)
-
✅ 与 Claude Code、Cursor、Codex 等深度集成
3.2 OpenSpec vs SpecKit
| 维度 | SpecKit | OpenSpec |
|---|---|---|
| 开发团队 | GitHub 官方 | Fission-AI |
| 适用场景 | 从零开始的新项目 | 现有项目的增量开发 |
| 结构化程度 | 高(7个标准命令) | 中(3个核心命令) |
| TDD 支持 | ✅ 内置强制 TDD | ❌ 需自行配置 |
| 安装复杂度 | 中(需要 Python + uv) | 低(npm 全局安装) |
| 文档风格 | 结构化规范文件 | 提案(Proposal)Markdown |
| 学习曲线 | 较陡 | 较平缓 |
3.3 OpenSpec 的三个核心命令
命令 1:openspec proposal - 创建变更提案
作用:为 AI 创建结构化的 Markdown 提案文档,描述要实现的变更。
示例:
go
# 创建提案
openspec proposal
# AI 会生成以下结构:
go
# Proposal: 添加用户认证功能
## 提案概述
本提案旨在为系统添加基于 JWT 的用户认证功能。
## 项目背景
当前系统没有任何认证机制,所有端点都是公开的。为了保护敏感数据和操作,需要实现用户认证。
## 拟议方案
### 功能需求
1. 用户注册
2. 用户登录
3. 令牌刷新
### 技术栈
- FastAPI
- JWT (PyJWT)
- bcrypt 密码哈希
- PostgreSQL 存储
### 实现约束
- 遵循现有项目架构
- 不破坏现有 API
- 向后兼容
## 预期成果
- 完整的认证系统
- 单元测试覆盖率 > 80%
- API 文档更新
## 时间估算
- 开发时间: 6 小时
- 测试时间: 2 小时
命令 2:openspec apply - 应用提案
作用:AI 根据提案文档生成代码实现。
示例:
go
# 应用提案
openspec apply
# AI 会:
# 1. 分析提案文档
# 2. 生成实现代码
# 3. 生成测试代码
# 4. 更新文档
命令 3:openspec archive - 归档变更
作用:将已完成的变更归档到"活文档"中,保持文档与代码同步。
示例:
go
# 归档变更
openspec archive
# 效果:
# - 将 proposal 移动到 docs/archive/ 目录
# - 更新 CHANGELOG.md
# - 生成变更总结
3.4 OpenSpec 工作流程
go
┌─────────────────────────────────────────────────────────────────┐
│ OpenSpec 工作流 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 【创建提案】openspec proposal │
│ └─ 生成 proposal.md 文档 │
│ │
│ 2. 【审核提案】人工审查提案 │
│ └─ 确认需求、技术方案、时间估算 │
│ │
│ 3. 【应用提案】openspec apply │
│ └─ AI 生成代码 + 测试 │
│ │
│ 4. 【验证实现】人工测试 + CI/CD │
│ └─ 确保符合提案要求 │
│ │
│ 5. 【归档变更】openspec archive │
│ └─ 更新活文档,保持可追溯性 │
│ │
└─────────────────────────────────────────────────────────────────┘
3.5 OpenSpec 安装与使用
安装步骤
go
# 1. 全局安装 OpenSpec
npm install -g @fission-ai/openspec@latest
# 2. 验证安装
openspec --help
# 3. 初始化项目(在现有项目中)
cd your-existing-project
openspec init
快速开始
go
# 在现有项目中添加新功能
openspec proposal # 创建提案
# (编辑 proposal.md)
openspec apply # 应用提案
# (审查代码、运行测试)
openspec archive # 归档变更
3.6 OpenSpec 的活文档架构
OpenSpec 的独特之处在于其"活文档"(Living Documentation)设计:
go
项目结构:
├── docs/
│ ├── proposal.md # 当前进行中的提案
│ ├── archive/ # 已归档的提案
│ │ ├── 001-add-auth.md
│ │ ├── 002-add-payment.md
│ │ └── ...
│ └── CHANGELOG.md # 自动生成的变更日志
├── src/ # 源代码
└── tests/ # 测试代码
每次归档后:
-
proposal.md被移动到docs/archive/目录 -
CHANGELOG.md自动更新 -
项目的变更历史完整可追溯
📊 四、如何选择:SpecKit vs OpenSpec
4.1 决策树
go
你的项目是?
│
├─ 从零开始的新项目
│ └─ 使用 SpecKit
│ └─ 完整的结构化工作流
│ └─ 内置 TDD 支持
│
└─ 现有项目(需要添加新功能)
└─ 使用 OpenSpec
└─ 轻量级集成
└─ 活文档架构
4.2 详细对比
| 场景 | 推荐工具 | 原因 |
|---|---|---|
| 全新项目 | SpecKit | 完整工作流,从零开始建立规范 |
| 遗留代码 | OpenSpec | 轻量级,不会破坏现有结构 |
| 需要 TDD | SpecKit | 内置测试框架,强制测试驱动 |
| 快速原型 | OpenSpec | 学习曲线低,上手快 |
| 团队协作 | SpecKit | 结构化规范,便于审查 |
| 个人开发 | OpenSpec | 简单灵活,自由度高 |
4.3 组合使用
场景:大型项目,新功能 + 遗留维护
go
# 新模块:使用 SpecKit
mkdir new-payment-system
cd new-payment-system
specify init
# ... SpecKit 工作流
# 遗留模块:使用 OpenSpec
cd legacy-user-system
openspec init
# ... OpenSpec 工作流
🎯 五、SDD 实战案例
5.1 案例:使用 SpecKit 构建 REST API
需求:构建一个简单的图书管理 API
go
# 1. 初始化项目
specify init
# 2. 创建项目准则
/speckit.constitution
生成的 constitution.md:
go
# 图书管理 API 项目准则
## 技术栈
- 语言: Python 3.11
- 框架: FastAPI
- 数据库: SQLite(开发)/ PostgreSQL(生产)
- ORM: SQLAlchemy
- 测试: pytest
## 代码规范
- 遵循 PEP 8
- 所有函数必须有类型注解
- API 文档使用 OpenAPI 规范
## 架构原则
- 分层架构: Router → Service → Repository
- 依赖注入
- 统一错误处理
go
# 3. 描述需求
/speckit.specify
生成的 specification.md:
go
# 图书管理 API 需求规范
## 功能概述
实现一个 RESTful API,支持图书的增删改查操作。
## 功能需求
### 1. 创建图书
- 端点: POST /api/v1/books
- 输入: title, author, isbn, publication_year
- 输出: 图书 ID + 完整图书信息
- 验证:
- title: 必填,1-200 字符
- author: 必填,1-100 字符
- isbn: 必填,符合 ISBN-13 格式
- publication_year: 可选,1900-当前年份
### 2. 查询图书
- 端点: GET /api/v1/books/{id}
- 输出: 完整图书信息
- 错误: 404 如果图书不存在
### 3. 更新图书
- 端点: PATCH /api/v1/books/{id}
- 输入: 部分图书字段
- 输出: 更新后的图书信息
### 4. 删除图书
- 端点: DELETE /api/v1/books/{id}
- 输出: 204 No Content
### 5. 列出所有图书
- 端点: GET /api/v1/books
- 查询参数: page, page_size, author
- 输出: 图书列表 + 分页信息
## 非功能需求
- 响应时间: < 100ms (P95)
- 并发: 支持 100 QPS
- 可用性: 99% SLA
go
# 4. 澄清需求
/speckit.clarify
AI 提出的问题:
go
# 澄清问题
1. [ISBN 唯一性] ISBN 是否应该是全局唯一的?
推荐: 是,添加唯一索引
2. [软删除] 删除图书是物理删除还是软删除?
推荐: 物理删除(第一阶段)
3. [分页默认值] 列出图书时,默认 page_size 是多少?
推荐: 20
go
# 5. 生成实现计划
/speckit.plan
# 6. 生成任务列表
/speckit.tasks
# 7. 实现代码
/speckit.implement
# 8. 运行测试
/speckit.test
5.2 案例:使用 OpenSpec 为现有项目添加功能
场景:为一个现有的 Django 项目添加导出 PDF 功能
go
cd existing-django-project
openspec init
# 1. 创建提案
openspec proposal
生成的 proposal.md:
go
# Proposal: 添加 PDF 导出功能
## 提案概述
为图书管理页面添加 PDF 导出功能,允许用户导出图书列表为 PDF 文件。
## 项目背景
当前用户只能在线查看图书列表,没有离线分享或存档的能力。
## 拟议方案
### 功能需求
1. 在图书列表页添加"导出 PDF"按钮
2. 支持导出当前筛选结果
3. PDF 包含图书封面、标题、作者、ISBN
4. 支持 A4 和 Letter 纸张大小
### 技术方案
- 使用 reportlab 生成 PDF
- 前端添加导出按钮(不破坏现有 UI)
- 后端新增 /api/v1/books/export/pdf 端点
### 实现约束
- 不修改现有数据模型
- 不影响现有功能
- 向后兼容
## 预期成果
- 完整的 PDF 导出功能
- 单元测试
- API 文档更新
## 时间估算
- 开发时间: 3 小时
- 测试时间: 1 小时
go
# 2. 编辑提案(确认细节)
vim proposal.md
# 3. 应用提案
openspec apply
# 4. 审查代码
# 5. 运行测试
pytest
# 6. 归档变更
openspec archive
📝 总结
核心要点
-
SDD(规范驱动开发):在写代码前,先让 AI 和人类对"要构建什么"达成明确的共识
-
SpecKit:GitHub 官方工具,结构化工作流,适合从零开始的新项目,内置 TDD 支持
-
OpenSpec:Fission-AI 开发,轻量级便携,适合现有项目,活文档架构
快速选择
go
项目类型?
├─ 全新项目
│ └─ SpecKit(完整工作流 + TDD)
└─ 现有项目
└─ OpenSpec(轻量级 + 活文档)
设计哲学
| 层面 | SpecKit | OpenSpec |
|---|---|---|
| 核心理念 | 结构化规范 | 提案驱动 |
| 开发模式 | Greenfield(从零开始) | Brownfield(增量开发) |
| 文档风格 | 规范文件 | 提案文档 |
| 质量保证 | 内置 TDD | 人工审查 |