Files
STM32F4-Base/docs/编号规范.md
T
wandering1 0f7b5a87fb 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%。
2026-10-26 12:28:14 +08:00

17 KiB
Raw Blame History

编号规范:默认不用编号

一句话:能把事实写清楚,就别发号。 全项目允许使用「字母+数字」编号的族只有 8 个(§4.1), 它们的共同点只有一个——有脚本按字面量匹配它。除此之外,一律写语义短语(§3.3)。

这条不是洁癖:规划 / 待办 / 审计 / 差距 / 阶段这些给人看的东西,历史上全发过号,也全都变成了 没人认得的代号。2026-10-26 一天清了两批 + 本文瘦身,编号字面量 10,956 → 8,230 处(§8.1),清掉的号里 绝大多数从来没被任何脚本读过一次。沿革与教训留在 §8.3 与 git log,正文不复述。

机器面才是事实源:族注册表 scripts/id_registry.json、旧号别名 scripts/id_aliases.json、 门禁 scripts/check_ids.py(八项校验,详解 docs/门禁说明/id-check.md)。本文与机器面冲突时 以机器面为准,并回来改本文。


1. 决定要不要发号之前,先问三句

问自己 答"否"的结论
有脚本 / CI / 回归测试要按这个字面量做匹配吗? 不发号,写语义短语(§3.3)
现有文档或登记表里已经能指代这件事吗? 引用它,别再发第二个号指同一件事
一年后别人还能在属主登记表查到它的定义吗? 查不到就别发——"先记着,以后再说"是编号失控的唯一来源

三条硬规矩(对确实要发的号):

  • 号不承载语义:严重度、优先级、模块名、轮次都不写进号里。事实一变,号就开始撒谎。
  • 号不回收、不复用:销项 = 删登记行 + 清掉所有引用 + 别名表标 void(§5.5)。历史上"销掉的号被 重新取走"撞过两次。
  • 引用必须带语义:号旁边要有人话,裸号不许独担信息(读者不该被迫查表才看懂一句话)。

1.2 这四类事故就是上面三条的由来

  1. 同一字母多义:P1 五义、L1 四义、U1 四义、D7 与元器件位号同形 → 前缀必须按事物类别 分配(§2)。
  2. 属主文档一删,号全体成孤儿:审计报告删除后,全仓几百处引用再也查不到定义 → 号越少,这种 "集体失效"的爆炸半径越小(§4.5)。
  3. 语义塞进号里:条目事后降级,改号则引用全断、不改则号实不符 → 号不承载语义(P-2)。
  4. 销项号被复用:登记簿删行后仓库里毫无痕迹,下一个条目顺手取走同号 → 不回收、不复用, 改用语义标识(短语自带唯一性)。

2. 八条设计原则(一句话版)

P-8 语义优先压过其余七条:给人看的条目一律不发号。其余七条只在"确实要发号"时生效—— P-1 前缀 = 事物类别(不是来源文档 / 审计轮次)· P-2 号不承载语义 · P-3 一个事实一个号 · P-4 规范形态唯一(连字符与补零不承载语义,写法只许一种)· P-5 只增不复用,新增先取游标 · P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语义、引用必语义。


3. 三种指代方式,按这个顺序挑

优先 方式 用在
① 最好 语义短语 规划 / 待办 / 缺陷 / 风险 / 决策 / 差距 / 文档内步骤与阶段——默认形态
② 其次 文档名 + 章节号 指某篇文档的某节(docs/网络/网络自愈架构设计.md §4.10,紧邻写法)
③ 最后 编号 只有 §4.1 那 8 个族,且必须能反查到定义

3.1 判定口诀

机器读 → 发号;人读 → 写短语。 拿不准就写短语:短语看不懂还能靠上下文猜,号看不懂只能去查表。

3.2 编号 vs 章节引用

章节引用不是编号,但同样要紧邻文档名——只写「§ + 小节号」而不写文档名,会被 doc-links 当成本文自引用而静默放过, 这是它的已知盲区,别踩。

3.3 语义标识(默认形态,怎么写)

  • 一行短语就是标识:≤20 汉字、说清"是什么事"、同一登记表内不撞名(同义异写算撞名)。
  • 好的例子:双转换器无共同采样触发、FTP 鉴权、写回缓存空闲 flush、L5 队列往返基线待重验。 坏的例子:优化项 3、遗留问题、重要缺陷——换个上下文就指代不明,等于又造了个号。
  • 登记处就是那张表:表首格写短语,不要再配一个字母号;跨文档引用写成 `docs/任务规划/登记簿.md` 「双转换器无共同采样触发」,同篇后续直接用短语。
  • 文档内的实施步骤 / 测试阶段 / 设计原则条目写中文:「步骤 3」「阶段 7」「DMA 边界安全」, 不写 S3 / TM-PHY-01 / DP-03 这种号。

4. 编号空间

4.1 允许用号的族(穷举——这张表以外一律不许发号)

族 形态 属主登记处(定义在哪查) 为什么必须是号
TC-* TC-<模块码>-<序号> docs/测试说明/*_Test_Guide.md、test/host/<模块>/*(代码即登记处) 用例↔断言双向追溯,要进 C 断言标签
TRAP-* TRAP-<域>-<nn> docs/问题记录/*_Trap_Records.md 踩坑证词的永久锚点,代码注释反查
L<n>-<nn> 保护功能号 docs/算法/继电保护功能复现规划.md 全库唯一"定义与引用都齐"的样板族
F-<MOD>-<nn> 功能项 docs/网络/网络自愈架构设计.md 代码注释按号回指设计条目
FR-* 需求 docs/产品需求/产品需求设计文档.md §5 需求↔测试追溯
CODE-RULE-<nn> 代码规范条款 scripts/check_coding_standard.py 门禁按条款号报错并统计存量
MENU-STATE-<nn> UI 状态机键 simulator/tests/check_menu_rows.py 像素回归脚本按它取状态行
P-<n> 本文的设计原则 本文 §2 就是本文自己的条目
  • 新增族的唯一正当条件:有脚本要按字面量匹配它。顺序固定:先改 id_registry.json(含属主登记处) → 再写属主文档 → 最后才允许在别处引用。反过来做必然造出悬空号。
  • 模块码是既定缩写,事实源 = registry 的族 pattern 与属主文档标题行,别自创(§6)。

4.1.1 已停发的族(别再指,更别再"复用"这些号)

停发族 现在怎么写 旧号去哪查
登记簿 N-x / S-x / T-x、专项 A-x、已删报告的 UI 簇 U1~U5(2026-10-26 方案 B) 语义短语——登记簿表首格本身就是短语,如「双转换器无共同采样触发」「CI 远端闭环未验证」 scripts/id_aliases.json 标 retired-to-phrase
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 等) 同上,写事实 无定义,本就不该存在

想知道某个号还活着吗:跑 scripts/check_ids.py --top 0,或直接查 id_aliases.json——命中 void / retired-to-phrase 就是死号。看到查不到的号,正确动作是删号留事实,不是补一个定义。

4.2 目标前缀(作废)

2026-10-26 删除:那批"改名后才启用"的前缀族从未有属主登记处,留着只会把读者带到一张不存在的登记表前。

4.3 冻结前缀(历史快照,正文不回改)

族还在注册表里、但属主登记处已删的:只为让冻结历史行不报"未登记前缀"而保留登记,游标一律冻结, 不得新增、不得复用。

4.4 这些不是编号——别顺手清,也别当门禁漏洞

元器件位号 U1/C12/R3/L5/D7(硬件语料按目录整体排除)、数学与协议记号(N-1、测频的正序与 负序分量 S1/S2、SHA-256、RS-485、ADC1_IN14、手册页码)、活表代号 E0~E19(网络自愈 §5.2, 无连字符,与死号 E-nn 只差一个连字符)、Socket 状态组合 U1~U15(网络自愈 §1.1)、档位词 P0~P3。 判据只有一条:带连字符、且能在属主登记表查到定义才叫编号;查不到的就是普通文本,不是"漏登记的号"。

4.5 已删报告的自有族

《项目审查与优化建议报告》2026-10-25 已删除,它自造的六族随之失去定义,且与登记簿同字母不同义。 看到"报告 N-16"这类写法一律按死号处理:删号留事实——各条目原本指向的设计文档就是现在的出处。


5. 分配、引用、销项

5.1 新增编号

先过 §1 三问。确实要发号:① 在 id_registry.json 确认族与游标 ② 在属主登记处写定义行 ③ 才允许在 别处引用。没有属主登记处的号不许存在——门禁的校验 3 就是照这句实现的。

5.3 代码注释

优先写短语(FTP 鉴权、监听生命周期模块化),别写字母号;确需引用活号时必须带属主文档名。 规划 / 待办类编号禁止出现在代码里——代码的寿命比任何一张待办表都长,待办表改了行,注释就成了 永久的假引用(本仓实测:196 处这样的死引用,全是这么攒出来的)。

5.5 销项与归档

删登记行 + 同步清掉全仓引用(清引用是销项的一部分,不是"以后再说")+ 别名表标 void。 冻结的历史(变更记录行、[示例] / [计划] 行)不回改,门禁对它们已豁免。

5.7 语义标识的登记与别名

短语就是登记处的行名,不需要别名表;**只有"号转短语"**时才在别名表留一条 retired-to-phrase, note 写清短语,方便把残留引用找干净。


6. 模块码表

TC 与 TRAP 共用模块码。唯一事实源是 scripts/id_registry.json 的族 pattern 与属主文档标题行; 本文故意不再抄一份——抄一份就多一处会过期的地方(历史上这张表就长期与代码不同步)。 要加模块码:先改 registry,再在属主文档出现,最后才在别处引用。

7. 改号与迁移

7.1 映射规则(作废)

"按审计报告把某族整体迁到另一族"那套映射已作废。2026-10-26 的实测结论是:绝大多数号该删不该迁。

7.2 孤儿编号处置(已完成)

代码有号、文档无号那批已按同一口径处理完:能对上属主表的补模块码,对不上的删号留事实; 绝不为了少报孤儿而凭空补定义行(那等于把账做平、把问题藏起来)。

7.3 改号操作规程(要动号就照这个走,一步都别省)

  1. 走 scripts/rename_ids.py:映射表驱动、显式 scope、默认干跑、自动写别名条目; 绝不全局查找替换——同一裸形字面量可能同属多个族(实测 S3 三义),全局替换等于造新撞号。
  2. 改完复核所有识别面:check_ids.py 与 check_test_traceability.py 的候选正则上界都要还能匹配新 形态;判据是"编号字面量总数有没有真的变小"(曾经因为正则上界太窄,改完号静默隐形 339 个)。
  3. 逐号做语义复核,不能只看 dry-run 命中数:最阴的失效是"字面改对、意思改错"。
  4. 登记表 / 映射表类文件不得当引用语料,否则自家审计表里的旧形态会被判成新账。
  5. 收尾重打台账 --prune-backlog(只减不增),并确认新错误级为 0。

8. 门禁:id-check(八项校验)

查什么、报错怎么读、盲区在哪——全在 docs/门禁说明/id-check.md,本文只留口径与基线。 八项校验一句话版:① 未登记前缀 ② 形态不合规(裸形 / 空格 / 中文 / 补零)③ 悬空引用 ④ 重复定义 ⑤ 冻结族越游标 ⑥ 编号未紧邻文档名 ⑦ 孤儿条目(告警)⑧ 可判定比例 + 两根护栏。

8.1 当前基线(2026-10-26 编号迁移批次后重打)

项 数值
扫描文件 / 编号字面量 754 个 / 8,230 处(两批清理前 10,956;本规范自己瘦身去掉 160 处 → 8,343,编号迁移批次再降到 8,230)
护栏 1:可判定比例下限 decidable_ratio_baseline 86.0%(实测 86.01%;容差 0.1pp,只许涨)
护栏 2:不可判定引用绝对数上限 undecidable_total_ceiling 1,166 处,只减不增(实跑 1,151 处)
校验 1/2/3/4/5/6 错误级 0;债务台账 0 条指纹 → --strict 实为全量拦截
告警 悬空 2(App/algo/freq.c 的正序 / 负序记号,属 §4.4 误判面)+ 孤儿 50(陷阱条目这类本就允许无人引用)

⚠ 读这些数字的口径:跨批次不可直接相减。方案 B 把"本可判定的引用"换成散文,分子分母同缩, 比例反而从 86.7% 掉到 85.98%,而不可判定绝对数一处没涨——所以同批加了护栏 2,并把比例基线 人工下调一次(工具按设计拒绝下调,必须留书面理由,见 docs/门禁说明/id-check.md §7.6);本规范瘦身后比例回到 86.0%, 护栏 2 也顺手从 1,192 收紧到 1,166。 以后判断"编号有没有变坏"看绝对数,不看比值:号只许越清越少,新增没登记的号一定被护栏 2 拦住。

8.3 改号与清号批次(只留要点)

2026-10-21 五批统一改名(陷阱号归范、主机侧单测认代码为属主登记处、追溯器三档口径对齐); 2026-10-26 两批清号(A:删死号约 1,557 处文本实删;B:登记簿系 20 个号转语义短语约 418 处)。 逐批动机与影响只在 git log 与 scripts/rename_maps/,本文不维护流水账。要记住的只有两条教训: 门禁曾经把"政策上禁止回改的变更记录行"当活账拦提交;也曾经用比值当唯一护栏而惩罚清号动作本身 ——两处都在 2026-10-26 修掉了,别再往回改。

8.4 台账与 --strict

错误级问题按「文件 + 校验项 + 字面量 + 次数」记指纹进 scripts/id_known_backlog.json,--strict 只拦 台账之外的新账,台账只减不增。本批台账已还清到 0 条——从现在起任何一条新错误级问题都会当场 拦提交,别指望还有豁免面可钻。


9. 还剩什么(以及别再做什么)

剩下能被机器读到的号就是 §4.1 那 8 族。除此之外,"编号说明"这件事本身应该继续变薄:每多一个族, 就多一处需要有人记得它的地方;每多发一个号,就多一个将来没人敢删的字符串。要新增族之前,请把这张 只有 8 行的表当作反对你的第一手证据。

10. 速查

  • 看到一个不认识的号 → 先查 id_aliases.json 与属主登记表;查不到就删号留事实,不要补定义。
  • 想给待办 / 缺陷 / 差距 / 风险发号 → 不许,写短语(§3.3)。
  • 想给文档内步骤或测试阶段发号 → 不许,写「步骤 3」「阶段 7」(§3.3)。
  • 想新增前缀族 → 先回答"哪个脚本要按字面量匹配它"(§4.1);答不出就别建。
  • 要改号 → scripts/rename_ids.py + §7.3 五步。
  • 门禁报错读不懂 → docs/门禁说明/id-check.md。

变更记录

日期 变更 说明
2026-10-26 编号治理收口:清死号 → 停发活号 → 本文重写为短版(用户三次裁定) 全仓字母+数字编号 10,956 → 8,230 处。① 清死号:属主登记处已删或从未启用的号一律就地删号留事实、禁补号(文本实删约 1,557 处)。② 停发活号:登记簿 N-x/S-x/T-x、专项 A-x、已删报告的 UI 簇 U1~U5 共 20 个号转成语义短语(约 418 处)——登记簿表首格就是短语,旧号进 scripts/id_aliases.json 标 retired-to-phrase;已销项的死号故意不进别名表,让门禁继续咬残留引用。③ 本文瘦身:619 行 → 229 行,删掉八原则长表、迁移映射表、模块码表与门禁细节(那些各有事实源:registry / 别名表 / docs/门禁说明/id-check.md),改成「先问三句再决定要不要发号」+ §4.1 允许用号的族穷举 = 8 个。④ 门禁配套:check_ids.py 加变更记录行豁免与第二根护栏 undecidable_total_ceiling(比值会被清号动作稀释,绝对数不会),债务台账还清到 0 条 → --strict 实为全量拦截,比例基线重打为 86.0%。本表按用户 2026-10-26 的明确指示只保留最近一条,更早沿革看 git log 与 docs/门禁说明/id-check.md §7.5(含其后的方案 B 一节);这是本文档的例外,不改变 §5.5对其他文档「冻结历史不回改」的约束。