ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI编程总跑偏?用OpenSpec规范驱动,从“拆盲盒”到“按图施工”

AI编程总跑偏?用OpenSpec规范驱动,从“拆盲盒”到“按图施工”

1. 为什么 AI 编程需要“规范驱动”

先问一个扎心的问题:你有没有遇到过 AI 编程助手一本正经地写出几百行代码,结果你一看,方向完全跑偏了?要么是没按你的目录结构来,要么是缺少关键的错误处理,要么是它信心满满地编造了一个根本不存在的函数接口。我见过太多人抱怨“AI 写代码像拆盲盒”,明明提示词写得挺清楚,出来的东西还是得大改。

问题不是出在提示词写得不详细,而是出在“一次性对话”这个模式上。你把所有要求塞进一段 prompt 里,AI 生成完代码就结束了,中间没有校验、没有阶段评审、没有标准化文件结构,它只能靠猜。猜对了算运气好,猜错了就是一场灾难。

OpenSpec 解决的就是这个问题。它的核心思路是:在 AI 写代码之前,先把“需求规格”和“验收标准”写成结构化文档,用文档驱动编码过程。也就是说,你不再用“唠嗑式提示词”让 AI 自由发挥,而是让 AI 按照一份预先定义好的规格说明去执行变更。变更做没做对,也不是靠肉眼判断,而是有明确的检查项和测试标准来验证。

这样做的收益非常明显:一是可复现,同样的规格文档交给 AI,跑出来的结果基本一致,不会今天一个样明天一个样;二是可评审,规格文档本身就是人类可读的,团队里任何一个人都能在 AI 动代码之前先确认需求方向;三是可追踪,每一个变更都有对应的 spec 记录,改了什么、为什么改、验收标准是什么,一目了然。

这个工具适合谁?适合所有用 AI 写代码的开发者和团队。哪怕你是个人开发者,只要你希望 AI 不只是一个“代码生成器”,而是一个真正能交付可靠代码的“协作工程师”,OpenSpec 这套思路就值得你认真研究。当然,它对团队协作的价值更大,因为规格文档本身就是一种沟通语言,能大幅减少“我以为你说的是这个意思”这类扯皮。

2. OpenSpec 的核心机制拆解

OpenSpec 不是一个重量级框架,它本质上是一套约定加一个 CLI 工具。你要先理解它的核心设计,才能真正用出价值。

2.1 AGENTS.md:给 AI 的“项目宪法”

OpenSpec 的第一个关键设计是在项目根目录维护一份AGENTS.md文件。这份文件的作用,是给 AI 一个关于项目结构、编码规范、技术栈、命名约定、约束条件的全局说明。

你可以把它理解成一份“项目宪法”。不管 AI 之后接到的任务是什么,它都会先读一遍 AGENTS.md,确保自己的行为符合项目的整体规则。这个设计解决了一个非常典型的问题:很多 AI 编程工具在生成代码时缺乏“项目上下文”,它不知道你这个项目用没用到特定框架、目录应该怎么组织、接口风格是 REST 还是 RPC。如果你只在某一次对话里告诉它,它下次就忘了。但 AGENTS.md 是持久化存在的,AI 每次都会读到,相当于把项目常识固化了下来。

实际写 AGENTS.md 的时候,我建议至少包含以下内容:

  • 项目的技术栈清单(语言、框架、构建工具、包管理器)
  • 目录结构说明,尤其是哪些目录放什么类型的代码
  • 编码规范,比如缩进风格、命名规则、注释语言
  • 常用的命令行操作(怎么跑测试、怎么构建、怎么启动开发环境)
  • 禁止做的事,比如不要修改某个文件、不要引入额外的依赖库

写的时候尽量具体,避免模糊表达。比如“保持代码整洁”这种话就没用,AI 不知道你所谓的整洁是什么意思。但如果你写“函数体超过 50 行必须拆分”,“所有公共 API 必须写 JSDoc 注释”,AI 就知道该怎么执行。

2.2 Spec 目录:需求的可执行化载体

OpenSpec 的第二个设计是在项目里创建一个spec/目录,里面按照specs/和projects/两条线组织规格文档。每份规格文档用 Markdown 写,结构固定,包含三部分:变更描述(Change Description)、需求与逻辑(Requirement and Logic)、任务与测试(Task and Test)。

这三部分各自承担不同的职责。Change Description 是对变更总体目标的概括,让人一眼看出这个变更要做什么。Requirement and Logic 是核心,要把需求和对应的逻辑拆开来讲,不能只写“首页要支持用户登录”,你得写清楚登录流程、会话保持方式、异常处理逻辑。Task and Test 则把工作拆成一个个可执行的任务,每个任务都要对应可验证的测试标准。

为什么要这样拆分?因为 AI 生成代码的问题往往不在于“写不出来”,而在于“不知道自己和目标之间有多少差距”。如果你只告诉它“写一个登录功能”,它可能直接给你甩一整套完整的认证模块,里面有一堆你根本不需要的东西。但如果你把需求拆成 Task A、Task B、Task C,每个 Task 都有明确的产出物和验收条件,AI 就能按部就班地执行,每完成一个任务就知道自己确实做对了。

2.3 变更状态机:从草稿到合入的完整生命周期

OpenSpec 对变更的生命周期定义得非常清晰。每一份 spec 文档都会经历几个状态:proposed(提议中)、active(执行中)、review(评审中)、merged(已合入)。

这个状态机不是形式主义,它确保变更在进入编码阶段之前,先经过需求确认。很多 AI 编程翻车就是因为跳过了“需求确认”这一环,需求都没对齐就开始写代码,写完发现根本不是我想要的,返工成本极高。OpenSpec 强制你在 first review 阶段先让人类评审需求文档,评审通过后才进入编码阶段,这个流程符合软件工程里的“先设计再开发”原则。

状态流转的实际操作,是通过 CLI 工具一步步完成的。你在命令行里执行openspec review,它会把当前变更标记为评审状态,同时生成一份差异对比,方便团队评审人在 Pull Request 里查看。这个过程顺畅且透明,不会出现“我明明改了,但没人知道改了什么”的情况。

3. 实战:从零初始化到第一次规范驱动开发

理论讲完了,实操才是重点。我用自己的实际经历,带你走一遍 OpenSpec 的完整流程。你要跟着操作也可以,大概十分钟就能跑通。

3.1 安装与初始化

安装 OpenSpec 很简单,它依赖 Node.js 和 npm 环境。如果你还没有装 Node.js,先去官网下载 LTS 版本装好。然后执行:

npm install -g @openspec/cli

装完验证一下版本:

openspec --version

接下来进入你的项目目录,执行初始化命令:

openspec init

这条命令会在项目根目录创建AGENTS.md和spec/目录结构。我强烈建议你在这时候花点时间认真写 AGENTS.md,不要直接用它生成的模板。因为后面所有 AI 编程操作都会以这份文件为行为基准,它写得越具体,AI 跑偏的可能性就越低。

顺便说一句,如果你担心 AGENTS.md 写得不完整,可以先写个基础版,然后在实际使用中不断补充。AI 是不会抱怨文档质量的,但文档质量会直接反映在它的产出质量上。

3.2 创建你的第一份 Spec

初始化完成后,创建一个新变更。假设我们要给一个 To-Do 应用增加“标签筛选”功能,执行:

openspec create filter-tasks-by-tag

执行之后,OpenSpec 会在spec/specs/filter-tasks-by-tag/spec.md生成一份规格文档模板。用编辑器打开,填入具体内容。

Change Description 部分,我写的是:

为任务列表增加按标签筛选功能,用户可以通过点击标签快速查看包含该标签的任务,并在筛选状态下正常执行完成任务、编辑任务等操作。

Requirement and Logic 部分,我拆成三条需求,每条对应明确的逻辑。比如“标签列表展示”这条需求对应的逻辑是:从所有任务中提取唯一标签集合并按使用频率排序,点击标签后触发筛选状态更新。

Task and Test 部分,我把工作拆分成了三个任务:

  1. 创建标签数据模型并迁移数据库
  2. 实现标签点击筛选的前端交互
  3. 为筛选功能补充后端查询接口和测试

每个任务下面都写了明确的验收标准。比如任务三的验收标准是“新增接口在无筛选条件时返回全部任务,有筛选条件时只返回匹配标签任务,响应时间不超过 200ms”。

写完整份 spec 之后,执行openspec plan filter-tasks-by-tag生成变更计划。这个计划文件里记录了这个变更涉及哪些文件、哪些技术决策、预计的修改范围,是后面所有编码工作的执行蓝图。

3.3 用规则驱动 AI 编码

现在到了真正的重头戏:让 AI 按照这个 spec 去写代码。配置好 Codex 或其他支持读取 AGENTS.md 的 AI 编程工具,直接让它执行:

请按照 OpenSpec 变更计划执行任务。先阅读 spec/specs/filter-tasks-by-tag/spec.md 中的需求,逐项实现并运行测试验证。

AI 收到这个指令后,会先读取 AGENTS.md 了解项目规则,再读取 spec 文档理解需求,然后按 Task 列表逐项执行。和之前“自由发挥”模式最大的区别是,它不再是基于你抛给它的几句提示词猜需求,而是基于一份结构化的完整规格去落地,每一步都知道自己在做什么、为什么这样做。

我实际测下来,这种模式下 AI 生成代码的准确率显著提升,返工次数明显减少。尤其是需求逻辑越复杂的时候,spec 文件的价值越能体现出来——它实际上是给 AI 补上了“需求分析”和“架构设计”这两块过去严重缺失的能力。

3.4 评审与合入

AI 完成编码后,进入评审阶段。执行:

openspec review filter-tasks-by-tag

这个命令会做几件事:对比 spec 中声明的任务和 git 中实际发生的变更,生成一致性报告;列出哪些任务已完成、哪些还有缺口;生成当前变更的完整 diff 信息供人评审。

我review完确认没问题后,执行:

openspec merge filter-tasks-by-tag

把变更标记为已合入状态,整个流程闭环结束。这个变更从需求定义、计划生成、编码执行、测试验证到评审合入,全程都有迹可循。以后想回头看“这个功能当初是怎么实现的”,打开 spec 目录就能找到完整记录。

4. 常见问题与排查技巧实录

用了一段时间之后,我整理了几个高频问题和对应的排查方法,相信你在实践中也会遇到。

4.1 高频问题速查表

问题现象可能原因排查方法
AI 生成的代码和 spec 不一致AGENTS.md 里的项目规则写得太模糊,AI 没有足够上下文检查 AGENTS.md 是否覆盖技术栈、代码结构、命名规范,把模糊描述改成具体规则
spec 里写了任务但 AI 跳过没做spec 的 Task and Test 部分描述不够具体,AI 无法将其拆成可执行步骤每个 Task 必须写明产出物和验收标准,避免类似“完善功能”这种无法执行的任务描述
review 阶段发现变更范围失控Change Description 描述的是一个笼统目标,没有界定边界写明“本变更不包括”什么内容,比如“本次不处理性能优化”
多个变更互相关联时状态混乱没有把关联逻辑写在 spec 里在 Requirement and Logic 部分显式声明依赖关系,注明前置变更的 spec 名称
通过评审的变更合入后测试失败测试标准写得太宽泛,没有覆盖边界条件在 Task and Test 中补充异常分支测试,例如输入为空、数据不存在、并发操作等情况

4.2 我最常踩的三个坑

第一个坑:一开始我把 AGENTS.md 写得像一篇散文,详细但散乱,AI 读完抓不住重点。后来改成结构化清单,每条规范独立一行,AI 的执行准确性立刻上来了。这个经验启发我:写 AGENTS.md 的时候,每条规则要能独立理解,不要依赖上下文推断。

第二个坑:按照自由发挥的习惯,我坚持在一份 spec 里塞了四个不相关的功能,结果 AI 在执行过程中逻辑混乱,文件修改互相干扰。后来我严格遵从一个变更只做一件事的原则,独立的小功能也要拆成独立的 spec,整个流程立刻顺畅了。

第三个坑:review 环节最初我很不上心,简单看看就 merged。结果有一次 AI 虽然按 spec 实现了功能,但代码风格和项目原有风格严重不一致,合入后维护成本升高。现在我会专门检查新增代码的风格和结构,这个环节不能省。

4.3 团队协作时的额外建议

如果你是在团队里推行 OpenSpec,建议第一周先跑一个小项目,让每个人都写一遍 spec 并互相评审。不用急着立一堆规定,先把基本流程跑顺。跑顺之后你会发现,规格文档这种“先文档后代码”的方式,不仅对 AI 有效,对团队里的人类同事同样有效——因为需求沟通的颗粒度变细了,很多东西在开发之前就被聊透了。

另外,可以把 spec 目录提交到 git 仓库,和代码一起管理。这样每次 Pull Request 里都包含对应的规格文档,评审人看着文档看代码,理解成本降低很多。团队成员离职或者新人加入的时候,翻开 spec 目录就能快速理解每个功能的设计意图,上手速度快得多。

5. 这套方法论更深层的价值

用 OpenSpec 一段时间后,我回头看它做的事情,本质上不是“让 AI 听你的话”,而是“让 AI 和你在同一个频道上”。很多 AI 编程工具的使用者处在“提示词工程师”阶段,费尽心思琢磨怎么把需求描述清楚,但 OpenSpec 提供了一条新的路:跳出“张嘴说需求”的框框,把需求文档化、结构化,让它成为 AI 和人类共同依赖的参考系。

你自己试试就明白我说的意思了。当 spec 文档写得足够清晰,AI 就会从一个被动的“代码生成器”变成一个理解目标并主动推进的“工程师助手”。你不需要在提示词里反复强调各种细节,因为规范已经替你把细节定义好了。这个体验上的跨越,是单纯优化提示词很难达到的。

我个人现在每个项目开始之前,都会先花 20 分钟写 AGENTS.md 和一个基础 spec,这个时间花得特别值。而且我发现,这个习惯一旦养成了就很难回去——体验过“按流程推进”的省心感,你就不想再回到“拆盲盒”式编程了。后面的路,你完全可以先拿一个真实的小需求跑一遍完整流程,经验积累起来之后再看看哪部分需要调整。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进