源码精读
把陌生的大型仓库读成可交付的内容。唯一不可妥协的要求:每一个技术论断都可回溯到源码的具体行。
AI 读码时幻觉几乎必然发生:根据文件名推测实现、根据常见模式补全细节、把注释当成代码行为陈述。掺进去一次,整份产出的可信度就是零,因为读者无法分辨哪句是真的。下面所有规则都是为了守住这一条。
第一步:先定规模,别过度应用
问清产出形态再动手。四阶段全流程很重,小任务不需要。
| 用户要什么 | 走哪些 |
|---|---|
| 读懂某个模块、回答一个机制问题 | 只用零幻觉引用纪律,不建大纲不做课页 |
| 一篇架构分析、一份技术文档 | 阶段一 + 阶段三 |
| 一门课、一个系列、多篇连载 | 四阶段全走,并建校验器 |
不确定就问:产出是给自己看还是给别人看,要不要交互演示,篇数大概多少。
零幻觉铁律
动笔前必须做到,每条都是作废级:
- 每一处引用、每一个行号、每一个类型名与函数名,动笔前用读文件工具实读核实。 禁止凭印象、禁止根据文件名推测、禁止照抄大纲里的候选行号
- 代码块与源文件逐字节一致。 保留原始缩进、属性宏、注释、空行。禁止转译、禁止美化、禁止写「示意代码」
- 中间跳过内容必须显式写省略标记(含
...的整行注释)。静默删行会被校验器抓成 FABRICATION - 找不到某个机制的实现,写明
未找到对应实现,检索关键词为 X、Y、Z。不许编一个看起来合理的 - 由推断得出的结论显式标注为推断
- 引用注释时说明这是注释,不要当成代码行为陈述
- 数字(行数、文件数、变体个数)必须统计过,统一用
splitlines()口径 - 引用符号链接时引真实文件,并注明链接关系
引用格式,三部分必填,路径相对仓库根:
```153:160:core/src/session/turn.rs
pub(crate) async fn run_turn(
sess: Arc<Session>,
...
) -> CodexResult<Option<String>> {
```
四阶段工作流
每一层的输入是上一层的输出,不要跳级。跳级的后果很具体:没有版本锚点,写到第十章时第一章的行号全部失效,且无法判断是当初写错还是后来改了。
- [ ] 阶段一 语料准备:锁版本、备对比语料、建检索脚本
- [ ] 阶段二 大纲:立一个真问题 + 逐章源码锚点
- [ ] 阶段三 章节书稿:八段结构,每处论断带行号
- [ ] 阶段四 成书:编成带封面封底的 HTML 书
- [ ] 贯穿 机器校验(批量生产之前就要建好)
阶段一:语料准备
git -C <repo> tag course-anchor-$(date +%Y%m%d)
git -C <repo> rev-parse --short HEAD
把 tag 与 commit 写进所有下游文档的文件头。然后做三件事:
- 备至少一个同类项目做对照。 只读一个仓库读不出设计决策,会把作者的选择当成唯一解。对比语料也要锁版本
- 建 ripgrep 检索脚本,不要建向量库。 查阅场景是关键词匹配,
rg毫秒级、零依赖 - 找「为什么」的一手材料,按优先级:仓库根的评审红线文件(
AGENTS.md、CONTRIBUTING.md、.cursor/rules/)→ 模块级 README → 模块头注释 → 测试文件 → 官方博客。指向外链的空壳文档要识别出来跳过
评审红线文件优先级最高:每条禁令背后通常都是一次真实事故,这是「为什么不那样做」的唯一一手来源。
阶段二:大纲
用 templates/00-outline-template.md。三件事按顺序:
- 先立一个真问题,把整门内容收束到一句话。这句话决定哪些内容进、哪些不进。缺了它,大纲会退化成源码目录的中文翻译
- 写清读者带走什么,具体到能直接用。「学会 Agent 架构」不算,「一份该不该做沙箱、做到哪一层的决策树」才算
- 逐章写锚点:核心问题、源码入口(文件加候选行号)、要分析的设计决策、对比对象、演示方向
已核实的行号标 ✓。✓ 的含义是曾经核实过,不是现在还对。 写作时即使看到 ✓ 也要重读,因为真正要引用的可能是相邻的行。
演示方向要在大纲阶段就逐章分配,句式统一。不提前分配,多个写作 Agent 会做出雷同的演示。
阶段三:章节书稿
填 templates/01-chapter-spec-template.md 里的占位符,填完的那一份就是唯一写作标准。八段顺序固定:
| 段 | 要求 |
|---|---|
| 场景还原 | 从具体会翻车的情形开局,不从概念定义开局 |
| 逐行精读 | 篇幅主体,一段代码一段话交替推进 |
| 设计决策分析 | 回答为什么,给出「不这样做会出什么事」 |
| 边界条件剖析 | ≥ 2 个「如果…会怎样」,答案落到确切分支和行号 |
| 横向对比 | ≥ 1 组,两侧都给路径行号,说清各自代价 |
| 演示设计 | 分步 + 每步字幕文案 + 逻辑轨迹面板 |
| 可迁移结论 | 哪些值得抄、最小成本形态、哪些是过度设计 |
| 思考题 | ≥ 3 道,含 1 道动手验证 |
两段最容易被敷衍,也最能拉开深度:边界条件不许答「取决于配置」,必须落到源码里某个 if 的某一行;横向对比不许写成功能清单对照,要说清另一侧为什么可以没有、或用什么别的东西补上了。
阶段四:成书
把章节 markdown 编成一本带封面、目录、正文、封底的 HTML 书:
pip install markdown
cp book/book.config.example.json book.config.json # 填书名、作者、被读仓库与版本锚点
python3 book/build_book.py
封面放阶段二立的那句话与版本锚点,封底放逐章引用数、图数、字数。读者判断一份源码解读值不值得信,看的就是这两样敢不敢摊开。
带省略的引用块,省略之后的行号构建器不排,只从两头数,中间留空。跳过了多少行只有源文件知道,编一个看起来合理的行号比不给更糟。
用法与输入格式见 book/README.md。校对用 python3 book/shot_book.py dist。
产出形态是课程站交互课页时走 templates/02-page-spec-template.md,与成书并行不冲突。课页上默认零代码,能在一页上贴的代码量远小于理解所需;演示必须有分步动画、每步一句人话字幕、逻辑轨迹面板。写「做个动画演示这个流程」等于没写。
文风
能写成正则的进禁忌,不能的进表达偏好。 无法自动检查的硬性规则等于没有规则。
禁忌交付前必须清零,跑:
python3 templates/style_scan.py path/to/chapters/
扫描器剥掉代码块、行内代码和「」直接引用后再判,避免源码字符被误报。只扫面向读者的正文,大纲和规范这类内部工作文档不在约束范围内。
不要用同义替换绕过正则,比如把「而不是」换成「而非」。禁的是靠否定制造对比这件事,不是那三个字。
完整清单在 templates/01-chapter-spec-template.md 第 4 节。
机器校验
投入产出比最高的一件事,必须在批量生产之前建好。 人工复核十万字的行号不现实。
至少校验三件:
- 代码块与源文件逐字节比对。以内容为准、行号为辅:按省略标记切成连续段,每段要在源文件里找到完全连续的匹配。拼不上判 FABRICATION,行号错了自动校正
- 文风禁忌扫描
- 引用密度下限。防一种隐蔽作弊:删掉报错的引用让校验变绿
第三条来自真实事故:某章初稿 56 处引用带若干报错,交付时只剩 22 处、全部通过。校验器只报「现有引用是否正确」,不报「该有的引用是否还在」,这个缺口必须补。
另外单独写一个脚本查「被引用文件是否存在」「行号是否越界」,逐字节比对验证不了路径写对没有。
校验器会误报,误报会让人开始忽略它的输出,那等于没有校验。每修一个误报都记下判据。
并行生产
规范里每一处含糊都会变成 N 份不同的理解。派活时必须给全四样:
- 填好的写作规范(一个文件,不要口头补充)
- 那一章的大纲条目
- 全部语料的绝对路径。先确认路径真实存在再说,凭印象说「某个语料不在本地」会让子 Agent 绕开它
- 校验命令,以及「必须全绿才算交付」
子 Agent 的四种典型偏差,规范里要提前堵:删引用让校验变绿、滥用省略标记凑字数、把检查糊弄过去、误报上游文档写错(实际命中率约两成)。
要求上报文档错误时带证据,格式固定:被质疑的原话 → 源码文件与行号 → 那几行的原文 → 为什么对不上。
并行中陆续收到的上游文档问题不要边收边改,开一个 PENDING_FIXES.md 累积,全部回来后统一核实统一修。
参考资料
- 方法论完整版,含每条规则的来由:METHODOLOGY.md
- 29 条踩坑清单,全部来自真实事故,卡住时来查:PITFALLS.md
- 大纲模板:templates/00-outline-template.md
- 章节写作规范模板:templates/01-chapter-spec-template.md
- 课页规范模板:templates/02-page-spec-template.md
- 成书构建器用法与输入格式:book/README.md
- 文风扫描器:templates/style_scan.py
- 真实成品,同一章从大纲到课页的纵向切片:example/README.md