diff --git a/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md b/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md index ebba848c0..cfc36e93c 100644 --- a/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md +++ b/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md @@ -391,6 +391,7 @@ npm run check > - **首采**:`agc-linux` 档本机(Windows)编不了,基线**留空**;首次 CI 运行以「采集」模式打印清单且**不判失败**,跑完需要一次 `node scripts/check-rust-warnings.mjs --profile=agc-linux --update-baseline` 入册。 > - **开关**:`GENARRATIVE_SKIP_RUST_WARNINGS=1` 可本地跳过(日常 `npm run lint` 不想多花几分钟时用);`GENARRATIVE_WARNCHECK_DEBUG=1` 打印包集 / clean 命令 / artifact 的 fresh 表 / message 总数。 > - **局限**:`git push --no-verify` 可绕过;CI 侧**不覆盖** AGC 壳的 Windows 生产口径(GTK/ring 无法在 Linux 交叉编译);基线只保证「不新增」,不保证存量收敛。 +> - **CI 侧现状与风险(接线方案待定)**:`repository-checks` 的 runner 镜像里**有** Rust 工具链与 AGC 所需的 Linux 依赖(该 job 的日志会打印 `rustc 1.98.1 / cargo 1.98.1 / rustfmt 1.9.0-stable`),所以检查**能跑、不会红**(`agc-linux` 首次只采集、`server-rs` 基线为 0);但该 job **没有任何 cargo 预热缓存步骤**,默认会在它自己的 target 目录里从零编译(AGC Linux 档的 tauri/webkit 全链依赖 + server-rs 全 workspace),**估 25-40 分钟**。优化方向(待定):给该 job 挂 `ci-rust-cache.sh` 并把 `GENARRATIVE_WARNCHECK_TARGET_DIR` 指过去,或把检查挪到已有缓存的 lane job 里作为一步。 - 口径:全仓 Rust **first-party** 编译 warning 清零,能直接修的一律修掉,不用 `#[allow]` 掩盖;与既有文档口径冲突的优先修订口径(同批同步改文档);确实不能修的逐条登记原因与关闭条件。仍然禁止:新增**未登记**的 `#[allow(dead_code)]`、假引用、仅为消警删除测试;生成代码不手改(要改就改生成器)。下面一条是当前**唯一**登记的例外。 - **已登记的 `#[allow(dead_code)]` 例外(2026-10-07,PR #650「Rust 编译告警」)**:`apps/ai-game-creator-shell/src-tauri/src/agent/codex_provider/mod.rs` 顶部的 `#![allow(dead_code)]`,覆盖它用 `#[path]` 挂载的两棵子树——`app_server`(= `agent/codex_app_server/**`,含凭据、模型目录与 OAuth 交接)与 `cli`(= `agent/codex_cli.rs`,含 CLI 请求路径)。 diff --git a/scripts/check-rust-warnings.mjs b/scripts/check-rust-warnings.mjs index 3efacecba..859cccdc3 100644 --- a/scripts/check-rust-warnings.mjs +++ b/scripts/check-rust-warnings.mjs @@ -120,15 +120,32 @@ if (process.env.GENARRATIVE_SKIP_RUST_WARNINGS === '1') { process.exit(0); } -function targetDirFor(name) { - // 显式覆盖:CI 可以把这里指向复用的编译缓存目录(值就是最终使用的目录,不再追加 profile 名)。 +let warmTargetDir; +function workspaceTargetDir() { + if (warmTargetDir) return warmTargetDir; + // 不带 CARGO_TARGET_DIR 跑 metadata,拿到 cargo 实际会用的 target 目录。 + const meta = cargo(['metadata', '--format-version', '1', '--no-deps'], { + ...process.env, + }); + try { + warmTargetDir = JSON.parse(meta.stdout).target_directory; + } catch { + warmTargetDir = join(tmpdir(), 'genarrative-warncheck'); + } + return warmTargetDir; +} + +function targetDirFor(_name) { + // 显式覆盖:CI 可以把这里指向复用的编译缓存目录(值就是最终使用的目录)。 if (process.env.GENARRATIVE_WARNCHECK_TARGET_DIR) { const dir = process.env.GENARRATIVE_WARNCHECK_TARGET_DIR; mkdirSync(dir, { recursive: true }); return dir; } - // 默认:profile 专属目录(同一个目录被后续运行复用,只有首次要全量编译依赖)。 - const dir = join(tmpdir(), 'genarrative-warncheck', name); + // 默认用**仓库常规 target 目录**(依赖已热):每次只 clean/重编本 profile 的包,秒级到分钟级。 + // 代价是会给开发者自己的增量状态带来抖动(可接受)。安全网是 fresh 完整性断言: + // 倘若本 profile 的包没有被重编,脚本会 exit 1 报测量不完整,绝不会静默给出“新增 0”。 + const dir = workspaceTargetDir(); mkdirSync(dir, { recursive: true }); return dir; }