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:
+15
-15
@@ -8,20 +8,20 @@
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(P3:段键表引擎 + net_cfg 集成)
|
||||
* v1.1 2026-09-18 王建锋 P0-1:临时缓冲改经 cfg_store_alloc(MCU = FreeRTOS 堆),
|
||||
* v1.1 2026-09-18 王建锋 临时缓冲改经 cfg_store_alloc(MCU = FreeRTOS 堆),
|
||||
* 移除对 C 库 malloc 的全部依赖(MicroLIB C 堆仅 512B,
|
||||
* 原 4 处 KB 级 malloc 真机必然失败);增编译期堆峰值预算
|
||||
* 校验 + 失败上报自检记录
|
||||
* v1.2 2026-09-21 王建锋 E-01(历史审计 P0,属主文档已删除):超长文件守卫根治——poll 判定
|
||||
* v1.2 2026-09-21 王建锋 超长文件守卫根治——poll 判定
|
||||
* 前置到 cfg_store_stat 真实 st.size(旧检查位于截断后的
|
||||
* len 上恒假=死码,超长文件被截断当有效解析 → 界外静默
|
||||
* 回工厂默认 → 基线粘住 → 用户配置销毁链);save 输出上限
|
||||
* 由 CFG_OUT_MAX 收紧至 CFG_FILE_MAX_LEN;s_write_doc 写盘
|
||||
* 唯一闸口拒写超长文档;load/poll 超长处置补自检留痕
|
||||
* v1.3 2026-10-04 王建锋 P2-1:受管键行超 CFG_LINE_TEST_MAX 时拒绝保存——
|
||||
* v1.3 2026-10-04 王建锋 受管键行超 CFG_LINE_TEST_MAX 时拒绝保存——
|
||||
* 原实现 Pass1 静默跳过超长行,Pass2 遂在段头补写新 KV 且
|
||||
* 原文超长行原样保留 → 同一键出现两行(旧值残留、静默截断)
|
||||
* v1.4 2026-10-15 王建锋 E-16(历史审计 P2,属主文档已删除):生成文档边界余量收口——
|
||||
* v1.4 2026-10-15 王建锋 生成文档边界余量收口——
|
||||
* s_gen_document 两处 `off += snprintf(...)` 改检查式(截断即
|
||||
* 返回 -1,不再跳过缓冲末尾);注册拒超长键名(≤ 15 字符),
|
||||
* 使每行 112 字节余量成为可编译期验证的前提
|
||||
@@ -29,7 +29,7 @@
|
||||
* len 1/2/4 小端补码)——s_decode_int() 用 strtol + ERANGE +
|
||||
* 宽度上下界校验,s_encode() 带负号输出;负零点偏移从此可
|
||||
* 干净落盘(动因见 docs/任务规划/数据可信.md §4.4 与 §7 决策 3)
|
||||
* 函数说明:引擎状态非重入——调用方须收敛同一任务(defaultTask:poll/save,见 P1-3;
|
||||
* 函数说明:引擎状态非重入——调用方须收敛同一任务(defaultTask:poll/save;
|
||||
* 启动期 load 先于任务竞争);FS 卷并发由 FatFS REENTRANT 卷锁保证
|
||||
* (见《配置文件设计说明》D15 A+ 方案)
|
||||
*/
|
||||
@@ -304,7 +304,7 @@ static int s_encode(const cfg_key_def_t *p_key, const uint8_t *p_src, char *p_ds
|
||||
case CFG_VAL_STR: {
|
||||
size_t slen;
|
||||
|
||||
/* P3-1:len==0 时 `p_key->len - 1u` 回绕为 SIZE_MAX → memcpy 巨长越界。
|
||||
/* len==0 时 `p_key->len - 1u` 回绕为 SIZE_MAX → memcpy 巨长越界。
|
||||
* STR 字段至少 1 字节(含结尾 NUL),len==0 非法,直接拒绝 */
|
||||
if (p_key->len == 0u) {
|
||||
return -1;
|
||||
@@ -619,7 +619,7 @@ static int s_load_file(uint8_t **p_pbuf, size_t *p_len) {
|
||||
* len - 数据长度 size_t
|
||||
* 返回值:0 - 成功;-1 - 写失败或超长拒写 int
|
||||
* 限定条件:p_buf 非空;len ≤ CFG_FILE_MAX_LEN
|
||||
* 函数说明:E-01 纵深防御——超长文档一旦落盘,下次开机 load 守卫即判损坏、
|
||||
* 函数说明:纵深防御——超长文档一旦落盘,下次开机 load 守卫即判损坏、
|
||||
* 整份用户配置连同注释/未知段销毁,故在唯一出口硬性拦截,使
|
||||
* "引擎永不产出超长 config.ini"成为结构性质(调用者新增路径免疫)
|
||||
*/
|
||||
@@ -923,7 +923,7 @@ static int s_surgical(char *p_in, size_t in_len, char *p_out, size_t out_cap, si
|
||||
* i_sec - 段索引 int
|
||||
* 返回值:1 - 是受管键;0 - 不是(无 '=' 或键名不匹配) int
|
||||
* 限定条件:仅比较 '=' 前的键名(大小写无关、剥尾部空白),不解析值
|
||||
* 函数说明:P2-1 用于"超长行是否落在受管键上"的判定(值可能很长,无法拷入定长缓冲);
|
||||
* 函数说明:用于"超长行是否落在受管键上"的判定(值可能很长,无法拷入定长缓冲);
|
||||
* 非修改式,故可安全用于仍供 Pass2 原样保留的行
|
||||
*/
|
||||
static int s_line_key_managed(const char *p_line, int i_sec) {
|
||||
@@ -969,9 +969,9 @@ static int s_line_key_managed(const char *p_line, int i_sec) {
|
||||
/*
|
||||
* 函数功能:保存 Pass 1——定位段头行号与各受管键行号
|
||||
* 入口参数:p_in - 原文本(可修改) char *
|
||||
* 返回值:0 - 成功;-1 - 受管键行超 CFG_LINE_TEST_MAX(拒绝保存,见 P2-1) int
|
||||
* 返回值:0 - 成功;-1 - 受管键行超 CFG_LINE_TEST_MAX(拒绝保存) int
|
||||
* 限定条件:行末被 NUL 化且不复原——调用方须传一次性副本
|
||||
* 函数说明:P2-1(2026-10-04):受管键行超过 CFG_LINE_TEST_MAX 时**不能**静默跳过
|
||||
* 函数说明:受管键行超过 CFG_LINE_TEST_MAX 时**不能**静默跳过
|
||||
* ——Pass2 会因该行未登记而在段头补写新 KV,同时原文超长行原样保留,导致
|
||||
* 同一键出现两行(旧值残留 + 新值,解析取谁取决于行序)。故此处显式拒绝:
|
||||
* 返回 -1,调用方中止保存、原文件不动、自检留痕。非受管键的超长行照旧跳过
|
||||
@@ -1033,7 +1033,7 @@ static int s_surgical_pass1(char *p_in) {
|
||||
}
|
||||
}
|
||||
else if (i_cur >= 0) {
|
||||
/* 超长行(> CFG_LINE_TEST_MAX):若其键名为本段受管键 → 拒绝保存(P2-1);
|
||||
/* 超长行(> CFG_LINE_TEST_MAX):若其键名为本段受管键 → 拒绝保存;
|
||||
* 否则按未知内容放过(Pass2 原样保留) */
|
||||
if (s_line_key_managed(p_line, i_cur) != 0) {
|
||||
return -1;
|
||||
@@ -1165,7 +1165,7 @@ int cfg_file_load(void) {
|
||||
}
|
||||
|
||||
if (st.size > CFG_FILE_MAX_LEN) {
|
||||
/* 文件超长 = 损坏:留工厂默认 + 重建模板(E-01:补自检留痕——销毁
|
||||
/* 文件超长 = 损坏:留工厂默认 + 重建模板(补自检留痕——销毁
|
||||
* 用户文件属重大事件,仅串口 DBG_ERROR 在现场无调试器时不可追溯) */
|
||||
if (s_write_template() != 0) {
|
||||
DBG_ERROR("load: corrupt file, template write FAIL");
|
||||
@@ -1254,7 +1254,7 @@ int cfg_file_save(void) {
|
||||
(void)memcpy(p_in1, p_in, in_len + 1u);
|
||||
|
||||
if (s_surgical_pass1((char *)p_in1) != 0) {
|
||||
/* P2-1:受管键行超 CFG_LINE_TEST_MAX → 中止保存(原文件不动)。此类超长行
|
||||
/* 受管键行超 CFG_LINE_TEST_MAX → 中止保存(原文件不动)。此类超长行
|
||||
* 只可能来自手工编辑(代码生成的受管 KV 行恒 <127B);若强行外科保存会
|
||||
* 产生重复键行,故宁可拒存并留痕,也不静默写坏。 */
|
||||
cfg_store_free(p_in1);
|
||||
@@ -1276,7 +1276,7 @@ int cfg_file_save(void) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* E-01:输出上限由 CFG_OUT_MAX(5120) 收紧至 CFG_FILE_MAX_LEN(4096)——
|
||||
/* 输出上限由 CFG_OUT_MAX(5120) 收紧至 CFG_FILE_MAX_LEN(4096)——
|
||||
* 旧上限允许把 >4096B 文档合法写盘(= 下一颗雷:下次开机 load 守卫
|
||||
* 判损坏、整份用户文件连同注释/未知段一起销毁)。超限走下方既有
|
||||
* 溢出中止路径:原文件不动 + 自检上报,RAM 副本保留(可修复后重试) */
|
||||
@@ -1342,7 +1342,7 @@ void cfg_file_poll(void) {
|
||||
{
|
||||
int i;
|
||||
|
||||
/* E-01(2026-09-21 审计 P0):超长守卫必须基于 cfg_store_stat 的真实
|
||||
/* 2026-09-21 审计 P0:超长守卫必须基于 cfg_store_stat 的真实
|
||||
* st.size 且先于 s_load_file——s_load_file 读长钉死 CFG_FILE_MAX_LEN
|
||||
* (nread ≤ 4096 恒成立),旧检查写在读后的 len 上恒假(死码):
|
||||
* 超长文件被截断当有效解析 → 界外段/键静默回工厂默认 → 基线粘住 →
|
||||
|
||||
+7
-7
@@ -8,12 +8,12 @@
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(P3:段键表引擎 + net_cfg 集成)
|
||||
* v1.1 2026-09-15 王建锋 属主任务由 netTask 改为 defaultTask(配置引擎单一属主,P1-3)
|
||||
* v1.2 2026-09-21 王建锋 E-01(历史审计 P0,属主文档已删除):超长守卫契约同步——poll 沉降
|
||||
* v1.1 2026-09-15 王建锋 属主任务由 netTask 改为 defaultTask(配置引擎单一属主)
|
||||
* v1.2 2026-09-21 王建锋 超长守卫契约同步——poll 沉降
|
||||
* 后先按真实 st.size 判超长(旧实现查截断后读长恒假)、
|
||||
* save 输出上限收紧至 CFG_FILE_MAX_LEN、写盘唯一闸口拒写
|
||||
* 超长;超长处置补自检留痕
|
||||
* v1.3 2026-10-15 王建锋 E-16(历史审计 P2,属主文档已删除):新增公开常量
|
||||
* v1.3 2026-10-15 王建锋 新增公开常量
|
||||
* CFG_FILE_MAX_NAME_LEN(段名/键名上限 15 字符)
|
||||
* v1.4 2026-10-25 DTU 项目组 数据可信卡 3:新增 CFG_VAL_INT 有符号十进制值类型
|
||||
* (len = 1/2/4,小端补码)——标定零点偏移等负值需有符号
|
||||
@@ -32,7 +32,7 @@ extern "C" {
|
||||
#include <stddef.h>
|
||||
|
||||
/* 配置文件长度上限(字节);超过 = 文件损坏,按出厂模板重建
|
||||
* (load 与 poll 同判,E-01:poll 在读取前基于真实 st.size 判定) */
|
||||
* (load 与 poll 同判:poll 在读取前基于真实 st.size 判定) */
|
||||
#define CFG_FILE_MAX_LEN 4096u
|
||||
|
||||
/* 引擎可注册段数上限 */
|
||||
@@ -103,7 +103,7 @@ int cfg_file_register(const cfg_section_reg_t *p_reg);
|
||||
* 2. 文件缺失 → 按当前 RAM 副本生成出厂模板写盘(首启建文件)
|
||||
* 3. 文件存在 → 解析:有效键写入 RAM 副本;无效键留工厂默认并留痕
|
||||
* 4. 文件超长(> CFG_FILE_MAX_LEN)= 损坏 → 工厂默认 + 重建模板
|
||||
* + 自检留痕(poll 检出运行期超长文件执行同一契约,E-01)
|
||||
* + 自检留痕(poll 检出运行期超长文件执行同一契约)
|
||||
*/
|
||||
int cfg_file_load(void);
|
||||
|
||||
@@ -116,7 +116,7 @@ int cfg_file_load(void);
|
||||
* 值原位改写,缺失段/键补写;文件缺失/损坏 → 按 RAM 副本重建
|
||||
* 完整文档(含文件头注释);写盘 = 临时文件 + 原子改名;输出超
|
||||
* CFG_FILE_MAX_LEN → 拒绝保存返回 -1(原文件不动 + 自检上报,
|
||||
* 引擎写盘闸口同拒,E-01)
|
||||
* 引擎写盘闸口同拒)
|
||||
*/
|
||||
int cfg_file_save(void);
|
||||
|
||||
@@ -129,7 +129,7 @@ int cfg_file_save(void);
|
||||
* 函数说明:(size, mtime 变更令牌) 相对基线变化且连续 CFG_FILE_SETTLE_CNT
|
||||
* 次轮询稳定 → 先查 st.size 超 CFG_FILE_MAX_LEN = 损坏 → 工厂默认
|
||||
* + 重建模板 + 自检留痕(不触发段回调:保留在线修复通道,重启
|
||||
* 收敛,E-01);否则重载全部段(各段复位工厂默认后解析);挂回调
|
||||
* 收敛);否则重载全部段(各段复位工厂默认后解析);挂回调
|
||||
* 段有差异 → 调用其回调(如触发网络重建);重载后刷新基线
|
||||
* (回调触发的写盘不引发二次重载)
|
||||
*/
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本
|
||||
* v1.1 2026-09-18 王建锋 增 cfg_store_alloc / cfg_store_free / cfg_store_heap_free:
|
||||
* 共享核心临时缓冲改走 FreeRTOS 堆(P0-1,MicroLIB C 堆仅 512B)
|
||||
* 共享核心临时缓冲改走 FreeRTOS 堆(MicroLIB C 堆仅 512B)
|
||||
* v1.2 2026-09-22 王建锋 原子写修复:rename 前先 unlink 已存在目标——本 FatFs
|
||||
* 移植 f_rename 不覆盖既有目标(FR_EXIST),旧实现一切
|
||||
* "目标存在的覆盖写"必然失败(E-01 台架验证暴露)
|
||||
* "目标存在的覆盖写"必然失败(台架验证暴露)
|
||||
* v1.3 2026-10-02 王建锋 四个后端函数纳入卷锁 try 语义(vol_lock_wait(0)):
|
||||
* 与 ftpTask 的 lftpd 文件操作互斥(并发 FTL 写 →
|
||||
* dhara journal 竞争实证);busy 返回 -1 由调用方
|
||||
@@ -22,7 +22,7 @@
|
||||
* FRESULT 里不存在的 FR_NO_SYSTEM,改成实际会返回的
|
||||
* FR_NOT_READY / FR_NO_FILESYSTEM 并写明"非 FR_OK 一律
|
||||
* 转 -1,不要枚举错误码集合"(无行为改动)
|
||||
* v1.4 2026-10-05 王建锋 原子写临时文件由 p_path 推导(P3-2):与目标同目录的
|
||||
* v1.4 2026-10-05 王建锋 原子写临时文件由 p_path 推导:与目标同目录的
|
||||
* 固定 8.3 名 config.TMP,不再硬编码卷根;目标恒为
|
||||
* "/config.ini" 时推导结果与旧值逐字节一致
|
||||
*/
|
||||
@@ -98,7 +98,7 @@ int cfg_store_read(const char *p_path, uint8_t *p_buf, size_t cap, size_t *p_nre
|
||||
#define CFG_STORE_TMP_PATH_MAX 24u
|
||||
|
||||
/*
|
||||
* 函数功能:由目标路径推导同目录的临时文件路径(P3-2)
|
||||
* 函数功能:由目标路径推导同目录的临时文件路径
|
||||
* 入口参数:p_path - 目标文件路径 const char *
|
||||
* p_out - 输出缓冲 char *
|
||||
* cap - 缓冲容量 size_t
|
||||
@@ -144,7 +144,7 @@ int cfg_store_write_atomic(const char *p_path, const uint8_t *p_buf, size_t len)
|
||||
if (p_buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
/* P3-2:临时文件由 p_path 推导(同目录 + 固定 8.3 名),不再硬编码卷根 */
|
||||
/* 临时文件由 p_path 推导(同目录 + 固定 8.3 名),不再硬编码卷根 */
|
||||
if (s_build_tmp_path(p_path, tmp_path, sizeof(tmp_path)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -165,7 +165,7 @@ int cfg_store_write_atomic(const char *p_path, const uint8_t *p_buf, size_t len)
|
||||
}
|
||||
/* 本 FatFs 移植的 f_rename 对已存在目标返回 FR_EXIST、不覆盖(ff.c
|
||||
* "new name already in use" 检查,上游同语义)——"目标存在的覆盖写"必须先
|
||||
* unlink 目标再 rename。2026-09-22 台架实证(E-01 验证暴露):缺本步时
|
||||
* unlink 目标再 rename。2026-09-22 台架实证:缺本步时
|
||||
* 一切非首启写(UI 保存/模板重建)静默失败,模拟器后端(POSIX rename
|
||||
* 覆盖语义)照不出。unlink→rename 非原子窗口掉电 = 配置文件暂失,
|
||||
* 开机 load 按"首启"重建工厂模板——与函数失败语义一致,丢失边界 =
|
||||
@@ -262,7 +262,7 @@ const char *cfg_store_tmp_path(void) {
|
||||
* 返回值:缓冲指针(内容未清零);失败返回 NULL void *
|
||||
* 限定条件:任务上下文调用(heap_4 内部临界区自护);释放必须用 cfg_store_free
|
||||
* 函数说明:MCU 端 MicroLIB C 堆仅 512B(startup Heap_Size=0x200),共享核心的 KB 级
|
||||
* 缓冲若走 C 库 malloc 必然返回 NULL,故统一由本接口取 FreeRTOS 堆(P0-1)
|
||||
* 缓冲若走 C 库 malloc 必然返回 NULL,故统一由本接口取 FreeRTOS 堆
|
||||
*/
|
||||
void *cfg_store_alloc(size_t size) {
|
||||
return pvPortMalloc(size);
|
||||
|
||||
Reference in New Issue
Block a user