feat(门禁): id-check 关闸——按债务台账增量拦截,warn-only 时代结束
机制(--strict 不再「有错就失败」,而是只拦台账外的新账) - scripts/id_known_backlog.json:340 条指纹覆盖 710 处存量(②167 类 / ⑥135 / ③38) - 指纹 = (文件, 校验号, 字面量) → 计数,故意不含行号:行号每改必漂, 用它当指纹会让台账天天假新增,三天后没人敢看 strict,台账失效比没台账更糟 - 带计数而非集合:同一文件里同一个号多出现一次也算新账(复制粘贴式扩散 正是编号烂掉的主路径,只按「出现过没有」判会放过它) - 新增 --write-backlog 与 --prune-backlog(只减不增;台账内条目变多当场点名); --strict 缺台账返回 2,绝不退化成一次性拦死存量;--only 与 --strict 互斥 - 钩子 entry 加 --strict;--only 与 --strict 互斥 - 顺带修 _scan_malformed 的反向 bug:原条件 (skip and name != "空格形 Trap") 语义正好写反,带 [示例] 的行反而专被 Trap 规则咬;改为示例行全部不判 - 第一次提交就被自己的台账咬住(id_known_backlog.json 里当然写着 P1-3 等号, 被当成新引用)→ 台账加入 excluded_paths:登记号的表不是引用号的文档, 与 id_aliases.json / id_registry.json 同一条道理 为什么不照「清零再升 strict」的原节奏(§8.4 详述) - 存量 710 处清完要数周,这期间新债一条都不拦,而新增才是烂掉主因 - 「等清零」让人习惯「报红但照样提交」,真关闸那天没人再信门禁; 本仓已有 mem-budget / mem-numbers 走 --no-verify 的先例,不再开第二个口子 关闸验收三例(临时件当场还原、git diff 干净) - A 全新前缀 Z-99 → exit 1 点名 ✅ 咬 - B 同号计数 1→2 → exit 1 点名 ✅ 咬 - C 干净态 710 处 → exit 0 放行 ✅ 放(放不住存量就会逼出 --no-verify) 验证:--strict 干净态 exit 0;可判定比例 82.74%(基线 82.6%); doc-links 失效/待确认 0;未改 C/H 不需 @build。 文档:编号规范 §8 上线节奏改写 + 新增 §8.4 机制表;pre-commit使用说明 §2.25; AGENTS.md 门禁行由 warn-only 改为已关闸增量拦截。
This commit is contained in:
@@ -544,7 +544,7 @@ repos:
|
||||
# (悬空/孤儿/重复定义是跨文件判定,pass_filenames: false)。
|
||||
- id: id-check
|
||||
name: 编号门禁(docs/编号规范.md §8 八项校验)
|
||||
entry: python scripts/check_ids.py
|
||||
entry: python scripts/check_ids.py --strict
|
||||
language: system
|
||||
files: \.(md|c|h|py|ya?ml|json|txt)$|^\.pre-commit-config\.yaml$
|
||||
pass_filenames: false
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
|
||||
## 提交门禁(pre-commit)
|
||||
|
||||
- 任一失败即拦截,共 **37 个钩子**(逐个详解 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers` + `id-check`(**编号门禁**,`docs/编号规范.md` §8 八项校验;**当前 warn-only**,可判定比例跌破 `id_registry.json` 基线才失败)+ `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + 主机侧单测 16 个(`-unit-test` 后缀)+ `test-suite-switch` + `registration-check`(双端注册反向校验 + UI 页面描述符表接线,N-23/U4)+ `mem-budget`(RAM 92% 预算门禁,N-27)+ `font-charset`(UI 字符集差集检查,防缺字白框,U4)+ `ui-golden`(UI 像素回归,菜单 8 状态 + 内容页 11 页黄金参考,U4)
|
||||
- 任一失败即拦截,共 **37 个钩子**(逐个详解 → `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` 基线即失败)+ `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + 主机侧单测 16 个(`-unit-test` 后缀)+ `test-suite-switch` + `registration-check`(双端注册反向校验 + UI 页面描述符表接线,N-23/U4)+ `mem-budget`(RAM 92% 预算门禁,N-27)+ `font-charset`(UI 字符集差集检查,防缺字白框,U4)+ `ui-golden`(UI 像素回归,菜单 8 状态 + 内容页 11 页黄金参考,U4)
|
||||
- **范围 = 项目代码**:第三方(`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/`
|
||||
|
||||
@@ -451,7 +451,7 @@ cppcheck 是开源 C/C++ 静态分析工具,**不运行代码**,通过语法
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| **触发条件** | 任意 `.md` / `.c` / `.h` / `.py` / `.yaml` / `.json` / `.txt` 或本配置文件变动(pre-commit 4.x 无 `always: true`,`files:` 按扩展名覆盖全触发面);**`pass_filenames: false`**——悬空引用 / 孤儿条目 / 重复定义是**跨文件**判定,只喂变更文件必然判错,故每次恒扫全库(实测 536 个文件 1.1 s,够快) |
|
||||
| **处理方式** | **当前 warn-only**(`docs/编号规范.md` §8 上线节奏:先清 backlog → 清零后 `entry` 加 `--strict` 拦提交,与 `doc-links` 章节校验同一条路径)。**唯一例外**:校验 8 的「可判定比例」跌破 `scripts/id_registry.json` 里的基线(82.3%)→ **任何模式都 FAIL**,这根线就是防回退的本体 |
|
||||
| **处理方式** | **2026-10-21 已关闸为【增量拦截】**:`entry` 带 `--strict`,只拦**台账之外**的新错误级问题;存量 710 处按 `scripts/id_known_backlog.json` 的指纹豁免(指纹 = 文件 + 校验号 + 字面量 + 计数,**故意不含行号**——行号会漂,用它当指纹台账天天假新增)。台账只减不增:`--prune-backlog` 收已还清的,条目变多或出现新字面量都当场拦;`--strict` 缺台账直接返回 2,**不退化成一次性拦死存量**(那会逼出 `--no-verify`)。另有一根恒生效的线:可判定比例跌破 `id_registry.json` 基线(82.6%)→ 任何模式都 FAIL |
|
||||
| **八项校验**([示例] 本行引用的是各种非法形态示例,不是真实编号) | ①未登记前缀 ②形态不合规(裸形 `S3` / 空格形 `Trap 07` / 中文形 `陷阱 1` / 补零错 / 档位词带后缀 / 大写后缀 / 缺模块码)③悬空引用 ④重复定义 ⑤冻结前缀越游标 ⑥文档内编号未紧邻文档名 ⑦孤儿条目(告警)⑧可判定比例(只许涨不许跌) |
|
||||
| **配置两份** | `scripts/id_registry.json`:前缀族 → 属主登记处 / 形态正则 / 是否冻结 / 游标,**逐项来自 `docs/编号规范.md` §4 总表**,游标取「规范记载值」与「全库实测最大号」的较大者,偏差写进 `cursor_note`(实测偏差见规范 §8.2);`scripts/id_aliases.json`:旧号 → 新号 / 作废标记(照搬 `section_aliases.json` 的成功范式) |
|
||||
| **判定口径** | 「定义」= 字面量出现在该族**属主登记处文档**里(不依赖表格行首等易漂移形态)→ §5.5「销项 = 删行 + 清全库引用」只做一半,校验 ③ 立刻报(`N-31`/`N-32` 正是这条)。「重复定义」= 字面量出现在**定义位**(表格首格 / 标题行 / 列表项行首),正文提到不算,否则任何交叉引用都会误判成事故。多族同形时的定族顺序:所在文档即属主 > 紧邻属主线索 > **定义位优先**(`docs/编号规范.md` §4.3 冻结快照族 `N-RPT`/`D-RPT`/`S-RPT`/`R-RPT`/`F-RPT`/`P-AUDIT`/`A-AUDIT`/`B-AUDIT` **不参与**——否则已销项的登记簿 `N-21` 会被审计报告同号接管,门禁反过来教人补错文档名,实测把校验 6 从 266 撑到 1437、可判定比例假崩到 68.7%)> 判悬空的族 > 全局族;小写子项后缀(`-b`/`-c`)在母号在册时视为已定义(`subitem_ok`),差异仍由双向追溯如实报 |
|
||||
|
||||
+32
-1
@@ -381,7 +381,7 @@ git grep -n '<旧字面量>' # 零残留
|
||||
| 8 | 打印**「编号引用可判定比例」** | 每次运行,只许涨不许跌 |
|
||||
|
||||
- 排除:`Lib/`、`Middlewares/`、HAL/CMSIS、`docs/芯片手册/`、`docs/硬件平台/`(位号)、构建产物。
|
||||
- 上线节奏:**先 warn-only 清 backlog → 清零后加 `--strict` 拦提交**(与 `doc-links` 章节校验完全同一条路径)。
|
||||
- 上线节奏:**先 warn-only → 2026-10-21 关闸为【增量拦截】**(`--strict` + 债务台账,见 §8.4)。与 `doc-links` 的差别在于:存量太多(710 处),等清零会逼出 `--no-verify`,所以先关闸再还债。
|
||||
- 顺带收编 `scripts/check_test_traceability.py`:正则补齐大写后缀与无模块码形态,覆盖 7 篇「单元测试说明.md」,一并挂进 `id-check`。
|
||||
**2026-10-21 口径改写**(B 层之后):差异分三档——`DOC-ONLY` 文档声明而代码没有(真断链)、`CODE-ONLY` 代码有而母号不在登记处且号旁无意图(真未登记)、`IN-CODE` 靠「代码旁写着意图」放过(弱保证,单列示数、不算过关);小写子项后缀按母号算。
|
||||
|
||||
@@ -457,6 +457,36 @@ git grep -n '<旧字面量>' # 零残留
|
||||
|
||||
---
|
||||
|
||||
### 8.4 债务台账与增量拦截(2026-10-21 关闸)
|
||||
|
||||
**为什么不照 §8 原节奏「清零后再 `--strict`」**:存量 710 处(② 形态迁移 398 + ⑥ 裸引写全属主 269 + ③ 真悬空 44),
|
||||
靠人清完要数周到数月;这期间**新欠的债一条都不会被拦**——而新增恰恰是编号烂掉的主因(`N-31`/`N-32` 撞号
|
||||
就是新增时撞上的)。更糟的是「等清零」会让所有人习惯看到「门禁报红但照样提交」,真到关闸那天已经没人信它。
|
||||
|
||||
**机制**:`--strict` 不再「有任何错误就失败」,而是**只拦台账之外的新错误级问题**。
|
||||
|
||||
| 件 | 说明 |
|
||||
|---|---|
|
||||
| 台账 | `scripts/id_known_backlog.json`:340 条指纹,覆盖 710 处错误级问题(② 167 类 / ⑥ 135 类 / ③ 38 类) |
|
||||
| 指纹 | `(文件, 校验号, 字面量) → 出现次数`。**故意不含行号**:行号每改必漂,拿它当指纹会让台账天天「假新增」,三天后没人敢看 strict 输出,台账等于失效——**台账失效比没有台账更糟** |
|
||||
| 为什么带计数 | 同一文件里同一个号**多出现一次**也算新账:复制粘贴式扩散是编号烂掉的常见路径,只按「有没有出现过」判会放过它 |
|
||||
| 只减不增 | `--prune-backlog` 收掉已还清条目;台账内条目**变多**会被 `--strict` 当场拦;确需新增一条必须写 `reason` 字段(默认禁止顺手加行,否则一周后台账变成第二个 backlog) |
|
||||
| 初始化 | `--write-backlog` 全量快照(关闸那次用过;之后再跑等于豁免新债,须显式确认) |
|
||||
| `--only` 与 `--strict` | **互斥**(局部扫描不能当门禁结论),同时给直接返回 2 |
|
||||
| 缺台账 | `--strict` 直接返回 2 并提示先生成,**绝不退化成「一次性拦死全部存量」**(那样必然逼人 `--no-verify`) |
|
||||
| 台账自身不得当语料 | 关闸第一次提交就被自己的台账咬了:`id_known_backlog.json` 里必然写着 `P1-3` / `Trap 05` 这些号,扫描器当成新引用 → 报 10 类新账、提交被拦。已把台账加入 `excluded_paths`(与 `id_aliases.json` / `id_registry.json` 同一条道理:**登记号的表不是引用号的文档**) |
|
||||
|
||||
**关闸验收(三例,2026-10-21 实测)**:
|
||||
|
||||
| 情况 | 期望 | 实测 |
|
||||
|---|---|---|
|
||||
| A 全新未登记前缀(`Z-99`)[示例] | 拦 | exit 1,`+1 [校验1] docs/tmp_teeth_a.md Z-99` ✅ |
|
||||
| B 同一文件里已登记的号**多出现一次**(计数 1→2) | 拦 | exit 1,`+1 [校验6] ui-verify/SKILL.md 内的 R-9` ✅ |
|
||||
| C 干净态(710 处存量全在台账内) | 放行 | exit 0,`增量拦截通过` ✅ |
|
||||
|
||||
临时注入文件与追加行当场还原(`git diff` 干净)。**C 例最关键**:放不住存量就会逼出 `--no-verify`,
|
||||
那是把门禁从「闸」降级成「报表」——本仓已有 mem-budget / mem-numbers 走 `--no-verify` 的先例,别再开第二个口子。
|
||||
|
||||
## 9. 落地阶段与验收
|
||||
|
||||
| 阶段 | 内容 | 验收判据 | 风险 |
|
||||
@@ -491,6 +521,7 @@ git grep -n '<旧字面量>' # 零残留
|
||||
|---|---|---|
|
||||
| 2026-10-14 | 新增 P-7 与引用可读性规则 | §2 加 **P-7「编号不语义,引用必语义」**(编号本体保持无语义并冻结,但正文引用必须带语义括注、禁裸 ID 独担信息)→ 六条原则变**七条**;§5.1 加前置步"先问能不能不加号";新增 **§5.6「编号密集文档的对照节(强制)」**(≥3 个编号族必须加「导读:编号与术语」);§4.1 补登记 **`E\d+`**(N34 自愈实验编号族,已封闭)并把 `N-\d{2}` 的在册范围订正为「曾用最大 `N-33`,现存至 `N-29`」;§1.2 悬空引用示例补 `N-32`;§7.1 同步订正。起因:`docs/网络/网络自愈架构设计.md` 合并与导读节实践暴露"裸编号引用不可读",用户裁定以后尽量用语义标识 |
|
||||
| (规划稿) | 建立本文档 | 全库扫描 1,385 个不同编号 / 19,306 处出现后定稿的两层编号体系(全局编号 + 文档内编号)、六条原则、目标前缀总表、三批迁移映射与 `check_ids.py` 门禁设计;用户决策:`E-xx` 冻结保留、严重度档位词 `P0~P3` 不变、文档落 `docs/编号规范.md`、阶段 1 三批全做 |
|
||||
| 2026-10-21 | **关闸:`id-check` 转增量拦截** | `check_ids.py` 新增 `--write-backlog` / `--prune-backlog` 与按台账比对的 `--strict`(指纹 = 文件 + 校验号 + 字面量 + 计数,**不含行号**);生成 `scripts/id_known_backlog.json`(340 条覆盖 710 处存量);钩子 `entry` 加 `--strict`。验收三例:新字面量拦、同号计数增长拦、干净态放行,全通过。新增 §8.4 说明机制与「为什么不照清零再升 strict 的原节奏」 |
|
||||
| 2026-10-21 | **追溯脚本同口径对齐** | `check_test_traceability.py` 差异定义改为 DOC-ONLY / CODE-ONLY / IN-CODE 三档(真差异 45 = 38 + 7;弱保证 238 单列示数);顺带修 `TC_RE` 模块码上界 `{0,4}`→`{0,8}`——**同一个坑第二次踩**(代码侧一度从 556 缩到 217),已写进 §8.1 |
|
||||
| 2026-10-21 | **B 层口径落地(批 3)** | 主机侧单测 118 号实测在代码目录外零消费者 → 建 9 族 `TC-HOST-*` 认代码为属主登记处(不逐号补文档);新增 `subitem_ok`(小写子项后缀母号在册即算已定义)、`snapshot_only`(§4.3 冻结快照族不参与定义位优先)、`allow_orphans` 旗标与 `excluded_paths` 补两项;补 `docs/任务规划/README.md` 为 `N`/`S-LDG`/`T-LDG` 属主(**我的配置漏项,曾误判 74 处真条目悬空**);`T-2`/`T-3`/`T-4`/`T-6` 入别名表标 `void`。错误级 1318 → 711(其中 504 处属口径修正、74 处属修 bug,**真正变好 0 处**)。新增 §8.1 口径修正记录表 |
|
||||
| 2026-10-20 | **编号改名开禁(用户授权)+ 批 1 落地** | 新增 `scripts/rename_ids.py`(§7.3 规划脚本:映射表驱动、显式 scope、干跑/落盘两态、自动写 `id_aliases.json` 的 scoped 条目、跳过 `[示例]`/`[计划]` 行与变更记录表、按原字节读写保 BOM 与行尾)。**批 1**:代码规范条款 `S1~S19` → `CODE-RULE-nn`(78 处/2 文件)、UI 像素回归状态 `S0~S7` → `MENU-STATE-nn`(61 处/3 文件);`check_ids.py` 支持 **scoped 别名** 并登记两族(66 族);可判定比例 82.3% → **82.7%**、裸形判错 71 → 50、错误级 1312 → 1291。§4.1 补两行、新增 §8.3 迁移批次记录 |
|
||||
|
||||
+98
-6
@@ -612,11 +612,56 @@ def parse_only(s):
|
||||
return {int(x) for x in re.split(r"[,\s]+", s) if x.strip().isdigit()}
|
||||
|
||||
|
||||
BACKLOG_FILE = REPO_ROOT / "scripts" / "id_known_backlog.json"
|
||||
|
||||
|
||||
def err_groups(ck):
|
||||
"""当前错误级问题按 `(文件, 校验号, 字面量)` 归并计数——**债务台账的指纹**。
|
||||
|
||||
指纹故意**不含行号**:行号每编辑一次就漂移,拿它当指纹会让台账天天"新增",
|
||||
三天后 strict 输出全是假警报,没人敢再看——台账失效比没有台账更糟。
|
||||
用**计数**而不是集合:同一文件里同一个号第 N+1 次出现必须能抓出来,
|
||||
复制粘贴式扩散正是编号烂掉的常见路径(§1.2 的跨文档同号不同义就这么来的)。
|
||||
"""
|
||||
g = defaultdict(int)
|
||||
for f in ck.findings:
|
||||
if f.severity == "error":
|
||||
g[(f.rel, f.code, f.literal)] += 1
|
||||
return g
|
||||
|
||||
|
||||
def load_backlog():
|
||||
"""台账 → {(file, code, literal): count};文件不存在返回 None。"""
|
||||
if not BACKLOG_FILE.is_file():
|
||||
return None
|
||||
doc = json.loads(BACKLOG_FILE.read_text(encoding="utf-8"))
|
||||
return {(e["file"], int(e["code"]), e["literal"]): int(e["count"])
|
||||
for e in doc.get("entries", [])}
|
||||
|
||||
|
||||
def backlog_doc(entries, errs, ratio):
|
||||
return {
|
||||
"schema": 1,
|
||||
"note": ("编号债务台账(docs/编号规范.md §8.4):--strict 只对**台账之外**的新错误级问题拦提交。"
|
||||
"台账只许减不许增——还清的用 --prune-backlog 收掉;确需新增一条必须写 reason 字段"
|
||||
"说明这笔债为什么该存在,默认禁止顺手加行(否则一周后台账就变成第二个 backlog)。"
|
||||
"指纹 = 文件 + 校验号 + 字面量,不含行号(行号会漂,用它台账天天假新增)。"),
|
||||
"generated_by": "scripts/check_ids.py --write-backlog",
|
||||
"total_error_findings": errs,
|
||||
"decidable_ratio_at_generation": round(ratio, 2),
|
||||
"entries": entries,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(
|
||||
description="编号门禁:docs/编号规范.md §8 的 8 项校验(默认 warn-only)")
|
||||
ap.add_argument("--strict", action="store_true",
|
||||
help="校验 1~6 的错误改为拦提交(默认 warn-only,不拦)")
|
||||
help="增量拦截:台账(scripts/id_known_backlog.json)之外的新错误级问题 → 拦提交")
|
||||
ap.add_argument("--write-backlog", action="store_true",
|
||||
help="把当前全部错误级问题写成债务台账(关闸前的初始化动作)")
|
||||
ap.add_argument("--prune-backlog", action="store_true",
|
||||
help="从台账里收掉已还清的条目(只减不增),并回写")
|
||||
ap.add_argument("--verbose", action="store_true", help="每条附带修法")
|
||||
ap.add_argument("--top", type=int, default=12, help="每类校验打印的条数(默认 12)")
|
||||
ap.add_argument("--only", default="", help="只跑指定校验,如 --only 1,3,5")
|
||||
@@ -635,6 +680,39 @@ def main():
|
||||
return rc
|
||||
ratio, errs = ck.report(args.top, parse_only(args.only))
|
||||
|
||||
groups = err_groups(ck)
|
||||
err_total = sum(groups.values())
|
||||
if args.only and (args.strict or args.write_backlog or args.prune_backlog):
|
||||
print("[ERR] --only 是局部排查,不能与 --strict / 台账写入同用(门禁结论必须全量)",
|
||||
file=sys.stderr)
|
||||
return 2
|
||||
if args.write_backlog:
|
||||
entries = [{"file": k[0], "code": k[1], "literal": k[2], "count": v}
|
||||
for k, v in sorted(groups.items())]
|
||||
BACKLOG_FILE.write_text(
|
||||
json.dumps(backlog_doc(entries, err_total, ratio), ensure_ascii=False, indent=2) + "\n",
|
||||
encoding="utf-8", newline="\n")
|
||||
print("[OK] 债务台账已写 %s:%d 条指纹,覆盖 %d 处错误级问题"
|
||||
% (BACKLOG_FILE.name, len(entries), err_total))
|
||||
return 0
|
||||
if args.prune_backlog:
|
||||
led = load_backlog()
|
||||
if led is None:
|
||||
print("[ERR] 还没有台账,无从清理", file=sys.stderr)
|
||||
return 2
|
||||
paid = [k for k in led if groups.get(k, 0) == 0]
|
||||
grew = [(k, led[k], groups.get(k, 0)) for k in led if groups.get(k, 0) > led[k]]
|
||||
kept = [{"file": k[0], "code": k[1], "literal": k[2], "count": groups[k]}
|
||||
for k in sorted(led) if groups.get(k, 0) > 0]
|
||||
BACKLOG_FILE.write_text(
|
||||
json.dumps(backlog_doc(kept, err_total, ratio), ensure_ascii=False, indent=2) + "\n",
|
||||
encoding="utf-8", newline="\n")
|
||||
print("[OK] 台账已还清 %d 条,剩 %d 条(只减不增)" % (len(paid), len(kept)))
|
||||
for k, was, now in grew[:10]:
|
||||
print("[WARN] 台账内条目**变多了**(这属于新增债务,strict 会拦):%s 校验%d %s %d→%d"
|
||||
% (k[0], k[1], k[2], was, now))
|
||||
return 0
|
||||
|
||||
if args.update_baseline:
|
||||
base = reg.get("decidable_ratio_baseline")
|
||||
if base is not None and ratio + RATIO_TOL < base:
|
||||
@@ -672,12 +750,26 @@ def main():
|
||||
print("\n[FAIL] 校验 8:可判定比例跌破基线 %.2f%% < %.2f%%(只许涨不许跌,容差 %.1fpp)"
|
||||
% (ratio, base, RATIO_TOL))
|
||||
return 1
|
||||
if errs:
|
||||
if err_total:
|
||||
if args.strict:
|
||||
print("\n[FAIL] 编号门禁:%d 处错误级问题(--strict 拦提交)" % errs)
|
||||
return 1
|
||||
print("\n[WARN] 编号 backlog:%d 处错误级问题,warn-only 不拦提交"
|
||||
"(§8 上线节奏:清账后加 --strict)" % errs)
|
||||
led = load_backlog()
|
||||
if led is None:
|
||||
print("\n[FAIL] --strict 但缺 scripts/id_known_backlog.json —— 拒绝退化成"
|
||||
"「一次性拦死全部存量」(那样只会逼人 --no-verify)。"
|
||||
"先跑 --write-backlog 生成台账(§8.4)", file=sys.stderr)
|
||||
return 2
|
||||
new = {k: c - led.get(k, 0) for k, c in groups.items() if c > led.get(k, 0)}
|
||||
if new:
|
||||
print("\n[FAIL] 编号门禁·增量拦截:%d 类**台账之外**的错误级问题(新引入的债,§8.4)"
|
||||
% len(new))
|
||||
for (rel, code, lit), n in sorted(new.items(), key=lambda kv: -kv[1])[:args.top]:
|
||||
print(" +%d [校验%d] %s %s" % (n, code, rel, lit))
|
||||
print(" → 改引用/补登记处;确属该欠的债要在台账写 reason(默认禁止顺手加)")
|
||||
return 1
|
||||
print("\n[OK] 增量拦截通过:无台账外新账(存量 %d 处按台账豁免,§8.4)" % err_total)
|
||||
else:
|
||||
print("\n[WARN] 编号 backlog:%d 处错误级问题,warn-only 不拦提交"
|
||||
"(关闸方式见 §8.4:--strict + 债务台账)" % err_total)
|
||||
else:
|
||||
print("\n[OK] 校验 1~6 无错误")
|
||||
return 0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -57,7 +57,8 @@
|
||||
"scripts/check_ids.py",
|
||||
".dsh/skills/*/scripts/state/",
|
||||
".dsh/n31_neg_inject_gen217.log",
|
||||
".dsh/n31_neg_inject_gen221_form5.log"
|
||||
".dsh/n31_neg_inject_gen221_form5.log",
|
||||
"scripts/id_known_backlog.json"
|
||||
],
|
||||
"excluded_suffixes": [
|
||||
".svg",
|
||||
|
||||
Reference in New Issue
Block a user