ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

OpenSpec:让需求文档像代码一样协作与追溯

OpenSpec:让需求文档像代码一样协作与追溯

1. 为什么"文档即代码"喊了这么多年,落地却一直这么难

先说个我自己的真实经历。前两年带一个中大型项目,团队十几个人,需求文档分散在在线文档、本地 Word、聊天记录和几个老同事的脑子里。需求评审会上大家对着一个"最新版"文档聊得热火朝天,结果开发到一半发现文档是一个月前的旧版本,产品经理自己都忘了改过哪几处。那种想砸电脑又无处发泄的感觉,做过大型项目的工程师应该都能共鸣。

后来我们尝试过各种方案:在线协作文档工具、专门的 Wiki 系统、甚至有人用数据库表单去管理需求。但问题始终没有真正解决——文档的变更过程不可追溯、不可 Review、不可回滚。就算工具再先进,本质还是"一个人写了大家看,版本永远靠自觉"。

这就是 OpenSpec 切入的点。它不是又一个在线文档工具,也不是什么重量级的 ALM 平台,而是把"软件规格说明"彻底变成一种可以被 Git 管理、可以被 Code Review、可以进 CI 检查的工程产物。规格文档在你本地就是一串 Markdown 文件,但整体运作起来,它有了一套完整的生命周期:创建、评审、合并、追溯、变更记录,跟代码的协作体验完全对齐。

这篇文章我会完整讲讲 OpenSpec 的核心设计逻辑,然后给出一套从零到一的落地流程,最后聊聊我在真实项目里踩过的坑。如果你也在为"需求文档管理混乱""前后端接口约定靠嘴传""新成员看文档不知道看哪份"这类问题头疼,这篇应该能给你一个有点不一样的解法。

2. OpenSpec 到底做了什么:给 Markdown 文档装上"开发流程"

OpenSpec 的价值很难用一句"它是文档工具"来概括。准确说,它是一个规格文档的工程化管理框架,把文档这件事从"内容创作"变成了"规范变更"。

2.1 核心设计:Markdown + Git + CLI,仅此而已

如果你把这个思路理解透,就会发现 OpenSpec 其实没发明什么新东西,它做的是把三样你已经很熟的工具组合起来,专门服务"规格文档"这个场景:

组件作用为什么选它
Markdown文档编写格式门槛极低、易读易写、Git 文本对比友好,任何工程师都能直接上手
Git版本控制、协作、评审分布式、有完整的权限模型、天然支持分支合并,是当前工程协作的事实标准
CLI脚手架、校验、流程工具把"流程"变成可强制执行的命令,不必依赖人的自觉性

核心思想特别朴实:既然代码可以用分支做隔离、用 PR/MR 做评审、用 CI 做检查,那规格文档为什么不能走同一套流程?OpenSpec 要做的就是把规格文档的书写规范和组织方式固定下来,再用一套 CLI 把这些"开发心智"落到操作层面。

2.2 仓库结构:为什么规格文件要这样摆

我第一次接触 OpenSpec 时不太理解它的目录约束,嫌"管得太宽"。后来用了两周才明白,这种约束正是它价值所在。它把规格仓库组织成了一种"可扫描、可校验、可编译"的状态,而不是一堆 Markdown 的乱葬岗。

specs/ ├── openspec/ │ ├── project.md │ └── components/ ├── capabilities/ │ ├── user-authentication/ │ │ ├── specification.md │ │ └── requirements.md │ └── payment-service/ ├── changes/ │ ├── 2025-01-15-add-sso-login/ │ │ ├── proposal.md │ │ └── tasks.md │ └── 2025-01-20-refactor-payment/

大致分三块:

  • openspec/:放项目级元信息和组件说明,相当于规格的"目录首页"。
  • capabilities/:描述系统"当前具备的能力",每个能力一个目录,内部包含specification.md(能力规格描述)和requirements.md(需求明细列表)。
  • changes/:存放"变更提案"。每个待实现的需求或改动是一个目录,内部有proposal.md(变更说明)和配套的任务拆解。

这个划分的逻辑在于:capabilities/反映的是系统的当前状态,changes/反映的是通向新状态的待办过程。前者是稳态,后者是流量,两者分离,才不会互相污染。

2.3 一份规格文件到底长什么样

说了半天理论,直接看一个我常用的能力规格结构。以"用户认证"这个能力为例,specification.md的骨架大概是:

# Capability: User Authentication ## 概述 系统通过邮箱 + 密码方式认证用户,签发 JWT Token。 ## 核心场景 - SC-1: 用户使用正确凭据登录,返回 access token 和 refresh token。 - SC-2: 用户使用错误密码登录,返回统一的认证错误信息。 ## 对外依赖 - 依赖账号服务(内部服务,HTTP)。 - 使用 Redis 存储 refresh token 状态。 ## 非功能要求 - token 有效期 30 分钟,refresh token 有效期 7 天。 - 登录接口 p99 延迟 < 200ms。

而requirements.md则是把场景拆成可追踪的需求条目:

## REQ-1: 密码登录 - 状态: 已实现 - 优先级: P0 - 场景: SC-1, SC-2 - 验收标准: 1. 输入正确邮箱和密码,返回 200 及 token。 2. 输入错误密码三次后,触发图形验证码。 ## REQ-2: Token 刷新 - 状态: 评审中 - 优先级: P1

这里有个关键点:需求条目必须可以对应到测试场景和验收标准,而不是一句"支持登录功能"就完了。这种强制性的结构化,逼着你把模糊想法说清楚,这是 OpenSpec 帮团队提升文档质量的核心手段。

3. 从零到一:一套可以直接照抄的 OpenSpec 落地流程

理论部分讲完了,下面进入实操。我按一个内部项目的实际推进节奏,分四步讲清楚每个人应该做什么、命令怎么敲、产物长什么样。

3.1 初始化规格仓库:为团队搭好"文档主干道"

第一步是把规格仓库建起来。你完全可以新建一个独立仓库,也可以把它放在主代码仓库的根目录下(我推荐后者,理由后面讲)。

# 如果在主仓库里,先创建 specs 目录 mkdir specs cd specs # 初始化 OpenSpec(伪代码,以实际帮助为准) openspec init

init之后,CLI 会生成一个最小的骨架仓库,包括openspec/目录组织和一份 README,说明这个仓库的用途和命名规范。做完这步,把它提交推送到远端,拉团队的负责人或者核心成员一起看一遍目录结构,确认"什么文件放哪里"的约定。

这个环节最容易犯的错误是"先让每个人都装好环境再开工",这完全本末倒置。先定结构,再补工具。文档仓库本身不需要任何开发者本地环境支持,编辑器 + Git 就够用。

3.2 把已有需求"回填"成能力规格:先建立基线

第一次引入 OpenSpec,最忌讳的是"以后新需求用这套,老需求先不管"。这样做的结果是仓库永远只有两三个新目录,老需求还在线上文档里,文档割裂的问题依旧存在。

正确姿势是:花一到两周时间,把当前系统正在做的、稳定的核心功能,按能力维度回填成规格文件。

举个例子。假设你手头有个电商后台,老需求散落各处。你可以这样梳理:

openspec create capability order-management openspec create capability inventory-service openspec create capability refund-flow

每个命令生成一个能力目录,然后你和产品、测试负责人一起,把老需求拆成specification.md里的场景和requirements.md里的需求条目。回填过程不用追求百分之百覆盖,把当前线上已实现的主要行为描述出来就够了,重点是形成基线。

回填完成后,我把这个基线仓库发给团队,要求所有人以后涉及现有功能变更,先到capabilities/里找对应能力目录,而不是新建一个 Word 文档。这一步做完,文档割裂的问题基本解决了 80%。

3.3 新需求的正确打开方式:从一个"变更提案"开始

基线建好后,新的需求流程就顺畅多了。一次典型的新需求流转是这样的:

  1. 产品经理提出需求:比如要新增"微信扫码登录"。

  2. 用 CLI 创建变更提案:

openspec create change add-wechat-login

此时会生成一个changes/2025-01-15-add-wechat-login/目录,里面有proposal.md和tasks.md。

  1. 在proposal.md里写清楚变更内容:改了哪些能力、新增了哪些需求条目、废弃了哪些旧行为。如果涉及对现有能力规格的修改,要把对应的改动描述写清楚,而不是直接改capabilities/里的文件。

这一步是理解 OpenSpec 的核心关键,我多说两句。规格仓库的capabilities/是"已经合入主干的代码",changes/是"等待合并的分支"。需求评审通过前,你只应该改changes/里的提案,不应该动capabilities/的内容。

  1. 团队评审这个变更提案:Review 的对象是"提案是否清晰地描述了系统行为的改变",而不是"文档格式漂不漂亮"。

  2. 通过评审后,合入变更:用 CLI 的一条命令,把提案里的改动"应用"到capabilities/对应文件上,让能力规格更新到新状态。同时 Git 提交信息完整记录这一次变更。

这个流程走顺之后,你会发现一个变化:文档的变更节奏和代码开发节奏开始同频了。产品经理提交提案,开发在提案的任务清单上领活,测试根据提案里的验收标准写用例,整个链路特别舒服。

3.4 把 OpenSpec 接进 CI:让文档检查成为合并门禁

落地 OpenSpec 只靠团队自觉是不够的,必须有强制手段。CLI 提供了校验命令(如openspec validate或openspec check),我强烈建议把它接入 CI,作为合并请求的一个必检步骤。

# GitHub Actions 示例 name: spec-check on: pull_request: paths: - 'specs/**' jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Validate OpenSpec run: | cd specs openspec validate

加了这个检查后,即使团队里有人对目录结构、格式规范不熟悉,CI 也会直接告诉他哪里有问题。我见过有不少团队把规则写在 wiki 里没人看,但没有人在 CI 报错时敢随便跳过。这就是工程化带来的强制性。

另外强调一个推荐做法:规格仓库放在主代码仓库里,而不是独立仓库。原因很简单:当规格文件与代码在同一仓库时,一个 PR 里能同时看到代码改动和对应的规格改动,评审人不需要在两个仓库之间跳来跳去。那种"代码在仓库 A、文档在仓库 B、两边版本还经常对不上"的痛苦,谁经历谁知道。

4. 团队协作里最容易翻车的几个细节

OpenSpec 这套东西逻辑上很顺,但真用到团队协作里,有几个坑是我实际踩过之后才反应过来的。写出来帮大家提前躲开。

4.1 "规格变更"和"代码变更"的时序问题

最常见的冲突场景是这样的:开发拿到需求后,在changes/里建了提案,但业务方催得紧,开发直接开始写代码了。等代码写完,capabilities/里的规格还没更新,提案也没合并。

这会导致一个很尴尬的局面——代码已经上线,规格还停留在"过去时"。虽然规范上要求"先更新规格再写代码",但现实里紧急需求总是有的。

我的折中方案是:明确两条线。紧急需求可以并行开发,但合并代码分支时,必须同时合并规格变更,否则代码 PR 的 CI 直接不通过。也就是说,规格的滞后可以是短时间的,但不能被"遗忘"。把"规格是否更新"和"代码是否可合并"绑定在一起,是解决这个问题的关键,而不是单纯靠流程约束。

4.2 Review 的粒度:小步提交比憋大招好一万倍

OpenSpec 的提案机制设计上鼓励"小步快跑"。一个提案最好只解决一个完整的需求点,而不是把一个月的需求都堆在一个提案里慢慢写。

我们来对比一下两种做法:

提案策略评审效果实际体验
大提案:一次提交 8 个需求点评审人看完前两个已经忘掉后六个,只能草草通过提案写了三周,Review 十分钟,等于没评审
小提案:一个需求点一个提案评审人 10 分钟能完整理解上下文节奏流畅,甚至可以在提案里直接讨论实现细节

这一点和代码评审的道理一模一样。Review 效果取决于评审单元的大小,提案拆得越小,评审质量越高。我会在团队约定里写死一句话:一个提案的描述,必须能让另一个不在场的同事只看这份文档就能理解改动的全部内容。

4.3 拒绝"文档八股":验收标准要有,但要避免空洞

有些团队把 OpenSpec 引入之后,会走进一个误区:要求每个需求条目都写满完整的验收标准,每条标准都要对应一个测试用例,结果文档写成了论文,光维护验收标准就占了一半工作量。

我的建议是:验收标准按风险级别来决定详略。

  • P0 需求(涉及资金、安全、核心链路):必须写可量化的验收标准,最好能对应到自动化测试。
  • P1 需求(主流程但非关键路径):写清楚正常路径和常见异常路径即可。
  • P2 需求(边缘优化类):一段话说明行为即可,不必刻意拆多条验收项。

举个例子,P0 的"微信登录"需求,验收标准写"使用有效微信授权码调用登录接口,返回 200 及新用户 token;token 有效期与密码登录一致"就足够,没必要再写"点击登录按钮后按钮文字变化"这种 UI 细节。好的规格不是字数越多越好,而是信息密度越高越好。

4.4 谁来维护规格仓库,这个问题得提前想明白

OpenSpec 落地最容易被忽略的问题,其实是"所有权"。如果团队里每个人都觉得"规格仓库是公共的,随手改一下没问题",那用不了一个月,仓库状态就会因为没人负责而腐烂。

我建议每个能力目录指定一个明确的 Owner:这个能力的规格变更,必须由 Owner 评审后才能合入。这个 Owner 通常是该模块的技术负责人,但注意——Owner 的角色是维护规格的一致性,而不是写所有规格内容。他负责把关"这份规格是否准确描述了当前系统行为",具体内容还是由对应需求的开发或产品来写。

有了明确的 Owner,CI 检查和提案评审才真正闭环。否则流程再完善,最终也会因为"查漏补缺的人是谁"这个问题而卡住。

5. OpenSpec 还能怎么玩:一些超出"文档管理"的扩展用法

用熟了之后,OpenSpec 的价值不只是"管文档",它还能和一些工程环节衔接,把规格文档变成更多自动化流程的输入源。

5.1 把规格需求映射到开发任务:tasks.md 的妙用

每个变更提案目录下的tasks.md,我建议按开发任务粒度写。比如"微信扫码登录"提案的任务清单:

## 任务清单 - [ ] 后端: 实现微信 OAuth 授权码换取用户信息接口 - [ ] 后端: 用户表新增 wechat_openid 字段,并加唯一索引 - [ ] 前端: 登录页新增微信扫码入口按钮 - [ ] 联调: 与微信回调域名配置联调登录链路 - [ ] 测试: 补充微信登录自动化用例

这些任务可直接对应到代码仓库的 issue 或看板。proposal.md描述"为什么变、变成什么样",tasks.md描述"怎么落地"。两者分离的好处是,评审提案时可以专注于"做什么",而不被"怎么做"的细节干扰。

5.2 从规格生成测试用例:打通验证链路

既然能力规格里有场景、需求条目有验收标准,那从规格自动生成测试用例的存根,就是水到渠成的事。OpenSpec 生态里有不少辅助工具支持这类扩展,你可以按自己的实际需要集成:

  • 解析requirements.md中每条需求的验收标准,生成测试用例标题列表。
  • 将核心场景导出为 Markdown 表格,供 QA 团队手工用例评审。
  • 在 CI 中比对"需求条目状态"和"自动化测试状态",找出"规格里说已实现但测试未覆盖"的需求。

这条链路跑通之后,规格文档就不再是写完就吃灰的静态文件,它变成了研发流程里一个可被自动读取、可被追踪状态的动态资产。

5.3 与架构决策记录(ADR)结合使用

另一个让我觉得很好用的扩展场景,是把 OpenSpec 的变更提案和架构决策记录结合起来。技术团队通常会用 ADR 记录重要架构选择的背景与取舍,但 ADR 和需求规格经常脱节——架构决策了,但对应的规格没变。

我的做法很简单:在proposal.md里加一个可选的"架构影响"章节,如果这个需求涉及架构层面的选择(比如引入新中间件、改变存储方案、调整接口协议),就写清楚选择的理由和备选方案。这样一份变更提案同时具备了 ADR 的决策记录属性和需求规格属性,评审的时候,技术选型和需求准确性可以一起被审视。

当然,不要强行把这份文档做成四不像。对于大型架构决策,我仍然会单独写一份完整的 ADR,只是在提案里指明"详见 ADR-xxx"。关键是建立引用关系,而不是试图把所有信息塞进一个文件里。

6. 一些真实落地后的总结和补充

最后聊聊我的真实体会。OpenSpec 不是那种装完就能立刻见效的工具,它的价值曲线是前期平缓、中后期陡峭的。最开始的回填基线阶段最痛苦,因为要把散落在各处的需求理解清楚并用结构化文档重新表达;但是当能力规格的基线真正成型后,后续每个新需求的流转效率提升是非常明显的。

对于团队规模,我的判断是:4 人以下的小团队,这套方案可能略显繁琐——几个人平时口头沟通就足够,硬塞流程反而增加负担。但如果你的团队在 10 人以上、有多个职能角色协作、或者需求迭代节奏快,那 OpenSpec 带来的"文档即代码"体验会明显超过传统文档工具。

我实际踩过几个坑,这里再补充几句:

  • 不要一开始就做全量迁移。先把一个新的小需求走通整条流程,让团队感受到"原来文档评审可以这么顺",再逐步回填老需求。一上来就搞大迁移,大概率会收获一堆半成品和怨气。
  • CLI 的校验命令要多用。本地提交前跑一遍validate,比推到远端被 CI 打回要体面得多。这条没什么技术含量,但能显著减少无谓的往返。
  • 规格文档不是写给老板看的汇报材料。它的读者是下一个接手的工程师、下个月来检查的测试、以及明年你自己。写的时候永远优先考虑"信息是否准确"和"能否被准确执行",而不是"读起来是否顺滑"。

把我最后想说的浓缩成一句:OpenSpec 本质上不是工具,而是一套让团队"在动手前先想清楚、在动手时能追踪、在动手后可追溯"的协作纪律。工具只是把那套纪律固化成了流程,真正让文档管理发生质变的,是整个团队对这个纪律的认同和执行。

如果你正在被需求文档混乱、接口约定靠嘴传的问题折磨,拿一个小项目试试 OpenSpec 的提案流程,跑通一个完整的需求闭环,你会回来感谢自己这个决定的。

RELATED READING

延伸阅读

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