AI 生成 patch 时常引入新依赖包或升级传递依赖,锁文件变更比逻辑变更风险更高——是替你做了供应链决策,而非代码修复。
AI 生成的补丁最危险的部分不是你审查的代码,而是你一扫而过的依赖图。当一个免费模型重写一个函数时,它通常会导入一个辅助包或提升一个传递依赖的版本,以使代码能够编译。这单独的一行 lockfile 携带的风险可能比整个 diff 还要大,因为它是一个替你做出的供应链决策。本文认为,每个 AI 补丁都需要在逻辑审查之前进行一次依赖审计,而免费服务器正是运行它的合适场所。
审查者关注 diff,因为 diff 是逻辑所在之处,但 lockfile 变更看起来像是机械性的,通常只会得到一个橡皮图章。一个名为 utils 或 helpers 的新包不会像被重写的认证流程那样触发同样的警报,即使这个包是一个新的供应链入口点。模型选择这个依赖是因为它很方便,而不是因为你审核过它的维护者、许可证或发布历史。
更深层的问题是 AI 模型优化的是编译结果,而不是最小的依赖足迹。它们会愉快地添加一个与你已有功能重复的包,因为训练数据显示类似仓库中广泛使用这些导入。因此,依赖 diff 不是补丁的副作用,而是模型替你做出的决策,后果由你承担。
忽视这个决策的成本会随着时间累积。每一个新依赖都意味着新的更新周期、新的传递漏洞集合,以及你对其激励机制一无所知的新维护者。一个单独添加的包就可以使你的供应链暴露面积翻倍,而添加它的 AI 模型永远不会负责维护它。
该工作流有五个步骤,每一步都是机械性的,足以编写成脚本并在免费服务器上运行。
第一步之所以能从免费模型访问中获益,是因为你可以在确定任何一个补丁之前生成多个候选补丁并比较它们的依赖占用情况。我使用 MonkeyCode 的免费模型访问来进行这种比较,当两个补丁通过相同测试时,lockfile diff 成为决胜因素。披露:本文是 MonkeyCode 产品推广的一部分。
第四步是免费服务器发挥作用的地方,因为依赖变更可能以单元测试从未见过的方式破坏构建。MonkeyCode 的免费服务器选项提供了一个可丢弃的环境,你可以在其中安装新的 lockfile、运行完整测试套件,并检查导入时故障,而不会影响你的生产流水线。下面的脚本自动化了这种比较。
该脚本在补丁前后捕获 lockfile,然后提取新增和移除的包以供审查。
#!/usr/bin/env bash
set -euo pipefail
cp requirements.txt requirements.before.txt
git apply patch.diff
pip freeze > requirements.after.txt
diff <(sort requirements.before.txt) <(sort requirements.after.txt) \
| grep -E '^[<>]' || echo "No dependency changes"
对于 Node 项目,等效的做法是使用 npm diff --diff=package.json 和 npm ls 来追踪依赖树。
#!/usr/bin/env bash
set -euo pipefail
cp package.json package.before.json
git apply patch.diff
npm install --package-lock-only
diff <(jq -S '.dependencies' package.before.json) \
<(jq -S '.dependencies' package.json) || echo "Dependency changes found"
npm ls --all > dependency-tree.txt
第二个脚本的输出给了你每个新包的完整传递闭包,这正是你制作分类表所需的数据。
每一种依赖变更都属于四个类别之一,每个类别有不同的门槛。
可疑新增是最重要的类别,因为这是模型无法用测试来证明其合理性的类别。免费服务器可以证明代码能工作,但它无法证明维护者是可信的,所以可疑新增的门槛是手动审查或拒绝。良性新增是免费服务器增加最多价值的类别,因为在新目标上的快速构建和测试循环可以确认该包不会破坏任何东西。
减少依赖漂移最简单的方法是在模型生成补丁之前对其施加约束。在你的 prompt 中加一行:"不要添加新的依赖,除非标准库无法表达该行为",模型就会经常使用现有包重写解决方案。
You are patching an existing codebase.
Constraints:
- Do not add new packages unless the standard library cannot do the job.
- If a new package is required, explain why in one sentence.
- Prefer modifying existing imports over adding new ones.
Diff:
{DIFF}
这个 prompt 不能消除问题,因为模型仍然会找借口导入包,但它降低了频率。依赖审计仍然是关卡,而 prompt 只是关卡上游的一个过滤器。
考虑一个向现有 API 端点添加 CSV 导出的补丁。模型编写了这个功能,diff 看起来很干净,但 lockfile 显示一个新包叫 fast-csv,发布日期是上周,而且没有 README。逻辑审查会通过,因为代码能工作,但依赖审计将该包标记为可疑,因为其来源不清楚。
免费服务器运行揭示了真正的问题:新包引入了一个传递依赖,与你现有的日期库冲突,而这种冲突只在导入时才出现。Pull Request 中的单元测试从未捕获到它,因为他们对 CSV 模块进行了 mock。依赖审计在几分钟内捕获了它,修复方法是用标准库实现替换 fast-csv。
依赖审计假设你的项目有 lockfile,这排除了那些在运行时解析依赖或在构建时将所有依赖打包进仓库的项目。它还假设免费服务器能够访问包注册表,因此空气隔离环境需要不同的验证路径。免费模型访问和免费服务器容量是限流和资源受限的,所以在构建流水线之前请查看当前计划文档。
有严格依赖白名单的团队已经在 CI 中内置了这个关卡,他们会发现审计是多余的。手动审查每个 lockfile 变更的团队根本不需要这个脚本。这个工作流在最有用的地方是——依赖变更被默认批准的地方,而这正是那个危险的默认设置,让 AI 补丁无声无息地扩大你的供应链。
依赖 diff 不是机械性的产物,而是模型在没有你参与的情况下做出的供应链决策。在逻辑之前审计 lockfile,并在免费服务器上运行审计,这样判决基于证据而不是感觉。能编译的包不是你应该信任的包。如果你定期审查 AI 补丁,在下一个补丁落地之前将依赖审计加入你的检查清单。