项目文档的目标不是拥有完整的文档目录,而是让人和 Agent 在需要时找到完成任务所需的目标、约束、理由和验证方式。
代码能表达当前实现,却常常无法回答为什么存在某个边界;聊天和会议能传递背景,却很难稳定进入下一次任务。好的文档体系把这些非显而易见的信息放进可发现、可追溯、可更新的位置,同时避免复制代码和配置已经明确表达的事实。
从问题开始,而不是从文档清单开始
只有当信息确实需要长期存在时,才创建它的权威位置。先问:
- 谁在什么任务中需要这条信息?
- 代码、Schema、配置或测试是否已经能可靠回答?
- 信息变化时,谁会触发更新?
- 如果写错或过时,会造成什么后果?
- 入口文档怎样让读者在正确条件下找到它?
如果一个答案只服务当前任务,应放在 Issue、计划或 Pull Request 中;如果它能从 package.json、类型或 --help 直接获得,就让环境继续做事实源。把这些内容复制到长文档,只会制造容易失效的缓存。
文档最值得保存的是环境无法直接告诉你的内容:
- 产品目标与明确非目标;
- 业务术语和边界;
- 难以从代码看出的架构理由;
- 权限、安全和兼容约束;
- 完成任务的验收标准;
- 部署、恢复等必须按顺序执行的操作。
一条信息只保留一个事实源
“唯一事实源”不是要求所有信息都放进同一个文件,而是同一种事实只由一个位置负责。
| 信息 | 优先事实源 |
|---|---|
| 依赖和脚本 | 包管理配置、任务脚本、锁文件 |
| 数据结构 | Migration、Schema、类型与约束 |
| HTTP 接口 | OpenAPI 或生成它的权威代码 |
| 当前行为 | 代码和可重复测试 |
| 业务词义 | CONTEXT.md 或领域词汇表 |
| 产品范围 | PRODUCT.md 或产品规格 |
| 当前系统结构 | ARCHITECTURE.md |
| 重要技术选择的理由 | ADR |
| 阶段和交付顺序 | ROADMAP.md 或任务系统 |
| Agent 工作规则 | AGENTS.md |
| 生产操作与恢复 | Runbook |
文档与运行证据冲突时,应先确认实现偏离了设计,还是文档已经过时,不能默认选择更方便的一边。
兼容入口也不应复制正文。例如不同 Agent 需要读取不同文件名时,可以让 CLAUDE.md 只指向 AGENTS.md,或使用受支持的链接机制,让规则只在一个地方维护。
用渐进披露组织上下文
Agent 不应在每次任务开始时读取所有产品、架构、安全和运维资料。文档入口应像路由器:先提供所有任务都会用到的最小信息,再为不同分支提供清晰指针。
仓库入口
├── README:项目是什么、怎样开始、文档在哪里
├── AGENTS:怎样在仓库中安全工作
├── 产品任务 → PRODUCT / 规格 / 验收标准
├── 领域任务 → CONTEXT / 对应模块文档
├── 架构任务 → ARCHITECTURE / 相关 ADR
├── API 任务 → OpenAPI / 契约测试
└── 生产任务 → Runbook / 发布与恢复流程一个有效的指针要同时说明“资料是什么”和“什么时候读取”:
- 修改文章发布规则时,先读 `docs/content.md`。
- 变更模块边界、数据所有权或外部依赖前,检查 `ARCHITECTURE.md`
和相关 `docs/adr/`。
- 执行生产发布、迁移或恢复时,按对应 Runbook 操作。“更多信息见 docs/”没有触发条件,读者仍需扫描整个目录。反过来,把所有专题规则塞进 AGENTS.md 又会让每个任务承担无关上下文。好的指针让不同任务只加载对应分支。
每类文档只回答一种主要问题
README:建立方向感
README 应让新读者快速知道:
- 项目解决什么问题、当前处于什么状态;
- 怎样完成最小启动或验证;
- 主要目录和详细文档从哪里进入;
- 哪些能力尚未实现,避免把计划当成现状。
它是入口,不是所有专题的汇总。详细产品范围、架构、设计系统和内容工作流应通过带触发条件的链接披露。
PRODUCT 与功能规格:定义结果
产品文档回答为谁解决什么问题、成功是什么、明确不做什么。具体功能规格则把目标转成可观察行为、边界条件和验收标准。
有效验收标准可以由测试、界面或运行证据判断:
当文章 status 为 draft 时,构建成功,但页面、搜索索引、RSS 和
sitemap 都不包含该文章。“支持草稿”“体验良好”无法区分完成与未完成,会让人和 Agent 提前结束任务。
CONTEXT:固定领域语言
词汇表只定义项目中的业务概念及容易混淆的近义词,不存实现步骤。比如“归档视图”是文章按时间组织的浏览方式,而不是独立内容类型;这条定义应在产品、代码和讨论中保持一致。
当术语变化时,先更新权威定义,再检查接口、类型和文案,而不是在多个说明中分别改写。
ARCHITECTURE:描述当前结构
架构说明回答系统有哪些模块、它们拥有什么数据、通过哪些 interface 协作,以及外部依赖藏在哪些 seam 后面。
它描述当前有效结构,不承担每个选择的完整历史。难以撤销、令人意外且存在真实权衡的选择进入 ADR,由架构说明链接到相关决定。
契约:让边界可校验
OpenAPI、事件 Schema、数据库约束和类型比自然语言更适合表达精确结构。说明文档补充业务语义、授权规则和兼容策略;测试证明实现是否满足契约。
Schema 合法不等于系统行为正确。数据所有权、跨字段规则、副作用和权限仍需代码与测试验证。
Roadmap、任务与 PR:保存时态
Roadmap 负责编排阶段、依赖和 Gate;Issue 负责一项待完成工作;Pull Request 负责说明本次实际变更与验证结果。
已经完成的状态应由代码、测试和部署证据核验。不要让长期架构文档承担每日进度,也不要把临时调试记录沉积为永久规则。
Runbook:指导高风险操作
部署、迁移、回滚和故障恢复需要有序步骤、前置条件、验证点、停止条件和恢复路径。每一步应有可观察的完成标准:命令返回什么、指标应如何变化、何时不能继续。
Runbook 应经过演练;一份从未执行过的操作清单只是未经验证的假设。
AGENTS.md 应怎样写
AGENTS.md 是面向编码 Agent 的仓库工作入口。它适合保存会显著改变执行行为、但不能从环境稳定推导的规则,例如:
- 开始实质工作前必须读取哪些项目资料;
- 哪些目录或系统属于任务范围;
- 如何保护用户已有改动;
- 哪些操作需要额外授权;
- 修改不同边界时应加载哪些专题资料;
- 完成任务需要哪些可检查证据。
一个小而有效的结构可以是:
# Working in this repository
## Before editing
1. Read `README.md` and inspect the current worktree.
2. For module-boundary changes, read `ARCHITECTURE.md` and related ADRs.
3. For content publication changes, follow `docs/content.md`.
## Boundaries
- Preserve unrelated user changes.
- Obtain approval before deployment or destructive data operations.
- Keep secrets and local environment values out of version control.
## Completion
- Review the actual diff.
- Run the checks relevant to every affected boundary.
- Report commands, results, unresolved risks, and files changed.这不是固定模板。若命令可以从 package.json 直接发现,AGENTS.md 只需指出权威入口或一个聚合验证命令,不必逐项复制所有脚本。只有难以发现的参数、环境前置条件或测试选择规则值得写入。
在 Monorepo 中,可以为真正具有不同工作方式的子项目增加局部 AGENTS.md。根文件保留共享边界,局部文件只补充该子树的差异。具体的发现和优先级行为取决于使用的 Agent;采用嵌套文件前,应以目标工具文档和实际运行验证。
写给 Agent 的指令怎样更可靠
先写动作,再写背景
步骤应按执行顺序出现,并以可验证条件结束。长篇原理放在步骤之后或专题文档中,避免关键动作被参考信息淹没。
使用正向目标
“保留用户无关改动,只修改任务涉及文件”比只写“不要乱改”更能指向期望行为。硬性禁止仍可保留,但应同时说明安全替代路径。
把规则放在触发点附近
数据迁移的回滚要求应靠近迁移步骤,工具权限应靠近工具说明。把定义、规则和例外散落在多个章节,会迫使执行者自行拼装。
写清完成标准
“测试一下”需求太低。更强的要求是:
列出所有受影响边界,并为每个边界提供对应的自动检查或人工验证;
任何未验证项都在交付中明确说明原因和风险。清楚且有要求的完成标准会驱动必要的检查,也能减少“代码写完即完成”的误判。
示例必须编码真实边界
示例用于说明容易误解的路径、格式和边界,不是装饰。示例与当前实现冲突时,Agent 很可能模仿错误示例,因此它们也需要测试或定期复核。
人与 Agent 的协作闭环
一次可靠任务通常经过:
- 定位:从入口和指针找到目标、相关边界与权威资料。
- 核验:用当前代码、配置、测试和运行证据校正文档记忆。
- 计划:明确受影响文件、interface、风险和验证方式。
- 实施:保持变更聚焦,保留用户无关改动。
- 验证:为每个受影响边界运行相称的检查。
- 交付:说明结果、证据、未解决问题与外部状态。
- 沉淀:只把持久决定、复用方案和重要陷阱写回权威文档。
最后一步尤其需要克制。聊天历史、普通代码改动、临时日志和 Git 已经明显表达的事实,不应再复制进长期文档。
防止文档腐化
文档和代码一起评审,但不是所有代码变更都需要改文档。判断方式是:权威事实、指针或执行流程是否发生了变化。
维护时重点检查:
- 指针指向的文件是否存在,触发条件是否清楚;
- 文档是否重复配置、Schema 或另一份文档;
- 描述的是当前事实、已验证历史,还是未来计划;
- 示例和命令是否仍能执行;
- 已完成或取消的临时内容是否可以删除;
- 是否出现无人读取、无人负责、无法验证的新文档。
删除失效内容通常比追加“注意:上面已过时”更安全。若历史理由仍有价值,把它记录为 ADR 或版本历史,而不是让旧规则继续占据当前入口。
一个项目最少需要多少文档
没有按规模固定的答案。一个新项目可以从以下三项开始:
- README:项目目标、状态、启动方式和文档导航;
- AGENTS:非显而易见的工作规则、专题指针与完成标准;
- 代码、配置和测试:当前实现的可执行事实源。
当真实需求出现时再创建 PRODUCT、CONTEXT、ARCHITECTURE、ADR、API 契约或 Runbook。文档体系应随需要分化,而不是先创建一批空模板等待内容填充。
一句话总结:面向人与 Agent 的好文档不是最多的文档,而是一组可发现的深模块——每条信息只有一个权威位置,入口用清晰触发条件把任务路由到需要的上下文,每个步骤都有可验证的完成标准。