返回 AIPA 笔记
AIPA Day 19

阻断式 CI eval gate — 让"尺子"挡住 merge

阻断式 CI eval gate — 让"尺子"挡住 merge

2026-07-03
eval-gateci-cdeval-driven-developmentbraintrust

日期: 2026-07-03 阶段: Phase 1 - 产品定义×评测×可观测底座 标签: #eval-gate #ci-cd #eval-driven-development #braintrust

核心问题

W1 已经证明「尺子先于引擎」:金标数据、规则基线、eval 数字在写任何 LLM 代码前就入了 CI(evalRuleBaseline 的断言已在 src/aml/__tests__/aml.test.ts)。但 W1 的 gate 是布尔单点——recall 低于门槛就红。一旦 P3 把规则换成 LLM,输出变成概率分布,单点门槛会立刻暴露三个病:(1) 30 案小集上一次跑分 95% 置信区间约 ±0.07,门槛踩在噪声带里会随机误杀;(2) LLM-judge 每条都跑,CI 成本飙到 $27/PR 量级,两个月内被团队偷偷关掉;(3) 只有「均值过线」没有「相对基线是否退化」,慢漂移完全测不出。

今天回答的工程问题:怎么把单点 gate 升级成 eval-driven development 的五道门,既能真正挡住质量回退,又不会严到逼团队绕过它——这是阶1「可观测底座」与本仓库 .github/workflows/ci.yml 的实际衔接设计。

关键内容

A. eval-driven development 的五道门(Braintrust / FutureAGI 模式,2026)

把「写 evals 就是写 PRD」(Aman Khan, 2026-04)落到流水线,得到一条从代码到生产的递进闸门链,每道门只解决前一道解决不了的失败:

代码改动
  │
  ├─ 门1  lint / 确定性检查 ──────► 格式、引用存在性、字段完整(零方差、亚毫秒)
  │
  ├─ 门2  离线 eval(PR gate)────► 金标集 100-200 案,绝对地板 + 相对 delta gate
  │
  ├─ 门3  成本预算门 ─────────────► $/案件 上限;超预算阻断(防 judge 成本失控)
  │
  ├─ 门4  影子 eval(shadow)─────► 0% 用户可见,在生产真实 trace 上重放新版本
  │
  └─ 门5  canary + 自动回滚 ──────► 1-5% 真实流量,滚动均值跌 >2-3pp 持续 15-60min 即回滚

关键设计是三人群分治(FutureAGI, 2026-03/05):门1-3 跑 PR 金标集(构建期、便宜、确定),门4 跑夜间生产语料(500-2000 案、完整 LLM-judge),门5 跑线上 canary 样本。同一套 rubric 库打分这三个人群,保证 PR 分数、canary 分数、生产分数口径可对照——否则「PR 绿了线上崩了」无从归因。

为什么必须分层而不是一道大门?因为「便宜、快、统计显著」三者只能取其二(pick two):30 案 9 条 rubric 用前沿 judge = ~$27/PR;2000 案夜扫 = ~$9/PR 但要 22 分钟;分类器级联(classifier cascade,只对低置信样本调前沿 judge)= ~20 美分/PR。PR 门必须快且便宜(<5min 工程师才不走神,>10min merge 会抢在判决前发生),所以把昂贵的全量 LLM-judge 推到夜扫,PR 门只用确定性检查 + 分类器级联。

B. 阻断阈值与豁免规则——防 flaky 误杀(这是 gate 不被绕过的命门)

单一「均值 ≥ X」必然 flaky。可用的设计是双门 AND:绝对地板 AND 相对 delta,两条都触发才阻断。

# evals/fi-evaluation.yaml —— 双门阻断(示意)
assertions:
  - template: "typology_recall"
    condition: "p95_score >= 0.85"     # ① 绝对地板:抓灾难性骤降
    on_fail: "error"                    # 退出码 2 → 硬挡 PR
  - template: "citation_validity"
    condition: "pass_rate >= 0.99"      # 引用溯源率近乎硬性
    on_fail: "error"
delta_gate:
  baseline: "rolling-7d"                # ② 相对 delta:抓慢漂移
  test: "welch_t"                       # Welch t 检验(不等方差)
  block_if: "p < 0.05 AND effect_size > noise_floor(~0.03)"

四条防误杀纪律(违反任一条,团队两三个月内必关 gate):

  1. 地板 + delta 双门,缺一不可。只有地板会漏掉「每周掉 1 分」的慢漂移;只有 delta 会被噪声触发。
  2. delta 比的是滚动 7 天生产基线,不是冻结的历史数字。基线以 per-route JSON 提交进 git、夜间更新,漂移本身在 diff 里可审。
  3. 统计显著性是阻断前提:delta 门只在 p<0.05 且效应量 > rubric 噪声地板(~0.03) 时才 fail。一个 2 分波动落在噪声带里,gate 对它报警有一半是假阳——团队被假演练两次,第三次就学会忽略。
  4. 退出码契约化,不许 grep stdout 里的 ERROR
退出码含义CI 动作
0通过merge 放行
2断言失败硬挡 PR check
3警告(--strict)Slack 通知,不阻断
6API 错误退避重试
7超时调大 timeout 或分片

反直觉洞察(gate 越严越没人用):直觉上「门槛订得越高质量越有保障」。真相相反——eval gate 太严会让团队整体绕过它。FutureAGI 列出的绕过触发器全是「过严」的变体:在每次 commit 而非 PR 上跑(被 churn 淹没)、30 案集均值门(方差 > 信号)、地板无 delta(误把噪声当回归报警)、LLM-judge 放在基础层(太贵,第二个月就被禁用)。被假演练折腾两次的团队,第三次假阳直接 git push --no-verify所以 gate 的设计目标不是"最严",是"零假阳前提下尽量敏感"——统计显著性 + 滚动基线就是把假阳率压到团队愿意一直开着它的水平。

C. 与本仓库 .github/workflows/ci.yml 的衔接

现状 CI 四步:checkout → install → pnpm typecheckpnpm testpnpm buildevalRuleBaseline 的断言已经搭在 pnpm testsrc/aml/__tests__/aml.test.ts 断言 recall/FPR 不退化)——这等于五道门里的门1+门2雏形,但还缺:成本门、delta gate、影子/canary(本仓库静态导出、无后端,门4/5 改为"设计存档 + 离线重放")。

衔接设计分三层,不新开 workflow,扩展现有 test-and-build job

加在哪跑什么阻断条件本仓库现状
门1 lint/确定性pnpm testtypology 标签确定性比对、SAR 引用存在性、整数分不变量任一断言假 → 退出码 2✅ 已有(aml.test.ts 14 项)
门2 离线 eval新增 pnpm eval:gate stepevalRuleBaseline(getGoldenDataset()) 双门:地板(recall ≥ 基线)+ delta(vs 提交进 git 的 eval-baseline.json地板破 OR (p<0.05 且效应量>0.03)⚠️ 地板已有,delta gate 待加
门3 成本预算同 step 末尾聚合本次 eval 的 token 成本(P3 接 LLM 后),对 $/案件 上限断言超预算 → 退出码 2⏳ P3 接 LLM gateway 后启用
门4/5 影子+canary不入 CI(无后端)设计存档:P3 LLM 版与规则版在同一金标上离线 A/B,记录在长文#1离线对比,人工 gate⏳ 设计语气,非已实现

落点:现有 CI 的 build 步注释已写明「Next build 是有效类型门,config-contract test 守 dead-code」——eval gate 复用同一哲学:把质量验证编码成退出码非零的 CI step,不达标代码进不了 main。门2 的 eval-baseline.json 用本仓库已有的「滚动数字提交进 git」纪律(参考 W1 周记把 eval 实测值写进 AIPA_PROGRESS.md 的做法),漂移可在 PR diff 里审。

D. 三套数据人群在本项目的映射(口径一致性的落地)

人群通用模式(FutureAGI)本项目对应谁打分
PR 金标集100-200 案/路由getGoldenDataset() 66 案(W1)→ P3 扩 ≥100evalRuleBaseline + P3 LLM-judge
夜间语料500-2000 案静态站无生产流量 → 用扩充合成集替代完整 judge(离线夜跑)
线上 canary1-5% 真实流量无后端 → 设计存档为离线 A/B同一 rubric 库

口径陷阱:FutureAGI 强调「同一套 rubric 库打分三人群」。本项目没有线上流量,最大风险是三人群其实是同一批合成数据的子集——这会让「PR 绿 = 生产绿」变成自证循环(W1 周记已登记的"生成器与规则同源"问题的放大版)。落地纪律:P3 扩集时,夜间语料必须含 PR 金标里没有的贴线案件与叠加类型学,否则三层 gate 退化成一层。

设计要点/决策表

要点说明与已有方案差异
五道门递进而非单点lint→离线→成本→影子→canary,各解决前一道测不出的失败W1 是布尔单点,无成本/漂移维度
双门 AND 阻断绝对地板 AND 统计显著 delta 才 fail单均值门 flaky,必被绕过
滚动 7 天基线提交进 git基线是会变的观测值,漂移在 diff 可审冻结门槛掩盖慢漂移
退出码契约化0/2/3/6/7 各对应 CI 动作,不 grep stdout日志重构不该破坏 gate
PR 门便宜快,judge 推到夜扫分类器级联把 PR 成本压到 ~20¢全量 judge 进 PR = $27/PR,必被关
gate 目标是「零假阳下最敏感」不是最严,是团队愿意一直开着过严 = 整体绕过 = 等于没有

对本项目的落地

  • .github/workflows/ci.yml:在 pnpm testpnpm build 之间插入 pnpm eval:gate step(门2+门3),失败退出码 2 硬挡 PR;不新开 job,复用现有 test-and-build
  • 新增 src/aml/evalGate.ts(设计):读 eval-baseline.json(提交进 git 的滚动基线),对 evalRuleBaseline(getGoldenDataset()) 输出做双门判定(地板:各 typology recall ≥ 基线−noise;delta:Welch t 检验 vs 基线);输出退出码契约化(0/2)。
  • eval-baseline.json:以 W1 实测(structuring/layering/mule_network recall 各 1.0、normal FPR 5.56%)为初始基线,CI 夜跑更新,PR diff 审漂移。
  • 门3 成本:P3 接 LLM gateway 后,把 $/案件(W4 OTel + Langfuse 聚合的 gen_ai.usage.input_tokens 派生量)接入同一 gate,超上限阻断。规则版当前 token 成本为 0,门3 现阶段为"占位 + 设计存档"。
  • 门4/5 诚实标注:本仓库静态导出无后端,影子/canary 不谎称已实现——以「P3 LLM 版与规则版在同一金标离线 A/B」的形式存进长文#1《从 recall@k 到生产级 evals》(W4),作为 AISA 叙事里"成本与质量双门"的证据。

参考资料

  1. FutureAGI — LLM Eval Gates in GitHub Actions(三人群分治、双门 AND、Welch t 检验、滚动 7 天基线、退出码契约、$27/PR vs 20¢、pick-two、gate 被绕过的五个触发器)(2026-03-31 发布,2026-05-20 更新;本日 WebFetch 核实)
  2. Braintrust — Best AI Eval Tools for CI/CD Pipelines(braintrustdata/eval-action GitHub Action:PR 上贴出改善/回退案例、对照 baseline、低于门槛阻断 merge)(2026-05-21;本日 WebFetch 核实)
  3. AppScale — AI-Native CI/CD for LLM Features 2026: 5 Gates, Eval, Canary(五道门 = lint/离线 eval/成本预算/影子/canary 自动回滚)(2026-05-06)
  4. arXiv 2411.13768v3 — Evaluation-Driven Development and Operations of LLM Agents: A Process Model and Reference Architecture(在线发布控制 = 影子 eval 0% 可见 → canary 小流量 → SLO 通过才扩量)(2024-11,2025 更新)
  5. Aman Khan —「Evals are the new PRDs」三类 evals 与 CI gate 定位 (2026-04 更新版)

SOTA 检查 (2026-06-11)

  • eval-driven development + 阻断式 CI gate 是 2026-06 现行 SOTA:Braintrust(eval-action)、FutureAGI(fi CLI + 退出码契约)、AppScale 五道门三家口径一致,均为近 1-3 个月发布/更新(2026-03~05),无更替迹象。
  • 「三人群分治 + 双门 AND + 滚动基线」是当前最完整的工程口径,本日未发现替代框架;arXiv 2411.13768(2024-11)给学术参考架构,但工程细节以 2026 工程博客为主线(符合本项目时效性硬规则:经典/参考架构打底,近 12 个月一手工程文为主线)。
  • 本项目无后端的现实约束:门4 影子 / 门5 canary 在静态站上无法真实实现——按诚实标注纪律写为"离线 A/B 设计存档",不谎称已部署。P3 接 LLM gateway 后门3(成本)可真正启用,届时回填本笔记。
  • 过时认知警示:「eval 是上线后跑的回归报表」已过时——2026 口径是 eval 编码成 CI 退出码、不达标挡 merge;同时警惕反向过时:把全量 LLM-judge 直接塞进每个 PR($27/PR)是 2024 早期做法,2026 已被「分类器级联 + judge 推夜扫」取代。
  • 待跟踪:Braintrust eval-action 的显式阈值语法(本日文档未给完整 syntax,门2 实现前需复查);本项目 evalGate.ts 落地后,delta gate 的 noise floor(~0.03 为通用值)需用本项目金标实测方差校准后回填。