乐于分享
好东西不私藏

AI 编程助手跨仓库协作时,需求该放哪?OpenSpec v1.5.0 的 Store 模式给出答案

AI 编程助手跨仓库协作时,需求该放哪?OpenSpec v1.5.0 的 Store 模式给出答案

Spec · Store · 跨仓库 · v1.5.0 · Fission-AI/OpenSpec —— 58K star 的规约驱动框架用一个新的 Store 概念,把「在哪规划」 和「在哪编码」彻底分开了。

一页概览:先对齐再编码

OpenSpec 是一个规约驱动的开发(SDD)框架,定位在 AI 编程 助手与你之间。传统上,你跟 AI 说「帮我加个暗色模式」,AI 可能直接写 400 行代码,结果方向不对。OpenSpec 的做法是: 你先用 /opsx:propose 写一份简短提案(proposal),AI 据此 生成规格(specs)、设计(design)和任务清单(tasks), 你确认后再执行。整个工作流跑在 openspec/ 目录下—— specs 描述系统当前行为,changes 存放每项变更的提案与 增量规约,变更完成后通过 archive 合并回 specs。

它用 TypeScript 编写,以 npm 包形式分发,支持 25+ 款 AI 编程工具(Cline、Codex、Cursor 等)。这个定位让它既不像 GitHub Spec Kit 那样笨重,也不像 Kiro 那样绑定特定 IDE, 而是一个轻量的、与工具无关的「对齐层」。

跨仓库时代的规划困境

OpenSpec 的标准布局是在项目根目录下放一个 openspec/ 文件夹,里面装着 specs 和 changes。对一个 单体应用来说,这已经够好——规划文件和代码文件同在一个 仓库里,改代码和改需求一样方便。

但当工作跨越多个仓库,问题就来了。一个功能可能同时涉及 API 服务器、前端 Web 应用和一个共享库——这时候究竟把 规划文件放到哪个仓库的 openspec/ 下面?放到 API 仓库, 前端开发者就看不到;放到前端仓库,后台那边又找不到。 团队里常出现的解法是:每人各自在本地放一份副本,或者 在 Wiki 里维护需求文档——结果要么版本漂移,要么 AI 编程助手根本读不到。

更大的问题是「规划先于代码」的场景。你还在讨论需求阶段, 代码仓库还没建,但规划已经开始了。或者某些需求永远不会 变成某个仓库的代码(例如安全合规策略)。传统做法只能在 文档工具里维护,然后人工同步到各团队的代码仓库——效率低、 易出错。v1.5.0 的 Stores 功能就是为这类场景设计的。

Store:独立的规划仓库

Store 的核心思路很直接:创建一个独立的 Git 仓库,它的 全部职责就是存放规划文件。这个仓库拥有和普通项目一样的 openspec/ 结构(specs + changes),外加一个身份文件 .openspec-store/store.yaml 标识自己是一个 Store。

建立 Store 只需要两个命令。第一,在你的机器上创建并注册:

openspec store setup team-plans --path ~/openspec/team-plans

这会在本地生成 Store 目录,注册到本地配置中。第二,创建 变更:

openspec new change add-login --store team-plans

之后所有操作——statusvalidatearchive——只要 带上 --store team-plans 就可以对 Store 中的规划进行操作。 Store 本身只是一个普通的 Git 仓库,你可以 push 到远程、 开分支、走 PR 评审,和代码仓库的协作流程完全一致。

更灵活的关联方式:如果代码仓库需要引用 Store 中的规划, 只需在它的 openspec/config.yaml 里加一行:

store: team-plans

这样在这个代码仓库中执行 OpenSpec 命令时,默认就会指向 team-plans。还有一种更松散的关联叫 references, 代码仓库可以声明自己「引用了」某个 Store,这时 AI 助手 在生成指令时会把 Store 中的 specs 摘要纳入上下文,但变更 仍然在该代码仓库的本地 openspec/ 中管理——适合平台团队 定义需求、产品团队各自实现的模式。

Worksets 是另一个配套功能。它让你把多个目录(Store + 几个代码仓库)打包成一个命名的集合,一行命令就能在 编辑器里同时打开:

openspec workset create platform \
  --member ~/openspec/team-plans \
  --member ~/src/api-server \
  --member ~/src/web-app
openspec workset open platform

声明式关联与本地优先

Store 模式的设计有两项核心原则,决定了它的行为边界。

第一,Store 只是一个普通 Git 仓库。OpenSpec 不会自动 clone、sync 或 push。你通过 store register 把一个已有 Git 目录注册为 Store 后,所有读写操作都发生在本地文件系统 上。这意味着规划文件在你未 commit 之前只有你可见,分支策略、 PR 流程和你用 Git 的方式完全一致。团队协作靠的是 Git 本身, 不是 OpenSpec 的同步逻辑。

第二,关联是声明式的,不是机械的config.yaml 中的 store: team-plansreferences: [team-plans] 只是改变了 OpenSpec 在生成指令时「能看到什么」,而不是 「命令在哪里执行」。当你在代码仓库里运行 openspec status 时,命令会按以下顺序确定操作根目录:

1. --store <id>             显式指定 -> 直接使用该 Store
2. 最近的上层 openspec/     本地有规划根目录 -> 用本地的
3. config.yaml 中的 store   指向一个 Store -> 用该 Store
4. 未命中                   报错或使用当前目录(经典行为)

这种层级解析让「一个命令该作用于哪个规划」的决策透明化, 每次执行都会打印 Using OpenSpec root: 提示当前根目录。

另一个值得关注的实现细节是 openspec doctoropenspec context 命令。前者会检查当前根目录及其引用的 Store 是否健康,对未注册的 Store 给出包含 clone 命令的 修复提示;后者则汇总当前工作上下文的完整视图,包括根目录、 引用的 Store 列表及其获取指令。这两个命令都支持 --json 输出,方便 AI 编程助手直接解析。

从架构上看,Store 把 OpenSpec 的「规划层」从代码仓库中 独立出来,但并未引入新的同步机制或网络调用。它的 可扩展性来自于 Git 本身的分布式能力,而使用体验的 一致性来自于命令行统一的路由解析。这是典型的「薄层封装」 思路——底层借 Git 的力量,上层给出一套语义清晰、 AI 友好的命令接口。