decision-log:记录 pre-commit 新增 Rust 格式守卫的取舍与本地限制

- 新增 2026-09-11 条目:背景(本地无 Rust 守卫、CI check:rustfmt 是唯一防线)、决策(lint-staged 增 *.rs + 包装脚本对两个 workspace 只查不改)、连带维护点(git-hooks.test.mjs 钉住整份配置形状,增键必须同步)
- 记下刻意保留的取舍:无暂存 .rs 时不触发;一旦暂存 .rs 则按整个 workspace 检查(与 CI 同口径),副作用是别人的未暂存未格式化 .rs 会挡住本次提交
- 记下未修的本地限制:check:git-hooks 第 2 个用例在 Windows 因 finally 里 rmSync 报 EBUSY 而红(断言全过、红在清理),TEMP 里堆了 16 个残留目录最早到 2026-09-05,加删除重试实测无效,CI 在 Linux 上不受影响
- 不动历史条目:2026-08-12 那条的「提交门禁」一行按本文件顶部口径只用于追溯
This commit is contained in:
2026-09-12 01:01:51 +08:00
parent 2a7bfadd72
commit cafd989bfb
@@ -15,6 +15,16 @@
- 关联文档:相关 PRD、技术文档、提交或 Issue
```
## 2026-09-11 pre-commit 补 Rust 格式守卫:lint-staged 增 *.rs,本地不再只靠 CI 的 check:rustfmt
- 背景:本 PR 已因 `check:rustfmt` 红过一次(`15660a98b` 修掉本批遗留的 8 处格式偏差)。根因是 `.husky/pre-commit` 只跑 `lint-staged`,而它的 glob 只覆盖 `*.{js,mjs,cjs,ts,tsx}` —— **Rust 格式在本地没有任何守卫**,唯一防线是 CI 那一侧(`check-repository-ci.sh``npm run lint``check:rustfmt`);本地没人跑得到的门禁等于没有门禁,「本地全绿、CI 才红」就会反复发生。
- 决策:lint-staged 增 `"*.rs": ["node scripts/lint-staged-rustfmt.mjs"]``cargo fmt` 只按 workspace 粒度格式化、**不接受文件参数**(lint-staged 会把命中的暂存路径追加到命令末尾),所以用包装脚本忽略 argv,对 `server-rs``apps/ai-game-creator-shell/src-tauri` 两个 workspace 各跑一次 `cargo fmt --all --manifest-path <m> -- --check`**只查不改** —— pre-commit 不应该自动改写别人正在改的 Rust 文件。workspace 路径与既有 `check:rustfmt` 一样写成 cwd 相对,因为 lint-staged 以 git 根为 cwd 运行任务。
- 连带维护点:`scripts/git-hooks.test.mjs``assert.deepEqual` **钉住 lint-staged 的整份配置形状**,增键必须同步该用例,否则 `check:git-hooks`(在 `npm run lint` 内)会以 `deepStrictEqual` 失败 —— 本次就是这样红了 Repository checks。该文件第 2 个用例里的 `lintStagedConfig` 是 temp repo 的测试替身,不随之增键:temp repo 没有 Rust 文件,`.rs` 只会命中 0 个。
- 已知影响(**刻意保留**):没有暂存 `.rs` 时守卫完全不触发(lint-staged 报 `[SKIPPED] *.rs — no files`);一旦暂存了 `.rs`,它检查的是**整个 workspace** 而不只是暂存文件 —— 这是为了与 CI 完全同口径而接受的取舍,副作用是「别人工作树里未格式化、且尚未暂存的 `.rs` 会挡住本次提交」,此时应按报错里的文件去找该文件的作者,不要顺手 `cargo fmt`(那会连带格式化别人的在途代码)。
- 已知本地限制(**未修,非本守卫引入**):`check:git-hooks` 第 2 个用例(`pre-push runs repository parity only for master updates`)在 Windows 本机会红,形态是 `finally``rmSync``EBUSY: resource busy or locked`(**断言全部通过,红在清理**)。本机 `%TEMP%` 堆积 16 个 `genarrative-pre-push-*` 残留目录、最早到 2026-09-05,说明该现象长期存在且每次运行都发生;给 `rmSync``maxRetries: 10`(约 5.5s 线性退避)实测**无效**,疑为 WSL bash 跨 `/mnt/c` 的句柄在子进程退出后仍被持有。CI 在 Linux 上不受影响,故不在本批修。
- 验证方式:`node scripts/lint-staged-rustfmt.mjs` exit 0lint-staged 分派层面确认 `*.rs` 任务真被触发(对 6 个 `.rs` 跑通)且无 `.rs``[SKIPPED]``npm run check:rustfmt``npm run check:encoding``git diff --check` 均 exit 0。变异验证:把 `*.rs``package.json` 摘掉 → `check:git-hooks` 第 1 个用例以同样的 `deepStrictEqual` operator 变红;还原(`package.json` 字节级哈希一致)后该用例回 `ok`
- 关联文档:`docs/project-memory/shared-memory/pitfalls.md``cargo fmt --all` 会扫到别人未提交半成品那条)。本文件 2026-08-12「Repository checks 采用 CI 与本地共用的单一门禁入口」条的「提交门禁」一行只描述当时的 JS/TS 范围,按本文件顶部口径历史条目只用于追溯,不再回改;提交 `dd7cf401a`(守卫本体)、`2a7bfadd7`(形状断言跟进)。
## 2026-09-11 冷启动首屏存在同一张卡被读两次(登记回声 + 取消/重扫路径):记录为后续项,本轮不修
- 背景:为解「从首页进项目 → 资源管理页首屏等图片」,本轮按用户批准做了 A(热预取不再按投影顺序盲取前 N,改为只预取几何上可见的卡)+ B(相交卡按「先视口内、再 160px `rootMargin` 圈」两档入队)。本条记录的是**做 A/B 时顺手发现、但属于另一条独立缺陷**的重复读;A/B 只改「取哪些、按什么顺序」,不碰它。