2846 字
约 9 分钟
18
S27-X10 · OpenSpec 与 Spec-Kit:规格驱动开发的落地

需求最初总是散落在聊天记录里:「那个导出功能,还要支持按门店筛选,顺便把上次说的权限也带上」。三个月后没人记得当初为什么这么定,AI 助手照着一句模糊描述写了 800 行代码,评审时谁也说不清它是不是符合预期。

规格驱动开发(spec-driven development)想解决的就是这件事:把"要做什么"写成一份人和 AI 都要读的文档,代码是它的实现,而不是反过来。


1. 要解决的问题

症状 现场表现 根因
需求只存在于对话里 换个接手人就要重新问一遍 没有单一的书面来源
AI 按模糊描述乱写 生成的代码"看着像",细节全错 输入信息量不足,模型只能猜
验收无可对照物 评审靠"感觉不对" 没有可逐条核对的条目
变更无人记录 半年后不知道某行为什么在那 决策没有留痕
反复返工 同一需求改五遍还在讨论范围 边界没写下来

这些问题不是"文档写得不够多",而是文档的形态不对:散在 wiki、issue、聊天里,没有强制约束力,也没有和代码建立引用关系。

2. 核心思路

一句话:先写规格,再写代码;规格是需求方、开发、AI 三方的共同输入。

它带来三个可检验的效果:

  1. 输入变确定:AI 拿到的是结构化描述,不是一句话;
  2. 验收可枚举:规格里的每条行为都能对应一个测试或一次手工核对;
  3. 变更可追:改行为必须先改规格,diff 就是变更记录。

3. 这类工具通常包含什么

层次 回答的问题 产物
需求层(spec) 要做什么、边界在哪、验收标准 用户故事 + 场景 + 明确的不做项
设计层(design/plan) 怎么做、有哪些取舍 技术方案、数据模型、接口约定
任务层(tasks) 谁做、按什么顺序做 可勾选的任务清单
约束层(constitution/规范) 全局必须遵守的规则 编码规范、架构约束、评审门槛

目录约定大同小异,形态通常是这样:

specs/
  refund-policy/
    spec.md          # 需求与场景
    design.md        # 技术方案与取舍
    tasks.md         # 任务清单(可勾选)
    changelog.md     # 规格自身的变更记录

一份 spec 的最小可用形态:

# 退款时效说明

## 背景
客服需要向用户解释退款到账时间,当前口径不统一。

## 场景
- 场景 1:用户询问退款时效
  - Given 订单已退款成功
  - When 用户询问"多久到账"
  - Then 回答"3–5 个工作日",并给出订单号
- 场景 2:退款失败
  - Given 退款状态为失败
  - Then 说明失败原因,并提供人工入口

## 不做
- 不承诺具体到账时刻
- 不查询银行侧状态

## 验收
- [ ] 两类场景都能被正确识别
- [ ] 失败场景不返回时效话术

注意"不做"这一节:它比"要做"更值钱,因为大部分返工来自范围蔓延。

4. 与 AI 编程工具的协作命令

这类工具的第二个组成部分是一组命令约定,让 AI 按固定节奏产出文档,而不是直接开始写代码:

阶段 典型命令形态 产出
初始化 init 建立目录与模板
立规 constitution / 规范文件 全局约束
写需求 specify / proposal spec.md
出方案 plan / design design.md
拆任务 tasks tasks.md
实现 implement / 执行 代码 + 勾选任务
归档 archive / validate 校验与收口
# 形态示意:具体子命令与参数按当前工具版本核对
openspec init                     # 在当前仓库建立规格目录
openspec list                     # 看有哪些规格与状态
openspec validate refund-policy   # 校验规格结构是否完整
openspec archive refund-policy    # 已交付的规格归档

命令名不是重点,节奏才是重点:规范 → 需求 → 方案 → 任务 → 实现。跳过中间任何一步,AI 就会回到"按一句话猜"的模式。

任务清单要能被勾选,否则它只是另一份待办清单:

# tasks.md
- [x] 定义退款状态枚举与话术映射
- [ ] 实现两类场景的意图识别
- [ ] 补充失败场景的人工入口链接
- [ ] 加测试:失败场景不得返回时效话术

5. 落地方式

5.1 规格进仓库,和代码同源

规格放在 specs/ 下,跟代码一个仓库、一个 PR 流程。这样"规格与代码是否一致"变成一次 code review 能看见的事,而不是靠人记。

# 变更的正确顺序:先改规格,再改代码
git switch -c feat/refund-eta
$EDITOR specs/refund-policy/spec.md      # 1. 改规格
git commit -m "spec: 补充退款失败场景"
# 2. 让 AI 按新规格出方案与任务
# 3. 实现代码,勾选 tasks.md
git commit -m "feat: 退款失败场景话术"

5.2 用 CI 守住一致性

# 最小校验:改动代码却没动规格,就该被问一句
- name: spec-check
  run: |
    changed_code=$(git diff --name-only origin/main...HEAD | grep -c '^src/' || true)
    changed_spec=$(git diff --name-only origin/main...HEAD | grep -c '^specs/' || true)
    if [ "$changed_code" -gt 0 ] && [ "$changed_spec" -eq 0 ]; then
      echo "代码有改动但规格未更新,请确认是否属于纯重构"; exit 1
    fi

这条检查不追求绝对正确——纯重构本来就不该改规格。它的作用是让"忘了写规格"变成一次显式的判断。

5.3 把规格喂给 AI 的正确姿势

把整份 spec 丢给模型之前,先确定它读到了三样东西:术语表、已有接口约束、验收条目。缺了术语表,同一个词在模型眼里可以有三种含义;缺了接口约束,它会自己发明一套。

读 specs/refund-policy/spec.md 与 design.md。
约束:
1) 术语按 specs/glossary.md 的定义,不得自造;
2) 只改 RefundService 与话术模板,不动订单模型;
3) 每条验收项都要有对应测试,列在 tasks.md。
先输出方案与任务清单,等我确认后再写代码。

最后一句是关键:让模型先交方案,再交代码。一次生成到底的代码,几乎必然在某条验收项上跑偏。

6. 与其他做法的关系

载体 记录什么 与规格的关系
规格(spec) 要做什么、边界、验收 主来源,行为的事实标准
ADR 为什么这么选(架构决策) 引用规格,解释取舍
Issue 谁在什么时候做哪件事 从 specs 的 tasks 派生
Wiki / 文档站 对外说明与教程 从规格改写,不反向约束
测试用例 行为是否成立 规格的机器可执行版本

别让它们互相替代:用 issue 记需求,三个月后 issue 关闭了需求就丢了;用 ADR 记需求,会把"要做什么"和"为什么这样设计"搅在一起。

7. 什么团队适合,什么不适合

情况 适合度 原因
需求相对稳定、交付周期长 高 规格的写作成本能被摊薄
多人协作、需要交接 高 单一书面来源减少口头传递
用 AI 大量生成代码 高 结构化输入直接提升生成质量
有合规/审计要求 高 变更留痕本身就是交付物
一次性脚本、内部小工具 低 写规格比写代码慢
探索期原型、方向天天变 低 规格会变成追着改的负担
单人项目、需求在脑子里 低 没有沟通损耗可省

判断口径:**规格的成本是"每次变更多写一段",收益是"每次交接少解释一轮"。**团队规模小、交接少,收益就撑不起成本。


8. 常见的六种失败形态

现象 原因 处理
规格写完就没人看 没有和代码建立引用 代码注释/PR 模板里引用 spec 路径
规格与代码脱节 改代码时跳过规格 CI 加一致性检查,评审时对照验收项
规格越写越像设计文档 需求层塞了实现细节 需求层只写行为,方案放 design.md
过程太重压过收益 每个小改动都走全流程 按变更规模分级:小改动只更新 spec 的一节
AI 生成的规格空泛 没给上下文与约束 先给背景、术语表、已有接口
多份规格互相矛盾 没有唯一来源与索引 一份规格一个目录,交叉引用而非复制

最后一条最隐蔽:复制粘贴出来的第二份规格,从诞生起就在腐化。


9. 边界:什么时候别引入

场景 更合适 理由
几天就交付的一次性脚本 直接写,写清注释 流程成本高于维护成本
需求还在剧烈探索 先做原型,稳定后再补规格 规格会变成频繁重写的负担
已有成熟的需求管理流程 把规格层接进现有流程 不要并行两套
团队没有评审习惯 先把评审跑起来 没有评审,规格只是自说自话
纯粹的技术重构 ADR + 测试 行为不变,规格无需改

一句话定位:规格驱动开发不是"多写文档",而是"把行为定义提前到代码之前,并让它成为可核对、可 diff、可交接的资产"。


10. 自测

  1. 需求散落在聊天记录里,会具体造成哪三类问题?
  2. 规格里的"不做"一节为什么比"要做"更值钱?
  3. 规范 → 需求 → 方案 → 任务 → 实现,跳过中间一步会怎样?
  4. 规格与 ADR、issue 各自的职责边界是什么?
  5. 什么样的团队不适合引入规格驱动开发?
  6. 规格与代码脱节,除了人工评审还能怎么守?
S27-X10 · OpenSpec 与 Spec-Kit:规格驱动开发的落地
https://www.clxhxhhr.top/posts/5788/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。