Part V · Engineering & Governance

17 AGENTS.md 当同一个目录里跑着好几个 agent,git 纪律必须写死

已发布 规则文件 165 行 禁用 git 命令 7 条
§1 Mental Model 一句话心智模型

先记住这一句

pi 的 AGENTS.md 不是「代码风格指南」,是一份并发协议。它最核心的一段基于一个具体事实:同一个工作目录里可能同时跑着好几个 pi 会话,各自在改不同的文件。所有 git 规则都是从这一句推出来的。

这是本书里最容易被低估的一章。多数项目的 agent 规则文件写的是「用 2 空格缩进」「别加 emoji」这类偏好;pi 的这份里有相当篇幅在解决一个真实的分布式问题——多个写者共享一个工作区。

推论只有一条,但很硬:任何「作用于整个工作区」的 git 操作都是禁止的,因为它必然踩到别人的未提交改动。

§2 Evidence 代码实证

前提写在开头

AGENTS.md原文 L50
Multiple pi sessions may be running in this cwd at the same time, each modifying
different files. Git operations that touch unstaged, staged, or untracked files
outside your own changes will stomp on other sessions' work. Follow these rules:
注意措辞:不是「可能会有冲突」,而是会踩坏别的会话的工作(stomp on)。前提陈述得越具体,后面的规则越难被模型「灵活理解」。

禁令清单:七条,无例外

AGENTS.md原文 L60–L62
Never run (destroys other agents' work or bypasses checks):

- `git reset --hard`, `git checkout .`, `git clean -fd`, `git stash`,
  `git add -A`, `git add .`, `git commit --no-verify`.
前六条都是「作用域是整个工作区」的操作。第七条 --no-verify 是另一类——它绕过的是 第 16 章 那道 pre-commit lockfile 门禁。

与之配套的是正向要求:只提交你这个会话改过的文件;用显式路径 git add <path>;提交前先 git status 确认只暂存了自己的文件。AGENTS.md:55

rebase 冲突的处理也顺着同一逻辑:只解决自己改过的文件里的冲突;冲突出现在你没改过的文件里,就中止并问用户;永不 force push。AGENTS.md:67

其余规则的共同形状:给出理由,或给出替代动作

规则为什么这样写有效
「改 bug 别降级代码去迁就过时依赖的类型错误,去升级依赖」AGENTS.md:19点名了模型最常见的偷懒路径,并指定了正确动作
「不要硬编码按键判断,加进 DEFAULT_*_KEYBINDINGS 保持可配置」AGENTS.md:23给了具体的落点,不是抽象原则
「别直接改 models.generated.ts,改生成脚本再重新生成」AGENTS.md:24并补了一句「带上重新生成的 diff 总是 OK 的,即使包含无关的上游模型元数据变化」——预先消除了模型的犹豫
「移除看起来是有意为之的功能或代码前,先问」AGENTS.md:21把「不确定时怎么办」显式化
「广泛修改前、编辑没完整看过的文件前、被要求调查或审计时,完整读文件;不要靠搜索片段」AGENTS.md:14针对的是 agent 特有的失败模式:grep 到一处就改

连「怎么跑测试」都规定得极细

「永远不要直接跑完整 vitest 套件」——因为里面含 e2e 测试,一旦环境里存在 endpoint/auth 环境变量就会激活,产生真实的 provider 调用和费用。替代方案给到了具体命令行。AGENTS.md:30

对 packages/coding-agent/test/suite/,规则是用 harness + faux provider,不许用真 provider API、密钥或付费 token。AGENTS.md:34 甚至规定了 issue 回归测试的存放路径与文件命名格式 <issue-number>-<short-slug>.test.ts。AGENTS.md:35

最后一条:冲突时怎么办

AGENTS.md原文 L165
If the user's instructions conflict with any rule in this document, ask for explicit
confirmation before overriding. Only then execute their instructions.
这条解决的是规则文件最尴尬的处境:用户说「跑一下 git stash」时,agent 该听谁的。答案是——先确认,确认后照用户说的做。规则不凌驾于用户,但也不被随口推翻。
§3 Design 设计动机与权衡

为什么「多会话共享工作区」这个前提值得整段规则

常规做法是给每个 agent 会话开一个 git worktree,物理隔离。pi 团队显然选择了不隔离——同一个 cwd 跑多个会话。

好处推得出来:共享工作区意味着共享构建产物、共享 node_modules、共享正在运行的 dev server;一个会话改了类型,另一个会话立刻能看到。对一个 25 万行的 monorepo,重建成本很高,隔离的代价是实打实的。

代价则是必须靠纪律替代隔离——而纪律的执行者是 LLM。所以规则写成了命令级黑名单而不是原则:模型可以误判「这个 git checkout . 应该没事」,但很难误判「这条命令在禁用清单里」。禁令的具体程度,是对执行者可靠性的一种补偿。

这份文件的写法比内容更值得学

通读下来,有效规则都符合同一个模式:不要 X + 因为 Y + 改为做 Z。三段齐全的规则(比如 models.generated.ts 那条)几乎不会被误读;只有「不要 X」的规则容易被模型在边缘情况下自行放宽。

另一个细节是预先消除犹豫。「带上重新生成的 diff 总是 OK 的,即使包含无关的上游模型元数据变化」——这句话存在的原因是:一个谨慎的 agent 看到自己的改动里混进了无关 diff,会停下来问。文档提前回答了这个问题,省掉一次往返。

与 CONTRIBUTING.md 的分工

AGENTS.md 的开头就写明它是给人和 agent 共用的项目规则,而贡献者门槛在 CONTRIBUTING.md(第 18 章)。README.md:50

这个分工是清晰的:AGENTS.md 管「在这个仓库里怎么干活」,CONTRIBUTING.md 管「你有没有资格进来干活」。而 CONTRIBUTING.md 里那句「如果你用 agent,请从 pi 根目录运行,让它自动读到 AGENTS.md」,把两者接了起来。CONTRIBUTING.md:19

§4 Limits 边界与失效条件

检查过并确认:AGENTS.md 中引用的 DEFAULT_EDITOR_KEYBINDINGS 与 DEFAULT_APP_KEYBINDINGS 在锚定 SHA 上确实存在于 packages/coding-agent/src,未构成漂移。

§5 Takeaway 拿走什么
§ Self-check 自测

场景你在 pi 仓库里让 agent「把工作区清干净重来」。按 AGENTS.md,它该怎么做?

看答案

B。两条都在 Never run 清单里,而末尾的 User Override 条款要求:与用户指令冲突时先要求显式确认,确认之后才执行用户的指令。规则不凌驾于用户,但也不被随口推翻。AGENTS.md:165

场景为什么 AGENTS.md 禁止直接跑完整 vitest 套件?

看答案

C。原文:「it includes e2e tests that activate when endpoint/auth env vars are present」。替代方案是 ./test.sh 或指定单个测试文件。AGENTS.md:30

基于 earendil-works/pi @ ac4ac9e(2026-08-07 快照)。
仓库 commit 速度约 428/月,行号引用仅对该 SHA 有效。