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
之后所有操作——status、validate、archive——只要
带上 --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-plans 或 references: [team-plans]
只是改变了 OpenSpec 在生成指令时「能看到什么」,而不是
「命令在哪里执行」。当你在代码仓库里运行 openspec status
时,命令会按以下顺序确定操作根目录:
1. --store <id> 显式指定 -> 直接使用该 Store
2. 最近的上层 openspec/ 本地有规划根目录 -> 用本地的
3. config.yaml 中的 store 指向一个 Store -> 用该 Store
4. 未命中 报错或使用当前目录(经典行为)
这种层级解析让「一个命令该作用于哪个规划」的决策透明化,
每次执行都会打印 Using OpenSpec root: 提示当前根目录。
另一个值得关注的实现细节是 openspec doctor 和
openspec context 命令。前者会检查当前根目录及其引用的
Store 是否健康,对未注册的 Store 给出包含 clone 命令的
修复提示;后者则汇总当前工作上下文的完整视图,包括根目录、
引用的 Store 列表及其获取指令。这两个命令都支持 --json
输出,方便 AI 编程助手直接解析。
从架构上看,Store 把 OpenSpec 的「规划层」从代码仓库中 独立出来,但并未引入新的同步机制或网络调用。它的 可扩展性来自于 Git 本身的分布式能力,而使用体验的 一致性来自于命令行统一的路由解析。这是典型的「薄层封装」 思路——底层借 Git 的力量,上层给出一套语义清晰、 AI 友好的命令接口。
夜雨聆风