fail-closed 门禁设计
用途:为编码 Agent 设计“默认拒绝”的验收关卡
定义
「定义」小节链接fail-closed(失效关闭):当检查无法执行、证据缺失或结果不确定时,门禁返回不通过,而不是放行。反面是 fail-open:出错时默认允许通过。
对 Agent 场景,fail-closed 的意义在于:Agent 最擅长制造“看起来通过”的表象,任何默认放行的缝隙都会被无意识地踩进去。
门禁的四层结构
「门禁的四层结构」小节链接| 层 | 检查内容 | 示例 |
|---|---|---|
| 1 静态层 | 变更范围与形态 | diff 是否只含允许路径、是否有敏感文件、是否修改了测试断言/配置阈值 |
| 2 构建层 | 可编译、类型检查、lint | 编译器零错误、格式检查通过 |
| 3 行为层 | 测试真实运行 | 目标用例执行、断言数量达标、新增代码有测试、失败信息可追溯 |
| 4 权威层 | 干净环境复现 | CI 运行通过、产物哈希一致、无本地缓存依赖 |
任何一层缺失 → UNVERIFIED,不通过。
关键设计规则
「关键设计规则」小节链接- 默认拒绝:白名单式声明“允许什么”,而不是黑名单式禁止“已知坏行为”。
- 零跳过:
skip/xit/@Ignore/被注释的测试视为失败项;确需跳过必须显式审批并计入未验证。 - 禁止改判据:门禁的阈值、测试断言、配置项属于“裁判”,Agent 修改裁判即视为 FAIL(可用路径级保护:
tests/**、*.spec.*、CI 配置、覆盖率阈值变更需人工确认)。 - 证据由工具产生:Agent 只能引用门禁输出,不能自填结论。
- 回执绑定权威状态:结论必须携带 commit 哈希、CI run ID、报告文件路径(见“回执与权威状态绑定”)。
- 可解释:每个不通过项给出“缺什么证据/违反哪条规则/如何补”,否则一线会绕过门禁。
- 快速失败:静态层秒级返回,避免昂贵构建后才发现范围越界。
与人工评审的分工
「与人工评审的分工」小节链接| 事项 | 由谁负责 |
|---|---|
| 可机械验证的事实(编译、测试、覆盖率、范围) | 门禁 |
| 语义正确性与需求满足 | 人工评审 |
| 门禁阈值与例外审批 | 平台负责人(有留痕) |
门禁不是取代评审,而是把评审从“核对事实”中解放出来,让人只看需要判断力的部分。
落地顺序
「落地顺序」小节链接- 先做范围与裁判保护(成本最低、收益最直接)。
- 接构建与测试执行,强制“必须运行”。
- 加断言数量与新增代码覆盖门槛。
- 接 CI 权威环境与回执。
- 最后加变异测试等高等级证据(按需)。
常见误区
「常见误区」小节链接| 误区 | 修正 |
|---|---|
门禁可被 --no-verify 绕过 |
权威判定放在服务端(CI/受保护检查),本地钩子只是提前反馈 |
| 只检查“测试通过”不检查“测试存在” | 无测试即 UNVERIFIED |
| 阈值写死不可配 | 版本化配置 + 变更审批 |
| 失败信息含糊 | 每条失败给出证据位置与补救动作 |
| 例外不统计 | 例外率必须看板化,例外常态化说明规则错了 |
延伸阅读
「延伸阅读」小节链接- 本站:四值判定模型、零跳过与等价复用、测试即门禁
- 安全工程中的 fail-secure 原则(公开资料)