文档说功能已完成,代码里却没有——怎么让这种错误在构建时就失败?
把 69 条主张写成机检条目,接入构建的第 5 道闸门:宏必须真被定义、拒绝码必须真被赋值、能力位不得同时出现在「未实现」列表。某类登记数低于下限,判定为「判据无效」,而不是「一切正常」。
做法是把「我们做到了 X」从散文变成可机检的条目:每条主张写一行 <类> | <字段>,由一个脚本在构建时逐条核对;核对不过就中断构建。当前登记 69 条(结构 12、拒绝码 9、能力位 13、判据存在性 33、留位 2)。关键在于配套的三条纪律:没有判据的条目必须显式声明理由、某类登记数低于下限就判定闸门失效、对外门面里的状态必须与代码一致。
现象
两轮独立审计查出 5 处「文档与实现不一致」,全部是同一个形状:文档写了,代码没做。
| 不一致形态 | 后果 |
|---|---|
| 某一节只写不做 | 他人按文档调用,得到静默失败 |
| 两条规则字面互相矛盾 | 无法同时满足,必有一条被忽略 |
| 漏写一个同步动作 | 状态机在边界条件下卡住 |
| 工具参数只说不做 | 校验形同虚设,误以为已检查 |
这些问题的共同点是:人能发现,机器发现不了。而人工审计的成本随规模线性上升,人一累就会漏。
更危险的一点在于它比「完全没做」更坏:
完全没做,下一个人会去实现它;文档写了、代码没做,下一个人会照着文档去改——从而把原本能跑的部分改坏。
原因
文档与代码之间没有可执行的连接。散文里的「已支持」「必须拒绝」「应当校验」都是自然语言断言,编译器不认,构建不查,测试不覆盖。
于是只有两种结局:要么靠人反复通读,要么靠事故暴露。
怎么做
第一步:给每条主张定一个"机检形式"。 不是描述,而是机器能判的字段组合。登记表格式 v1.0 如下:
A | OFF_SENSOR_MAP | src/engine.h
B | DB_RC_CRC | src/dev_bind.h | tools/dev_bind_test.py | 坏 CRC 必须被拒
C | DCL_CAP_HOTRELOAD | src/transport.h
E | 契约§3.8.3 接受时清 reject | tools/accept_test.py | reject_clear
| 分隔而不是空格——多词字段必须能被完整表达,这一点是用 10 条假红换来的(见下)。
第二步:为每类主张定义"机检什么"。 五类核心判据:
| 类 | 对象 | 机器要验证的 | 当前条目 |
|---|---|---|---|
| A | 结构 | 宏在被指文件里真被定义;特定前缀还须被静态断言引用 | 12 |
| B | 拒绝码 | ① 定义 ② 在实现里真被赋值 ③ 验收脚本里有判据读到 | 9 |
| C | 能力位 | 出现在「已实现」集合,且不在「尚未实现」集合 | 13 |
| N | 留位 | 反过来:在「尚未实现」里、且不在「已实现」里 | 2 |
| E | 判据存在性 | 契约里每条「能失败的判据」,脚本里真有同名判据 | 33 |
还有两类自动检查,不占登记条目:完整性(每个能力位都必须被登记为 C 或 N,否则闸门看不见它)与门面一致性(表格行不得自相矛盾、文中「当前状态」必须等于代码里的定义)。
第三步:接进构建,失败即中断。
# build.sh 中的第 5 道闸门
if ! "$PY_BIN" "$WIN_HERE/tools/ref_claims_check.py" --root "$WIN_HERE"; then
exit 1
fi
第四步:给闸门本身设下限。 覆盖率不达标要判「判据无效」,不能因为"扫到 0 条"就打印一切正常:
MIN_A = 8 MIN_B = 4 MIN_C = 5
MIN_N = 2 MIN_E = 6 MIN_F = 2
验证
| 检查项 | 实测 |
|---|---|
| 闸门是否真接入构建 | build.sh 第 239 行调用校验脚本,失败即 exit 1 |
| 校验脚本是否真实存在 | 39,549 字节,含解析与五类判据实现 |
| 登记条目总数 | 69 条(A 12 / B 9 / C 13 / E 33 / N 2) |
| 覆盖率下限 | 六项下限均在脚本中定义,低于下限即判判据无效 |

三个由事故换来的细节,比判据本身更值钱:
① 分隔符错了会产生假红。 改前用空格分隔,多词字段被拆错,一次跑出 10 条假红;改后统一用竖线分隔。假红的代价不是麻烦,而是下次真红没人信——所以这条也写进了工具注释。
② 「扫到 0 条」曾经打印 OK。 这与另外两个校验脚本踩过同一个坑:正则没匹配上时返回空集合,脚本认为"没有问题"。修法是把下限写进代码,让"空"变成失败。
③ 门面比正文更容易腐坏。 同一天里,README、差距表、发布说明出现过 6 处过期状态。契约与代码一致、但对外文档写着旧状态,读者照样被误导——于是专门补了一类「门面一致性」检查:表格不得自相矛盾、状态值必须与代码定义相等、文中链接必须指向真实文件。
边界
- 这套闸门校验的是结构一致性(文档说的符号、状态、判据是否真实存在),不是行为正确性。代码能编译、断言能通过,也不代表控制律是对的。
- 它只能约束"被登记的主张"。没有被写进登记表的隐性假设,闸门看不见——所以「完整性检查」只能保证能力位不漏,保证不了思路漏洞。
- 登记表本身可能写错:字段填了、判据名拼错,会得到一条"通过"的假象。这类风险靠定时的人工复核与引用扫描(文档里的文件与行号是否仍存在)兜底。
- 覆盖率下限是经验值,防的是"空表冒充干净",防不住"少登记几条以求过关"。
- 引入成本不低:每加一个能力位、一个拒绝码,都要同步登记并写判据,否则构建直接失败。这既是它的价值,也是它的摩擦。
最后验证于 2026-10-29 · 项目 claims 登记表(69 条)· 构建脚本第 5 道闸门 · 覆盖率下限六项