OpenSpec+SDD:给AI写代码立一份可执行的规范契约
2026/9/15 4:04:34 网站建设 项目流程

说实话,我用AI写代码的时间越长,越觉得“AI替代程序员”这类口号有点过于乐观。不是AI不行,而是大多数人根本没搞明白怎么跟AI描述需求。我见过太多人扔给AI一句“帮我写个用户登录模块”,然后对着AI生成的一堆“能用但根本不敢上线”的代码发愁。问题出在哪?出在你们之间缺了一份规范驱动的开发契约。今天要聊的OpenSpec和SDD(规范驱动开发),就是专门解决这个痛点的——它不是让你多写一堆没用的文档,而是把需求文档、任务拆解、验收标准这三件事做成了能被AI直接消费和执行的结构化流程,让“从需求文档到代码交付”这条链路真正跑通,顺带治一治AI乱写、反复返工、代码不可维护这几个老毛病。这篇文章适合所有在用Cursor、Copilot或任何AI编程助手的开发者,尤其是被AI“一本正经地胡说八道”坑过的朋友。

1. AI写代码为什么总在翻车:需求缝隙才是罪魁祸首

1.1 我踩过的AI乱写坑:三句话需求引发的灾难

先讲个真实经历。之前我让AI给我的内部工具加一个“批量导入用户”的功能,我把需求浓缩成了一句话:“导入Excel,校验数据,返回结果”。AI倒是很勤快,唰唰生成了两百行代码,用了Apache POI、搞了正则校验、还自作主张加了个“自动识别邮箱格式”的规则。看着挺全,结果跑起来全是问题:Excel列名跟我的模板对不上、空行处理逻辑直接报错、失败记录没有落到日志里。我就来回调Prompt、改逻辑、反复让它修,前前后后折腾了四个多小时才把这一小功能跑通。问题不在AI,是我压根没说清楚“哪些列必填”“空值怎么处理”“导入失败要不要回滚”,这些细节全被一句简单需求抹平了,AI只能靠猜。这次经历让我意识到,AI写代码翻车的根源不是模型能力,而是需求缝隙——你没说的、没定义清楚的边界,全部成了AI自由发挥的灰色地带。

1.2 SDD规范驱动开发的诞生逻辑:给AI补一份可执行的需求契约

AI不像人类同事,你说一句“大概这么弄”,他能靠行业经验自己补齐上下文。AI是纯粹的“按字面执行”,你给的信息越模糊,它的发挥空间就越大,而发挥越大,翻车概率越高。SDD的本质,就是把需求从“人的意图”翻译成“AI可执行的规范”。这里的“规范”不是传统意义上那种洋洋洒洒几十页的需求说明书,而是一份结构化的、按字段/条目组织的、能被AI逐条读取并对应到代码实现的需求契约。

我自己的理解是:SDD在“需求”和“实现”之间搭了一座桥。传统流程里,产品经理写文档、开发读文档、开发再写代码,中间每一道转述都是一次信息损耗。SDD则把这座桥尽量缩短——需求文档本身就是给AI看的实现说明书,人工智能读取后直接按章节对应产出代码。这样省掉了人工翻译的环节,也就减少了需求理解的偏差。

1.3 OpenSpec在SDD中的角色:需求文档到代码交付的翻译官

SDD是一套方法论,OpenSpec就是让这套方法论落地的工具。你可以把OpenSpec理解为SDD的“脚手架”:它规定了需求文档怎么写、任务怎么拆、验收标准怎么定、AI按什么顺序执行,甚至把整个项目的规范变更记录都纳入了版本管理。

我用OpenSpec之后最大的感受是,它把“让AI写代码”这件看似随性的事,变成了一个有状态、有约束、可回溯的工程流程。以前我面对的是一个空荡荡的对话窗口,现在面对的是一个完整的项目上下文:AI知道当前版本的规格是什么,知道自己要完成哪些任务,知道怎么验证自己写的代码是否合格。OpenSpec本质上是在给AI“立规矩”,用流程约束代替无休止的Prompt调优。

2. OpenSpec核心概念拆解:spec、tasks、acceptance三件套

2.1 spec.md:把“想要什么”写成人机都能读懂的规格

OpenSpec里最核心的文件是spec.md,它定义了一个功能/模块/变更的完整行为规范。我第一次接触的时候以为它跟普通需求文档一样,写满“用户可以通过邮箱注册”这种一句话。后来被坑了才发现,OpenSpec里的规格必须达到人能看懂、AI能执行双重标准。

怎么写才算合格?我自己总结了一套模板:功能背景(为什么要做)、用户流程(从哪进来、经过什么、到哪结束)、规则明细(字段定义、边界条件、异常处理)、数据结构(入参出参字段级描述)、依赖约束(不能改什么、必须复用哪些)。比如写一个“邮箱注册”规格,不能只写“支持邮箱注册”,而要落到“注册邮箱必须符合RFC规范”“密码长度8到20位且包含大小写字母和数字”“同一邮箱24小时内最多发送5次验证码”这种颗粒度。只有达到这个颗粒度,AI生成的代码才不用大幅返工。

2.2 tasks.md:把规格拆成AI能干完的粒度

有了一份清晰的规格,第二步就是把规格拆成若干个开发任务。tasks.md在OpenSpec中的作用就是任务清单,但它不是简单列“前端、后端、测试”这种大板块,而是拆到“一个AI能在一个作业周期内完成并验证”的粒度。

拆任务的颗粒度怎么把握?我的经验是:一个任务尽量对应一个文件、一个接口、一个独立逻辑。比如“邮箱注册”可以拆成:建数据库表并初始化迁移脚本、实现注册接口的参数校验、实现密码加密存储与用户落库、实现验证码发送与校验、编写注册接口集成测试。每个任务都具备明确的输入输出和完成标准,AI执行完一个再进入下一个,避免一次性喂十件事导致它顾此失彼。这块很像写代码时把大函数拆成小函数,每个函数只做一件事——对你友好,对AI也友好。

2.3 acceptance.md:用验收标准锁死交付质量

acceptance.md是我觉得OpenSpec里最容易被忽略但价值最高的一部分。它相当于一个功能过不过关的裁判规则。没有验收标准的时候,AI告诉我“写完了”,我得提心吊胆地自己拿Postman调接口去试;有验收标准之后,AI自己就能对照逐条自检,能过才敢说“完成”。

验收标准怎么设?关键是要可验证。不要写“注册流程应当顺畅”这种主观描述,要写“使用合法的邮箱和密码,调用注册接口,必须返回201状态码和用户ID”“使用已注册邮箱重复调用,必须返回409冲突,且不产生新的用户记录”“密码长度不足8位时,必须返回422和对应的错误码”。这些标准说白了就是测试用例的雏形,AI按它们逐项自检,你也能拿着它们做自动化回归。从需求文档到代码交付,验收标准就是最后一道闸门。

2.4 OpenSpec项目结构与初始化实操

说完了三件套,看一下OpenSpec的目录结构。初始化之后,项目根目录下会出现一个openspec/目录,内部通常按变更集(changeset)来组织规范文件:

openspec/ ├── project.md # 项目级全局说明 ├── changesets/ │ ├── add-user-login/ # 某个变更的名称 │ │ ├── spec.md # 规格说明 │ │ ├── tasks.md # 任务拆解 │ │ └── acceptance.md # 验收标准 │ ├── fix-import-bug/ │ │ ├── spec.md │ │ ├── tasks.md │ │ └── acceptance.md │ └── archive/ # 已完成并合并的变更集

初始化操作很简单:安装OpenSpec命令行工具后,在项目根目录执行openspec init,它会自动生成上述骨架。每个新的开发需求进来,就新建一个changeset,在里面写三件套。开发完成后,把变更集归档到archive/,规格和实现就形成了完整的时间线,以后查“某个功能为什么这么做”时直接翻归档文件,比看代码注释靠谱得多。

3. 3小时实战全流程:从零开始用OpenSpec交付一个功能

3.1 第一阶段:需求梳理与规格编写

最快上手的场景,是给现有的小项目添加一个“用户重置密码”的功能。我先把需求聊透,列出四条主干:用户提交注册邮箱、系统发送重置链接、用户通过链接设置新密码、新密码生效后续旧凭证全部失效。然后我把这四条展开成spec.md,每个环节都补充边界条件:邮箱不存在时到底返回“邮件已发送”还是“用户不存在”(我选择前者,避免用户枚举风险);重置链接有效期设为30分钟;链接只能使用一次,使用后立即失效;新密码禁止与最近三次历史密码相同。

写规格的过程其实是在逼自己思考产品的模糊地带。平时你脑子里“大概这么回事”的需求,在这里必须变成白纸黑字的明确规则。这个过程大概花掉40分钟,但我觉得非常值——因为写完之后,AI的执行路径已经被锁死了九成。

3.2 第二阶段:任务拆解与AI代理分配

规格写完,开始拆任务。tasks.md我拆成了六项:

  1. 新建password_resets表,字段包含id、email、token、expires_at、used_at、created_at
  2. 实现“发送重置邮件”接口:校验邮箱格式、生成随机token、写库、调邮件服务
  3. 实现“验证重置链接”的接口:校验token存在、未过期、未使用
  4. 实现“重置密码”接口:校验新密码强度、更新密码、标记token已使用、清空该用户所有登录会话
  5. 编写上述三个接口的集成测试
  6. 更新项目API文档

每拆完一个任务,我会顺手标注它依赖哪个任务、需要读写哪些表、对应哪几个文件。然后我把不同任务分配给不同的AI代理/会话执行,或者在同一会话里按顺序执行。任务独立的好处是,单个任务失败时不需要其他任务跟着回滚,修完再跑一遍就行。

3.3 第三阶段:代码生成与人工复核

AI按任务清单逐个实现。由于规格已经写清了字段和规则,它生成的代码基本符合预期,但仍需要人工复核几个关键点:第一,敏感操作有没有做权限校验;第二,异常分支有没有被吞掉;第三,数据一致性有没有被破坏。以重置密码为例,我会重点检查新密码更新和token失效是不是在同一个事务里,否则可能出现密码改了token还能用这种低级事故。

我的习惯是:AI每完成一个任务,我会立即让它跑一遍对应的测试,并贴上测试结果。OpenSpec的task清单天然适合这种“完成即验证”的节奏,不会像传统开发那样攒一堆任务到最后开会才发现做偏了。

3.4 第四阶段:验收测试与交付闭环

所有任务完成后,进入验收环节。我把acceptance.md里写的每条标准逐一交给AI,让它拿实际代码来证明是否满足。比如“使用无效token调用重置接口返回404”这条,AI会直接写个集成测试跑给我看。这一步是“防止AI自我感觉良好”的关键,因为AI自己判断“应该能行”和实际跑出结果之间,往往隔着一堆环境问题、全局变量污染、依赖版本冲突。

验收通过后,把changeset归档。至此,从需求文档到代码交付的完整闭环就结束了。整个过程我计时过,一个中等复杂度的功能,从0到上线大约需要2到3小时,其中1小时是规范编写和任务拆解,1小时是AI生成和测试跑通,剩下1小时是人工复核和问题修正。比起以前全手写动辄一天的周期,效率提升非常明显。

4. 工具链集成:把OpenSpec嵌进你的日常开发流

4.1 Cursor中使用OpenSpec的配置心得

我日常主力IDE是Cursor,OpenSpec在Cursor里用起来很顺手。核心做法是在项目根目录放好.cursor/rules文件,并让规则内容指向openspec/目录,告诉AI“每次开始任务前先读取当前changeset下的spec.md和tasks.md”。这样一样,AI每次开新会话时自带需求上下文,不需要我反复复制粘贴需求描述。

我还习惯在每个changeset的tasks.md开头加一段“当前进度说明”,比如“已完成1-3任务,待完成任务4”,这样即使Cursor中途重启会话,AI也能快速恢复上下文。这个习惯治好了我“换个对话就失忆”的头痛病,强烈推荐。Cursor的Composer/Chat窗口会和openspec目录下的文件交互,你把所有相关文件Add进上下文后,AI的回复质量基本稳定在高水位。

4.2 IDEA插件CCGUI集成OpenSpec

如果你主力IDE是IDEA,也有办法把OpenSpec接进日常流程。最近社区里比较流行的是CCGUI插件,它的核心能力是把AI对话面板嵌进IDEA侧边栏,并且支持读项目文件作为上下文。我在IDEA里用OpenSpec的路子是:把当前changeset的目录作为CCGUI的上下文参考路径,让插件把spec.mdtasks.mdacceptance.md加载进来,再让AI基于这些文件生成代码或补充测试。

CCGUI的好处是它延续了IDEA的老牌调试体验——AI改完代码,你直接鼠标悬停看diff,不满意的片段就地反馈让AI重新生成。配合OpenSpec的变更集结构,IDEA的本地历史也能和OpenSpec的归档对应上,查旧逻辑时两边对照很方便。社区里也有改进版插件能直接通过/openspec命令唤起spec文件选择器,省去了手动添加上下文的功夫。

4.3 Superpower与OpenSpec搭配使用

再说说Superpower。这名字听起来像是什么超级能力,其实它的定位是一个AI辅助工作流的“进程调度器”,帮你管理多条并行的AI执行线。我用OpenSpec + Superpower的姿势是:把拆好的tasks逐条喂给Superpower,让它调度多个AI代理/多个模型并行推进互不干扰的任务,同时汇总每个任务的状态和结果报告。

比如重置密码功能里,“建表”和“写邮件发送规则”互不依赖,我就让Superpower起两个并行执行线。它负责跟踪哪些任务完成、哪些任务卡住,并且把结果聚合回同一个tasks.md,更新进度。遇上有任务反复失败时,Superpower会帮我调用不同的模型重试,比如默认用Claude,遇到困难任务切换成GPT-4.1,思路瞬间清晰。这种“多模型容灾”的做法,配合OpenSpec的标准格式,基本能让“AI罢工”变成小概率事件。

5. 常见问题排查与避坑实录

5.1 规格文件写得太粗:AI交付结果全偏

我见过太多人用OpenSpec前信心满满,写完spec.md就扔给AI,结果AI交出一堆不沾边的东西。问题大概率出在规格太粗。比如“添加购物车”如果是“用户可以添加商品”,AI只能生成一个最基本insert逻辑;但如果你写明“同一商品重复添加时数量累加且不允许超过库存”“未登录用户添加时跳转登录页”“加购成功后返回购物车商品总数”,AI就知道自己的实现空间被限制住了,不会天马行空加戏。

排查思路很简单:如果AI交付的东西重复出现某个你没要求过的行为,或者频繁“自作主张”,先回去看spec.md,把对应场景的规则补明确,再让AI重做。让AI“少犯错”最有效的手段之一,就是消灭所有可能的歧义。

5.2 任务拆解的粒度玄学:拆多细才算合适

拆任务太粗,AI一个任务干太多事,出错后定位困难;拆太细,又会产生大量管理开销,光维护task状态就累死人。我实践下来的合理粒度是“一个任务对应一次可验证的交付物”。拿“购物车”举例,“实现购物车数据表”是一个任务,“实现加购接口”是另一个任务,“实现减购接口”是第三个,但不需要把“测试数据表”单独拆成第四个任务,因为表和接口天然绑定,测试用例应当随着接口一起产出。

这个标准说白了就是“这个任务完成后,你能否单独验证它没跑偏”。能验证,说明粒度合适;不能验证,说明需要再拆。

5.3 验收标准形同虚设:如何设置可自动验证的标准

很多人把acceptance.md写成了空话合集:“加购应当正确”“结算应当流畅”。这种标准AI没法执行。可验证的验收标准必须带上具体的输入、行为和预期输出。我整理了一张对照表供参考:

不可验证的写法可验证的写法
加购功能正常用户ID为1、商品ID为2、数量为3时,调用POST /api/cart返回200,且响应中cart_count为1
验证码有效期合理使用过期验证码注册时返回422,错误码为REGISTER_CODE_EXPIRED
数据一致性有保障密码更新成功后,原token调用重置接口必须返回404
权限控制有效未登录用户访问订单列表接口时返回401,且不返回任何订单数据

标准一旦落到这个颗粒度,AI就能自动化验证,你也能在CI里加一层回归测试,所有验收标准直接转成断言。

5.4 版本升级带来的兼容性问题

OpenSpec更新节奏不慢,我遇到过几次版本升级后目录结构或命令变了的情况。比如早期版本中changeset目录名必须用kebab-case,后来的版本支持了驼峰命名;还有一次是归档目录从archived/改成了archive/,导致旧脚本全部失效。

我的经验是:升级前先看CHANGELOG,升级后立即跑一遍openspec validate。OpenSpec自带校验命令,能检查目录结构、文件命名、规范完整性。千万不要在大版本迁移时直接沿用旧教程的命令,社区里就有人因为旧命令不兼容,卡了半个多小时找原因。

6. 我的实战体会与后续扩展方向

全套流程用下来,我最大的体会是:OpenSpec真正的价值不是“让别人给你写规范”,而是逼着你自己把需求想清楚。以前我面对一个需求,脑子里往往只有模糊的“目标状态”,编码时边写边改、边改边补,现在前置到规格阶段就逼你逐条明确。这其实是对开发习惯的改造,比工具本身更影响生产力。

后续我准备把OpenSpec的验收标准和CI/CD结合起来,让每次提交代码时自动跑到acceptance.md里的全部场景,直接把不合格的代码挡在流水线外面。另一个想法是用OpenSpec的变更集做知识库管理——每个归档的changeset都是一份“为什么这么实现”的活档案,新人接手项目时不用翻代码猜逻辑,直接读归档规范就能快速上手。

如果你也在被AI乱写、返工、不可维护这几个问题困扰,建议先拿一个中小型功能试试OpenSpec。不用追求一步到位,先把spec.md写清楚,你就能感觉到什么叫“AI终于理解我说的话了”。踩过几次坑之后你会发现,从需求文档到代码交付,差的不是AI能力,而是那份把需求钉死的规范。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询