AUTHOR: Locez
VERSION: 1
我不是在审查贡献,而是在和不承担后果的 AI 代码生成器对抗
这篇文章记录一次 kotonoha 的维护事故。
它不是一篇关于“AI 能不能写代码”的文章,我想记录的是另一件更具体的事:当一个没有明确范围和人工检查点的 AI agent 被接入公共仓库时,维护者会承担什么样的成本。
这次事故的结果很简单:我原本准备按照自己的计划重构项目,一觉醒来之后,仓库里出现了二十个左右的新 PR。通常来说即便使用 AI 进行审查,维护者也必须明确给 AI 大量的指示与关注的点,考虑 AI 所不会考虑的事情。这正是人类维护者该负有的责任。
我的重构计划
kotonoha 的 Issue #16 讨论的是一次平台层重构。它涉及平台探测、Wayland 能力、窗口适配器、拖曳策略和输出生命周期等问题。
这份计划对我来说是一个执行顺序,而不是一组可以被外部自动领取的任务。每一步都需要先确认现有行为,再决定边界,最后用测试和真实环境验证。它的价值不只是列出“要改哪些文件”,还包括哪些事情暂时不能一起改。
有许多细节决策、纠正是完全不会体现在 bilihud 的公开重构记录还有 PR 记录里面的。
但一个自动化 agent 很容易把公开 Issue 解释成另一种东西:这里有一批尚未完成的工作,可以自行拆分并开始实现。
公开 Issue 是讨论入口,并不自动构成实现授权。这次事故首先发生在这个边界没有被明确建立的时候。
在一个周六的下午,当时我在影院看电影,突然看到了 20 个 PR,当时心情就有点不对了。但是还是勉强回复了:我晚点回去看看。
然后一个美好的周六,我处理这些低质量 PR 通宵了。然后周日的下午,我终于开始受不了,开始无脑点合入,想着后面再重新重构一下吧。一个美好的周末就这样结束了。
以为结束了么?没有的,2 天后的周二,提交者又在群组说 DDos 一下我,我一看又发了 20 个 PR,这一次我真的累了,我在群里跟他苦口婆心说了利弊,跟为什么。但是对方一种避重就轻的回复让我非常烦躁,我甚至想过直接扔掉这个项目了。
最后我又把这个新的 20 个 PR 合入了,随后我把 Pull Request 关闭了。
另外新增依赖什么的,因为提交者使用 Gentoo 且是 Gentoo-zh overlay 维护之一,所以更新了 Gentoo 打包,deb 合 rpm 有 CI,AI 可以自己修,但是 Arch 上的包直到现在都是坏的,AI 不会自己去修,因为提交者根本不思考,不考虑项目到底做了什么,凭着一个 AI 觉得自己天下无敌。
这不是普通的 AI 辅助
这批 PR 不是贡献者用 AI 辅助完成几个局部函数,或者说经过设计的,而是把整个提交和迭代过程交给了 AI。
贡献者本人说明,他使用 Claude 作为主 agent,再让 GPT 负责具体实现,然后让两个 agent 围绕如何复刻 bilihud 的重构模式和 review 持续迭代。
按照这个工作方式,AI 自己完成了下面这些工作:
- 阅读 bilihud 仓库和已有 PR,并从中学习;
- 复刻 bilihud 仓库的重构计划;
- 拆分改动并生成代码、测试和 PR 说明;
- AI 根据维护者的 review 继续修改;
- 每次都是回复问题成立,已经修复
这形成了一个持续循环:
1 | AI 生成改动 -> 提交 PR -> 维护者用 AI 指出问题 -> AI 修改 -> 提交 |
在这个循环里,review 不再只是一次独立审查,而成了 AI 下一轮修改的输入。维护者需要指出每个边界,AI 再根据这些边界继续生成代码。
问题在于,架构判断和最终验收并没有由贡献者本人承担。一个主 agent 加一个实现 agent,不会因为彼此能够迭代,就自动获得软件工程经验。
软件工程中有很多事情不是“把代码写出来”就能解决的:哪些改动现在不应该做,哪些兼容性必须保留,哪个边界属于平台层,哪种失败可以接受,怎样拆分才不会让主线失去可验证性,以及什么时候应该停止继续扩大范围。这些判断依赖项目历史、运行时事实和维护者对长期成本的承担。
AI 可以提出方案、生成实现、运行测试,也可以根据 review 修改代码,但它不拥有这些判断的责任。它可以持续生成下一份看起来完整的修改,却不承担主线回归、发布故障和后续维护的后果。
AI 能看到什么,不能看到什么
最初的仓库里没有一个有效性的约束 AGENTS.md。
bilihud 的公开 PR 提供了大量可以模仿的内容:目录结构、命名方式、平台抽象、提交格式和重构步骤。AI 可以从这些公开改动中拼出一个合理的实现模板,却无法仅凭这些 PR 知道 kotonoha 哪些地方与 bilihud 不同,哪些协议事实不能照搬,哪些能力必须由平台层负责。
但是 bilihud 的重构 PR 里面没有体现的是我专门在迭代过程中多次优化 AGENTS.md,以确保项目能顺利高质量推进。这就导致这 20 个 PR 写出来的代码全是面条代码,哪还是重构代码。
直到我后来专门指出了这个问题,说这都没抄到精髓,后来提交的 PR #43 才把大量工程约束写入 AGENTS.md,新增内容达到 337 行,覆盖架构边界、强类型、异步生命周期、平台能力、测试证据和维护流程。
这个时间顺序很重要:约束是在一批改动已经产生之后才被补进仓库的。AI 并不具备主动优化项目的能力,一个重构计划,连 AGENTS.md 居然都不是第一步,这是何其的胆大与以为自己天下无敌?
即使后来补上 AGENTS.md,它也不能替代授权、范围和停止条件。文档只能告诉 agent 什么是约束,不能替维护者决定哪些工作现在应该做。这些只是提升了一下 AI coding 的下限,决定上限的永远是 人
这件事的责任不在“AI 会犯错”
AI 会犯错,这是预期行为。真正的问题是,AI 被放进了一个没有明确授权边界的公共提交循环里,而发起这个循环的人没有承担与输出规模相匹配的架构判断和验收责任。
AI 不拥有项目,也不维护用户反馈。它不会为主线回归、发布事故或未来的维护成本负责。它只会继续生成下一份输出。
维护者却必须承担所有后果:
- 判断改动是否符合项目架构;
- 确认测试是否覆盖真实行为;
- 检查发布和构建流程;
- 处理跨 PR 的依赖和冲突;
- 在合并后恢复能够长期维护的代码结构。
因此,问题不是“能不能使用 AI”,而是“谁拥有方向、边界和停止权”。如果这些责任没有由人承担,AI 辅助开发就会变成把验证成本转嫁给维护者。
这次事故改变了什么
贡献者本人没有软件工程的架构设计经验,却让 Claude 负责主控、让 GPT 负责实现,再用两个 agent 的持续迭代代替自己的工程判断。这不是我从 PR 文案推断出来的,而是他自己对工作方式的说明。
这件事的关键不在于他不会写某一段代码,而在于他把本应由自己承担的架构责任交给了 agent:从一个公开的重构计划自行扩大出一批跨模块改动,把 review 当成下一轮生成的输入,最后让维护者成为唯一的架构负责人、测试负责人和返工负责人。
这次事故没有改变其他人,但是改变了我在处理这种事情的边界,贡献者是 gentoo-zh 群友,我为了避免一些冲突,早期隐忍了,最终的结果是变本加厉,我苦口婆心的讲述正面与反面并没有起到作用。为了一个项目的健康发展,这些行为应该也是零容忍的,因为伤害的不仅是我,甚至是使用关注这个项目的人,一看这么多面条代码,还敢用吗?
结语
我并不反对 AI 写代码。
我反对的是,把架构判断和责任一起外包给 AI,然后把维护者的时间当成免费的验证服务。
这次事件里,无脑的代码生成的速度超过了维护者审查的速度。结果不是项目获得了更多贡献,而是维护者被迫承担了一份没有请求、没有预算、也没有停止条件的工程工作。
我原本只是在按照自己的计划重构项目。后来,我不得不花费真实的人和 AI,去对抗一台不承担后果的代码生成器。
