GitHub Spec Kit 实战(二):写一份不偏的 /speckit.specify
上一篇文章(《GitHub Spec Kit:让规格成为可执行的代码》)我们跑通了完整流程。但跑通不等于写好——/speckit.specify 这一步最容易翻车。
我前前后后写了 20 多份 spec,翻车翻到麻木。最常见的偏,不是写得不够详细,而是从第一句就写错了:
- 第一句就在讲 React、SQLite、PostgreSQL
- 需求里塞了一堆"也许用户还需要 XX 功能"
- 验收标准全是"系统响应时间 < 200ms"这种程序员视角
- 没写 [NEEDS CLARIFICATION],AI 替你猜,猜错了一行行回滚
这篇文章把 /speckit.specify 的所有坑拆开讲清楚。看完你应该能写出一份 AI 不需要反复返工的 spec。
一句话原则:写什么,不写什么
/speckit.specify 命令的源码在仓库 templates/commands/specify.md,里面有句反复出现的话:
Focus on WHAT users need and WHY.
Avoid HOW to implement (no tech stack, APIs, code structure).
Written for business stakeholders, not developers.
翻译成中文:写用户要什么和为什么,别写怎么实现。
这不是说说而已。AI 拿到你的 spec 后会逐字读,里面出现"React"它就用 React,出现"PostgreSQL"它就上 PostgreSQL。你只想做个相册管理,AI 顺手给你整一套云存储抽象——那是你的 spec 喂的,不是 AI 主动加的。
一份合格的 spec 长这样
Spec Kit 的 spec-template.md 强制四节:
| 章节 | 必填 | 写什么 |
|---|---|---|
| User Scenarios & Testing | 是 | 3-5 个按优先级排序的用户故事,每个能独立交付 |
| Requirements | 是 | FR-001/002/…,每条可测试 |
| Success Criteria | 是 | SC-001/002/…,业务视角、可验证、技术无关 |
| Assumptions | 是 | 你替用户做的合理默认 |
| Key Entities | 涉及数据时 | 业务实体的定义和关系 |
注意一个细节:不适用的章节直接删掉,不要留"N/A"。模板的注释里专门写了。
User Scenarios:按 P1/P2/P3 排的故事
这是 spec 里最值钱的一节。Spec Kit 的 spec-template.md 对 User Story 有三条硬要求:
Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them, you should still have a viable MVP
意思是:P1 单独做完,就是一个能跑的产品。P2、P3 是迭代加分项。这样设计的好处是——AI 拿到 spec,先做 P1,能跑通;做 P2,再增量;做 P3,再叠加。不会一上来铺大而全的架构。
我用上一篇文章的相册例子重写一遍(按 Spec Kit 模板的口径):
### User Story 1 - 按日期自动建相册 (Priority: P1)
我上传一张照片,系统自动按拍摄日期归到对应相册里。
**Why this priority**: 这是 MVP 的核心——没有这一步,整个产品价值为零。
**Independent Test**: 上传 5 张不同日期的照片,验证 5 个相册自动出现。
**Acceptance Scenarios**:
1. **Given** 我没建过相册,**When** 我上传一张拍摄于 2024-03-15 的照片,
**Then** 系统自动建一个"2024 年 3 月"相册并把这张照片放进去。
2. **Given** 已有"2024 年 3 月"相册,**When** 我上传同一月的另一张照片,
**Then** 这张照片被加进已有相册,不新建。
Why this priority 和 Independent Test 是模板里强制要求的两段,别省。前者让 AI 知道排序逻辑,后者让 AI 知道做完这条该验收什么。
Requirements:每条都能塞进测试用例
spec-template.md 给的格式是 FR-001 / FR-002 / … 编号列表,每条写 System MUST ... 或 Users MUST be able to ...。注意几个细节:
### Functional Requirements
- **FR-001**: 系统 MUST 保留照片原始 EXIF 信息中的拍摄日期,作为自动分组的依据。
- **FR-002**: 系统 MUST 按"年-月"粒度自动创建相册,不支持自定义分组粒度(v1)。
- **FR-003**: 系统 MUST 在相册内按拍摄时间倒序显示照片。
- **FR-004**: 用户 MUST 能在主页面拖拽照片到不同相册重新分组。
- **FR-005**: 相册 MUST 不支持嵌套——相册里没有子相册。
- **FR-006**: 系统 MUST [NEEDS CLARIFICATION: 单用户还是多用户?多用户的话相册隔离规则?]
几条死规则:
-
每条独立可测——
FR-001不能写成"系统处理照片正确"。要写"系统保留 EXIF 拍摄日期",验收时一查就知道。 -
明确说"不做"。
FR-002里"不支持自定义分组粒度(v1)“、FR-005里"不支持嵌套”——把你主动砍掉的范围写出来。AI 不会替你加"也许你想要 XX 功能",但也不会替你砍。你不写它就猜。 -
[NEEDS CLARIFICATION]标记不能超过 3 个。specify.md源码里明文规定:LIMIT: Maximum 3 [NEEDS CLARIFICATION] markers total
Prioritize clarifications by impact: scope > security/privacy > user experience > technical details而且优先级顺序也写死了:scope > security/privacy > UX > technical 细节。技术选型怎么选、数据库用什么表——这些不是澄清项,是后面
/speckit.plan的事。
Success Criteria:业务视角的"做完了"
这是 AI 翻车最严重的一节。spec-template.md 里给出了好例子和坏例子的对比:
好的:
- “Users can complete checkout in under 3 minutes”
- “System supports 10,000 concurrent users”
- “95% of searches return results in under 1 second”
- “Task completion rate improves by 40%”
坏的(直接抄模板的):
- “API response time is under 200ms” —— 太技术,应该写"用户提交后立刻看到结果"
- “Database can handle 1000 TPS” —— 实现细节,应该写用户侧指标
- “React components render efficiently” —— 框架相关
- “Redis cache hit rate above 80%” —— 技术栈相关
判断标准很简单:一个完全不懂技术的 PM,能拿这条 SC 去验吗? 能→好;不能→改。
Spec Kit 模板给出的四条死规则:
- Measurable:带具体数字(时间、百分比、计数、速率)
- Technology-agnostic:不提框架、语言、数据库、工具
- User-focused:从用户/业务视角描述,不是系统内部
- Verifiable:可测试、可验证,不依赖实现细节
相册例子的 SC:
### Measurable Outcomes
- **SC-001**: 用户上传 100 张不同日期的照片,从上传到全部归入对应相册,时间不超过 30 秒。
- **SC-002**: 用户在 5000 张照片的库中,找到任意一张照片的时间不超过 5 秒。
- **SC-003**: 95% 的首次用户,在 2 分钟内完成首次上传+查看自动归类结果的全流程。
- **SC-004**: 用户拖拽照片重分组的操作,平均 1.5 秒内系统反馈完成。
每条都能拿到用户面前直接验。
Assumptions:你替用户做的默认
这节容易被忽略,但它救命。模板要求把所有"spec 里没说但你做了合理默认"的决定写下来:
## Assumptions
- 目标用户为个人消费者(不是企业团队),不需要多用户权限隔离
- v1 仅支持 JPG/PNG 格式,HEIC/RAW 在 v2 考虑
- 移动端响应式支持(自适应布局),但不做原生 App
- 数据存储在用户本地优先,云同步在 v2 考虑
- 现有项目用 SQLite 做本地存储(这个算"现状",不是 spec 决定)
注意最后一条:Assumptions 写默认行为,不写实现选型。“用 SQLite"这条其实不该写——它属于 plan 阶段。你可以在 Assumptions 里写"假定本地有持久化存储能力”,至于用 SQLite 还是文件系统,那是 plan 的事。
Key Entities:涉及数据才填
spec-template.md 注释里写明 “include if feature involves data”。相册例子需要:
### Key Entities
- **Photo**: 一张照片,含原始 EXIF 信息中的拍摄日期、文件大小、格式;属于一个且仅一个 Album。
- **Album**: 一个相册,标识为"年-月"格式的标题(如"2024 年 3 月");包含 0 个或多个 Photo;相册之间无层级。
- **User**: 一个用户,拥有 0 个或多个 Album。
只有"是什么"和"什么关系",没有"用什么字段、什么类型、什么索引"。后者是 plan。
写完后:3 轮自检
specify 命令会自动生成一份 checklists/requirements.md 做质量检查。但你写完就该自己过一遍——下面是 Spec Kit 内置检查项的人工版:
Content Quality
- 全文搜 React/Vue/Spring/MySQL/Redis/Django/PostgreSQL/Redis/Kafka/任何技术栈名字——命中就改
- 全文搜
should/最好/考虑——这些是软词,spec 要的是 MUST - 每段是否聚焦用户价值?不是就在往实现细节滑
Requirement Completeness
-
[NEEDS CLARIFICATION]不超过 3 个 - 每条 FR 都能直接写成一个测试用例
- 每条 SC 都符合"PM 能拿去做验收"标准
- 边界条件在 Edge Cases 里写出来(断网、文件超大、日期缺失等)
Feature Readiness
- P1 单独做完能跑通吗?
- 没写的"不做"明确说出来了吗?
- Assumptions 写完整了吗?
一个反例:从合格到翻车只要一句话
给你看个真实场景——用户最初的需求写的是:
我想做一个照片管理应用,前端用 React Native,后端用 Python FastAPI,数据存 PostgreSQL,支持 AI 自动打标签……
这一段从第一句就坏了。技术栈占了 80%,AI 会按这些字面信息去搭项目,结果不是你想要的。
改写后:
做一个照片管理应用。用户上传照片后,系统按拍摄日期自动归入对应相册;用户可在主页面拖拽照片重新分组。MVP 阶段(v1)只支持单用户本地使用。
然后按 Spec Kit 模板写四节。/speckit.specify 一跑出来的 spec.md,没有任何一个技术选型词。等 /speckit.plan 阶段,AI 会根据 spec + 你的 codebase 上下文自己选型——这才是 Spec Kit 想让你做的事。
写完就准备进 plan 阶段
specify 命令会在 checklists/requirements.md 里给出三项结论之一:
- All items pass → 直接进
/speckit.plan - 有 [NEEDS CLARIFICATION] → 命令会自动生成澄清问题给你(最多 3 个,每个带 A/B/C 建议答案),你答完它再更新 spec
- 其他项失败 → 命令会自检 3 轮修复,第 3 轮还修不好就标红让你人工处理
把澄清问题答好,spec 就稳了。下一篇会讲 /speckit.constitution 怎么写——那是 spec 之前的"项目宪法",决定了所有 spec 都要遵守的硬约束。
3176

被折叠的 条评论
为什么被折叠?



