Store:在专属仓库中规划
Beta。 Store、引用、工作上下文和 Workset 都是新增功能。命令名、标志、文件格式和 JSON 输出在不同版本之间仍可能变化。下面每一段演练都基于当前构建实际跑过,但升级后请重新阅读本指南。
它解决的问题
Rasen 通常寄居在一个代码仓库里:一个紧挨着你代码的 rasen/ 文件夹,存放着该仓库的规格和变更。
一旦你的规划大过一个仓库,这套就不再合适了:
- 你的工作横跨多个仓库 —— 一个功能同时牵动 API server、web app 和一个共享库。这份规划该放进谁的
rasen/文件夹? - 你的团队在代码诞生之前就做规划,或者规划了一些永远不会成为本仓库代码的东西。
- 需求由一个团队拥有,却被其他团队消费。wiki 上的版本会漂移,而且你的编码智能体反正也读不了它。
Store 就是答案:一个独立的仓库,唯一职责就是规划。它有着你已经熟悉的 rasen/ 结构 —— 规格和变更 —— 外加一个小小的身份文件。你在自己的机器上按名字注册它一次,之后所有普通的 Rasen 命令都能从任何地方在它里面工作。
它的结构
team-plans (a store: planning in its own repo)
├── .rasen-store/store.yaml identity: "I am team-plans"
└── rasen/
├── specs/ what is true
└── changes/ what is in motion
▲
│ registered on each machine by name;
│ shared by pushing/cloning like any repo
┌─────────────┼─────────────┐
│ │ │
web-app api-server mobile-app
(code repo) (code repo) (code repo)
两条规则让一切保持简单:
- 一个 Store 就是一个 git 仓库。 提交、推送、拉取、审查都由你自己来。Rasen 从不自行 clone、sync 或 push 任何东西。
- 声明,而非机制。 仓库可以声明自己与 Store 的关系(见下文)。声明改变的是 Rasen 能告诉你什么 —— 永远不会改变你的命令作用在哪里。
五分钟拥有你的第一个 Store
两条命令,带你从零到一个可用的、Store 作用域内的变更:
rasen store setup team-plans --path ~/rasen-stores/team-plans
Store ready: team-plans
Location: /Users/you/rasen-stores/team-plans
Rasen root: ready
Registry: registered
Next: run normal rasen commands against this store, for example:
rasen new change <change-id> --store team-plans
Share this store by committing and pushing it like any Git repo.
rasen new change add-login --store team-plans
Using Rasen root: team-plans (/Users/you/rasen-stores/team-plans)
Created change 'add-login' at /Users/you/rasen-stores/team-plans/rasen/changes/add-login/
Schema: spec-driven
Next: rasen status --change add-login --store team-plans
这就是全部模型。从这里开始,生命周期正是你所熟悉的 —— status、instructions、validate、archive —— 每条命令都加上 --store team-plans,而每一条打印出来的提示都会替你带上这个标志。Using Rasen root: 这一行总会告诉你命令正作用在哪里。
案例:一个团队,一个规划仓库
一个团队把自己的规格和变更集中放在 team-plans 里,而不是散落在各个代码仓库中。
第一天(搭建它的那个人):
rasen store setup team-plans --path ~/rasen-stores/team-plans \
--remote git@github.com:acme/team-plans.git
git -C ~/rasen-stores/team-plans push -u origin main
传入 --remote 会把 clone URL 记录进 Store 自己的身份文件(.rasen-store/store.yaml),写进初次提交里。此后每一次 clone 一诞生就知道自己从哪儿来,于是健康检查和错误信息能为还没有它的队友打印出一条完整的、可直接粘贴的修复指令。
每个队友(每台机器一次):
git clone git@github.com:acme/team-plans.git ~/rasen-stores/team-plans
rasen store register ~/rasen-stores/team-plans
从那以后,所有人都按名字在同一个规划仓库里工作:
rasen status --store team-plans --change add-login
rasen show add-login --store team-plans
共享工作就是 git,这是有意为之。 你创建的变更在你提交并推送之前只存在于你的 checkout 里 —— 和代码一样。规划因此白得了分支、pull request 和 review,因为 Store 就是一个普通仓库。
把团队的代码仓库接上。 一个把规划完全外置的代码仓库,只需在 rasen/config.yaml 里加一行:
# web-app/rasen/config.yaml
store: team-plans
现在,在 web-app 内运行的每条 Rasen 命令都会作用在 team-plans 上,完全不需要任何标志:
cd ~/src/web-app
rasen status --change add-login
Using Rasen root: team-plans (/Users/you/rasen-stores/team-plans)
...
这个指针是一个回退项,绝不是覆盖:显式的 --store 永远优先;如果该仓库长出了自己真正的规划文件夹,那些优先(并附一条警告,提醒你删掉这个过时的指针)。
案例:跨越团队边界的需求
一个平台团队拥有需求。产品团队在自己的仓库里、用自己的设计,依此构建。一个引用描述这种关系,却不必搬动任何一方的工作。
platform-reqs (store) api-server (code repo)
owned by the platform team owned by a product team
┌──────────────────────────┐ ┌──────────────────────────┐
│ rasen/specs/ │ ◀────────│ rasen/config.yaml │
│ payments/spec.md │ reads │ references: │
│ auth/spec.md │ │ - platform-reqs │
│ │ │ rasen/specs/ │
│ rasen/changes/ │ │ (their own designs) │
│ platform work │ │ rasen/changes/ │
│ │ │ (their own work) │
│ │ └──────────────────────────┘
└──────────────────────────┘
产品团队在自己仓库的 rasen/config.yaml 里声明它依赖什么:
references:
- platform-reqs
引用是只读的上下文。仓库保留自己的 rasen/ 根;工作也留在那里。改变的是:该仓库里的 rasen instructions 现在会包含一份被引用 Store 的规格索引 —— 每条都带一行摘要和精确的抓取命令(rasen show <spec-id> --type spec --store platform-reqs)。在 api-server 里工作的智能体能找到上游的支付需求、引用它们,并在仓库自己的根里写下它的低层设计 —— 不需要任何人到处粘贴上下文。
一个引用可以带上自己的 clone 来源,这样还没有该 Store 的队友会得到一条完整的修复指令,而不是一个死胡同:
references:
- { id: platform-reqs, remote: "git@github.com:acme/platform-reqs.git" }
当你想把规划和代码同时打开,就建一个 Workset。 这是个人且显式的:每个人在自己机器上挑选实际会用到的文件夹。这些本地 checkout 路径的任何信息都不会被提交到共享的规划仓库。
rasen workset create platform \
--member ~/rasen-stores/platform-reqs \
--member ~/src/api-server \
--member ~/src/web-app
你随时可以问的两个问题
"我的配置健康吗?" —— rasen doctor 以只读方式检查当前根及其引用的 Store,每条发现都附一条可粘贴的修复指令:
Doctor
Root
Location: /Users/you/src/api-server
Rasen root: ok
References
- platform-reqs: ok (/Users/you/rasen-stores/platform-reqs)
- design-system: Referenced store 'design-system' is not registered on this machine.
Fix: git clone -- git@github.com:acme/design-system.git '/Users/you/rasen-stores/design-system' && rasen store register '/Users/you/rasen-stores/design-system' --id design-system
"我正在和什么打交道?" —— rasen context 从 Rasen 的声明中组装出工作集:根和它引用的 Store。
Working context for api-server (/Users/you/src/api-server)
Rasen root
api-server /Users/you/src/api-server
Referenced stores
platform-reqs /Users/you/rasen-stores/platform-reqs
Fetch: rasen show <spec-id> --type spec --store platform-reqs
两者都为智能体支持 --json。rasen context --code-workspace <path> 还会额外写出一个 VS Code workspace 文件,包含整个集合 —— 这是该命令唯一会执行的一次写入。
Workset:重新打开你一起工作的那些文件夹
与上面所有内容分开说:大多数人每个工作时段都会把同样几个文件夹一起打开 —— 规划仓库外加两三个代码仓库。一个 Workset 就是这件事的个人化、命名视图,用一条命令在你选定的工具里重新打开。
workset "platform" rasen workset open platform
├── team-plans ~/rasen-stores/team-plans │
├── api-server ~/src/api-server ▼
└── web-app ~/src/web-app all three open in your tool
rasen workset create platform \
--member ~/rasen-stores/team-plans --member ~/src/api-server \
--tool code
rasen workset list
platform (opens in VS Code)
team-plans /Users/you/rasen-stores/team-plans
api-server /Users/you/src/api-server
随后 rasen workset open platform 会启动保存好的工具:编辑器(VS Code、Cursor)打开一个包含全部成员的窗口然后返回。第一个成员是主成员。任何时候都可以用 --tool <id> 覆盖工具。
Workset 被有意设计成非共享状态。它们只存在于你的机器上、从不被提交、也不对工作本身做任何断言 —— 它们只记录你喜欢把哪些文件夹一起打开。删除一个 Workset 永远不会动到成员文件夹。新工具是配置,不是代码:任何能通过 workspace 文件或逐文件夹 attach 标志启动的东西,都可以加到全局配置(rasen config edit)的 openers 键下。
命令如何决定作用在哪里
每条普通命令都按相同方式、依以下顺序解析自己的根:
1. --store <id> you said so explicitly → that store
2. nearest rasen/ a real planning root here → this repo
(walking up from cwd)
3. store: pointer config.yaml declares a store → that store
4. none of the above stores registered on this → error with a
machine? selection hint
no stores registered? → the current
directory
(classic behavior)
Using Rasen root: 这一行(以及 --json 输出中的 root 块)会告诉你处于哪种情况。
已知限制
- Beta 形态。 本页的一切都可能在版本之间变化 —— 名字、标志、文件格式、JSON 键。
- 每台机器上每个 Store id 只能有一个 checkout。 在同一 id 下注册第二个 checkout 会失败,并提示先
store unregister。 - 永不同步 —— 这是设计如此。 Rasen 从不 clone、pull 或 push。陈旧的 checkout 会显示陈旧的规格,直到你自己 pull;引用则实时地从磁盘上现有的内容建立索引。
- 某些命令留在原地。
view、templates、schemas只作用于当前目录 —— 没有--store。 - 单机状态是单机状态。 Store 注册表和 Workset 是本地设置。关于你机器上的任何布局信息都不会被提交到共享的规划中。
- Workset 的两种启动方式。 一个无法通过 workspace 文件或逐文件夹 attach 标志启动的工具,无法作为 opener 被添加。
- Agent JSON 有已知的大小写分割(Store 族键是 snake_case,工作流族是 camelCase)。记录在智能体契约中;统一它被延后到一个版本化的发布。
事物的存放位置
| 什么 | 位置 | 共享? |
|---|---|---|
| 一个 Store 的规划 | <store>/rasen/(规格、变更) |
是 —— 提交并推送它 |
| 一个 Store 的身份 | <store>/.rasen-store/store.yaml |
是 —— 随 Store 一起提交 |
| Store 注册表 | <data dir>/stores/registry.yaml |
否 —— 仅此机器 |
| Workset | <data dir>/worksets/ |
否 —— 仅此机器 |
<data dir> 在所有平台上都是 ~/.rasen。设置 RASEN_HOME 以重新定位它;$XDG_DATA_HOME/rasen 仍被作为 RASEN_HOME 下的兼容性别名所受理。
参考
每条命令的确切标志和 JSON 形态见:CLI 参考(Store、Doctor、工作上下文、个人 Workset)和智能体契约。