助手每次对话读到的不只是当场那几句话。写在输入里的一句错话,它会照着做,而且明文摆在那里,评审时少有人质疑。
新人第一天,关掉聊天记录,助手只凭仓库里的文件,能不能产出符合团队习惯的代码?
答「不能」,说明约定还在人脑里或靠口口相传。要补的是文件,不是再开一次会。
三层不是三种风格,是三种寿命。根那层改一次,之后每一次对话都受影响,所以那里只放真的到处都算数的短句;改动层一次一换,写得多具体都不亏。
| 层 | 放什么 | 什么时候生效 | 落在哪 |
|---|---|---|---|
| 根 | 跨模块都必须成立的短句 | 每次对话,整仓都算 | AGENTS.md |
| 目录 | 只在某一类文件上成立的做法 | 匹配的文件进入上下文时 | 规则文件 |
| 改动 | 这一次要做什么、怎么验收 | 本次改动期间 | specs/、changes/ |
判落点只问一句:删掉它,下一次不相关的任务会不会因此变糟。同一层里还要选做成哪一种落点——仓库说明、规则、钩子、命令、技能、子智能体六种,逐项对照见规则页的总表。
三层在目录上分得开:根那层只有 AGENTS.md,目录那层与其余落点都在工具自己的配置目录下,改动那层是 specs/ 与 changes/。注释写的是这份文件什么时候被读到。
仓库根目录/ ├── AGENTS.md # 根 · 每次对话都读,约 110 行 ├── CLAUDE.md # 根 · Claude Code 的入口,正文只有 @AGENTS.md ├── .cursor/ │ ├── rules/backend-tests.mdc # 规则 · globs 命中 backend/**/*_test.go 才加载 │ ├── skills/check-scope/SKILL.md # 命令或技能:看有没有 disable-model-invocation │ ├── agents/verifier.md # 子智能体 · readonly: true │ └── hooks.json # 钩子 · version: 1,由它调起 hooks/ 下的脚本 ├── .claude/ │ ├── rules/scope-tests.md # 规则 · 用 paths(YAML 列表),不是 globs │ ├── skills/check-scope/SKILL.md │ ├── agents/verifier.md # 子智能体 · tools: Read, Grep, Glob │ └── settings.json # 钩子 · 写在 hooks 字段里,不是 hooks.json ├── .trae/ │ ├── rules/scope-tests.md │ ├── commands/check-scope.md # 命令 · 独立目录,不在 skills/ 下 │ ├── skills/trace-retrieval/SKILL.md │ ├── agents/verifier.md │ └── hooks.json ├── specs/ # 改动层 · 可执行规约,一次任务一换 ├── changes/ └── docs/decisions/ # 决定的来历,不进根文件
两种工具并存时,同一条约束只在一处写正文,另一处用引入或链接——写两处时由工具决定哪一份生效,见 AGENTS.md。每个落点页各有一支只画自己的目录结构。
场景:给「按租户导出」这个需求写一次改动,从上到下会用到三层的落点。
AGENTS.md 里「查询只绑定会话中的 scope_id」——写一次,之后每次对话都在;目录那层出的是改 *_test.go 时才加载的成对断言规则;改动那层出的是 specs/ 里这次的验收条目,做完就换下一批。
AGENTS.md——200 行的上限很快就破。
wc -l AGENTS.md 检查。超了先删,不新开一节放背景。docs/。每加一条之前,先决定删哪一条。仓库说明只增不减,半年后没人读完它,它就从约束退化成背景噪音。
缺一条,助手最多做错一次,有人发现就补上了。留一条过期的,助手会照它做,评审时谁也不质疑——一份写着「接口仍是 v1」的说明,能让全组按错的字段名写半个月。