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:
+45
-3
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user