ENZH

四个 AI 审代码,三个 AI 修 Bug

四个 AI 审查员并行审代码四个 AI 审查员并行审代码

能跑不等于扛得住

上一篇讲的是构建——十个任务、五个 AI、三波 DAG 调度。Mio 的多模态输入、增强 onboarding 和 selfie 生成,一个 session 全部落地。

但构建只是一半的工作。

五个并行 agent 产出了 81 个 commit,横跨三层架构。代码能跑,类型检查全过。可"能跑"和"扛得住"是两回事。

这篇讲另一半:代码审查、Bug 修复、版本发布——用同样的 Agent Team 模式,做完全不同类型的工作。

先扫了一眼,就发现问题了

这个 session 是在一次崩溃恢复后开始的——上下文已经被压缩过,所以第一步是重新确认状态。

比 origin 领先 38 个 commit
TypeScript: 0 errors

基线没问题。但扫描 repo 状态时,我发现了一个问题:{custom_story} 占位符泄漏到了 LLM prompt 里。五个人格配置文件包含了死的模板占位符——本该在 onboarding 阶段被替换,但替换逻辑根本没处理这些占位符,于是它们原封不动地出现在发给模型的 system prompt 里。

这种 bug 是"能跑"的——模型会忽略这段乱码,照常回复。但每条消息都在浪费 token,而且如果有人检查 prompt,看到 {custom_story} 就很尴尬。

小修复,但这正是为什么要在发布前做 review。

四个专业审查员,各看各的

我跟 Claude Code 说:"ok do a full review with agent team of the implementations."

它启动了四个专业审查 agent,各负责一个领域:

  1. Media 审查员 — transcribe、vision、process、selfie、reference-images、file-download
  2. Onboarding 审查员 — 状态机、命令、预设配置、schema
  3. Pipeline 审查员 — server index.ts、router、system-prompt、agent loop
  4. 安全审计员 — API key、输入验证、路径穿越、SSRF、prompt 注入、成本滥用

为什么要专业化?

原因和人类团队一样——安全专家和功能审查员看同一个文件,看到的东西不一样。通用审查员看代码正确性,安全审计员看攻击面。

两个 BLOCK,不能发布

四份报告大约五分钟内全部返回。汇总:

审查员结论CRITICALHIGHMEDIUM
MediaWARNING0410
PipelineBLOCK246
OnboardingWARNING047+
SecurityBLOCK245

两个 BLOCK,两个 WARNING。不能发布。

四个 CRITICAL

  1. 缺少成本归因processMedia()userId 可用之前就被调用了,导致媒体处理成本无法归属到正确的用户
  2. 打字指示器泄漏 — 消息批次为空时,clearInterval 没被调用,bot 会一直显示"正在输入..."
  3. HTTP API 路径穿越/api/agents 端点接收 presetId 参数,直接拼进了文件路径,没有任何验证。经典的目录穿越漏洞
  4. Bot token 泄漏到下载 URL — Telegram 文件下载 URL 包含 bot token。下载出错时,URL(含 token)可能泄漏到错误日志里

大约十个 HIGH

对四份报告去重后(有些问题被多个 agent 同时标记):

  • 引用图片缓存无上限——三个审查员分别标记
  • selfie/media 操作没有超时
  • 生成端点没有限流
  • .replace() 中的 $ 符号导致模板注入
  • item.size 未定义时文件下载无上限
  • 没有 MIME 类型验证
  • 超时后 about_user 被设为空字符串,绕过了验证
  • /reonboard 在 onboarding 进行中时有竞态条件
  • bubble transform 中出现 NaN token 计数
  • 成本追踪静默失败(.catch(() => {}) 吞掉了错误)

有些问题一个认真的审查员就能发现。但路径穿越和 bot token 泄漏?这是安全审计员专门探测攻击面才找到的。成本归因问题?这是 pipeline 审查员追踪跨模块数据流才发现的。

专业化是值得的。

三个修复员,严格按文件分

拿到审查结果后,我启动了三个修复 agent,严格按文件所有权分配:

安全修复员

文件:agents.ts、file-download.ts、onboarding.ts、process.ts

  • 路径穿越:添加 preset ID 白名单验证
  • Bot token 泄漏:用通用错误信息替换原始错误
  • 模板注入:用 split/join 替换 .replace()
  • MIME 验证:为 audio、image、video 添加类型白名单

Pipeline 修复员

文件:index.ts、loop.ts、reference-images.ts

  • 打字指示器:在空批次路径添加 clearInterval
  • 成本归因:将 Telegram user ID 传递到 processMedia()
  • NaN token:在合成事件中替换为 0
  • Selfie 超时:添加 30 秒 AbortController
  • 缓存上限:最多 10 条,按最旧优先淘汰
  • 成本日志:用实际错误日志替换 .catch(() => {})

Onboarding 修复员

文件:onboarding.ts、process.ts、commands.ts

  • 超时默认值:设为"用户未填写自我介绍"而非空字符串
  • Reonboard 竞态:在启动新会话前调用 clearOnboardingState()
  • 下载后大小检查:Telegram 省略文件大小时在下载后验证
  • Promise.allSettled:单个媒体失败不再导致全部结果丢失

注意这个模式:没有两个 agent 编辑同一个文件。 上一篇里,文件所有权在构建阶段防止了合并冲突。同样的原则在这里也适用——三个 agent 同时修 bug,只有在它们不互相踩脚的情况下才能工作。

第四个 agent——文档更新员——同步运行,更新了 CLAUDE.md、API.md、SCHEMA.md、TECHNICAL.md、DATA-FLOWS.md、CONVENTIONS.md 和 TODO.md。文档漂移是真实存在的问题,现在修比以后发现过期文档便宜得多。

Changelog 和发布:机械工作交给 Agent

所有修复提交后,我说了一句:"let's also add a changelog thing."

Claude Code 并行启动了两个 changelog agent:

  • v0.0.1 agent:分析前 39 个 commit(2 月 26 日上午 10 点 PST 之前)——基础构建阶段
  • v0.0.2 agent:分析后续 81 个 commit——上一篇的三功能冲刺加上所有审查修复

两个 agent 各写了自己的部分,合并成一个 CHANGELOG.md。然后:

git tag v0.0.1 <commit-hash>
git tag v0.0.2
gh release create v0.0.1 --notes-file ...
gh release create v0.0.2 --notes-file ...

两个版本、两个 tag、两个 GitHub release。这种没人想手动做的机械工作——交给 agent 处理,我在旁边看着就行。

把经验写进项目记忆

最后一步是制度记忆。我往项目的 CLAUDE.md 里加了两样东西:

  1. "Releases & Versioning" 章节,记录 changelog 和 tag 工作流
  2. 一条规则:"Always use doc-updater subagent for documentation updates"

大多数人会跳过这部分。Bug 修了,版本发了,走人。但如果流程改进没有被记录下来,下次还会遇到同样的摩擦。

CLAUDE.md 是项目的记忆——写进去的东西会跨 session 持久化,跨上下文压缩持久化,跨崩溃恢复持久化。就像我在 VM 那篇里讲的,长 session 中崩溃恢复是常态。你往 CLAUDE.md 里编码得越多,上下文重置时丢失的就越少。

全景

从审查到发布的完整周期:

阶段一:审查前清理           (1 个 agent,手动修复)
阶段二:并行代码审查         (4 个专业审查员)
阶段三:并行修复             (3 个修复员 + 1 个文档更新员)
阶段四:Changelog + 发布    (2 个 changelog agent)
阶段五:流程改进             (把经验编码到 CLAUDE.md)

五个阶段,总共十二个 agent,全部在一个 Claude Code session 内完成。

几条经验

跑了几轮审查修复周期之后的总结:

审查员要专业化。 安全审计员和 pipeline 审查员在同一个文件里能找到不同的 bug。通用审查会漏掉领域特定的问题。

修复员要严格文件所有权。 绝不让两个 agent 编辑同一个文件。按文件分配职责,不要按 issue 分。两个 issue 涉及同一个文件?分给同一个修复员。

文档更新和修复同步进行。 别等"以后"——以后永远不会来。并行跑一个文档更新 agent 几乎没有额外成本,但能防止文档漂移。

仪式性工作全部自动化。 Changelog、tag、release——这些机械任务不需要人类判断。让 agent 处理。

流程改进要立刻落纸面。 审查过程中学到了什么,在结束 session 之前写进 CLAUDE.md。制度记忆会复利增长。

构建和审查是一个硬币的两面

上一篇展示了如何用 Agent Team 构建——分解计划、调度依赖、让五个 agent 并行写代码。

这篇展示了另一面:用同样的模式来审查、修复和发布。机制是一样的——任务分解、文件所有权、并行执行。

但工作形态不同。构建是创造性的、向前看的。审查是对抗性的、回溯性的。两者都受益于专业化和并行化。

Mio v0.0.2 的完整工作流:规划、构建(5 个 agent)、审查(4 个 agent)、修复(3 个 agent)、发布(2 个 agent)、改进(编码经验)。一个 session,十四个 agent,一个人在顶层做决策。

不只是用 AI 构建——而是用 AI 交付。


© Xingfan Xia 2024 - 2026 · CC BY-NC 4.0