这是【DSH 工程哲学】系列的第三篇。第一篇确立了“裁判权收拢到确定性机器”的底线,第二篇讲了如何用 ADR 给 Agent 铸造长期决策记忆。这一篇则要回答许多工程师转型 AI 全栈时最困惑的问题:为什么我把一万字的“团队开发规范大全”反复喂给 Agent,它却依然视而不见、屡屡犯规? 答案不在于提示词写得不够长,而在于我们对文档本身的组织方式,早已不符合 Agent 的阅读机制。

如果你在前两篇的启发下,已经认真在项目里写下了一大份“开发规范”,那么大概率会遇到这样的场景:
为了约束 Agent 不乱改文件、不乱动依赖、不写出注水文档,你把所有规则打包塞进一个巨大的 REPO_GUIDE.md——整整五千字,事无巨细。结果 Agent 每次会话还是我行我素,甚至因为上下文被这份“规范大全”撑爆,连最基本的类型约束都开始出错。
你以为是 Agent 太笨,其实是你把给人类看的文档和给 Agent 读的规则混在了一起。人类的阅读方式是打开目录、按需翻阅;而 Agent 的阅读方式是自动加载、全量进上下文。一份五千字的规范,对人是“参考书”,对 Agent 是“一整页塞满字的水泥墙”。
在 DeepSeek Harness 的工程哲学中,解决这个问题的核心不是“把规范写得更短”,而是建立一套严格的 文档分层体系(Tier Taxonomy)——让每个事实只有一个家,让 Agent 只加载它此刻真正需要的那几行。
一、第一性原理:P3 载体分工原理
在 DeepSeek Harness 源码库 的方法论体系中,这一篇的地基是 P3 载体分工原理(Carrier Separation):
不同性质的信息,必须存放在不同的载体里,且载体之间不互相混装。
按照这一原理,工程师产生的信息可以被分成四类,各有其“家”:
| 信息性质 | 生命周期 | 载体 |
|---|---|---|
| 一次性判断(为什么这样选) | 决策已经做出,记录当时语境 | Agent Notes / ADR |
| 当前事实(现在系统长什么样) | 跟随代码持续更新 | 文档 / 包 README |
| 重复程序(每次都要怎么做) | 反复执行的操作流程 | Skills |
| 恒定约束(永远不允许越界) | 长期有效的不变规则 | Gates / 门禁 |
把这四类信息混装在一个“开发规范大全”里,是绝大多数项目文档腐化的根源:决策理由当成了现状描述、操作流程被当成约束、约束又被写成了建议。Agent 在一个 5000 字的混装文件里,根本分不清哪些是皇帝敕令、哪些是心路历程。
二、家载体分工:AGENTS.md 自动加载 vs README 人读
在 P3 之上,DSH 还建立了一个更精妙的机制——按“谁来读”来分工:
- AGENTS.md(根 + 各子树 + 各包):是 Agent 自动加载的载体。Agent 处理某个路径下的文件时,该路径及所有祖先目录的
AGENTS.md会自动并入上下文,不需要任何人显式提示。治理规则、触发契约、文档标准必须放在这里,否则 Agent 不主动读就不进上下文,治理在机制上落空。 - README(根 + 各包):是 人读契约。它承载 config / semantics / limitations / Model Experience,给人翻阅,也欢迎 Agent 在被显式要求时阅读。但它不是治理规则的载体——因为 Agent 不会主动去读它。
这一分工用一句话概括就是:
想让 Agent 每次都看见的规则,放进 AGENTS.md;想让人类随时查的契约,放进 README。两者不混用。
如果你把“禁止修改其他文件”这条铁律写在 README 里,那么它只对认真读 README 的人类生效,而对自动加载上下文的 Agent 来说,相当于不存在。这是一个经常被忽视、却决定治理是否落空的机制断层。
flowchart TD
subgraph AgentContext["Agent 处理文件时"]
A1[祖先目录 AGENTS.md] -->|自动并入| C[Agent 上下文]
A2[当前目录 AGENTS.md] -->|自动并入| C
end
subgraph HumanRead["人读契约层"]
B1[根 README] --> D[人类按需翻阅]
B2[包 README] --> D
end
E[治理规则] -->|唯一家| A1
E -->|唯一家| A2
F[配置/语义/限制] -->|唯一家| B2
C --> G[每次会话必载<br/>Standing Orders]
D --> H[按需查阅<br/>Config & Semantics]
三、12-Tier 分类法:每个事实一个家
有了“谁来读”的分工,DSH 又进一步把“每种事实放哪个家”做成了一张穷尽的 12-Tier 分层表。这里只摘录其中最关键的几行:
| Tier | 负责承载 | 明确不承载 |
|---|---|---|
| 根 AGENTS.md | 常载 standing orders(每次会话必载,1-3 行每条,链到 home) | 故事、示例、复述 |
| 子树 AGENTS.md | 该子树特定规则 | 根已载的全仓规则 |
| architecture.md | 有序地图:组合、核心包、环、接缝、扩展点 | 类型细节、决策理由、状态标注 |
| Agent Notes | 活动决策记录(当前态现在时) | 迁移计划、验收清单、spec-speak |
| postmortem/ | 事故故事(唯一允许战争叙事层) | —— |
| cookbook/ | 带编号验证步的 how-to | 设计理由(→ note) |
| 包 README | 单包契约:配置/语义/限制/扩展点 | JSDoc 复述、生成目录复述 |
| 生成参考 | 从源码再生成的穷尽英文源 + 新鲜度门禁 | 手编生成源 |
放置速查:bug→postmortem;理由→note;过程→cookbook;类型定义→subsystems;包契约→README;standing orders→根 AGENTS.md + 理由链。
这套表的威力在于“每个事实一个家”(One Home Per Fact):任何一条规则只存在一个权威位置,其它位置一律链接过去。当你发现同一条规则出现在多个地方,就触发了治理警报——因为将来它们必然漂移。
四、词数预算:文档膨胀是 Agent 变蠢的第一诱因
文档分层只是第一步。DSH 还有一道许多人意想不到的硬门禁——词数预算(Wordcount Budgets):
scripts/doc-budgets.manifest.json 为每一份 standing 文档设定了词数上限,任何一份文件超限或缺文件,pnpm run verify-doc-budgets 都会直接判红、非零退出。实测的硬上限包括:
- 根
AGENTS.md≤ 2,080; architecture.md≤ 2,400;packages/AGENTS.md≤ 810、docs/AGENTS.md≤ 1,430;packages/README.md≤ 994;cordis-primer.md600、testing.md1,300、examples/AGENTS.md310。
门禁红了怎么办?DSH 规定按 relocate → condense → raise 的顺序处理:
- Relocate(搬家):把属于别的 tier 的内容搬走,必要时留一行链接;
- Condense(压缩):属于这里但可以更短的内容,压缩;
- Raise(提额):只有内容确实需要这个篇幅时才提高上限,且必须在 PR 里 justify manifest diff——上限过低的预算本身也是一个 bug。
上限是护栏(guardrail),不是压减目标:目标线以下必须保留至少 5% 余量。这套机制的本质是承认一个残酷事实——上下文窗口再大,也是越用越小的;每一词进入 Agent 上下文的文档文字,都在消耗它处理真实问题的注意力。
五、Slop 审计法:拒绝“废话文学”
最后一道防线,是 DSH 用来给文档做“内容卫生”的 Slop Checklist(废话审计清单)。任何文档被写入前,都要过一遍这份清单:
- 重复规则:同一条规则出现在多个家(留一个家,其余链过去);
- 历史叙事:
previously/now/renamed/ PR 号——状态会腐烂,历史属于 commit 与 postmortem; - 状态标注:
implemented!/future:——状态跟着仓库布局与 manifest 走,写在正文里必然过时; - 手抄目录:JSDoc、测试清单、包清单——源码或生成器才是权威;
- 推理转写:逐步实现叙事、测试走查、被拒的局部备选——删除推导路径,只留结果契约;
- 理由复制:同一理由在兄弟方法旁重复——只保留在 owning 能力处一次;
- 段落墙:一段多规则多括号插入语——拆开或降级到它的家;
- 强调通胀:到处都是 bold / CAPS——“没有强调”;
- spec-speak:implemented note 里出现
should/ 迁移计划——implemented 描述“是什么”,不是“应该怎样”。
这条清单的价值在于:它把“什么是好文档”这个主观问题,变成了可以被逐项勾选的客观审计流程。Agent 能写,也必须能审。
六、从原理到实践:明天就能用上的落地动作
这套体系看起来很重,但作为个人或小团队,你只需要做三件小事,就能立刻享受一半的收益:
- 先把规则搬进 AGENTS.md:把要和 Agent 约定的铁律(3-5 条以内),写进根目录的
AGENTS.md,每条一行,链到细节文档。你会发现 Agent 突然“听得懂人话”了,因为它每次会话的上下文里,自动多了这几行。 - 给 README 做减法:把 README 纯化为人读契约(怎么配、什么限制、什么语义),删除一切和 Agent 有关的训诫——那些属于 AGENTS.md。
- 立一条词数红线:给
AGENTS.md设一个 500 词的硬上限,写超了就先删后加。这比任何“精炼文档”口号都有效,因为它把抽象愿望变成了可执行的工程约束。
让规则进入 Agent 的自动加载区,让契约留在人读的参考层——当一个事实只有一个家的时候,文档才不会成为 Agent 的噪音,而是成为它最可靠的行为规范。
🛠️ 本课哲学的实证落地:文档分层与词数治理,作为 AI Coding 工程质量控制元框架 PonyGo 的脚手架能力,为启动期项目内置了「每个事实一个家」的 tier 组织与 machine 化门禁(如
ponygo audit的文档面体检),可参考:https://github.com/lanhui100/ponygo