夜雨聆风学习资料网

ARTICLE · 1185353

我是如何将SDD接入AI编程工具链的

我是如何将SDD接入AI编程工具链的

好的开发工具不能直接决定代码质量,却能让已经想清楚的方案更稳定地落地。

前文介绍了 SDD 的核心思路:规范先行,代码服务于规范,并按六个阶段推进开发。真正开始实践时,开发者往往会卡在两个更具体的问题上:

  1. 规范文档到底怎么写?
  2. 写好的规范如何稳定地交给 AI 工具执行?

本文会借 OpenSpec 拆解这两个问题。读完后,你将能看懂一套 SDD 工具链如何串起探索、提案、实现、验收与归档,也能根据可读性和校验强度,为不同规范选择 Markdown、YAML 或 JSON Schema。

SharkChili · 禅与计算机程序设计的艺术

开源贡献

  • mini-redis:教学级 Redis 精简实现 · https://github.com/shark-ctrl/mini-redis

关注公众号,回复 【加群】 获得笔者联系方式,加入技术交流群。

OpenSpec 如何把规范变成工作流

一份规范如何跨工具复用

OpenSpec 是 Fission AI开源的 SDD 框架。它用 Markdown 保存规范,再用命令推动规范从提案走向实现和归档。核心目标是让规范尽量独立于具体 AI 工具:只要工具接入了相应工作流,同一份规范就可以继续复用。这种思路和 JVM 的“一次编译,到处运行”有一点相似,JVM 依靠严格的字节码和运行时约定;OpenSpec 依靠的则是共享文件结构、命令和工作流约定,体现一种抽象与具体的解耦,实现工程上的可复用。

OpenSpec 的一次完整变更通常包含四个动作:

  1. 使用 explore 探索需求和代码上下文。
  2. 使用 propose 生成规划产物,再由人工审核和调整。
  3. 确认方案后,使用 apply 按任务实现代码。
  4. 验收通过后,使用 archive 归档本次变更。

对存量系统来说,这套流程的优势很直接:每次变更都可以从一份小提案开始,无须先为整个系统补齐庞大文档。规范会随变更逐步累积,这也是本文选择 OpenSpec 作为 SDD 入门工具的原因。

先安装,再初始化 OpenSpec

可以通过 npm 全局安装 OpenSpec:

npm install -g @fission-ai/openspec@latest

macOS 或已安装 Homebrew 的 WSL 环境,也可以使用:

brew install openspec

安装完成后,在项目根目录执行:

openspec init

OpenSpec 会让用户选择需要接入的 AI 编程工具:

本文选择 Claude Code 进行演示:

初始化完成后,OpenSpec 会在 Claude Code 的 Skill 目录中生成后续工作流需要的文件。这里先确认初始化结果,具体用法放到后面的实践案例中。

用四层模型看懂 AI 工具生态

如果只看工具名称,各种 AI 编程项目很容易混在一起。更清楚的办法是看它们分别解决哪一层问题。

第一层是原子技能。它们通常是可复用的指令、小型工作流或专用 Agent,例如:

  1. 追问需求的 grill-me。
  2. 按 TDD 节奏执行编码。
  3. 只负责代码审查的 Agent。

它们不处理一个完整需求,而是约束 AI 做好某个关键动作:

第二层是上下文持久化。它通过项目规则文件维护团队约定、任务背景和业务知识,让 AI 在会话开始时获得相对稳定的项目上下文。CLAUDE.md 和 AGENTS.md 是这一层的典型产物。

第三层是规范生成框架。它们面向完整需求,把模糊想法整理为可审查、可拆解、可执行的规范,而不只是约束一个动作。OpenSpec、spec-kit 和 Kiro Specs 都可以放在这一层理解。

第四层是完整工程方法。BMAD、superpowers 等项目会继续向上串联头脑风暴、需求澄清、规划、执行、验收和知识沉淀,形成完整的工程闭环。它们关注的不只是这次规范能否产出,还包括这次开发留下的经验能否降低下一次开发的门槛。

这四层不是必须一次配齐的套餐。小型项目的瓶颈如果只是 AI 容易忘记项目规则,原子技能加上下文文件可能已经足够;大型系统如果还涉及复杂业务知识、架构约束和多人协作,才需要继续组合规范框架与完整方法。选择依据不是哪个工具更流行,而是当前工作流的瓶颈在哪一层。

SDD 规范应该用什么格式表达

选定规范框架后,下一个问题是:规范应该用什么格式表达?

过去,很多规范主要供编译器或代码生成器读取,因此常用 YAML 或 JSON Schema 描述结构和约束。AI 时代的规范多了两类读者:人类需要审查意图和取舍,大语言模型需要理解上下文并执行任务。因此,选择载体时至少要同时考虑可读性、工具可解析性和校验强度。

Markdown:负责讲清意图

Markdown 通常是 SDD 规范的默认选择,原因不是它的约束最强,而是它在人类可读性和工具兼容性之间取得了较好平衡:

  1. Markdown 是纯文本,方便进入 Git 做差异审查和版本追踪,也容易被当前的 AI 编程工具读取。
  2. 标题、列表、表格和代码块能够表达需求、设计、任务与验收标准,开发者不需要先掌握一套复杂语法。

下面这份需求规范就是一个最小完整示例。它用自然语言说明背景、目标、范围和验收标准,让人和 AI 都能判断“做什么”与“不做什么”。同时,它没有过早限定具体库或代码组织方式,把实现取舍留给设计阶段。

# 每日任务持久化## 背景每日任务编辑页包含任务标题、任务状态、任务日期和任务内容。用户保存任务后,需要在退出页面或重新打开任务时继续查看和编辑这些数据,当前需求需要明确每日任务的保存与恢复范围。## 目标- 持久化保存任务标题、任务状态、任务日期和任务内容。- 新建或编辑任务后,再次查询能够获得最后一次成功保存的数据。## 范围### 做什么- 保存每日任务清单,保存内容包括任务标题、状态、日期和任务内容。- 查询已保存的任务清单及单个任务详情。- 再次打开任务时,展示最后一次成功保存的数据。- 任务内容支持 Markdown 文本。### 不做什么- 不支持删除或恢复任务。- 不支持任务排序、延期、移动日期或批量操作。- 不支持任务提醒、共享、附件和统计分析。- 不考虑多人同时编辑或并发写入场景;任务工作台仅由个人维护。- 不改变现有任务状态的名称和业务含义。- 不改变每日任务编辑页的布局、样式和交互方式。- 不处理历史任务数据的迁移或清理。## 验收标准- 新增任务后进行查询,返回的标题、状态、日期和任务内容与新增时提交的数据一致。- 修改任务状态和任务内容后进行查询,返回的是最后一次成功修改的状态和内容。- 在单用户验收环境且数据库正常可用时,保存和查询接口的单次响应时间均不超过 200ms。## 技术约束- 持久化方案、表结构和缓存策略统一在 `03-design.md` 中定义,需求范围不绑定具体实现细节。

Markdown 的短板也很明显:它可以用结构帮助表达,却不能自动证明业务语义正确。Markdown 语法和格式可以交给工具检查,需求是否漏了边界、验收标准是否能够证明结果,仍然需要人或 AI 做语义审查。

YAML:负责描述接口契约

YAML 是一种数据序列化格式,在 SDD 中常用来表达 API 契约、配置和元数据。当 YAML 遵循 OpenAPI 等契约规范,并接入对应工具时,可以进一步生成 Mock 服务、运行契约测试或生成 API 文档。这些能力来自“契约规范 + 工具”,不是 YAML 格式本身自带的。

下面只演示请求和响应的数据形状,真实契约仍需要符合所选工具的完整格式:

-request:method:GETpath:/user/1response:status:200body:id:1name:张三

YAML 的代价是语法约束更多,编写时还要兼顾下游工具能否正确解析。因此,API 契约可以优先选择 YAML;需求背景、设计取舍和任务拆解等叙述性内容,通常更适合 Markdown。

JSON Schema:负责约束数据结构

JSON Schema 用来精确定义 JSON 数据的字段、类型和约束,并可以交给验证器做标准化检查。它的人工读写成本高于 Markdown,在表达同等信息时通常也更长。因此,JSON Schema 适合放在需要强校验的数据结构上,不需要代替所有叙述性规范。

{"$schema": "https://json-schema.org/draft/2020-12/schema","type": "object","properties": {"id": { "type": "integer" },"name": { "type": "string" }  },"required": ["id"]}

三种载体如何分工

这三种载体不是三选一,而是在同一份规范中各自承担不同任务,实践中可以先用 Markdown 写清意图和范围,再用 YAML 表达 API 契约,对必须机器校验的数据结构补充 JSON Schema。

如何让 AI 在正确时机读到规范

规范写好后,还需要解决一个更容易被忽略的问题:AI 如何在合适的时间读到对的规范,并按约定完成任务?

不同 AI 编程工具有不同的上下文加载机制,但目标相同:

为项目提供稳定的上下文入口,让 AI 知道要遵守哪些规则、读取哪些规范、如何验收结果。

用规则文件保存长期约定

首先要保存的不是某个具体需求,而是项目长期有效的 SDD 工作规则。Claude Code 和 Codex 会按各自的目录和覆盖规则,在会话中加载 CLAUDE.md 或 AGENTS.md 等项目文件。实际可见范围仍受目录、优先级和上下文长度影响,不能假设文件中的所有内容永远都会完整留在模型上下文里。

因此,项目可以在这类规则文件中明确几件事:哪些改动必须走 SDD,规范放在哪里,先审查什么,验收后如何归档。笔者的日常工作台就将“较大改动使用 OpenSpec 推进”写进了 CLAUDE.md。

用 Skill 固化重复动作

Skill 是面向特定任务的可复用操作约定。它会告诉 AI 何时启动某个工作流、需要读取哪些材料、产出什么结果以及如何检查结果。

一次完整的 SDD 变更会经过需求梳理、方案设计、规范编写、任务拆解和代码实现。这些动作可以分别封装成 Skill,避免每次都临时用对话重新解释标准。

OpenSpec 在执行 init 时生成的文件,就是针对 SDD 工作流的技能封装。例如 openspec-propose 会约束变更提案包含哪些产物、按什么顺序生成,从而降低规范格式在不同任务中漂移的概率。

拆清依赖,再让 Subagent 并行

当需求和设计已经确定,SDD 工作流可以把实现拆成 tasks.md 中的多个任务。其中没有依赖、也不会同时修改同一份文件的任务,才适合交给多个 Subagent 并行处理。

这样做主要有两个收益:

  1. 隔离上下文:每个 Subagent 只处理一个明确任务,减少不相关信息的干扰。
  2. 缩短等待时间:无依赖任务可以同时推进,不必串行等待。

并行不是默认更快。如果任务共享未稳定的设计、有先后依赖,或会同时改动同一文件,并行反而会增加冲突和返工。规范先把边界与依赖写清楚,才是 Subagent 并行的前提。

用 Hook 把检查变成自动门禁

项目规则和 Skill 能告诉 AI “应该怎么做”,却不一定能在关键节点自动检查它是否做到。Hook 就是补上这一缺口的事件触发机制:在工具支持的事件前后执行脚本,并在支持阻断的事件上根据检查结果决定是否继续。从 Java 角度看,它可以类比为针对特定事件的增强,但不等同于 AOP。

例如,可以在每次 Write 或 Edit 后触发单元测试。测试全绿只能证明已覆盖场景通过,不能代替规范核对、代码审查和必要的端到端验收。

下面的 PostToolUse Hook 会在工具写入后执行测试脚本。如果脚本在失败时返回工具约定的退出码并输出错误信息,AI 就能获得失败反馈,再进入“生成、修复、验证”的循环。但它不会撤销已经完成的写入,也不能保证 AI 一定会自动修复。如果还要阻止 AI 在未通过验收时结束任务,需要再在 Stop 等支持阻断的事件上配置检查。

"PostToolUse": [  {"matcher": "Write|Edit","hooks": [      {"type": "command","command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/mvn-test-gate.sh\"","statusMessage": "运行 Java 单元测试","timeout": 300      }    ]  }]

把 SDD 接入 AI 工作流,可以压缩为四个动作:

  1. 用项目规则文件沉淀长期有效的 SDD 约定。
  2. 用 Skill 封装 SDD 中可复用的专用动作。
  3. 将无依赖任务交给 Subagent 并行推进。
  4. 用 Hook 在关键节点自动检查和阻断。

让规范与代码一起进入 Git

如何在 Git 中组织规范文件

SDD 不是要用规范取代代码,而是要让“为什么这样改”和“最后改了什么”能够相互核对。因此,规范文档应当和代码一起进入 Git,接受版本管理和差异审查。

笔者习惯按下面的结构管理规范:

  1. 在仓库中设置 specs 目录。
  2. 每个需求对应一个独立目录,例如 daily-task-mysql-persistence。
  3. 用序号标识不同阶段的规范文档,让读者能够按顺序审查。
specs└── daily-task-mysql-persistence    ├── 01-proposal.md    ├── 02-spec.md    ├── 03-design.md    ├── 04-api-contract.md    └── 05-tasks.md

这样一来,变更范围、设计取舍、任务拆解和代码改动会留在同一仓库中,后续才能追溯当时的决策,并核对实现是否偏离规范。

先审规范,再审代码

当开发流程变成“先定规范,再按规范编码”,审查顺序也应该跟着调整。如果需求边界本身就错了,直接审查代码只会确认 AI 是否正确实现了一个错误方向。

规范审查至少要回答下面几个问题:

  1. 需求和边界是否准确?
  2. 验收标准是否清晰且可验证?
  3. ADR 中的推理和取舍是否站得住?
  4. 技术方案是否遗漏关键约束?
  5. 任务是否可执行,每个结果是否可验收?

规范确认无误后,再审查关键代码和本次完整 Diff,核对实现是否符合规范。规范审查不能代替代码审查:AI 仍然可能在逻辑、边界和技术细节上出错,这些问题还需要通过代码审查和测试暴露。

实战:用 OpenSpec 改造分页控件

为什么要改造分页控件

下面用一次真实的分页改造,看 OpenSpec 如何在 Claude Code 中串起探索、提案、实现、验收和归档。

笔者的个人写作平台最初只有“上一页”和“下一页”两个分页按钮。随着迁移的文章增多,想在相隔较远的页码之间往返时,就只能连续点击。本次需求是将它改为带页码、指定页跳转和尾页跳转的分页控件。

开始前先确认项目约束

正式开始前,先确认 SDD 工作流已经接入当前项目。这是一个存量项目,CLAUDE.md 中已经记录了项目用途、前后端技术栈,以及使用 worktree 创建 feature/* 分支的开发规则,因此这一步无需重复配置。

为了让每个任务的改动都容易审查,项目还做了两层约束:CLAUDE.md 要求先更新规范、再小步提交代码;Git Hook 则限制单次提交的暂存改动不超过 400 行。前者规定工作顺序,后者在提交时阻止超限改动,两者共同保持本次变更的可审查性。

先确认到底要改前端还是后端

分页控件显示在前端,却不能直接推断只需要改前端。页码跳转是否可用,还取决于后端接口是否已经返回总页数并支持指定页查询。因此,笔者先用 openspec-explore 探索当前前后端交互:

/openspec-explore 本次改造需将前台分页控件由原本的上一页和下一页,改为如下分页控件:1. 带有页码,且支持上下页跳转2. 支持输入页码后跳转到指定页3. 支持跳转到尾页请说明当前前后端如何交互,涉及哪些代码改动,以及是否存在风险。

Claude Code 探索代码后发现,后端分页接口已经能支持这次交互,本次改动可以收缩到前端页面。

范围明确后,再执行 /openspec-propose 生成变更提案,而不是带着“可能要改后端”的模糊假设直接开始编码。

先审提案,再审设计与任务

提案生成后,不是立即执行,而是先逐份检查规范。

首先检查 proposal.md:本次要做什么、不做什么、改动范围在哪里,是否与前面沟通的结果一致。

然后检查设计文档:改动是否仍然收敛在前端,分页控件的边界情况是否已经被考虑。

最后检查任务拆解:调整页面、增加控件、适配请求参数,每个子任务完成后都有对应验证,并在最后检查完整链路和边界。这三部分都与需求一致,因此本次无需再调整规范。

任务完成不等于验收通过

确认规范无误后,执行 /openspec-apply-change,让 Claude Code 按任务清单实现代码。

实现完成后,任务清单中的子任务已全部标记完成:

任务打勾只代表执行状态,不代表改动已经验收通过。接下来还要检查 feature 分支中的完整 Diff,确认改动没有超出规范,再合入验收分支进行实际页面验证。

改造后的页面如下。笔者对页码切换、上下页、指定页和尾页跳转做了实际操作,本次范围内的分页交互符合预期。

验收后再归档规范与代码

验收通过后,执行 /openspec-archive-change 归档本次规范产物,为后续追溯、审查和迭代保留依据。

OpenSpec 完成规范归档后,再将归档产物与代码一起提交到 Git,让两者进入同一套版本管理流程。

至此,这次分页改造完成了从探索、提案、审查、实现、验收到归档的闭环。

先找瓶颈,再选工具

选择 SDD 工具时,最容易问的是“哪个最好用”,但这个问题缺少了决定答案的前提:你希望工具解决工作流中的哪个瓶颈?

在比较工具之前,可以先检查三件事:

  1. 能否说清 SDD 解决的问题,而不只是记住几个命令?
  2. 能否解释每份规范的用途和审查标准?
  3. 能否把一个需求拆成边界清晰、可验收的设计与任务?

如果这三个问题还答不清楚,先手写一次小型变更的提案、设计和任务,比继续对比工具功能更有价值。如果已经能做到,再回到前文的四层模型,找出当前工作流卡在原子技能、上下文、规范框架还是完整方法,然后只引入解决这一瓶颈的工具。

现在就选一个你正在做的小需求,先写清“做什么、不做什么、怎么算完成”,再让 OpenSpec 补全提案。你需要检查的不是它生成了多少文档,而是这些文档有没有准确记录你的工程判断。

SharkChili · 禅与计算机程序设计的艺术

开源贡献

  • mini-redis:教学级 Redis 精简实现 · https://github.com/shark-ctrl/mini-redis

关注公众号,回复 【加群】 获得笔者联系方式加入技术交流群

相关学习资料