88601422c3
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 零新增问题。
89 lines
9.6 KiB
Markdown
89 lines
9.6 KiB
Markdown
# Steps(自 SKILL.md 外置)
|
||
|
||
> 本文由 stale-doc-count-sweep 的 SKILL.md「Steps」一节逐字外置而来(渐进展开:主文件只留索引与指针)。步骤号沿用原文,未重编。
|
||
|
||
1. **实测真值:先剔伪命中,再双源互证**(不抄用户口述、不抄另一处文档)。逐数走上面那张表;两个来源对不上时**先找分歧根因**(把全部命中逐条打印出来看),不要取第一个、不要取平均,并在结论里写明分歧与取舍(实测:菜单 `#page=` 计数 29 对 注册表 28,根因是头部注释示例行)。
|
||
|
||
```bash
|
||
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` / 码点唯一化)——不许臆读乱码,也不许因此退回去抄文档里的旧数。
|
||
|
||
2. **全形态 + 全命中面扫描**。一个数一次列出它全部历史形态,别只扫当前旧值:本轮 = `122/217`、`179/274`、`185/280`、`47 → 53`、`53 → 60`、`PAGES = 53`、`UI_PAGE_MAP_COUNT = 22`、`已绑 22 叶`、`未绑 11`、`内容页 53 页`。
|
||
|
||
```bash
|
||
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` 会截掉后半句(那里常写着日期戳或口径)。
|
||
|
||
3. **逐条分类,五类各走各的路**(本 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 步把整行打印出来再判;判错历史行 = 把当天事实改成假账。
|
||
|
||
4. **每处先读现文,再逐条字面替换并断言命中数**(弃用整文件正则批处理)。本窗两度返工都是没先读现文:step 45 断言 `HIT 0` 抛错(目标串与现文不一致),step 44 是脚本语法错。脚本写成临时文件再跑(内嵌 heredoc/模板字符串里的反引号会截断整脚本),按**字节**替换以保 BOM 与行尾不动:
|
||
|
||
```python
|
||
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)。
|
||
|
||
5. **一笔只装一类事**。数字同步一笔(`cbb4fdb8`:11 处 + 变更记录一行);口径更正另起一笔(`6daa01ae`);提交后复扫逮到的漏网当前态再补独立一笔(`11d60057`)。钩子一增一减写成一个当日行的两个阶段(51 → 52 加 `id-check-new`、随即 52 → 51 摘 `id-check`),别写两行互相打脸。提交说明如实写(「先认一笔自己的错:上一笔的未绑 21 叶是探针错」),别把口径修正包装成「补充说明」。
|
||
|
||
6. **被改文件全文通读,核对其余小节**——不是只看 diff。同一文档内互相引用的小节必须一致(本窗产品需求:§2.4 立项未排、§5.14 FR-SOE-3、§8.2 绑定现状、§8.3 已绑分页表、§9.1 差距表、§9.2 顺序表六处同时引用这四个数;`docs/任务规划/README.md` §1 当前执行表 vs §2 全项目顺序表)。若发现上一笔自己写进文档的数**口径就错了**,明确认错并改正,同时把**可复核的重算方法**写进文档(「按缩进判叶子:有更深缩进后继者即非叶子」),防止再错。
|
||
|
||
7. **提交后再复扫一遍**(收尾硬步骤,不许省,也不许只在提交前扫)。按第 2 步的**全部**旧形态整仓再扫一次,逐条分类为 当前态 / 历史行 / 同数不同义:本窗 `cbb4fdb8` 提交后复扫得 14 条命中,12 条以上都在变更记录历史行(`47 → 53`、`53 → 60`、`122/217` 冻结),**唯一残留的当前态命中**是 `docs/架构设计/项目架构总览.md` §3「界面层」那行 → 单独补一笔 `11d60057`。说不出归属的就是漏改。
|
||
|
||
```bash
|
||
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)/'
|
||
```
|
||
|
||
8. **跑门禁、分笔提交**(`git commit` 属 Ask first,须用户明确指示后再做):
|
||
|
||
```bash
|
||
& '.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)。
|