Files
STM32F4-Base/.dsh/skills/mem-budget/reference/measurement-identity.md
T
wandering1 f08b12a46c docs(技能渐进展开): 五个技能正文逐字外置到 reference/,主文只留索引与指针
按「主文留头量、深规程外置」重写本仓技能,全部是逐字搬移:
搬移前断言原文每条非空行必须出现在新主文或 reference 文件里,
0 丢失才落盘;步骤编号一律不重排(正文有「第 12 步」交叉引用);
每个切点保留原小标题 + 索引(加粗引导句与步骤标题)+ 指针行。

主文变化(上限口径 = 插件写侧 65536 字节,见上一笔 skill-size 钩子):
- id-family-semantic-migration 33392 -> 10968(17%),reference 3 篇
- stale-doc-count-sweep 19811 -> 6945(11%),reference 2 篇
- mem-budget 19963 -> 13042(19%),reference 3 篇
- keil-build 12917 -> 8879(14%),reference 2 篇
- task-worktree 72601 -> 28139(42%),reference 8 篇

task-worktree 本笔同时收录另一会话已写完的 C2/D/G 三节正文——那
三处手改与我的拆分落在同一份文件改动里,不可分离;其内容同样已
随 reference/ 外置,主文只剩标题、索引与指针。

外置语料合计 122211 字节 / 30 篇:围栏数逐篇为偶,无 BOM/CR/U+FFFD。
draw-diagram 与 serial-boot-test 脚本是另一会话的在飞改动,本笔未含。

skill-size 钩子在本笔首次真跑(前一笔无 .dsh/skills 文件可触发)。

gate: pre-commit 全绿(doc-links、id-check-new、check-yaml、
      skill-size、check-added-large-files);30 篇 reference 手工字节
      体检 clean;skill() 逐个复载确认加载的是拆分版。
2026-10-29 15:03:12 +08:00

3.8 KiB
Raw Blame History

测量身份口径(先钉树与时刻,再看数字)(自 SKILL.md 外置)

本文由 mem-budget 的 SKILL.md「测量身份口径(先钉树与时刻,再看数字)」一节逐字外置而来(渐进展开:主文件只留索引与指针)。步骤号沿用原文,未重编。

1. 脚本按 __file__ 定位产物,不按 cwd —— 跨树必须换脚本

# scripts/stack_report.py:36-38
REPO_ROOT   = pathlib.Path(__file__).resolve().parent.parent
HTM_DEFAULT = REPO_ROOT / "MDK-ARM" / "STM32F407-Demo" / "STM32F407-Demo.htm"
FREERTOS_C  = REPO_ROOT / "Src" / "freertos.c"        # 配置栈来源,无命令行开关
# scripts/ram_report.py:16-18 同样用 dirname(dirname(abspath(__file__))) 定位 .map

⇒ cd 进别的 worktree 再跑主仓的脚本 量的仍是主仓那份 .htm/.map,数字不可比。 实测代价:这样一次"独立复算"量到主仓的 1,544 B / margin 1,016 B FAIL,据此写下的 +80 B 归因 被队友的逐树逐帧差分表推翻——目标 worktree 的真数是 1,464 B / margin 1,096 B / PASS。

正确做法:量哪棵树就跑那棵树自己的脚本(该树必须已在这棵树上构建过、有自己的 .htm/.map; 开树与合并的生命周期见 task-worktree skill):

'.venv/Scripts/python.exe' "<目标树>/scripts/stack_report.py"
'.venv/Scripts/python.exe' "<目标树>/scripts/ram_report.py"

⚠ 只给主仓脚本传 -i <另一棵树的 .htm>(或位置参数传另一棵树的 .map)不够: stack_report.py 的配置栈仍从脚本所在那棵树的 Src/freertos.c 读(FREERTOS_C 写死自 __file__, 没有开关),两树栈配置一旦不同就是"半棵树的混合数字"。要整支脚本换树跑。

自检(每次复算都做):报告头两行 - Source: ... 与 - Linker run: ... 就是你实际量的树和时刻。 Source 若只打印一个裸文件名(不带 MDK-ARM/... 相对路径),说明 -i 指到了脚本 REPO_ROOT 之外的产物。

2. 重跑报告脚本不算新测量(复述 ≠ 复验)

stack_report.py / ram_report.py 只是解析盘上那一份 .htm/.map;产物没变,再跑一次数字必然不变。 那只能叫"复述",不能写成"我复验过"。要拿到新数字必须先有一次新的 Linker run(增量构建也算), 并把新时刻与产物来源一并写进记录。

⚠ ram_report.py 正文里的 > Generated: … 是脚本运行时刻,重跑就变——它不是链接时刻, 不能拿来当"这是新测量"的凭证。

3. 钉身份的取数法(.htm/.map 按约定不入库 → 把时刻写进正文/台账)

grep -aE 'Last Updated|Maximum Stack Usage' MDK-ARM/STM32F407-Demo/STM32F407-Demo.htm | head -2
# → "ARM Linker, 5060960: Last Updated: Mon Oct 26 22:52:12 2026"
  • .htm 里唯一的链接时刻锚点是 Last Updated:;Linker run 只是 stack_report.py 自己输出里的标签, Date of Link、Image component 不在 .htm 里(实测按它们 grep 全空,白跑一轮)。
  • 取不到该字段时退回产物 mtime;同一笔链接里 .htm 与 .map 的 mtime 只差 ~0.1 s,可据此确认两份产物同源。 再配 git log -1 --format=%H 与该树 git status 的未跟踪文件数。
  • 记录最小格式:tree/commit + Linker run 时刻 + 产物来源(本次构建 / 盘上既有)。 本仓 .htm/.map 不入库,不钉时刻就等于把数字和树脱钩,下一个读数字的人无从判断它描述哪棵树。
  • 归属还能机械证明时顺手做掉:git log --name-only <那笔>..HEAD -- "*.c" "*.h" 逐行筛(排除 .uvprojx)。 若那笔之后没有任何提交再碰固件源文件,产物描述的就是在库那棵树,不是提交前快照。
  • 同族坑:git show :path / git show HEAD:path 读的是索引/HEAD,不是工作区。