带 AI 精读一个大型开源仓库
几十万行的陌生代码,带着 AI 读出设计决策。约束只有一条:每一个技术论断都能回到源码的具体行。
放行条件写在 admit。user 没被封,或者 token 仍有效,就发 Permit。失败时走 revoke。
gate/src/admit.rs 是为演示编的短片段,用来展示校验机制本身。真实仓库里,脚本拿回去比对的是锁过版本的源文件。打开一个几十万行的仓库,没有导读,上游每天在改。你问 AI 这段是怎么调度的,它会流畅地吐出一个函数名和一个看起来合理的行号。那个函数可能根本不存在。你把这句话写进笔记,下次按行号点进去对不上,分不清是当初写错了,还是后来上游改了。
源码是最难的一类材料。量大,没有导读,上游在动。AI 在这里最容易编造,因为它能把不存在的符号说得很顺。
定一条约束:每一个技术论断都带文件路径加行号。写 session 在超时后会清掉 pending tool 这种句子之前,先打开那个文件,读到那一行,再写。引用里写清路径、起始行、结束行。代码块和源文件逐字节一致。找不到就写未找到对应实现,并记下检索用过的关键词,不要补一个看起来合理的。
站里那组 Codex 课页,比如 新功能先找落脚的 crate,就是这套做法跑出来的成品。每一处判断旁边都能指到源码。
这套方法从四个项目里长出来:Claude Code、Grok、DeepSeek Harness、OpenAI Codex。最后产出了 61 节课页。
这条约束有两层用处。一层是迫使你真的读到那一行,印象和文件名推测过不了关。另一层是让别人能验证你。没有行号的源码文章,读的人只能选择相信作者。这是工程经验。
行号是地基。上游每天合 PR。你今天记下的第 76 行,下周可能已经是另一段逻辑。不先锁版本,写到后面,前面的引用会成批失效。失效之后更麻烦:分不清当初就写错了,还是后来上游改了。两种情况的处理完全不同。
四件事按顺序做。小任务不必四步全走。只想搞清一个机制,守住论断带行号就够。要写成一门课或一个系列,四步都走,并且一开始就准备校验脚本。
记下当前 commit,最好打一个 tag,写进后续文档的文件头。后面所有行号都相对于这一次快照。
每章只立一个核心问题,并列出这一章要读的文件。这一步决定哪些进、哪些不进。
每处论断带行号,代码块和源文件逐字节对齐。推断要标明是推断。
课页、演示、给别人讲的版本,正文几乎不再堆代码。行号仍留在能被点开的地方。
版本锚点把当时仓库长什么样冻住。后面任何引用失效,都能拿这个 commit 复现。提纲先于正文,是为了避免边读边写、写到一半发现两章在重复同一段源码。这是工程经验。
人工复核十万字里的行号不现实。AI 会改一个符号,静默删掉一行,或者把行号写漂。这些改动肉眼扫过去经常看不出来。
还有一类更隐蔽。校验器只报现有引用对不对,不报该有的引用还在不在。AI 为了让校验变绿,会直接删掉报错的那些引用。真实事故:整章从 56 条引用掉到 22 条,全绿。校验规则本身也会被优化。
让脚本把文章里的代码块拿回源文件,按声称的路径和行号切开,逐字节比对。对得上才过。差一个字符、少一行、行号对不上内容,都标红。
另外给一个数量门槛:这一章开始有多少条引用,结束时不能无故变少。掉了就报。
它会一本正经骗你,三道防线 讲的是同一件事的通用版。这一页的机器校验是它的工程化版本:出处变成了文件加行号,交叉验证变成了脚本重读源文件。
人做不到对十万字逐字节。脚本可以。它不管文字写得顺不顺,只问两件事:你声称的那几行现在还在不在,跟源文件是不是同一个字节序列。口径同时包含数量和正确性,删引用这条捷径就走不通。
常见做法
把仓库丢给 AI,直接要一份架构总结。函数名、行号、条件方向都可能是编的。读的人没有验证入口。时间省在前面,错埋在后面。
代价:看起来完整,无法核对这一页的做法
先锁版本,论断带行号,脚本逐字节比对,并且盯引用数量。每个判断都要打开文件。只想快速摸一眼的小问题,会被这套流程压得偏重。
代价:慢,小任务不必四步全走拿你正在看的仓库试一条引用
写一句你以为成立的技术判断,带上文件路径和行号。然后把那几行原样贴进对话,让 AI 按源文件再读一遍。
对不上的那个字符记下来,看它会把结论带去哪。如果它对得上,再补问一句:这段代码旁边还有哪一行是这句判断没覆盖到的。
完整方法论、三份可复用模板、28 条踩坑清单,以及可直接装的 Agent Skill。这一页讲的流程和校验口径都在里面。
打开 GitHub 仓库