通过静态形状检查(补丁能否干净应用、是否改动了不该改的文件)和有限运行时冒烟测试(Git worktree + 快速验证),在人工 review 前过滤掉不合格的 AI 生成补丁。
一个生成的补丁可能看起来逻辑通顺、通过 CI,却仍然在没人计划检查的地方出了问题。通常的失败不在于模型有多聪明,而在于审查流程把「看起来没问题」当成了「可以安全合并」。本文描述了一个轻量的可复现验证框架,它让 AI 生成的补丁在任何人花时间看 diff 之前,先过两道廉价的关卡——静态形态检查和有边界的运行时冒烟测试。
此模式所用的环境是 MonkeyCode 的免费模型访问和免费服务器选项。声明:本文作为 MonkeyCode 产品推广内容的一部分撰写。
两道关卡的作用
第一道关卡是形态检查。它回答三个问题:
补丁能否干净地应用到当前 HEAD?
它是否只修改了它声称要修改的文件?
它是否避开了受保护的路径,比如迁移文件和密钥文件?
第二道关卡是运行时冒烟测试。它在一个一次性 Git worktree 中应用补丁,运行一个窄范围的冒烟测试目标,如果目标失败或超时则拒绝补丁。
两道关卡都不证明正确性。它们充当分诊过滤器:拦住那些不值得人工审查的补丁,把真正有风险的候选留给人类处理。当你在一个免费模型端点上同时生成多个候选补丁时,这就特别有用了。你可以让验证框架丢弃噪音,只审查那些存活下来的候选。
下面的脚本用标准 Git 和 shell 实现了两个关卡。将它保存在仓库中作为 tools/ai-patch-gate.sh,赋予可执行权限,然后针对候选的 .patch 文件运行它。
#!/usr/bin/env bash
set -euo pipefail
repo="${REPO_DIR:?set REPO_DIR to the repository root}"
patch_file="${1:?usage: tools/ai-patch-gate.sh /path/to/candidate.patch}"
timeout_s="${TEST_TIMEOUT_S:-120}"
# Gate 1a: the patch must apply to HEAD without conflicts.
if ! git -C "$repo" apply --check "$patch_file"; then
echo "REJECT: patch does not apply cleanly to HEAD" >&2
exit 2
fi
# Gate 1b: reject patches that touch sensitive or high-risk paths.
scope="$(git -C "$repo" apply --numstat "$patch_file")"
if grep -Eq '(^|/)migrations/|(^|/)secrets/|(^|/)\.env' <<< "$scope"; then
echo "REJECT: patch touches a protected path" >&2
echo "$scope" >&2
exit 3
fi
# Gate 2: run the smoke target in an isolated worktree.
scratch="$(mktemp -d)"
git -C "$repo" worktree add --detach "$scratch" HEAD >/dev/null
trap 'git -C "$repo" worktree remove --force "$scratch" >/dev/null 2>&1 || rm -rf "$scratch"' EXIT
git -C "$scratch" apply "$patch_file"
if ! timeout "$timeout_s" make -C "$scratch" smoke-test; then
echo "REJECT: smoke-test failed or timed out" >&2
exit 1
fi
echo "ACCEPT_FOR_REVIEW: apply, scope, and smoke-test passed"
冒烟测试目标应该针对本次修改定制,而不是完整的测试套件。对于修改了缓存层的补丁,目标可能是重新构建模块并运行一次读写序列。对于 API 补丁,它可能是启动服务器并针对受影响的路由发一个请求。
如果免费服务器选项提供 shell,同样的脚本可以在那里运行。如果它是 Web 运行时而非 shell,把 make 那行替换为对部署候选版本的一个请求,并保留超时设置。免费模型访问适合产生候选补丁文件来喂给验证框架;验证框架本身不依赖任何特定模型。
如何解读结果
这张表比单一的 CI 通过/失败更有用,因为它把可自动检测的失败和需要人工审查的候选区分开了。验证框架通过不应该被解读为对补丁的认可;它只意味着补丁满足了你预先设定的最低条件。
局限性及何时跳过此方案
验证框架只能捕获你的冒烟测试已知的失败类别。补丁可以通过删除本该失败的测试来通过,可以改变冒烟目标未覆盖的行为,可以通过引入一个不会超时的慢路径来通过。它不验证安全属性、数据库迁移、用户可访问性或对有状态服务的影响。
如果一个补丁无法以有界的方式进行测试——例如,一个需要生产数据副本的 schema 迁移,或者一个失败的冒烟测试仍然可能有副作用的支付流程变更——不要把这个验证框架作为主要控制手段。同样的原则也适用于没有可复现冒烟目标的团队。
这种方法也不是人工审查的替代品。它的意义在于把审查时间花在那些最可能有微妙问题的候选上,而不是完全取消审查。
从一个模块开始
最小可用的版本不是一个完整的 CI 流水线。选一个具有可复现冒烟目标的模块,加上这个脚本,然后针对接下来五个生成的补丁运行它。记录出现最多的拒绝原因;这会告诉你生成器在哪些地方出错了,以及需要加强哪些规则。
小的、自动化的拒绝规则通常比更强的模型更能改善审查队列。一旦验证框架运行起来,你就可以通过补丁没有产生的失败来评估它们,而不是看它们看起来有多自信。
如果你想用一个免费模型 prompt 和一个免费服务器来尝试这个模式,先为一个模块定义冒烟测试目标,然后把下一个生成的补丁喂给这道关卡。