17 篇文档的变更记录(含修订记录、带编号与中文序号标题)节里只剩一句 「不再记流水账」的占位话,整节删掉,连带它前面的分隔线。 仍保留真台账的只有 5 篇(看门狗 / 配置文件设计 / RAM 预算台账 / 内容页架构 / 本地工具路径方案),外加 scripts/archive 归档区。 份数口径改成可复跑的普查:文档规范 §5.1 补自查命令, stale-doc-count-sweep 的速查表与陷阱各加一条——只 grep 裸标题会漏 带编号与中文序号的两种写法,实测 5 篇只数得出 3 篇,差点据此把 全仓正确的份数改错。 门禁:逐篇与全量 check_doc_links 除 simulator/SDL2 联接假红外 0 问题; skill-size rc=0;表格列数与字节体检相对 HEAD 零新增问题。
9.6 KiB
Steps(自 SKILL.md 外置)
本文由 stale-doc-count-sweep 的 SKILL.md「Steps」一节逐字外置而来(渐进展开:主文件只留索引与指针)。步骤号沿用原文,未重编。
-
实测真值:先剔伪命中,再双源互证(不抄用户口述、不抄另一处文档)。逐数走上面那张表;两个来源对不上时先找分歧根因(把全部命中逐条打印出来看),不要取第一个、不要取平均,并在结论里写明分歧与取舍(实测:菜单
#page=计数 29 对 注册表 28,根因是头部注释示例行)。cd "<repo>" ls simulator/tests/ref/shot_*.bin | wc -l # 张数(判据 = 入库实数) awk '/^PAGES = \[/,/^\]/' simulator/tests/check_content_pages.py | grep -cE '^ *\("' # 页数(第二个来源,两者必须一致) grep -n '#page=' ui_menu_tree.txt | head -3 # 先看首条是不是注释示例行,再定叶数 grep -rn 'UI_PAGE_MAP_COUNT' Drivers/BSP/UI/ui_page_registry.h # 已绑叶数(生成物) grep -c '\.bitmap_index' Drivers/BSP/UI/ui_font_cn_12.c # 314 = 含 notdef;字形 = 该数 - 1 & '.venv\Scripts\python.exe' -c "import yaml;d=yaml.safe_load(open('.pre-commit-config.yaml',encoding='utf-8'));print(sum(len(r['hooks']) for r in d['repos']))" # 钩子数口径⚠ 权威脚本输出乱码时(
check_font_charset.py在 GBK 代码页下整行打印成 U+FFFD 替换字符串 +: PASS,数字全读不出来),改为直接数源文件里符号出现次数(.bitmap_index/.range_start/ 码点唯一化)——不许臆读乱码,也不许因此退回去抄文档里的旧数。 -
全形态 + 全命中面扫描。一个数一次列出它全部历史形态,别只扫当前旧值:本轮 =
122/217、179/274、185/280、47 → 53、53 → 60、PAGES = 53、UI_PAGE_MAP_COUNT = 22、已绑 22 叶、未绑 11、内容页 53 页。grep -rn --include=*.md --include=*.py --include=*.yaml --include=*.txt --include=*.c --include=*.h \ -E '122 唯一字|217 字形|179 汉字|274 字形|185 唯一字|280 字形|47 → 53|53 → 60|内容页 53|PAGES = 53|UI_PAGE_MAP_COUNT = 22|已绑 22|未绑 11' . \ | grep -v -E '^\./(ci-artifacts|\.mnemon|\.dsh/runs)/'命中面比「文档」宽,至少包含:
docs/**、AGENTS.md、.pre-commit-config.yaml(钩子name:显示名内嵌页数:name: UI 像素回归(菜单 8 状态 + 内容页 60 页 黄金参考)就是命中点)、scripts/*.py、simulator/**/README.md、以及.dsh/skills/*/SKILL.md(本窗font-regen正文自带 179/274 计数,直到 step 150 才发现;编号门禁退役那轮id-family-semantic-migration、task-worktree两个 skill 正文与scripts/README.md同样是引用面)。先列出
文件:行:全文,判定前必须看整行——cut -c1-120会截掉后半句(那里常写着日期戳或口径)。 -
逐条分类,五类各走各的路(本 playbook 的核心,别用一条规则套全部命中):
类别 判定 动作 当前态陈述 描述「现在是多少」 改成实测真值 变更记录历史行 形如「47 → 53 页」的当日事实 原样冻结不回改——但这条只适用于保留变更记录的 5 篇真台账(台账 / 被别处当唯一证据出处的文档,清单 → docs/文档规范.md§5.1)与scripts/archive/归档;其余文档没有变更记录节,不再追加任何流水行,数字同步只改当前态同数不同义 最坏路径 < 40KB这类内存/绘制缓冲红线不动,并在结论里写明「为什么不动」 带日期戳的测量 「2026-10-26 实跑 …覆盖当时 40 页中的」 不臆改新数,只补「当时」两字锁口径;新数留待下次实跑回填 数字对但口径描述错 数没错、句子把口径讲错了(实测:写「218 字(含 ASCII/符号,共 313 字形)」,而 ui_cn_chars.txt的 218 个码点全为非 ASCII)另起一笔只改口径的提交( 6daa01ae),不与数字同步混笔;这类命中在任何数字 diff 里都看不见,只能把口径句逐句读一遍拿不准就回到第 2 步把整行打印出来再判;判错历史行 = 把当天事实改成假账。
-
每处先读现文,再逐条字面替换并断言命中数(弃用整文件正则批处理)。本窗两度返工都是没先读现文:step 45 断言
HIT 0抛错(目标串与现文不一致),step 44 是脚本语法错。脚本写成临时文件再跑(内嵌 heredoc/模板字符串里的反引号会截断整脚本),按字节替换以保 BOM 与行尾不动:import pathlib, sys sys.stdout.reconfigure(encoding='utf-8', errors='replace') JOBS = [ # (文件, old, new, 期望命中数) ('AGENTS.md', '内容页 53 页黄金参考', '内容页 60 页黄金参考', 1), ('.pre-commit-config.yaml', '内容页 53 页 黄金参考', '内容页 60 页 黄金参考', 1), ('docs/架构设计/项目架构总览.md', '122 字/217 字形', '218 字/313 字形', 1), ('docs/UI设计/UI_自动化测试流程.md', '文本断言 **310 条**、覆盖 40 页中的', '文本断言 **310 条**、覆盖当时 40 页中的', 1), ] for path, old, new, expect in JOBS: p = pathlib.Path(path); raw = p.read_bytes() o, n = old.encode('utf-8'), new.encode('utf-8') got = raw.count(o) assert got == expect, f'{path}: 命中 {got},期望 {expect}(未写入)' assert o != n, f'{path}: old 与 new 相同' p.write_bytes(raw.replace(o, n)) print(f'OK {path}: {old} -> {new} x{got}')每行打印
old -> new xN,收口时这串输出就是「改了哪几处」的账。脚本报错/没编译过,先git diff --stat确认零写入再换写法(不要在半落地状态上叠改)。- 反引号:TS 侧先用可见占位符(如
~TB~)写文本,落盘前再还原成真反引号 ——const BT = String.fromCharCode(96); const q = s => s.split(TOKEN).join(BT)(本窗实测:直接把带反引号的串塞进模板字符串/heredoc,整批零落地或把变更记录行写坏)。用tools.edit批量改时同样先await tools.read现文再传old_string;批量里若某条old_string与new_string相同会报must differ—— 只有该条作废、其余已落盘,别整批重跑。 - 历史行被写坏(反引号及紧随其后的字符经工具传递被吞 → 变更记录行只剩半行、尾部出现
??这类残迹):立刻按无反引号兜底写法整行重写——裸词accident / oper / alarm / start / yk、页面绑定写成不带反引号的#page=——而不是拿同样带反引号的串再改一遍(实测连返工三次:step 81→82→83→85)。
- 反引号:TS 侧先用可见占位符(如
-
一笔只装一类事。数字同步一笔(
cbb4fdb8:11 处 + 变更记录一行);口径更正另起一笔(6daa01ae);提交后复扫逮到的漏网当前态再补独立一笔(11d60057)。钩子一增一减写成一个当日行的两个阶段(51 → 52 加id-check-new、随即 52 → 51 摘id-check),别写两行互相打脸。提交说明如实写(「先认一笔自己的错:上一笔的未绑 21 叶是探针错」),别把口径修正包装成「补充说明」。 -
被改文件全文通读,核对其余小节——不是只看 diff。同一文档内互相引用的小节必须一致(本窗产品需求:§2.4 立项未排、§5.14 FR-SOE-3、§8.2 绑定现状、§8.3 已绑分页表、§9.1 差距表、§9.2 顺序表六处同时引用这四个数;
docs/任务规划/README.md§1 当前执行表 vs §2 全项目顺序表)。若发现上一笔自己写进文档的数口径就错了,明确认错并改正,同时把可复核的重算方法写进文档(「按缩进判叶子:有更深缩进后继者即非叶子」),防止再错。 -
提交后再复扫一遍(收尾硬步骤,不许省,也不许只在提交前扫)。按第 2 步的全部旧形态整仓再扫一次,逐条分类为 当前态 / 历史行 / 同数不同义:本窗
cbb4fdb8提交后复扫得 14 条命中,12 条以上都在变更记录历史行(47 → 53、53 → 60、122/217冻结),唯一残留的当前态命中是docs/架构设计/项目架构总览.md§3「界面层」那行 → 单独补一笔11d60057。说不出归属的就是漏改。grep -rn -E '22 叶|未绑 11|11 叶|53 页|122 唯一字|217 字形|185 唯一字|280 字形|内容页 53|PAGES = 53|UI_PAGE_MAP_COUNT = 22' \ . | grep -v -E '^\./(ci-artifacts|\.mnemon|\.dsh/runs)/' -
跑门禁、分笔提交(
git commit属 Ask first,须用户明确指示后再做):& '.venv\Scripts\python.exe' scripts/check_doc_links.py --all --sections-strict # 期望「文档路径检查通过(N 个文档)」 & '\.venv\Scripts\python.exe' scripts/archive/id_gate/check_ids_new.py --range A..B # 编号形态普查(两道门禁 2026-10-28 / 2026-10-29 都已退役,不再是提交钩子) & '.venv\Scripts\python.exe' scripts/ci_local.py # 或 pre-commit run --files <被改文件>PowerShell 形态把
./.venv/Scripts/python.exe换成& '.venv\Scripts\python.exe'。提交信息一律git commit -F <UTF-8 无 BOM 文件>,别用-m(中文长标题易超 100 字符、终端代码页会转码);标题 ≤100、正文每行 ≤80(实测把正文压到 66/78 字符才过 gitlint)。