从规则到机器检查
文字规则可以解释意图和取舍,却不能保证每次都被读到和执行。能够确定判断对错的约束,应尽量写成类型、测试、lint 规则或检查脚本,再接到合适的执行位置。只有检查确实运行,并且失败会阻止目标动作时,它才形成门禁。
机器化不是让每条 lesson 依次经过 steering、skill、hook、lint 和 CI。应根据约束能否确定判断、违反后的风险和检查成本,直接选择成本最低且足够可靠的控制。仍然需要取舍的事项留给评审和人工判断。
18.1 机器检查的三个组成部分
一条机器规则能否生效,要分别看它怎样表达、何时执行,以及失败后阻断什么:
| 组成部分 | 作用 | 常见形态 |
|---|---|---|
| 约束表达 | 定义什么情况算违反 | 类型和数据结构、测试、lint 规则、结构检查、策略脚本 |
| 执行位置 | 决定什么时候运行检查 | 本地命令、提交钩子、CI |
| 失败处置 | 决定失败产生什么后果 | 提醒、阻止提交、阻止合并 |
检测器和门禁不是一回事。写出一条 lint 规则,只解决了”能不能发现”;把它接进必需 CI,并让失败返回非零状态,才解决”能不能阻止合并”。提交钩子能提前反馈,但每个克隆仓库都要安装,也可能被绕过;需要强制执行的检查还要在 CI 中运行。
类型和数据结构可以让一部分非法状态无法表达,但不是所有架构边界都能靠类型保证。跨模块依赖、文件布局或禁止调用某个接口,可能需要结构检查;产品取舍、风险接受和可维护性判断仍要由人处理。机器检查给出可重复的结果,但也可能误报、漏报或只报告失败而不说明修法。
文字规则仍有作用。它说明为什么存在这条约束、适用范围是什么、失败后去哪里修;机器负责重复判断和执行阻断。两者可以共同存在,不必互相取代。
18.2 机器化的准入条件
反复出现是评估机器化的信号,不是唯一判据。决定是否建立检查前,先回答下面几个问题:
| 判断 | 适合机器化的信号 | 不适合直接机器化的信号 |
|---|---|---|
| 能否确定判断 | 能根据代码、配置或执行结果稳定判断对错 | 需要理解意图、审美或风险取舍 |
| 风险是否值得阻断 | 违反后会造成安全、数据或交付风险 | 后果轻微,只是偏好 |
| 是否反复发生 | 同类问题重复出现,人工提醒没有解决 | 一次性的局部失误 |
| 检查成本是否可控 | 运行稳定,误报可解释,耗时可接受 | 容易误伤,结果不稳定,维护成本高 |
| 是否有执行位置 | 可以接进本地检查、hook 或 CI | 没有可靠的触发点 |
第一次出现的普通问题可以先记成踩坑记录,复发后再评估是否值得机器化。“第三次出现”可以作为启动评估的提醒,不能代替上面的判断。高严重度问题不必等待复发;只要边界明确,一次事故也可以直接推动测试、安全扫描或 CI 门禁。反过来,需要人工取舍的问题出现很多次,也不应勉强写成不可靠的检查。
skill 也不是必经的升级层。它适合封装需要按步骤执行、要读取材料或调用工具的工作流;能由一个确定命令判断的规则,可以直接写成检查并接进门禁。环境或工具链能够解决的问题,优先修环境和检查,不在提示词中反复追加同义提醒。
18.3 门禁落地流程
把一条已有规则改造成机器门禁,可以按下面的顺序进行:
- 从真实案例写出坏模式、允许情况和适用范围,不从一句宽泛提醒直接起草检查。
- 判断机器是否能根据代码、配置或运行结果稳定判错;不能稳定判断的,保留在评审流程中。
- 选择约束表达。非法状态优先由类型或数据结构消除;行为用测试;语法和依赖模式用 lint 或结构规则;跨文件约定用检查脚本。
- 让检查失败时返回明确的失败状态,并给出文件位置、违反的规则和修复入口。
- 准备一个应失败的样例和一个合法样例,证明检查既能抓住问题,也不会把允许的写法一起拦住。
- 根据风险选择执行位置。需要快速反馈的放进本地命令或提交钩子;必须阻止进入主干的,在 CI 中再运行并设为合并必需项。
- 删除与检查完全重复的操作性提醒;如果 Agent 在动手前仍需知道替代方案,就保留一句理由、适用范围和修复指引。
- 记录检查的所有者和复测条件。代码结构、工具或工作方式变化后,重跑正反样例;检查已经过期、误报过多或成本失衡时,修改、降级或删除。
通过标准:坏样例稳定失败,合法样例通过;检查会在约定事件中实际运行;需要阻断时,失败确实会阻止提交或合并;输出能指向违反位置和修复入口;对应的文字规则没有与机器逻辑形成两份可能漂移的真相源。
18.4 配套机制与项目责任
本手册的配套方案提供了三类基础部件,但没有预置适用于所有技术栈的完整门禁:
- hook 配置展示了如何在指定事件上执行命令。支持哪些事件、能否阻断以及输入格式,要按当前客户端和版本验证。
check-steering.sh检查 steering ID、重复规则编号、残留占位符和基线文件是否缺失。它不判断跨文件语义是否一致,部分项目状态只报告警告。- ast-grep 可以按语法结构搜索和改写代码。它本身不是门禁;项目要把具体模式写成规则,让失败状态可被调用方识别,再接入 hook 或 CI。
语言相关的 formatter、linter、类型检查、测试和安全扫描由项目按技术栈配置。template 提供接入位置和通用纪律,项目负责选择检查器、写规则、建立正反样例,并把必须执行的检查设为合并门槛。
本章小结
机器门禁由约束表达、执行位置和失败处置共同组成,写出检查器不等于已经强制执行。反复发生是机器化信号,高严重度问题可以直接建立门禁;能否稳定判断、检查成本和风险共同决定落点。检查上线前要用正反样例验证,接入后仍要复测和清理过期规则;文字只保留机器无法表达的理由、范围和修复入口。
参考与出处
- 与其反复修改提示词,不如修正环境、测试和自动化约束:GitLab: AI-Assisted Development Playbook
- 用数据模型让非法状态在类型层面无法表示,把约束前移到编译期:Elm Radio: Make Impossible States Impossible
- hook 的触发事件、动作和客户端支持范围:Kiro Hooks 文档
- 用语法结构编写搜索、检查和改写规则:ast-grep 文档