CodeBuddy 学习(5):Speckit 规约驱动开发
一、概述:为什么需要 Speckit
1.1 传统 AI 编程的三大痛点
| 痛点 | 你有过的经历 | Speckit 如何解决 |
|---|---|---|
| 需求脱节 | 你说做 A,AI 写成了 B,边界条件全漏 | 先写规约再执行,规约就是契约 |
| 风格混乱 | 你和同事的提示词不同,产出像拼凑的 | 统一流程 + 文档模板 |
| 不可复现 | 同一个需求今明两天给 AI,结果不同 | 规约 + 七步闭环,质量可保障 |
1.2 Speckit 的本质
Speckit 是 GitHub 推出的规约驱动开发工具。它的核心思想是:
先写规约,再按规约执行。维护软件 = 维护规约,代码只是规约的输出物。
这意味着:调试时你修改的是规约文档,而不是直接改代码;重构时你重构的是规约文档,AI 帮你重新生成代码。规约就是你与 AI 之间的契约。
1.3 环境准备
bash
# 方式一:持久化安装(推荐)
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git
# 方式二:一次性使用
uvx --from git+https://github.com/github/spec-kit.git specify init todo-app
# 初始化项目
specify init todo-app
cd todo-app
uv是 Python 的快速包管理器。如果尚未安装: macOS/Linux:curl -LsSf https://astral.sh/uv/install.sh | shWindows:powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
二、核心概念:三个支柱
2.1 规约驱动(Spec-Driven)
| 维度 | 传统开发 | Speckit 规约驱动 |
|---|---|---|
| 起点 | 直接写代码 | 先定义做什么 / 不能做什么 / 验收标准 |
| 维护 | 维护代码 | 维护规约 → 代码自动重新生成 |
| 调试 | 逐行排查代码 | 修规约 → 重新生成 |
| 重构 | 手动改代码 | 重构规约 → 重新生成 |
2.2 项目宪法(Constitution)
"宪法"是给 AI 画一个它不能出去的圈------无论如何都不能违背的原则:
| 宪法定义什么 | Todo App 示例 |
|---|---|
| 数据策略 | 纯前端 LocalStorage,不连云端 |
| 技术规范 | React + TypeScript,不用蓝紫渐变 |
| 质量底线 | Lint / Format / 基础测试必须通过 |
2.3 七步闭环
scss
Constitution → Specify → Clarify → Plan → Tasks → Analyze → Implement
(宪法) (规约) (澄清) (方案) (拆解) (检查) (执行)
三、完整实战:Todo App 七步全流程
Step 1:Constitution(项目宪法)
原理
宪法是整个规约体系的根基。它在所有规约之前建立,定义了项目不可协商的边界。此后的所有规约、方案、实现都在宪法划定的范围内进行。
操作
你输入:
diff
/speckit.constitution
这是一个任务清单管理系统,要求:
- 中文界面,清新简洁风格
- 纯前端,数据用 LocalStorage 持久化
- 不使用蓝紫渐变
- 必须有 Lint/Format 检查,基础测试必须通过
AI 输出 (constitution.md 摘要):
markdown
# 项目宪法
## 不可协商原则
1. 数据策略:仅使用 LocalStorage,不连接任何云服务
2. 设计规范:中文界面,清新风格,禁用蓝紫渐变
3. 质量门槛:ESLint 零错误,Prettier 格式化,至少一个基础测试套件通过
## 技术栈
- React 18 + TypeScript 5
- TailwindCSS(清新色系)
- Vitest(测试)
Step 2:Specify(写规约------只谈 WHAT)
原理
Specify 阶段只描述做什么 ,不讨论怎么做。这是一个严格的分界线------如果你在规约里写了"用 useState 管理状态",那就提前进入了实现细节,AI 会失去方案选择的自由度。
操作
你输入:
markdown
/speckit.specify
实现一个任务清单应用,功能包括:
1. 新增任务(标题 + 描述)
2. 删除任务(确认弹窗)
3. 标记完成 / 取消完成(带动画)
4. 状态筛选(全部 / 未完成 / 已完成)
5. LocalStorage 持久化
AI 输出 (spec.md 摘要):
markdown
# 产品规约:Todo App
## 功能列表
| ID | 功能 | 验收标准 |
|----|------|---------|
| F1 | 新增任务 | 标题(必填)+描述(可选),列表立即更新 |
| F2 | 删除任务 | 确认弹窗 → 确认后从列表移除 |
| F3 | 标记完成/取消 | 点击切换状态,带过渡动画 |
| F4 | 状态筛选 | 三个标签:全部/未完成/已完成 |
| F5 | 数据持久化 | 刷新页面后数据仍在 |
Step 3:Clarify(需求澄清)
原理
Specify 写完后,AI 并不会立即进入方案设计------它会先反过来向你提问。这一步的目的是消除需求中的歧义。因为人类写需求时,总会不自觉地省略很多"显然"的信息(但 AI 不觉得显然)。
操作
AI 提问:
makefile
Q1: 任务标题有字数限制吗?
Q2: 已完成的任务能否重新编辑?
Q3: 删除确认弹窗用什么样式?
Q4: 完成切换动画具体是什么效果?
Q5: 筛选后切换标签,已输入的筛选条件是否保留?
你回答:
标题最多 100 字。
已完成的任务不能重新编辑(只读展示)。
居中弹窗,确认/取消两个按钮。
删除线 + 变灰,过渡时间 0.3s。
切换标签时保留筛选条件。
Step 4:Plan(技术方案)
原理
Plan 阶段是规约到代码之间的桥梁------将 WHAT 翻译为 HOW。AI 会输出数据模型、API 签名、组件树、文件组织等具体的技术决策。
操作
AI 自动输出(plan.md 摘要):
markdown
# 技术方案
## 技术栈
React 18 + TypeScript 5 + TailwindCSS + Vitest
## 数据模型
interface Todo {
id: string;
title: string; // 最多 100 字
description?: string;
completed: boolean;
createdAt: string;
updatedAt: string;
}
## LocalStorage 策略
key: 'todos'
读写封装在 storage.ts 工具模块中:
- loadTodos(): Todo[]
- saveTodos(todos: Todo[]): void
## 组件树
App
├── TodoHeader(标题 + 新增按钮)
├── TodoInput(输入框 + 添加按钮,条件渲染)
├── TodoFilter(全部/未完成/已完成 标签)
└── TodoList
└── TodoItem(单条任务:勾选框 + 文字 + 删除按钮)
## 状态管理
useTodos Hook 封装全部状态逻辑:
- todos, filter, addTodo, deleteTodo, toggleTodo
Step 5:Tasks(任务拆解)
markdown
## Phase 1:项目搭建
- [ ] T1.1 初始化 Vite + React + TS 项目
- [ ] T1.2 配置 TailwindCSS、ESLint、Prettier
## Phase 2:核心功能
- [ ] T2.1 定义 Todo 类型和 storage 工具函数
- [ ] T2.2 实现 useTodos Hook
- [ ] T2.3 实现 TodoInput 组件
- [ ] T2.4 实现 TodoItem 组件
- [ ] T2.5 实现 TodoFilter 组件
## Phase 3:组装与持久化
- [ ] T3.1 组装 App 页面
- [ ] T3.2 集成 LocalStorage 持久化
## Phase 4:测试与优化
- [ ] T4.1 编写组件单元测试
- [ ] T4.2 运行 ESLint + Prettier 修复
Step 6:Analyze(一致性检查)
原理
在正式执行之前,AI 会做一次交叉验证:检查 spec(需求规约)和 plan(技术方案)之间是否一致,tasks(任务拆解)是否覆盖了 plan 中的所有产出物。
操作
AI 输出:
diff
=== 一致性分析报告 ===
✅ spec ↔ plan 一致性:通过
⚠️ 发现 1 个歧义:ConfirmModal 组件未在 plan 中列出 → 已自动补全
⚠️ 发现 1 个欠指定:T3.2 缺少验收条件 → 建议补充
Step 7:Implement(落地执行)
go
T1.1 初始化项目 ✓
T1.2 配置工具链 ✓
T2.1 类型 + 工具函数 ✓
T2.2 useTodos Hook ✓
T2.3 TodoInput ✓
T2.4 TodoItem ✓
T2.5 TodoFilter ✓
T3.1 App 组装 ✓
T3.2 持久化 ✓
T4.1 单元测试 → 1 个失败 → AI 自动修复 → 全部通过 ✓
T4.2 ESLint → 0 error ✓
四、调试:七步中常见问题
4.1 Spec 有问题 → 回 Step 2
vbnet
现象:跑到 Step 5 才发现漏了一个功能(如"任务排序")。
原因:Step 2 写规约时没有想全所有功能。
修复:
1. 回到 Step 2,在 spec.md 中补充遗漏功能。
2. 重新运行 Step 3(Clarify)→ Step 4(Plan)→ Step 5(Tasks)。
3. 不要直接在代码里打补丁------否则规约和代码会脱节。
4.2 Analyze 发现冲突 → 修改文档
arduino
现象:Analyze 报告 spec 和 plan 不一致。
例如:spec 要求"支持批量删除",但 plan 中没有对应的组件和 Hook。
原因:Plan 阶段遗漏了 spec 中的需求项。
修复:
1. 打开 plan.md,补充批量删除的设计。
2. 重新运行 Analyze 确认一致。
原则:修文档,不修代码。文档修了对的,代码重新生成就对了。
4.3 Implement 中途卡住 → --continue
markdown
现象:执行 Implement 时某个测试失败了,流程中断。
原因:生成的代码有 Bug,或测试用例写得太严。
修复:
1. AI 会自动尝试修复。
2. 如果手动修改了代码,用 --continue 让 AI 继续执行剩余任务。
3. 如果修复多次仍失败,检查是否是 spec 或 plan 本身有逻辑问题。
五、旧项目 Bug 修复六步闭环
对于已有项目,Speckit 同样适用。以下是 Bug 修复场景的六步流程:
| 步骤 | 命令 | 实际做什么 |
|---|---|---|
| 1 | specify init . |
在当前项目中初始化 Speckit |
| 2 | /speckit.specify |
描述缺陷 + 期望行为 |
| 3 | /speckit.plan |
根因分析,输出修复方案 |
| 4 | /speckit.tasks |
拆解修复步骤(单一职责) |
| 5 | /speckit.implement |
逐个执行修复任务 |
| 6 | npm run dev |
验证修复效果 |
示例:Bug 是"点击删除按钮后,任务没有从列表中移除"。
Step 2(specify):
arduino
缺陷:点击删除按钮,确认弹窗消失后,任务仍在列表中。
期望:确认弹窗点击"确认"后,任务从列表移除,LocalStorage 同步更新。
Step 3(plan 根因分析):
perl
根因:deleteTodo 函数中将 id 参数错误地传给了 splice(传的是 index 而非找到的索引)。
修复方案:修正 deleteTodo 中使用 findIndex + splice 的逻辑。
调试过程
场景:修复引入了新的 Bug
markdown
现象:修复了一个 Bug,但跑测试时发现另一个功能坏了。
原因:修复逻辑影响了其他代码路径(典型的副作用)。
排查:
1. 在 plan 的根因分析中,是否分析了所有调用方?
2. 修复是否只针对最小范围,还是"顺手"改了其他逻辑?
修复:
1. 回到 Step 3(Plan):重新做根因分析,列出所有受影响的范围。
2. 更新 tasks,确保修复只针对最小范围。
3. 加入回归测试用例。
六、小结
bash
有话说不清? → /specify 写下来
AI 理解偏了? → /clarify 对清楚
方案不满意? → /plan 改方案(不是改代码!)
步骤不对? → /analyze 查矛盾
代码跑不通? → 修 spec/plan/tasks,重新 /implement
维护软件 = 维护规约,代码只是规约的输出