目录

人负责写原始文档和做决策,LLM 负责综合、更新和一致性检查。文档不再是写完即腐烂的静态产物,而是一个由 LLM 持续维护的活知识库。

一个古老的问题

每个软件工程师都经历过这样的场景:你接手一个项目,翻开文档,发现 README 还在描述半年前删掉的模块,API 文档里的字段和代码完全对不上,架构图画的是两个版本前的设计。你问同事,同事说"别看文档,直接看代码吧"。

文档腐烂(documentation decay)不是因为工程师不想写文档,而是因为维护文档的成本太高。写一份设计文档可能花两个小时,但之后每次代码变更都需要回来同步更新 —— 检查交叉引用是否还成立、术语是否一致、边界条件是否还对 —— 这些琐碎的记账工作让人疲惫,最终被放弃。

Karpathy 的洞见:知识编译而非知识检索

2025 年,Andrej Karpathy 提出了一个关于 LLM 与知识管理的重要观察。他的核心主张出奇地简单:

不要让 LLM 每次都从原始文档中重新发现模式,而应该让它构建和维护一个结构化的知识库,让知识持续积累。

这就是 LLM Wiki 模式。它和传统的 RAG(检索增强生成)有一个关键区别 —— RAG 每次查询都强迫 LLM 从零开始重建理解,而 Wiki 模式将综合(synthesis)本身视为一等公民的产物。知识不断积累,因为交叉引用已经建立,矛盾已经被标记,概念之间的关系已经被梳理。

Karpathy 勾勒了一个三层架构:

  • 原始来源(Raw Sources):人类策划的不可变文档 —— 论文、文章、笔记。LLM 永远不碰这一层。
  • Wiki:LLM 生成和维护的 Markdown 页面 —— 摘要、实体、概念、对比。LLM 完全拥有这一层的结构和内容。
  • Schema:定义 wiki 结构、命名约定和工作流的配置文件,让 LLM 成为一个有纪律的维护者而不是一个通用聊天机器人。

以及三个核心操作:Ingest(摄入新来源并更新 wiki)、Query(查询并将有价值的发现回写 wiki)、Lint(健康检查 —— 找矛盾、找孤立页面、找缺失引用)。

他还提出了一个深刻的分工:

人的工作是策划来源、指导分析、问好的问题。LLM 的工作是其他一切。

这个"其他一切",恰好是杀死人类 wiki 的那些事情 —— 更新摘要、维护交叉引用、检查一致性。这些工作对人来说是乏味的苦差事,对 LLM 来说却是可靠且不知疲倦的日常。

将 LLM Wiki 带入软件工程

Karpathy 的 LLM Wiki 是领域无关的 —— 他用它管理论文阅读笔记、技术调研。但当我们审视软件工程的文档管理时,发现这个模式有天然的适配性,同时也需要领域特定的适配。

为什么软件文档特别适合这个模式?

软件项目的文档有几个独特特征:

  1. 文档与代码有严格的对应关系。API 文档描述的端点必须在代码中存在,数据模型文档里的字段必须和 schema 一致。这种对应关系是可验证的 —— 这意味着 lint 不仅可以检查文档内部一致性,还可以深度审计文档与代码的匹配度。

  2. 文档有明确的生命周期。一份设计规格(spec)在实现过程中会演进,实现完成后基本稳定;一份架构决策记录(ADR)一旦做出就不再改变。软件文档的分类和变更模式是有规律的。

  3. 版本控制是天然的基础设施。软件项目几乎都用 Git,这意味着每一次文档变更都自动有完整的 diff 历史,而 git loggit diff 可以作为自动发现变更的信号源。

  4. AI Coding Agent 是天然的消费者。在 AI Coding 的时代,文档不仅服务于人类开发者,还直接服务于 AI 编码代理。一个结构化的知识库可以让 AI agent 在修改代码前先理解设计意图和约束。

从三层到三层:领域适配

我们保留了 Karpathy 的三层架构,但做了软件工程的领域适配:

第一层:docs/raw/ — 原始文档归档

Karpathy 的"Raw Sources"在软件工程中自然地按文档类型组织:设计规格(specs)、实现计划(plans)、架构决策记录(adr)、API 文档(api)、产品需求(prd)、会议纪要(meeting)……每个文件带日期前缀,带元数据 frontmatter 标记来源和分类。

一个关键的设计决策是:raw 并非绝对不可变,而是可控演进的。Karpathy 的原始来源(论文、文章)确实是不可变的 —— 论文发表后不会改。但软件工程的 spec 和 plan 在实施过程中会演进。与其让文档与现实脱节,不如提供一个有审计追踪的正式变更通道。每一次变更都经过 git history 和审计日志的双重追踪,保留完整的演进脉络。

第二层:docs/wiki/ — LLM 维护的当前知识库

这一层忠实地继承了 Karpathy 的设计理念:LLM 完全拥有此目录的结构和内容。Wiki 页面没有日期前缀,因为它们代表的是"当前状态"而非"某个时间点的记录"。每个页面通过 sources 字段回溯到 raw 中的原始文档,建立可追溯的知识链。

Wiki 和 Raw 的关系,就像数据库中的物化视图和原始表的关系 —— wiki 是 raw 的综合投影,始终反映最新的整合理解。

第三层:docs/schema.md + docs/README.md — AI 入口

Schema 定义了系统的约定 —— 目录结构、文档格式、分类体系、操作契约。README 是 wiki 的导航索引。它们共同构成 AI coding agent 的入口:agent 通过读取这两个文件来决定需要深入阅读哪些 wiki 页面。

超越 Ingest-Query-Lint:五个操作

Karpathy 定义了三个核心操作。我们在此基础上扩展为五个,以适配软件工程的工作流:

  • Init — 在任何项目中一键初始化文档系统。冷启动即可用,不需要预先存在任何文档。
  • Ingest — 继承 Karpathy 的设计,但增加了自动发现:无参数运行时,通过 git diff 自动找出当前分支上新增的文档类文件,减少人工操作的摩擦。
  • Update — 这是软件工程特有的操作。当实现过程中 spec 需要演进时,通过 update 进行有审计追踪的原地修改,而不是创建新文件。默认的自动发现模式会分析 git commit 记录,找出哪些 raw 文档可能需要更新。
  • Lint — 继承 Karpathy 的健康检查,但增加了文档-代码深度审计。不仅检查 wiki 链接是否有效、页面之间是否矛盾,还将文档中的声明(API 端点、数据模型、配置项)与实际代码逐项对照。
  • Query — 继承 Karpathy 的查询和回写机制,但增加了 Agent 模式:AI coding agent 在修改某个文件前,可以请求该文件相关的设计上下文 —— 设计意图、约束条件、历史决策 —— 以结构化格式输出,直接消费。

两个关键的设计理念

Git 即信号源。我们没有构建独立的变更追踪系统,而是将 Git 本身作为变更发现的信号源。git diff 告诉我们分支上发生了什么,git log 告诉我们实现过程中的代码变化。这意味着文档维护可以成为一个"一键同步"操作 —— 在完成一个功能后运行一下,系统自动分析变更并建议需要更新的文档。

渐进式丰富。系统从冷启动即可用,不需要一次性导入所有文档。每次使用 ingest 添加一份文档,wiki 就多一些知识;每次 lint 发现一个不一致,修复后系统就更准确一些。随着使用的积累,文档系统从空白逐渐成长为一个丰富的项目知识库。这与 Karpathy 所说的"知识持续积累"的理念完全一致。

一个更根本的转变

回到最初的问题:为什么文档会腐烂?

因为维护文档的边际成本始终由人承担 —— 而人的注意力是稀缺资源。Karpathy 的洞见在于,LLM 改变了这个等式。那些杀死人类 wiki 的繁琐工作 —— 更新交叉引用、同步摘要、检查一致性 —— 恰好是 LLM 擅长且不知疲倦的。

这不是用 AI 替代人写文档。恰恰相反,人依然负责最关键的部分:决定构建什么、为什么构建、如何权衡取舍。这些决策、意图和判断,是文档中真正有价值的内容。LLM 负责的是将这些散落的决策编织成一个连贯的、持续更新的知识网络。

当我们将这个理念应用到软件工程中,得到的不仅是"不腐烂的文档",而是一个与代码共同演进的活知识库 —— 新来的开发者可以通过它快速理解项目的设计脉络,AI coding agent 可以在编码前获取充分的设计上下文,每一次代码变更都有可能触发文档的同步更新。

文档终于有机会成为它本该成为的样子:一个团队的共享记忆,而非一份过时的快照。


本文中描述的软件工程文档管理系统已开源:llm-docs