背景(独立验收发现)
IR-0006 验收阶段(#402 / 卡 #414 W2-C3),独立对 wave_schema.py
BEH-07 预算硬停做代码级复算时发现:任何在卡 budget 块中声明 wallclock_sec 维度的卡,
当 wave_check 对账时,Python 直接抛未处理的 KeyError 异常退出码 1,
被 cost-check.sh 当作"非 INFRA、非超限"吞掉,最终输出 WAVE-OK = 预算硬停机制被静默绕过。
Bug 链(完整 fail-open 路径)
第 1 层:键名不一致(wave_schema.py L168 vs L191)
- BUDGET_KEYS 声明(L54):
('usd', 'tokens', 'wallclock_sec', 'human_minutes')
← wallclock_sec(与 card.yml 模板一致)
- ledger 聚合 agg 键(L168/L187-189):
'wall_sec'
← wall_sec(与 standards/evidence/record.schema.yaml cost.wall_sec 一致)
- 超限比较(L191-192)遍历
BUDGET_KEYS[:3],当 k=wallclock_sec 时
agg['wallclock_sec'] = KeyError(agg 里只有 wall_sec)
第 2 层:异常未被 Python 代码捕获
KeyError 不是 die(3/4),是裸异常 → exit code = 1。
第 3 层:cost-check.sh 错误处理缺口(L230-249)
rc=1(未处理异常)时,rc 既非 2 也非 4,掉落到解析空 out → rows=[] → no error → no exceeded →
输出 "WAVE-OK 预算卡 0 张对账无 hard-stop 超限"。
净结果: 任何声明了 wallclock_sec 预算的卡,在真实超限场景下,100% 不会触发
BEH-07 的熔断三件套(熔断变量 + 撤 auto-merge + P0 issue)。预算硬停死。
实测复现(独立 agent 沙箱,非 CI 快照摆拍)
账本: 卡 #414 累计 wall_sec=8000s, usd=5.5, tokens=210k
预算: wallclock_sec: 7200(卡侧写的是 wallclock_sec——模板默认)
预期: exceeded_dims 至少含 wallclock_sec → on_exceed=hard-stop → exit 4
实际: KeyError(wallclock_sec) → cost-check 打出 WAVE-OK → 绿
违反的治理条款
| 条款 |
影响 |
| AC-9 BEH-07 波次预算硬停(四元组超限→熔断三件套) |
wallclock_sec 维度失效;同时超多维时列表推导提前崩,所有维度都不比较 |
| 宪法 §5 / INV-01 fail-closed |
本该红的判定(超预算)被当作绿——违反 fail-closed 基本方向 |
| ADR-0040 无人值守护栏 (b) |
auto-fix-limit 前的 cost-check 守卫失效——超限不会撤 automerge |
修复建议(最小变更,不重写)
建议 A + C 合入(双保险):
方案 A(对账侧:键名映射)
# governance/wave_schema.py L191 附近
AGG_KEY_FOR_BUDGET = {"usd": "usd", "tokens": "tokens",
"wallclock_sec": "wall_sec", # 关键映射
"human_minutes": None}
exceeded_dims = [k for k in BUDGET_KEYS[:3]
if k in budget and AGG_KEY_FOR_BUDGET[k] is not None
and agg[AGG_KEY_FOR_BUDGET[k]] > float(budget[k])]
方案 C(调用侧:硬兜底防御——任何非 0/4 exit code 都 INFRA)
# governance/cost-check.sh L230 附近
out=$(python3 DIR/wave_schema.py wave-check --cards cards --ledger-dir led 2>/dev/null) || rc=$?
if [[ -n "${rc:-}" && $rc -ne 4 ]]; then # rc=4=超限(期望红),其余=异常→INFRA
printf 'INFRA\twave-check 异常退出 rc=%d(fail-closed:预算面不可信,不静默通过)\n' "$rc"
return 0
fi
C 兜底保证:未来任何类似命名错,至少不会 fail-open。
严重性自评
- Severity: HIGH(治理核心 fail-closed 方向被违反,预算熔断承诺失效)
- 可利用性: 中等(budget 模板占位明确写了 wallclock_sec: 7200,新卡 99% 会带)
- 爆炸半径: 单仓 governance/cost-check.sh + governance/wave_schema.py(C1 路径)
- 修复后回归: governance/tests 补一条 wallclock_sec 超限 wave-check rc=4 断言
验收对账基准(修完必须实测绿)
- 声明 wallclock_sec=7200,账本超 8000s → wave-check rc=4
- cost-check 同场景 → 打出 WAVE-EXCEEDED(非 WAVE-OK)
- 反向:未超限 → rc=0
- 畸形 budget(wallclock_sec 写成 wall_sec)→ validate 报错(保持模板对齐)
关联
背景(独立验收发现)
IR-0006 验收阶段(#402 / 卡 #414 W2-C3),独立对 wave_schema.py
BEH-07 预算硬停做代码级复算时发现:任何在卡 budget 块中声明 wallclock_sec 维度的卡,
当 wave_check 对账时,Python 直接抛未处理的 KeyError 异常退出码 1,
被 cost-check.sh 当作"非 INFRA、非超限"吞掉,最终输出 WAVE-OK = 预算硬停机制被静默绕过。
Bug 链(完整 fail-open 路径)
第 1 层:键名不一致(wave_schema.py L168 vs L191)
('usd', 'tokens', 'wallclock_sec', 'human_minutes')← wallclock_sec(与 card.yml 模板一致)
'wall_sec'← wall_sec(与 standards/evidence/record.schema.yaml cost.wall_sec 一致)
BUDGET_KEYS[:3],当 k=wallclock_sec 时agg['wallclock_sec']= KeyError(agg 里只有 wall_sec)第 2 层:异常未被 Python 代码捕获
KeyError 不是 die(3/4),是裸异常 → exit code = 1。
第 3 层:cost-check.sh 错误处理缺口(L230-249)
rc=1(未处理异常)时,rc 既非 2 也非 4,掉落到解析空 out → rows=[] → no error → no exceeded →
输出 "WAVE-OK 预算卡 0 张对账无 hard-stop 超限"。
净结果: 任何声明了 wallclock_sec 预算的卡,在真实超限场景下,100% 不会触发
BEH-07 的熔断三件套(熔断变量 + 撤 auto-merge + P0 issue)。预算硬停死。
实测复现(独立 agent 沙箱,非 CI 快照摆拍)
违反的治理条款
修复建议(最小变更,不重写)
建议 A + C 合入(双保险):
方案 A(对账侧:键名映射)
方案 C(调用侧:硬兜底防御——任何非 0/4 exit code 都 INFRA)
C 兜底保证:未来任何类似命名错,至少不会 fail-open。
严重性自评
验收对账基准(修完必须实测绿)
关联