CodeBuddy 学习(5):Speckit 规约驱动开发
先分享一个核心观察:在AI编程工具日益普及的今天,很多开发者仍然在用“碰运气”的方式和AI协作——同一个需求,今天和明天让AI做,结果可能完全不同。这并不是AI的问题,而是我们缺少和AI沟通的“契约”。
一、概述:为什么需要 Speckit
1.1 传统 AI 编程的三大痛点
| 痛点 | 你的经历 | Speckit 如何解决 |
|---|---|---|
| 需求脱节 | 你说做 A,AI 写成了 B,边界条件全漏 | 先写规约再执行,规约就是契约 |
| 风格混乱 | 你和同事的提示词不同,产出像拼凑的 | 统一流程 + 文档模板 |
| 不可复现 | 同一个需求今明两天给 AI,结果不同 | 规约 + 七步闭环,质量可保障 |
如果你也经历过这些场景,那 Speckit 这套方法值得认真看看。
1.2 Speckit 的本质
Speckit 是 GitHub 推出的规约驱动开发工具。它的核心思想可以用一句话概括:

这意味着什么?调试时你修改的是规约文档,而不是直接改代码;重构时你重构的也是规约文档,AI 自动帮你重新生成代码。规约就是你与 AI 之间的桥梁——或者说,是必须遵守的“合同”。
1.3 环境准备
# 方式一:持久化安装(推荐)
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
二、核心概念:三个支柱
2.1 规约驱动(Spec-Driven)
传统开发和规约驱动开发的区别,核心在于“起点”和“维护对象”的变化:
| 维度 | 传统开发 | Speckit 规约驱动 |
|---|---|---|
| 起点 | 直接写代码 | 先定义做什么 / 不能做什么 / 验收标准 |
| 维护 | 维护代码 | 维护规约 → 代码自动重新生成 |
| 调试 | 逐行排查代码 | 修规约 → 重新生成 |
| 重构 | 手动改代码 | 重构规约 → 重新生成 |
简单来说,规约才是“源码”,代码只是它的编译产物。
2.2 项目宪法(Constitution)
“宪法”是给 AI 画的边界——定义了无论如何都不能违背的原则:
| 宪法定义什么 | Todo App 示例 |
|---|---|
| 数据策略 | 纯前端 LocalStorage,不连云端 |
| 技术规范 | React + TypeScript,不用蓝紫渐变 |
| 质量底线 | Lint / Format / 基础测试必须通过 |
2.3 七步闭环
Constitution → Specify → Clarify → Plan → Tasks → Analyze → Implement
(宪法) (规约) (澄清) (方案) (拆解) (检查) (执行)
三、完整实战:Todo App 七步全流程
Step 1:Constitution(项目宪法)
原理
宪法是整个规约体系的根基。它在所有规约之前建立,定义了项目不可协商的边界。后续的所有规约、方案、实现都在宪法划定的范围内进行——这是一个“先定规矩,再谈执行”的思路。
操作
你输入:
/speckit.constitution
这是一个任务清单管理系统,要求:
- 中文界面,清新简洁风格
- 纯前端,数据用 LocalStorage 持久化
- 不使用蓝紫渐变
- 必须有 Lint/Format 检查,基础测试必须通过
AI 输出(constitution.md 摘要):
# 项目宪法
## 不可协商原则
1. 数据策略:仅使用 LocalStorage,不连接任何云服务
2. 设计规范:中文界面,清新风格,禁用蓝紫渐变
3. 质量门槛:ESLint 零错误,Prettier 格式化,至少一个基础测试套件通过
## 技术栈
- React 18 + TypeScript 5
- TailwindCSS(清新色系)
- Vitest(测试)
Step 2:Specify(写规约——只谈 WHAT)
原理
Specify 阶段只描述做什么,不讨论怎么做。这是一个严格的分界线——如果你在规约里写了“用 useState 管理状态”,那就提前进入了实现细节。这种做法会限制 AI 在方案选择上的自由度,反而可能错过更优解。
操作
你输入:
/speckit.specify
实现一个任务清单应用,功能包括:
1. 新增任务(标题 + 描述)
2. 删除任务(确认弹窗)
3. 标记完成 / 取消完成(带动画)
4. 状态筛选(全部 / 未完成 / 已完成)
5. LocalStorage 持久化
AI 输出(spec.md 摘要):
# 产品规约:Todo App
## 功能列表
| ID | 功能 | 验收标准 ||----|------|---------|
| F1 | 新增任务 | 标题(必填)+描述(可选),列表立即更新 |
| F2 | 删除任务 | 确认弹窗 → 确认后从列表移除 |
| F3 | 标记完成/取消 | 点击切换状态,带过渡动画 |
| F4 | 状态筛选 | 三个标签:全部/未完成/已完成 |
| F5 | 数据持久化 | 刷新页面后数据仍在 |
Step 3:Clarify(需求澄清)
原理
Specify 写完后,AI 并不会立即进入方案设计——它会先反过来向你提问。这一步的目的是消除需求中的歧义。因为人类写需求时,总会不自觉地省略很多“显然”的信息(但 AI 不觉得显然)。
操作
AI 提问:
Q1: 任务标题有字数限制吗?
Q2: 已完成的任务能否重新编辑?
Q3: 删除确认弹窗用什么样式?
Q4: 完成切换动画具体是什么效果?
Q5: 筛选后切换标签,已输入的筛选条件是否保留?
你回答:
标题最多 100 字。已完成的任务不能重新编辑(只读展示)。居中弹窗,确认/取消两个按钮。删除线 + 变灰,过渡时间 0.3s。切换标签时保留筛选条件。
这一步的关键在于:不要嫌问题啰嗦,AI 问得越细,后期返工越少。
Step 4:Plan(技术方案)
原理
Plan 阶段是规约到代码之间的桥梁——将 WHAT 翻译为 HOW。AI 会输出数据模型、API 签名、组件树、文件组织等具体的技术决策。
操作
AI 自动输出(plan.md 摘要):
# 技术方案
## 技术栈
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[]
- sa veTodos(todos: Todo[]): void
## 组件树
App
├── TodoHeader(标题 + 新增按钮)
├── TodoInput(输入框 + 添加按钮,条件渲染)
├── TodoFilter(全部/未完成/已完成 标签)
└── TodoList
└── TodoItem(单条任务:勾选框 + 文字 + 删除按钮)
## 状态管理
useTodos Hook 封装全部状态逻辑:
- todos, filter, addTodo, deleteTodo, toggleTodo
看到这里,你应该能感受到:plan 阶段比直接写代码要轻松得多——你只需要评审,不用手写每一行。
Step 5:Tasks(任务拆解)
## 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 输出:
=== 一致性分析报告 ===
✅ spec ↔ plan 一致性:通过
⚠️ 发现 1 个歧义:ConfirmModal 组件未在 plan 中列出 → 已自动补全
⚠️ 发现 1 个欠指定:T3.2 缺少验收条件 → 建议补充
这个步骤的价值在于:不用等到代码写完了才发现不对。
Step 7:Implement(落地执行)
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
现象:跑到 Step 5 才发现漏了一个功能(如"任务排序")。
原因:Step 2 写规约时没有想全所有功能。
修复:
1. 回到 Step 2,在 spec.md 中补充遗漏功能。
2. 重新运行 Step 3(Clarify)→ Step 4(Plan)→ Step 5(Tasks)。
3. 不要直接在代码里打补丁——否则规约和代码会脱节。
4.2 Analyze 发现冲突 → 修改文档
现象:Analyze 报告 spec 和 plan 不一致。例如:spec 要求"支持批量删除",但 plan 中没有对应的组件和 Hook。
原因:Plan 阶段遗漏了 spec 中的需求项。
修复:
1. 打开 plan.md,补充批量删除的设计。
2. 重新运行 Analyze 确认一致。
原则:修文档,不修代码。文档修对了,代码重新生成就对了。
4.3 Implement 中途卡住 → --continue
现象:执行 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):
缺陷:点击删除按钮,确认弹窗消失后,任务仍在列表中。
期望:确认弹窗点击"确认"后,任务从列表移除,LocalStorage 同步更新。
Step 3(plan 根因分析):
根因:deleteTodo 函数中将 id 参数错误地传给了 splice(传的是 index 而非找到的索引)。
修复方案:修正 deleteTodo 中使用 findIndex + splice 的逻辑。
这个流程的关键在于:从问题描述到根因分析到修复方案,每一步都有文档记录,不会出现“改完就忘”的情况。
调试过程
场景:修复引入了新的 Bug
现象:修复了一个 Bug,但跑测试时发现另一个功能坏了。
原因:修复逻辑影响了其他代码路径(典型的副作用)。
排查:
1. 在 plan 的根因分析中,是否分析了所有调用方?
2. 修复是否只针对最小范围,还是"顺手"改了其他逻辑?
修复:
1. 回到 Step 3(Plan):重新做根因分析,列出所有受影响的范围。
2. 更新 tasks,确保修复只针对最小范围。
3. 加入回归测试用例。
六、小结
回顾一下,Speckit 的核心逻辑其实可以用几句话总结:
- 有话说不清?→
/specify写下来 - AI 理解偏了?→
/clarify对清楚 - 方案不满意?→
/plan改方案(不是改代码!) - 步骤不对?→
/analyze查矛盾 - 代码跑不通?→ 修 spec/plan/tasks,重新
/implement
最核心的理念是:维护软件就是维护规约,代码只是规约的输出。这句话值得反复体会——它改变了我们和 AI 协作的方式。
