| name | spec |
| description | Spec-Driven Development (SDD) 工作流——在改动代码前先生成一份中文设计文档(spec) 并与用户确认。**必须触发**的场景:用户提出新增功能/加一个按钮/页面/接口/字段/能力、refactor/重构、修复非平凡 bug、优化、做一个 X、涉及 2 个及以上文件的多步改动、提到「设计/方案/规划/先想清楚」。即使没说「写 spec」,只要改动不是纯 typo、文档润色、依赖升级、版本号、单行修复,都应触发。关键词(中):新功能、新增、加、实现、重构、修复、优化、改造、调整;关键词(英):feature、refactor、fix、optimize、redesign、rework、add、implement。 |
Spec-Driven Development (SDD) 工作流
为什么需要这个 skill
直接跳进代码改会让用户失去决策点。Spec 的本质是把决策从隐式变成显式——
让用户在动代码之前,先看到「我们要解决什么问题、怎么解决、改哪些文件、
验收标准是什么」,然后点头或调整。
写 spec 不是为了仪式感,而是为了:
- 让改动可评审、可追溯(spec 文件就是历史决策记录)
- 在写代码之前发现方案缺陷,比写完发现便宜得多
- 给未来的自己/同事/AI 一个上下文,看 git log 不用猜
- 让多会话 AI 协作更稳定——下次会话能从 spec 重建上下文
触发判定
触发(满足任一):
- 新增用户可见的能力(按钮、页面、API、配置项、字段、快捷键)
- 重构现有代码(移动文件、抽函数、改架构、调整数据流、换库)
- 修复非平凡 bug(需要分析根因、影响多文件、可能改变边界行为)
- 任何涉及 2 个及以上文件的改动
- 用户提到「设计 / 方案 / 规划 / 先想清楚 / 怎么做」等暗示
不触发:
- 单文件 typo / 文案修正
- 依赖升级、版本号变更
- 纯文档/注释更新
- 单行 lint 修复
- 用户明确说「先随便写一下 / 不用 spec / 快速 prototype」
边界模糊时,默认触发——写一份薄 spec 比跳过 spec 便宜。
工作流(触发后必做)
第 0 步:确保 specs 框架存在
第一次在本项目触发 spec skill 时,specs/ 目录可能还没建。先检查、缺什么补什么,再进入第 1 步。
检查(用 Glob 模式 specs/** 或 Bash ls specs/):
specs/ 目录存在
specs/features/、specs/refactors/、specs/bugfixes/ 三个 bucket 都存在
specs/README.md 存在
bootstrap 动作(缺什么做什么,全有就跳过本步骤):
| 缺什么 | 做什么 |
|---|
specs/ 或某个 bucket 目录 | 创建缺失的目录;每个 bucket 加 .gitkeep 占位(空目录才能进 git) |
specs/README.md | 从 .claude/skills/spec/assets/spec-readme.md 复制到 specs/README.md |
复制 README 后必须做一次项目适配:
- 通读 README,找到
<!-- TODO --> 标注的位置
- 看
package.json 的 scripts 字段(或 Makefile / Cargo.toml / pyproject.toml 等本项目实际用的构建配置)
- 把模板里的 lint / test 命令占位符替换成项目实际命令
- 在回复里简短告诉用户:「我建好了 specs/ 框架,README 已根据本项目工具链调整,请快速过一眼」
注意:bootstrap 完成后直接进入第 1 步分类——不要为 bootstrap 单独暂停。用户注意力应集中在即将写的 spec 内容上。
第 1 步:分类与命名
判断本次改动属于哪一类:
| 类别 | 目录 | 判定 |
|---|
| feature | specs/features/ | 新增用户可感知的能力 |
| refactor | specs/refactors/ | 不改外部行为的内部改造 |
| bugfix | specs/bugfixes/ | 修复已有功能异常 |
选一个 kebab-case 主题名,简短、描述性。例如:
cowork-session-persistence
go-backend-graceful-shutdown
react-window-resize-fix
如果改动跨多个主题,拆成多个 spec,不要一份 spec 包揽。
第 2 步:创建 spec 文件
路径模板:
specs/<bucket>/<topic>/<YYYY-MM-DD>-<topic>-design.md
<YYYY-MM-DD> 用今天日期(不要用 commit 日期)
- 同一主题迭代时,新建带新日期的文件,不要改旧文件——旧版作为历史保留
- 框架不存在的场景已在第 0 步处理,这里默认
specs/<bucket>/ 已就绪
如果 <topic>/ 目录已存在旧版 spec:
- 阅读旧版,新版本应基于旧版的现状
- 在新版「概述」里说明本次迭代相对旧版改了什么
第 3 步:填充模板(中文)
完整模板(章节可按内容增减,但「概述」「验收标准」必须有):
# <主题>设计文档
## 1. 概述
### 1.1 问题 / 背景
<!-- 为什么要做这件事?现状哪里不够好?引用具体的用户反馈、报错日志、性能数据 -->
### 1.2 目标
<!-- 做完之后,世界应该变成什么样。用 1-3 句话讲清楚 -->
### 1.3 非目标(可选)
<!-- 明确不做什么,防止范围蔓延 -->
## 2. 用户场景
### 场景 1: <场景标题>
**Given** 初始状态...
**When** 用户/系统做了某动作...
**Then** 预期结果...
### 场景 2: ...
## 3. 功能需求
### FR-1: <需求标题>
<具体要求>
### FR-2: ...
## 4. 实现方案
### 4.1 <模块 / 步骤>
<!-- 关键设计决策、伪代码、接口签名、数据结构 -->
### 4.2 <...>
## 5. 边界情况
| 场景 | 处理方式 |
|------|---------|
| 用户中断操作 | ... |
| 网络断开 | ... |
| 跨平台差异(Win/Mac/Linux) | ... |
## 6. 涉及文件
| 文件 | 变更说明 |
|------|---------|
| `src/main/xxx.ts` | 新增 YYY 函数 |
| `frontend/src/...` | 修改 ZZZ 组件 |
## 7. 验收标准
- [ ] 场景 1 的 Given/When/Then 通过
- [ ] 通过 oxlint + prettier
- [ ] 通过 `npm test`
- [ ] 通过 `npm run test:go`(如涉及后端)
- [ ] 通过手动验证:...
填充原则:
- 模板是参考,不是八股——「非目标」「场景 2」没东西就删掉
- 每个章节都应有实际内容,不要为了凑章节写空话
- 「实现方案」要具体到接口签名、数据结构、关键决策的理由,不要只写「会实现 X 功能」
- 「涉及文件」要列出真实路径,哪怕是预测的
第 4 步:暂停,等用户确认
在写任何业务代码之前,把 spec 内容展示给用户,明确询问:
「这份 spec 看起来对吗?需要调整哪里?确认无误后我开始实现。」
如果用户要求改动,改 spec,再确认。不要在脑子里改了之后跳过这一步。
只有用户明确说「OK / 开始 / 确认 / go」之类,才能进入第 5 步。
第 5 步:按 spec 实现
- 按「涉及文件」清单逐项实施
- 遵守项目
AGENTS.md(lint / i18n / 共享常量 / commit 规范)
- 实现过程中如发现 spec 有遗漏或错误,回头更新 spec,不要只在代码里隐式处理
第 6 步:对照验收标准自检
实现完成后:
- 逐项跑 spec 里「验收标准」的 checklist
- 跑
npm run check(lint + format + test + test:go)
- 在最终回复里贴出:
- 实际修改的文件列表
- 验收标准通过情况
- 任何与 spec 偏离的地方(以及为什么)
Spec 之外
- 简单文档改动不需要 spec
- 实验性代码、POC 不需要 spec,但变成正式代码时要补
- spec 不是 PR description——PR description 简短指向 spec 即可
参考路径
specs/README.md(如存在):目录/命名规则的权威说明
AGENTS.md(项目根):代码层面的规范
.github/PULL_REQUEST_TEMPLATE.md(如存在):PR 模板