从理论到 CI:AI 编码质量闭环的五道机器把关

发布时间:2026/9/6 4:49:50
从理论到 CI:AI 编码质量闭环的五道机器把关 阅读前提自动化水平 L1–L5 的分层人站在哪道闸门见《AI 编码自动化水平与失控防线》——本文用到的L4指自动调度 CI 联动人站在合并闸门与架构审批这一档。免审的兑换法则与三道防线见《免审的代价AI 编码里省掉的每一次人眼审查都要有东西兑换》文中免审分层第 N 层均指该篇的三层划分。另有两个贯穿全文的概念可证伪能被反例推翻的证据声明不算证据才算同生同源代码与测试由同一轮生成只能证自洽、不能证符合独立规格。核心论点前两篇分别给了防线分层与兑换法则——但方法论停在文章里对AI 大量生成、没做 review的项目毫无意义。本文把两篇理论落到 CI 和代码五道机器把关从输入约束到客观验收每道都可执行、可证伪、不依赖 Agent 自述。其中变异测试、改测试放宽检测、生成时安全扫描、提示词版本化四道已在 CI 与代码层完整生效离线 eval 已接 CI但七道判据里验收判据与自洽判据待接入真实调度器后才全面生效——下文如实标注每道落地状态。为什么要做这件事一个真实处境项目里大量代码是 AI 生成的人没有时间逐行 review。这意味着两篇方法论里人在回路的环节被架空了——L4 说人站在合并闸门但闸门后面没人。补救方式不是逼人回去逐行看而是用确定性工具把人眼审查替换成机器可证伪的凭证让流程里可被确定性验证的那一段在没有人盯的情况下也不失控。五道把关对应的就是输入约束版本化、伪绿/放宽防住、生成时安全兜住、客观度量代替人眼。五道机器把关#把关交付物验证什么落地状态1离线 eval评测脚本与固定考题集流程级回归度量不证符合规格独立子仓库 CI 回归评测门禁2变异测试变异注入脚本免审分层第 2 层测试必须失败CI 变异检测门禁3改测试放宽检测测试改动审查脚本免审分层第 3 层堵非法消红CI 测试放宽检测门禁4生成时安全扫描安全扫描脚本生成时盲区密钥 / 危险函数 / 依赖CI 安全扫描门禁5提示词版本化提示词管理模块prompt 改动可 review / 回滚代码重构已集中维护并版本化下面逐道说明其交付物、验证方式与落地状态。1. 离线 eval用固定考题代替人眼评测脚本里维护一组固定考题覆盖租户限流、注入闸、隐私脱敏、退避重试、语义缓存、契约测试、金额校验、租户隔离等场景由驱动脚本拉起编排流程跑批再用七道确定性判据打分粒度判据——任务拆分过粗即判失败伪绿fakegreen判据——内联含恒真断言、占位空实现即判失败验收判据——考题约定的验收关键词必须命中反模式判据——禁止出现的写法如恒真断言不得出现语言判据——测试产物语言不得错配如期望 Python 却生成 Java/JS 测试即判失败自洽判据——真实模式下执行生成的测试确认 code 能被其 tests 跑绿dry-run空跑不真正调用模型生成下标记为 SKIP仅证自洽不证符合规格变异判据——对产物注入变异后其生成的测试必须转红否则说明测试没真正锁定逻辑落地状态评测引擎以 git submodule独立子仓库标识符见文末「代码锚点」形式独立维护CI 里已有回归评测门禁接成合并前门禁但七道判据的生效程度不一——粒度、伪绿、反模式、语言四道已可跑通验收判据与自洽判据待接入真实调度器后全面生效dry-run 下自洽判据标记为 SKIP。价值它评的是这套编码流程靠不靠谱不是某一次任务。改 prompt / 换模型 / 调门禁后跑一遍看通过率曲线是否退化——这是没有 review 时最低成本的客观凭证。实现注评测引擎是一个独立子仓库。七道判据与评测引擎已抽离为独立项目只负责打分、不负责生成以 git submodule 形式引入本仓库。它与被测项目零依赖解耦评测引擎只定义驱动接口、考题数据结构与七道确定性判据纯函数本仓库用一个驱动实现去包住真实的编码编排流程、用本项目的考题集提供输入注入后即可驱动。这样评测引擎能脱离本项目用脱机自测的假驱动验证判据本身灵不灵。eval 测的是什么流程回归不是单任务符合性eval 把整套流程prompt 模型 门禁在一份固定考题集上跑批度量的是跨任务、跨时间的总体通过率与退化趋势把关回答“这份代码对不对这份规格”per-task conformanceeval 回答“换 prompt / 模型 / 门禁后流程整体还稳不稳”pipeline regressioneval 的路径人工固定考题集离线 eval跨任务/跨时间流程总体通过率与退化趋势把关的路径人工设计规格生成五道把关单任务代码是否符合这份规格两条路径的输入都由人写但回答的问题不同一条问这份代码对不对这份规格另一条问流程整体还稳不稳。独立性铁律eval 的考题集必须独立于单任务设计规格。两者都是人写的——若同源、同人、同假设就可能一起错spec 漏了一种情况考题集也没覆盖通过率照样漂亮真实需求却没满足。考题集应来自独立渠道不同工程师、生产事故复盘、真实用户反馈才能补上原 spec 作者的盲区。一个分工示例下文的题量与通过率均为假设推演用于说明两类度量的分工非实测数据以对话历史摘要接入 L2 / L3 记忆为例人工设计规格写明L2 每 5 轮触发一次、L3 兜底取最后一条用户消息。五道把关据此验证生成代码——这验证的是代码符合这份规格。离线 eval 的考题集是跨域任务限流 / 记忆 / 脱敏 / 重试…。某次 prompt 调成更激进地复用既有工具重跑 eval总体通过率下跌且掉分的集中在记忆类子题。这是单任务把关给不了的流程级回归信号——聚焦记忆的单项任务门禁仍绿流程整体已在退化。共错的反例若规格漏写L3 必须取最后用户消息原代码取成了最后一条助手消息且考题集由同一人按同一心智模型编写、也没覆盖用户 vs 助手那么把关与 eval 双双通过缺陷静默上线。只有考题集交给独立视角编写才能兜住这类 spec 作者的盲区。边界机器把关最多证到哪一步把这一节串起来机器把关能兑现的承诺有一个明确天花板能减少人审的只有这一块当人类先写好明确的接口契约 测试矩阵即设计规格agent 通过调用「生成代码 生成测试」的同生同源工具产出确定性代码并运行这套测试建议时——机器可以验证 code↔tests 自洽从而把这部分的人工 review 兑换掉。其余代码生成必须人做最终确认凡不是「接口明确 测试先行 工具确定性生成」的产出机器只证自洽、证不出符合独立规格最终确认权都在人。换不同的 AI / agent 来写代码和测试也不创造独立性独立性来自测试从规格派生、编写时不读实现不来自生成器的数量或身份。若测试 agent 的上下文里仍喂着代码看着答案写考卷即便换多个 agent 也只是把同生同源换了个背锅者真正起作用的是把测试 agent 的输入从代码换成规格/契约并配只吐签名的工具让实现体物理上读不到而变异测试仍须保留兜底——独立派生不等于断言够紧。逻辑分层视图把关层按 ①–⑤ 编号CI 执行序见下文「闭环在 CI 里怎么串」生成层 · 按能否从规格推导分流第0道 · 人不可省是否机器把关层 · 五道证自洽/灵敏度不证符合① 离线 eval流程级回归度量② 变异测试注入缺陷必红③ 改测试放宽检测④ 生成时安全扫描⑤ 提示词版本化写 / 审 设计规格接口契约 测试矩阵可推导部分 → 代码生成器确定性、免审需判断部分 → AI 编码工具 / 人业务规则、边界、集成确定性产出已证自洽合并 / 上线人不逐行盯阻断 PR非确定性产出最终确认权 → 人读图要点红色人不可省写规格 审非确定性产出蓝色生成器吃确定性免审橙色AI 吃判断性正是把关对象绿色五道机器把关只证自洽灵敏度不证符合。独立性来自SPEC规格不来自生成器或 AI 的身份。换句话说五道机器把关不是把人移出回路而是把人从逐行盯确定性产出里解放出来挪到写规格、审规格、确认非确定性产出这两头它最多能保证在规格到位的前提下确定性那段不用人盯它保证不了的是没有规格兜底的生成可以免于人审。一个贯穿示例考题新增按租户维度的令牌桶限流约定验收关键词「租户 / 429 / 令牌桶 / 限流」、黑名单「恒真断言」。若产物含恒真断言则粒度判据 PASS、伪绿判据 FAIL、反模式判据 FAIL、变异判据 FAIL注入变异后测试仍绿说明断言根本没锁定逻辑→整题 FAIL。缺陷没让构建变红却被确定性判据抓出。通过规则粒度、伪绿、变异三道为硬门槛任一不 PASS 即一票否决验收、反模式、自洽、语言四道不判 FAIL 即可产物缺失时记 SKIP不当失败也算。第 1 道给出的是流程级信号——它告诉你总体在退化但指不出是哪一处退化。剩下四道是产物级把关各自盯住一类具体的失效形态定位能力更强。先看最容易被测试全绿掩盖的那一类。2. 变异测试注入缺陷测试必须失败变异注入脚本对限流、循环守卫等纯逻辑模块注入确定性变异布尔翻转 / 比较符翻转 / 算术边界再跑对应测试若测试仍全绿则判为未捕获变异 伪绿证据阻断 PR。本地实跑限流模块 6 个变异、循环守卫 3 个变异捕获率 100%变异检测由 CI 配置里的变异检测 job执行结果落入本仓库的评测结果目录——印证了测试真能感知注入缺陷兑现《免审的代价AI 编码里省掉的每一次人眼审查都要有东西兑换》的核心论点。为什么需要它若只以测试全绿作为合并门禁AI 改出恒真断言或翻转比较符后测试依旧全绿缺陷就静默上线——这正是《免审的代价AI 编码里省掉的每一次人眼审查都要有东西兑换》所说的假绿。变异测试把测试绿变成测试绿且确实能抓错让门禁本身可被证伪。补充多加异常/边界测试替代不了变异测试。前者回答测了哪些场景覆盖度后者回答测试够不够敏感、改错了会不会红可证伪性。异常用例也是凭假设列举的只要断言写得松如用宽泛的异常捕获代替具体异常场景覆盖再多也可能假绿——变异注入直接翻转比较符与相等判断验证的是测试会反应这件事本身。两者互补异常测试是被测物变异测试是校准仪表。大白话类比把测试想成烟雾报警器。普通测试只证明报警器装了、按一下会响测试全绿它没证明真着火时会不会叫。变异测试就是故意在厨房点根烟看报警器响不响——点了烟还不响说明这报警器是个摆设假绿。多加异常测试等于多装几个报警器但没验证它们灵不灵变异测试验证的是报警器本身灵不灵。3. 改测试放宽检测堵住最隐蔽的非法消红测试改动审查脚本基于代码差异检查 PR 是否改动已有测试文件的断言删除 / 注释断言 → 阻断严格判断相等 / 同一性改成宽松判断包含 / 非空即可→ 标记阈值放大如把预算上限放宽一个数量级→ 阻断为什么需要它上一节的变异测试管的是测试灵不灵——但它抓不到有人把测试手动改钝的情况。设想 AI 为了让 CI 变绿悄悄把相等判断改成包含判断、把阈值放大一个数量级测试既没被跑红也不是自动假绿而是被人为放水了。这种非法消红变异测试看不见它只看注入缺陷后测试红不红不 Review 测试本身的改动。测试改动检测专盯这一步凡是改已有测试断言不是新增一律要求声明理由、否则阻断——把撤防动作暴露出来。大白话类比变异测试是点了烟看报警器响不响测试放宽检测是有人趁你不在把报警器的灵敏度旋钮拧到最低让它对烟没反应。前者验仪器后者防人为破坏仪器。两者互补一个防测试太钝一个防测试被人为调钝。落地状态CI job 形态任一检出即阻断合并与变异测试同属「无人 review 时的合并闸门」。负向测试把一条精确断言放宽成非空即可脚本成功检出并阻断。新增测试文件合法免审改动已有测试需声明并分离到独立 PR。前两道都盯着测试——一个验测试灵不灵一个防测试被改钝。但即便测试完全有效仍有一类风险它们都看不见代码本身引入了危险的东西而测试对此毫无表态。4. 生成时安全扫描运行时护栏覆盖不到的盲区隐私脱敏与注入闸只管流量但 AI 生成的代码本身可能引入硬编码密钥、危险函数、危险依赖。安全扫描脚本提供内置零依赖规则硬编码密钥 危险求值 / 反序列化 / 命令执行类写法可选接完整静态分析、可选依赖漏洞扫描负向测试注入硬编码密钥加危险求值成功抓到高危项并阻断。至此四道都在生成之后检查产物。但还有一类退化产物本身完全合法、四道全绿——问题出在生成它们的指令变了。这需要往源头追。5. 提示词版本化输入约束也要可 review原提示词散落在编排器字符串里改一处影响所有任务却无感知。提示词管理模块集中维护多阶段模板并带上版本号与变更记录。CI 跑评测即为回归基线提示词改前改后通过率对比退化一眼可见。落地状态代码重构已集中维护并带版本号与变更日志标识符见文末「代码锚点」——哪版提示词导致通过率退化可逐条追溯。第 5 道属于输入侧前置——它不是在生成后把关而是在生成前把约束版本化因此置于下文 CI 执行序的顶端输入处。闭环在 CI 里怎么串执行序为输入约束第 5 道提示词版本化作为代码改动常驻、不单独成 job→ AI 生成 → 生成时安全扫描 / 变异测试 / 测试放宽检测 → 离线 eval 汇聚为流程级通过率 → 输出可证伪的机器证据兑换原本的人眼审查。任一判失败即阻断合并。每一道都不依赖Agent 说自己对了而是用可证伪的机器证据兑换原本的人眼审查——这正是《免审的代价AI 编码里省掉的每一次人眼审查都要有东西兑换》里说的凭证。以上只是机器闭环——非确定性产出仍回到上图的人闸并非免于人审。没有它会发生什么为说明每道把关的不可替代性下面给出撤掉该道时静默发生的失效场景——这些场景单靠 Agent 自述或测试全绿都发现不了撤掉生成时安全扫描AI 顺手写入一个硬编码密钥运行时护栏只管流量完全看不到代码层风险密钥随代码入库。撤掉离线 eval换模型或改提示词后流程悄然退化没有任何客观曲线能证明变差了回归靠运气。撤掉提示词版本化某次提示词微调让所有任务输出格式漂移因无版本锚点连改了什么都难以回溯。变异测试与测试放宽检测的失效场景分别见第 2、3 节的为什么需要它此处不重复。这三类失效与前述两类的共同点它们都不会让测试变红也不会让构建失败——这正是免审最危险的地方也是五道机器把关存在的理由。落地位置把关在编排器里如何被强制执行前五道把关在本文是「方法论 CI job」形态在本仓库的实际落地里它们被编排器的阶段状态机当成硬性闸门逐道卡住而非仅在 CI 跑一遍。落地位置与接线离线 eval第 1 道回归评测脚本拉起本项目的考题集在固定考题集上跑批对照评测基线条目判退化趋势CI 的回归评测 job把它接成合并前门禁。质量门覆盖率 / 静态扫描在「test 后、merge 前」由编排器的质量门检查函数强制——缺覆盖率或缺少静态扫描产物即标阻断标记文本见文末「代码锚点」。它是 test→merge 之间的额外硬闸与变异 / 放宽 / 安全扫描同类。变异 / 放宽 / 安全扫描第 2–4 道保持 CI job 形态CI 配置里的变异检测 / 测试放宽检测 / 安全扫描 job任一失败即阻断合并等价于「无人 review 时的合并闸门」。接线保真由接线漂移自检脚本自检设计门 / 合并门 / 质量门 / eval / PR 任一接线漂移都会被判失败确保「已在 CI 与代码层生效」可被机器反复核验而非停在文章里。注设计门禁与合并门禁是L4 人闸不在「机器把关」之列——它们处理机器证不出符合性、必须人拍板的情况机制见项目内设计门禁文档。如何复用这套把关五道把关彼此独立可挑最痛的几道先落地不必一次全上。按投入小、收益直接的顺序建议先上变异测试 测试放宽检测门槛最低两者都是对现有测试集做静态/动态校验不依赖新增业务代码CI 里各加一个 job 即可当天能跑起来。再上生成时安全扫描零依赖规则可立即拦截硬编码密钥与危险写法接bandit/ 依赖扫描作为可选项逐步打开。提示词版本化把散落的提示词收口到带版本号的管理模块改动即留痕是后续 eval 回归的前提。离线 eval 放最后它需要一套稳定的驱动与考题集前期可用最小骨架先占位待前三道跑稳再接真实调度器、让验收判据生效。CI 里的推荐执行顺序生成时安全扫描 → 变异测试 → 测试放宽检测 → 离线 eval提示词版本化作为代码改动常驻不单独成 job。任何一道判失败即阻断合并等价于无人 review 时的合并闸门。核心要点机器把关只证自洽、不证符合独立规格它能确认生成的代码能跑通生成的测试却证明不了产物符合外部需求——别把它当成正确性的证明。五道把关互补、不可互相替代离线 eval 看流程级退化变异测试看测试灵不灵测试放宽检测看测试被没被改钝安全扫描看注入与密钥提示词版本化让所有退化可追溯。把关的独立性来自规格不来自生成器换个模型或 prompt 门禁仍能拦才算真独立依赖生成器自述的通过一文不值。