docs(门禁): 钩子计数与门禁索引同步到实测口径(51 / 50+1 / 22 / 28 篇)

实测口径(三数同源):
- YAML 解析后的 hook 条目数 = 51(不是文本 grep 声明行)。
- gitlint 未声明 stages(实测 stages = None)→ 按默认属全阶段计,
  pre-commit 阶段 50 + commit-msg 阶段 gitlint 1 = 51。
- 带 -unit-test 后缀的专属钩子实测 22 根(AGENTS 的 Lead 裁定 2026-10-27:
  不补第 23 根)。
- docs/门禁说明/ 下除 README 外实测 28 篇(上一轮加钩子没同步篇数)。

逐处:AGENTS.md 补齐 2026-10-25 道E 三根钩子的逐项枚举(补齐后该行
各项相加才等于 51);docs/代码规范/pre-commit使用说明.md 两阶段表
49/50 → 50/51、§5 文件表 40 → 51 并注当日 51 → 52 → 51 净零;
docs/门禁说明/gitlint.md 的 --no-verify 跳过面 39 → 50(= 51 减自身);
docs/门禁说明/README.md 索引 27 → 28 篇、grep 自查口径改为锚定行首的
实测结果、硬拦截行 16 → 22 个主机单测;test/host/README.md 16 → 22 两处;
docs/环境与部署/并行任务工作树方案.md 30 / 40 → 51;
docs/测试说明/测试开发标准流程.md 那条 2026-10-11 审计的「18 个钩子」
加「当时」锁口径、不臆改成现值;两份 skill 正文里的 id-check 说法改为
「已于 2026-10-28 退役、现行只查新增行」。
This commit is contained in:
2026-10-28 15:37:02 +08:00
parent dc214e1426
commit 4ba02212eb
9 changed files with 20 additions and 17 deletions
@@ -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` |
| 中文前缀(「卡」+ 数字)、纯散文里的号、圈号 ①②③ | **自建带标签正则扫描器**(门禁看不见它,id-check 报告与本族无关) | 逐处替换 + 断言命中数(`rename_ids.py` 靠族 pattern 驱动,这里用不上) | **刻意不登记**:登记了机器也看不见,只多一张没人核的表;停发只靠规范 + 评审 |
| 中文前缀(「卡」+ 数字)、纯散文里的号、圈号 ①②③ | **自建带标签正则扫描器**(门禁看不见它,2026-10-28 退役前的 id-check 全库报告与本族无关;现行 id-check-new 只查新增行) | 逐处替换 + 断言命中数(`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。
+1 -1
View File
@@ -197,7 +197,7 @@ WT="$MAIN/../_wt/und-attr" # 仓外同级 _wt/ 下;一次
rm -rf "$WT" 2>/dev/null
git -C "$MAIN" worktree add --detach "$WT" HEAD >/dev/null 2>&1 || { echo WT_FAIL; exit 9; }
git -C "$WT" status --porcelain # 应为空
"$PY" "$WT/scripts/archive/id_gate/check_ids.py" 2>&1 | tail -25 # ← TODO 口径:以 .pre-commit-config.yaml 里 id-check 钩子的 entry/args 为准;基线与注入用**同一条命令**
"$PY" "$WT/scripts/archive/id_gate/check_ids.py" 2>&1 | tail -25 # ← 口径:id-check 钩子已于 2026-10-28 退役(脚本移入 scripts/archive/id_gate/),按该脚本自身默认参数跑;基线与注入用**同一条命令**
```
- `--detach`(**不要 `-b`**):净室没有分支、不写 `_wt/.state/<ID>.json` 台账 → **不占 `MAX_CONCURRENT = 3`
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -63,7 +63,7 @@ git commit
> **2026-10-23 迁移**:原本节 27 个"逐钩子详解"小节,已全部迁往 `docs/门禁说明/`——**每种门禁
> 一篇**,八段固定结构(查什么 / 为什么要它 / 触发面 / 报错怎么读 / 好处 / **限制与盲区** /
> 豁免与基线口径 / 改门禁本身)。40 个 hook 的总览与"三种拦截姿态" → `docs/门禁说明/README.md`。
> 豁免与基线口径 / 改门禁本身)。当时 40 个 hook 的总览与"三种拦截姿态" → `docs/门禁说明/README.md`。
> 搬走的原因:只写"拦了什么"的文档会让人以为绿就是对的,而"什么时候会骗人"必须有归处。
> 同一事实只在一处详述(`docs/文档规范.md` 同此要求),所以本节不再重复逐钩子表格。
@@ -88,7 +88,7 @@ git commit
| 机制 | 口径 |
|---|---|
| **两个阶段** | pre-commit 阶段 **49** 个钩子 + commit-msg 阶段 `gitlint`(口径 = YAML 解析后的 hook 条目数 **50** 减去 gitlint;自查命令与「声明 / 文档 / 实跑」三数同源核对 → `docs/门禁说明/README.md` §2);`default_install_hook_types: [pre-commit, commit-msg]` 是显式声明的——换机后 `pre-commit install` 才会带上 commit-msg 钩子 |
| **两个阶段** | pre-commit 阶段 **50** 个钩子 + commit-msg 阶段 `gitlint`(口径 = YAML 解析后的 hook 条目数 **51** 减去 gitlint;自查命令与「声明 / 文档 / 实跑」三数同源核对 → `docs/门禁说明/README.md` §2);`default_install_hook_types: [pre-commit, commit-msg]` 是显式声明的——换机后 `pre-commit install` 才会带上 commit-msg 钩子 |
| **一根钩子在输出里出现两次** | 未声明 `stages:` 的钩子**默认属于所有阶段**,pre-commit 与 commit-msg 两遍都会列出它;第二遍的"文件"是提交信息文件,几乎必然 `(no files to check)Skipped`。**只看输出结尾会把"实跑通过"读成"没跑"**——判某钩子跑没跑要认它**第一次**出现的那行(实测 2026-10-24:只改 `.pre-commit-config.yaml` 的提交里 `test-coverage` 与 `bsp-err` 都是 Passed,尾巴那一遍是 Skipped) |
| **stash 陷阱** | pre-commit 跑钩子前会 stash 未暂存改动,钩子看到的是"没有你中间状态"的树。**改代码 + 同时更新基线/受管区的,必须先 `git add` 再跑钩子**,否则会拿到假报警(本仓踩过,`docs/门禁说明/bsp-err.md` §4 记了现场)。**它藏不住什么,见下一行** |
| **stash 覆盖面:只覆盖已跟踪文件的未暂存改动**(2026-10-26 读源码定案,**对所有钩子通用**) | 机制在 pre-commit 的 `staged_files_only._unstaged_changes_cleared()`:`git diff-index <tree>` 取补丁 → `git checkout -- .` → 跑完 `git apply` 还原。所以「钩子实跑 = 只看到 HEAD + 本笔 staged」这句**对已跟踪文件成立、对未跟踪文件不成立**:未跟踪文件压根不在 `diff-index` 里,**不会被藏**;`git add -N`(intent-to-add)也救不了——pre-commit 只 `git rm --cached` 把它撤下索引(`_intent_to_add_cleared()`),**文件本体仍在盘上**。后果:别人写了尚未入库的文件(新页面实例 / 新单测目录 / 新文档)躺在树里时,**任何一笔碰到该文件所属钩子 `files:` 的提交都会被这份半成品拖红**——红的内容没错,但账不该记在这笔提交上。实测:`ui_page_clock.c`、`ui_page_reset.c` 处于未跟踪且未绑 `#page` 期间,`generated-fresh` 对**所有人**的 UI 提交都会 FAIL(现场日志 `docs/门禁说明/generated-fresh.md` §6 第 8 条)。三条结论:① 提交排序——会让全树变红的半成品要么先落地(绑引用 + 重跑生成器)要么先挪出工作树;② 凡「判定基准取工作区」的钩子(重跑比对类、全库统计类)在多人同树下必须配**静默窗口**;③ 真要 `--no-verify` 抢跑,正文必须点名是哪几个**未跟踪**文件拖的红,别让它被读成「钩子不可信」 |
@@ -326,7 +326,7 @@ $env:PATH = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Env
| 文件 | 位置 | 说明 |
|---|---|---|
| `.pre-commit-config.yaml` | 仓库根 | 钩子配置(**50 个钩子**;口径 = YAML 解析后的 hook 条目数,自查命令 → `docs/门禁说明/README.md` §2。原写「40 个,2026-10-24 清点」是当时的快照数、之后加钩子没同步——正是 §2.2 计数口径行要避免的事)。逐项详解在 `docs/门禁说明/`(索引 `docs/门禁说明/README.md`;主机侧单测 **22 根**合一篇,含各套件来历与「18 套无专属钩子」台账 `docs/门禁说明/host-unit-tests.md` §6;UI 侧另有 `font-charset` 与 `ui-golden` 两篇——后者此前**在旧手册里连小节都没有**,只活在配置注释里,本次补齐) |
| `.pre-commit-config.yaml` | 仓库根 | 钩子配置(**51 个钩子**;口径 = YAML 解析后的 hook 条目数,自查命令 → `docs/门禁说明/README.md` §2。原写「40 个,2026-10-24 清点」是当时的快照数、之后加钩子没同步——正是 §2.2 计数口径行要避免的事)。2026-10-28 复核 = 51:同日 51 → 52(加 id-check-new)、随即 52 → 51(退役 id-check),一增一减写成当日一行的两个阶段、净零。逐项详解在 `docs/门禁说明/`(索引 `docs/门禁说明/README.md`;主机侧单测 **22 根**合一篇,含各套件来历与「18 套无专属钩子」台账 `docs/门禁说明/host-unit-tests.md` §6;UI 侧另有 `font-charset` 与 `ui-golden` 两篇——后者此前**在旧手册里连小节都没有**,只活在配置注释里,本次补齐) |
| `.gitlint` | 仓库根 | gitlint 规则(宽松,兼容中文) |
| `.cubemx_survival_baseline.json` | 仓库根 | CubeMX 易失定制基线(哈希;`--write` 重建) |
| `scripts/check_mojibake.py` | scripts/ | U+FFFD 检测脚本 |
@@ -533,7 +533,7 @@ flowchart LR
> [`../CI/远程CI完整指南.md`](../CI/远程CI完整指南.md) §0.0。
> 🔴 **`gitlint` 属 `commit-msg` stage,`--all-files` 永远跑不到它(2026-10-11 审计)**:
> `.pre-commit-config.yaml` 定义 **18** 个钩子,而 CI 日志只报 **17** 个(`passed=16 skipped=1`)——
> `.pre-commit-config.yaml` 当时定义 **18** 个钩子,而 CI 日志只报 **17** 个(`passed=16 skipped=1`)——
> 缺的正是 gitlint。即"单行中文标题 ≤100 字符"这条门禁**本地有、CI 无**,且表现为**全绿**
> 而非失败,所以长期无人发现。现由 CI 侧 **`scripts/ci_gitlint_range.ps1`**(PR 用 `base..head`、
> push 用 `event.before..sha`、跳过 merge 提交)与本地 `ci_local.py` 的 **提交信息门禁** 段分别逐条校验。
@@ -646,3 +646,4 @@ CI 就静默停摆(2026-10-11 实测 run 16~21 共 12 个 job 零日志)。
| 2026-10-26 | 三层断言表同步 UI 三页落地后的真值:像素层 **27 → 40 内容页**、文本层 **242 → 310 条(覆盖 37 页)**;上方变更记录里的 27 / 242 属当日事实,保留不动 |
| 2026-10-27 | 三层断言表的像素层计数同步真值:**40 → 47 内容页**(判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 47 张 + `check_content_pages.py` 的 `PAGES` 47 项);文本层 310 条 / 覆盖 37 页仍是 2026-10-26 实跑口径,未随新增页重测,留待下次实跑回填;本条只加新行,历史行 27 → 40 原样保留 |
| 2026-10-27 | 三层断言表的像素层计数同步真值:**47 → 53 内容页**(判据 = `simulator/tests/ref/` 入库 `shot_*.bin` 实数 53;6 张新增是通讯设置页六态,`31ca4a1f..HEAD` 对 ref 目录只有 6 个 A、零 M)|
| 2026-10-28 | §9.1 那条 2026-10-11 审计里的钩子数(定义 18 / 只报 17 / 其中跳过 1)加「当时」二字锁死口径,不臆改成现值:本轮同步钩子计数实测口径 = YAML 解析条目 **51**,静态门禁实跑 **50** 条 + 提交信息门禁 1 条 = 51(三数同源),自查命令 → `docs/门禁说明/README.md` §2 |
@@ -19,7 +19,7 @@ Python 环境、以及 `docs/任务规划/` 这类**全局唯一登记簿**都
**做法**:每个任务一棵 `git worktree` + 一条任务分支,任务之间物理隔离;干完由固定命令合回主干。
**范围**:只解决「开发期隔离 + 回收期合并」的机械流程。**不改变**既有的分支纪律
(push 需许可)、门禁口径(pre-commit 30 钩子 + `@build` + `@test`)与文档约定。
(push 需许可)、门禁口径(pre-commit 51 钩子 + `@build` + `@test`)与文档约定。
---
@@ -406,7 +406,7 @@ docs\内存管理\RAM使用分析与优化方案.md:585 [路径引用] docs/内
| 主题 | 去处 |
|---|---|
| 提交门禁 40 个钩子 | `docs/代码规范/pre-commit使用说明.md` |
| 提交门禁 51 个钩子 | `docs/代码规范/pre-commit使用说明.md` |
| 自动化测试与台架流程 | `docs/测试说明/自动化测试流程.md` |
| 文档写作规范(编码/链接/登记) | `docs/文档规范.md` |
| 工具路径环境变量(换机) | `docs/环境与部署/本地工具路径环境变量方案.md` |
+6 -5
View File
@@ -12,10 +12,11 @@
2026-10-28:51 → 52 加 `id-check-new`、随即 52 → 51 摘掉 `id-check`(退役全库语料审计))。
⚠ **别用 `grep -c` 去数配置里的声明行**:该文件里有一条**注释掉的**候选钩子(clang-format,第 65 行),
文本 grep 会多算 1 = 52——「声明 52 / 文档 51 / 实跑 51」这种三个数不同源的争执就是这么来的。真要 grep,
用只认行首缩进的模式直接数是 52(含那一条注释掉的候选,故与 YAML 口径差 1)。
用**锚定行首缩进**的模式(它天然跳过以 # 开头的注释行)2026-10-28 实测直接得 **51**,与 YAML 口径一致;
会多算 1 = 52 的是**不锚定行首、按子串**匹配声明行的写法(那条被注释掉的候选也被它算进去)。
⚠ 反过来的坑也真踩过(2026-10-27):在配置**注释里复述那个 grep 字面量**,会让文本 grep 再虚高 1——
数数只认 YAML 解析,注释与文档里都别写出那个字面量(`docs/门禁说明/nested-comment.md` §8 记了现场)。
实跑侧口径:`scripts/ci_local.py` 的 `[SUMMARY] 静态门禁: pre-commit hooks -- passed=A failed=B skipped=C`,
实跑侧口径:`scripts/ci_local.py` 的静态门禁汇总行 `[SUMMARY] …: pre-commit hooks -- passed=A failed=B skipped=C`(方括号里那一段是**层级名**,脚本输出与文档层的语义名正分头迁移 → 抓这行**按 `passed=` 字段匹配**,别把层级名前缀写死进字面量,否则会 grep 不到而误判「没有实跑数」),
`A+B+C` = **commit 阶段**的钩子数(50),再加 `gitlint` 1 条(它的 commit-msg 阶段声明写在**上游**仓库自带的
钩子清单里,本配置文件里查不到,见 `scripts/ci_local.py` 文件头)→ 50 + 1 = 51 = 声明数,三数同源。
- 通用机制(两阶段、stash 陷阱、`always` 已废、增量拦截三段式、旧 §2.x 查号表):
@@ -27,7 +28,7 @@
| 姿态 | 含义 | 有哪些 | 失败时该做什么 |
|---|---|---|---|
| **改写型** | 不报错,直接改你的文件 | `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`、16 个主机单测、官方 5 个、`gitlint` | 只能改代码或改文档;**不要**找豁免开关 |
| **硬拦截** | 违反即失败,没有存量豁免 | `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` | 改成语义短语,或把设备名/协议名登记进脚本白名单(行内 `[编号豁免]` 是最后手段) |
@@ -56,7 +57,7 @@
| [`cubemx-survival.md`](cubemx-survival.md) | `cubemx-survival` | CubeMX 重生成会不会把定制静默抹掉(人工目检审计兜底) | `.ioc`、`Src/`、`Inc/` | 已写 |
| [`test-suite-switch.md`](test-suite-switch.md) | `test-suite-switch` | 板级套件开关必须互斥;全注释 = 产品构建 | `test/board/test_config.h` | 已写 |
| [`font-charset.md`](font-charset.md) | `font-charset` | UI 用到的汉字是否都在子集字体里(缺字 = 白框) | `Drivers/BSP/UI/**`、字体脚本 | 已写 |
| [`ui-golden.md`](ui-golden.md) | `ui-golden` | UI 像素回归:菜单 8 状态 + 内容页 60 页黄金参考图比对 | UI 源码、模拟器 | 已写 |
| [`ui-golden.md`](ui-golden.md) | `ui-golden` | UI 像素回归:菜单 8 状态 + 内容页 60 张黄金参考图比对 | UI 源码、模拟器 | 已写 |
| [`bom-guard.md`](bom-guard.md) | `bom-guard` | 带 BOM 的文件被编辑工具剥掉 BOM(ARMCC 换解码 → 假语法错) | `Drivers/BSP/UI/**` 等名单内文件 | 已写 |
| [`setview-check.md`](setview-check.md) | `setview-check` | 定值查看行表与 `prot_set` 枚举序 / `g_prot_set_meta` 上下限是否同一份口径 | `tools/setview_check/**`、`ui_w_setview.*` | 已写 |
| (专篇待补,档位与限度正文在 [`../UI设计/UI_自动化测试流程.md`](../UI设计/UI_自动化测试流程.md) §7.3) | `uinav-selftest` | 板端 UI 导航器认屏快检(黄金参考帧分类;完整闭环档=合入前/上板前手工跑,快检不互替) | `scripts/board_ui_nav.py`、`simulator/tests/ref/*.bin` | 指针 |
@@ -82,7 +83,7 @@
## 4. 现状与下一步
- **本目录 27 篇已全部成文**(2026-10-27 实测口径:`docs/门禁说明/` 下除 README 外 27 篇,与上表「文档」列
- **本目录 28 篇已全部成文**(2026-10-27 实测当时 27 篇;2026-10-28 复核:`docs/门禁说明/` 下除 README 外 28 篇,与上表「文档」列
**一一对应**——「有页无行」与「有行无页」两个差集都是空集;一行覆盖多个 hook 的行(`cppcheck`+`test-cppcheck`、
22 个 `*-unit-test`)按行内列举计。上一句写「23 篇」是存量误差:2026-10-25 连加 `bom-guard` /
`setview-check` / `uinav-selftest` 三根、本轮加 `generated-fresh` 都没同步它(本轮前实有 25 篇)。
+2 -1
View File
@@ -27,7 +27,7 @@
## 3. 触发面 / 看不见什么
- `git commit`、`--amend`、`-F`、合并生成的提交都会跑;**`--no-verify` 连它和其它 39 个钩子一起跳过**。
- `git commit`、`--amend`、`-F`、合并生成的提交都会跑;**`--no-verify` 连它和其它 50 个钩子一起跳过**。
- 不校验:提交说明与 diff 是否相符、是否真的构建/测试过、是否夹带无关改动、是否该拆成多笔。
## 4. 报错怎么读
@@ -69,3 +69,4 @@ gitlint..............................................................Failed
| 日期 | 变更 |
|---|---|
| 2026-10-23 | 首篇逐项文档(生效值:标题 100 / 正文行 ≤80 / `body-is-missing` 已忽略) |
| 2026-10-28 | 同步 §3 漏网面计数:`--no-verify` 跳过的「其它钩子」39 → **50**。口径 = `.pre-commit-config.yaml` 经 YAML 解析出的 **51** 条减去 `gitlint` 自身(当日 51 → 52 加 `id-check-new`、随即 52 → 51 退役 `id-check`,一增一减净零);39 是上一轮加钩子时漏同步的快照数 |
+2 -2
View File
@@ -75,7 +75,7 @@
> `docs/测试说明/相量层单元测试说明.md`、`docs/测试说明/卷锁单元测试说明.md`、
> `docs/测试说明/时间同步单元测试说明.md`;
> harness 用法见 [`common/README.md`](common/README.md)。
> 已挂 pre-commit 钩子(各模块同名 `*-unit-test`,共 **16** 个;逐个说明见
> 已挂 pre-commit 钩子(各模块同名 `*-unit-test`,共 **22** 个;逐个说明见
> `docs/代码规范/pre-commit使用说明.md` §2 与 AGENTS.md 门禁条)。
### nand_port —— dhara NAND 移植层为什么能在 PC 上测
@@ -137,7 +137,7 @@
- **PYTHONPATH/路径敏感**:脚本按仓库根相对路径读写,**从仓库根执行**
- 本目录**被 pre-commit 门禁的 cppcheck / 代码规范排除**(`test/` 豁免);
但各模块的 `run_unit_test.py` 自身**作为独立钩子**参与门禁(见上,共 16 个)
但各模块的 `run_unit_test.py` 自身**作为独立钩子**参与门禁(见上,共 22 个)
- 台架探针族分工(2026-10-13 起):**自愈/Trap 常备回归腿在本目录**(`relisten_stress` /
`ftp_abort_probe` / `n30_repro` / `e02_probe` / `e6_soak` 等);`MDK-ARM/*.py` 只余被文档**当作
可信判据引用过**的三件(`ftp_freeze_probe` / `tcp_reconnect_probe` / `bench_verdict`)——