本层判断标准

这一条要求,有没有一条命令能证明它被满足?谁在什么时候跑?

找不出命令的,先改写成可判断的写法;只能靠人的,写清由谁在哪一步看。写了「靠人」却没写名字和步骤的,按没做处理。

三层与四类判断:谁判、多久、置信度到哪

同一句「改好了」,落在不同层上成本差两个数量级。按改动落在哪一层选手段,不要一律交给最贵的那一层。

判断方式谁来判单次成本置信度到哪覆盖不到什么
工具判断:格式化、静态检查、类型、复杂度、密钥、依赖漏洞本地跑一条入口命令2–5 分钟规则写死的接近 100%逻辑对不对、越权语义、答非所问
测试判断:单元与接口测试测试命令30 秒–3 分钟已写进用例的行为高;没覆盖的为 0界面文案、模型输出质量、性能
评测判断:固定问题集与判分规则评测脚本,按样本条数计时3–15 分钟问题集内可复现;问题集外不可外推视觉、交互、布局
人看:关键路径、改动意图、红线另一名组员,指名到人30–60 分钟覆盖面最宽,复现性最差批量回归;人换了就回到原点

顺序不能换:前一层不过不进后一层。2 分钟的工具能挡住的问题,别交给 60 分钟的人。反过来,工具报绿也不等于能跳过人看——「这个改动该不该做」只有人能判。

四类里只有评测判断不进那一条入口命令:单次 3–15 分钟且按量计费,只在改提示词、换模型、改问题集时单独跑。性能与容量也不落在四类里任何一类——它靠基准压测跟上次的基线比,判的是趋势不是对错。

长什么样子

一次门禁就是一条命令跑完八项,任一项非零即停在本地。下面是一次全绿的输出。

一次门禁跑完的输出

$ make check
fmt      ✓ 0 处
lint     ✓ 0 处
types    ✓ 0 处
unit     ✓ 142 通过 / 0 跳过    新增行覆盖 91%
api      ✓ 9 通过
secrets  ✓ 0 命中
complex  ✓ 0 超限
policy   ✓ 指令文件未被改动
→ 全部通过,可推送

要认的是这个形状:八项一次跑完、只报通过与否、不看人怎么解释。任何一项变成「警告」「先合后修」,这一条命令就不再是判据。

助手交出来的样子

$ make check
fmt      ✓ 0 处
lint     ✓ 0 处
unit     ✓ 138 通过 / 0 跳过
complex  ✓ 0 超限
→ 全部通过,可推送
(八项这次只出现四项:api、secrets、policy 没跑)

认它的办法:先看项数,再看勾。八项变四项、或某一项从「非零即停」改成「警告」,比某项红了更危险——红了会被看见,少了不会。入口命令里出现 || true、--no-verify,或某一项被整段删掉,都是同一个动作的不同写法。

典型应用示例:一次越权改动怎么被挡下来

场景:助手给「按租户导出」写完实现,人直接提了合并请求,说明里只写了「实现导出」。

有它 合并请求一开,门禁逐项跑完,接口测试里那条越权断言变红——失败信息给出文件名与用例名。改动停在合并之前,作者自己就看到是查询没绑会话里的值;评审人拿到的是一份已经过了机器的改动,只需要看意图。
没有它 越权语义混在几十行差异里,评审人得逐行读完才知道查询绑的是不是当前范围;这次没看出来的,下一次也没人记得查这一条。

门禁跑哪八项

门禁是唯一不依赖人盯着的约束:人可以不看,但它每次都在。检查名可以点开,进到那一项的说明。

检查挡住什么失败时
格式化空格、换行、import 顺序自动修,不值得讨论
静态检查可疑写法、未使用变量、空值处理错误报出文件、行、规则号
类型检查接口对不上、字段名拼错阻断合并
单元与接口测试行为回归阻断合并,附失败用例
复杂度函数过长、嵌套过深、圈复杂度超限阻断合并,指出超限的那个函数
密钥扫描误提交的密钥与凭据阻断合并,并轮换已泄漏的那一个
依赖漏洞含已知漏洞的依赖高危阻断,中危限期修
规约场景回归这次改动违反了自己写的规约阻断合并,指出违反的是哪一条

每一项的阈值数字写在对应的检查页,这一页不重复。第八项最容易漏:规约里的场景不能自动跑,它就只是一份文档。覆盖率则相反,是最容易被误用的一项——它挡的是「新增代码一行测试都没写」,不是「测试写得好不好」。

八条红线与发现方式

红线是「不可降级的底线」,不是「所有质量问题」——风格、命名、格式交给工具。前四条本地能拦,后四条靠分支保护与评审;每条都要写得出发现方式,写不出的先别进清单。

红线违反了怎么发现挡在哪一步
密钥、令牌、私钥进仓库密钥扫描退出码非 0;或改动差异里出现密钥样式的前缀与私钥头提交前钩子 + 门禁
调试输出留在要合并的改动里静态检查报出对应规则号;或差异里出现打印语句门禁
大段注释掉的旧代码改动差异里连续多行以注释符开头且含括号评审
函数超过复杂度上限复杂度检查退出码非 0,报出函数名与超限值门禁
为让检查变绿而改判据同一次合并请求里既有测试文件、又有阈值或规则文件的改动,却没有对应的规约变更评审
核心逻辑没人读过就合入批准人数为 0,或批准者说不清这段改动解决了什么分支保护要求 ≥ 1 个批准
直接推 main主分支的提交里出现未经合并请求的提交分支保护
看不懂的助手改动照合评审人对改动意图给不出答案,却点了批准评审:拆小,或让作者把意图写进说明

第 5 条最难发现,因为它常伪装成「顺手优化」。判断方式很简单——同一次合并请求里出现检查配置与功能代码,就拆成两次。

不许改判据与假测试

助手最常见的「修复」不是改错,是改判据——它要的是让报错消失,而让报错消失最快的方式往往是削弱检查。下面这些改动一律挡回,不算完成。

可以这么做 函数太复杂就拆开,接口对不上就改实现,测试失败先看是不是需求本来就要变——需求变则改规约,并且走一次规约评审。
不要这么做 删掉失败的那条断言;给用例加 skip;把检查错误降级为警告;给整份文件加类型忽略;把复杂度上限调高好让当次通过。

真想放宽一项检查,就走单独的合并请求:不夹带功能改动,说明为什么,由人提交。检查配置、阈值、指令文件都是判据本身,改动要比普通代码更严——把它们放进 CODEOWNERS,指定必审的人。指令类文件也列进来,是因为助手会读它们,与判据是同一类东西,专用写法见指令与配置保护。

同一类问题在测试里还有另一种形态:假测试。它们跑起来是绿的,一条行为也没验证,却同时把覆盖率抬上去——所以看覆盖率看不出它们,评审里也最容易被放过,因为改动说明都写得像是修复。

现象说明什么评审时看什么
报告全绿,新增测试里没有断言一条行为也没验证;覆盖率数字被当成成绩单打开新增的测试文件,看有没有断言那一行
只断言替身被测代码没真正执行,替身返回什么就断言什么看断言右值是不是被测逻辑的输出
跳过的与被注释掉的用例留在提交里报告仍绿,被断言的行为再没人管看跳过数是零还是在涨
期望值跟着实现改改的是判据不是行为看同一条用例的期望值被改过几次

把两条要求写进合并请求:新增的测试至少有一条会在数据错时变红的断言;跳过的用例单独写原因与恢复时间。

落在哪

入口命令全仓库只有一条,本地与持续集成跑同一条,不存在「本地过、线上不过」;工作流只调这条命令,不在 YAML 里另抄一份规则。工作流本身不能代替分支保护——检查跑绿了,仍然有人可以直接推到 main,所以要同时打开「禁止直接推送」与「合并前必须通过检查」两项。

文件它管什么改动由谁签字
Makefile入口命令的聚合入口,全仓库只有这一处定义项目负责人
pyproject.toml / .golangci.yml各检查项的阈值,集中在一处项目负责人
工作流配置什么时候触发项目负责人
AGENTS.md、.claude/、.cursor/会被助手读进上下文的指令项目负责人