ops 放哪:独立仓还是放进项目
一句话判断标准,加上独立 ops 仓的三个代价和补法
判断一份文档放哪,只问一句:这份内容会不会因为改代码而需要跟着改?会,放代码仓;不会,放 ops 仓。 组织档我用独立的 ops 仓,但它有三个代价:agent 看不见、跟代码绑定的文档会过时、跨仓相对链接会断。每一个都要提前补上。
判断标准
| 例子 | 会因为改代码而改吗 | 放哪 |
|---|---|---|
| 一个功能的 spec 和实现计划 | 会 | 代码仓 |
| “怎么恢复本地数据库”,步骤依赖 Makefile | 会 | 代码仓 |
| 两个仓库共用的命名规范、权限分工 | 不会 | ops 仓 |
| 一次事故的复盘 | 不会,复盘写的是已经发生的事 | ops 仓 |
| 一次技术选型调研 | 不会 | ops 仓 |
一篇复盘经常同时产出两样东西:复盘本身放 ops 仓;它要求修改的 runbook 或检查脚本,放回代码仓。
三档各放哪
| 档位 | ops 放哪 | 说明 |
|---|---|---|
| 小工具 | 不需要 | README + 一页 CLAUDE.md |
| 产品 | 仓库内 docs/ | specs、plans、adr、runbooks、retros,加上 .claude/ |
| 组织 | 独立 ops 仓 | 代码仓保留 spec、plan 和跟代码绑定的 runbook |
什么时候拆出独立的 ops 仓
出现下面任何一种情况,就该把 ops 从代码仓里拆出来:
- 第二个代码仓库出现了,而且要共用决策
- 代码仓是一个上游开源项目的 fork,或者要开源,而你又有不该公开的治理文档。ops 内容放进去,要么和上游合并冲突,要么开源前得逐条清理
- 有些内容只该让一部分人看到:客户、商业、权限清单、事故细节
- 有不写代码的协作者要读写这些文档
我是第二条和第三条同时成立:其中一个代码仓就是 fork,复盘里又有不能公开的细节。
独立 ops 仓的三个代价和补法
1. agent 看不见
OpenAI 在《Harness engineering》里说得很直接:仓库之外的东西,对 agent 来说等于不存在。你在代码仓里开会话,Claude 默认只能读这个仓库,ops 仓里写得再好,它也不知道。
补法分两步:
在代码仓的 CLAUDE.md 里写几行指针,告诉它规则在哪、什么时候该去读:
## 组织规则在 ops 仓
- 跨仓决策:https://github.com/<组织>/<ops 仓>/tree/main/decisions
- 本机路径:~/work/org-ops(已加入 additionalDirectories)
- 涉及命名、权限、发版的改动,动手前先读 decisions/ 里相关的 ADR在代码仓的 .claude/settings.local.json 里,把 ops 仓加进可访问目录。路径因人而异,所以放在不进 git 的 local 文件里:
{
"permissions": {
"additionalDirectories": ["/Users/you/work/org-ops"]
}
}注意,additionalDirectories 只给文件读写权限,不会加载 ops 仓里的 CLAUDE.md、skill 和 agent 定义。要用 ops 仓里的 skill 和 subagent,改用 claude --add-dir ~/work/org-ops 启动;连它的 CLAUDE.md 也要加载,还得设环境变量 CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1(见官方文档)。
2. 跟代码绑定的文档会过时
我吃过一次亏:一份数据库恢复手册放在 ops 仓,写着“Makefile 的 reset 会先备份”,还附了检查命令。代码仓里的 Makefile 早被一次上游合并改掉了,备份步骤已经不在,手册完全不知道。
补法:
- 会因为改代码而改的文档,搬回代码仓,和代码在同一个 PR 里修改、审查
- 文档里的“检查步骤”改成 CI。与其写“请确认 Makefile 里有 pg_dump”,不如让 CI 每次都断言一遍(做法见护栏体检)
3. 跨仓相对链接会断
代码仓里曾经有 10 处 ../org-ops/... 这样的相对链接,在我本机的主目录里点得开,换个地方就全断了:
- 在 worktree 里:
claude --worktree把 worktree 建在仓库内的.claude/worktrees/<名字>/下,../指向的已经不是原来那个位置 - 在 GitHub 网页上:相对路径只在同一个仓库里解析
- 在云端 agent 里:云端会话只克隆了这一个仓库
补法:跨仓引用一律写完整 URL,再让园丁 agent 定期检查失效链接。先把现有的找出来:
grep -rn --include='*.md' '](\.\./' .它会列出所有向上跳的相对链接,逐个看哪些跳出了仓库。详见跨仓链接用完整地址。
外加一条:模板复制会漂移
第二个组织的 ops 规则文件,最初是从第一个组织复制过来的。半年后一查,里面 6 处引用指向不存在的文件;两边的“下次 review 日期”一字不差,而且都已经过期半年。从复制出去那一刻起,两份就开始各自漂移。
补法:共用的部分做成可继承的模板(插件),各组织只写自己特有的部分。做法见让 ops 和项目一起进化,事故见模板复制后会各自漂移。
替代方案:ops 作为目录放进主代码仓
适合有多个代码仓、有 fork、有保密内容的组织。权限可以单独控制,不写代码的人也能参与。代价就是上面三条,要一条条补上。这是我的选择。
文档归属表
| 文档 | 放哪 | 命名 |
|---|---|---|
| Feature spec(开头一节写 intent) | 代码仓 docs/specs/ | YYYY-MM-DD_<slug>.md |
| 实现计划 | 代码仓 docs/plans/ | YYYY-MM-DD_<slug>-plan.md |
| 跟代码绑定的 runbook | 代码仓 docs/runbooks/ | <topic>.md |
| 跨仓、组织、商业决策 | ops 仓 decisions/ | ADR-NNN_<topic>.md |
| 协作剧本 | ops 仓 playbooks/ | <topic>.md |
| 一次性调研 | ops 仓 research/ | YYYY-MM-DD_<topic>.md |
| 复盘 | ops 仓 retros/ | YYYY-MM-DD_<event>.md |
单仓产品把以上全部放进仓库自己的 docs/,ADR 放 docs/adr/。
一个 ops 仓的骨架:
org-ops/
├── CLAUDE.md 一页:这个仓放什么、红线、ops agent 是谁
├── decisions/ ADR
├── playbooks/ 协作剧本
├── research/ 一次性调研
├── retros/ 复盘
└── .claude/
├── settings.json 权限规则;可选的 agent 字段
└── agents/org-a-ops.md ops agent 定义,名字在所有组织里唯一