ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

OpenSpec:AI编程失控的解法,先立规矩再动手

OpenSpec:AI编程失控的解法,先立规矩再动手 2025年的AI编程工具说实话已经卷到了一种离谱的程度。Cursor、Claude Code、Codex CLI、OpenCode把每一个单独拎出来都活得下去但它们都共享同一个毛病你让它改一个bug它可能顺手把你命名了半年的接口变量全部重命名你让它加一个筛选功能它改完以后你根本不知道它动了哪些文件review起来跟考古一样。我用OpenSpec大概是从2024年底开始的这个东西解决的恰好就是这个问题——AI写代码之前先立规矩再动手。OpenSpec不是又一个代码生成器它是一个“规范驱动开发”的流程层。简单说它让AI Agent在动代码之前先产出一份人类可读的改动规格说明明确“当前状态是什么、目标状态是什么、要改哪些文件、哪些是必须需求、哪些是期望需求”等这份说明书被人工认可之后AI才被允许进入执行模式。这篇文章我会把OpenSpec的安装、核心概念、工作流、实际案例和我在使用过程中踩过的坑全部分享出来适合那些已经被AI编程工具搞到破防、但又不愿意放弃AI效率的开发者。1. 为什么“先立规矩再动手”AI编程最大的失控点1.1 让AI直接改代码改一次崩三处我先说一个几乎所有人都会遇到的场景。你让AI给待办事项应用加一个“优先级”字段它改起来特别快几十秒就给你列了五个文件。你以为这就完了仔细一看它把整个表格组件重写了之前手工调好的样式全丢了测试用例也改了甚至顺手把工具函数里的排序逻辑换成了另一种写法。这种“程序员的热情过度发挥”在AI身上体现得淋漓尽致因为它不知道哪些代码是你精心设计过的、哪些是可以动的它只知道你的描述里最接近的意图是什么。我早期用Cursor做项目的时候因为这类问题回滚过很多次。有一次给客户做一个小型CRM我让AI优化一下列表查询接口的性能它花了十分钟把后端ORM模型全部重构了重构完数据库迁移对不上前端接口字段也变了整个项目直接跑不起来。当时我就意识到问题不在AI的能力而在于我给它的是“目标”而不是“约束”。AI写代码不是写不好它是太自由了自由到不考虑全局的稳定性。1.2 人类最适合做的是“意图管理”而不是“代码搬运”后来我开始琢磨一个很朴素的问题在AI编程时代人类开发者真正的价值到底在哪里代码的具体实现AI已经写得很好了尤其是那些重复的模式化代码。但有一件事AI短时间学不会就是“知道自己手上有哪些雷”。哪些模块是上线了好几年的稳定代码哪些函数被十多个地方引用哪些改动会牵连到别的服务这些信息散落在开发者的脑子里不在AI的训练数据里。传统的代码审查是AI改完代码之后你来review diff这叫“事后检查”。问题在于AI的diff太发散了它一口气改了二十个文件你根本看不过来也没法判断每一个改动背后的理由。OpenSpec换了一个思路把审查点从“代码”提前到“意图”。在AI动手之前先让它把要怎么做、改哪些文件、预期的行为变化写出来你审查的是一份规格说明书而不是几百行diff。这本质上是一种“意图管理”的分工人类管方向和边界AI管执行和细节。1.3 OpenSpec的定位AI Agent的“产品经理”我经常给朋友打一个比方让AI直接写代码就像你请了个装修师傅告诉他“我要把厨房弄好看点”然后让他自由发挥。师傅可能给你装了个欧式吊顶但是水管没动因为你没说。OpenSpec做的事情是先让师傅出一张设计图标注清楚哪里要拆、哪里要留、用什么材料、预算多少你看了设计图说行他才开始动工。装修师傅还是那个师傅但流程变了翻车概率就大幅下降了。所以OpenSpec的定位不是替代Cursor或者Claude Code而是站在它们上面的一层“流程控制中枢”。如果说AI Agent是执行者那OpenSpec就是那个逼着AI先做方案的产品经理。它不写代码它逼着AI把思路写出来然后等你说“可以动手”。这个概念在整个AI编程工具链里非常稀缺也是我当时决定深入用它的根本原因。2. OpenSpec核心机制拆解plan、run、review三段式2.1 三个命令把AI编程变成有状态的工程流程OpenSpec整个工作流可以压缩成三个核心命令openspec plan、openspec run、openspec review。这三个命令对应了“计划、执行、验收”三个阶段和传统软件工程的瀑布模型有点像但它不是死板的流程而是一种轻量级的质量门禁。先解释一下plan阶段。你给OpenSpec一个模糊或清晰的需求描述它会调用你配置好的AI模型去读懂项目现有代码然后生成一份规格文件。这个文件不是代码是描述改动的文档包含当前实现状态、目标实现状态、受影响文件、需要满足的条件列表等等。生成的spec会被放在项目里的一个固定目录下等着你人工审查。等你确认spec没问题再执行openspec run。这个时候AI才会真正去修改代码按照spec里约定的内容逐个实现。这里有一个很关键的设计run阶段AI只能围绕spec文件里提到的文件和需求去改不能自由发挥去动其他代码。最后用review命令对执行结果做核验看看改动是否真的和约定一致有没有漏改、错改。整个过程有据可查AI不是随便改完就交差而是必须面对一个“验收标准”。2.2 项目结构一切有据可查OpenSpec初始化之后会在项目根目录生成一个.openspec文件夹我习惯把它提交到Git仓库里因为里面的spec其实就是一个轻量级的需求和设计文档库。这个目录下通常会有几个关键部分我用一个表来说明目录/文件作用我的使用习惯project.md记录项目整体约定、技术栈、架构约束每次动大需求前先更新它让AI有全局上下文specs/存放已经完成并归档的规格说明当作项目文档的一部分随时能查changes/存放当前正在进行的变更规格每次开工前都来这个目录看一眼状态agent-log.md记录AI在每次任务中的执行日志出了问题能回溯AI到底做了什么这个结构最让我舒服的一点是它天然形成了一种“项目记忆”。以前用AI改代码这周改完下周就忘了当时为什么这么改。有了spec归档每次改动的原因、目标、范围都清清楚楚。后来我跟团队配合的时候发现新成员看一遍specs/目录里的历史文档比让他自己读三天源码还有效。2.3 spec文件就是一个“需求规格书”OpenSpec的每个变更都对应一个.md格式的spec文件。我用过一段之后总结出它包含的几块核心内容首先是变更概述一句话说清楚这次要干嘛然后是当前状态和目标状态这个非常关键它强迫AI先去看懂现有代码而不是凭空想象还有受影响文件清单这相当于给AI画了一个“安全范围”文件清单之外的代码不允许动最后一个部分是需求列表里面区分need和wantneed是必须实现的核心功能want是有余力再做的优化点。举个例子我让AI给一个待办事项应用增加标签功能spec文件的核心部分大概长这样# spec: add-tags-to-todos ## Overview 为待办事项增加标签分类能力。 ## Current State - Todo表只有 id、title、completed 三个字段 - API只支持新增、查询、完成待办 - 前端不展示任何分类与筛选 ## Desired State - Todo新增 tags 字段类型为 string[] - API支持按标签筛选列表 - 前端在待办项上展示标签并支持按标签过滤 ## Files to Change - src/models/todo.ts - src/routes/todos.ts - src/pages/TodoList.tsx ## Requirements **Need必须完成** 1. todo模型增加 tags 字段默认空数组 2. create/update 接口接收 tags 参数并做格式校验 3. TodoList组件展示标签并支持点击标签筛选 **Want期望实现** 1. 标签支持自定义颜色 2. 标签支持模糊搜索这个文件一旦生成就相当于你和AI之间签了一份合同。AI在执行阶段如果跑偏了你只需要把这份spec拿出来对照就能明确告诉它哪里违反约定。这种“契约感”是直接对话式编程给不了的。3. 快速上手安装OpenSpec并跑通第一个AI改造任务3.1 安装与初始化两条命令的事OpenSpec的安装很简单Node环境正常的机器上一条npm命令就能装好npm install -g openspec装完以后在你要改造的项目根目录里执行初始化openspec initinit过程会引导你选择默认的AI模型和provider比如Claude Code或者OpenAI兼容接口还会生成上面说的.openspec目录。第一次跑init的时候我建议你认真看一下生成的project.md把项目的技术栈、目录结构、编码约定写进去。这一步很多人会偷懒跳过去但后面你就发现project.md写得越清楚AI在写spec的时候越准确因为它的思考有了一个“项目世界观”。初始化完成之后你就可以开始第一条plan指令了。这里有个小技巧不要把需求描述得又大又空最好一句话说清目标、范围、约束。比如“让Todo模型支持标签保留现有接口兼容”和“给Todo加标签”前者生成的spec质量会高很多。3.2 实战让AI给自己写代码流程加上Todo标签功能我拿一个真实的Todo项目来走一遍完整流程。先运行plan命令openspec plan 为Todo增加标签功能支持按标签筛选保留现有API兼容这一步会唤起AI工具去读项目代码然后生成spec文件。等命令结束后我先不急着run而是打开生成的spec文件逐条检查它的表述是否准确。有一次AI生成的spec里写“注意删除旧的todo删除接口”这明显是过度理解了需求我赶紧在Files to Change里加了一个“禁止删除任何现有路由”的约束再重新plan一次。确认spec没问题后执行openspec runOpenSpec会进入执行模式AI开始按照spec改动代码。整个过程和普通AI编程差不多但有一个核心差异它不会开第二个无关文件去“顺便优化”。执行完以后我会跑一遍测试npm test然后再执行review命令openspec reviewreview会检查改动是否和spec里的需求一一对应有没有漏项。如果review发现AI没有完成某个need项它会直接标记为不通过你就得重新让AI补上。这一步相当于给AI的产出做了“校验和”。3.3 在Cursor、Claude Code、OpenCode、Codex里用OpenSpec我常用的组合是OpenSpec作为流程管理层Cursor和Claude Code作为执行引擎。具体操作是在Cursor的Agent模式或者Claude Code里直接把openspec plan、openspec run、openspec review当成工具命令来调用让AI自己去执行命令、读取spec、改动代码。这里面有个顺序上的讲究plan阶段和run阶段最好用同一个AI会话因为plan阶段AI已经读了一遍项目结构对项目的理解会延续到run阶段跑起来更顺。但如果你用的是Codex或者OpenCode这类工具要注意不同工具的上下文管理方式不一样切换工具时可能会丢掉之前的记忆所以最稳妥的方式是每次执行run之前都让AI重新读一遍spec文件而不是假设它还记得。顺便说一句有一种常见错误是让AI既写spec又自己执行相当于“自己写需求自己实现”最后spec往往写得很敷衍。我的经验是在plan阶段和run阶段之间至少要“人工停顿一下”你亲手看过一眼spec再放AI进去跑。这一步花不了多少时间但能省掉后面至少一半的返工。4. 案例拆解一次完整的接口重构是如何落地的4.1 需求描述把错误处理逻辑从Controller抽到Middleware我拿一个稍微复杂一点的案例来说明OpenSpec在高风险重构里的价值。有个老项目的API接口每个Controller里都写了一段重复的try/catch错误处理代码互相拷贝改一处要同步改好几处。我想把错误处理逻辑统一收敛到一个全局中间件里删掉各个Controller里的重复代码。迁移的时候我给自己提了一个硬性要求接口行为不能有任何变化对外部调用方完全透明。这种“不能有任何行为变化”的重构恰恰是直接让AI改最容易翻车的场景因为AI会惯性觉得“既然重构那就顺手优化一下响应格式”。所以我在plan命令里把约束写得很明确openspec plan 将Controller中重复的try-catch错误处理抽到全局中间件API响应格式严格保持不变禁止修改任何路由路径4.2 spec文件里的关键设计约束比需求更重要生成的spec里Desired State部分描述了重构后的代码结构Files to Change列明了涉及的文件清单这部分没什么意外。真正有价值的是Requirements里的Need约束我也写进了“禁止”条款**Need必须完成** 1. 新增 src/middleware/error-handler.ts统一捕获异常并返回错误响应 2. 所有Controller中重复的try/catch代码块移除改用中间件处理 3. 错误响应格式与现有格式完全一致{ code: number, message: string } **Want期望实现** 1. 中间件支持异步错误捕获 2. 增加请求ID字段方便日志追踪 **Do Not** - 不得修改路径参数和路由定义 - 不得修改HTTP状态码映射关系 - 不得改动数据校验逻辑你发现没有我专门加了Do Not这一段。这是我在一次糟糕的AI重构经历之后总结出来的做法——AI对“能做什么”的理解往往远超你对它的预期但“不能做什么”你必须显式告诉它。没有这一段AI看到Controller里有个变量命名不规范会顺手改掉虽然不破坏功能但让review diff变得巨大纯粹增加你的工作量。这个spec提交给AI执行后改动集中在新增middleware文件和删除各Controller的重复代码。执行完我跑了全量接口测试所有用例通过响应体结构对比一致。整个过程最让我满意的是review阶段的输出能明确列出哪些代码被删除、哪些文件没被触碰方便我做二次确认。4.3 AI执行后的验收环节不是跑通就完事了openspec review这个命令的验收意识很多开发者可能觉得多余。但我想说它其实是整个流程里最被低估的环节。很多情况下AI执行完毕后代码能跑但它可能用了“伪装实现”——比如为了保留一个方法签名内部直接抛异常而不是真正实现逻辑。这部分静态看代码很难发现。我现在的做法是review通过后我还会跑一遍静态检查工具和测试覆盖率用工具去兜底AI的“软性偷懒”。然后我会抽查一下关键文件的diff看有没有和spec无关的改动。如果一切正常才把这次变更归档到specs/目录里变成项目的正式文档资产。还有一个小细节审查的时候不要只看代码还要看agent-log.md。这份日志会记录AI在执行过程中做了哪些决策、遇到过什么问题。有一次我发现AI在日志里写“为避免破坏现有测试跳过了一个文件的修改”就立刻意识到有个功能实际上没实现。所以日志是用来抓AI“自作主张”的重要证据链。5. 常见问题与避坑实录5.1 AI总是改超范围代码怎么破这个问题几乎每个用OpenSpec的人都会遇到尤其是在最开始几周。AI的Files to Change通常也被约束了但它还是会想办法“越界”。比如它可能在改动schema时顺手给另一个无关实体也加了字段或者为了测试方便在配置里加了一个硬编码的环境变量。我的解决办法有两个层面第一在spec里用Do Not显式列出禁止改动的内容这条对AI非常有效第二把改动范围控制在更小的“变更单元”里一次只做一件事。比如一个需求同时涉及后端API和前端页面我会把它拆成两个独立的change分别plan和run。这样即使AI跑偏定位和回滚也容易不会一个错误牵连整个需求。5.2 spec写得“差不多”执行效果就打五折如果你的spec里都是“优化用户体验”“提升代码质量”这种模糊描述那AI执行出来的结果基本等于没约束。OpenSpec的价值全在spec的精确度上need项要具体到可以验证的行为比如“新增接口GET /api/todos?tagwork返回带有work标签的待办列表”而不是“支持按标签查询”。建议在spec里为每个Need项写一个明确的验收方式要么是接口返回结构要么是一个单元测试用例。AI执行完review时它会去对照这些标准。如果你自己都没想清楚验收标准AI自然只能靠猜。5.3 小改动也走完整流程会不会太重有朋友问我改一个拼写错误、调一个配置项也要走plan、run、review我的回答是完全没必要。我自己判断的标准很简单如果这次改动影响面小于一个函数、不涉及数据模型、不改变对外接口直接让AI改完拉倒不需要开spec流程。但如果改动跨了两个以上文件、涉及数据模型或接口路径那走OpenSpec就是值得的因为这类改动的回滚成本太高。我的经验数据是在OpenSpec流程下一次跨文件重构的平均耗时和直接让AI改差不多但review时间能显著下降因为大多数实现问题已经在plan阶段被拦截了。算总账并不亏。5.4 如何把OpenSpec接入CI/CD和代码质量检查OpenSpec本身不解决CI/CD的问题但它的产物可以嵌入到现有流程里。我现在的做法是在MR的CI流水线中增加一个步骤先执行openspec review再跑一遍lint和测试甚至接上像SonarQube那类静态扫描工具做额外检测。一旦review发现spec中某个Need没有满足流水线直接中断MR不能合并。这种做法实际上把“AI写代码的验收权”从个人经验升级成了自动化门禁。以前是人去逐行看AI的diff现在是让流程卡住不规范的结果。对于团队协作来说这是一层很划算的保障。6. 实际收益OpenSpec到底值不值得用6.1 直接改代码 vs OpenSpec流程差别有多大我整理了这段时间实际使用下来的对比按我自己的体感打分维度直接让AI改代码OpenSpec流程单次任务耗时快但返工率高前期慢后期稳定跨文件改动安全度低容易失控高有边界约束Review成本高diff巨大低按spec逐条核对可追溯性差改完就忘好有完整文档归档团队协作个人经验主导流程规范驱动学习成本基本为零需要适应plan阶段整体来看OpenSpec更像是一个“纪律工具”。它不会让AI变得更强但会让AI的产出变得可控。如果项目是临时脚本、一次性工具完全没必要用如果是长期维护的产品代码、特别是团队协作它的价值会随着时间指数上升。6.2 什么项目最适合用OpenSpec我总结了三类最适合OpenSpec的场景。第一类是数据模型和业务逻辑复杂的项目这类项目改动一个字段往往牵一发动全身spec里的“影响范围”描述能避免很多连锁事故。第二类是客户项目需求变更是家常便饭每次变更都有spec归档后续追溯和报价都有依据。第三类是团队里有多个开发者在不同AI工具之间切换的项目OpenSpec提供了一个统一的流程框架避免每个人各写各的。反过来如果项目还在非常早期的原型验证阶段需求一天变八次那么每次变更都走plan流程会很痛苦这时候更适合跑得快的玩法等需求稳定了再引入OpenSpec也不迟。6.3 我的使用建议从小任务开始如果你想尝试OpenSpec我的建议是别一上来就拿核心模块做实验。先挑一个两周后的重构任务或者一个独立的新增小功能用OpenSpec走一遍完整的plan-run-review流程体会一下“先立规矩再动手”的感觉。在用完第一次之后你大概率会形成一个新习惯不管用什么AI工具都习惯先把约束写清楚再让AI去执行。这个习惯本身比OpenSpec这个工具更值钱。另外一个小技巧spec文件写完后先放二十分钟再看一眼再去跑run命令。这个“冷静期”能让你发现很多第一遍写的时候没注意的漏洞比如缺失的边界条件、过宽的改动范围。等你在plan阶段把能想到的坑都填平run阶段的AI几乎不会让你失望。
返回列表