chore(编号): 存量编号全量转语义短语,门禁识别面与语料同批重打

登记簿、文档与代码注释里的存量字母加数字编号(N-x / S-x / T-x / E-x / A-x / 卡号)
一律改写为语义短语,净删 2,028 处引用;删除基线与待确认、并行分道方案、排期详述、
采集保护收尾 4 篇(内容已并入 docs/任务规划/README 与登记簿)。

门禁机器与三张账同批重打:check_ids.py 新增变更记录行豁免与第二根护栏
undecidable_total_ceiling;check_test_traceability.py 只加 stdout/stderr UTF-8
reconfigure(TC_RE 未动);check_cubemx_survival.py 的 --write 固定 newline=LF;
id_registry / id_aliases(+19 条 retired-to-phrase)/ id_known_backlog 重打。

test/ 56 个文件同步 TC 标签语义化,其中 18 个 TU 改了 CHECK / printf 里的标签文字,
是本批唯一改变构建产物的文件集合。

为什么合成一笔、不拆四笔(实测撞闸,非偏好):pre-commit 跑钩子前会 stash 未 staged
部分,拆开后中间提交必然是「新规则 + 旧语料」——实跑可判定 85.15% < 基线 86.00%、
不可判定 1,453 > 上限 1,166,编号门禁直接拦下。编号识别面与它描述的语料只能同码移动。

实跑基线(工作区全量):754 文件 / 8,230 处编号字面量 / 可判定 7,079 = 86.01%
(基线 86.0%,容差 0.1pp)/ 不可判定绝对数 1,151(上限 1,166)/ 校验 1-6 错误级 0 /
告警 = 悬空 2(App/algo/freq.c 的 S2,属 §4.4 同号不同义)+ 孤儿 50。

基线从 84.0 抬到 86.0 的理由见 docs/门禁说明/id-check.md §7.6:本批真删了 2,028 处
引用,可判定面随真实内容上升,不是把分母做小。同批新增排除 docs/硬件平台/ 语料,使
识别面少 264 处——芯片手册位号与网表料号不属编号空间(registry 有 excluded_paths_note)。

⚠ 余量只剩 0.11pp(约 10 处)与绝对数 15 处:把「可判定的引用」改成散文会立刻撞第二
根护栏。另遗留一项:id_aliases 里 retired 的 N / S / T / A 别名没有 scope(U1~U5 有),
今后有人新写一个 A-4,校验 3 不会响,只能靠人,建议下批补 scope。

固件不变证据:115 个 .c/.h 剥注释并归一字符串后与 HEAD 逐字节全等,残留代码差异 0;
App / Src / Drivers 的字符串字面量零改动。@build 0 错误 0 警告;40/40 主机套件、2,889
断言全通过;覆盖率 line 89.2% / func 92.6%;pre-commit 48 钩子 --all-files 全绿;
check_doc_links --all 通过(176 文档,章节引用无法判定 0);逐字节卫生核过:14 个带
BOM 文件与 HEAD 一致、0 个 CR、0 个 U+FFFD,字符串字面量纯 ASCII。

.cubemx_survival_baseline.json 的 watchdog-module 哈希 56bf27 变 2bb051 属合法:
Src/freertos.c 的 USER CODE 区内只有注释文字随编号改写,代码未变。

同批带上体积同码凭证与 RAM 台账行(@build 之后盖戳):RW_IRAM1 79,008 B / 60.3%,
RW_CCM 57,376 B / 87.9%,阈值 92%。
This commit is contained in:
2026-10-26 12:28:14 +08:00
parent 7635480e06
commit 0f7b5a87fb
253 changed files with 2234 additions and 4541 deletions
+7 -7
View File
@@ -11,14 +11,14 @@
|---|---|---|
| `check_coding_standard.py` | `C coding standard` | C 代码规范机械检查(命名前缀/常量右置/头文件保护宏等) |
| `check_mojibake.py` | `Forbid U+FFFD mojibake` | 扫描 `U+FFFD` 乱码(`EF BF BD` 字节) |
| `check_doc_links.py` | `doc-links` | **文档链接存在性** + 命名规范(D-3/D-7)+ **`§N.M` 章节引用**(口径见 `docs/文档规范.md` §3.5)。钩子已带 `--sections-strict`(自引用失效也拦);`--section-todo` 列出机器判不了目标的 `§`(带改写建议)。每次跑打印「可判定比例」行,防覆盖率回落 |
| `check_doc_links.py` | `doc-links` | **文档链接存在性** + 命名规范 + **`§N.M` 章节引用**(口径见 `docs/文档规范.md` §3.5)。钩子已带 `--sections-strict`(自引用失效也拦);`--section-todo` 列出机器判不了目标的 `§`(带改写建议)。每次跑打印「可判定比例」行,防覆盖率回落 |
| `section_aliases.json` | (被 `check_doc_links.py` 读) | 文档**昵称别名表**:「内存方案」→ `docs/内存管理/RAM使用分析与优化方案.md`。只登记无歧义昵称;登记一次即把该昵称的引用纳入硬门禁 |
| `check_ids.py` | `id-check` | **编号门禁**:`docs/编号规范.md` §8 的八项校验(未登记前缀 / 形态 / 悬空 / 重复定义 / 越游标 / 未紧邻文档名 / 孤儿 / 可判定比例)。**已关闸为增量拦截**:钩子带 `--strict`,只拦 `scripts/id_known_backlog.json` 台账之外的新错误级问题(存量按指纹豁免、台账只减不增);可判定比例跌破基线任何模式都失败。详表(含限制与盲区)→ `docs/门禁说明/id-check.md` |
| `id_registry.json` | (被 `check_ids.py` 读) | 前缀族**注册表**:属主登记处 / 形态正则 / 冻结 / 游标,逐项来自 `docs/编号规范.md` §4;`decidable_ratio_baseline` = 校验 8 的基线(只许涨)。与 `section_aliases.json` 同一套"别名表 + 可判定比例"范式 |
| `id_aliases.json` | (被 `check_ids.py` 读) | 编号**别名/作废表**:旧字面量 → 现行字面量或 `status: void`(如 `N-32` 销项后仍被引用、`T-4` 随销项永久作废、模块码 `PHY→NET`) |
| `id_aliases.json` | (被 `check_ids.py` 读) | 编号**别名/作废表**:旧字面量 → 现行字面量或 `status: void`(如已销项的旧号仍被引用 → `status: void`、模块码 `PHY→NET`) |
| `check_test_traceability.py` | (被 `id-check` 顺带调用) | **TC 用例双向追溯**:文档 ↔ 代码两侧的 TC 编号集合比对;2026-10-20 起范围扩到 `test/host/` 与 7 篇「单元测试说明.md」(`--board-only` 回退旧板级口径)。此前该脚本**未挂任何钩子** |
| `gen_task_table.py` | `task-table` | FreeRTOS 任务表以 `Src/freertos.c` 为**唯一事实源**生成/校验(D-2/D-7) |
| `check_mem_numbers.py` | `mem-numbers` | 内存/Flash 数字以 `.map` 为唯一事实源校验(D-7 体积档) |
| `gen_task_table.py` | `task-table` | FreeRTOS 任务表以 `Src/freertos.c` 为**唯一事实源**生成/校验 |
| `check_mem_numbers.py` | `mem-numbers` | 内存/Flash 数字以 `.map` 为唯一事实源校验(体积档) |
| `check_test_suite.py` | `test-suite-switch` | 测试套件开关=产品构建(防测试固件静默提交) |
### 报告生成(非门禁)
@@ -37,12 +37,12 @@
> `check_doc_links.py` 除链接存在性外,还校验 **`§N.M` 章节引用**是否指向目标文档真实存在的编号标题(口径见 `docs/文档规范.md` §3.5)。
### CI 与本地等价(2026-10-01 T-6)
### CI 与本地等价(2026-10-01)
| 脚本 / 文件 | 作用 |
|---|---|
| `ci_local.py` | **本地跑与 CI 等价的门禁**(L0 pre-commit + L0b 提交信息 + **L0c 体积门禁** + L0.5 主机侧单测):自动选用装了 pre-commit 的解释器;无 `.map` 时自适应跳过 `mem-numbers` / `mem-budget`(⚠ 那是 SKIP 不是通过,缺口由 L0c 兜住);退出码 0/1/2 与 CI 对齐。CI 定义见 `../.gitea/workflows/ci.yml`,覆盖边界见 `docs/测试说明/测试开发标准流程.md` §9 |
| `check_size_gate.py` | **体积门禁的强制路径(A-5 残余)**:`.map` 只在本地有,钩子无它时自适应 SKIP,于是"没测=通过"。本脚本用**已提交的同码凭证** `scripts/size_attestation.json` 把这条判据变成无需 Keil 也能跑:`--stamp` 只在"`.map` 存在、比全部受管源码新、且未超 92%"时才盖章(已挂在 `ram_baseline.py --update` 里,无新增人工步骤);`--local` 供 ci_local 的 L0c 步;`--ci` 供 runner(同码性 + 按凭证数字复核红线,主干 push 拦红、其余事件 `--warn-only`);`--show` 排障。**口径与边界的唯一正文在本脚本模块 docstring** |
| `check_size_gate.py` | **体积门禁的强制路径**:`.map` 只在本地有,钩子无它时自适应 SKIP,于是"没测=通过"。本脚本用**已提交的同码凭证** `scripts/size_attestation.json` 把这条判据变成无需 Keil 也能跑:`--stamp` 只在"`.map` 存在、比全部受管源码新、且未超 92%"时才盖章(已挂在 `ram_baseline.py --update` 里,无新增人工步骤);`--local` 供 ci_local 的 L0c 步;`--ci` 供 runner(同码性 + 按凭证数字复核红线,主干 push 拦红、其余事件 `--warn-only`);`--show` 排障。**口径与边界的唯一正文在本脚本模块 docstring** |
| `size_attestation.json` | (被 `check_size_gate.py` 读写)体积同码凭证:受管源码指纹(`git ls-files` 范围内逐文件 sha256 聚合)+ 测量数字与占比 + `.map` 出处。改固件源码后不重测 → 指纹对不上 → L0c 与 CI 同时拦红 |
| `check_test_coverage.py` | 主机单测**覆盖率**(2026-10-23):mscoverage 动态插桩跑 `test/host/**` 全部 16 套,统计自研生产源码行/函数覆盖(并集)+ 与 `test_coverage_baseline.json` 比回退;`--module/--update-baseline/--md/--json/--list`;**不在 pre-commit 里**,入口是 `ci_local.py --coverage`(口径见 `docs/测试说明/主机单测覆盖率口径.md`) |
| `ci_gitlint_range.ps1` | CI 侧**提交信息门禁**:逐条校验本次 push/PR 引入的提交(`--all-files` 跑不到 `commit-msg` stage,故必须单独守) |
@@ -63,7 +63,7 @@
& '.venv\Scripts\python.exe' scripts/ci_local.py
& '.venv\Scripts\python.exe' scripts/ci_local.py --l0-only # 只跑 L0
& '.venv\Scripts\python.exe' scripts/ci_local.py --l05-only # 只跑 L0.5
& '.venv\Scripts\python.exe' scripts/ci_local.py --size-only # 只跑 L0c 体积门禁(A-5 强制路径)
& '.venv\Scripts\python.exe' scripts/ci_local.py --size-only # 只跑 L0c 体积门禁(强制路径)
& '.venv\Scripts\python.exe' scripts/check_size_gate.py --show # 体积同码凭证现状(0.3 s,无需 Keil)
& '.venv\Scripts\python.exe' scripts/check_size_gate.py --stamp # 用新鲜 .map 重新盖戳(--update 已自动带做)
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""BSP 错误码与超时命名约定检查(报告 S-5 的机械检查那一半)。
"""BSP 错误码与超时命名约定检查(机械检查那一半)。
为什么要有这个脚本:约定写在 docs 里不会自己生效。同一层的驱动今天并存六套返回约定,
而"能不能重试"只写在个别注释里;叫 *_TIMEOUT 的东西里既有真毫秒(单位靠不统一的 _MS 后缀表达)、
+2 -2
View File
@@ -142,7 +142,7 @@ CHECKS = [
hint="崩溃现场报告实现(打印 PC/LR/xPSR/CFSR/HFSR/BFAR/MMFAR)"
"须在 USER CODE BEGIN 0 区内(生成区内的标准保护位)。",
),
# N-20(2026-10-12):Error_Handler 统一降级。函数体本身在 CubeMX 的
# Error_Handler 统一降级(2026-10-12;详述见看门狗设计说明.md §4.4)。函数体本身在 CubeMX 的
# `USER CODE BEGIN/END Error_Handler_Debug` 区内(L2 受保护),重生成不丢;
# 本项是 L3 兜底:被打回模板默认(__disable_irq+while(1) 静默挂死)**不报编译错**,
# 只在真出外设初始化故障时暴露——整机只剩 IWDG 兜底且无自检日志。
@@ -592,7 +592,7 @@ def main():
print(" → 若是本次有意改动,确认无误后跑 `--write` 重建基线;")
if args.write:
with open(BASELINE, "w", encoding="utf-8") as f:
with open(BASELINE, "w", encoding="utf-8", newline="\n") as f:
json.dump(
{"snapshot": snap, "_note": "CubeMX 存活审计基线;改动用 --write 重建"},
f,
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
文档路径一致性 + 命名规范检查(D-3/D-6/D-7)。
文档路径一致性 + 命名规范检查。
由 pre-commit 调用:python scripts/check_doc_links.py <file...>,发现问题退出码 1。
检查三类:
+3 -3
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""check_font_charset.py - UI 字符集差集门禁(防"缺字显示白框",报告 §6.5 U4 残余)。
"""check_font_charset.py - UI 字符集差集门禁(防"缺字显示白框",原报告 §6.5 的 UI 字符集与像素回归门禁残余项)。
背景:
本工程唯一中文字体 `Drivers/BSP/UI/ui_font_cn_12.c` 是**子集**字体:只包含
@@ -9,7 +9,7 @@
`make_font.py` 的 `verify_coverage()` 只在**生成期**校验"txt ⊆ 字体 cmap";
若开发者改了 UI 字符串却忘了重跑 extract_cn / make_font,提交期**无任何门禁**
能拦住——缺字上机渲染为空白(白框),无日志无报错,只能靠肉眼截图发现。
本钩子把这条约定机械化(U4 三钩子之二,golden 已建、registration-check 见 §2.18)。
本钩子把这条约定机械化(UI 字符集与像素回归门禁三钩子之二,golden 已建、registration-check 见 §2.18)。
判定口径(两段链条,缺一环即白框):
A. 必需字符集(源码在用 ∪ KEEP_EXTRA 保留字) vs ui_cn_chars.txt
@@ -51,7 +51,7 @@
1 = 失败(存在白框方向的缺口:必需字不在 txt(含 KEEP_EXTRA 保留字被剔),或 txt 字不在字体;--strict 时未知冗余也算)
2 = 环境错误(字符集文件 / 字体文件 / 生成器脚本缺失)
创建日期:2026-10-15(U4 残余,报告 §6.5 / §7 交付物清单"字符集差集检查"行)
创建日期:2026-10-15(UI 字符集与像素回归门禁残余项,报告 §6.5 / §7 交付物清单"字符集差集检查"行)
"""
import argparse
+45 -3
View File
@@ -67,6 +67,18 @@ CAND_MOD = re.compile(r"(?<![\w./\\-])([A-Z][A-Z0-9]{0,3})-([A-Z][A-Z0-9]{0,9})-
CAND_HYPH = re.compile(r"(?<![\w./\\-])([A-Z][A-Z0-9]{0,3})-(\d{1,4}[A-Za-z]?)(?![\w-])")
CAND_BARE = re.compile(r"(?<![\w.\-/])([A-Z])(?:\.(\d))?(1[0-9]|[0-9])(?![\w.\-])")
# 变更记录行(表格首格是日期,或「(规划稿)」)= 冻结历史,不参与编号判定。
# 与 rename_ids.py / check_doc_links.py / check_test_traceability.py 同一条口径——此前只有
# 本脚本缺这条豁免,于是把「政策上禁止回改的历史行」(§5.5)当活账拦提交:2026-10-26 实测
# 36 处错误级 + 20 处告警全部来自历史行。豁免计数打印在案(skip_changelog),
# 不让它变成看不见的面分母缩水。
CHANGELOG_ROW = re.compile(
r"^\s*\|\s*(?:20\d\d-\d\d-\d\d|(规划稿))\s*\|"
# 另一类变更记录:首格是版本号、次格是日期(形如 | v1.6 | 2026-10-25 | …,实测见
# docs/子系统设计/控制台单写者日志设计说明.md 的附录表)。只认「版本号 + 日期」两格连排,
# 单独一个版本号不算——普通表格也可能拿版本号当首格(2026-10-26 方案 B 补)。
r'|^\s*\|\s*v\d+(?:\.\d+){1,2}\s*\|\s*(?:20\d\d-\d\d-\d\d|\d{4}-\d{2})\s*\|')
# 紧邻窗口(与 check_doc_links.py 的 SEC_MAX_GAP / SEC_GAP_CHARS 同口径)
ADJ_WINDOW = 60
# 第 8 项的容差(百分点):比例的分母随"这一批改了几篇文档"漂移,0.1pp 以内不算回退
@@ -200,7 +212,7 @@ class Checker(object):
continue
# 二进制工件整体跳过(2026-10-25 道F task-22:boot_log_data 的 gz 串口存档被
# read_text(errors=replace) 解出乱码流,随机字节拼出「字母-数字」形态伪编号(形态故不举
# 例,举例即入扫,见 docs/门禁说明/id-check.md §6 第 9 条),把无关存量顶成校验 1 新账。
# 例,举例即入扫,见 docs/门禁说明/id-check.md §6 第 10 条),把无关存量顶成校验 1 新账。
# gzip 魔数或头 2KB 含 NUL 即判二进制——
# 字节流没有编号语义,与 registry noise_literals/盲区豁免同一口径,不该进文本面。
# ⚠ 不是豁免策略:png 等既有二进制此前是"侥幸没撞上形态",现在才是按性质处理。
@@ -251,6 +263,11 @@ class Checker(object):
return any(rx.match(literal) for rx in self.noise)
def scan_line(self, rel, lineno, line):
if rel.endswith(".md") and CHANGELOG_ROW.match(line):
# 冻结历史行:形态/悬空/紧邻一律不判(口径同 [示例] / [计划],见 CHANGELOG_ROW 注释)
self.stats["skip_changelog"] += len(CAND_MOD.findall(line)) + len(CAND_HYPH.findall(line))
self._scan_malformed(rel, lineno, line, skip=True)
return
if "[示例]" in line or "[计划]" in line:
# 报错样例 / 尚未创建的条目:与 check_doc_links.py 共用同一套豁免约定(§5.2)
self.stats["skip_example"] += len(CAND_HYPH.findall(line))
@@ -602,10 +619,11 @@ class Checker(object):
for f in self.findings:
by_code[f.code].append(f)
print("=== 编号门禁 check_ids.py(docs/编号规范.md §8)===")
print("扫描 %d 个文件;编号字面量 %d 处(豁免 [示例]/[计划] 行 %d 处、"
print("扫描 %d 个文件;编号字面量 %d 处(豁免 [示例]/[计划] 行 %d 处、变更记录行 %d 处、"
"非编号噪声 %d 处、裸形盲区 %d 处、命中别名表 %d 处)"
% (self.stats["files"], self.stats["refs_total"], self.stats["skip_example"],
self.stats["noise_allowed"], self.stats["skip_bare_unmanaged"],
self.stats["skip_changelog"], self.stats["noise_allowed"],
self.stats["skip_bare_unmanaged"],
self.stats["alias_hits"]))
print("已声明的同号不同义族对(§4.3):%d 个字面量,不计入校验 4"
% self.stats["collision_allowed"])
@@ -647,6 +665,13 @@ class Checker(object):
"未建档" if base is None else "%.1f%%" % base, RATIO_TOL))
print(" 可判定 = 字面量落进已登记前缀族**且该族属主登记处已存在**;"
"未登记前缀、形态违规、属主登记处还是 [计划] 的都算不可判定 → 只许涨不许跌")
# 绝对数护栏(2026-10-26 方案 B 同批加):比值会被口径稀释——**删掉一批「本可判定」
# 的引用反而让比例下跌**(清号批次实测 -0.2pp),拿比值当唯一护栏等于惩罚清号。
# 不可判定引用的**绝对数**不受稀释影响:号只许越清越少,不会因分母变小而"变多"。
und_now = total - dec
ceil_now = self.reg.get("undecidable_total_ceiling")
print(" 不可判定引用绝对数 %d 处%s(只许减不许增;比值会骗人,绝对数不会)"
% (und_now, "(未设上限)" if ceil_now is None else ",上限 %d" % ceil_now))
return ratio, errs
@@ -775,6 +800,15 @@ def main():
# 基线**下取整到 0.1 个百分点**:小数点第 2 位随"这一批改了哪几篇文档"抖动,
# 用 round() 会把 82.34 进位成 82.3 再反过来把自己判死(实测踩过),故 floor。
reg["decidable_ratio_baseline"] = math.floor(ratio * 10) / 10.0
# 绝对数上限只许往下走(同一条「只朝好的方向」纪律);本次比上限高就拒绝,
# 免得有人拿 --update-baseline 给「号变多」开后门。
und_now = ck.stats["refs_total"] - ck.stats["decidable"]
ceil_old = reg.get("undecidable_total_ceiling")
if ceil_old is not None and und_now > ceil_old:
print("[ERR] 拒绝上调绝对数上限:本次不可判定 %d > 上限 %d"
% (und_now, ceil_old), file=sys.stderr)
return 1
reg["undecidable_total_ceiling"] = und_now
REGISTRY_FILE.write_text(json.dumps(reg, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8", newline="\n")
print("[OK] 基线已写进 scripts/id_registry.json:%.1f%%(本次实测 %.2f%%)"
@@ -803,6 +837,14 @@ def main():
print("\n[FAIL] 校验 8:可判定比例跌破基线 %.2f%% < %.2f%%(只许涨不许跌,容差 %.1fpp)"
% (ratio, base, RATIO_TOL))
return 1
# 绝对数护栏:与比值护栏同时生效,任一越线即失败(§8.1)。
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"
" → 要么把新增的号登记进属主文档 / 别名表,要么别加这个号"
% (und_now, ceil_now))
return 1
if err_total:
if args.strict:
led = load_backlog()
+1 -1
View File
@@ -44,7 +44,7 @@ ALLOW = {
}
# 存量基线(2026-10-22 清点 6 条,只减不增)。每条 = (引用方, 被引用的 App 头)。
# 修法是"注入/传参",不是把上层服务搬进 BSP——详见报告 §0.4 的 S-1 行。
# 修法是"注入/传参",不是把上层服务搬进 BSP。
# 2026-10-25 道B(task/UI-rec-reader)还清 UI 记录 3 条:ui_w_records 改注入式
# ui_rec_reader_t(契约 UI_数据供给设计说明.md §7.2),runlog/selftest/records.h
# 不再 include sys_log.h,绑定在 App/task/ui_task.c 与 simulator/main.c。
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""两份 lv_conf.h 特性子集一致性门禁(2026-10-11 加,随 F-1/F-2/F-3 落地)。
"""两份 lv_conf.h 特性子集一致性门禁(2026-10-11 加)。
背景:`Lib/lv_conf.h`(MCU)与 `simulator/lv_conf.h`(PC)是**两份独立文件**,
此前长期漂移——模拟器早已 I1-only,MCU 端却让 11 个 `LV_DRAW_SW_SUPPORT_*`、
+2 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
内存/Flash 数字一致性门禁(D-7 第三档:体积)。
内存/Flash 数字一致性门禁(体积档)。
问题
----
@@ -324,7 +324,7 @@ def scan_prose(text: str, stale, errors, path: pathlib.Path):
def main(argv):
ap = argparse.ArgumentParser(description="内存/Flash 数字一致性门禁(D-7 体积档)")
ap = argparse.ArgumentParser(description="内存/Flash 数字一致性门禁(体积档)")
g = ap.add_mutually_exclusive_group()
g.add_argument("--check", action="store_true", help="检查模式(默认)")
g.add_argument("--write", action="store_true", help="同步受管快照区")
+11 -11
View File
@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
"""check_registration.py - 双端注册反向校验门禁(纯标准库)。
背景(登记簿 N-23,出处审查报告 N-06 残余):
背景(登记簿条目「rs485_task 白名单缺口」):
本工程 Keil 工程与 PC 模拟器都用**显式文件列表**(无通配扫描)。新 `.c`
必须手动注册两处才会被编译:
① `MDK-ARM/STM32F407-Demo.uvprojx` 的 `<FilePath>` 条目(MCU 固件构建)
@@ -16,7 +16,7 @@
② 存在但未进 CMakeLists -> 模拟器不编译(**仅当该文件本应进模拟器时**才是缺口;
MCU-only 文件不进模拟器是**正确**的,见下方豁免)
③ 注册了但文件不存在(反向)-> 幽灵注册(改名/删除后残留的注册条目)
另对 UI 页面模块(U4 门禁补强,2026-10-15,报告 §6.5):
另对 UI 页面模块(UI 字符集与像素回归门禁补强,2026-10-15,报告 §6.5):
④ `Drivers/BSP/UI/ui_page_*.c` 定义了 `ui_page_<name>_desc`,但该符号在 UI 目录内
除自身 .c/.h 外无任何引用 -> 页面未接入
`ui_content_page.c` 的 `s_defs[]` 描述符表:两端**编译
@@ -29,12 +29,12 @@
模拟器只建模 **UI + 网络配置共享核心**;其余模块(MCU 驱动 / 固件任务 / 纯算法 /
CubeMX 生成层)**不进模拟器是设计事实**,模拟器另有 `_sim` 替身或根本无对应。
豁免用**显式清单 + 每行理由注释**(命名模式 `*_mcu.c` + 个别点名),
**不做整目录一刀切**(N-23 教训正是"目录级盲区")。唯一例外是 `Src/`:
**不做整目录一刀切**(这一项的教训正是"目录级盲区")。唯一例外是 `Src/`:
CubeMX 生成的外设初始化/中断/main,按构造即 MCU 专属、不可能有模拟器替身,
故整目录豁免(任务口径明确认可"Src/ 全部")。
已知缺口过渡(存量不拦、只对新缺口 FAIL):
`KNOWN_GAPS` 登记存量缺口(N-23 存量,Lead 处置中):命中 -> 打印 `[WARN]` 不拦;
`KNOWN_GAPS` 登记存量缺口(白名单存量,Lead 处置中):命中 -> 打印 `[WARN]` 不拦;
新出现的缺口 -> 打印 `[GAP]` 并 FAIL。`--strict` 关闭白名单(存量也 FAIL),供审计。
退出码:
@@ -46,7 +46,7 @@
& '.venv\\Scripts\\python.exe' scripts/check_registration.py
& '.venv\\Scripts\\python.exe' scripts/check_registration.py --strict
设计依据:docs/任务规划/登记簿.md N-23;.dsh/skills/new-source-file
设计依据:docs/任务规划/登记簿.md 条目「rs485_task 白名单缺口」;.dsh/skills/new-source-file
创建日期:2026-10-12
"""
@@ -138,10 +138,10 @@ SIM_EXEMPT = [
("Drivers/BSP/UI/ui_port.c", "MCU UI 端口层(显示/触摸硬件),模拟器另有 sim/sim_port.c"),
]
# --- 已知缺口白名单(存量,N-23,Lead 已处置)---
# --- 已知缺口白名单(存量,Lead 已处置)---
# 命中 -> WARN 不拦;新缺口 -> GAP FAIL。仅针对"存在但未注册"方向。
KNOWN_GAPS = {
"App/task/rs485_task.c": "E-59 门禁刻意未接线(B2 消费者就绪时随任务立项注册)",
"App/task/rs485_task.c": "RS-485 接线门禁(驱动契约未修完,随 B2 暂缓)",
}
@@ -250,7 +250,7 @@ def parse_cmake():
return sources
# --- UI 页面模块 → 描述符表接线(④,U4 门禁补强)---
# --- UI 页面模块 → 描述符表接线(④,UI 字符集与像素回归门禁补强)---
UI_DIR_REL = "Drivers/BSP/UI"
@@ -261,7 +261,7 @@ def check_ui_page_wiring():
(`ui_content_page.h` 枚举 + `ui_content_page.c` 的 `s_defs[]` 表)。漏了后者的页面
两端照常编译链接(desc 无引用 → 链接器剥离),①②③ 全绿但菜单打不开这一页。
判定:页面模块 = `ui_page_*.c` 中定义 `<stem>_desc =` 的文件(不定义 desc 的
`ui_page_*.c` 不是页面模块——未来 U3 生成的 `ui_page_registry.c` 承载表引用,
`ui_page_*.c` 不是页面模块——未来 UI 页面原型化生成的 `ui_page_registry.c` 承载表引用,
本规则依旧成立且不会把它误判为页面);引用面 = `Drivers/BSP/UI/` 下全部 .c/.h,
排除该页自身 .c/.h(自身头文件里的 extern 声明不算接线)。
"""
@@ -363,7 +363,7 @@ def main():
if not os.path.isfile(os.path.join(REPO_ROOT, f.replace("/", os.sep))):
gaps.append("[GAP] %s | 幽灵注册(CMakeLists)" % f)
# ④ UI 页面模块未接入描述符表(框架注册,U4;①②③ 照不出的盲区)
# ④ UI 页面模块未接入描述符表(框架注册,UI 字符集与像素回归门禁;①②③ 照不出的盲区)
ui_gaps, ui_pages = check_ui_page_wiring()
gaps.extend(ui_gaps)
@@ -380,7 +380,7 @@ def main():
print("结果: FAIL(%d 个新缺口/幽灵注册/页面未接线,%d 个存量 WARN)" % (len(gaps), len(warns)))
return 1
if warns:
print("结果: PASS(无新缺口;%d 个存量缺口已白名单 WARN,N-23 Lead 处置中)" % len(warns))
print("结果: PASS(无新缺口;%d 个存量缺口已白名单 WARN,白名单缺口由 Lead 处置中)" % len(warns))
return 0
print("结果: PASS(双端注册一致)")
return 0
+4 -4
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""体积门禁强制路径(A-5 残余,2026-10-25)。
"""体积门禁强制路径(2026-10-25)。
要消除的盲区
------------
@@ -61,7 +61,7 @@
python scripts/check_size_gate.py --ci [--warn-only]
python scripts/check_size_gate.py --show
设计依据:docs/任务规划/测试与架构专项.md(A-5 残余)、docs/CI/README.md。
设计依据:docs/任务规划/测试与架构专项.md、docs/CI/README.md。
创建日期:2026-10-25
"""
@@ -325,7 +325,7 @@ def _report(args, ci_mode, lines):
"""失败输出:CI 事件加 GHA 标注;--warn-only 降级为 0(非主干不拦)。"""
if ci_mode:
tag = "::warning::" if args.warn_only else "::error::"
print(tag + " 体积门禁未通过(A-5 强制路径)", file=sys.stderr)
print(tag + " 体积门禁未通过(强制路径)", file=sys.stderr)
for ln in lines:
print(ln, file=sys.stderr)
if args.warn_only:
@@ -439,7 +439,7 @@ def main(argv=None):
except Exception: # noqa: BLE001
pass
ap = argparse.ArgumentParser(
description="体积门禁强制路径(A-5 残余:同码凭证 + CI 红线复核)")
description="体积门禁强制路径(同码凭证 + CI 红线复核)")
g = ap.add_mutually_exclusive_group()
g.add_argument("--stamp", action="store_true", help="用新鲜 .map 盖同码戳(@build 后)")
g.add_argument("--local", action="store_true", help="本地/ci_local 自查:工作树须与测量同码")
+1 -1
View File
@@ -17,7 +17,7 @@ r"""
为什么要它(2026-10-23,W5 验证常态):
原评审报告 §4.8 记的两处空白之一(该报告 2026-10-25 已删除):无覆盖率口径——
L0.5 只回答“跑过哪些 TC”,回答不了“生产源码里哪些行根本没进过”。用例数与 TC 追溯率
会随时间上升,但覆盖率照的是另一类真相:**新增分支一行没测**(N-12/N-13 那类“读代码
会随时间上升,但覆盖率照的是另一类真相:**新增分支一行没测**(那类“读代码
才发现”的缺陷,覆盖率是最便宜的机器照法)。
工具链现实(2026-10-23 本机实测,换机必读):
+2 -2
View File
@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
"""check_test_suite.py - 测试套件开关门禁:防止测试固件被静默提交(纯标准库)。
背景(2026-10-01 测试架构评审 T-1,P0):
背景(2026-10-01 测试架构评审,P0):
`test/board/test_config.h` 的 `TEST_SUITE_*` 宏决定固件里编入哪个测试套件;
**全部注释 = 产品构建**。但该开关此前**没有任何门禁检查**——实测已提交的
HEAD 里 `TEST_SUITE_CH395F` 就是开启状态,`.map` 含 34 处 test 代码,
@@ -37,7 +37,7 @@
& '.venv\\Scripts\\python.exe' scripts/check_test_suite.py --allow-test-build
& '.venv\\Scripts\\python.exe' scripts/check_test_suite.py --file <路径>
设计依据:docs/任务规划/登记簿.md T-1;docs/测试说明/测试开发标准流程.md §3.1
设计依据:docs/任务规划/登记簿.md;docs/测试说明/测试开发标准流程.md §3.1
创建日期:2026-10-01
"""
+9 -2
View File
@@ -26,7 +26,7 @@
① 文档声明了、代码没有 → DOC-ONLY;
② 代码有、母号不在文档、**且号旁边没写人话意图** → CODE-ONLY(真未登记);
③ 代码有、靠"旁边有意图"放过 → 单独打印为 IN-CODE,**弱于文档**,不算已登记。
小写子项后缀(`TC-XXX-003b`)按母号算(`subitem_ok`),与编号门禁同口径。
小写子项后缀(`TC-<模块码>-003b` 这类小写尾号)按母号算(`subitem_ok`),与编号门禁同口径。
**批 6 再分两档**:硬件层人工用例(标题/章节含「(硬件层)」)记为 `BENCH`、文档已标未实现/待补/暂缓/已取消的记为 `NOTIMPL`,两者**单列示数**不进差异——但也不是「已覆盖」,只是「不该在这里期望代码」。
**2026-10-21 第二次口径修正(批 5)**:变更记录行与 `[示例]`/`[计划]` 行**不参与比对**
(冻结历史按编号规范 §8.1 不回改,旧号靠 `id_aliases.json` 解析;这条豁免另三支脚本早有,本脚本是最后缺它的一个,`DOC-ONLY` 因此 38 → 29、交集不变);被豁免的号存进 `frozen_ids`,`--verbose` 全量列出——**豁免不等于已对应**,别拿它当收敛。
@@ -48,6 +48,13 @@
import argparse
import re
import sys
# 控制台编码兜底:pre-commit / CI 之外的裸跑环境代码页常是 936(GBK),
# print 中文或 ⚠ 会抛 UnicodeEncodeError 让脚本带 traceback 以非零码死掉
# (同 check_ids.py / check_doc_links.py 的做法;2026-10-26 补齐,此前裸跑在第 245 行崩)。
for _stream in (sys.stdout, sys.stderr):
if hasattr(_stream, "reconfigure"):
_stream.reconfigure(encoding="utf-8", errors="replace")
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
@@ -58,7 +65,7 @@ DOC_DIR = REPO_ROOT / "docs" / "测试说明"
# 2026-10-20 收编进 id-check 门禁时补的三条(docs/编号规范.md §8「顺带收编」):
# ① 规范 §4.1 的合规形态 `TC-[A-Z]{1,4}-\d{3,4}[a-z]?`(带小写后缀,TC-NET-1502b);
# ② 现存的大写后缀形态(TC-AI-01A [示例],§7.1 待统一小写)也要能抓出来,否则整条漏扫;
# ③ 无模块码形态(iec104 的 TC-014/TC-104,§7.2 列为孤儿)纳入比对而不是静默忽略。
# ③ 无模块码形态(iec104 文档里缺模块码的那批用例号,§7.2 列为孤儿)纳入比对而不是静默忽略。
# ⚠ 模块码上界必须跟着 §6 模块码表走:批 2 单词化后码长可达 9 位(ADCHEALTH),
# 这里曾停在 {0,4},导致代码侧集合从 556 悄悄缩到 217——**同一批改名要复核所有
# 识别面,不止 check_ids.py**(2026-10-21 实测踩到)。
+1 -1
View File
@@ -10,7 +10,7 @@
作者:王建锋
创建日期:2026-10-20
修改记录:
2026-10-20 王建锋 创建(W6 U4 收尾:golden 入提交门禁)
2026-10-20 王建锋 创建(W6 UI 字符集与像素回归门禁收尾:golden 入提交门禁)
"""
import os
+10 -10
View File
@@ -2,14 +2,14 @@
# -*- coding: utf-8 -*-
"""ci_local.py - 本地一键跑"与 CI 等价"的门禁(纯标准库)。
为什么需要它(2026-10-01 T-6):
为什么需要它(2026-10-01):
CI(`.gitea/workflows/ci.yml`)只在 push / PR 时跑,且需要 Gitea Actions +
Windows runner 就绪。**提交前想自查、或 runner 还没配好时**,用本脚本在本地
跑同一套判定,命令与退出码与 CI 一一对应。
覆盖范围(与 CI 完全一致):
L0 静态门禁 = `pre-commit run --all-files` + 提交信息门禁(gitlint)
L0c 体积门禁(A-5 残余的强制路径,2026-10-25)= `scripts/check_size_gate.py --local`
L0c 体积门禁(强制路径,2026-10-25)= `scripts/check_size_gate.py --local`
**fail-closed**:没有体积同码凭证、或代码与测量不同码即红——不再"没跑=通过"。
CI 侧的「体积门禁」步跑的是同一条实现(那条无需 Keil,见 .gitea/workflows/ci.yml)。
L0.5 主机侧纯逻辑单测 = `test/host/**/run_unit_test.py`
@@ -36,7 +36,7 @@
1 = 有门禁/单测失败
2 = 环境错误(缺 pre-commit / python 模块等)
汇总行(S3,2026-10-02,对齐 CI 的 ::notice::):
汇总行(2026-10-02 起,对齐 CI 的 ::notice::):
[SUMMARY] L0: pre-commit hooks -- passed=N failed=M skipped=K
[SUMMARY] gitlint: N commit message(s) checked, M failed
[SUMMARY] L0.5: K runner(s), A/B assertions passed, fail=F
@@ -169,7 +169,7 @@ def _run(cmd, env=None):
def _run_capture(cmd, env=None):
"""跑子进程,输出**既直通终端又捕获**(对齐 CI 的 Tee-Object)。
返回 (退出码, 全部输出文本)。用于 L0.5 解析各模块汇总行(S3 汇总)。
返回 (退出码, 全部输出文本)。用于 L0.5 解析各模块汇总行。
"""
print("$ " + " ".join(str(c) for c in cmd))
cp = subprocess.run(cmd, cwd=str(REPO_ROOT), env=env,
@@ -291,11 +291,11 @@ def run_gitlint(count):
def run_size_gate():
"""L0c:体积门禁(A-5 残余的强制路径)。返回退出码(0/1/2)。
"""L0c:体积门禁(强制路径)。返回退出码(0/1/2)。
为什么必须单列一步(2026-10-25):`mem-numbers` / `mem-budget` 的事实源是 Keil
`.map`,无 `.map` 时两者**自适应 SKIP 并返回 0**——"改了代码但根本没编译"
这条最常见的漏测路径因此在本地也是绿的,CI 更是整根钩子都不跑。A-5 说的正是
这条最常见的漏测路径因此在本地也是绿的,CI 更是整根钩子都不跑。它要拦的正是
这个**"没跑 = 通过"**的盲区。
本步跑 `scripts/check_size_gate.py --local`,不需要 Keil:它校验**体积同码凭证**
@@ -305,7 +305,7 @@ def run_size_gate():
"""
print("")
print("=" * 64)
print(" L0c 体积门禁(A-5 残余:同码凭证 + 92% 红线,无需 Keil)")
print(" L0c 体积门禁(同码凭证 + 92% 红线,无需 Keil)")
print("=" * 64)
script = REPO_ROOT / "scripts" / "check_size_gate.py"
if not script.is_file():
@@ -409,7 +409,7 @@ def main(argv=None):
g.add_argument("--l0-only", action="store_true", help="只跑 L0 静态门禁")
g.add_argument("--l05-only", action="store_true", help="只跑 L0.5 主机侧单测")
g.add_argument("--size-only", action="store_true",
help="只跑 L0c 体积门禁(A-5 强制路径;约 0.3 s,无需 Keil)")
help="只跑 L0c 体积门禁(强制路径;约 0.3 s,无需 Keil)")
ap.add_argument("--coverage", action="store_true",
help="额外跑主机单测覆盖率(约 25 s;需 VS 代码覆盖率组件;默认不跑,CI 也不跑)")
ap.add_argument("--keep-going", action="store_true",
@@ -441,7 +441,7 @@ def main(argv=None):
return 2
rc = 0
# 实际跑过哪些段——收尾那行只报这些。理由与 A-5 同源且是同一类错误:
# 实际跑过哪些段——收尾那行只报这些。理由与那个盲区同源且是同一类错误:
# "--l05-only 却宣布 L0/L0b/L0c 全部通过"就是把没跑的说成跑过了(SKIP 冒充 PASS
# 的镜像版)。2026-10-25 做 task-10 时从 --l05-only 的输出里发现,当场改掉。
ran = []
@@ -456,7 +456,7 @@ def main(argv=None):
rc_msg = run_gitlint(args.commits)
ran.append("L0b")
# L0c 体积门禁同样**无条件照跑**:它回答的是"这份代码测过体积没有",
# 与 L0/L0b 的结论正交,且只要 0.3 s——少跑一次就是 A-5 那个盲区。
# 与 L0/L0b 的结论正交,且只要 0.3 s——少跑一次就是那个盲区。
rc_size = run_size_gate()
ran.append("L0c")
if rc != 0 or rc_msg != 0 or rc_size != 0:
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FreeRTOS 任务表一致性工具(D-2 / D-7)。
FreeRTOS 任务表一致性工具。
背景
----
+152
View File
@@ -3,6 +3,158 @@
"generated_from": "docs/编号规范.md §7 迁移映射 + §4.3 冻结前缀;本表只登记**仓库里已实际出现**的旧字面量 → 现行字面量,不做尚未落地的批量改写(§7.2 阶段 1 一律保留存量)",
"note": "旧号引用不因本表而改写:本表只让门禁把「旧号引用」判成可解析(校验 3 悬空引用 / 校验 4 重复定义)。批量改写属 §9 阶段 1,须逐批 dry-run + 三重复核(§7.3)。 带 scope 的条目只在所列文件内生效(同一裸形字面量可能属多族,全局别名会把真撞号洗成已解析)。",
"aliases": {
"N-3": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B(用户裁定:规划/待办类编号一律转语义标识):登记簿行保留、# 列改短语「L5 队列往返基线待重验」。旧号此后不得再指,引用侧已全部改写"
},
"N-16": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「网络负向场景台架验证」;旧号不得再指"
},
"N-18": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「双转换器无共同采样触发」(AGENTS.md 与采集链文档同批改写);旧号不得再指"
},
"N-23": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿「N-23 残余」行改短语「rs485_task 白名单缺口」;旧号不得再指"
},
"N-25": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「网络性能资源建议簇」;旧号不得再指"
},
"N-27": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「缩堆迁 CCM 后半(暂缓)」;mem-budget 钩子说明同批改写;旧号不得再指"
},
"N-28": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「uvprojx 空 TU 观察」;旧号不得再指"
},
"N-29": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「仓库体积膨胀观察」;旧号不得再指"
},
"N-30": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「relisten 沉降段原语化受阻」;原 resolved-in-place 条目由本条取代;旧号不得再指"
},
"S-3": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B 曾把登记簿该行的 # 列改成语义短语;同日晚些时候用户裁定**不做这项改造**、登记行已删除。旧号不得再指(与 MENU-STATE S3 旧号、代码规范条款旧号无关,那些条目带各自 scope)"
},
"S-4": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「dhara 重试自旋残留」;旧号不得再指"
},
"S-5": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「可选全序列卷锁」;旧号不得再指"
},
"T-7": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:登记簿 # 列改短语「CI 远端闭环未验证」;旧号不得再指"
},
"A-4": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:docs/任务规划/测试与架构专项.md 条目改短语「采集链路测试可验证性约束」;旧号不得再指"
},
"A-5": {
"to": null,
"status": "retired-to-phrase",
"note": "2026-10-26 方案 B:体积门禁 CI 强制路径条目改短语「体积门禁 CI 强制路径」;旧号不得再指"
},
"U1": {
"to": null,
"status": "retired-to-phrase",
"scope": [
"Drivers/BSP/UI/*",
"docs/UI设计/*",
"docs/任务规划/*",
"docs/子系统设计/看门狗设计说明.md",
"docs/代码规范/pre-commit使用说明.md",
"docs/门禁说明/*",
".pre-commit-config.yaml",
"docs/README.md",
"docs/产品需求/*",
"docs/网络/*",
"docs/测试说明/*",
"docs/架构设计/*",
"docs/内存管理/*",
"docs/CI/*",
"docs/子系统设计/*"
],
"note": "2026-10-26 方案 B:已删报告的 UI 标准化簇号 U1 → 短语「UI 设计令牌层」。**scope 限定**:同字面量在 docs/硬件平台 与 tools/netlist_semantics 是元器件位号,不受本条影响"
},
"U2": {
"to": null,
"status": "retired-to-phrase",
"scope": [
"Drivers/BSP/UI/*",
"docs/UI设计/*",
"docs/任务规划/*",
"docs/子系统设计/*",
"docs/代码规范/*",
"docs/门禁说明/*",
"docs/测试说明/*",
"test/*"
],
"note": "2026-10-26 方案 B:UI 标准化簇 U2 → 短语「记录页共享组件合并」;同字面量在硬件网表语境是位号"
},
"U3": {
"to": null,
"status": "retired-to-phrase",
"scope": [
"Drivers/BSP/UI/*",
"docs/UI设计/*",
"docs/任务规划/*",
"docs/子系统设计/*",
"docs/门禁说明/*",
"docs/测试说明/*"
],
"note": "2026-10-26 方案 B:UI 标准化簇 U3 → 短语「UI 页面原型化」;同字面量 `U3.14` 一类是位号(点号后缀),不在本条范围"
},
"U4": {
"to": null,
"status": "retired-to-phrase",
"scope": [
"Drivers/BSP/UI/*",
"docs/UI设计/*",
"docs/任务规划/*",
"docs/子系统设计/*",
"docs/代码规范/*",
"docs/门禁说明/*",
".pre-commit-config.yaml"
],
"note": "2026-10-26 方案 B:UI 标准化簇 U4 → 短语「UI 字符集与像素回归门禁」"
},
"U5": {
"to": null,
"status": "retired-to-phrase",
"scope": [
"Drivers/BSP/UI/*",
"docs/UI设计/*",
"docs/任务规划/*",
"docs/子系统设计/*",
"docs/门禁说明/*",
"docs/README.md"
],
"note": "2026-10-26 方案 B:UI 标准化簇 U5 → 短语「UI 剩余 21 叶页面落地」"
},
"N-31": {
"to": null,
"status": "void",
File diff suppressed because it is too large Load Diff
+95 -30
View File
@@ -1,7 +1,7 @@
{
"schema": 1,
"generated_from": "docs/编号规范.md §4 编号空间总表(§4.1 在册 / §4.2 目标 / §4.3 冻结 / §4.4 划界)+ §6 模块码表 + §7 迁移映射。游标取「规范记载值」与「全库实测最大号」的较大者,实测偏差一律写进 cursor_note,不凭印象编。",
"decidable_ratio_baseline": 84.0,
"decidable_ratio_baseline": 86.0,
"spec_docs": [
"docs/编号规范.md"
],
@@ -58,7 +58,8 @@
".dsh/n31_neg_inject_gen217.log",
".dsh/n31_neg_inject_gen221_form5.log",
"scripts/id_known_backlog.json",
"scripts/rename_maps/"
"scripts/rename_maps/",
"docs/硬件平台/"
],
"excluded_suffixes": [
".svg",
@@ -215,10 +216,11 @@
"frozen": false,
"cursor": "N-34",
"check_dangling": true,
"cursor_note": "规范 §4.1 记游标 N-34;实测登记簿现存至 N-30(N-31 曾于 2026-10-14 被复用撞号,见 docs/任务规划/README.md §0)→ 新条目一律改语义标识(P-8),实需编号才取 N-34",
"cursor_note": "2026-10-26 方案 B 停发:存量号已全部转语义短语(docs/编号规范.md §4.1.1),游标冻结不前进,旧号在 id_aliases.json 标 retired-to-phrase;本族登记只为冻结历史行不报未登记前缀",
"adjacent_cues": [
"登记簿"
]
],
"retired": "2026-10-26 方案 B 转语义短语"
},
{
"name": "S-LDG",
@@ -233,10 +235,11 @@
"frozen": true,
"cursor": "S-5",
"check_dangling": true,
"cursor_note": "现存 S-3/S-4/S-5;§7.1 之后不再新增 S 号",
"cursor_note": "2026-10-26 方案 B 停发:存量号已全部转语义短语(docs/编号规范.md §4.1.1),游标冻结不前进,旧号在 id_aliases.json 标 retired-to-phrase;本族登记只为冻结历史行不报未登记前缀",
"adjacent_cues": [
"登记簿"
]
],
"retired": "2026-10-26 方案 B 转语义短语"
},
{
"name": "T-LDG",
@@ -252,11 +255,12 @@
"frozen": true,
"cursor": "T-7",
"check_dangling": true,
"cursor_note": "现存 T-7(复审 T-1~T-5 见 docs/任务规划/测试与架构专项.md 卷首)",
"cursor_note": "2026-10-26 方案 B 停发:存量号已全部转语义短语(docs/编号规范.md §4.1.1),游标冻结不前进,旧号在 id_aliases.json 标 retired-to-phrase;本族登记只为冻结历史行不报未登记前缀",
"adjacent_cues": [
"登记簿",
"专项"
]
],
"retired": "2026-10-26 方案 B 转语义短语"
},
{
"name": "E-AUD",
@@ -338,7 +342,7 @@
"title": "待确认 / 开放问题(§4.2 规划类 → 语义标识)",
"pattern": "\\bOQ-[0-9]{1,3}\\b",
"owner_docs": [
"docs/任务规划/基线与待确认.md"
"docs/任务规划/登记簿.md"
],
"scope": "global",
"frozen": true,
@@ -351,7 +355,7 @@
"title": "里程碑目标形态 MS-<nn>(§4.2;存量 M1~M3)",
"pattern": "\\bMS-[0-9]{1,2}\\b",
"owner_docs": [
"docs/任务规划/采集保护收尾.md"
"docs/任务规划/登记簿.md"
],
"scope": "global",
"frozen": false,
@@ -688,8 +692,7 @@
"pattern": "\\bB[0-9]{1,2}\\b",
"owner_docs": [
"docs/任务规划/README.md",
"docs/任务规划/采集保护收尾.md",
"docs/任务规划/排期详述.md"
"docs/任务规划/登记簿.md"
],
"scope": "global",
"frozen": true,
@@ -713,8 +716,7 @@
"title": "结构债排期条目 C1~C6(§4.1 **2026-10-25 废止**,改语义名;存量仅作历史指称)",
"pattern": "\\bC[1-9]\\b",
"owner_docs": [
"docs/任务规划/README.md",
"docs/任务规划/排期详述.md"
"docs/任务规划/README.md"
],
"scope": "global",
"frozen": true,
@@ -735,8 +737,7 @@
"title": "验证窗口排期条目 D2~D7(§4.1 **2026-10-25 废止**,改语义名;存量仅作历史指称)",
"pattern": "\\bD[1-9]\\b",
"owner_docs": [
"docs/任务规划/README.md",
"docs/任务规划/排期详述.md"
"docs/任务规划/README.md"
],
"scope": "global",
"frozen": true,
@@ -757,7 +758,7 @@
"title": "里程碑 M1~M3(§4.2 目标 MS-<nn>;存量冻结)",
"pattern": "\\bM[1-3]\\b",
"owner_docs": [
"docs/任务规划/采集保护收尾.md",
"docs/任务规划/登记簿.md",
"docs/任务规划/README.md"
],
"scope": "global",
@@ -1073,11 +1074,12 @@
"cursor_owner_only": true,
"check_dangling": true,
"dangling_outside_owner": "warn",
"cursor_note": "「编号不随条目删除而回收」(专项文档卷首)→ 已销项的号再被引用即悬空;⚠ 与登记簿 S-3/S-4/S-5 同号不同义(§1.2),也与 CI 步骤号 S3、代码规范条款号 S3 同形 → 文档外只告警",
"cursor_note": "2026-10-26 方案 B 停发:存量号已全部转语义短语(docs/编号规范.md §4.1.1),游标冻结不前进,旧号在 id_aliases.json 标 retired-to-phrase;本族登记只为冻结历史行不报未登记前缀",
"adjacent_cues": [
"复审",
"专项"
]
],
"retired": "2026-10-26 方案 B 转语义短语"
},
{
"name": "A-REVIEW",
@@ -1091,11 +1093,12 @@
"frozen": true,
"cursor": "A-7",
"check_dangling": true,
"cursor_note": "现存 A-4/A-5 行,其余已销项(编号不回收)",
"cursor_note": "2026-10-26 方案 B 停发:存量号已全部转语义短语(docs/编号规范.md §4.1.1),游标冻结不前进,旧号在 id_aliases.json 标 retired-to-phrase;本族登记只为冻结历史行不报未登记前缀",
"adjacent_cues": [
"复审",
"专项"
]
],
"retired": "2026-10-26 方案 B 转语义短语"
},
{
"name": "T-REVIEW",
@@ -1113,7 +1116,9 @@
"复审",
"专项"
],
"collides_with": "N"
"collides_with": "N",
"cursor_note": "2026-10-26 方案 B 停发:存量号已全部转语义短语(docs/编号规范.md §4.1.1),游标冻结不前进,旧号在 id_aliases.json 标 retired-to-phrase;本族登记只为冻结历史行不报未登记前缀",
"retired": "2026-10-26 方案 B 转语义短语"
},
{
"name": "P-AUDIT",
@@ -1123,8 +1128,7 @@
"owner_docs": [
"docs/任务规划/README.md",
"docs/任务规划/测试与架构专项.md",
"docs/任务规划/登记簿.md",
"docs/任务规划/排期详述.md"
"docs/任务规划/登记簿.md"
],
"scope": "global",
"frozen": true,
@@ -1227,8 +1231,9 @@
"cursor_owner_only": true,
"check_dangling": false,
"dangling_note": "与 UI 状态机 U1~U15、位号 U17 三方同形(§4.4 位号目录已排除)→ 只拦越游标",
"cursor_note": "U1~U5 原见《项目审查与优化建议报告》§6.5(该报告 2026-10-25 已删除);现行排期见 docs/任务规划/README.md §2.0「UI 扩展」与 登记簿 U 簇行",
"owner_note": "属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除(用户裁定:内容大部分已闭环);登记职责与 26 行「号 → 现在详述于」对照表迁到 docs/编号规范.md §4.5,故 owner_docs 指向该节——它只用于**恢复可判定比例**(§4.5 是冻结存档登记处),定义集仍为空(snapshot_only 族剔除规范正文,见 check_ids.py 的 _def_owners),因此不参与悬空/撞号/裸形判定。未闭环项早已并轨到登记簿 N-19~N-29 + U 簇"
"cursor_note": "2026-10-26 方案 B 停发:存量号已全部转语义短语(docs/编号规范.md §4.1.1),游标冻结不前进,旧号在 id_aliases.json 标 retired-to-phrase;本族登记只为冻结历史行不报未登记前缀",
"owner_note": "属主文档 docs/问题记录/项目审查与优化建议报告.md 已于 2026-10-25 删除(用户裁定:内容大部分已闭环);登记职责与 26 行「号 → 现在详述于」对照表迁到 docs/编号规范.md §4.5,故 owner_docs 指向该节——它只用于**恢复可判定比例**(§4.5 是冻结存档登记处),定义集仍为空(snapshot_only 族剔除规范正文,见 check_ids.py 的 _def_owners),因此不参与悬空/撞号/裸形判定。未闭环项早已并轨到登记簿 N-19~N-29 + U 簇",
"retired": "2026-10-26 方案 B 转语义短语"
},
{
"name": "U-STATE",
@@ -1818,7 +1823,6 @@
"owner_note": "B 层口径(用户裁定 2026-10-21,同 TC-HOST-MEAS/TC-HOST-ADCCAL 先例;2026-10-25 道D 卡 10 建族):属主登记处 = 单测代码目录,不逐号补文档;路由顺序证据链在 TC-IEC104-029(test/host/iec104)",
"cursor_note": "游标按建族时实测最大号收录(2026-10-25):越界即视为未登记的冒号牌"
},
{
"name": "TC-HOST-IEC104",
"class": "TC",
@@ -1930,7 +1934,7 @@
"cursor_note": "游标按实测最大号收录(2026-10-23):越界即视为未登记的冒号牌"
},
{
"name": "TC-HOST-TC-HOST-LFTPIO",
"name": "TC-HOST-LFTPIO",
"class": "TC",
"title": "主机侧单测用例号:FTP 文件 IO 层与路径规范化(test/host/lftpd_io)",
"pattern": "\\bTC-LFTPIO-[0-9]{1,4}[a-z]?\\b",
@@ -1952,7 +1956,7 @@
"cursor_note": "游标按实测最大号收录(2026-10-23):越界即视为未登记的冒号牌"
},
{
"name": "TC-HOST-TC-HOST-LFTSTR",
"name": "TC-HOST-LFTSTR",
"class": "TC",
"title": "主机侧单测用例号:FTP 命令行字符串工具(同模块内)(test/host/lftpd_io)",
"pattern": "\\bTC-LFTSTR-[0-9]{1,4}[a-z]?\\b",
@@ -2146,5 +2150,66 @@
"owner_docs_exclude": [
"docs/测试说明/测试文档模板规范.md"
],
"designator_rule": "硬件语料位号识别:docs/硬件平台/ 与 docs/芯片手册/ 里匹配 ^[RCDJXUT][0-9]{1,3}$(无连字符)的字面量判为**位号**,不产生任何编号结论;不含 B(V0.0 网表报告的 B1 是真专项条目),带连字符的 D-7/N-18/TC-206 不受影响。机制在 check_ids.py 的 add() 里落地(统计键 designator_skipped)。**本目录仍未纳入扫描语料**:纳入前必须先把位号从可判定比例的 refs_total 里减掉,否则约 4200 处位号会把比例分母灌水、掩盖真实变化。 【批 9 扩展】同一规则再覆盖**引脚名/总线名/网名/区间**:^[A-Z]{2,3}[0-9]{1,2}(-[0-9]{1,2})?(如 PB12-15、PG0-15、PF13-15、DB0-15、OS0-2、KEY1-3、AIN1),同样不进 refs_total。带连字符的一字母形态(C-10 / A-9 / N-18 / D-7)与 TC-206 / TC1003 一律不受影响,仍照旧判。器件料号(FOC-817SC-F 被切成 FOC-817)**不做形状规则**:[A-Z]{3}-\\d{3} 与真家族 DEF-* 撞形,代价远大于收益,故留在台账 reason 里记账。"
"designator_rule": "硬件语料位号识别:docs/硬件平台/ 与 docs/芯片手册/ 里匹配 ^[RCDJXUT][0-9]{1,3}$(无连字符)的字面量判为**位号**,不产生任何编号结论;不含 B(V0.0 网表报告的 B1 是真专项条目),带连字符的 D-7/N-18/TC-206 不受影响。机制在 check_ids.py 的 add() 里落地(统计键 designator_skipped)。**本目录仍未纳入扫描语料**:纳入前必须先把位号从可判定比例的 refs_total 里减掉,否则约 4200 处位号会把比例分母灌水、掩盖真实变化。 【批 9 扩展】同一规则再覆盖**引脚名/总线名/网名/区间**:^[A-Z]{2,3}[0-9]{1,2}(-[0-9]{1,2})?(如 PB12-15、PG0-15、PF13-15、DB0-15、OS0-2、KEY1-3、AIN1),同样不进 refs_total。带连字符的一字母形态(C-10 / A-9 / N-18 / D-7)与 TC-206 / TC1003 一律不受影响,仍照旧判。器件料号(FOC-817SC-F 被切成 FOC-817)**不做形状规则**:[A-Z]{3}-\\d{3} 与真家族 DEF-* 撞形,代价远大于收益,故留在台账 reason 里记账。",
"excluded_paths_note": [
"docs/硬件平台/ :2026-10-26 补齐——规范 §8 一直写着排除,registry 却没写进去,导致位号与网表复核条目被扫成编号(实测报 28 处错误,其中校验 1 把器件型号 FOC-817、网表复核条目 C-1~C-10/A-10/A-11 全部当自造号)。位号识别仍保留作为第二道保险"
],
"cleared_2026_10_26": {
"note": "2026-10-26 清号批次:这些族的字面量已从活文档与代码注释中删除(属主登记处已删除或从未启用)。族定义保留在本文件里只有一个目的:让历史行、[示例]/[计划] 行与别名表不触发校验 1。不得新增引用;新增会被校验 3/5 拦下。可清单位:全仓零引用后可连族带别名一起删除。",
"families": [
"E-AUD",
"P-AUDIT",
"N-RPT",
"D-RPT",
"S-RPT",
"R-RPT",
"F-RPT",
"U-RPT",
"S-REVIEW",
"A-REVIEW",
"B-AUDIT",
"T-LDG",
"S-LDG",
"I-ORPHAN",
"WAVE-TASK",
"TM",
"DP-LEGACY",
"DP",
"H-GAP",
"L-GAP",
"GAP",
"DR",
"RC",
"MS-TGT",
"GEN",
"WI",
"OQ",
"RSK",
"SC",
"ST",
"CS",
"UL",
"LAT",
"DEF",
"PAT",
"TRAP-NOMOD",
"TC-NOMOD",
"TC-UPPER"
]
},
"retired_to_phrase_2026_10_26": {
"note": "用户裁定方案 B:规划/待办类编号(登记簿 N-x/S-x/T-x、专项 A-x、已删报告 UI 簇 U1~U5)一律转语义短语。族保留登记、游标冻结;引用侧同批改写约 418 处、字面量净减 443(8,946 → 8,503):活号 237 + 已销项死引用 196 + U 簇非位号约 45。短语表见 docs/编号规范.md §4.1.1。",
"families": [
"N",
"S-LDG",
"T-LDG",
"A-REVIEW",
"S-REVIEW",
"T-REVIEW",
"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(都只朝好的方向动)。",
"undecidable_total_ceiling": 1166,
"undecidable_ceiling_note": "不可判定引用绝对数上限(refs_total - decidable),只许减不许增;--update-baseline 同步下调且拒绝上调。加它的原因:比值会被清号动作稀释,绝对数不会。"
}
+7 -7
View File
@@ -1,14 +1,14 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
RAM 预算门禁 + 趋势台账(登记簿 N-27 前半 / 审查报告 §5.5 三件套,2026-10-12)。
RAM 预算门禁 + 趋势台账(登记簿条目「缩堆迁 CCM 后半(暂缓)」的台账/门禁那半 / 审查报告 §5.5 三件套,2026-10-12)。
三件套的机械部分收在本脚本(事实源 = Keil `.map`,与 `check_mem_numbers.py` 同口径):
1. **92% 阈值门禁**(`--gate`,pre-commit `mem-budget` 钩子入口):
RW_IRAM1 / RW_CCM 任一区占比 > 92% → FAIL,并附 Top-10 RW+ZI 对象表;
无 `.map`(未做 Keil 构建)→ 自适应跳过(与 `mem-numbers` 同口径,
CI 盲区登记在 `docs/任务规划/测试与架构专项.md` A-5 残余)。
CI 盲区登记在 `docs/任务规划/测试与架构专项.md`)。
`--gate` 同时校验台账受管区与 `.map` 一致(防漂移,同 `mem-numbers` 思路)。
2. **趋势基线** `scripts/ram_baseline.tsv`(`--update` 每次 @build 后追加一行;
`--trend` 看趋势并高亮 RW+ZI 较上一行增长 >1 KB 的对象——方案 §4.0.3
@@ -18,7 +18,7 @@ RAM 预算门禁 + 趋势台账(登记簿 N-27 前半 / 审查报告 §5.5 三
子系统配额(报告 §5.5 第 3 条的规划值;RTOS 堆 2026-10-12 B5 48→56 KB):
网络 12 KB / 存储 12 KB / UI 16 KB / RTOS 堆 56 KB / 应用 8 KB
——UI 配额是 R-9/R-2 落地后的**目标态**,现状超配 = W3 债务,台账如实展示;
——UI 配额是缩池与迁 CCM 落地后的**目标态**,现状超配 = W3 债务,台账如实展示;
配额改动 = 先登记 `docs/内存管理/RAM预算台账.md` 变更记录,再改本脚本 `QUOTAS`。
用法(仓库根):
@@ -28,7 +28,7 @@ RAM 预算门禁 + 趋势台账(登记簿 N-27 前半 / 审查报告 §5.5 三
python scripts/ram_baseline.py --trend [-n 10]
退出码:0 通过/跳过;1 门禁失败或受管区漂移;2 事实源解析失败。
创建日期:2026-10-12(W1-0,登记簿 N-27 前半)
创建日期:2026-10-12(登记簿条目「缩堆迁 CCM 后半(暂缓)」的台账/门禁那半)
"""
import argparse
import pathlib
@@ -175,7 +175,7 @@ def cmd_gate(args):
if map_path is None:
print("[SKIP] 无 .map(未做 Keil 构建)→ RAM 预算门禁不适用")
print(" ⚠ **SKIP 不等于 PASS**:本钩子这一趟什么都没检查。")
print(" A-5 残余的强制兜底(无需 Keil,改代码后必然拦红):")
print(" 强制兜底(无需 Keil,改代码后必然拦红):")
print(" 本地 scripts/ci_local.py 的 L0c 步 / CI 的「体积门禁」步,")
print(" 都跑 scripts/check_size_gate.py(同码凭证 + 92% 红线复核)。")
print(" 改过代码请先 @build,再 python scripts/ram_baseline.py --update。")
@@ -331,7 +331,7 @@ def cmd_update(args):
f"({region_pct(reg['RW_IRAM1']):.1f}%) / RW_CCM {reg['RW_CCM']['size']:,} B "
f"({region_pct(reg['RW_CCM']):.1f}%) → {TSV_PATH.relative_to(REPO_ROOT)}")
# A-5 残余(2026-10-25):同一次「真实测量」顺带刷新**体积同码凭证**
# 强制路径(2026-10-25):同一次「真实测量」顺带刷新**体积同码凭证**
# scripts/size_attestation.json——这样「每次 @build 后跑 --update」这条**既有
# 纪律**同时喂饱那条无需 Keil 也能判的强制门禁(check_size_gate --ci /
# --local,即 ci_local 的 L0c 步与 CI 的体积门禁步),不新增人工步骤。
@@ -411,7 +411,7 @@ def main(argv=None):
except Exception:
pass
ap = argparse.ArgumentParser(
description="RAM 预算门禁 + 趋势台账(N-27 前半 / 报告 §5.5 三件套)")
description="RAM 预算门禁 + 趋势台账(缩堆迁 CCM 暂缓项的台账/门禁 / 报告 §5.5 三件套)")
g = ap.add_mutually_exclusive_group()
g.add_argument("--gate", action="store_true", help="92% 阈值门禁(pre-commit 入口)")
g.add_argument("--write", action="store_true", help="同步台账受管区")
+1
View File
@@ -8,3 +8,4 @@ date code ro rw zi er_irom1 er_pct iram1 iram1_pct ccm ccm_pct top_rwzi
2026-10-23 213676 18860 1188 131500 232536 22.2 75264 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
2026-10-24 213780 18860 1204 131852 232640 22.2 75632 57.7 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4128;sys_log_mcu.o=3944;default_task.o=2736
2026-10-25 224860 24640 1332 135100 249500 23.8 79008 60.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4128;sys_log_mcu.o=3944;default_task.o=2736
2026-10-26 224860 24640 1332 135100 249500 23.8 79008 60.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4128;sys_log_mcu.o=3944;default_task.o=2736
1 date code ro rw zi er_irom1 er_pct iram1 iram1_pct ccm ccm_pct top_rwzi
8 2026-10-23 213676 18860 1188 131500 232536 22.2 75264 57.4 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4120;sys_log_mcu.o=3588;default_task.o=2736
9 2026-10-24 213780 18860 1204 131852 232640 22.2 75632 57.7 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6766;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4128;sys_log_mcu.o=3944;default_task.o=2736
10 2026-10-25 224860 24640 1332 135100 249500 23.8 79008 60.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4128;sys_log_mcu.o=3944;default_task.o=2736
11 2026-10-26 224860 24640 1332 135100 249500 23.8 79008 60.3 57376 87.9 heap_4.o=57376;lv_mem_core_builtin.o=16384;lftpd.o=7884;ui_net_sink.o=6770;ui_port.o=6420;nand_ftl.o=6216;ch395f.o=4162;console_log.o=4128;sys_log_mcu.o=3944;default_task.o=2736
+4 -4
View File
@@ -8,9 +8,9 @@
2. 改完必须自动登记 `scripts/id_aliases.json`(旧号 → 新号),否则历史提交正文与
未改写的文档里的旧号会集体变成"悬空引用"(§8 校验 3)——别名表是改名的**前置条件**,
不是可选项。
3. 同一个裸形字面量在不同文件里可能是**不同族**(实测 `S3` 既是代码规范条款、又是
3. 同一个裸形字面量在不同文件里可能是**不同族**(实测同一裸形既是代码规范条款、又是
UI 像素回归状态、又是 2026-10-02 复审专项条目)→ **改名与别名都必须限定作用域**,
全局替换会制造新的撞号(正是 §1.2 记录的 N-31/N-32 类事故)。
全局替换会制造新的撞号(正是 §1.2 记录的「销项号被重新取走」那类事故)。
用法:
& '.venv\\Scripts\\python.exe' scripts/rename_ids.py --map .dsh/rename_batch1.json # 干跑(默认)
@@ -89,7 +89,7 @@ def match_files(patterns, candidates):
def render(template, groups):
"""按模板渲染新号。**只有模板带格式说明符时**才把数字组转 int——
否则 `TC-PROTSET-011` 会被渲染成 `TC-PROTSET-11`(丢前导零,实测差点毁掉整批补零形态)。"""
否则 `TC-PROTSET-011` 会被渲染成丢前导零的形态(实测差点毁掉整批补零)。"""
vals = {}
for k, v in groups.items():
if v is None:
@@ -153,7 +153,7 @@ def merge_aliases(new_aliases, batch):
"""把本批 `旧号 → 新号` 并进 id_aliases.json,带 scope(同字面量多义的关键)。"""
doc = json.loads(ALIASES_FILE.read_text(encoding="utf-8"))
table = doc.setdefault("aliases", {})
# 已**完全限定**的字面量(如 `TC-PROTSET-011`)可以全局认别名;裸形(`S3`)必须带 scope
# 已**完全限定**的字面量(如 `TC-PROTSET-011`)可以全局认别名;裸形必须带 scope
scope = [] if batch.get("global_alias") else [norm(x) for x in batch.get("files", [])]
added = 0
for old, news in sorted(new_aliases.items()):
+4 -4
View File
@@ -1,15 +1,15 @@
{
"built_at": "2026-10-25T18:46:17+08:00",
"fingerprint": "101b6500c00ec55bba062c4141f5942479e329bba1b839be5d25be287751c228",
"built_at": "2026-10-26T12:21:03+08:00",
"fingerprint": "27086d0cd632d2443ff06d519183e4b9f748d08582c7e4f61b26b3d81ee0d312",
"fingerprint_files": 1422,
"fingerprint_source": "git-index",
"gated_regions": [
"RW_IRAM1",
"RW_CCM"
],
"git_head": "9d90e00d52bba74834c80f8fef483dc00e6f7507",
"git_head": "7635480e06f853fd27f1e48e059d71e59dca2165",
"map": "MDK-ARM/STM32F407-Demo/STM32F407-Demo.map",
"map_mtime": 1792925151,
"map_mtime": 1792982281,
"pct": {
"ER_IROM1": 23.79,
"RW_CCM": 87.89,
+1 -1
View File
@@ -5,7 +5,7 @@
判据口径出处(两处;改口径先改文档、再同步本脚本,自检断言会拦漂移):
- 「无源 vs 真停滞」判别:docs/子系统设计/控制台单写者日志设计说明.md 文末附录
(N-2 × S8 合并评估,2026-10-25)——静默段贴边(前一行 / 结束后一窗)命中
(日志静默观察项与单写者化的合并评估,2026-10-25)——静默段贴边(前一行 / 结束后一窗)命中
「丢弃账 / 故障账」留痕行 = 真停滞嫌疑;零命中 = 无源(系统安静,正常形态)。
- 开机良性豁免:docs/测试说明/实机测试实施指南.md §9 第 8 条——开机屏障期
(reset cause / armed / netTask: started 等锚点后一窗)偶见的单抽样 MISS start