资讯动态

OpenSpec实战:规格驱动开发如何让AI编程更可控

发布时间:2026/10/18 18:53:45 来源:尧图企业网站定制
这两年我最大的开发习惯转变是把“写代码之前先写规格”这件事正式纳入流程而引我走上这条路的核心工具就是 OpenSpec。起因很直接团队用上 AI 编程助手之后代码产出速度快了好几倍但合并完代码再回头看经常发现跟最初的需求对不上甚至把需求本身做歪了。OpenSpec 是一套围绕“规格驱动开发”设计的开源工作流方案核心做法是把规格文件直接放进代码仓库让开发者本人和 AI 助手基于同一份 markdown 文档对齐目标、拆解计划、验收结果。这篇 OpenSpec 使用教程会从设计动机讲起重点拆初始化、目录规范、核心命令和端到端流程再配上我在真实项目里的实操过程与踩坑记录适合正在用或准备用 AI 辅助开发的工程师、技术负责人参考。1. OpenSpec 想解决的问题为什么“想清楚再动手”反而成了稀缺能力1.1 传统需求链路里的信息损耗先讲一个很常见的场景。产品经理在群里提了个需求开发随手记两行笔记然后直接打开编辑器开始写。代码写了两天Review 的时候才发现某个边界条件根本没定义或者某个行为跟原有模块冲突。这时候返工的成本已经不是多写几行代码的问题而是设计决策本身要推倒重来。这种事在任何团队都发生过区别只在于频率高低。这种链路本质上是在做有损压缩口头需求 → 二手转述 → 开发理解 → 代码实现每一层都会丢信息而且丢的往往是最关键的那部分——边界条件、异常路径、非功能约束。文档不是没有但大多数人写的文档是给“以后的人”看的不是给“正在写代码的自己”看的。于是写完即过时过时即没人看没人看就更不想写最终形成恶性循环。规格驱动开发的出发点就是试图打断这条循环链条。1.2 AI 编程工具让问题更刺眼而不是自动消解很多人以为引入 AI 编程工具之后需求描述成本会下降因为“AI 很聪明说个大概它就能补全”。这个判断对了一半。AI 确实能补全但补全的是它从训练数据里学到的“大概率预期”而不是你的真实需求。你在对话里描述得越细它实现得越准只要你停下来不说它就开始自由发挥而且往往发挥得很有自信这就让错误在代码层面快速扩散。另一个更隐蔽的问题是跨会话失忆。多轮长对话里模型对早期内容的记忆会逐渐被稀释一旦新开一个会话上次聊好的约束就彻底清零。我见过不少团队AI 接入初期生产力暴涨用了一两个月后开始花大量时间让 AI 反复“重读需求”甚至要人工逐行检查它有没有擅自加功能。问题不在模型能力而在需求本身没有一个稳定的、可被反复引用的载体。1.3 规格文件就是需求和代码之间的“缓存层”OpenSpec 抓的正是这个矛盾。它的核心思想很朴素既然人和 AI 都记不住完整上下文那就把话说清楚写进仓库里让规格文件成为需求和代码之间的缓存层。无论换人、换会话、还是换模型只要还读同一个 openspec 目录目标和约束就始终在那里。这是几十年前软件工程里“需求确认”思想的现代化实现但 OpenSpec 把它做轻了——不需要评审委员会不需要需求管理平台几个 markdown 文件加一个小型 CLI 就能运转起来。先说明一下这里的 OpenSpec 不是 OpenAPI/Swagger 的替代品。OpenAPI 解决的是接口定义格式问题OpenSpec 站在更上游管的是需求规格、实现计划和验收条件。两者可以共存你可以在 spec 里引用对应的 OpenAPI 文档也可以把接口契约单独维护互不冲突。理解了这个定位后面看命令和文件格式才不会产生混乱。2. 目录规范与 spec 文件格式先把“规矩”立起来2.1 初始化之后仓库里多了什么拿到一个新项目第一步永远是openspec init它会在仓库根目录生成一个 openspec 目录和一份模板配置。以我目前习惯的版本为例初始化后的目录大致是这种结构openspec/ README.md core/ workflow.md # 团队工作流约定 quality.md # 质量标准与验收要求 projects/ demo-service/ proposals/ # 提议回答“为什么做” plans/ # 计划回答“怎么做” specs/ # 规范回答“具体做什么” implementations/ # 实现回答“做成了什么” acceptance/ # 验收回答“凭什么算完成”不同发行版本里具体目录名可能有差异我也见过把验收条件合并进 spec 文件、把提议单独放一层的写法。关键不在于目录怎么命名而在于这几类信息必须被明确分开。提议、计划、规范、实现记录、验收结果五样东西一旦混在一个文档里最后就会退化成没人维护的“项目说明”。另外提醒一句CLI 的具体命令名在不同版本里可能略有出入不确定时先跑openspec --help看一眼不要硬记命令。2.2 一份 spec 文件应该长什么样目录结构清楚了再看一份具体的 spec 文件。下面这个例子是在我做的一个登录限流需求里实际写过的简化版本--- id: user-login-rate-limit title: 登录接口限流 status: proposed owner: backend-team created: 2025-01-10 --- ## Why 当前登录接口没有任何限流措施调用方可以无限次尝试密码 已经触发过一次短信轰炸事件需要从接口层收敛风险。 ## What Changes - 在 API 网关为 /api/login 增加基于 IP 账号的滑动窗口限流 - 默认窗口 5 分钟同一账号最多 20 次尝试同一 IP 最多 100 次 - 超限返回 429并在响应头携带 Retry-After 字段 - 限流命中情况接入现有监控告警 ## Impact - 涉及服务api-gateway、auth-service - 风险点可能误杀正常用户的多次登录尝试需观察误报率 - 不涉及密码策略、验证码逻辑、第三方登录这个文件的信息密度比我以前写过的任何“需求文档”都高原因在于三个设计选择。第一frontmatter 里的 id 和 status 是后面所有 CLI 命令追踪的依据id 全局唯一status 对应流程状态机。第二Why 段写的是决策上下文让人和 AI 都明白“为什么要动手”而不是“今天的任务列表”。第三What Changes 全部写成可验证的行为而不是“让登录更安全”这类无法验收的空话。格式本身不复杂复杂的是有意识地区分“背景”和“验收标准”。2.3 五类文件的定位差异proposal、plan、spec、implementation、acceptance 这套文件体系刚开始接触会觉得冗余好像同一个需求要写五遍。我用一张表把它们的定位差异列出来看完你就能理解为什么需要分开文件回答的问题内容重点什么时候维护proposal为什么做背景、动机、目标需求刚出现时plan怎么做步骤分解、依赖、验证方式proposal 通过后spec具体做什么行为规则、接口约束、边界开发开始前冻结implementation做成了什么改动清单、关联 PR/commit开发结束后同步acceptance凭什么算完成可验证的验收条件开发前后持续对照这张表的核心信息是每个文件都在回答一个独立的问题互相之间不允许出现“这个内容放哪个文件都行”的模糊地带。尤其是 plan 和 spec很多人都分不清。我的理解方式很简单plan 描述的是过程spec 描述的是结果。过程可以随机应变结果必须稳定。模糊地带一多文件分工就会失去意义流程会迅速塌缩回原来的“一份文档写到底”模式。2.4 给人看也喂给 AI写作风格的三条原则整个规范体系有一个隐藏要求文件既要让人类 Review 者十秒看懂也要让 AI 在多次读取后依然能找到关键约束。我的写作习惯可以归纳为三条。第一条少用程度副词“尽快完成”要写成“本迭代内上线”“性能变好”要写成“P95 延迟低于 800ms”。第二条边界显式化把“不涉及什么”明确写进 ImpactAI 才不会在实现时顺手改了无关模块。第三条一条一个行为What Changes 里每一条都应该能独立对应到一段代码改动或一个测试用例。这条在 Review 时尤其管用如果某个 spec 条目在代码里找不到对应实现要么是代码漏了要么是 spec 写了无用信息无论哪种情况都需要处理而不是让两者互相将就。实践下来绝大多数无效 spec 条目都来自形容词太多、动词太少这个判断标准可以直接抄进团队规范里。3. 端到端实操一条新需求从提议到验收的完整闭环3.1 创建提议先把“为什么”说清楚拿到一条新需求我的第一反应不是打开对话窗而是先跑一条命令openspec create proposal user-login-rate-limit。CLI 会生成一份带模板的 proposal 文件自带的 Why / What Changes / Impact 三个区块会强制你补全平时最容易跳过的信息。模板的价值就在于它帮你兜住了最低限度的结构要求不会因为着急上手而省掉关键内容。这个阶段最容易被忽略的纪律是proposal 阶段不要写技术方案甚至不需要指定用什么中间件。你只需要回答三个问题现在哪里疼、期望变成什么样、改动大概会波及哪些系统。剩下的技术选型和实现细节留到 plan 阶段。我见过不少团队一上来就争论限流用 Redis 还是本地缓存结果业务方向还没对齐方案就白做了。proposal 的价值就是让所有人先确认“要不要做”再谈“怎么做”顺序反了会浪费大量讨论成本。3.2 编写 plan把目标翻译成可执行的步骤proposal 审查通过之后进入计划阶段。我会用openspec plan生成 plan 文件或者直接在 plans 目录下手动创建把一个需求拆解成可执行的若干步。拆分标准不是“一步一个文件”而是一步必须对应一个可以独立验收的结果。步骤之间要有清晰的先后依赖每一部的产出都能被检查和验证而不是笼统地写“完成限流逻辑”就结束。还是拿限流举例。我把它拆成三步第一步在 API 网关侧增加过滤器和对应的单元测试第二步接入监控指标和告警规则第三步做一轮压测并调整窗口参数。每一步都标注涉及的模块、建议改动的文件和可运行的验证方式。这样写的好处是后续不管是我自己写还是丢给 AI 写工作都变成“按顺序执行”。计划写得越细中途返工的概率越低这是我在多个项目里反复验证过的经验。好的 plan 还有一个隐藏判断标准可以拿给一个不了解项目的人照着做不需要再问任何问题。如果做不到说明步骤里还藏着大量隐含知识这些知识在写代码时就会变成误解。3.3 让 Agent 按 spec 干活而不是按闲聊干活plan 就绪后我开始让 AI 参与实现。关键操作不是把对话背景从头贴一遍而是给它最小上下文入口文件路径、权威的 spec 文件路径、以及一条明确约束——没有在 acceptance 里列出的行为不要擅自实现。我常用的 prompt 模板大概是这样的你正在为项目实现功能user-login-rate-limit。 先完整阅读以下文件 - openspec/projects/demo-service/specs/user-login-rate-limit.md - openspec/projects/demo-service/plans/user-login-rate-limit.md 按 plan 的第 1 步开始实现只做这一件事。 完成后把改动整理成 diff 摘要 并对照 spec 里的 What Changes 逐条打勾。 不要实现 acceptance 以外的功能。这段 prompt 的精髓在于“只做 plan 里的一步”。我把需求拆得足够细之后每个 Agent 会话只专注一步上下文占用小输出不容易漂移出错时也只需要回滚局部改动。如果你让 Agent 一口气实现整个 feature它通常会在后半段开始“自由发挥”最后你得去排查一个巨大的 diff排查成本可能和直接自己写差不多。把大目标切成小步骤喂给 AI是我用 OpenSpec 之后收获最大的实操经验。3.4 validate、apply、accept收尾不是走过场开发完成并自测通过后回到 CLI 层面收尾。我的工作流大致是先跑openspec validate检查 spec 文件的格式、引用关系和状态机流转是否合法确认无误后跑openspec apply user-login-rate-limit把状态从 planned 切到 implemented最后等代码 Review 通过、合并之后再执行openspec accept让它进入 accepted 状态。很多人把 apply 和 accept 当成可有可无的仪式实际上它们解决的是“做完了但没人确认”这个黑洞。accept 之后我会把验收记录对应的 commit hash 或 PR 链接写进 acceptance 文件将来有人问“这东西什么时候上线、谁确认的”直接翻文件就行不用再去翻聊天记录。这是一个成本极低、收益极高的习惯强烈建议保留。它也让“完成”这个定义有了客观证据而不是靠某个人拍脑袋说“我觉得差不多好了”。4. 把 spec 喂给 AI 的正确姿势上下文管理的几个实操细节4.1 “喂 spec” 比 “描述需求” 更省 token也更稳这部分经验主要来自我用 Claude Code 和 Cursor 的对比实践。同样是实现一个功能如果你在对话里描述需求每个字都在消耗上下文预算而且描述到第五轮时模型对第一轮内容的印象已经开始变淡。把 spec 文件路径丢给 Agent 让它自己去读相当于用几百 token 的路径索引换来几千 token 的稳定上下文。对严格按量计费的工具来说这也意味着更低的成本。所以我的原则是凡是能在 spec 文件里明确写清楚的绝不在对话里重复说。对话只承担两件事——告诉 Agent 读哪个文件以及确认这一步的目标。这听起来很简单但真正做到还挺难因为人总有重复唠叨的冲动。你越克制Agent 的输出越稳定这是一个反直觉但真实有效的规律。克制不是偷懒而是把表达空间让给文件本身。4.2 Agent 开始“自作主张”时按这条路径排查用 OpenSpec 配合 AI 做得多了你会发现一个规律Agent 一旦偏离预期几乎都是因为两个原因要么它没读到正确的 spec 文件要么 spec 本身写了模糊的需求。排查路径应该是先看 Agent 的工具有没有访问到目标文件路径再看它读到的内容是哪一个版本最后才轮到怀疑模型能力。很多人一看到输出不对就怀疑选错了模型其实大部分时候问题出在喂进去的上下文上。一个经常被忽略的坑是分支版本不一致。spec 文件在某个功能分支上已经更新了但 Agent 默认读取的是 main 分支的旧版本方向自然就偏了。我所在团队后来约定“当前功能分支的 spec 为准”并且要求开始实现前让 Agent 把读到的 spec 关键条目复述一遍。这个复述动作很好用等于用低成本方式验证了 Agent 的上下文是否正确而不是等它写完一大段代码才发现方向错了。4.3 把 audit 挂进 CI用机器盯流程OpenSpec 提供的 audit 命令最实用的场景是检查规格覆盖情况有没有 feature 的 spec 还没被 accept有没有代码改了但 spec 没更新有没有提议长期停留在 proposed 状态没人处理。我们团队在 CI 里加了一步openspec audit --strict让包含未跟踪变更的合并请求直接给出提示。这一步接上之后流程合规就不再依赖某个人的提醒而是每次合并都被自动检查。注意audit 校验的是流程状态和文件一致性不是替你审查代码正确性。它解决的是“团队真的在按规格驱动流程走”的问题相当于流程上的 type check。内容质量好不好还得靠人 Review spec 本身。所以我的建议是把审计挂进 CI 之后再把 spec Review 放进代码 Review 的前置环节两者配合流程才算真正闭环。审计能防住“没走流程”Review 能防住“走了流程但内容不行”。4.4 spec 文件是跨会话的长期记忆最后补充一个容易被低估的价值spec 文件让团队记忆从“某个同事记得”变成“仓库里搜得到”。新人入职或者三个月后回来维护老功能直接看 openspec 目录就能还原当初的设计决策和约束。这种可追溯性在日常开发里感觉不到但每次出现人员变动、需求回溯、线上问题排查时它都是救命级别的资产。我还会把一些“为什么不做 X”的讨论结果写成反例放到 Impact 段里。这类信息对后来者极其重要因为代码里只会留下“做了什么”很少留下“为什么没做那个”。而没做的那个往往是引发下一次返工和争论的根源。把“不做的事情”也规格化是我从 OpenSpec 工作流里学到的额外一课扩展一下它几乎适用于所有长期维护的仓库。5. 我在真实项目里踩过的坑和踩完之后立的规矩5.1 坑一spec 写得像论文结果没人看也没人用第一次带团队接入 OpenSpec 时我犯的最大错误是过度设计。每个文件都写得特别详尽用了大量形容词描述系统愿景甚至把技术架构演进路线也写进去了。结果 Review 的时候同事根本读不下去AI 也找不到关键约束在哪里。后来我把衡量标准改成一条任何一段话如果删掉之后不影响决策、不影响验收就删掉。这条标准一下子把大部分水分挤干了。现在团队里的 spec 文件全部加起来通常也就一百多行。能一句话说清楚的事绝不用三段话铺垫。这一点在 AI 时代尤其重要因为模型分配注意力是基于文本量的无关信息越多关键约束被稀释得越厉害。你要做的是帮 AI 圈出重点而不是在文档里埋没重点。写完之后拿给同事看一遍如果对方三分钟之内没有提问这份 spec 才算是合格的。5.2 坑二spec 与实现分家流程变成走形式这是所有规格驱动流程最典型的失败模式。开发前写了 spec开发中图方便直接改代码最后想起来 spec 没同步。等到 accept 的时候代码和 spec 已经对不上了只能二选一要么改代码要么改 spec但两边都不想改于是 accept 变成毫无意义的打勾仪式。很多团队说自己的规格化流程“跑不动”根子就在这个环节。我后来立的规矩很简单任何改代码的 PR必须同步修改它关联的 spec 文件如果 PR 里只有代码、没有 spec 更新Reviewer 的第一反应就是打回去。这个规则靠人自觉靠不住必须写进 CI 脚本和 PR 模板里用机器去卡。流程要想活得久不能依赖自律要依赖强制。另外一个细节是spec 更新要跟着代码 commit 走不要攒到最后统一补否则等于没说。5.3 坑三粒度失控每个小函数都开一个 spec跟过度设计相对的另一个极端是把 spec 拆得过碎。有人把“按钮文案改成‘提交订单’”这种只改一行代码的需求也单独建一个 feature结果 openspec 目录本身变成新的技术债维护成本超过了它带来的收益。团队很快会对流程产生逆反心理觉得这套东西只是在增加工作量没有带来价值。结合多个项目的实践我建议的粒度标准是一个 spec 对应一个用户或业务可感知的行为变化大致等于以前的一个 Story 级别而不是一个 Task。判断方法也很简单你能否用一句话向非技术同事描述这个 spec 的产出如果可以粒度基本合适如果要解释半天那就说明拆得太碎了。粒度的判断标准要写进规范里否则每个人理解不一样目录很快会变成大杂烩。5.4 坑四AI 读了过期的 spec方向越干越偏这是 AI 时代特有的坑。因为 Agent 的上下文来自文件内容一旦 spec 文件在另一个分支更新了或者 plan 在实现过程中被调整了而 Agent 仍然按旧文件执行就会出现方向性偏差。这并不是模型笨而是它的输入源本身没有跟上变化。就像给一个员工看旧版需求文档他再认真也做不出你想要的东西。我们的解决办法是在 plan 旁边维护一个 Change Log 文件每次调整计划就在里面追加一条原因同时要求 Agent 在开始实现前先读 Change Log。代价很小但防漂移的效果非常好。如果你发现自己的 Agent 经常“跑偏”先别急着换模型检查一下它读的参考文件是否和当前进展同步。这个检查只要多花三十秒却能避免大段返工。5.5 踩坑之后沉淀的检查清单症状根因对策spec 没人读写得太长或太虚删到“删掉不影响决策”为止accept 走过场spec 与实现分家PR 必须携带 spec 更新CI 卡住openspec 目录膨胀粒度太碎一个 spec 对应一个业务可感知变化Agent 频繁跑偏读到过期或不一致文件维护 Change Log要求 Agent 先读需求仍频繁返工proposal 阶段被跳过先审 proposal再进 plan这张表现在每次复盘都会拿出来对一遍基本能定位团队里八成的流程问题。表格里的每一条都对应具体场景和具体动作比空泛的“加强流程意识”有用得多。定期用这张表做一次“体检”比等到出问题再检查要省事得多。6. 从个人项目到多人协作落地 OpenSpec 的实践顺序6.1 先选一个小项目证明价值再谈全面铺开我强烈不建议一上来就在核心项目里全面推行。合理的做法是选一个半个月迭代的小服务把 proposal → plan → implement → accept 的闭环完整跑一遍让团队感受到“Review 有依据、联调少返工”的甜头再扩大范围。选项目时有个硬条件参与的人不多但需求变化频繁。只有需求频繁变化spec 带来的稳定性才会被充分感知在那种需求三个月不变的项目里这套流程的收益很难显现强行推行反而会让人觉得多此一举。跑完试点之后把过程中的真实反馈收集起来尤其是“哪些环节减掉了浪费、哪些环节增加了负担”这类信息。要知道这个流程不是越多越严格越好而是越贴合团队实际越好。不同团队的组织方式、沟通习惯、AI 使用深度完全不一样照搬别家的模板通常会水土不服。6.2 团队落地的五件事总结我们在多个团队落地时的标准动作第一初始化 openspec 目录让每个成员都独立跑一遍 init避免出现“只有我一个人在维护”的情况第二统一模板字段禁用自由发挥的目录命名文件名和字段不统一后面所有工具链都会跟着乱第三把 audit 挂进 CI让流程校验自动化第四在 PR 模板里加上“关联 spec 文件名”这一栏倒逼提交人回填第五每月清理一次 openspec 目录把长期停留在 proposed 状态、无人推进的提议归档或删除。这五件事每件都不难难的是同时做到。如果只能先做两件我建议先做 audit 进 CI 和 PR 模板改造它们会持续压着流程不腐化。其他三件可以后续慢慢补但这两件基本是底线因为它们是外在约束。人靠内在动力维持流程短期内可行长期几乎必然失效这是团队协作里的铁律。6.3 原型项目和正式项目规格要求可以不一样如果团队里有很多快速验证类项目可以放宽规格模板。我的做法是给项目打 prototype 标签这类项目只要求写 proposal 和 acceptance不强制写 plan。因为原型阶段的计划变化太快强行写 plan代价大于收益。一旦原型转正式再补全 plan 细节也不迟。这个变通很重要否则成员会为了“符合流程”而堆砌没用的计划进而对整个流程失去信任。流程设计的本质是约束力度适配项目类型的风险等级而不是一个模板打天下。6.4 关于这套流程我的个人体会最后说点私人层面的感受。OpenSpec 这类工具真正改变的在我看来不是代码质量而是团队对“需求还没想清楚”这件事的感知速度。以前写代码要等写完、Review 发现货不对板才知道需求有问题现在写 proposal 和 spec 的阶段就能暴露大部分分歧返工成本从几天的代码量降到了几小时的文档量。我接手过的几个项目都验证了这一点所以规格先行并不是喊口号而是切切实实省下了时间。如果你也想在项目中尝试我建议不要一上来就追求完整闭环先跑最小验证一条需求、一份 proposal、一份 acceptance、一次 accept。跑通一个循环之后你自然会知道下一步该加强哪一块。我在第一个项目里只用了 proposal 和 acceptance 两样东西后来觉得不够用才逐步把 plan 和 implementation 补进来。流程是长出来的不是抄出来的这句话放在任何规格化实践里都适用。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑