# 规则编写指南 一条清洗规则 = `cleaner/rules.py` 里的一个函数 + `rules/*.yaml` 里的一条声明。 ## 函数签名 ```python def _your_rule(text: str, params: dict, stats: dict) -> str: ... stats["your_hits"] = stats.get("your_hits", 0) + n # 计入报告 return new_text ``` - 输入输出都是**整篇文本**;引擎按 `order` 从小到大依次调用。 - `params` 来自 YAML,改参数不用改代码。 - `stats` 的 key 会出现在 `report.json`,命名用蛇形复数(如 `page_lines`)。 ## YAML 声明 ```yaml rules: - name: your_rule # 必须与 REGISTRY 键一致,加载时校验 order: 55 # 应用顺序;同段处理尽量插在相关规则之间 enabled: true # 某用例不适用的规则可单关 params: threshold: 3 protect: ["正则1", "正则2"] ``` ## 设计守则(从 gov_test_data 踩坑总结) 1. **只删噪音,不删正文**。拿不准的形态默认保留,宁可漏删不可误删。 2. **重复 ≠ 页眉**。标书是平行模板文档:签章栏、日期栏、声明结尾句、 编号条款都会重复出现。判定页眉前先过: - `protect` 正则(业务模板白名单) - 内容形态豁免(编号/列表/表格/字段行) - burst 检测(连续刷屏才是 OCR 崩坏) 3. **每个规则独立可测**。tests/ 里用真实数据浓缩的最小样例做回归, 尤其是防误伤样例(protect 命中、编号条款保留)。 4. **统计必须可见**。每条规则报告命中数,批量清洗后扫一眼 report.json 就能发现某条规则突然命中异常(多半是误伤)。 ## 已知规则明细 见 `rules/default.yaml` 内注释与 README 规则表。