diff --git a/docs/project-memory/shared-memory/pitfalls.md b/docs/project-memory/shared-memory/pitfalls.md index 773c851d8..4db440483 100644 --- a/docs/project-memory/shared-memory/pitfalls.md +++ b/docs/project-memory/shared-memory/pitfalls.md @@ -5238,3 +5238,26 @@ - **排查顺序**:① 先看失败耗时——几十毫秒说明该入口没等,是等待窗口缺失,不是锁没释放。② 看错误里的 `ownerIsSelf`:`true` 指向同进程另一条写通道,`false` 指向外部进程;该字段只比 PID,PID 复用会把外人报成自己人,只当线索、不当判据(回收判据另有 `processStartedAt` 兜底)。③ **锁文件在失败后通常已被 Drop 删掉,现场缺文件不否定争用**;同理 `agc_list_registered_assets` 的 `pendingOperations: []` 只表示没有在跑的付费生成,与项目写锁无关,不构成“锁没有持有者”的证据。④ `.agent/.manifest.json.lock` 是 manifest 的持久 OS 文件锁(Windows 不共享写句柄 / Unix `flock`),0 字节长期存在是设计如此,不是残留锁,也不要用项目写锁的回收判据去处理它。⑤ 看到“项目写锁路径权限被拒绝”时注意它的含义:这是**等满等待窗口后**的终态改判(Windows 上真实 ACL 拒绝就走这条路),不是某一瞬间的 metadata 观察;反过来,`项目正在被其他写操作占用:…(持锁方身份不可读:锁文件此刻不存在…)` 是零等待入口无法区分拆链窗口与 ACL 拒绝时的并列表述,两者不要互相否定。 - **验证**:Rust 定向覆盖同进程重叠写等待、同轮并行写、有界等待不占 runtime worker、活外部进程持锁带身份、权限拒绝不投影成争用,以及两条平台无关判据用例(重试性只由错误码决定、终态改判三条件);`runtime_project_write_lock_waits_for_delete_pending_target` 继续覆盖带句柄的 delete-pending 必须等到成功。 - **关联**:`apps/ai-game-creator-shell/src-tauri/src/agent/direct_tool_bridge.rs`、`apps/ai-game-creator-shell/src-tauri/src/project/write_lock.rs`、`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_actions/project_gates.rs`。 +## 2026-09-11 裸 rustfmt 会把「一个文件」放大成整个模块树,并行工作树里不要盲跑整仓 fmt + +- **现象**:只想按 `check:rustfmt` 的报错格式化 1 个 Rust 文件,跑完 `git diff --stat` 却显示 `src/agent/` 下 **50 个文件**被改动(`cargo fmt --all` 之后同样会扫到别人未提交的半成品)。 +- **原因**:裸 `rustfmt ` 把传入文件当成**模块根**,会跟随该文件的 `mod` 声明递归格式化所有子模块;`cargo fmt -- <文件...>` 才只作用于列出的文件。两者作用域不同,`--check` 的报错范围也因此不同——只修 `--check` 报出来的那几行不够,要用同一作用域复核。 +- **处理**:改格式前先 `git diff --stat` 确认范围并备份将被改动的文件;需要精确到文件时用 `cargo fmt -p -- <文件...>`(只格式化列出的文件),或 `rustfmt --config skip_children=true`(注意 `skip_children` 下的折行口径可能仍与 `cargo fmt` 不一致,最终以 `cargo fmt -p -- --check <文件...>` 为准)。**多人并行的工作树里禁止盲跑 `cargo fmt --all`**,它会格式化别人未提交的半成品。误伤后先备份、再用 `git apply -R` 反向补丁精确还原,**不要** `git checkout --`。 +- **验证**:本次同一批文件,裸 `rustfmt` 改 50 个;`cargo fmt -p genarrative-ai-game-creator-shell -- <5 个文件>` + `cargo fmt --all --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --check` 均 exit 0 且范围恰好 5 个文件。非破坏性复核作用域可用 `cargo fmt -p -- --check <文件...>`。 +- **关联**:`rustfmt.toml`、`package.json` 的 `check:rustfmt`(server-rs 与 AGC src-tauri **两条**命令,CI 常在第一条就退出,第二条从未跑到)。 + +## 2026-09-11 build-gate 的警告门被代理环境变量误伤:构建成功却判红 + +- **现象**:`npm run build` 失败,但日志里主站与 `admin-web` 都打印了 `✓ built in …`,末尾是 `Build gate failed because warnings were emitted:`,列出的全是 `(node:PID) [UNDICI-EHPA] Warning: EnvHttpProxyAgent is experimental, expect them to change at any time.` 与 `(Use \`node --trace-warnings ...\`)`。 +- **原因**:本机设了 `NODE_USE_ENV_PROXY=1` 与 `HTTP_PROXY` / `https_proxy` 时,Node 会启用 `EnvHttpProxyAgent` 并打印那条 experimental 警告;`scripts/build-gate.mjs:57-67` 的警告门逐行匹配 `/\bwarn(ing)?\b/i`、**只忽略含 `ExperimentalWarning` 字样的行**,这条不含该字样,于是没被忽略规则兜住。 +- **处理**:本地跑这条门禁前清空 `NODE_USE_ENV_PROXY` / `HTTP_PROXY` / `http_proxy` / `HTTPS_PROXY` / `https_proxy` / `ALL_PROXY`(无需改代码)。若要让本地也能带代理跑,应在忽略规则里补 `EnvHttpProxyAgent` / `UNDICI-EHPA`——**属改门禁规则,本次未擅自改**。CI 无这些变量,不会触发。 +- **验证**:同一 commit 只清空上述变量后重跑 `npm run build` → **exit 0**(日志末段不再出现 `[build-gate]` 失败段落)。反过来,带变量重跑必然复现同一批 `EnvHttpProxyAgent` 警告。 +- **关联**:`scripts/build-gate.mjs`、`package.json` 的 `build`;`scripts/check-repository-ci.sh` 的第 12 步。 + +## 2026-09-11 worktree 里 MSYS bash 跑 git 脚本会失效,门禁要按同序逐条等价执行 + +- **现象**:在 `.worktrees/` 工作树里执行 `npm run check:repository-ci`(内部是 bash 脚本),第一步就报 `[repository-ci] 比较基线不可用: `;直接用 bash 诊断则是 `fatal: not a git repository: /mnt/c/...//C:/Users/.../.git/worktrees/`。 +- **原因**:bash 走 MSYS 的 `/usr/bin/git`,而 worktree 的 `.git` 是**文件**、内容为 Windows 绝对路径 `C:/Users/.../.git/worktrees/`;MSYS git 把它当相对路径拼到当前目录后,解析成 `/mnt/c/.../C:/Users/...`。同一个 ref 用 Windows git 验证 `git cat-file -e ^{commit}` 返回 0,所以这不是基线选错,而是 worktree + MSYS 不兼容。 +- **处理**:在这类 worktree 里跑 script 门禁时,**按脚本同序、同命令用 Windows git / PowerShell 逐条等价执行**(`SPACETIME_SCHEMA_BASE_REF=` 之类环境变量照传),不要因为 bash 包装层失败就判定门禁本身红。 +- **验证**:`git cat-file -e "$(git rev-parse master)^{commit}"` 在 PowerShell 下 exit 0;逐条等价执行后 10 道门禁的通过与失败分布与脚本语义一致(本次仅 rustfmt / appSurface / build 三条红,各有独立归因)。 +- **关联**:`scripts/check-repository-ci.sh`、`scripts/run-bash-script.mjs`。 \ No newline at end of file