你的计划.md 需要一个“魔鬼代言人”(Codex 自荐)

你是否曾经在晚上 11 点写了一个技术计划,确信一切无懈可击,但第二天早上发现忘记添加身份验证? 我深有同感,而且不止一次。最糟糕的不是这个疏忽——而是当你用人工智能来规划时,计划听起来是如此连贯,以至于你的大脑停止了对问题的挖掘。Claude 会生成一个带有章节、依赖项和执行顺序的文档,一切看起来都是高级工程师的作品。但问题是,没有人反驳过它。 Aseem Shrey 发布了一篇文章,精准点出了这个问题,并为此提出了一个优雅的解决方案:让第二个模型审查第一个模型的计划。而且不仅仅审查一次——循环审查,直到审查员说“通过”。 问题:没有人反对你的 AI 当你仅依靠一个模型来规划和执行时,你得到的结果确实连贯但没有争议。AI 不会反驳自己。它不会说“嘿,这个身份验证模型不完整”,或者“你的 shell 脚本中的引用有问题”。 这就像你自己写了一份文档,自我审查,然后对自己说“这可真是完美”。当然是完美的——毕竟是你自己写的。注意这个点:同行评审会存在于科学、工程和医疗领域是有原因的。并不是因为作者愚蠢,而是因为创作者通常是自己作品最差的审查者。 我以前在写我的 Jedi 代码审查委员会时讨论过这个问题。不过当时谈论的是如何审查代码。而 Aseem 的建议是先审查计划,在写出任何代码之前就发现问题。这相当于提前一阶段处理问题。 操作方法:Claude 规划,Codex 审查 这个过程基于 Claude Code 的一个“技能”实现——一个 Markdown 文件,无需额外的基础设施或外部服务。当你调用 /codex-review 时: Claude 会将计划写入一个临时文件。 计划会以只读模式发送到 Codex CLI(它可以读取你的代码库获取上下文,但不改动任何东西)。 Codex 审查后会给出结论:VERDICT: APPROVED 或 VERDICT: REVISE。 如果返回的是 REVISE,Claude 会修正计划并重新提交。关键在于,Codex 会恢复之前的会话,因此能够记住它之前的反馈,并验证问题是否真的被解决了。 审查最多迭代 5 次。在实践中,通常 3 次就足够了。 简而言之,这是两个 AI 之间的一次“拉取请求”,一个提出计划,另一个专注于找漏洞。全程无需人为干预。 3 轮迭代解决了 14 个漏洞 在 Aseem 的文章中,以一个多代理系统的控制面板为案例,循环审查从原计划中找到了 14 个问题: 第一轮(8 个问题):写入端点没有身份验证。Shell 脚本的引用存在错误。数据模式的字段冲突。嵌套数组没有限制。未处理并发问题。仅支持手动测试。 第二轮(剩余 6 个问题):非原子操作的声明。ACL 权限分配过于宽泛。未指定密钥轮换机制。状态建模不一致等问题。 第三轮:所有问题解决,计划获得通过。 ...

2026年3月23日 · Fernando

从 /simplify 到绝地委员会:如何与 Kent Beck、Martin Fowler 和 Mike Acton 一起进行代码审查

Claude Code 提供了一个名为 /simplify 的 slash command,可以自动审查你的代码。我用它检查了一个大幅变更——大约 8 个文件、500 行代码——结果让人有些意外。它确实发现了些我可能漏掉的点,但也带来了不少无用信息,让我浪费了不少时间。 所以我把它拆解了,然后又重新像拼图一样组装回来。 /simplify 是如何工作的 这是 Claude Code 内置的一项功能(无需额外安装)。它会并行运行三个代理,分别从三个不同的角度来审查代码变更: 代码复用(Code Reuse) —— 是否有可以替换新代码的现有工具? 代码质量(Code Quality) —— 冗余状态、复制粘贴、不良抽象、stringly-typed code 等。 效率(Efficiency) —— 不必要的 I/O、未充分利用的并发、内存泄漏等。 这三个代理会各自给出发现的问题,之后系统尝试直接修复它们。 找到的亮点 代码复用代理发现我在测试代码的两处重复了一个完全相同的辅助函数:相同的名字、相同的代码内容,但分布在两个不同的文件中。我把它提取到一个共享模块里,干净利落。 效率代理指出了一个处理循环中不必要的磁盘操作:每次迭代都加载状态、修改后存储、读取数据、重新加载、再存储。写操作重复了两次,而实际上只需要一次。我没注意到这些隐患,但工具发现了。 还发现了一个内存缓冲区在错误路径中没有清除。如果在分配和释放之间发生错误,会产生内存泄漏。这种问题在主路径上已经被处理到了,但显然 copy-paste 草率遗漏了某些细节。 到这里为止,还算满意。三个发现,全都合法且可操作。但 /simplify 的问题并不在于它发现了什么,而是在于它发现了太多不重要的东西。 存在的缺陷 低级别的问题噪音过多。 它建议我删除一个 struct 的字段,因为 “它与一个计算属性是重复的”。这个字段占用 8 个字节,但被代码和测试中的十多处引用使用。做这个改动带来的代码修改工作量,远远超过了省下这几个字节的好处。 缺乏对项目上下文的理解。 它标记了一个并发模式为 HIGH 严重性,并且的确指出这是一个潜在风险。这一点没错,书面上看是合理的。但实际上,这个问题已经在项目的 CLAUDE.md 文档中记录了,工具链中专门配置了 lint 来应对,并且项目内还有一个相关的 issue 在处理。而 /simplify 并不知道这些,因为它只能基于代码变更的 diff 操作,缺乏项目整体的视角。 无法分辨“错误”和“可优化”。 上文提到的双磁盘操作的确效率低下,但并不是错误。而并发模式的问题就是真正的潜在炸弹。这两者的严重性却都被标记为 MEDIUM,优先级看上去一样,这种扁平的优先级划分很难起到实际帮助。 对外部数据强行推荐 enums。 它建议把某些 DTO 中的字段从字符串转换为枚举,但这些字段只是从外部 API 拉取后用于显示。把它们改成枚举需要自定义解码逻辑,却提供不了任何实际好处——如果对方 API 增加了新值,这样的枚举反倒会导致解析出错。枚举在这种情况下,不如保持字符串更稳妥。 ...

2026年3月9日 · Fernando