团队中的 OpenSpec
其他指南中的所有内容无论你是单人开发还是二十人团队都适用。团队场景下不同的只是边缘问题:规范存放在哪里、团队成员如何评审方案、以及这些内容如何适配我们已有的拉取请求(PR)流程?
简单来说:变更只是文件,OpenSpec 从不触碰 git。因此它能适配你现有的工作流,而非替换它。本页将介绍经过验证的适用规范。
一条规则:OpenSpec 不触碰 git
OpenSpec 仅读写 openspec/ 目录下的纯 Markdown 文件。它永远不会在你的项目中执行提交、创建分支、推送或拉取操作,也不会自行克隆或同步存储库(store)。这意味着:
- 你可以像提交普通源代码一样提交
openspec/目录。 规范、进行中的变更和归档内容都属于你项目的历史记录。(没错,提交整个文件夹即可——详见常见问题。) - 变更是一个可以像代码一样做版本控制的文件夹。
openspec/changes/add-dark-mode/本质上就是分支上的普通文件。 - 以下所有内容都是约定俗成的规范,而非强制要求。 OpenSpec 不会强制你按这种方式操作,只是这种适配方式最为顺畅。
日常流程循环
适配良好的工作流会将变更映射到分支和拉取请求上:
git switch -c add-dark-mode 按常规创建分支
│
/opsx:propose add-dark-mode 起草方案(包含提案 + 规范 + 任务)
│
评审方案 在编写任何代码前阅读方案——详见《评审变更》
│
/opsx:apply 构建实现;产物与代码变更同步完成
│
git commit && open a PR PR 中包含规范差异和代码
│
团队成员评审、合并
│
/opsx:archive 将差异合并到 specs/,将变更文件夹移至归档目录方案和代码位于同一个分支中并行存在,因此团队成员可以同时评审两者;六个月后,归档的规范仍然能解释代码为何是当前这个样子。
在拉取请求(PR)中评审规范
团队在此处能切实感受到收益。当 PR 包含变更的差异规范时,评审者会获得原始代码 diff 永远无法提供的内容:用自然语言描述本次变更预期达成的目标,而这发生在他们阅读任何一行代码之前。
给评审者的建议评审顺序:
- 阅读
proposal.md—— 本次变更要解决的问题和范围是否正确? - 阅读
specs/下的差异规范 —— “完成”的定义是否准确?(这就是《评审变更》中提到的两分钟快速评审流程,现在在 PR 中即可完成。) - 再阅读代码 diff —— 代码是否完全实现了上述要求?
如果评审者不同意该方案,可以直接针对提案提出异议,成本极低,无需再在 300 行代码的范围内反复争论。你可以将差异规范放在 PR 描述的开头,或指向变更文件夹,让评审者首先查看这部分内容。
归档时机
归档操作会将变更的差异合并到主 openspec/specs/ 目录中,同时将变更文件夹移动到 openspec/changes/archive/YYYY-MM-DD-<name>/ 路径下。由于 specs/ 是共享事实来源,因此归档时机在团队协作中非常重要。以下是两种可行的规范:
- PR 合并后再归档(推荐)。 分支承载着进行中的变更;一旦变更合并到主分支,即可在此时执行归档(通常是一个极小的后续提交,或通过定时清理完成)。这样可以确保共享的
specs/目录仅随实际已上线的变更向前更新。 - 在 PR 内部归档。 这种方式对小型团队更简单:添加代码的同一个 PR 同时完成同步和归档。代价是
specs/的差异和代码差异会同时提交,可能导致 PR 内容更冗杂。
选择其中一种方式并保持统一。无论选择哪种,/opsx:archive 都会检查任务是否全部完成,并优先提示同步,避免未完成的变更被意外合并。
两人并行开发多个变更
由于每个变更都是独立的文件夹,因此不会产生冲突:
- 不同变更、不同负责人——完全没问题。
add-dark-mode和rate-limit-login是不同分支上的独立文件夹,在两者都完成归档之前不会互相影响。 - 一个变更、一个负责人。 两个人编辑同一个变更文件夹时产生的冲突,和两个人编辑同一个文件的冲突完全一致。请确保一个变更仅由单个作者负责,或将其拆分为两个变更(这也是合理控制变更规模的另一个原因)。
- 冲突只会出现在
specs/目录中。 如果两个变更都修改了同一个需求,归档第二个变更时会在openspec/specs/…/spec.md产生冲突——你可以像处理普通合并冲突一样解决它,保留符合实际情况的需求描述。这种情况非常罕见,而且这恰恰是特性而非缺陷:这是 git 在提示你,两个变更对系统行为的预期存在分歧。
当规划内容超出单个代码仓库的承载范围
以上所有内容都默认假设规划内容存放在代码仓库自身的 openspec/ 目录下,这是最合理的默认设置。当你的规划确实需要覆盖多个仓库或多个团队时——例如一个功能涉及三个服务,或需求由一个团队负责、其他团队消费——就可以使用测试版的 stores(存储库) 功能:规划内容会获得独立的仓库,所有代码仓库都可以指向该仓库。你可以先阅读存储库用户指南了解详情。