chore(id-check): 两根护栏转报告制——编号门禁减负第一步

背景(用户裁定 2026-10-28):语义标识已是默认形态,编号体系本身不再产生价值,
而门禁每次都花时间。实测拆账:单次运行只有 1.8 s,但 近 80 笔提交里 61 笔 改了
id_registry.json / id_aliases.json / check_ids.py / docs/编号规范.md;语料共 99 族
(78 族已冻结、8 族快照、21 族未冻结),registry 87.6 KB + 别名表 187 KB。
结论:贵在养语料,不在跑检查。故先摘掉语料审计的强制面。

本笔只做第一步(①②③ 路线见 docs/编号规范.md §8.5):
- 护栏 1(可判定比例基线)与护栏 2(不可判定引用绝对数上限)改为 只打印、不影响退出码;
  输出标签由 [比例] 改 [比例·报告],越线打 [报告] 两行并指向 §8.5。
  --update-baseline 保留(只用来把当前值记成新记录基线)。
- 校验 1~6 不动:台账外新账照旧拦提交,这是本次减负的边界。
- 同步改口径文档:docs/编号规范.md §8 表与 §8.1 护栏行 + 新增 §8.5 退役路线,
  docs/门禁说明/id-check.md §1 表 + §6 限制第 7 条 + 新增 §7.6.1,AGENTS.md 门禁段,
  id_registry.json 两条 note,各加一条 2026-10-28 变更记录行。

自证(实测):
- 把 decidable_ratio_baseline 临时改 99.9、undecidable_total_ceiling 临时改 1 →
  两护栏必然越线,实跑 退出码 0,只出 [报告] 两行;字节级还原 registry 后复跑正常。
- 反向自证牙还在:往一个新文件写一个自造前缀 + 数字(让 git 看见该文件)→
  校验 1 报 1 处错误 + 增量拦截 FAIL,退出码 1。
- 全门禁:check_ids --strict 校验 1~6 无错误(可判定 87.15% / 不可判定 1033,仅报告);
  doc-links --all --sections-strict 通过(210 文档);mojibake / bom-guard /
  coding-standard / git diff --check 全 rc=0。钩子数不变(替换口径,不加不减)。
This commit is contained in:
2026-10-28 12:18:00 +08:00
parent 6daa01aea4
commit bf2a5c21b0
5 changed files with 54 additions and 24 deletions
+1 -1
View File
@@ -92,7 +92,7 @@
## 提交门禁(pre-commit)
- 任一失败即拦截,共 **51 个钩子**(**口径 = YAML 解析后的 hook 条目数**:自查命令与「声明 / 文档 / 实跑」三数同源核对见 `docs/门禁说明/README.md` §2 首条——⚠ 直接 grep 配置里的声明行会多算一条**注释掉的**候选钩子(= 52),不是口径;**配置注释里也别复述那个 grep 字面量**,它会让文本计数再虚高 1(2026-10-27 实测踩过);加一条钩子就同批改 AGENTS 与门禁索引两处计数。2026-10-25 道E 连加 `bom-guard` / `setview-check` / `uinav-selftest` 三条,2026-10-26 加 `generated-fresh` 一条,2026-10-27 加 `nested-comment` 一条;**每种门禁一篇详解(查什么 / 拦下过什么真事 / 限制与盲区 / 基线口径)→ `docs/门禁说明/README.md` 索引**;通用机制与整体口径 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers` + `id-check`(**编号门禁**,`docs/编号规范.md` §8 八项校验;**已关闸为【增量拦截】**:只拦 `scripts/id_known_backlog.json` 台账之外的新错误级问题,存量按指纹豁免、台账只减不增;另有一根恒生效的线——可判定比例跌破 `id_registry.json` 基线即失败;**2026-10-26 方案 B 同批加了第二根**:不可判定引用**绝对数**超过 `undecidable_total_ceiling` 即失败,因为比值会被"把可判定的引用改成散文"稀释(详见 `docs/门禁说明/id-check.md` §7.6))+ `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + 主机侧单测 **22 根专属钩子**(`-unit-test` 后缀 = 有独立 `files:` 触发面、需要秒级归因的那个子集;2026-10-25 增补 adc-cal / prot-dim / vol-idle-sync / ui-data / meas / run-par 六根)——**这是口径不是缺口**:`test/host/` 实测 40 套带 `run_unit_test.py`,其余 **18 套**(含 `test/host/ui_sink`)没有专属钩子,但每次提交都被 `test-coverage` 总闸全量真跑并守基线回退,**失败照样拦**,只是归因落在总闸输出上;**没有专属钩子 ≠ 没被跑**,18 套台账与补钩子的判据 → `docs/门禁说明/host-unit-tests.md` §6 第 4 条。**Lead 裁定 2026-10-27:不补第 23 根**——读「这套跑没跑」去看总闸输出,别数钩子(原写「23 个 / 含 ui-sink 七个」是双重错:既把 22 说成 23,又宣称 ui-sink 有钩子——配置历史里 `ui-sink-unit-test` 从未存在)+ `test-coverage`(**覆盖率总闸**:跑全部 40 套并守基线回退;缺 mscoverage 组件时按用户裁定 **FAIL**、不 skip,2026-10-24)+ `test-suite-switch` + `registration-check`(双端注册反向校验 + UI 页面描述符表接线,登记簿条目「rs485_task 白名单缺口」)+ `generated-fresh`(**生成器幂等性**:把 `tools/menu_gen/gen_menu.py`、中文字库链、`tools/arch_diagram/gen_*.py` 拷进**系统临时目录**重跑,与工作区**逐字节**必须一致——钩子只读、不写仓库也不 stash 别人在飞的改动;实证 `0f7b5a87` 改了模板文字没重跑生成物,接线前实测另有 5 张 `docs/images/` 配图已漂 → 钉成只减不增基线,**业务生成物零豁免面** → `docs/门禁说明/generated-fresh.md`)+ `nested-comment`(**块注释嵌套**:注释体内再出现 /* 会被 ARMCC 报 9-D,且**按包含者数量刷屏**、只在重编译该 TU 时才暴露;本仓诱因就是「在注释里写作用域/通配路径」,改法是写全目录或用尖括号 <Drivers/BSP/UI/ui_x.c>;接线当日实扫 403 个 .c/.h,新发 0、存量 2 处(`test/host/common/` 两份假件头)钉只减不增基线 → `docs/门禁说明/nested-comment.md`)+ `mem-budget`(RAM 92% 预算门禁,登记簿条目「缩堆迁 CCM 后半(暂缓)」)+ `font-charset`(UI 字符集差集检查,防缺字白框)+ `ui-golden`(UI 像素回归,菜单 8 状态 + 内容页 60 页黄金参考)+ `layer-deps`(**分层方向**:`Drivers/BSP/**` 不得 include `App/**` 的头;存量 3 条基线只减不增(2026-10-25 记录 reader 注入削掉 UI 记录 3 条边,6→3))+ `bsp-err`(**BSP 错误码与超时命名约定**:公开 API 不得拿 `HAL_StatusTypeDef`/`bool` 当错误通道、`*_TIMEOUT` 宏不得取负值、非 void 须写「返回值:」、**返回错误码的函数不得裸丢弃返回值**(须接住或显式 `(void)`;实测编译器与 cppcheck 都不报这类,只有这条会响);约定正文 `Drivers/BSP/bsp_err.h`,存量基线只减不增(2026-10-23 首清点 19 条 → 已还 18;`consume-result` 上线又暴露 37 条存量丢弃 → **现 38 条**))
- 任一失败即拦截,共 **51 个钩子**(**口径 = YAML 解析后的 hook 条目数**:自查命令与「声明 / 文档 / 实跑」三数同源核对见 `docs/门禁说明/README.md` §2 首条——⚠ 直接 grep 配置里的声明行会多算一条**注释掉的**候选钩子(= 52),不是口径;**配置注释里也别复述那个 grep 字面量**,它会让文本计数再虚高 1(2026-10-27 实测踩过);加一条钩子就同批改 AGENTS 与门禁索引两处计数。2026-10-25 道E 连加 `bom-guard` / `setview-check` / `uinav-selftest` 三条,2026-10-26 加 `generated-fresh` 一条,2026-10-27 加 `nested-comment` 一条;**每种门禁一篇详解(查什么 / 拦下过什么真事 / 限制与盲区 / 基线口径)→ `docs/门禁说明/README.md` 索引**;通用机制与整体口径 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers` + `id-check`(**编号门禁**,`docs/编号规范.md` §8 八项校验;**已关闸为【增量拦截】**:只拦 `scripts/id_known_backlog.json` 台账之外的新错误级问题,存量按指纹豁免、台账只减不增;两根护栏(可判定比例基线 / 不可判定引用**绝对数**上限)**自 2026-10-28 起只报告、不拦提交**(用户裁定:语料维护成本已高过它买到的一致性;退役路线见 `docs/编号规范.md` §8.5),硬拦的只有校验 1~6 的台账外新账(口径见 `docs/门禁说明/id-check.md` §7.6.1))+ `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + 主机侧单测 **22 根专属钩子**(`-unit-test` 后缀 = 有独立 `files:` 触发面、需要秒级归因的那个子集;2026-10-25 增补 adc-cal / prot-dim / vol-idle-sync / ui-data / meas / run-par 六根)——**这是口径不是缺口**:`test/host/` 实测 40 套带 `run_unit_test.py`,其余 **18 套**(含 `test/host/ui_sink`)没有专属钩子,但每次提交都被 `test-coverage` 总闸全量真跑并守基线回退,**失败照样拦**,只是归因落在总闸输出上;**没有专属钩子 ≠ 没被跑**,18 套台账与补钩子的判据 → `docs/门禁说明/host-unit-tests.md` §6 第 4 条。**Lead 裁定 2026-10-27:不补第 23 根**——读「这套跑没跑」去看总闸输出,别数钩子(原写「23 个 / 含 ui-sink 七个」是双重错:既把 22 说成 23,又宣称 ui-sink 有钩子——配置历史里 `ui-sink-unit-test` 从未存在)+ `test-coverage`(**覆盖率总闸**:跑全部 40 套并守基线回退;缺 mscoverage 组件时按用户裁定 **FAIL**、不 skip,2026-10-24)+ `test-suite-switch` + `registration-check`(双端注册反向校验 + UI 页面描述符表接线,登记簿条目「rs485_task 白名单缺口」)+ `generated-fresh`(**生成器幂等性**:把 `tools/menu_gen/gen_menu.py`、中文字库链、`tools/arch_diagram/gen_*.py` 拷进**系统临时目录**重跑,与工作区**逐字节**必须一致——钩子只读、不写仓库也不 stash 别人在飞的改动;实证 `0f7b5a87` 改了模板文字没重跑生成物,接线前实测另有 5 张 `docs/images/` 配图已漂 → 钉成只减不增基线,**业务生成物零豁免面** → `docs/门禁说明/generated-fresh.md`)+ `nested-comment`(**块注释嵌套**:注释体内再出现 /* 会被 ARMCC 报 9-D,且**按包含者数量刷屏**、只在重编译该 TU 时才暴露;本仓诱因就是「在注释里写作用域/通配路径」,改法是写全目录或用尖括号 <Drivers/BSP/UI/ui_x.c>;接线当日实扫 403 个 .c/.h,新发 0、存量 2 处(`test/host/common/` 两份假件头)钉只减不增基线 → `docs/门禁说明/nested-comment.md`)+ `mem-budget`(RAM 92% 预算门禁,登记簿条目「缩堆迁 CCM 后半(暂缓)」)+ `font-charset`(UI 字符集差集检查,防缺字白框)+ `ui-golden`(UI 像素回归,菜单 8 状态 + 内容页 60 页黄金参考)+ `layer-deps`(**分层方向**:`Drivers/BSP/**` 不得 include `App/**` 的头;存量 3 条基线只减不增(2026-10-25 记录 reader 注入削掉 UI 记录 3 条边,6→3))+ `bsp-err`(**BSP 错误码与超时命名约定**:公开 API 不得拿 `HAL_StatusTypeDef`/`bool` 当错误通道、`*_TIMEOUT` 宏不得取负值、非 void 须写「返回值:」、**返回错误码的函数不得裸丢弃返回值**(须接住或显式 `(void)`;实测编译器与 cppcheck 都不报这类,只有这条会响);约定正文 `Drivers/BSP/bsp_err.h`,存量基线只减不增(2026-10-23 首清点 19 条 → 已还 18;`consume-result` 上线又暴露 37 条存量丢弃 → **现 38 条**))
- **范围 = 项目代码**:第三方(`Lib/`、`Middlewares/`、CMSIS、HAL、`lftpd`、`dhara`、`MDK-ARM`)排除;`cppcheck`/`coding-standard` 另排除 `test/`,规范检查再排除 CubeMX 生成的 `Src/`/`Inc/`。**`simulator/` 已纳入全部钩子**(2026-10-11)——生成物只靠 `.gitignore` 挡,**不在 `exclude` 里写目录名**(教训见 `docs/代码规范/pre-commit使用说明.md` §5.5)
- ⚠ **pre-commit 4.x 已移除 `always: true`**(实测对 `local` 钩子只告警 `Unexpected key(s)` 并跳过)→ 想"总是跑"的钩子**必须让 `files:` 覆盖到所有会触发它的文件**,没有兜底开关
- **改写型钩子(`trailing-whitespace` + `end-of-file-fixer`)豁免 CubeMX/Keil 生成文件**(配置里 YAML 锚点 `&cubemx-generated`);⚠ **只读检查不受影响**:`cppcheck` / 乱码 / `cubemx-survival` / `task-table` / `mem-numbers` 仍覆盖 `Src/`、`Inc/`
+21 -7
View File
@@ -227,23 +227,23 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
查什么、报错怎么读、盲区在哪——**全在 `docs/门禁说明/id-check.md`**,本文只留口径与基线。
八项校验一句话版:① 未登记前缀 ② 形态不合规(裸形 / 空格 / 中文 / 补零)③ 悬空引用 ④ 重复定义
⑤ 冻结族越游标 ⑥ 编号未紧邻文档名 ⑦ 孤儿条目(告警)⑧ 可判定比例 + 两根护栏。
⑤ 冻结族越游标 ⑥ 编号未紧邻文档名 ⑦ 孤儿条目(告警)⑧ 可判定比例 + 两根护栏(**自 2026-10-28 起只报告,不拦提交**,路线见 §8.5)。
### 8.1 当前基线(2026-10-26 编号迁移批次后重打)
| 项 | 数值 |
|---|---|
| 扫描文件 / 编号字面量 | 784 个 / **7,828 处**(2026-10-27 复测;两批清理前 10,956 → 8,230,此后新代码与新文档回涨 553 处,其中测试用例族占大头,见 §9.1) |
| **护栏 1**:可判定比例下限 `decidable_ratio_baseline` | **86.0%**(实测 86.01%;容差 0.1pp,只许涨) |
| **护栏 2**:不可判定引用绝对数上限 `undecidable_total_ceiling` | **1,166 处**,只减不增(2026-10-27 实跑 **1,161** 处,余量 5;构成拆解见 `docs/门禁说明/id-check.md` §7.7) |
| **护栏 1**(报告值,不拦提交):可判定比例下限 `decidable_ratio_baseline` | **86.0%**(2026-10-28 实跑 87.15%;容差 0.1pp) |
| **护栏 2**(报告值,不拦提交):不可判定引用绝对数上限 `undecidable_total_ceiling` | **1,166 处**(2026-10-28 实跑 **1,033** 处;构成拆解见 `docs/门禁说明/id-check.md` §7.7) |
| 校验 1/2/3/4/5/6 错误级 | **0**;债务台账 0 条指纹 → `--strict` 实为**全量拦截** |
| 告警 | 悬空 2(`App/algo/freq.c` 的正序 / 负序记号,属 §4.4 误判面)+ 孤儿 50(陷阱条目这类本就允许无人引用) |
> ⚠ **读这些数字的口径**:跨批次**不可直接相减**。方案 B 把"本可判定的引用"换成散文,分子分母同缩,
> 比例反而从 86.7% 掉到 85.98%,而**不可判定绝对数一处没涨**——所以同批加了护栏 2,并把比例基线
> **人工下调**一次(工具按设计拒绝下调,必须留书面理由,见 `docs/门禁说明/id-check.md` §7.6);本规范瘦身后比例回到 86.0%,
> 护栏 2 也顺手从 1,192 收紧到 1,166。
> 以后判断"编号有没有变坏"看**绝对数**,不看比值:号只许越清越少,新增没登记的号一定被护栏 2 拦住。
> 比例反而从 86.7% 掉到 85.98%,而**不可判定绝对数一处没涨**——护栏 2 就是这么来的。
> **2026-10-28 起两根护栏都只报告、不拦提交**(用户裁定:语料维护的成本已经高过它买到的一致性——
> 近 80 笔提交里 61 笔被编号体系牵连)。数字照样打,但不再决定一笔提交能不能过;
> 硬拦的只剩校验 1~6 的台账外新账。判断"编号有没有变坏"仍看绝对数与字面量总数。退役路线见 §8.5。
### 8.3 改号与清号批次(只留要点)
2026-10-21 五批统一改名(陷阱号归范、主机侧单测认代码为属主登记处、追溯器三档口径对齐);
@@ -257,6 +257,19 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
**台账之外**的新账,台账只减不增。本批台账已还清到 **0 条**——从现在起任何一条新错误级问题都会当场
拦提交,**别指望还有豁免面**可钻。
### 8.5 门禁退役路线(2026-10-28 裁定)
目标不是"关掉检查",而是把成本从**养 99 族语料**降到**禁止新编号**。三步,每步可独立回滚:
| 步 | 内容 | 状态 |
|---|---|---|
| ① | 两根护栏(比例基线 / 不可判定绝对数上限)**转报告制**:照打数字,不再影响退出码 | **已完成 2026-10-28** |
| ② | 用 **diff 级新号拦截**替换语料审计:只看新增行里命中"字母+数字"形态、且不在豁免表里的字面量,FAIL 并提示改成语义短语;豁免表约 50 条(器件位号 / 协议与端口名 / 遥信遥控点号),基本不增长 | 待做 |
| ③ | 退役语料:99 族盘点成"活族清单",冻结族段与 `id_aliases.json` 移入归档;`check_ids.py` 降为手工报告工具,退出钩子 | 待做(② 落地观察一周再动) |
**在 ② 落地之前,校验 1~6 仍是唯一的机械牙**:别因为"两根线不拦了"就顺手写号——
新增的未登记前缀照样当场 FAIL(实测:在一个新文件里写一个自造前缀 + 数字,校验 1 与增量拦截双拦)。
---
## 9. 还剩什么:存量清点与批次(2026-10-27 实测)
@@ -440,6 +453,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
| 日期 | 变更 | 说明 |
|---|---|---|
| 2026-10-28 | **编号门禁减负第一步:两根护栏转报告制** | 用户裁定「编号门禁每次浪费很多时间」→ 先摘掉语料审计的强制面。护栏 1(可判定比例基线)与护栏 2(不可判定绝对数上限)自此**只打印、不拦提交**;实测把基线调到 99.9%、上限调到 1 处,退出码仍为 0。硬拦只剩校验 1~6 的台账外新账(同一实测:新文件里写一个自造前缀 + 数字,校验 1 与增量拦截照旧 FAIL)。退役路线 ①②③ 写进 §8.5;减负依据 = 近 80 笔提交有 61 笔被编号体系牵连、语料共 99 族(78 族已冻结)。 |
| 2026-10-28 | **变更记录行里已停发/作废族的示例编号改形态描述;并用门禁自身计数器把「这一笔能不能压下不可判定绝对数」钉死为零** | 用户指令:把变更记录行里已停发族的那几枚示例编号改成语义形态描述,并确认它让不可判定引用绝对数净减、不是只算自己这一笔。**实测裁定:净减 = 0**。门禁把「表格首格是日期」的行整行豁免于编号判定(registry 侧的变更记录豁免,本笔前全库已豁免 198 处站点),本表的示例编号从来不进引用总数分母,改它必然不动绝对数——改前改后同一个计数器均为 **1003**(上限 1166;可判定 87.43%,三项都是 2026-10-28 本回合实测)。唯一移动的是那行豁免计数本身(本文件少 1 处站点),把它当清退成果就是把自记账成全局减量,正是本笔要排除的错法。本文对该计数器的全部贡献 **6** 处,逐文件集合差实测:全是「非编号」判定栏里既定的噪声名与裸形盲区(哈希算法名、总线名、严重度档位、硬件位号),不是编号,不清。本笔动的 3 处只是写法:作废的网络条目孤儿号(F 前缀 + 模块码段 + 数字序号三段)与已删报告的 UI 簇(字母 U 紧跟一位数字,区间两端即该簇首尾两枚);事实本体仍在别名表、registry 游标备注与 git 历史,一处没丢。刻意不动:硬件位号形态的举例(判非编号)、保留现存号族的冻结游标数字(冻结水位的证据本体)、其它文档与注册表里的同名字段(各自写域)。§5.5 同步写死该例外的硬口径。零代码、零编号增删、两根护栏基线均未调整。 |
| 2026-10-27 | **批次五:「数据可信」任务卡号整族清退 + 注入验证卡销项删行** | 用户指令「数据可信.md 已经完成的内容请进行销项删除,去除相关编号」。实测 **288 站点 / 56 文件**(代码与测试 191 / 文档 56 / 门禁配置与本文 41)全改语义短语;§5 表首列由「序」改「标识(任务名)」、14 个旧号进 §9.3 换算表;顺带按属主文档判语义清掉同形态的悬空引用 4 处(「UI 补齐」波次的 `[comm]` 段前置项)。门禁面:编号字面量与不可判定绝对数**零变化**(中文前缀不在语料),收口复跑 `check_ids.py --strict` 与 `check_doc_links.py --all --sections-strict` |
| 2026-10-27 | **批次四:`L-PROT` / `FEAT` 发号口关闭(§4.1 七行→五行)+ 本文自述形态化 + 登记 `T-TEST` 机器面空白** | 用户指令「语义标识已定为默认形态,看看还有哪些编号族仍被引用、各自还剩多少,把能清的族清掉一批」。按门禁 `Checker` 实测三口径重打 §9 存量表:**真编号活引用只剩 `TC-*`(保留、水位 497/81 未涨)、`TRAP-*`、`CODE-RULE-*`、`MENU-STATE-*` 四族**,批次一/二涉及的 `N-*`/`TM-*`/`T-TEST`/`L-PROT`/`FEAT` 活引用均已归零。本笔:① §4.1 把 `L<n>-<nn>`、`F-<MOD>-<nn>` 从『允许继续发号』整行移出并在『已停发』栏各写一行(含探针证据:新形态号 → 校验 3 错误级);② 本文 6 处形态自述改「字母+数字」描述,使四个族门禁命中归零、lesson 不丢;③ registry 给 `L-PROT`/`FEAT` 补 `retired`、给 `T-TEST` 补 cursor_note(pattern 上限即 3 → 冻结游标是空操作,停发今天只有规范效力);④ 分类登记 §4.4 误判面(版本记号 / 活表代号 / 状态组合 / 位号)与 §4.3 冻结波次号两类**不清**的理由。未改门禁判定逻辑、未动冻结历史与原始串口日志、未新增任何号。 |
+15 -2
View File
@@ -20,7 +20,7 @@
| 5 | **冻结族越游标**:已冻结的族里出现游标之外的新号 | 错误 |
| 6 | **引用未紧邻文档名**:文档内编号(各文档自己的风险表等)裸引 | 错误 |
| 7 | **孤儿条目**:定义了但全库无人引用 | 告警(不拦) |
| 8 | 打印**编号引用可判定比例**,只许涨不许跌(跌破 `id_registry.json` 里的基线即失败) | 恒生效 |
| 8 | 打印**编号引用可判定比例**与**不可判定引用绝对数**;记录基线 / 上限在 `id_registry.json` | **只报告**(2026-10-28 起不再失败,见 §7.6) |
"定义"的机械判据是:**该字面量出现在它所属族的"属主登记处"文档里**。不依赖表格行首之类
容易漂移的形态。副作用要知道:把号写进属主文档的**任何位置**都算定义。
@@ -86,7 +86,8 @@
否定("该号从未存在")也算定义——批量改名工具最阴的失效模式就是"字面改对、意思改错"。
6. **登记表类文件不得当引用语料**(`id_registry.json`、`id_aliases.json`、`id_known_backlog.json`、
`scripts/rename_maps/` 里必然写着旧的非法形态),否则第一次提交就被自家审计表当"新账"拦下。
7. 校验 8 只许涨不许跌:好处是防退化,代价是**顺手写一个未登记族的号就会红**,哪怕与本次改动无关。
7. 校验 8 的两根护栏**自 2026-10-28 起只报告、不拦提交**:此前"只许涨不许跌"好处是防退化,代价是
**顺手写一个未登记族的号就会红**,哪怕与本次改动无关——代价最终由每一笔提交付,故转报告制(§7.6 末)。
8. 它不懂"这个号该不该存在"。新增一族编号是否合理,仍是 `docs/编号规范.md` 的人工判断。
9. **变更记录行豁免**(2026-10-26 加):首格是日期的表格行不参与判定——政策禁止回改历史,
拦它等于逼人改历史或 `--no-verify`。代价:新写进变更记录行的旧形态编号照不出来。
@@ -158,6 +159,17 @@
(`| v1.6 | 2026-10-25 | …`)那类表漏豁免——同一份冻结历史被两种表头拆成两种待遇,属工具缺陷,
现已补齐(要求版本号与日期两格连排,单独的版本号不算,避免普通表格被误免)。
### 7.6.1 2026-10-28:两根护栏转「报告制」(本节口径的最新状态)
用户裁定:**编号门禁每次浪费很多时间,而语义标识已是默认形态** → 先摘掉语料审计的强制面。
- 变的是**强制力**:护栏 1 / 护栏 2 越线只打 `[报告]` 两行,退出码不再受影响;
上面 §7.6 描述的"下调基线要留书面理由"这套摩擦**随之退役**(`--update-baseline` 仍在,用来记当前值)。
- 不变的是**牙**:校验 1~6 的台账外新账照旧拦提交(`--strict`),这是本次减负的边界。
- 减负依据(实测):单次运行仅 **1.8 s**,但**近 80 笔提交里 61 笔**改了语料 / 门禁 / 规范;
语料共 **99 族**(78 族已冻结、8 族快照、21 族未冻结),registry 87.6 KB + 别名表 187 KB。
- 后续路线(替换语料审计 → 退役语料)见 `docs/编号规范.md` §8.5。
## 7.7 「不可判定绝对数」到底是什么:构成实测 + 每批自证没吃余量的做法(2026-10-27)
先给一条与直觉相反的结论,它是这一节存在的理由:**给带属主登记处的族加引用,完全不吃这根护栏**
@@ -220,6 +232,7 @@
| 日期 | 变更 |
|---|---|
| 2026-10-28 | **两根护栏转报告制(减负第一步)**:护栏 1(可判定比例基线)/ 护栏 2(不可判定绝对数上限)不再影响退出码,只打 `[报告]` 两行;探针实测基线 99.9% + 上限 1 处 → 退出码 0。边界自证:新文件里写一个自造前缀 + 数字 → 校验 1 与增量拦截照旧 FAIL。口径与退役路线见本文 §7.6.1 与 `docs/编号规范.md` §8.5 |
| 2026-10-28 | **批次六收口复测自证**(Lead 单道执行,本轮未并行派单):把 「retired-to-phrase」 与 「void」 两类别名当探针全库复扫(排除 `excluded_paths`、门禁自身语料与变更记录行口径),**真编号活引用 0**——剩余命中面是变更记录行(§4.3 不回改)、元器件位号与 Socket 状态组合(§4.4 判非编号,清它等于改硬件资料)、属主文档的历史对照列。教训两条:① 本文件的当日构成表按冻结证据保留不重打,§8.1 那两根护栏的账面数**随在飞改动漂移**,把某天的实测值写进正文表格等于给自己造一条会过期的断言,本轮第一次尝试就这么撞了一次(写完再跑,数已经变了);② 想留当日数就写进 `ci-artifacts/` 下的仓库外口径文件,正文只留结论与口径。本笔零编号增删,护栏基线不动。 |
| 2026-10-27 | **本仓第一次真正「还」第二根护栏的债**(道G task-45):卷锁观测计数旁自造的四位状态号(一字母+一数字的裸形写法)全量换成语义短语——`App/fs/vol_lock.c`、`App/fs/vol_lock.h`、`test/host/vol_lock/vol_lock_test.c`、`docs/测试说明/卷锁单元测试说明.md` 四处共 36 处出现清零,四态语义只留 `App/fs/vol_lock.h` 一处。改前实测不可判定绝对数 1,162(03:15),改后 1,156(03:22),余量从 4 格变 10 格;`--strict` exit 0、卷锁套件 45/45 未掉、未动 `undecidable_total_ceiling`。**顺带查清一件口径事,比这次还债本身更值得记**:绝对数只统计**落不进任何已登记族**的裸形;撞进已登记族的写法(台架/测试那一族的族模式只覆盖到该字母加一位数字的 0~3)本来就记在**可判定**一侧——于是这次 36 处里只有 6 处真正减了绝对数,另 23 处删掉是同时缩分子与分母(比值几乎不动:86.74% → 86.77%)。⇒ 「删裸形」不等于「按出现次数还债」;要腾余量得优先清**无族可归**的裸形态,而写文档时一开始就别用裸形才是正解。另注:写在模块头修改记录行里的第 7 处本来就被「变更记录行豁免」挡住不计数,所以账面是 6 不是 7。 |
| 2026-10-27 | 新增 §7.7:实测拆解「不可判定绝对数」的构成(裸形盲区 834 + 噪声白名单 326 + 真·硬不可判定 2 = 1,162,精确闭合),并写入每批自证没吃余量的五项式做法(含「不得用 stash/checkout 回退别人在飞改动」与 --update-baseline 只下调);同批撤回一条 Lead 错指令——「怕吃余量而把编号写成散文」恰好是 §7.6 这根护栏要防的稀释行为 |
+15 -12
View File
@@ -16,7 +16,7 @@ check_ids.py — 编号门禁(docs/编号规范.md §8 的 8 项校验)。
5 冻结前缀出现游标之外的新号 错误
6 文档内编号引用未紧邻文档名 错误
7 定义了但全库无引用(孤儿条目) 告警
8 打印「编号引用可判定比例」 每次运行,只许涨不许跌
8 打印「编号引用可判定比例」 每次运行,只报告不拦提交(2026-10-28 起)
「定义」的机械判据:**字面量出现在该族的属主登记处文档里**(不依赖表格行首这类易漂移的
形态)。因此 §5.5 的「销项 = 删行 + 清全库引用」一旦只做一半,校验 3 立刻报——这正是
@@ -27,7 +27,7 @@ check_ids.py — 编号门禁(docs/编号规范.md §8 的 8 项校验)。
构建产物。裸形盲区显式登记在 id_registry.json 的 `unmanaged_bare`,不是「检查通过」。
上线节奏(§8):默认 **warn-only**(退出码 0);`--strict` 才让校验 1~6 拦提交。
第 8 项的比例跌破基线**任何模式都失败**(它就是防回退的那根线)。
第 8 项(两根护栏)自 2026-10-28 起**只报告、不拦提交**(用户裁定);退役路线见 docs/编号规范.md §8.5。
用法(仓库根):
& '.venv\\Scripts\\python.exe' scripts/check_ids.py # warn-only 全库
@@ -35,7 +35,7 @@ check_ids.py — 编号门禁(docs/编号规范.md §8 的 8 项校验)。
& '.venv\\Scripts\\python.exe' scripts/check_ids.py --top 30 --verbose # 多打 + 修法
& '.venv\\Scripts\\python.exe' scripts/check_ids.py --update-baseline # 抬升第 8 项基线
& '.venv\\Scripts\\python.exe' scripts/check_ids.py --only 1,3,5 # 只跑部分校验
退出码:0 = 通过 / 仅告警;1 = 错误(--strict)或比例跌破基线;2 = 环境错误。
退出码:0 = 通过 / 仅告警;1 = 错误(--strict);2 = 环境错误。(比例 / 绝对数越线不再影响退出码)
"""
import argparse
@@ -660,17 +660,17 @@ class Checker(object):
dec = self.stats["decidable"]
ratio = (100.0 * dec / total) if total else 100.0
base = self.reg.get("decidable_ratio_baseline")
print("\n[比例] 校验 8 编号引用可判定 %d/%d = %.2f%%(基线 %s,容差 %.1fpp)"
print("\n[比例·报告] 校验 8 编号引用可判定 %d/%d = %.2f%%(记录基线 %s,容差 %.1fpp;只报告,不拦提交)"
% (dec, total, ratio,
"未建档" if base is None else "%.1f%%" % base, RATIO_TOL))
print(" 可判定 = 字面量落进已登记前缀族**且该族属主登记处已存在**;"
"未登记前缀、形态违规、属主登记处还是 [计划] 的都算不可判定 → 只许涨不许跌")
"未登记前缀、形态违规、属主登记处还是 [计划] 的都算不可判定(指标口径保留;自 2026-10-28 起只报告)")
# 绝对数护栏(2026-10-26 方案 B 同批加):比值会被口径稀释——**删掉一批「本可判定」
# 的引用反而让比例下跌**(清号批次实测 -0.2pp),拿比值当唯一护栏等于惩罚清号。
# 不可判定引用的**绝对数**不受稀释影响:号只许越清越少,不会因分母变小而"变多"。
und_now = total - dec
ceil_now = self.reg.get("undecidable_total_ceiling")
print(" 不可判定引用绝对数 %d 处%s(只许减不许增;比值会骗人,绝对数不会)"
print(" 不可判定引用绝对数 %d 处%s(只报告,不拦提交;比值会骗人,绝对数不会)"
% (und_now, "(未设上限)" if ceil_now is None else ",上限 %d" % ceil_now))
return ratio, errs
@@ -832,19 +832,22 @@ def main():
except OSError as exc:
print("[WARN] 无法运行追溯脚本:%s" % exc, file=sys.stderr)
# 两根护栏自 2026-10-28 起转「报告制」(用户裁定):只打印,不影响退出码。
# 理由:它们逼着每一笔提交维护 99 族语料(近 80 笔提交有 61 笔被编号体系牵连),
# 而真正防回潮的是校验 1~6 的台账外新账。退役路线见 docs/编号规范.md §8.5。
base = reg.get("decidable_ratio_baseline")
if base is not None and ratio + RATIO_TOL < base and not args.update_baseline:
print("\n[FAIL] 校验 8:可判定比例跌破基线 %.2f%% < %.2f%%(只许涨不许跌,容差 %.1fpp)"
print("\n[报告] 校验 8:可判定比例 %.2f%% 低于记录基线 %.2f%%(容差 %.1fpp)"
% (ratio, base, RATIO_TOL))
return 1
# 绝对数护栏:与比值护栏同时生效,任一越线即失败(§8.1)。
print(" 只报告、不拦提交。想把当前值记成新基线跑 --update-baseline;"
"口径见 docs/编号规范.md §8.5")
# 绝对数护栏同样转报告制(2026-10-28):越线只打印,不影响退出码。
und_now = ck.stats["refs_total"] - ck.stats["decidable"]
ceil_now = reg.get("undecidable_total_ceiling")
if ceil_now is not None and und_now > ceil_now and not args.update_baseline:
print("\n[FAIL] 校验 8:不可判定引用绝对数 %d > 上限 %d(只许减不许增,§8.1)\n"
" → 要么把新增的号登记进属主文档 / 别名表,要么别加这个号"
print("\n[报告] 校验 8:不可判定引用绝对数 %d 高于记录上限 %d(只报告、不拦提交)"
% (und_now, ceil_now))
return 1
print(" 清理方向不变:号只该越清越少;口径见 docs/编号规范.md §8.5")
if err_total:
if args.strict:
led = load_backlog()
+2 -2
View File
@@ -2215,7 +2215,7 @@
"U-RPT"
]
},
"baseline_note": "2026-10-26 方案 B 曾把比例基线由 86.6% 下调到 85.9%(转短语消掉的全是「本可判定」引用,比值被稀释而不可判定绝对数未增;理由见 docs/门禁说明/id-check.md §7.6 与 docs/编号规范.md §8.1);同批新增第二根护栏 undecidable_total_ceiling 后,本文档又瘦身了一半,删掉的多是不可判定的历史号引用,两根护栏已按 --update-baseline 重打为比例 86.0% / 绝对数 1166(都只朝好的方向动)。",
"baseline_note": "2026-10-26 方案 B 曾把比例基线由 86.6% 下调到 85.9%(转短语消掉的全是「本可判定」引用,比值被稀释而不可判定绝对数未增;理由见 docs/门禁说明/id-check.md §7.6 与 docs/编号规范.md §8.1);同批新增第二根护栏 undecidable_total_ceiling 后,本文档又瘦身了一半,删掉的多是不可判定的历史号引用,两根护栏已按 --update-baseline 重打为比例 86.0% / 绝对数 1166(都只朝好的方向动)。2026-10-28 起两根护栏只报告、不拦提交(用户裁定,退役路线见 docs/编号规范.md §8.5)。",
"undecidable_total_ceiling": 1166,
"undecidable_ceiling_note": "不可判定引用绝对数上限(refs_total - decidable),只许减不许增;--update-baseline 同步下调且拒绝上调。加它的原因:比值会被清号动作稀释,绝对数不会。"
"undecidable_ceiling_note": "不可判定引用绝对数上限(refs_total - decidable),只许减不许增;--update-baseline 同步下调且拒绝上调。加它的原因:比值会被清号动作稀释,绝对数不会。2026-10-28 起转报告制:越线只打印,不影响退出码(见 docs/编号规范.md §8.5)。"
}