Rule Catalog

September 2, 2026 · View on GitHub

索引版本。每条规则的完整正文位于 ../rules/ 目录下; 本文档仅做摘要、severity、关联组件指引。

修改任意一条规则时,请按 ../docs/ARCHITECTURE.md §8 表格同步检查所有连带文件。

语言

  • English(骨架 / source of truth)../rules/01-*.md ~ ../rules/12-*.md(root 层)。英文是骨架语言:钩子注入默认英文(prompts/ root),任意其它层的规则语义都以英文骨架为准。命令 / skill 的正文用中文书写(作者语言,可以是任意语言),但它们引用的规则定义以英文骨架为准。
  • 中文翻译../rules/zh/。逐节跟随英文骨架、与英文 1-1 对应;如出现 drift,以英文骨架为准(CI 硬门 ../hooks/scripts/i18n_check.py 会拦,见 I18N.md)。运行时用 CC_ENFORCER_LANG=zh 切换注入语言;任意新语言放 rules/<code>/ + prompts/<code>/,缺失文件自动回退英文骨架。

规则编号约定

  • 编号格式:<两位数>-<kebab-case-名>.md
  • 编号一旦发布不再回收(即使规则被废弃,也不复用编号)。
  • 当前编号区间:01–12

规则一览

ID标题Severity完整文件主要适用场景
01验证而非猜测must../rules/01-verify-dont-guess.md任何关于文件、API、版本、文献、报错信息的断言
02系统式而非反应式must../rules/02-systematic-not-reactive.md修 bug、改架构、重构、添加功能
03修根因,不修症状must../rules/03-root-cause.md异常处理、测试失败、CI 失败、竞态、钩子失败;v0.28 起含上游溯源阶梯(症状位 → 传播路径 → 起源)与确诊先行
04完整阅读,拒绝关键词依赖must../rules/04-full-context.md编辑文件前、跨文件影响分析
05引用必须可追溯must../rules/05-cite-sources.md任何对外陈述(PR 描述、回复用户、报告)
06验证收敛must../rules/06-verify-convergence.md任何修复 / 更新 / 补丁完成后的强制收敛验证
07任务忠实must../rules/07-task-fidelity.md任何任务声称完成前的请求覆盖、无降级、无遗漏二次确认
08改前必读,写前必想must../rules/08-read-before-edit-think-before-write.md任何 Edit / Write 前的前置硬纪律(v0.11 物理强制)
09系统式修改,禁止打补丁must../rules/09-systematic-modification.md修改过程中的反补丁内容拦截(v0.11 物理强制);v0.28 起含"一个根因,一次统一修复"(同类清扫,禁点对点补丁)
10禁止非必须硬编码must../rules/10-no-hardcoding.md修改过程中把本应是配置/环境的密钥/凭证内联成代码字面量的内容拦截(v0.22 物理强制)
11禁止非必须路径依赖must../rules/11-no-path-dependency.md修改过程中把机器特定的 user-home 绝对路径硬编码进代码的内容拦截(v0.22 物理强制)
12全库同步 —— 连带更新每一处引用must../rules/12-repo-wide-sync.md修改收尾的全库引用清扫(被动:sync-gate + Stop layer (i),v0.23 物理强制)+ 按需全库陈旧/过时/冗余/错误/漂移扫描(主动:repo-refresh skill)

Severity 等级

Severity含义
must强制规则。违反即被视为"偷懒"。当前所有规则均为此级别。
should强烈建议;除非有明确理由,否则遵守。(v0.1 暂未启用)
info信息性提醒;agent 应了解但无强制义务。(v0.1 暂未启用)

规则之间的关系

            01 验证                      05 引用
              │                            │
              ▼                            ▼
       ┌──────────────────────────────────────┐
       │   04 完整阅读                          │
       └─────────────────┬────────────────────┘


       ┌──────────────────────────────────────┐
       │   02 系统式思维                        │
       └─────────────────┬────────────────────┘


       ╔══════════════════════════════════════╗
       ║ 08 改前必读 / 写前必想(前置硬纪律 · 物理强制)║
       ╚═════════════════┬════════════════════╝


       ┌──────────────────────────────────────┐
       │   03 修根因                            │
       └─────────────────┬────────────────────┘


       ╔══════════════════════════════════════╗
       ║ 09 系统式修改 / 反补丁(内容硬纪律 · 物理强制)║
       ╚═════════════════┬════════════════════╝


       ╔══════════════════════════════════════╗
       ║ 10 无硬编码 / 11 无路径依赖(内容值约束 · 物理强制)║
       ╚═════════════════┬════════════════════╝


       ┌──────────────────────────────────────┐
       │   06 验证收敛                          │
       └─────────────────┬────────────────────┘


       ┌──────────────────────────────────────┐
       │   07 任务忠实                          │
       └─────────────────┬────────────────────┘


       ╔══════════════════════════════════════╗
       ║ 12 全库同步(仓库引用图轴 · sync-gate 物理强制)║
       ╚══════════════════════════════════════╝
  • 01 / 04 / 05输入端约束:决定 agent 如何获取与陈述事实。
  • 02思考过程约束:决定 agent 如何把事实组织成方案。
  • 08修改前置硬纪律:把 04 + 02 折叠成 Edit / Write 之前的最低必答清单,并由 PreToolUse + Stop layer (e) 物理强制(v0.11)。
  • 03输出端 (改什么) 约束:决定 agent 修改代码时是否触达根因。v0.28 起 03 拥有上游溯源阶梯:症状位 / 传播路径 / 起源三级——修在前两级都算补丁;停在中途必须显式点名真正起源并说明理由;根因假设先经第一方证据确诊再动手。
  • 09输出端 (怎么改) 约束:把 03 的"反偷懒"升级为修改内容层的硬纪律,由 PreToolUse new_string 内容检测 + Stop layer (f) 物理强制(v0.11)。v0.28 起 09 增加统一修复要求:确诊的根因定义一个"类",全库同类实例一次修完,点对点补丁被明令禁止。
  • 06输出端 (改完之后 · 技术面) 约束:决定 agent 是否真的把根因解决到收敛、是否经得起验证。
  • 07输出端 (改完之后 · 契约面) 约束:决定 agent 是否把用户要求的全部原标准交付(无遗漏、无降级、无范围溢出)。06 与 07 互补:06 解决"症状-根因"轴,07 解决"请求-交付"轴。
  • 08 与 09 互补:08 是修改的"准备充分了吗",09 是修改内容的"姿势对了吗"。08 在 PreToolUse 的"已读检查"上 + Stop layer (e) 的"系统式自答"上落地;09 在 PreToolUse 的"new_string 内容检测"上 + Stop layer (f) 的"根因 + 影响 + 方案三件套"上落地。
  • 10 / 11 是内容值约束(v0.22):09 拦"打补丁的姿势",10 / 11 拦"塞进内容的值本身"——本应外化为配置/环境的密钥凭证(10)、本应运行时派生的机器特定路径(11)。三者共享 PreToolUse(Edit|Write) new_string 内容检测机制、共用 why-comment 逃生舱把"非必须"落地为可验证判定;与 09 不同的是 10 / 11 无 Stop layer(内容检测器一律 PreToolUse-only,避免对已被拦截的写入双重追责)。
  • 检测器的"能被绕过 = 等于没有"(v0.25):三个内容检测器在 v0.25 各补了一处 语法盲区,共同的教训是逃生舱必须真的被读到,而不是靠改变字符串让检测器沉默。 rule 09 的 try/except: pass 此前要求 pass 完全裸露,于是行尾加任意注释即可 放行——包括那条本该被审查的 why 注释,等于逃生舱对该标记从未生效;同时一个 try 只看第一个 except,放过了"窄 handler + 兜底吞掉"这个最典型形态。rule 10 的密钥 匹配要求分隔符紧跟关键字,于是 JSON / 带引号键 YAML("api_key": "…",最常见的 凭证形态)全部漏过。判定这类缺口的方法是形态矩阵:对同一语义列出所有合法书写 形式,逐个过检测器,而不是只测自己脑子里那一种写法。
  • "概念"要由模型回答,不是由更多正则回答(v0.26.0):v0.25.1 点名了下面那条 根因,却只修了它的实例;第四轮审阅(审的是 v0.25.1 自己的修复 diff)证明机制 一旦留着,同一根因立刻长出新一批——包括一个倒退:嵌套 try/except 从 v0.25.0 的 DENY 变成 v0.25.1 的 allow,而那次重写的 docstring 正宣称"现在用栈处理嵌套"。 修法是把四个反复被猜的结构性问题交给共享模型回答: lib/srclex.py(这个 # 是注释 / docstring / 数据?这个字面量到哪结束?哪些物理行是一条逻辑行?——刻意选词法器而非 ast/tokenize,因为 Edit 的 new_string 通常不是完整语法单元)、 lib/mdctx.py(这一行是 agent 自己的断言,还是 被引用 / 被围栏包住的示例?——Stop layer (h) 的两个半区现在共用它,此前它们 各持一份残缺副本且结论不一致)、lib/shellcmd.py (这条命令真正执行的是什么?git 子命令是哪个?python 的脚本操作数是哪个?), 以及 state 的 schema 归一(不再只修"这次抛异常的那个字段")。判定这类缺口的 方法从"形态矩阵"升级为**"这个检测器在回答什么问题?它有资格回答吗?"**。
  • 检测器描述的必须是"概念"而不是"字符串"(v0.25.1):上一条只补了单个盲区, v0.25.1 的第三轮审阅发现同一根因还有九种拼写在外面——CRLF 让五个单行标记 全部失效(本插件主平台就是 Windows);任意尾随文本让标记根本不匹配,于是 @ts-ignore 后跟一个光秃秃的延期词反而放行、而理由检查从未运行;把理由写在 pass 上面独立一行(最自然的写法)会把吞错行挪出扫描器视野,逃生舱依旧 不可达——v0.25 只修了同行写法,还配了一条因错误原因而通过的回归测试; except X: pass 单行形、time.sleep(max(0, d)) 嵌套括号、 源码里成对反斜杠的 "C:\\Users\\bob"git -C repo push --force、 引号形 "--force"+refspec--mirror 同样全在外面。 推论一:理由必须真的是注释。逃生舱此前搜整个原始窗口,于是 reason = compute() 这种普通代码里的 token 就能让标记沉默。 推论二:每条"带理由应放行"的测试必须配一条"去掉理由必须拦"的孪生断言, 否则测试可能只是因为检测器从未触发而通过——这正是本仓库连续两个版本踩中的形态。
  • 配置读进来的值必须先验类型(v0.25.1)severity = ["must"]mode = [] 都是合法 TOML,而 值 not in 集合TypeError: unhashable type, 逃出两个 docstring 自称"never raises"的 loader,落进最外层 failing-open—— rule 04 + 08 整场失效,Stop layer (i) 连同回合边界的 clear_edit_flag 一起没了。 与 v0.25 那条编码缺陷是同一个洞的两扇门:那次加固的是文件怎么读, 这次加固的是读出来的值能是什么
  • 点对点补丁升级为"溯源 → 确诊 → 统一修复"硬纪律(v0.28.0):问题出现时禁止 逐处修补。rule 03 新增上游溯源阶梯(沿因果链上爬到机制 / 设计决策 / 缺失不变量 为止,停在中途必须显式说明),rule 09 新增"一个根因,一次统一修复"(确诊先于 动手;确诊的根因定义一个类,全库同类实例枚举后一次修完;验证还要重触发类里 另一个实例以证明类已闭合,类只有一个成员时显式说明即可)。动机是本仓库自己的实测史:v0.25.1 点名了根因却只修 实例,机制存活并在 v0.26 再生出同一类新缺陷(含一个倒退);v0.26 换机制(33 条 finding → 三个根因 → 四个统一件)才收口——v0.28 把那次的做法固化为每次修复的 强制形态。与 v0.22.1 同一先例,零新检测器:这是推理形态而非钩子可匹配的语法 形态,落在规则文本 + 注入表;既有硬层(补丁标记内容层、rolling-patch 频率层、 Stop layer (f) 三件套)仍是物理地板。
  • 12 是输出端(仓库引用图轴)约束(v0.23):06 收敛"被改的部分",07 覆盖"用户要的部分",12 补上"仓库其余部分跟着走"——所改内容的全库引用(文档 / 下游 / 测试 / 镜像翻译)必须连带更新或显式核对。被动半区由项目级 .claude/cc-enforcer/sync-gate.toml + Stop layer (i) 物理强制(组未满足且无 同步核对 / sync-check 标记 → BLOCK;无配置的项目该层关闭);主动半区是 repo-refresh skill 的全库五类缺陷扫描。

各组件如何引用这些规则

组件引用方式
../prompts/session-start.md全部 12 条规则的浓缩版(v0.11 加入 rule 08 / 09;v0.20 标准回答骨架改为 YAML 回复 schema + tldr 大白话收尾;v0.23 加 tldr 长度硬约定 + rule 12)
../prompts/user-prompt.md12 条规则的结构化每轮自检清单(v0.11 重构;v0.20 收尾骨架改 YAML schema;v0.23 加 tldr 长度 + rule 12 触发行)
../commands/checklist.md把 12 条规则中的 10 条映射成可勾选的检查项(A 改前 / B 改后 / C 收敛验证 / D 任务忠实 / E 改前必读·写前必想 / F 系统式修改 / G 大白话 TL;DR 收尾 / H 全库同步);规则 10 / 11 是纯内容层 PreToolUse DENY,无可自证项,故无对应清单项
../agents/verifier.md主要执行规则 05(引用可追溯)+ 规则 01 的事后验证;同时尊重规则 07 + 08
../skills/systematic-debug/SKILL.md主要执行规则 02 + 03 + 06 + 08 + 09
../skills/repo-refresh/SKILL.md规则 12 主动半区:全库陈旧 / 过时 / 冗余 / 错误 / 漂移扫描(v0.23)
../hooks/scripts/read_guard.py规则 04 + 08(read-before-edit)+ 规则 09(new_string 补丁标记物理拦截 + rolling-patch 频率策略)+ 规则 10 + 11(硬编码 / user-home 路径依赖内容检测)+ 规则 12(edited_files 会话记录,v0.23)
../hooks/scripts/lib/editscale.py规则 09 的规模判定(v0.35):small / systematic / medium 分类(含相对目标文件的 30% 覆盖率通道)+ 两个豁免(净减少、记账类)。频率策略留在 read_guard,这里只回答"这次改动相对它所改的东西有多大"
../hooks/scripts/bash_guard.py规则 03 + 09(bypass 模式拦截)
../hooks/scripts/stop_guard.py规则 06 layer (a)(c) + 规则 01 layer (b) + 规则 07 layer (d) + 规则 08 layer (e) + 规则 09 layer (f) + 规则 01+06 layer (g) + TL;DR 收尾约定 layer (h, v0.20;v0.23 加单条长度上限,v0.35 改按 160 显示列计) + 规则 12 sync-gate layer (i, v0.23)
../hooks/scripts/lib/messages.py + messages_en.py / messages_zh.py所有规则的输出前提(v0.38):守卫打印的每一句话(deny 理由、九层状态表、恢复指引)都住在消息目录里,按 CC_ENFORCER_LANG 逐键解析、缺键回落英文骨架。此前这些文案硬编码在守卫里且是双语混排的——英文正文缀一行中文 大白话——而 CC_ENFORCER_LANG 只管注入文案、管不到它们。规则的判定不变,变的是这些判定用哪种语言讲给你听
../hooks/scripts/lib/hookio.py所有规则的输入前提(v0.37):四个钩子入口统一从 sys.stdin.buffer 读字节、按 UTF-8 严格解码。此前走 sys.stdin.read()(宿主机码页 + surrogateescape),非 UTF-8 宿主机上载荷被静默改写——规则 09 的 rationale 判定被一个破折号推翻,而规则 01/06/07/08/12 在 Stop 层要找的中文标记全成乱码,等于中文回复整轮不受管。它决定的不是某一条规则,而是每条规则是否看得见它要判的那串字
../hooks/scripts/lib/sync_gate.py规则 12 被动半区:.claude/cc-enforcer/sync-gate.toml 加载 + 连带组求值(v0.23);写目标解析(default_project_path,确定性)与 glob 匹配(matches_any,与门禁共用唯一定义)v0.31
../hooks/scripts/manage_sync_gate.py + ../commands/sync-gate.md规则 12 的配置编写与体检(v0.31):init / list / check / add / remove / pathcheck 是关键——加载器 failing-open,被丢弃的组与打不中文件的 glob 都不会报错,只会静默停止守护;check 把两者点名并以退出码 1 结束,可进 CI(本仓库自 v0.32 起对自己的配置断言它)

添加新规则的流程

  1. ../rules/ 下创建 13-xxx.md(v0.23 起编号区间是 01–12,新规则从 13 开始)。
  2. 文件必须包含 YAML frontmatter(参考现有任意规则的开头):
    ---
    id: "13"
    title: "<规则标题>"
    severity: must
    ---
    
  3. 同步更新:
  4. ../CHANGELOG.md "Unreleased" 段记录新增规则。