From 51d89cf9d30ae2d4e606506f91373d1f66c1936c Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Thu, 29 Oct 2026 20:22:47 +0800 Subject: [PATCH] =?UTF-8?q?gate:=20=E6=8C=89=E7=94=A8=E6=88=B7=E8=A3=81?= =?UTF-8?q?=E5=AE=9A=E6=95=B4=E4=BD=93=E9=80=80=E5=BD=B9=E7=BC=96=E5=8F=B7?= =?UTF-8?q?=E9=97=A8=E7=A6=81=20id-check-new=EF=BC=88=E9=92=A9=E5=AD=90=20?= =?UTF-8?q?52=20=E2=86=92=2051=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 配置:摘掉该钩子,原位置留一条退役注记(不复述数钩子数的字面量)。 YAML 解析口径实测:声明 51 / 带 manual 3 / 提交期实跑 48。 脚本:git mv 进 scripts/archive/id_gate/check_ids_new.py,与已退役的 check_ids.py 同档;docstring 改退役口径,REPO_ROOT 因归档位置深两级 改取 parents[3],失败提示与自述路径同步改写。从归档位置实测: --self-test 5 正例拦下 / 29 反例放行 rc=0;--worktree 与暂存区模式 rc=0。 文档(七份):AGENTS.md 六处——总数、加钩流水(顺带补上 2026-10-29 漏记的 skill-size 一笔)、枚举项删除、本行相加数、提交期实跑、门禁索引 与主题表两行;门禁说明 README 八处——声明数、实跑数、计数流水、grep 陷阱的举例数、§2 标题、姿态表「只查新增」行、两行索引状态;编号规范 七处——引导块改「本文即唯一事实源」、族总表一处、§8 标题与正文、 §8.5 补第④步、④ 之后无机械牙那段、速查;门禁说明 id-check-new.md 整篇重写为退役留档(查什么 / 落地前的噪声回放 / 退役五条理由 / 手工 跑法 / 此后靠什么 / 认下丢了什么);门禁说明 id-check.md 与归档目录 README、check_ids.py 里「现行门禁 = id-check-new」的指针同步改写。 技能(三份):id-family-semantic-migration 一行、stale-doc-count-sweep 的 pitfalls 与 steps 各一行改手工跑法(steps 第 5 条那笔历史计数例不动)。 此后编号形态没有机器面:判据只剩 docs/编号规范.md §1 三句自问、§4.1 族总表与人工评审;2026-10-14 那类"销项删行后号被重新取走"不再有提交期 警报——这条代价已写进留档,别当成"检查没了随便写"。 纯文档与门禁配置,未跑 @build。全程未 push。 --- .../id-family-semantic-migration/SKILL.md | 2 +- .../reference/pitfalls.md | 2 +- .../stale-doc-count-sweep/reference/steps.md | 2 +- .pre-commit-config.yaml | 20 +-- AGENTS.md | 6 +- docs/编号规范.md | 34 +++-- docs/门禁说明/README.md | 20 +-- docs/门禁说明/id-check-new.md | 138 ++++++++---------- docs/门禁说明/id-check.md | 4 +- scripts/archive/id_gate/README.md | 14 +- scripts/archive/id_gate/check_ids.py | 8 +- .../{ => archive/id_gate}/check_ids_new.py | 27 ++-- scripts/archive/id_gate/编号治理历史.md | 2 +- 13 files changed, 134 insertions(+), 145 deletions(-) rename scripts/{ => archive/id_gate}/check_ids_new.py (87%) diff --git a/.dsh/skills/id-family-semantic-migration/SKILL.md b/.dsh/skills/id-family-semantic-migration/SKILL.md index c23bee09..3b04a4ae 100644 --- a/.dsh/skills/id-family-semantic-migration/SKILL.md +++ b/.dsh/skills/id-family-semantic-migration/SKILL.md @@ -12,7 +12,7 @@ version: 1.1.0 | 族形态 | 计数口径来源 | 改名手段 | `scripts/archive/id_gate/id_aliases.json` | |---|---|---|---| | 字母+数字,且在 `scripts/archive/id_gate/check_ids.py` 语料内(`id_registry.json` 有族、族 pattern 能匹配它) | 门禁自身计数(`ck.refs` / `ck.stats` / 报告行) | `scripts/rename_ids.py`(映射表 + 显式 scope + 默认干跑) | **要登记**:死号 `void`、转短语 `retired-to-phrase` | -| 中文前缀(「卡」+ 数字)、纯散文里的号、圈号 ①②③ | **自建带标签正则扫描器**(门禁看不见它,2026-10-28 退役前的 id-check 全库报告与本族无关;现行 id-check-new 只查新增行) | 逐处替换 + 断言命中数(`rename_ids.py` 靠族 pattern 驱动,这里用不上) | **刻意不登记**:登记了机器也看不见,只多一张没人核的表;停发只靠规范 + 评审 | +| 中文前缀(「卡」+ 数字)、纯散文里的号、圈号 ①②③ | **自建带标签正则扫描器**(门禁看不见它,2026-10-28 退役前的 id-check 全库报告与本族无关;两道门禁现都已退役(2026-10-28 / 2026-10-29),要普查形态就手工跑归档脚本 scripts/archive/id_gate/check_ids_new.py --range) | 逐处替换 + 断言命中数(`rename_ids.py` 靠族 pattern 驱动,这里用不上) | **刻意不登记**:登记了机器也看不见,只多一张没人核的表;停发只靠规范 + 评审 | 怎么判(三条,任一为否即无识别面):① `grep -nE '"name"|"pattern"' scripts/archive/id_gate/id_registry.json`,没有任何族 pattern 能匹配该形态;② `./.venv/Scripts/python.exe scripts/archive/id_gate/check_ids.py --top 0` 的任何校验里找不到它;③ registry 的 `blind_spots` 已明写不判(圈号与正常列举无法机械区分、裸形同字母多义只在属主登记处判)。实测:「卡」+ 数字**没有族**(中文形态只有 `malformed` 里 `陷阱 ?[0-9]` 那条禁令,管的是陷阱编号不是卡号),该族真实站点 288 处 / 56 文件,而门禁对它贡献 0。 diff --git a/.dsh/skills/stale-doc-count-sweep/reference/pitfalls.md b/.dsh/skills/stale-doc-count-sweep/reference/pitfalls.md index e356a8dc..7459efa4 100644 --- a/.dsh/skills/stale-doc-count-sweep/reference/pitfalls.md +++ b/.dsh/skills/stale-doc-count-sweep/reference/pitfalls.md @@ -20,4 +20,4 @@ - **误报跟着改**:「< 40KB」是绘制缓冲红线,与页数无关。 - **带日期戳的测量臆改新数**:「2026-10-26 实跑 …覆盖 40 页」改成 47 就是把历史测量冒充现值;只加「当时」。 - **用截断的 grep 输出判定**:`cut -c` 截掉的后半句常含日期戳/口径,据此分类必错。 -- **新写文本撞编号门禁**:新增的「单字母+数字」裸形(如 `SD2506`、`CP56Time2a`)会被 `id-check-new`(只查 `git diff` 新增行、零语料)拦下;旧的八项全库校验 `id-check` 已于 2026-10-28 退役进 `scripts/archive/id_gate/`。撞到就把自己这批文本逐处归因或改形态描述,别去放宽白名单。 +- **新写文本别再造编号**:两道编号门禁都已退役(全库八项校验 2026-10-28、只查新增行 2026-10-29,脚本与白名单在 `scripts/archive/id_gate/`),**撞号不再有机器报警**,只剩规范与评审——所以这批文本的形态自查要自己做(`docs/编号规范.md` §1 三句;要机器帮忙就手工跑 `scripts/archive/id_gate/check_ids_new.py --worktree`)。 diff --git a/.dsh/skills/stale-doc-count-sweep/reference/steps.md b/.dsh/skills/stale-doc-count-sweep/reference/steps.md index 26826557..9f29aad5 100644 --- a/.dsh/skills/stale-doc-count-sweep/reference/steps.md +++ b/.dsh/skills/stale-doc-count-sweep/reference/steps.md @@ -81,7 +81,7 @@ ```bash & '.venv\Scripts\python.exe' scripts/check_doc_links.py --all --sections-strict # 期望「文档路径检查通过(N 个文档)」 - & '.venv\Scripts\python.exe' scripts/check_ids_new.py --self-test # 新增行编号门禁(旧 check_ids.py 已退役进 scripts/archive/id_gate/) + & '\.venv\Scripts\python.exe' scripts/archive/id_gate/check_ids_new.py --range A..B # 编号形态普查(两道门禁 2026-10-28 / 2026-10-29 都已退役,不再是提交钩子) & '.venv\Scripts\python.exe' scripts/ci_local.py # 或 pre-commit run --files <被改文件> ``` diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0bad2054..c7f863bc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -680,20 +680,12 @@ repos: # 61 笔被编号体系牵连),脚本与语料整体移入 `scripts/archive/id_gate/` # (保留可复现性,**不再进提交门禁**)。退役路线与判据替换见规范 §8.5。 - # 14) 编号门禁(2026-10-28 起是**唯一**的编号门禁):只查**新增行**,零语料 - # 背景:语义标识已是默认形态,全库语料审计的成本高过收益(见上条历史)。 - # 判据:看 git diff 的新增行里有没有**未登记形态**的「字母+数字」标识 - # (自造前缀直接 FAIL;已停发族只 WARN);白名单在脚本里,按实测普查枚举、几乎不增长。 - # 自检:`python scripts/check_ids_new.py --self-test`;范围自查用 `--range A..B`。 - # ⚠ 计数口径(2026-10-28,一增一减写成同日的两个阶段,净零):本条落地使 YAML 解析条目 - # 51 → 52,同日摘掉退役的旧语料审计钩子后 52 → **51**。口径与自查命令、「声明 / 文档 / - # 实跑」三数同源核对 → docs/门禁说明/README.md §2 首条(本文件注释与 AGENTS 必须同批改)。 - - id: id-check-new - name: 编号门禁·新增行(零语料,拦截新造编号) - entry: python scripts/check_ids_new.py - language: system - files: \.(md|c|h|py|ya?ml|txt)$|^\.pre-commit-config\.yaml$ - pass_filenames: false + # 14) 编号门禁(2026-10-28 上线只查新增行那一道;2026-10-29 用户裁定**整体退役**,钩子已摘) + # 退役后编号形态没有机器面:判据回到 docs/编号规范.md §1 三句自问 + §4.1 族总表 + 评审。 + # 脚本移入 scripts/archive/id_gate/check_ids_new.py(手工可跑,--self-test 保留),留档说明 + # → docs/门禁说明/id-check-new.md;两步路线 → docs/编号规范.md §8.5。 + # ⚠ 计数口径:本条摘除使 YAML 解析条目 52 → **51**,须与 AGENTS.md 的「共 N 个钩子」、 + # docs/门禁说明/README.md §2 标题三数同源同批改(自查命令见该条;别在注释里写数钩子的字面量)。 # 14) 分层方向门禁(2026-10-22 加,结构债的"防扩大"那一半) # 背景:AGENTS.md 与 项目架构总览.md 早就写着"六层单向依赖",但**从来没有机械检查** diff --git a/AGENTS.md b/AGENTS.md index cd4a3859..7594e8aa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -93,7 +93,7 @@ ## 提交门禁(pre-commit) -- 任一失败即拦截,共 **52 个钩子**(**口径 = YAML 解析后的 hook 条目数**:自查命令与「声明 / 文档 / 实跑」三数同源核对见 `docs/门禁说明/README.md` §2 首条——⚠ 直接 grep 配置里的声明行会多算一条**注释掉的**候选钩子(比口径多 1),不是口径;**配置注释里也别复述那个 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` 一条;2026-10-28 加 `id-check-new` 一条并同批退役 `id-check`(口径 52 → 51:编号门禁换牙——新的只查新增行、零语料,旧的八项全库校验连语料一起移入 `scripts/archive/id_gate/`,路线见 `docs/编号规范.md` §8.5);**每种门禁一篇详解(查什么 / 拦下过什么真事 / 限制与盲区 / 基线口径)→ `docs/门禁说明/README.md` 索引**;通用机制与整体口径 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers` + `id-check-new`(**编号门禁**:只查 `git diff` 新增行里有没有未登记形态的「字母+数字」标识,零语料、零维护;白名单是前缀级两张表,见 `docs/门禁说明/id-check-new.md`。旧的八项全库校验 `id-check` 已于 2026-10-28 退役,脚本与两份语料移入 `scripts/archive/id_gate/`,只在手工复查存量时才跑;退役路线见 `docs/编号规范.md` §8.5)+ `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + `bom-guard` / `setview-check` / `uinav-selftest`(2026-10-25 道E 那三条:前半句的加钩流水里有它们、逐项枚举里漏了,补上后本行各项相加才等于 52)+ 主机侧单测 **22 根专属钩子**(`-unit-test` 后缀 = 有独立 `files:` 触发面、需要秒级归因的那个子集;2026-10-25 增补 adc-cal / prot-dim / vol-idle-sync / ui-data / meas / run-par 六根)——**这是口径不是缺口**:`test/host/` 实测 44 套带 `run_unit_test.py`,其余 **22 套**(含 `test/host/ui_sink` 与录波三套)没有专属钩子,但每次 CI / `scripts/ci_local.py` 都被 `test-coverage` 总闸全量真跑并守基线回退,**失败照样拦**,只是归因落在总闸输出上;**没有专属钩子 ≠ 没被跑**,22 套台账与补钩子的判据 → `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`(**覆盖率总闸**:跑全部 44 套并守基线回退;缺 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 时才暴露;本仓诱因就是「在注释里写作用域/通配路径」,改法是写全目录或用尖括号 ;接线当日实扫 403 个 .c/.h,新发 0、存量 2 处(`test/host/common/` 两份假件头)钉只减不增基线 → `docs/门禁说明/nested-comment.md`)+ `skill-size`(**SKILL.md 不超插件写侧上限 65536 字节**:dsh-mnemon 只在写侧校验、加载侧不查,超限技能照常可读却每次「生成草案」被拒、永久卡在「生成中」;另查 `reference/` 指针悬空与 BOM → `docs/门禁说明/skill-size.md`)+ `mem-budget`(RAM 92% 预算门禁,登记簿条目「缩堆迁 CCM 后半(暂缓)」)+ `font-charset`(UI 字符集差集检查,防缺字白框)+ `ui-golden`(UI 像素回归,菜单 8 状态 + 内容页 66 张黄金参考)+ `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 条**))。**提交期实跑 49 根**(2026-10-28 用户裁定):`cppcheck` / `test-cppcheck` / `test-coverage` 三根带 `stages: [manual]`——实测合计 ~165 s = 一次带代码提交耗时的三分之二,提交期只跑快的那些;这三根由**远端 CI** 强制(`.gitea/workflows/ci.yml` 的「手动阶段门禁」步,逐根 `--hook-stage manual`)与 `scripts/ci_local.py` 的 manual 段,本地手工复跑 `python -m pre_commit run --all-files --hook-stage manual `(一次只能一个 id) +- 任一失败即拦截,共 **51 个钩子**(**口径 = YAML 解析后的 hook 条目数**:自查命令与「声明 / 文档 / 实跑」三数同源核对见 `docs/门禁说明/README.md` §2 首条——⚠ 直接 grep 配置里的声明行会多算一条**注释掉的**候选钩子(比口径多 1),不是口径;**配置注释里也别复述那个 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` 一条;2026-10-28 加 `id-check-new` 一条并同批退役 `id-check`(口径 52 → 51:编号门禁换牙——新的只查新增行、零语料,旧的八项全库校验连语料一起移入 `scripts/archive/id_gate/`,路线见 `docs/编号规范.md` §8.5);2026-10-29 加 `skill-size` 一条(51 → 52),同日按用户裁定**退役 `id-check-new`**(52 → **51**:只查新增行的编号门禁整体退场,脚本与白名单一起移入 `scripts/archive/id_gate/`,编号形态此后无机器面,留档 `docs/门禁说明/id-check-new.md`);**每种门禁一篇详解(查什么 / 拦下过什么真事 / 限制与盲区 / 基线口径)→ `docs/门禁说明/README.md` 索引**;通用机制与整体口径 → `docs/代码规范/pre-commit使用说明.md`):通用 5 + `gitlint` + `cppcheck` / `test-cppcheck` + `no-mojibake` + `coding-standard` + 文档三件套 `doc-links` / `task-table` / `mem-numbers`+ `lv-conf-sync`(两份 `lv_conf.h` 特性子集一致)+ `cubemx-survival` + `bom-guard` / `setview-check` / `uinav-selftest`(2026-10-25 道E 那三条:前半句的加钩流水里有它们、逐项枚举里漏了,补上后本行各项相加才等于 51)+ 主机侧单测 **22 根专属钩子**(`-unit-test` 后缀 = 有独立 `files:` 触发面、需要秒级归因的那个子集;2026-10-25 增补 adc-cal / prot-dim / vol-idle-sync / ui-data / meas / run-par 六根)——**这是口径不是缺口**:`test/host/` 实测 44 套带 `run_unit_test.py`,其余 **22 套**(含 `test/host/ui_sink` 与录波三套)没有专属钩子,但每次 CI / `scripts/ci_local.py` 都被 `test-coverage` 总闸全量真跑并守基线回退,**失败照样拦**,只是归因落在总闸输出上;**没有专属钩子 ≠ 没被跑**,22 套台账与补钩子的判据 → `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`(**覆盖率总闸**:跑全部 44 套并守基线回退;缺 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 时才暴露;本仓诱因就是「在注释里写作用域/通配路径」,改法是写全目录或用尖括号 ;接线当日实扫 403 个 .c/.h,新发 0、存量 2 处(`test/host/common/` 两份假件头)钉只减不增基线 → `docs/门禁说明/nested-comment.md`)+ `skill-size`(**SKILL.md 不超插件写侧上限 65536 字节**:dsh-mnemon 只在写侧校验、加载侧不查,超限技能照常可读却每次「生成草案」被拒、永久卡在「生成中」;另查 `reference/` 指针悬空与 BOM → `docs/门禁说明/skill-size.md`)+ `mem-budget`(RAM 92% 预算门禁,登记簿条目「缩堆迁 CCM 后半(暂缓)」)+ `font-charset`(UI 字符集差集检查,防缺字白框)+ `ui-golden`(UI 像素回归,菜单 8 状态 + 内容页 66 张黄金参考)+ `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 条**))。**提交期实跑 48 根**(2026-10-28 用户裁定):`cppcheck` / `test-cppcheck` / `test-coverage` 三根带 `stages: [manual]`——实测合计 ~165 s = 一次带代码提交耗时的三分之二,提交期只跑快的那些;这三根由**远端 CI** 强制(`.gitea/workflows/ci.yml` 的「手动阶段门禁」步,逐根 `--hook-stage manual`)与 `scripts/ci_local.py` 的 manual 段,本地手工复跑 `python -m pre_commit run --all-files --hook-stage manual `(一次只能一个 id) - **范围 = 项目代码**:第三方(`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/` @@ -176,8 +176,8 @@ | ADC 采样节拍 / 通道映射 / V0.1 硬件缺陷 | `docs/子系统设计/ADC采样节拍设计说明.md`、`docs/硬件平台/ADC通道映射说明.md` | | 存储栈(FatFs / dhara / lftpd / 两条 FatFs 陷阱) | `docs/架构设计/STM32F4-Base存储架构说明.md` | | RAM / 栈预算 / 容量台账 | `docs/内存管理/RAM使用分析与优化方案.md`、`内存内容分配策略.md` | -| **每个提交门禁一篇详解**(查什么 / 拦下过什么真事 / 限制与盲区 / 基线口径) | `docs/门禁说明/README.md`(52 个钩子 → 29 篇索引,其中 1 篇是退役留档 + 1 指针) | -| **要不要给某个东西发编号**(默认:不发,写语义短语)/ 允许用号的 7 个族(`TC-*` 已停发——「停发」不等于「暂缓」,也不等于「可以清号」)/ 编号门禁现状(`id-check-new`:只查新增行;旧的八项校验已退役) | `docs/编号规范.md`(§1 先问三句、§4.1 族总表〔穷举〕与『已停发』栏、§8 门禁现状与退役路线) | +| **每个提交门禁一篇详解**(查什么 / 拦下过什么真事 / 限制与盲区 / 基线口径) | `docs/门禁说明/README.md`(51 个钩子 → 29 篇索引,其中 2 篇是退役留档 + 1 指针) | +| **要不要给某个东西发编号**(默认:不发,写语义短语)/ 允许用号的 7 个族(`TC-*` 已停发——「停发」不等于「暂缓」,也不等于「可以清号」)/ 编号门禁现状(**两道都已退役**:全库八项校验 2026-10-28、只查新增行 2026-10-29;此后无机器面,只靠 §1 三句 + 评审) | `docs/编号规范.md`(§1 先问三句、§4.1 族总表〔穷举〕与『已停发』栏、§8 门禁现状与退役路线) | | 提交门禁通用机制(阶段 / stash 陷阱 / 触发面 / 增量拦截三段式) | `docs/代码规范/pre-commit使用说明.md` §2 | | 代码规范 V1.0 / cppcheck 口径 | `docs/代码规范/嵌入式C语言代码规范_V1.0.md`、`cppcheck使用说明.md` | | 自动化测试 / 实机测试 / 板级套件 | `docs/测试说明/自动化测试流程.md`、`实机测试实施指南.md`、`board-test-suite` skill | diff --git a/docs/编号规范.md b/docs/编号规范.md index 8b91180d..cd10264a 100644 --- a/docs/编号规范.md +++ b/docs/编号规范.md @@ -9,9 +9,10 @@ > 2026-10-26 起两批清理把编号字面量从 **10,956 压到 8,230 处**,2026-10-27 复测为 **7,828 处**(`编号治理历史.md` §8.1 有口径说明); > 而清掉的号里绝大多数从来没被任何脚本读过一次。沿革与教训留在 `编号治理历史.md` §8.3 与 git log,正文不复述。 > -> **机器面才是事实源**:现行门禁 `scripts/check_ids_new.py` 的两张**前缀级白名单**(`KNOWN_DASH` / `KNOWN_BARE`) -> 是 §4.1 的机器投影;本文与白名单冲突时以白名单为准,回来改本文(详解 `docs/门禁说明/id-check-new.md`)。 -> 旧的族注册表 / 别名表 / 八项校验脚本已随全库审计退役进 `scripts/archive/id_gate/`,只在手工复查存量时用。 +> **本文就是唯一事实源**:两道编号门禁已分别于 2026-10-28(全库八项校验)与 2026-10-29(只查新增行) +> 退役,脚本、两张前缀白名单与族语料都在 `scripts/archive/id_gate/`,**不再进提交门禁**。 +> 形态判据只剩本文 §1 的三句自问 + §4.1 族总表 + 人工评审;留档 `docs/门禁说明/id-check-new.md` +> 与 `docs/门禁说明/id-check.md`,路线见 §8.5。归档脚本随时可手工普查形态(`--range A..B`)。 --- @@ -130,7 +131,7 @@ | 登记簿 `N-x` / `S-x` / `T-x`、专项 `A-x`、已删报告的 UI 簇 `U1~U5`(2026-10-26 方案 B) | 语义短语——**登记簿表首格本身就是短语**,如「双转换器无共同采样触发」「CI 远端闭环未验证」 | `scripts/archive/id_gate/id_aliases.json` 标 `retired-to-phrase` | | 网络设计条目 `F-NET/F-DRV/F-MS-`(12 个,2026-10-27 批次一) | 「`编号治理历史.md` §7 + 条目名」短语,如 `(`编号治理历史.md` §7「全局读即清搁浅事件」)`;条目名的权威清单 = `docs/网络/网络自愈架构设计.md` `编号治理历史.md` §7「条目名」列;那个 DRV 段孤儿号按本节末句**删号留事实**、未补定义 | `scripts/archive/id_gate/id_aliases.json` 标 `retired-to-phrase`(13 条)+属主文档 `编号治理历史.md` §7 编号列仅作历史对照 | | 「数据可信」任务卡号(中文前缀「卡」+ 数字,形态见 `编号治理历史.md` §9.3;2026-10-27 批次五) | §5 表的**标识列直接写任务名**(「端子/子板变比确认」「两点标定与精度验收」),代码注释与文档写语义短语(「标定折算落地」「未标定闭锁」「遥测快照发布」…);**逐号换算表见本文 `编号治理历史.md` §9.3** | ⚠ **机器面空白**:中文前缀不进 `scripts/archive/id_gate/check_ids.py` 语料(族 pattern 全是拉丁形态)→ 门禁咬不到,今天只有本表 + `编号治理历史.md` §9.3 + 评审三条兜;`id_aliases.json` 刻意不登记(登记了机器也看不见,只多一张没人核的表) | -| 测试验证层级号(`L0`、`L0.5`、`L1~L3` 这一族,**注意与 UI 设计令牌层 L0、硬件位号 L1~L3、采集链旧层名等同形族无关**;2026-10-28 批次六) | 文档与 CI 步骤名写语义名(静态门禁 / 主机侧纯逻辑单测 / 板端测试套件 / 主机侧回归 / 人工目检);ASCII 短码(static / preflight / commitmsg / size / host-unit / coverage)**只进**日志标签、命令行旗标、CI job id、日志文件名 | ⚠ **同形族警示**:逐号换算表与判族表见 `scripts/archive/id_gate/编号治理历史.md` §10 与 §10.1(撞族六个,动手前先判族);本族虽是拉丁形态但**门禁咬不到**——`id-check` 同日退役、现行 `id-check-new` 只看新增行里的「字母+数字」形态,停发只靠本表 + 归档换算表 + 评审 | +| 测试验证层级号(`L0`、`L0.5`、`L1~L3` 这一族,**注意与 UI 设计令牌层 L0、硬件位号 L1~L3、采集链旧层名等同形族无关**;2026-10-28 批次六) | 文档与 CI 步骤名写语义名(静态门禁 / 主机侧纯逻辑单测 / 板端测试套件 / 主机侧回归 / 人工目检);ASCII 短码(static / preflight / commitmsg / size / host-unit / coverage)**只进**日志标签、命令行旗标、CI job id、日志文件名 | ⚠ **同形族警示**:逐号换算表与判族表见 `scripts/archive/id_gate/编号治理历史.md` §10 与 §10.1(撞族六个,动手前先判族);本族虽是拉丁形态但**门禁咬不到**——两道编号门禁已退役(全库校验 2026-10-28、新增行检查 2026-10-29),停发只靠本表 + 归档换算表 + 评审 | | `E-xx` 审计发现、`P0-x`~`P3-x` 审计条目、报告六族 `D/R/F/N/U/S`、复审残号 `S1~S14`/`A-x`/`B1~B10`/`T-x`、模拟器差距 `H-x`/`L-x`、`TM-*` 阶段号、`DP-*`、`gen`/`round`/会话临时号 | 写条目本身("原子快照取数"、"队头阻塞"、"台架日志代次 288"、"第 3 轮台架") | 别名表标 `void`;**部分死号故意不进别名表**,好让门禁继续咬残留引用 | | 规范曾规划却从未启用的前缀族(`DEF`/`WI`/`DR`/`OQ`/`RSK`/`GAP`/`SC`/`GEN`/`MS`/`UL`/`LAT`/`CS` 等) | 同上,写事实 | 无定义,本就不该存在 | @@ -175,10 +176,11 @@ --- -## 8. 门禁(2026-10-28 起:只有一道) +## 8. 门禁(2026-10-29 起:一道也没有) -**现行门禁 = `id-check-new`**(钩子同名):只查 `git diff` 的**新增行**里有没有未登记形态的 -「字母+数字」标识;零语料、零维护。判据、白名单与盲区 → `docs/门禁说明/id-check-new.md`。 +**现行没有编号门禁**:2026-10-29 用户裁定把最后那道只查新增行的 `id-check-new` 也摘了(钩子口径 +52 → 51,脚本与白名单移入 `scripts/archive/id_gate/check_ids_new.py`,留档 `docs/门禁说明/id-check-new.md`, +理由与手工跑法都在那篇)。判据回到本文 §1 三句自问、§4.1 族总表与人工评审。 本节以下(`编号治理历史.md` §8.1~`编号治理历史.md` §8.4)是**已退役**的全库语料审计(`id-check`,八项校验)的留档: 脚本与两份语料已整体移入 `scripts/archive/id_gate/`,不再进提交门禁, @@ -186,18 +188,21 @@ 八项校验一句话版(历史口径):① 未登记前缀 ② 形态不合规 ③ 悬空引用 ④ 重复定义 ⑤ 冻结族越游标 ⑥ 编号未紧邻文档名 ⑦ 孤儿条目(告警)⑧ 可判定比例 + 两根护栏。 -### 8.5 门禁退役路线(2026-10-28 裁定) +### 8.5 门禁退役路线(2026-10-28 裁定,2026-10-29 收口) -目标不是"关掉检查",而是把成本从**养 99 族语料**降到**禁止新编号**。三步,每步可独立回滚: +目标不是"关掉检查",而是把成本从**养 99 族语料**降到**禁止新编号**,最后一步是承认连这点机器面 +也不划算(2026-10-29 用户裁定)。四步,每步可独立回滚: | 步 | 内容 | 状态 | |---|---|---| | ① | 两根护栏(比例基线 / 不可判定绝对数上限)**转报告制**:照打数字,不再影响退出码 | **已完成 2026-10-28** | -| ② | 用 **diff 级新号拦截**替换语料审计:只看新增行里命中"字母+数字"形态、且不在白名单里的字面量,FAIL 并提示改成语义短语;白名单 = 前缀级两张表(活族 11 + 器件/协议/点号约 90),基本不增长 | **已完成 2026-10-28**(`scripts/check_ids_new.py` + 钩子 `id-check-new`,与 `id-check` **双跑观察期**;详解 `docs/门禁说明/id-check-new.md`) | -| ③ | 退役语料:99 族语料+脚本整体移入 `scripts/archive/id_gate/`(保留可复现性,不再进提交门禁);`check_ids.py` 降为手工报告工具,钩子摘除(口径 52 → 51) | **已完成 2026-10-28**(用户裁定跳过观察期直接做;`docs/门禁说明/id-check-new.md` 是唯一现役编号门禁) | +| ② | 用 **diff 级新号拦截**替换语料审计:只看新增行里命中"字母+数字"形态、且不在白名单里的字面量,FAIL 并提示改成语义短语;白名单 = 前缀级两张表(活族 11 + 器件/协议/点号约 90),基本不增长 | **已完成 2026-10-28**(脚本 + 钩子 `id-check-new`,与 `id-check` **双跑观察期**;脚本今在 `scripts/archive/id_gate/check_ids_new.py`,详解 `docs/门禁说明/id-check-new.md`) | +| ③ | 退役语料:99 族语料+脚本整体移入 `scripts/archive/id_gate/`(保留可复现性,不再进提交门禁);`check_ids.py` 降为手工报告工具,钩子摘除(口径 52 → 51) | **已完成 2026-10-28**(用户裁定跳过观察期直接做;当时 `id-check-new` 是唯一现役编号门禁) | +| ④ | 退役最后那道新增行拦截:钩子摘除(口径 52 → 51)、脚本与两张白名单移入 `scripts/archive/id_gate/`;此后**编号形态无机器面** | **已完成 2026-10-29**(用户裁定;留档 `docs/门禁说明/id-check-new.md`,含拦下过什么与为什么退) | -**在 ② 落地之前,校验 1~6 仍是唯一的机械牙**:别因为"两根线不拦了"就顺手写号—— -新增的未登记前缀照样当场 FAIL(实测:在一个新文件里写一个自造前缀 + 数字,校验 1 与增量拦截双拦)。 +**④ 之后没有任何机械牙**:别把"门禁不响了"读成"可以随便写号"——自造前缀在评审里照样扎眼, +而 `scripts/archive/id_gate/check_ids_new.py --range A..B` 随时能把一批改动重扫一遍(它退成了工具, +不是消失了)。要恢复机器面也便宜:把脚本放回 `scripts/` 并重新挂一条钩子(口径 +1,同批改三处计数)。 --- @@ -208,7 +213,8 @@ - 想给文档内步骤或测试阶段发号 → 不许,写「步骤 3」「阶段 7」(§3.3)。 - 想新增前缀族 → 先回答"哪个脚本要按字面量匹配它"(§4.1);答不出就别建。 - 要改号 → `scripts/rename_ids.py` + `编号治理历史.md` §7.3 五步。 -- 门禁报错读不懂 → `docs/门禁说明/id-check.md`。 +- 编号形态拿不准 → 本文 §1 三句自问;两道门禁的历史与手工跑法 → `docs/门禁说明/id-check.md`、 + `docs/门禁说明/id-check-new.md`。 --- diff --git a/docs/门禁说明/README.md b/docs/门禁说明/README.md index 19d72abb..884f2e85 100644 --- a/docs/门禁说明/README.md +++ b/docs/门禁说明/README.md @@ -1,7 +1,7 @@ # 门禁逐项说明(每种门禁一篇) -> 本目录逐项说明各门禁:**声明的 52 个钩子到底在干什么、拦谁、放谁、什么时候会骗人**——其中 3 根慢钩子带 -> `stages: [manual]`,一次 `git commit` 只实跑 49 根(口径见下条)。 +> 本目录逐项说明各门禁:**声明的 51 个钩子到底在干什么、拦谁、放谁、什么时候会骗人**——其中 3 根慢钩子带 +> `stages: [manual]`,一次 `git commit` 只实跑 48 根(口径见下条)。 > 每个门禁一篇,八段固定结构:查什么 / 为什么要它 / 触发面 / 报错怎么读 / 好处 / > **限制与盲区** / 豁免与基线 / 改门禁本身要注意什么。**最后一节是这套文档存在的理由**—— > 一份只看"拦了什么"的门禁文档,会让人以为绿就是对的。 @@ -9,10 +9,12 @@ - 配置事实源:`.pre-commit-config.yaml`。**钩子数的唯一口径 = YAML 解析后的 hook 条目数**,不是文件里的文本行数。 自查(打印声明数;加/删一条钩子后,这个数要与 **AGENTS.md 的「共 N 个钩子」**、**本目录 §2 标题**同时对齐): `& '.venv\Scripts\python.exe' -c "import yaml; d=yaml.safe_load(open('.pre-commit-config.yaml', encoding='utf-8')); print(sum(len(r['hooks']) for r in d['repos']))"` - → **52**(2026-10-26:49 → 50 加 `generated-fresh`;2026-10-27:50 → 51 加 `nested-comment`; - 2026-10-28:51 → 52 加 `id-check-new`、随即 52 → 51 摘掉 `id-check`(退役全库语料审计);2026-10-29:51 → 52 加 `skill-size`(SKILL.md 写侧上限与 reference 指针,详见 [`skill-size.md`](skill-size.md)))。 + → **51**(2026-10-26:49 → 50 加 `generated-fresh`;2026-10-27:50 → 51 加 `nested-comment`; + 2026-10-28:51 → 52 加 `id-check-new`、随即 52 → 51 摘掉 `id-check`(退役全库语料审计);2026-10-29:51 → 52 加 `skill-size`(SKILL.md 写侧上限与 reference 指针,详见 [`skill-size.md`](skill-size.md)); + 同日 52 → **51** 退役 `id-check-new`——只查新增行的编号门禁整体退场,脚本与白名单移入 + `scripts/archive/id_gate/`,此后**编号形态没有机器面**(留档 [`id-check-new.md`](id-check-new.md)))。 ⚠ **别用 `grep -c` 去数配置里的声明行**:该文件里有一条**注释掉的**候选钩子(clang-format,第 65 行), - 文本 grep 会多算 1 = 52——「声明 52 / 文档 51 / 实跑 51」这种三个数不同源的争执就是这么来的。真要 grep, + 文本 grep 会多算 1(当前口径 51 会数成 52)——「声明 52 / 文档 51 / 实跑 51」这种三个数不同源的争执就是这么来的。真要 grep, 用**锚定行首缩进**的模式(它天然跳过以 # 开头的注释行)2026-10-28 实测直接得 **51**(当时口径),与 YAML 口径一致; 会多算 1(比口径多 1)的是**不锚定行首、按子串**匹配声明行的写法(那条被注释掉的候选也被它算进去)。 ⚠ 反过来的坑也真踩过(2026-10-27):在配置**注释里复述那个 grep 字面量**,会让文本 grep 再虚高 1—— @@ -39,12 +41,12 @@ | **改写型** | 不报错,直接改你的文件 | `trailing-whitespace`、`end-of-file-fixer` | 重新 `git add` 被改的文件再提交(它改的是工作区,不是索引) | | **硬拦截** | 违反即失败,没有存量豁免 | `cppcheck`、`coding-standard`、`doc-links`、`no-mojibake`、`mem-budget`、`ui-golden`、`font-charset`、`lv-conf-sync`、`task-table`、`mem-numbers`、`registration-check`、`cubemx-survival`、`test-suite-switch`、22 个主机单测、官方 5 个、`gitlint` | 只能改代码或改文档;**不要**找豁免开关 | | **增量拦截** | 规则恒生效,但存量钉在基线/台账里,只许减不许增 | `layer-deps`(3 条,2026-10-25 还清 UI 记录 3 条)、`bsp-err`(38 条)、`generated-fresh`(5 处 `docs/images/` 配图存量,脚本内 `BASELINE`)、`nested-comment`(2 处主机侧假件头,`test/host/common/`,脚本内 `BASELINE`) | 报错先分清是**新增**还是**存量搬家**:`--verbose` 看归类,`--prune` 看已还清 | -| **只查新增** | 只看本次改动的增量,没有存量基线,也没有台账 | `id-check-new` | 改成语义短语,或把设备名/协议名登记进脚本白名单(行内 `[编号豁免]` 是最后手段) | +| **只查新增** | 只看本次改动的增量,没有存量基线,也没有台账 | ~~`id-check-new`~~(**2026-10-29 退役**,脚本在 `scripts/archive/id_gate/`;这一姿态已无现役门禁) | 手工复查时才谈得上:改成语义短语(门禁不再跑,行内 `[编号豁免]` 也随之失效) | ⚠ 增量拦截最容易误会的一点:**绿灯不等于没问题**,只等于"没有比上次更差"。 每个增量拦截门禁的基线数字都写进它自己的文档,读那篇时第一眼看的就是"现在在册多少条"。 -## 2. 索引(52 个 hook → 29 篇,其中 1 篇是已退役门禁的留档 + 1 根只有本表指针(专篇待补)+ 1 根详解在 docs/测试说明/) +## 2. 索引(51 个 hook → 29 篇,其中 2 篇是已退役门禁的留档 + 1 根只有本表指针(专篇待补)+ 1 根详解在 docs/测试说明/) > 带 `stages: [manual]` 的三根(`cppcheck` / `test-cppcheck` / `test-coverage`)**提交期不跑**,只在远端 CI 的 > 「手动阶段门禁」步与 `scripts/ci_local.py` 的 manual 段跑;下表对应两行的「文档」列已标注。 @@ -53,8 +55,8 @@ |---|---|---|---|---| | [`bsp-err.md`](bsp-err.md) | `bsp-err` | BSP 的对外 API 面:错误通道类型、超时宏命名、必须写返回值、返回值不得裸丢弃 | `Drivers/BSP/**` 或门禁自身 | 已写 | | [`layer-deps.md`](layer-deps.md) | `layer-deps` | 分层方向:`Drivers/BSP/**` 不得 include `App/**` | `Drivers/BSP/**` | 已写 | -| [`id-check.md`](id-check.md) | ~~`id-check`~ | **已退役(2026-10-28)**:全库语料的八项校验,留档备查;现行编号门禁见下一行 | 在时有:几乎所有文本文件 | 已写(退役留档) | -| [`id-check-new.md`](id-check-new.md) | `id-check-new` | **只查新增行**有没有新造编号(零语料前缀白名单,已停发族只告警) | 任意 md/c/h/py/yaml/txt | 已写 | +| [`id-check.md`](id-check.md) | ~~`id-check`~ | **已退役(2026-10-28)**:全库语料的八项校验,留档备查;接班件也在下一行 | 在时有:几乎所有文本文件 | 已写(退役留档) | +| [`id-check-new.md`](id-check-new.md) | ~~`id-check-new`~ | **已退役(2026-10-29,用户裁定)**:只查新增行的编号门禁,留档备查(含退役理由与手工跑法);**编号形态此后无机器面** | 在时有:任意 md/c/h/py/yaml/txt | 已写(退役留档) | | [`doc-links.md`](doc-links.md) | `doc-links` | 文档里的路径引用是否存在;`--sections-strict` 另查章节号是否还存在 | 任意 `.md` | 已写 | | [`cppcheck.md`](cppcheck.md) | `cppcheck`、`test-cppcheck` | 静态分析(真机侧与 `test/` 侧两套范围与抑制项) | C/H 源文件 | 已写(`stages: [manual]`) | | [`coding-standard.md`](coding-standard.md) | `coding-standard` | 编码规范 V1.0 的可机械检查子集(命名、头文件保护宏、模块头注释块…) | C/H 源文件 | 已写 | diff --git a/docs/门禁说明/id-check-new.md b/docs/门禁说明/id-check-new.md index a960625b..0c77fb12 100644 --- a/docs/门禁说明/id-check-new.md +++ b/docs/门禁说明/id-check-new.md @@ -1,103 +1,81 @@ -# id-check-new(编号门禁·新增行) +# `id-check-new` — 编号门禁·新增行(零语料)——**已退役(2026-10-29)** -> 一句话:**只查这次改动新增的行里有没有新造的编号**,不维护任何族清单。 -> 它是 `id-check` 全库语料审计的接班件(退役路线见 `docs/编号规范.md` §8.5)。 +> ⚠ **本文是退役留档,不要照着它去改门禁。** +> 2026-10-29 用户裁定:这道门禁整体去掉——钩子从 `.pre-commit-config.yaml` 摘除(YAML 解析口径 +> 52 → 51),脚本移入 `scripts/archive/id_gate/check_ids_new.py`(仍可手工跑,`--self-test` 保留)。 +> **此后编号形态没有任何机器面**:判据只剩 `docs/编号规范.md` §1 的三句自问、§4.1 允许用号的族 +> (穷举)与人工评审。前辈 `id-check`(全库八项校验)已于 2026-10-28 退役 → `docs/门禁说明/id-check.md`; +> 两步合起来的路线 → `docs/编号规范.md` §8.5。 +> 下面 §1~§6 是退役前的原样描述,只在手工复查「这批改动 / 这段历史里有没有野生编号」时用得上。 -## 1. 它在查什么 +## 1. 它当初在查什么 拿 `git diff` 的**新增行**,只做三件事: | 形态 | 例子(形态描述,不是本仓号) | 判据 | |---|---|---| -| 破折形态 | 两字母前缀 + 连字符 + 数字 | 首段不在白名单 → **FAIL**;在「已停发族」→ 只 WARN | -| 裸形态 | 大写字母串紧跟数字(外设/器件/点号写法) | 前缀不在白名单 → **FAIL** | -| 单字母 + 数字 | 元件位号与层次号同形的那些 | **一律放行**(见 §6 盲区) | +| 破折形态 | 两字母前缀 + 连字符 + 数字 | 首段不在 `KNOWN_DASH` → **FAIL**;在 `RETIRED_DASH`(已停发族)→ 只 WARN | +| 裸形态 | 大写字母串紧跟数字(外设 / 器件 / 点号写法) | 前缀不在 `KNOWN_BARE` → **FAIL** | +| 单字母 + 数字 | `C12` / `U15` / `L3` / `R3` 这类元件位号与层次号同形 | **一律放行**(已知盲区,与旧门禁的"裸形盲区"同源) | -判据全文只有两张前缀表(`KNOWN_DASH` ≈ 11 条、`KNOWN_BARE` ≈ 90 条)与一张算术排除表 -(`SIZE`/`LEN`/`MAX` 之类后面跟 `-数字` 是减法不是编号)。**没有族形态正则、没有游标、 -没有属主登记处、没有比例基线**——这就是它相对 `id-check` 的全部区别。 +判据全文只有两张前缀表(退役时 `KNOWN_DASH` 11 条、`KNOWN_BARE` 90 余条)与一张算术排除表 +(`SIZE` / `LEN` / `MAX` 之类后面跟 `-数字` 是减法不是编号)。**没有族形态正则、没有游标、没有属主 +登记处、没有比例基线**——这就是它相对 `id-check` 的全部区别,也是它当初被选为接班件的理由。 -## 2. 为什么要它(与 id-check 的分工) +豁免三档:行内含 `[示例]` / `[计划]` 按冻结口径跳过;确需保留的字面量(如冻结的现场日志)在同一行 +写 `[编号豁免]`;脚本自身、`scripts/archive/`、`docs/芯片手册/`、`docs/硬件平台/`、`Lib/`、 +`Middlewares/` 等在排除清单里。**加白名单是唯一的放宽手段**——没有"整库豁免"入口,也没有 `--write` +现状洗白(与旧门禁同一条纪律)。 -`id-check` 需要养 99 族语料(`id_registry.json` 87.6 KB + `id_aliases.json` 187 KB); -实测它的**单次运行只有 1.8 s**,贵的是"每笔提交都要维持语料自洽"——近 80 笔提交里 61 笔 -改了语料/门禁/规范。而它真正有用的那部分(拦住"新写一个自造编号")不需要语料: -只要知道"这个前缀我从没见过"就够了。 +## 2. 为什么当初要它 -所以两者的分工是:**`id-check` 管存量一致性(逐步退役),`id-check-new` 管增量不许新增**。 -观察期内两条**同时跑**,互相兜底;观察期结束后按 `docs/编号规范.md` §8.5 摘掉 `id-check`。 +`id-check` 要养 99 族语料(`id_registry.json` 87.6 KB + `id_aliases.json` 187 KB):单次运行只有 +**1.8 s**,贵的是"每笔提交都要维持语料自洽"——近 80 笔提交里 **61 笔**动了语料 / 门禁 / 规范。 +而它真正有用的那一小块(拦住"新写一个自造编号")根本不需要语料:只要知道"这个前缀我从没见过"。 +所以 2026-10-28 的分工是:`id-check` 管存量一致性(当日退役),`id-check-new` 管增量不许新增。 -## 3. 触发面 +落地前测过噪声:拿最近 **80 笔真实提交**回放,未知形态只有 15 种,其中 12 种是设备 / 协议名 +(已进白名单)、3 种是已停发族(只告警)→ 白名单调好后**回放 0 误报**。 -- `files:` = 任意 `md` / `c` / `h` / `py` / `yaml` / `txt` 或本配置文件本身;`pass_filenames: false` - (脚本自己读 `git diff`,不靠钩子传文件名)。 -- 只读**新增行**:删行、改行里的旧编号不查(那是存量,归 `id-check`;退役后不再有人管, - 但这正是用户裁定接受的代价)。 -- 默认查**暂存区**(`git diff --cached`)。手工自查:`--worktree`(未暂存改动)/ `--range A..B`(一段提交)。 -- 排除面与旧门禁对齐:第三方库、HAL/CMSIS、`docs/芯片手册/`、`docs/硬件平台/`、`docs/images/`、 - `simulator/tests/ref/`、`ci-artifacts/`、`.dsh/skills/`、`scripts/rename_maps/`、 - 以及二进制/生成物后缀(`.svg` `.png` `.bin` `.map` `.json` 等)。 +## 3. 退役的理由(这一节是本文的重点) -## 4. 报错怎么读 +1. **它咬的是形态,不是语义**:白名单是"形态"级不是"号"级——前缀合法则 `TIM3` 放行、`TIM99` 同样 + 放行;同形多义(历史上 `S3` 三义那类撞车)它照不出来。这与旧门禁 `id-check.md` §6 记的盲区同源, + 只是范围缩到新增行。 +2. **白名单就是它的维护面**:每遇到一类合法字面量(新型器件、协议名、固件生成的产物文件名)就要加 + 一条;不加就误拦,加了就把该前缀后头的所有数字永久放宽。2026-10-29 当天就撞过一次:文档里写 + 录波段文件名 `WAVE00.BIN` 被拦,先改写成 `WAVE.BIN` 绕行、再登记 `WAVE` 前缀(`KNOWN_BARE` + 最后一次改动)。这类"合法新词撞形态门"是常态,不是意外。 +3. **默认形态早就是语义短语**(`docs/编号规范.md` §1 与 §3.3;登记簿新条目一律写语义短语, + `docs/任务规划/README.md` §0),新造号在评审里本来就看得见,机器面的边际收益低于误拦成本。 +4. 与 2026-10-28 摘掉全库审计是**同一条判断的延续**:编号体系不再产生价值。留着这道门只让"要不要 + 再登记一个前缀"变成反复出现的小额开销。 +5. 别往"轻量版"方向找补:改成只告警(退出码恒 0)等于把形态判断变成没人看的滚屏;转 + `stages: [manual]` 又因为它是 diff 型脚本、脱离提交时机基本扫不到东西。两条都是留着成本、 + 去掉收益,所以整体退役。 -```text -[FAIL] 新增行里有 2 处**未登记形态**的字母+数字标识: - docs/xxx.md:3 ZZ-9 [示例] - → 语义标识是默认形态:改写成短语(docs/编号规范.md §1); - 确属设备名/协议名/位号,就把前缀登记进 scripts/check_ids_new.py 的白名单。 +## 4. 退役后手工怎么用 + +``` +& '.venv\\Scripts\\python.exe' scripts/archive/id_gate/check_ids_new.py --self-test # 正反例自检(5 正例 / 29 反例) +& '.venv\\Scripts\\python.exe' scripts/archive/id_gate/check_ids_new.py --range A..B # 复扫一段提交的新增行 +& '.venv\\Scripts\\python.exe' scripts/archive/id_gate/check_ids_new.py --worktree # 查未提交的改动 ``` -三种处理:① 改成语义短语(默认);② 确实是设备名/协议名(如新的芯片型号)→ 把前缀加进 -`KNOWN_BARE` / `KNOWN_DASH`;③ 这一行必须保留字面(如冻结的现场日志)→ 行内写 `[编号豁免]`。 -⚠ `[示例]` / `[计划]` 行按既有冻结口径**整行跳过**,这也是本门禁的已知口子(§6)。 -⚠ 上面报错样例那行带 `[示例]`:两条门禁都认这个冻结标记、认不出「这段是文档举例」, -所以**在文档里举反例必须带 `[示例]`**,否则举例自己就会被拦(这条就是被自己拦过一次之后补的)。 -退出码:0 = 通过 / 仅告警;1 = 有新增编号;2 = 环境错误(git 不可用、不在仓库内)。 +跑不跑都不影响提交。真正还用得上它的场合是**编号清退批次**:拿它当"形态普查"的尺子,比自己临时 +写正则省事(做法 → `.dsh/skills/id-family-semantic-migration/SKILL.md`)。 -## 5. 好处 +## 5. 此后靠什么守着 -- **零维护**:加一个设备型号是改一行白名单,不需要登记族、游标、属主文档、基线比例。 -- **判据窄**:只对"新增"负责,所以不必解释"为什么这个历史号还在"——那类争论在旧门禁里占了大半时间。 -- **自证成本低**:`--self-test` 内置 5 个正例 + 29 个反例(含 `TC-NET-204`、`TRAP-ADC-01`、 - `TPAFE5160`、`GD5F2GQ5UE`、`C12`、`SIZE-2`、`GPIO_PIN_5` 等),改脚本后一条命令验证没把牙弄掉。 -- **落地前测过噪声**:拿最近 80 笔真实提交回放,未知形态只有 15 种,其中 12 种是设备/协议名 - (已进白名单)、3 种是已停发族(只告警)→ 白名单调好后回放 **0 误报**。 +- `docs/编号规范.md` §1「先问三句」+ §4.1 允许用号的族(穷举)+ §3.3 禁发范围——**新增族不再需要 + 登记机器白名单**,那个"唯一口子"随门禁一起消失;答不出"哪个脚本要按字面量匹配它"就别建族。 +- 评审与销项纪律:`docs/任务规划/README.md` §0(已随销项消失的号永久作废、不得复用)。 +- ⚠ 要认下丢了什么:**"销项删行后号被重新取走"这类事故当初正是靠机械牙发现的**(2026-10-14 撞号 + 事故 → 语义标识裁定)。此后提交期不再有这类警报,只剩规范与人工核。 -## 6. 限制与盲区(这一节请当正文读) +## 6. 改这个脚本本身要注意什么(历史留笔) -1. **单字母 + 数字一律放行**:元件位号(`C12`/`U15`/`R3`/`D7`)与层次号、裸形族号同形, - 机械区分不出来 → 新写一个单字母+数字的号**不会**被拦。这是本门禁最大的洞,与旧门禁的 - 「裸形盲区」同源,属显式接受的代价。 -2. **只查新增行**:把旧编号从 A 行搬到 B 行、或整段重排,算"新增"→ 会拦(因为形态未登记); - 反之,只要形态在白名单里,新写的也放行——白名单是"形态"级,不是"号"级。 -3. **`[示例]`/`[计划]` 整行跳过**:想绕过本门禁,写个 `[示例]` 就行。这靠评审纪律,不靠机器。 -4. **未跟踪文件不在扫描面**(`git diff` 语义):手工在 `git add` 之前跑 `--worktree` 看不到新文件; - 提交时必已进暂存区,所以门禁场景不受影响。 - 推论:**在 `pre-commit run --all-files`(`ci_local.py` 的静态门禁)下它是空转的**—— - 那种跑法把文件当"全量"传进来,而本脚本只读暂存区 → 暂存区空 → 打印通过。 - 它只在**真实提交**时才有牙;别拿静态门禁全绿当"没有新编号"的证明。 -5. **算术白名单是启发式**:`SIZE-2`/`LEN-1` 这类被排除;但若某处写着一个「不在白名单的前缀 + - 连字符 + 数字」,就会误报一次——把前缀加进白名单即可,不构成误拦风险。 -6. **不校验语义**:白名单里的前缀可以拿来写任何东西(`TIM3` 合法,`TIM99` 也放行)。 - 它只回答"这是不是新造的前缀",不回答"这个号该不该存在"。 - -## 7. 豁免与白名单口径 - -| 类别 | 放行方式 | 维护动作 | -|---|---|---| -| 设备 / 芯片 / 模块型号(`TPAFE5160`、`CH395F`、`SD2506`、`GD5F2GQ5UE`) | `KNOWN_BARE` 前缀 | 新器件时加一条 | -| 协议 / 标准(`IEC104`、`SHA-256`、`RS-485`、`UTF-8`) | `KNOWN_DASH` / `KNOWN_BARE` | 基本不增长 | -| 遥信/遥控点号(`YX`/`YK`/`YT`/`YH`)与保护元件代号(`OC`/`UV`/`OV`/`CP`…) | `KNOWN_BARE` | 协议数据,不是标识符 | -| 活族编号(`FR-*`、`TRAP-*`、`TC-*`、`CODE-RULE-*`、`MENU-STATE-*`) | `KNOWN_DASH` | 新增族要先在此登记 | -| 已停发族(登记簿/专项/层次/原则等旧族) | `RETIRED_DASH` → **只 WARN** | 不拦提交,提示改语义短语 | -| 固件生成的产物文件名(录波段号 `WAVE00.BIN` 到 `WAVE99.BIN`) | `KNOWN_BARE` 前缀,2026-10-29 登记 `WAVE` | 换一类产物名再加一条;先分清产物名与编号族 | -| 一次性保留 | 行内 `[编号豁免]` | 提交说明里要交代原因 | - -## 8. 改这个门禁本身要注意什么 - -- 改完必跑 `python scripts/check_ids_new.py --self-test`(正例漏拦 / 反例误拦都会红)。 -- 加白名单是**唯一**放宽手段;没有"整库豁免"入口,也没有 `--write` 现状洗白(与旧门禁同一条纪律)。 +- 改完必跑 `--self-test`(正例漏拦 / 反例误拦都会红);退役后这条纪律只对手工复查生效。 - 别把白名单做成"按字面量枚举"的账本——那就退化成 `id_aliases.json` 的老路(187 KB 维护负担), 前缀级枚举才是它便宜的原因。 -- 与 `id-check` 的关系变更(摘掉旧的)要同批改:本页、`docs/编号规范.md` §8.5、 - `docs/门禁说明/README.md` 的索引与计数、`AGENTS.md` 的钩子数。 +- 归档位置的 `REPO_ROOT` 与原位不同(深两级,取 `parents[3]`);再挪目录要一起改。 diff --git a/docs/门禁说明/id-check.md b/docs/门禁说明/id-check.md index 8bc0a4f9..c45033f6 100644 --- a/docs/门禁说明/id-check.md +++ b/docs/门禁说明/id-check.md @@ -3,7 +3,9 @@ > ⚠ **本文是退役留档,不要照着它去改门禁。** > 2026-10-28 用户裁定:编号体系本身不再产生价值,全库语料审计的维护成本高过收益 > → 钩子摘除(52 → 51),脚本与两份语料整体移入 `scripts/archive/id_gate/`; -> **现行编号门禁 = `id-check-new`**(只查新增行、零语料)→ `docs/门禁说明/id-check-new.md`。 +> **接班件 `id-check-new` 也已于 2026-10-29 退役**(只查新增行那道,用户裁定)→ `docs/门禁说明/id-check-new.md`。 +> 两道编号门禁自此全部退场:**编号形态没有机器面**,判据回到 `docs/编号规范.md` §1 三句自问 + §4.1 +> 族总表 + 人工评审;归档脚本 `scripts/archive/id_gate/check_ids_new.py` 可随时手工普查形态。 > 退役路线与判据替换 → `docs/编号规范.md` §8.5。下面保留退役前的原样描述与实测基线, > 只在手工复查「存量编号现状」时还用得上。 diff --git a/scripts/archive/id_gate/README.md b/scripts/archive/id_gate/README.md index 9e1f3d62..ba66a74b 100644 --- a/scripts/archive/id_gate/README.md +++ b/scripts/archive/id_gate/README.md @@ -1,11 +1,12 @@ -# 编号门禁·全库语料审计(已退役,2026-10-28 归档) +# 编号门禁归档(两道都已退役:全库语料审计 2026-10-28、新增行检查 2026-10-29) -本目录是 2026-10-20 ~ 2026-10-28 期间在 `pre-commit` 里跑的那套**全库编号审计**, -连同它的两份语料一起搬进来,**不再进提交门禁**。 +本目录是 2026-10-20 ~ 2026-10-29 期间在 `pre-commit` 里跑过的**两套编号门禁**,连同它们的 +语料与白名单一起搬进来,**都不再进提交门禁**。2026-10-29 的裁定见每篇文末与其留档文档。 | 文件 | 是什么 | |---|---| | `check_ids.py` | 八项校验脚本(规范 §8)。手工复查存量编号现状时才跑 | +| `check_ids_new.py` | 只查新增行的那道(2026-10-28 ~ 2026-10-29 在钩子里跑),2026-10-29 用户裁定退役后降为**手工形态普查**;`--self-test` 保留,`REPO_ROOT` 因归档位置深两级改取 `parents[3]` | | `id_registry.json` | 99 族的注册表:形态正则 / 属主登记处 / 冻结 / 游标 / 两条护栏的数值 | | `id_aliases.json` | 旧号 → 新号 / 作废(`retired-to-phrase`、`void`)的别名表,187 KB | | `id_known_backlog.json` | 债务台账(收口时已还清到 0 条) | @@ -18,9 +19,10 @@ ## 现在用什么 -- **现行门禁**:`scripts/check_ids_new.py` + 钩子 `id-check-new` —— 只查 `git diff` 新增行, - 零语料。详解 `docs/门禁说明/id-check-new.md`。 -- **路线与验收条件**:`docs/编号规范.md` §8.5(①②③ 三步的来龙去脉)。 +- **没有现行门禁**:接班的 `id-check-new`(只查新增行、零语料)也在 2026-10-29 被用户裁定退役, + 脚本进本目录。编号形态此后无机器面,判据 = `docs/编号规范.md` §1 三句自问 + §4.1 族总表 + 评审; + 留档 `docs/门禁说明/id-check-new.md`(拦下过什么、为什么退、手工怎么再跑)。 +- **路线与验收条件**:`docs/编号规范.md` §8.5(①②③④ 四步的来龙去脉)。 - **规范正文**(仍然有效,只是不再全库机械校验):`docs/编号规范.md` §1 先问三句、§4.1 族总表。 ## 怎么手工跑一次 diff --git a/scripts/archive/id_gate/check_ids.py b/scripts/archive/id_gate/check_ids.py index 24510204..fa3380e3 100644 --- a/scripts/archive/id_gate/check_ids.py +++ b/scripts/archive/id_gate/check_ids.py @@ -5,10 +5,12 @@ check_ids.py — 编号门禁(docs/编号规范.md §8 的 8 项校验)— ⚠ 退役说明(先读这段,别把它当活门禁用): 本脚本与两份语料(id_registry.json / id_aliases.json)已整体移入 scripts/archive/id_gate/, - **不再进 pre-commit**,也不再有人被要求维护语料。现行编号门禁是 scripts/check_ids_new.py - (钩子 id-check-new:只查新增行、零语料)。本脚本保留下来只做一件事: + **不再进 pre-commit**,也不再有人被要求维护语料。接班的 scripts/check_ids_new.py + (钩子 id-check-new:只查新增行、零语料)已于 2026-10-29 一并退役,也进了本目录—— + **编号形态此后没有机器面**。本脚本保留下来只做一件事: 想复查「存量编号现状」时手工跑一遍出报告。 - 路线与判据替换的来龙去脉 → docs/编号规范.md §8.5;新门禁详解 → docs/门禁说明/id-check-new.md。 + 路线(①②③④ 四步)→ docs/编号规范.md §8.5;两道门禁的留档 → docs/门禁说明/id-check.md + 与 docs/门禁说明/id-check-new.md。 下面这份 docstring 是退役前的原样,未改,作为历史口径保留。 两份配置(数据源 = 规范 §4 编号空间总表,逐项对应,不凭印象): diff --git a/scripts/check_ids_new.py b/scripts/archive/id_gate/check_ids_new.py similarity index 87% rename from scripts/check_ids_new.py rename to scripts/archive/id_gate/check_ids_new.py index af1be72b..ef6fce66 100644 --- a/scripts/check_ids_new.py +++ b/scripts/archive/id_gate/check_ids_new.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -"""check_ids_new.py — 编号门禁·第二步:只查**新增行**的新编号(零语料、无语料维护) +"""check_ids_new.py — 编号门禁·新增行(**已退役 2026-10-29,用户裁定**;本脚本降为手工报告工具) -背景(docs/编号规范.md §8.5):语义标识已是默认形态,1~6 项全库语料审计的成本高过收益。 -本脚本替代它的**唯一实际用途**——拦住"新写一个自造编号":只看 git diff 的新增行。 +退役口径:钩子已从 .pre-commit-config.yaml 摘除(YAML 解析条目 52 → 51),编号形态此后 +**没有机器面**——靠 docs/编号规范.md §1 的三句自问 + 评审。留档说明 → docs/门禁说明/id-check-new.md。 +本脚本与 check_ids.py(2026-10-28 退役的全库八项校验)同处一档:手工复查「这批改动 / 这段历史 +里有没有野生编号」时才跑,跑不跑都不影响提交。 判据(三条,都不依赖任何族清单 / 游标 / 属主登记处): 1. 破折形态(形如 前缀-数字,或 前缀-段-数字):首段不在 KNOWN_DASH → FAIL; @@ -12,11 +14,11 @@ 3. 单字母+数字(C12 / U15 / L3 / R3)→ **放行**:元件位号与层次号同形,这是本脚本的已知盲区 (与旧门禁的"裸形盲区"同源,见 docs/门禁说明/id-check-new.md §5)。 -用法(仓库根): - python scripts/check_ids_new.py # 查暂存区(pre-commit 用这个) - python scripts/check_ids_new.py --worktree # 查工作区未暂存的改动(自查) - python scripts/check_ids_new.py --range A..B # 查一段提交的新增行 - python scripts/check_ids_new.py --self-test # 内建正反例自检(改脚本后必跑) +用法(仓库根;钩子摘除后没有自动调用者,四条都是手工): + python scripts/archive/id_gate/check_ids_new.py # 查暂存区 + python scripts/archive/id_gate/check_ids_new.py --worktree # 查工作区未暂存的改动 + python scripts/archive/id_gate/check_ids_new.py --range A..B # 查一段提交的新增行 + python scripts/archive/id_gate/check_ids_new.py --self-test # 内建正反例自检(改脚本后必跑) 退出码:0 = 通过 / 仅告警;1 = 新增了未知编号;2 = 环境错误。 豁免:行内含 [示例] / [计划] 的行按冻结口径跳过;确需保留的写法在同一行写 [编号豁免]。 """ @@ -33,7 +35,8 @@ for _stream in (sys.stdout, sys.stderr): except (AttributeError, ValueError): pass -REPO_ROOT = Path(__file__).resolve().parent.parent +# 归档位置比原位置深两级(scripts/archive/id_gate/)→ 上溯到仓库根要 parents[3] +REPO_ROOT = Path(__file__).resolve().parents[3] # --- 破折形态:首段白名单(活族 + 标准编号;新增族要先登记到这里,这就是"允许用号的唯一口子") KNOWN_DASH = frozenset({ @@ -98,7 +101,8 @@ EXCLUDED_DIRS = ( ) EXCLUDED_FILES = frozenset({ - "scripts/check_ids_new.py", # 本脚本自带正反例白名单,不能自我拦截 + "scripts/check_ids_new.py", # 本脚本自带正反例白名单,不能自我拦截(归档后整目录已在 + # EXCLUDED_DIRS 的 scripts/archive/ 里,这行只是历史留笔) }) EXCLUDED_SUFFIX = (".svg", ".png", ".jpg", ".jpeg", ".gif", ".bin", ".map", ".htm", ".html", ".tsv", ".log", ".o", ".axf", ".hex", ".ico", ".ttf", ".woff", ".pyc", @@ -248,7 +252,8 @@ def main(argv=None): if args.verbose: print(" %s" % text) print(" → 语义标识是默认形态:改写成短语(docs/编号规范.md §1);") - print(" 确属设备名/协议名/位号,就把前缀登记进 scripts/check_ids_new.py 的白名单。") + print(" 确属设备名/协议名/位号,就改形态(写语义短语)——本门禁已于 2026-10-29 退役,") + print(" 不再是提交钩子;要再拿它当尺子就手工跑 scripts/archive/id_gate/check_ids_new.py。") return 1 print("[OK] 新增行无未登记编号%s" % ("(%d 处停发族提示)" % len(warns) if warns else "")) diff --git a/scripts/archive/id_gate/编号治理历史.md b/scripts/archive/id_gate/编号治理历史.md index d6e4924c..f3af6f6d 100644 --- a/scripts/archive/id_gate/编号治理历史.md +++ b/scripts/archive/id_gate/编号治理历史.md @@ -355,7 +355,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语 | 日期 | 变更 | 说明 | |---|---|---| | 2026-10-28 | **编号门禁第三步收口:全库语料审计退役(钩子 52 → 51)** | 用户裁定跳过观察期直接做。`check_ids.py` 与两份语料(`id_registry.json` 87.6 KB / `id_aliases.json` 187 KB)+ 债务台账整体移入 `scripts/archive/id_gate/`(附归档 README,含"为什么退役 / 现在用什么 / 怎么手工跑");`id-check` 钩子摘除,现役编号门禁只剩 `id-check-new`(只查新增行)。连带改:`rename_ids.py` 的别名表路径指向归档、新门禁排除面加 `scripts/archive/`、`doc-links` 跳过 `.mnemon/` 与 `ci-artifacts/`(本地状态与草稿,非项目文档)、`id-check.md` 加退役横幅、`门禁说明/README` 与 `AGENTS` 的钩子数三数对齐(声明 51 / commit 阶段 50 + gitlint 1)。归档脚本从新路径实跑:811 文件 / 8,051 字面量、`--strict` rc=0。 | -| 2026-10-28 | **编号门禁第二步落地:新增行拦截(零语料)** | `scripts/check_ids_new.py` + 钩子 `id-check-new`:只看新增行,破折形态未知前缀 FAIL、已停发族只 WARN、单字母+数字放行(元件位号同形,见该门禁 §6 盲区)。白名单是**前缀级**两张表(活族 11 条 / 器件与协议约 90 条),不是字面量账本——后者会退化成 `id_aliases.json` 的老路。调参依据:最近 80 笔真实提交回放,未知形态 15 种(12 种是设备与协议名、3 种是停发族),调好后误报 0;自检 5 正例 + 29 反例。与 `id-check` **双跑**一个观察期后再按 `docs/编号规范.md` §8.5 ③ 退役旧语料。 | +| 2026-10-28 | **编号门禁第二步落地:新增行拦截(零语料)** | 脚本(今在 `scripts/archive/id_gate/check_ids_new.py`)+ 钩子 `id-check-new`:只看新增行,破折形态未知前缀 FAIL、已停发族只 WARN、单字母+数字放行(元件位号同形,见该门禁 §6 盲区)。白名单是**前缀级**两张表(活族 11 条 / 器件与协议约 90 条),不是字面量账本——后者会退化成 `id_aliases.json` 的老路。调参依据:最近 80 笔真实提交回放,未知形态 15 种(12 种是设备与协议名、3 种是停发族),调好后误报 0;自检 5 正例 + 29 反例。与 `id-check` **双跑**一个观察期后再按 `docs/编号规范.md` §8.5 ③ 退役旧语料。 | | 2026-10-28 | **编号门禁减负第一步:两根护栏转报告制** | 用户裁定「编号门禁每次浪费很多时间」→ 先摘掉语料审计的强制面。护栏 1(可判定比例基线)与护栏 2(不可判定绝对数上限)自此**只打印、不拦提交**;实测把基线调到 99.9%、上限调到 1 处,退出码仍为 0。硬拦只剩校验 1~6 的台账外新账(同一实测:新文件里写一个自造前缀 + 数字,校验 1 与增量拦截照旧 FAIL)。退役路线 ①②③ 写进 `docs/编号规范.md` §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 历史,一处没丢。刻意不动:硬件位号形态的举例(判非编号)、保留现存号族的冻结游标数字(冻结水位的证据本体)、其它文档与注册表里的同名字段(各自写域)。`docs/编号规范.md` §5.5 同步写死该例外的硬口径。零代码、零编号增删、两根护栏基线均未调整。 | | 2026-10-27 | **批次五:「数据可信」任务卡号整族清退 + 注入验证卡销项删行** | 用户指令「数据可信.md 已经完成的内容请进行销项删除,去除相关编号」。实测 **288 站点 / 56 文件**(代码与测试 191 / 文档 56 / 门禁配置与本文 41)全改语义短语;`docs/编号规范.md` §5 表首列由「序」改「标识(任务名)」、14 个旧号进 §9.3 换算表;顺带按属主文档判语义清掉同形态的悬空引用 4 处(「UI 补齐」波次的 `[comm]` 段前置项)。门禁面:编号字面量与不可判定绝对数**零变化**(中文前缀不在语料),收口复跑 `check_ids.py --strict` 与 `check_doc_links.py --all --sections-strict` |