长文

教Agent读懂家规:每个事实一个家的文档分层之道

【DSH 工程哲学】第3篇:从 12-Tier 分层到词数预算,揭秘 DeepSeek Harness 如何让文档成为 Agent 的长期行为规范。

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

DSH 文档分层与家规治理隐喻插图

如果你在前两篇的启发下,已经认真在项目里写下了一大份“开发规范”,那么大概率会遇到这样的场景:

为了约束 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.md 600、testing.md 1,300、examples/AGENTS.md 310。

门禁红了怎么办?DSH 规定按 relocate → condense → raise 的顺序处理:

  1. Relocate(搬家):把属于别的 tier 的内容搬走,必要时留一行链接;
  2. Condense(压缩):属于这里但可以更短的内容,压缩;
  3. 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 能写,也必须能审。


六、从原理到实践:明天就能用上的落地动作

这套体系看起来很重,但作为个人或小团队,你只需要做三件小事,就能立刻享受一半的收益:

  1. 先把规则搬进 AGENTS.md:把要和 Agent 约定的铁律(3-5 条以内),写进根目录的 AGENTS.md,每条一行,链到细节文档。你会发现 Agent 突然“听得懂人话”了,因为它每次会话的上下文里,自动多了这几行。
  2. 给 README 做减法:把 README 纯化为人读契约(怎么配、什么限制、什么语义),删除一切和 Agent 有关的训诫——那些属于 AGENTS.md。
  3. 立一条词数红线:给 AGENTS.md 设一个 500 词的硬上限,写超了就先删后加。这比任何“精炼文档”口号都有效,因为它把抽象愿望变成了可执行的工程约束。

让规则进入 Agent 的自动加载区,让契约留在人读的参考层——当一个事实只有一个家的时候,文档才不会成为 Agent 的噪音,而是成为它最可靠的行为规范。


🛠️ 本课哲学的实证落地:文档分层与词数治理,作为 AI Coding 工程质量控制元框架 PonyGo 的脚手架能力,为启动期项目内置了「每个事实一个家」的 tier 组织与 machine 化门禁(如 ponygo audit 的文档面体检),可参考:https://github.com/lanhui100/ponygo

本文目录 本文由 Daniel Ma & AI协同编辑

本文要点

  • 01 一、第一性原理:P3 载体分工原理
  • 02 二、家载体分工:AGENTS.md 自动加载 vs README 人读
  • 03 三、12-Tier 分类法:每个事实一个家