跳转到主要内容

文档驱动:AI 软件工程的第一秘籍

文档不是代码写完以后的补充,而是写代码之前的输入、开发过程中的工作记忆,以及交付时的验收标准。

前几天写了《AGI 机关枪发下来了》,讲我怎么一个月烧掉十几个 AI 订阅,把手头一堆项目全推了一遍。 后台和评论区问得最多的,不是“哪个模型好用”,而是:这么多 AI 写出来的代码,你怎么保证它不是屎山?

这问题问得对。机关枪发下来,人人都能突突;但代码写得快,不等于软件做得好,更不等于半年以后还能维护。所以今天就来聊聊我这几个月用 AI 做工程的路数和心得。

核心总共四条:文档驱动、对抗审查、暴力测试、复杂度惩罚。 你看,其实有的时候,越是简单粗暴的东西越是管用。所谓什么秘籍,说穿了也就那么回事——但不得不说,确实管用。

这几点里,今天这篇真正想展开讲的是第一条:文档驱动。它是另外三条的地基,也是我投入最重的一件事——重到什么程度呢?我干脆顺手做了一个文档框架出来,专门用来实践它。


许愿与设计

本来想先摆理论、讲背景,再谈实践,想想太麻烦了。直接说我用 AI 做中大型项目开发和维护时,碰到的几个核心痛点吧。

第一个痛点,我管它叫“许愿”:把你自己到底要什么说清楚。 对于小 Demo,怎么搞都无所谓。对于中型及以上规模的软件项目,这件事是有不小门槛的。

你不能对着 AI 许愿说“我要一个跑在对象存储上的数据库”,或者“我要用 Go 重写一个 Patroni、重写一个 pgAdmin”。 这种愿望太 高层 了,AI 还没进化到你丢给它这么一句话,它就能把整个东西全给你做出来的地步。 中间有大量工程细节和架构决策,得你自己来拍板。

许愿是整个流程里最需要你花精力的一步。愿望许得足够好,Agent 可以一口气跑上好几天,把你许的东西一点点落地,你不用隔三差五去微调、去调度它。愿望许得糊里糊涂,它跑得再欢也是白跑。

那“许愿”最后应该是个什么形式?我认为应该是一份 PRD(产品需求文档)。这一步人类必须介入:你来描述需求,Agent 帮你把它整理成 PRD,然后这份文档你得自己仔细读。

你可以不读代码,但不能不读需求文档。 因为你要什么,只有你自己说了算。

如果你嫌整份 PRD 读起来太费劲,那至少要读里面的用户故事(User Story):让 Agent 把典型的使用场景描绘出来,你看一遍,判断“这是不是我想要的东西”。 有出入就提意见,来回打磨,直到你自己觉得:“对,就是这个,去做吧。”

老冯的经验是,千万千万不要在这一步省时间。你在这一步偷懒,最后都是要还的。 你没有描述清楚需求就开工,最后得到的东西就纯粹是看运气、抽卡。 抽卡对于小型项目并不是不可以,有时候你一发就能实现 90% 的完成度——SSR 出金,那也是有的。 但工程不能纯粹看运气,能在设计决策的时候拍定的方案,那你就不应该拖到后面去做。

当然,如果是探索性的东西,你也不知道什么方案好、什么方案不好,那就是没办法。 但你至少可以把有效的搜索空间给降下来,不要让它出特别离谱的东西。

这一步花多少时间?我的经验是:中型项目,至少值得花半天、一个上午来生成和审阅 PRD 再开工。 搞定之后就让它去跑,让它消耗订阅。一两天以后你再回来,进入验收阶段。


开发与修复

第二个痛点出在开发过程中。Coding Agent 和人类工程师不一样,它有自己的秉性。简单说,你可以把它理解成一个 失忆的天才

想象你招了一个工程师,业务能力顶级:什么语言随手就写,什么框架一看就会,一天能干出普通人一周的活。但他有个毛病——每天早上上班,昨天的事全忘了。项目为什么这么设计、哪些方案试过不行、哪些坑踩过、哪些地方是故意留白的,一概不记得,你得从头跟他讲。

人类团队一直在用各种非正式手段弥补这个问题。老员工带新人,吃饭的时候讲讲项目的陈年旧事;Code Review 时顺嘴解释一句“这块当年这么写,是因为……”。这些没进代码、却真实支撑着项目运转的知识,有个名字叫 Tribal Knowledge,部落知识。

Agent 没有这个部落,也参加不了你的午饭局。它能依靠的只有三样东西:代码、测试和文档。

这也是 AI 编程带来的一个实质变化:以前文档是代码写完以后的补充,现在文档首先是写代码之前的输入。 以前文档写得差,最直接的后果无非是新人上手慢一点;现在文档写得差,Agent 很可能从方向上就做错,把你早就否掉的方案重新实现一遍,而且实现得还挺完整,费了大劲干一堆南辕北辙的活。

怎么解决?我的答案是:给它工作记忆。 但绝对不是“给我装一个 MCP”“给我装一个 Claude Mem”这种挫不拉叽的东西,而是把工作记忆也作为文档来管理。

你要是不管它,Coding Agent 就会随地大小便,在项目各个角落里拉出各种零散的 Markdown:这里一个 PLAN.md,那里一个 NOTES.md,再加上一堆 TODO。与其让它随地大小便,不如明确做两件事:

  1. 完整保存思考过程。 原始记录存一份放在工作目录里,按时间顺序(编年体)或者按议题顺序,把完整过程记下来。
  2. 定期总结索引。 让它把过往的工作记忆总结成索引,更新到 AGENTS.md(或者 CLAUDE.md)里,记下之前的 Thread 和 Session 都干了什么。以后碰到类似问题,它可以先翻翻之前的想法和架构决策,避免重蹈覆辙。

这两层缺一不可。 你不能把所有东西堆在一块,所以上面要有索引;但也不能只留索引,底层的原始记录必须完整保留。


测试与验收

第三个痛点是测试和验收。

测试是分等级的:单元测试、集成测试、验收测试,各不一样。以现在 AI 的智力,单元测试、集成测试这种代码,我是根本看都不看的。 除非是特别核心的路径改动,或者有兼容性上的破坏,否则一眼都不看,直接让它自测、自己汇报,然后用第二条技巧——对抗审查——来把关。

只有两个顶级 Agent 互相审完都达不成共识的问题,我才会人工介入,这种情况现在已经很少了。

但有一件事你没法让它代劳,就是 验收测试。它做出来的东西到底是不是你真正想要的? 你对 AI 说“你帮我验收一下”,这肯定不行。监工、签字这个活,你没法外包。 连这个都不做,那做出来的有极大概率是垃圾。

验收等于拿自己的信誉去背书。 作为一个负责任的工程师,这是绝对不能偷懒的地方。

那怎么验收?你能“偷懒”到什么程度?你可以让 AI 帮你出一份验收方案。

这就是文档开始起作用的地方了。你得反过来想:这个软件的用户是谁?可能是人类,也可能是别的 Agent。

如果是人类,他以前是怎么使用软件的?他是不是要先去你的网站,点开 Get Started,然后跟着教程从最基本的功能开始,把最核心的流程走一遍?这是一个惯例。

所以你完全可以要求 Agent:交付的不只是代码,还必须包括这份代码的使用说明和手册。而且这份手册,要用跟代码同样的质量和要求来维护。 你验收的时候,就是照着手册走一遍:Get Started 能不能跑通?教程里的每一步是不是真的能做出来?


文档驱动

上面三个环节聊透了,你会发现:用 AI 做 Coding,核心就是上下文管理。当然,这是一句废话——用 AI Agent 干任何事,核心都是上下文管理。 但落到软件工程和代码开发上,这个上下文究竟是什么?不外乎两样东西:代码和文档。

如果你的代码本身就高度自描述、表达力极强——比如纯 Python、纯脚本,或者 YAML、DSL 这种自己能解释自己的东西,或者就是个迷你项目——那也许不额外写文档也无所谓。但你写的要是 Go、Rust,或者是一个完整的中大型项目,那肯定得配文档。

我的结论:你应该把文档当成跟代码一样重要、甚至更重要的东西来处理。

文档具体可以分成几种:

  1. 设计文档:写清目标、约束、方案、边界与架构取舍;
  2. 工作记忆文档:也就是上面说的两层——完整原始记录,加定期整理的索引;
  3. 参考与交付文档:描述系统怎么工作的 Reference、带用户走通流程的教程、版本发布的 Release Notes,以及记录架构利弊权衡的决策文档。

这么多种类的文档,怎么管?你当然可以建一个目录全丢进去,再让 Agent 去总结这个目录里有些什么,但这太挫了。

你得想清楚一点:文档必须是可以方便交付的。 它是交付物的一部分,不是内部随手记的小笔记,也不是随便扔在 Obsidian 或者云笔记里的东西。

做软件从第一天起就要明白,你交付的不只是二进制,还有文档;两者是同等地位的交付物。既然要交付,那第一天就应该写好,并且用一个像样的方式管起来。

我概括下来的做法是:给每一个项目配一个伴生的文档站。 你可以在项目里放一个 docs 目录,也可以单独拆一个仓库;我自己更喜欢单独拆一个。

文档站的框架,我在 GitHub 上做了一个 OINK Hugo 主题,基于 Google 的 Docsy 做了大量定制和融合。它的好处主要有三条:

  1. 交付简单。 可以傻瓜式地在 GitHub PagesCloudflare Pages 上跑自动 CI/CD。一提交、一推送,文档站就自动构建、自动发布,不用操心流水线。
  2. 该有的都有。 代码块、标签页、步骤、图表、公式、文件树、全文搜索、多语言、版本切换,还有知识管理用的反向链接,都内置了,直接就能交付一个非常美观的文档站。每一页都带纯 Markdown 版本,整站还有 llms.txt:人看渲染出来的网页,Agent 直接抓 Markdown,用的是同一份源。
  3. 最小化摩擦。 不要前端 npm 全家桶那一大坨。一个 Hugo 二进制完全离线构建,速度极快,几千个页面的大站也能瞬间完成、实时浏览。能用原生 Markdown 语法表达的,绝不用花里胡哨的组件。

为什么要写好文档

为什么要在文档上花这么大力气?文档到底是给谁看的?

首先你得设身处地想:如果一个人、或者一个 Agent 要用你的东西,他第一眼会干什么?总不能拿着二进制去摸索吧?其实这也是一条路,我另一个项目 PIG 就是这个理念:把文档嵌进二进制里,通过 help 直接输出结构化的文档,具体设计写在《Agent-Native CLI》里。但我认为这不是通用的路子。通用的做法,还是来看你的文档。

第二,文档不只是给用户看的,也是给你自己看的,而且在验收环节是最重要的标准。AI 写的代码没多少人会逐行看。你不想看代码可以,但至少得看文档。AI 给你糊了一个东西出来,你没时间手把手把每个点全测一遍,那配套的 Reference 文档总得看一眼吧?

要明白一点:现在的 Coding Agent,水平已经是专家级的天才工程师了,需要你扮演一个资深架构师的角色去派活、去验收。但它还没聪明到你随便许一个宏大的愿望,它就能全自动替你实现的程度。

这里有一个我认为很关键的观点:

如果你追求的是工程质量,花掉的 Token 至少应该有 70%~80% 用在 QC 和测试上,而不是用在写代码上。

写代码其实很快,也不怎么耗 Token;真正耗 Token 的是穷举各种测试,这才是把质量提上去的地方。 AI 软件工程的基本特点是:你可以让 AI 一次性给你出一个质量 70 分到 80 分的东西,但你可能 80% 的成本都花在最后那 20 分上。

你想交付一个真正可靠、别人敢用、被广泛使用、你自己也敢用的东西,这笔开销绝对不能省。 什么地方可以偷懒,什么地方不能偷懒,自己心里要有数:

单元测试可以不用手写,平时也不用看,这是可以偷懒的地方。但宏观路线和方向有没有走错,架构品味上有没有很蠢的设计,这是不能偷懒的。发现了就要及时纠偏(steering),把方向调回来。

反过来说,如果一个项目交付不出质量合格的文档,那我认为这个东西就完全不行。

最典型的例子,就是我朋友蒋老板。上篇文章里说过,他就是那个拿着机关枪的大猩猩,糊出了 5 个数据库、1 个操作系统、1 个编译器;最近又糊了一个基于对象存储的 OLTP 数据库。

客观地说,他这个数据库有可能在某个场景下确实能解决某个问题;但总的来说,还是应该划到 garbage 这一类里。为什么?因为连个像样的文档都没有。没有文档,别人根本不知道它能干什么、边界在哪,也没法验收。


一个具体的例子:Silo

上面聊了这么多,来看一个具体的例子:Silo

Silo 是我维护的一个 MinIO 分支。MinIO 上游把社区版砍了,管理控制台砍成了空壳,二进制停发,仓库归档;Silo 把这些东西都续上了。现在它已经是最活跃的 MinIO 分支,60 万次下载,2,500 多个 Star,一堆开源项目把默认镜像换成了它。

我是怎么维护这个项目的?每一个 Issue,我都会创建一份设计文档,把完整的设计思路和思考过程沉淀下来。我认为这件事非常重要。这么关键的一款基础设施软件,你拿 AI 去糊,大多数人的第一反应都是:“这质量能有保证吗?”

所以你必须把这些东西完整地记下来:我们遇到了哪些问题?我们是怎么思考的?关键决策是怎么做出来的?

Silo 站点的 FAQ 里写得很直白:Agent 是功能开发与代码 Review 的主力;每一个变更都必须通过 CI 与人工审核,所有建设性变更都要经过人类的利弊权衡才会合入;Agent 的完整工作记录和取舍也会归档留存。因为当某个修复日后被证明是错的,你最想看的,就是当初为什么这么做。

我认为 Session Log 才是一个项目真正沉淀下来的资产。代码只记录了 What 和 How,而 Why 的部分,必须在文档里——至少也要在注释里——体现出来。

这种记录比代码更难得,它把前面说的部落知识真正沉淀了下来。Silo 那十几篇安全公告发布说明,就是这套做法在公开场合的产出。

这里还要提一嘴:对于中大型项目,我认为正确的做法是小步快跑,不要想着一次性糊个大的。一定要拆成小的、可验收的单元来处理。复杂的架构都是演化出来的,而不是设计出来的。而这个演化的历史是非常重要的。

就好比 PostgreSQL,它的代码虽然很有价值,但老冯认为灵魂其实不在代码里,而在这 30 年的社区邮件列表里,以及这份质量极高的文档里。 毕竟对于绝大多数用户来说,他可能不会去看 PG 的源代码,但几乎一定会去看 PG 的手册文档。


下一步是什么

除了文档驱动,软件工程里还有几个经典的小技巧,我认为有三个最实用:对抗审查、暴力测试、复杂度惩罚。

它们的原理都朴实无华,但越朴实的东西往往越耐造。至于那些花里胡哨的东西,像 BMADSuperpowers 这类 Skill 全家桶,当前这个赛季我已经不用了。

BMAD 那一套,我觉得纯粹就是过度设计:把软件工程里那些对人类团队可能成立的糟粕,原样搬到 Agent 身上。Agent 不需要你做这么细的分工。 我认为现阶段分两到三个互相审查的对抗角色就够了。每一个 Agent 都是全能选手,你只要给俩 Agent 预设一个对抗的立场,这就够了,不需要再给它切什么产品经理、架构师、测试工程师。

当然,这只是我在当前赛季(始于 2026 年 7 月)的实践体会。老冯现在是最强的那一档模型一把梭,只用最好的,根本不会浪费时间去用便宜的小模型。原则就一条:干尖儿活,用尖货。 所以我的 Token 也烧得特别快,平均一天要烧掉两个半订阅。就算有 Tibo 的疯狂 Reset,再加上好几个号轮着用也不太够,纯靠 Tibo 圣徒的 Reset 才勉强撑住。

下一个版本,最佳实践可能又不一样了。

目前我看到两种范式值得琢磨。

范式一:Agent 进入 IM

一种是把 Claude 接进 IM,接到 Slack 里(Claude Tag)。它能看到你的聊天记录和讨论,你可以像使唤真人一样使唤它。最重要的是,这样它就有了前面说的“部落知识”这种上下文。 在群里 @Agent 干活也是一种挺有意思的体验。我觉得这是一个不错的人与 Agent 共存、交互的协作方式。

范式二:超级 Orchestrator

我看 Tibo 说,下一步的主要范式会变成一个超级聪明的 Orchestrator——Astra,去调度各路小弟干活。我觉得这可能是更好的方向。 据 Tibo 说 Astra 发布的时候又会有一个巨大的飞跃,可能一般人的本地电脑都跑不了,要用云端电脑来跑。

老冯之前是想琢磨一下,自己烧一个(Agent 操作系统)出来给自己用,或者是找点现成的开源项目折腾一下。 但是我又觉得,与其浪费时间折腾这些,你再多等两周,官方直接下场做了,真的没必要折腾,对不对?

至于另外三条实践 —— 对抗审查、暴力测试、复杂度惩罚。具体实操中怎么落地,以后有时间再单独聊。


最后

今天主要聊了文档驱动在实操中是什么样子,也给了例子。

另外,我的 OINK 框架 最近已经定型,发布了 1.0.0 版本,该有的特性都有了,我也刚把它提交到了 Hugo 官方主题仓库

现在用它非常简单粗暴:直接跟 Codex 或者 Claude 说“用 pgsty/oink 这个 hugo 主题”,它自己就会克隆一个 Starter 站点、修改内容、构建、发布;你只管写 Markdown 就行。已经有一些朋友拿它在公司内部搭文档站了。

交付一个美观、开箱即用的文档网站,总比交付几个零零散散、随地大小便的 Markdown 要好太多。

我现在做的项目基本全都是 Build in Public。大家可以去下面这几个站点看看:项目的设计思路、发布历史、各种契约都在里面,都是实际可操作的例子。

代码可以许愿生成,质量不能。文档就是你给愿望加上的边界,也是你最后签字验收时的凭据。