☰
OpenSpec:把说不清的需求变成AI可执行的结构化规范
2026/10/16 21:03:57 网站建设 项目流程

总觉得需求“说不清楚”,这个问题我带了五六年,直到最近才找到一套让我顺手的解决方式,就是 OpenSpec。OpenSpec 是一套规范驱动的项目工作流工具,核心思路是把产品需求、技术方案和实施任务统一成一组结构化的 Markdown 规范文件,让团队里的人类和 AI 都能在同一份上下文上对齐。它的使用方式不复杂:初始化一个目录、按模板写一个变更提案、把需求拆成若干条 spec,然后按任务执行。网上很多 OpenSpec 使用教程都写成了命令说明书,把一堆参数扔给你就完事,我不打算那么干。这篇更想讲清楚它背后的设计思路,以及我在实际项目里怎么把它嵌进日常流程。适合谁?适合那些在 AI 辅助编码中用得不顺手的人,也适合被 PRD 和代码永远对不上号困扰的团队。

1. OpenSpec 是什么:把“说不清楚的需求”变成可执行规范

1.1 为什么我在 AI 编码时代开始认真对待“需求描述”

先说一个我自己的经历。前两年我开始大量使用 AI 编码助手,刚开始觉得惊艳,复杂点的页面、脚本、接口示例,它都能在几十秒里给你列出来。但慢慢的,问题暴露了:它写出来的代码看着没问题,一跑就发现业务逻辑不对。我一开始以为是模型能力不行,后来复盘发现,八成问题出在我自己身上——提示词里那句“改一下登录逻辑,加个记住我”,在不同语境下能被理解成至少五种方案。

这是个很典型的场景。AI 编码工具再强,本质上还是一个“读完上下文后做预测”的系统。你喂给它的需求描述越模糊,它就越倾向于用最常见、最保险的实现方式猜。但业务需求偏偏不是“最常见”就能满足的:要不要长期 token?过期多久?记住我之后要不要自动刷新 token?这些细节,你得先想明白,才有资格让 AI 帮你写代码。

OpenSpec 恰好切入的就是这个位置。它不负责替你决策,而是强制你把决策落在纸面上,并且用一种机器和人都容易读的结构来组织。说白点,它就是把“模糊想法”变成“结构化规范”的中间层。传统做法是人跟人开会对齐,OpenSpec 的做法是把对齐的产物、变更提案和 spec 文件直接沉淀到仓库里,谁都能看、谁都改得动、AI 也读得懂。

1.2 OpenSpec 与 PRD、用户故事的差异

有人可能会问,这不就是写 PRD 或者用户故事吗?还真不一样。

PRD 通常面向的是“人类评审”,写得好的 PRD 讲究排版、句式、上下文,但这些自由格式对程序来说是灾难。产品经理写了一段很漂亮的描述,比如“希望用户在登录后有更流畅的体验,提升留存”,这句话人看了可能点头,但 AI 无法从里面提取出一个“可以验证”的行为。它缺少边界条件,缺少可观测的验收标准,缺少具体的触发场景。

用户故事又往往太简短,通常就是“作为用户,我希望……以便……”。它适合排优先级、适合站在用户视角思考,但作为实现说明书来说,颗粒度完全不够。一个“记住我”的故事背后,涉及前端存储、后端认证、安全策略、失效机制,靠三行用户故事根本讲不清楚。

OpenSpec 把规范拆成了一个相对完整的结构:每个变更有 proposal,里面写清楚动机和影响;每个 spec 文件只承载一个可验证的行为要求;tasks 再把实现步骤列清楚。本质上,它是把敏捷开发里经常挂在嘴边的“Definition of Done”落到了文件层面,让每个变更在被实现之前,先被定义清楚。而且最关键的是,这些文件进入 Git 仓库后,天然支持 diff、评审、回溯,完全可以像代码一样走审核流程,这是传统 PRD 很难做到的。

维度传统 PRD用户故事OpenSpec spec
面向对象人类评审产品讨论人 + AI 共同执行
可验证性弱,依赖人为解读弱,缺少验收细节强,逐条可验收
变更追踪靠文档版本管理靠看板备注随 Git 进版本库,天然可 diff
粒度控制整体方案故事级别单条 spec 独立可拆

1.3 这套思路到底解决了什么核心问题

我梳理下来,OpenSpec 解决的核心问题有三个维度。

第一是“减少歧义”。同一句话,产品经理、后端、前端、AI 助手理解出来的东西基本都不一样。把需求拆成一条条带前置条件、行为描述、验收标准的 spec 后,歧义空间被大幅压缩。即使最终实现有问题,你也能快速定位到是“哪条 spec 写错了”,而不是在代码层面猜需求。

第二是“让 AI 的使用成本下降”。使用 AI 编码助手最贵的不是 API 费用,而是上下文对齐成本。你把 2000 字的 PRD 扔给 AI,它可能只会关注最后一段;但你把结构清楚的 spec 文件逐条喂给 AI,它可以按图索骥地实现。很多 AI 支持仓库级分析和项目上下文,OpenSpec 的结构化文件正好可以被 AI 高效读取,相当于给 AI 一份“边界清晰的任务书”。

第三是“让变更可追溯”。有了提案和 spec 文件,你就能回答“这个功能当时为什么这么做”“那条限制是谁加的”。这些信息散落在聊天记录里最容易丢失,放在代码注释里又太零散,但在 OpenSpec 的目录结构中,它们跟着代码一起走,形成了一条完整的决策链。

2. 一次变更的骨架:目录、状态机与规范文件

2.1 先看目录结构:每个文件在说什么

要理解 OpenSpec,最容易上手的方式是先看目录结构。以我常用的版本为例,初始化一个项目后,会生成类似下面这样的一套骨架:

openspec/ ├── project.md ├── specs/ └── changes/ ├── 20250201-add-login-remember/ │ ├── proposal.md │ ├── specs/ │ │ ├── auth-remember-token.spec.md │ │ └── frontend-remember-checkbox.spec.md │ └── tasks.md └── 20250210-refactor-cache/ ├── proposal.md ├── specs/ └── tasks.md

project.md是项目级说明,相当于整个项目的高空视图,写清项目目标、整体约束、技术选型,让任何一个新加入的人或 AI 在最短时间内了解项目背景。specs/目录放那些已经稳定、跨变更共享的通用规范,适合沉淀一些“所有模块都必须遵守”的规则。changes/目录则是每一次独立变更的家,每一个子目录对应一次变更提案,里面再拆成 proposal、specs、tasks 三个部分。

这种设计最聪明的地方在于:它把“一次变更”这个虚的东西变成了一个实体目录。以前你参与一个改动,流程是“开会讨论、拉群沟通、写代码、提 MR、被打回、再开会”,整个过程是离散的,信息散落在各个角落。在 OpenSpec 的组织下,所有相关信息都收敛在一个目录里,你要 review 一个改动,只需要看这个目录下这几个文件,心智负担一下子小了很多。

2.2 提案状态流转:从 Draft 到 Archive

在 OpenSpec 的工作流里,每个 change proposal 都有自己的生命周期。我习惯把它理解成一条流水线:起草、评审、接受、归档。

起草阶段,你创建一个新的变更目录,这时候 proposal 还处于 Draft 状态,内容是草稿,随时可以改。评审阶段,你把它提交到团队里让人 review,关注点不只是代码,而是“需求定义是否准确”“spec 是否可验证”“影响范围是否完整”。评审通过后,方案被接受,开始进入实现阶段,spec 文件成为你写代码时的事实依据。等到代码合并、功能上线,这条 proposal 就可以归档,从 active 状态变成 archived。

你可能觉得这有点形式主义,但经历过几次“需求变更没有记录”之后,你会发现状态流转真的能救命。有一次我在一个旧项目里看到一个奇怪的配置项,翻遍 wiki 都没有说明,最后是在一个已归档的 OpenSpec proposal 里找到了当初的设计讨论,三分钟就把来龙去脉搞清楚了。这种体验是聊天记录永远给不了你的。

状态标识核心动作
草稿Draft自由编辑 proposal 与 spec
评审中In Review焦点是需求定义与可验证性
已接受Accepted开始按 spec 实现,代码以 spec 为准
已归档Archived保留决策记录,移出当前视图

2.3 为什么 spec 文件要“小而专”

我总结过 OpenSpec 里最容易踩的坑之一,就是把 spec 写得又大又全,一个文件把所有需求揉在一起。这看起来省事,实际上到了评审和验收的时候非常痛苦,因为没法逐条验证。

OpenSpec 的思路跟测试里面的“单一断言”很像:一个 spec 文件只描述一个行为、一项决策或一条约束。比如实现登录的“记住我”,可以拆成几个 spec:认证接口需要支持 remember 参数、前端需要根据勾选状态处理 token 持久化、服务端 token 过期策略需要在记住我场景下调整。每个 spec 都是独立可验证的,A 条失败不影响 B 条完成,而且实现顺序可以并行。

这样一来,AI 也能受益。你把三条独立 spec 交给 AI,它每完成一条就能确认一次,而不是让它一次性生成一个两千行的登录改造方案,出了问题根本不知道从哪里排查。小而专,本质上是把复杂度分解,让人和机器都能在一个可控的粒度上思考。

3. 实操过程:从零初始化到第一个变更跑通

3.1 安装与初始化:一分钟搭好骨架

如果你要试 OpenSpec,最直接的方式是先把它装到全局环境里。我的常见做法是使用 npm 安装,具体命令如下:

npm install -g openspec

安装完成后,进到一个干净的项目目录,执行初始化命令:

mkdir openspec-demo && cd openspec-demo openspec init

正常情况下,项目下会自动生成 openspec 目录和对应的骨架文件。这一步基本不需要动脑,但有一个细节值得注意:初始化之后先打开project.md看一眼,把里面项目名称、定位、技术栈这些信息改成真实的。千万别跳过,因为后续 AI 或者新同事一进项目就会优先读取这个文件,它直接影响整个项目上下文的准确度。我第一次用的时候偷懒没改,后来 AI 在生成代码时一直误以为项目是某个示例工程,排查了好久。

3.2 创建第一个变更提案

初始化完成后,就可以尝试创建一次变更了。以“给登录页面增加记住我功能”为例,命令大致是这样的:

openspec new "Add remember me to login flow"

执行后,changes/目录下会多出一个以“日期-名称”格式命名的子目录,里面是模板文件。打开proposal.md,你会看到需要填写的几个核心部分:为什么做、做了什么、影响哪些模块、变更类型是新增、修复还是重构。这个地方不用写太多字,但要把目的写清楚,尤其是“为什么做”这一项,很多人在实际使用时会忽略,直接跳到技术方案。等到三个月后你再看这次变更,唯一还能看懂的就是这个 why,代码实现早就忘了。

3.3 把需求拆成 spec 并落地任务清单

proposal 写完之后,重点来了:拆分 spec。我会在specs/目录下为每条白纸黑字的需求建立一个文件,命名尽量带上模块名和关键字。还是上面的例子,我大概会拆出这么几条:

specs/ ├── auth-remember-token.spec.md ├── auth-token-expiry-policy.spec.md └── frontend-remember-checkbox.spec.md

每份 spec 文件内部的格式,我建议至少包含三个部分:背景与目的、行为描述、验收标准。行为描述写清楚“当用户勾选记住我并登录成功后,系统应该返回一个有效期 30 天的长效 token”;验收标准则写成可检查的条目,比如“使用勾选记住我的账号登录,关闭浏览器后再次打开,用户仍然处于登录态”。这一步做完,需求已经基本具备了可执行性。

接下来是tasks.md,这一步是把 spec 再往下落一层,变成具体的开发任务。每一个任务最好能对应到具体文件、接口或组件,比如“在后端认证接口中增加 remember 参数处理”“在前端登录表单中增加记住我复选框”。任务列表可以和 spec 一一对应,也可以拆得更细,只要实现的时候能一条一条清掉就行。

3.4 把 spec 交给 AI:一次真实的协作过程

说实话,OpenSpec 真正让我觉得值回票价的时候,是把它接到 AI 编码流程里之后。我现在的做法是:在 AI 助手里明确告诉它项目根目录下有一套 OpenSpec 规范,然后直接把当前变更的 proposal 和 specs 路径丢给它。

一个比较稳的提示词写法大概是:

请先阅读 openspec/changes/20250201-add-login-remember/ 目录下的 proposal.md 和所有 spec 文件, 然后按照 tasks.md 里的任务顺序逐项实现。每完成一项,同步更新 tasks.md 的完成状态。

这里有个很实在的经验:千万不要让 AI 一下子把所有任务全干完。我试过让 AI 一口气实现整个变更,结果它在第三项任务上发挥想象,生成了一个跟需求完全不一样的设计,返工成本比手写还高。改成逐项实现之后,每完成一项我就检查一次,及时纠正,整体效率反而高很多。OpenSpec 的 task 拆分正好非常适合这个节奏,天然把一个大需求切成了 AI 能够稳妥吃掉的小块。

另外,如果 AI 支持仓库级语义检索,它会自己去翻 spec 文件,你只需要告诉它“变更文档在 openspec/changes 下”。如果 AI 不支持,你就手动把相关 spec 文件的内容复制到上下文里。结构化文本的另一个好处就在这:复制出来也不会乱,AI 能很轻松地按条目执行。

4. 把 spec 写好的四个心法

4.1 用验收标准倒推内容

写 spec 最常见的误区是从“实现方案”出发,上来就写“我们要用 Redis 缓存、要用 JWT 做认证”。这些实现细节不是不能写,但 spec 的第一输出应该是“行为”,而不是“技术选型”。我自己的方法是倒着写:先写完验收标准,再往上补行为描述和背景。

怎么理解这招?以“记住我”为例,我先列验收标准:关闭浏览器后重开,记住我用户登录态保持 30 天;未勾选记住我,关闭浏览器后需要重新登录;30 天后 token 过期,重新登录可刷新。这些验收标准列完,技术方案基本就被限定在很窄的空间里了,后面不管是 JWT、Redis 还是别的实现,都不会跑偏。先定义“怎么算完成”,再讨论“怎么做”,是我认为写 spec 最重要的一条原则。

4.2 别把非功能约束丢掉

很多团队用 OpenSpec 只写功能需求,性能、兼容性、安全这些非功能约束经常被忽略。但恰恰是这些约束,在 AI 生成代码时最容易出问题。你如果不告诉 AI“这个接口需要在 200ms 内返回”,它可能写出一个同步调用外部服务的实现,性能直接翻车;如果不写“token 必须使用 HttpOnly Cookie 存储”,AI 可能随手把 token 塞进 localStorage,留下安全隐患。

所以我在写 spec 的时候,会专门为那些容易忽略的约束留出位置:有没有性能指标?要不要兼容旧版本?涉及用户数据,有没有权限和安全要求?这些东西哪怕只写一句话,都能在关键时候保住工程质量。AI 不会主动替你思考安全边界,但你把边界写清楚了,它能做得很稳。

4.3 让每条 spec 都能被“判定 OK 或 NOT OK”

我判断一条 spec 写得好不好,唯一的标准是:一个没参与过讨论的新人,能不能在看完这条 spec 后明确地对实现结果说一句“这不对,这里没达到要求”?如果答案是可以,这条 spec 就是合格的。

这要求描述要足够具体。比如“登录功能要支持记住我”,这句话就不合格,因为没法判定;改成“用户勾选记住我登录成功后,服务端返回有效期 30 天的刷新令牌,客户端持久化保存并在会话恢复时自动使用”,这才是可判定的。把 spec 当验收单来写,而不是当需求笔记来写,效果完全不一样。

4.4 该归档就归档,保持变更区的干净

最后一条是运维层面的经验。OpenSpec 的 changes 目录里会不断累积变更提案,如果不定期归档,目录很快就会变成一个越来越大的垃圾堆。归档不是说删掉,而是把已经完成的提案从 active 移到 archived,让它退出当前视图,但仍然保留历史记录。

我自己的习惯是,每个合并到主分支的变更,在发布后立即归档。这样好处很明显:当你想知道当前有哪些改动在飞,打开 changes 目录一眼就能看全;当你想查历史决策,去 archived 里翻。干净的状态意味着低的认知负担,这话放在代码里成立,放在需求管理里同样成立。

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

5.1 命令执行报错:先检查是不是没在项目根目录

我在使用过程中遇到最多的报错,其实不是什么高深问题,而是把openspec init执行错了位置,或者在多个项目之间切来切去时,跑到别的目录里去执行命令,结果 CLI 找不到 openspec 目录。遇到这种情况,先看一眼当前目录下有没有 openspec 文件夹,再确认有没有执行过 init。很多时候,问题出在不是工具本身,而是使用习惯。

另外,版本差异也可能导致命令不兼容。不同时期的 OpenSpec CLI,命令名和参数可能会有调整。我的建议是,遇到命令不认识或者参数对不上,先执行openspec --help或openspec <command> --help看当前版本的说明,不要硬记命令,因为工具还在快速迭代阶段。

5.2 spec 写得太多或太少,尺度怎么把握

这个问题几乎每个试用 OpenSpec 的人都会问:一个变更到底拆多少条 spec 合适?我的经验是,以“可独立验证”为准。如果你发现一条 spec 里包含了两个以上的验证点,那就该拆;如果两条 spec 永远只能同时完成同时验证,那就该合并。

举一个反面例子,有次我把“用户资料编辑和头像上传”写进了同一条 spec,结果评审的时候大家都很痛苦,因为两个功能互相纠缠,验收标准写不清楚。后来拆成两条独立的 spec,每个人都轻松了,开发也可以并行。宁可稍微拆多一点点,也不要写成一坨,因为拆开容易合并,写糊了想拆就得重新梳理逻辑。

5.3 AI 依旧理解偏了,多半是 spec 本身有歧义

如果在 AI 按 spec 实现后仍然偏离需求,先不要急着怪 AI,回头看看 spec 里的动词是不是太虚了。像“优化”“提升”“支持更好的体验”这类词,几乎必然导致污染。你可以试着把所有模糊词汇列出来,一个个换成可量化、可观测的表述,通常问题就解决了。

还有一种情况是 spec 之间互相矛盾。比如 A spec 说 token 有效期 30 天,B spec 说 token 在会话结束后立即失效,AI 当然会混乱。这时候需要你人工检查整个 changes 目录下所有 spec 的一致性。OpenSpec 的优势在于所有信息集中在一个目录里,这种矛盾排查起来并不难。

5.4 团队不买账,推行 OpenSpec 的技巧

如果你是团队里第一个想引入 OpenSpec 的人,很可能会遇到抵触情绪,大家会觉得“又多了流程”。我的实际感受是,不要一开始就让全员全流程使用,而是先从一个痛点最明显的项目切入,比如一个频繁被 AI 改错需求的项目,用 OpenSpec 把流程跑通,让效果说话。

其次,尽量把使用成本降到最低。我的做法是先只用 OpenSpec 的目录结构,不去强制所有字段都填,甚至可以先不引入 CLI,纯粹靠模板就能跑起来。等到大家体会到“需求变更有了记录”“AI 输出质量提高了”这些好处后,再逐步把评审、归档这些环节加进来。工具是拿来解决问题的,不是拿来表演流程的,这是我一直提醒自己的话。

5.5 任何时候都适合上 OpenSpec 吗

最后聊一句大实话:OpenSpec 不是银弹,也不是所有项目都需要它。一个很小的个人试验项目,或者一个只有几百行代码的脚本工具,硬套这套规范反而会拖慢节奏。我自己的判断标准是:只要这个变更需要别人 review、需要被记录、需要交给 AI 实现,它就值得走一遍 OpenSpec 的流程。

反过来,如果你一个人闷头写代码,完了就不管了,那 OpenSpec 确实不太必要。规范的价值来自长期积累和多人协作,一个人写给自己看的备注,用不上这么重的仪式感。这一点想清楚,你就不会把工具用变形。

6. 最后,说点工具之外的体会

从第一次接触 OpenSpec 到现在,我最大的变化不是代码写得更快了,而是想问题的方式变了。以前拿到需求,第一反应是“怎么改”,现在会先想“这条需求到底能不能被验证”“背后的约束条件是什么”。这种思维迁移看起来不起眼,但它让我和 AI 协作时的返工率明显下降,也让团队里的沟通从“你猜我想什么”变成了“一起看 spec 对不对”。

如果你也正在被需求歧义、AI 代码跑偏、评审流于形式这些问题困扰,我建议你拿一个小需求试一次 OpenSpec,不用追求一步到位,先从把 proposal 写清楚开始。工具本身很简单,真正值钱的是那份把需求打磨到可以执行的习惯。希望这篇基于个人实操的梳理能帮你在用的过程中少踩几个坑,也欢迎你把我没提到的经验留言分享出来,大家一起把这个流程越用越顺。

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

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

立即咨询