diff --git a/.gitea/workflows/project-ci.yml b/.gitea/workflows/project-ci.yml index 928311509..d56eba0f4 100644 --- a/.gitea/workflows/project-ci.yml +++ b/.gitea/workflows/project-ci.yml @@ -470,56 +470,6 @@ jobs: - name: Validate production API deploy behavior run: npm run check:production-api-deploy - rust-warning-check: - name: Rust warning check - runs-on: genarrative-ci - steps: - - name: Checkout source from Gitea - env: - GENARRATIVE_GITEA_FETCH_DEPTH: '1' - GENARRATIVE_GITEA_TOKEN: ${{ github.token }} - run: genarrative-gitea-checkout - - - name: Validate preinstalled CI job image and sandbox - run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh - - # 只为这个 job 需要的依赖预热;复用与 Rust lane 相同的隔离编译缓存,避免全量重编。 - - name: Prepare Rust dependencies - shell: bash - run: | - set -euo pipefail - for manifest in server-rs/Cargo.toml apps/ai-game-creator-shell/src-tauri/Cargo.toml; do - for attempt in $(seq 1 5); do - if cargo fetch --locked \ - --target x86_64-unknown-linux-gnu \ - --manifest-path "${manifest}"; then - break - fi - if [[ "${attempt}" -eq 5 ]]; then - echo "dependency fetch failed after 5 attempts: ${manifest}" >&2 - exit 1 - fi - sleep $((attempt * 2)) - done - done - - - name: Prepare isolated Rust compilation cache - shell: bash - run: | - set -euo pipefail - node --test scripts/ci-rust-cache.test.mjs - bash scripts/ci-rust-cache.sh prepare - - # 与本地 pre-push 同一个脚本(scripts/check-rust-warnings.mjs);基线感知,只拦「新增」告警。 - # 覆盖:server-rs workspace(Linux 可跑,0 存量)+ AGC 壳 Linux 档。 - # 不覆盖:AGC 壳「Windows + 编辑器 feature」生产口径——那档只能在 Windows 上编,由本地钩子覆盖。 - - name: Run Rust warning check - run: npm run check:rust-warnings -- --profile=server-rs --profile=agc-linux - - - name: Report isolated Rust compilation cache - if: always() - run: bash scripts/ci-rust-cache.sh report - repository-checks: name: Repository checks runs-on: genarrative-ci diff --git a/.husky/pre-push b/.husky/pre-push index 3eff4b550..2044c66f1 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,9 +1,4 @@ # Git 在链接工作树里执行 Hook 时会注入 GIT_DIR 等仓库定位变量,优先级高于 cwd; # 钩子链(npm → check:repository-ci → 测试夹具)会继承它们并写到真实仓库,故在入口统一清除。 unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE GIT_COMMON_DIR GIT_PREFIX GIT_CONFIG_PARAMETERS GIT_CEILING_DIRECTORIES -# pre-push 的 ref 行(stdin)被两段检查共用:先落一份临时文件,第二段才读得到。 -push_refs="$(mktemp)" -cat > "${push_refs}" -trap 'rm -f "${push_refs}"' EXIT -npm run check:pre-push-master -- "$@" < "${push_refs}" -node scripts/pre-push-rust-warnings.mjs < "${push_refs}" +npm run check:pre-push-master -- "$@" diff --git a/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md b/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md index ecc8048ae..ebba848c0 100644 --- a/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md +++ b/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md @@ -382,6 +382,15 @@ npm run check > - **局限**:① `git push --no-verify` 可以绕过(CI 仍会跑,但只覆盖 Linux 档 + server-rs);② 本机 target 目录被污染时会读出假数字,取数前先 `cargo clean -p `;③ CI 不跑 clippy;④ 基线只保证「不新增」,不保证存量收敛;⑤ AGC 壳 Windows 档只有在 Windows 机器上推代码时才被检查。 > > 以下小节是**历史记录**(`deny(warnings)` 时代的落法、AGC 门禁 predicate、harness 假告警边界、2026-10-06 基线表与检查命令),保留供追溯;其中的 Werror 接线与判据已随本 PR 撤销,`deny(warnings)` 在 tip 上**已 0 命中**。 +> +> **接法更正(2026-10-07 收口)**:不另造 hook / 不新增 CI job,而是把检查**挂进 `npm run lint`**——它是 CI 的 `Repository checks`(`.gitea/workflows/project-ci.yml` 里 `run: npm run check:repository-ci` → `scripts/check-repository-ci.sh` → `npm run lint`)与「推 master 时的 pre-push」(`.husky/pre-push` → `npm run check:pre-push-master` → `scripts/pre-push-master.sh` → `npm run check:repository-ci`)**共用的那条命令**;因此一次接入,两处生效。 +> +> - **feature 分支推送本地不跑**这项检查(`scripts/pre-push-master.sh` 只在推 `refs/heads/master` 时才真正执行;这是仓库既有行为,未改)。 +> - **测量确定性**(`scripts/check-rust-warnings.mjs`):profile 专属 target 目录(默认 `/genarrative-warncheck/`,可用 `GENARRATIVE_WARNCHECK_TARGET_DIR` 指向复用缓存)+ 对本 profile 的 first-party 包逐个 `cargo clean -p <包名>`,取数后**完整性断言**:profile 的每个包都必须出现 `compiler-artifact` 且 `fresh=false`,否则 exit 1 报「测量不完整」(原因:cargo 只对真正重编的 crate 打印告警,热目录下未变化 crate 的存量告警不重现,会给出「新增 0」的假答案)。 +> - **被否决的方案**:取数前**整体清空** target 目录——实测 AGC 壳清空后要重建 tauri/webkit 全链依赖(**15-25 分钟**),代价不可接受。 +> - **首采**:`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 交叉编译);基线只保证「不新增」,不保证存量收敛。 - 口径:全仓 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/package.json b/package.json index c48245c1f..6b93bbd18 100644 --- a/package.json +++ b/package.json @@ -139,7 +139,7 @@ "check:server-rs-ddd": "npm run check:spacetime-schema && npm run check:spacetime-runtime-access && npm run check:module-runtime-artifact && node scripts/check-server-rs-ddd-boundaries.mjs", "lint:eslint": "eslint . --ext .ts,.tsx,.js,.mjs,.cjs --max-warnings 0", "typecheck": "tsc -p tsconfig.typecheck-guardrails.json --noEmit", - "lint": "npm run check:encoding && npm run check:doc-index && npm run check:npm-workspaces && npm run check:git-hooks && npm run check:rustfmt && npm run check:spacetime-schema && npm run check:generated-bindings && npm run check:game-distribution-dto-parity && npm run check:game-distribution-price-limit-parity && npm run check:production-ops && npm run check:preview-deployer && npm run check:maintenance-page && npm run check:nginx-spa-routes && npm run check:pingora-route-parity && npm run lint:eslint && npm run typecheck", + "lint": "npm run check:encoding && npm run check:doc-index && npm run check:npm-workspaces && npm run check:git-hooks && npm run check:rustfmt && npm run check:rust-warnings && npm run check:spacetime-schema && npm run check:generated-bindings && npm run check:game-distribution-dto-parity && npm run check:game-distribution-price-limit-parity && npm run check:production-ops && npm run check:preview-deployer && npm run check:maintenance-page && npm run check:nginx-spa-routes && npm run check:pingora-route-parity && npm run lint:eslint && npm run typecheck", "lint:fix": "eslint . --ext .ts,.tsx,.js,.mjs,.cjs --fix && prettier --write .", "format:rust": "cargo fmt --all --manifest-path server-rs/Cargo.toml && cargo fmt --all --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml && cargo fmt --all --manifest-path plugins/agc-unity-editor/native/unity-editor-bridge/Cargo.toml && cargo fmt --all --manifest-path plugins/agc-godot-editor/native/godot-editor-bridge/Cargo.toml", "format": "prettier --write . && npm run format:rust", diff --git a/scripts/check-rust-warnings.mjs b/scripts/check-rust-warnings.mjs index 1d2b5fa9e..3efacecba 100644 --- a/scripts/check-rust-warnings.mjs +++ b/scripts/check-rust-warnings.mjs @@ -1,27 +1,40 @@ #!/usr/bin/env node -// Rust 编译告警的「基线感知」检查。 +// Rust 编译告警的「基线感知」检查:本地 pre-push 与 CI 的 warning check 共用这一份实现。 // -// 为什么不是 Werror:`deny(warnings)` 把 warning 变成编译错误,等于让上游新代码的存量告警 -// 直接挡住所有人、也会让本地开发构建变红(PR #650 的决策记录里有完整经过)。改成 -// 「本地 pre-push + CI 的显式检查」,并按基线只拦**新增**告警。 +// 为什么不是 Werror:把 warning 变成编译错误会让上游新代码的存量告警直接挡住所有人, +// 也会让本地开发构建变红(见 PR #650 的决策记录)。改成「推送前 + CI」的显式检查,只拦新增。 // -// 单一真源:本地 `.husky/pre-push` 与 CI 的 `warning check` job 调用的是同一份实现(本文件)。 +// ## 测量口径(先定死) +// - **只收本 profile 的 first-party 告警**(按源码路径前缀): +// `agc-*` → `apps/ai-game-creator-shell/src-tauri/**`;`server-rs` → `server-rs/**`。 +// 这样 path 依赖(shared-contracts / platform-llm …)的告警不会串进 AGC profile +// (它们是 server-rs profile 的职责),也解释了「同一棵树 14 条 vs 33 条」的差。 +// - 归属判定用 `compiler-message` 的主 span 的 `file_name`(相对仓库根规范化)做前缀匹配。 +// +// ## 确定性来源(两层,缺一不可) +// 1. **profile 专属 target 目录**:默认 `/genarrative-warncheck/`, +// 由脚本自己设 CARGO_TARGET_DIR(**不继承外部**,避免「清了 A 目录、编了 B 目录」); +// 可用 `GENARRATIVE_WARNCHECK_TARGET_DIR` 显式覆盖(CI 想复用缓存时用)。 +// 2. **同名 env 下 `cargo clean -p` 精确清理本 profile 的 first-party 包**:包集用 +// `cargo metadata` 的 `id` **精确集合**(注意:server-rs 成员的 id 形如 `path+file:///…#0.1.0` +// —— **不含包名**;AGC 是 `…#genarrative-ai-game-creator-shell@0.1.67`),clean 用 `name@version`。 +// 3. **断言**:本 profile 的每个包都必须出现 `compiler-artifact` 且 `fresh === false`; +// 否则 exit 1 并提示「测量不完整」——**绝不给「新增 0」的假答案**。 +// 根因备忘:cargo 只对真正重编的 crate 打印告警,热目录下未变化 crate 的存量告警不会重现。 // // 用法: -// node scripts/check-rust-warnings.mjs # 按当前平台选默认 profile +// node scripts/check-rust-warnings.mjs # 按平台选默认 profile // node scripts/check-rust-warnings.mjs --profile=server-rs --profile=agc-windows -// node scripts/check-rust-warnings.mjs --profile=agc-linux # CI(Linux)用 -// node scripts/check-rust-warnings.mjs --update-baseline # 把当前结果写回基线(人工确认后) -// node scripts/check-rust-warnings.mjs --json # 机器可读 +// node scripts/check-rust-warnings.mjs --profile=agc-linux # CI(Linux) +// node scripts/check-rust-warnings.mjs --profile=server-rs --update-baseline +// node scripts/check-rust-warnings.mjs --json // -// 基线键 = `路径 | 符号 | lint`(**不含行号**,行号只作输出附注),存于 -// `scripts/warning-baseline.json`。这样上游改一行导致的整体漂移不会让基线全部失效。 -// -// 退出码:0 = 无新增;1 = 有新增(或调用失败)。存量减少只在输出里提示「可更新基线」。 +// 基线键 = `路径 | 符号 | lint`(不含行号)。退出码:0=有效且无新增;1=有新增/测量不完整/编译失败;2=参数错。 import { spawnSync } from 'node:child_process'; -import { existsSync, readFileSync, writeFileSync } from 'node:fs'; -import { dirname, join, relative, resolve } from 'node:path'; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join, relative, resolve, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); @@ -30,7 +43,6 @@ const AGC_MANIFEST = 'apps/ai-game-creator-shell/src-tauri/Cargo.toml'; const AGC_FEATURES = 'cocos-editor-execute,unity-editor-execute,godot-editor-execute'; -// profile = 一档「口径」:同一份代码在不同平台/feature 下的告警集合互不相同,因此基线按 profile 分组。 const PROFILES = { 'server-rs': { description: @@ -44,6 +56,8 @@ const PROFILES = { '--manifest-path', 'server-rs/Cargo.toml', ], + manifest: 'server-rs/Cargo.toml', + firstParty: ['server-rs'], platforms: ['linux', 'win32', 'darwin'], }, 'agc-windows': { @@ -58,11 +72,14 @@ const PROFILES = { '--manifest-path', AGC_MANIFEST, ], + manifest: AGC_MANIFEST, + firstParty: ['apps/ai-game-creator-shell/src-tauri'], + packageDirs: ['apps/ai-game-creator-shell/src-tauri'], platforms: ['win32'], }, 'agc-linux': { description: - 'AGC 壳:Linux target + 三编辑器 feature(CI 覆盖;本机 Windows 无法交叉编译 GTK/ring,跑不了)', + 'AGC 壳:Linux target + 三编辑器 feature(CI 覆盖;本机 Windows 无法交叉编译 GTK/ring)', command: [ 'cargo', 'check', @@ -72,6 +89,9 @@ const PROFILES = { '--manifest-path', AGC_MANIFEST, ], + manifest: AGC_MANIFEST, + firstParty: ['apps/ai-game-creator-shell/src-tauri'], + packageDirs: ['apps/ai-game-creator-shell/src-tauri'], platforms: ['linux'], }, }; @@ -93,43 +113,125 @@ if (unknown.length > 0) { console.error(`[rust-warnings] 未知参数:${unknown.join(' ')}`); process.exit(2); } +if (process.env.GENARRATIVE_SKIP_RUST_WARNINGS === '1') { + console.log( + '[rust-warnings] GENARRATIVE_SKIP_RUST_WARNINGS=1:本次跳过 Rust 告警检查(仅建议本地临时使用)。', + ); + process.exit(0); +} -function defaultProfiles() { - const names = requested.length > 0 ? requested : Object.keys(PROFILES); - return names.filter((name) => { - if (requested.length > 0) return true; - return PROFILES[name].platforms.includes(process.platform); +function targetDirFor(name) { + // 显式覆盖:CI 可以把这里指向复用的编译缓存目录(值就是最终使用的目录,不再追加 profile 名)。 + 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); + mkdirSync(dir, { recursive: true }); + return dir; +} + +function cargo(args, env) { + return spawnSync('cargo', args, { + cwd: repoRoot, + encoding: 'utf8', + maxBuffer: 256 * 1024 * 1024, + env, }); } -function loadBaseline() { - if (!existsSync(baselinePath)) return { schema: 1, profiles: {} }; - return JSON.parse(readFileSync(baselinePath, 'utf8')); +function packageIds(profile) { + const meta = cargo( + [ + 'metadata', + '--format-version', + '1', + '--no-deps', + '--manifest-path', + profile.manifest, + ], + { + ...process.env, + CARGO_TARGET_DIR: targetDirFor(profile.name), + }, + ); + if (meta.status !== 0) return []; + try { + const parsed = JSON.parse(meta.stdout); + const members = new Set(parsed.workspace_members ?? []); + const root = repoRoot.replaceAll('\\', '/'); + return (parsed.packages ?? []) + .filter((pkg) => { + if (!members.has(pkg.id)) return false; + const manifest = String(pkg.manifest_path).replaceAll('\\', '/'); + if (!manifest.startsWith(root)) return false; + const dir = manifest.slice(0, manifest.lastIndexOf('/')); + // 只把**本 profile 自己的**包纳入「必须重编」的断言。 + // 注意:AGC 壳的目录下还有 `vendor/**` 的 path 依赖(codex-patch-parser 等), + // 它们不是本 profile 的包,不要求重编(它们的告警也被 first-party 前缀过滤掉)。 + if (profile.packageDirs) + return profile.packageDirs.some((dir_) => dir === `${root}/${dir_}`); + return profile.firstParty.some( + (prefix) => + dir === `${root}/${prefix}` || dir.startsWith(`${root}/${prefix}/`), + ); + }) + .map((pkg) => ({ + id: pkg.id, + name: pkg.name, + spec: `${pkg.name}@${pkg.version}`, + manifestPath: pkg.manifest_path, + })); + } catch { + return []; + } } -// 从 rustc 诊断里取「符号」:消息里第一个反引号片段(`fn x` / `unused import: \`a::b\`` / `field \`f\``)。 -function symbolOf(message) { - const match = /`([^`]+)`/u.exec(message); - return match ? match[1] : message.slice(0, 80); +function normalizeId(id) { + const text = String(id ?? ''); + // 旧形态 ` (path+file:///…)`:取括号里的 path+… 部分; + // 其余(`path+file:///…#`)**原样使用**。 + // 曾经踩过的坑:只取 `#` 之后的片段会碰撞——server-rs 的 27 个成员版本全是 0.1.0, + // 归一化后都变成 "0.1.0",于是「每个包都必须重编」的断言永远为假(观察到「重编 1/27 却 exit 0」)。 + const match = /\((?path\+[^)]*)\)$/u.exec(text); + return match ? match.groups.path : text; } -function lintOf(code) { - return code?.code ?? 'unknown'; +function isFirstParty(profile, relativePath) { + const posix = relativePath.split(sep).join('/'); + return profile.firstParty.some( + (prefix) => posix === prefix || posix.startsWith(`${prefix}/`), + ); } -function normalizePath(file) { - return relative(repoRoot, resolve(repoRoot, file)).replaceAll('\\', '/'); -} - -function collectWarnings(profile) { +function collectWarnings(profile, packages, env) { const [bin, ...args] = profile.command; + // 确定性由两步保证:① 本 profile 的 first-party 包逐个 `cargo clean -p <包名>`(保留依赖缓存); + // ② 取数后用**条数对照**自证(见下方 incomplete 判定)。整体清空 target 目录的方案已被否决: + // 实测 AGC 壳清空后要重建 tauri/webkit 全链依赖(15-25 分钟),代价不可接受。 + const cleanArgs = ['clean', '--manifest-path', profile.manifest]; + // 仅用于验证「完整性断言真的会失败」:GENARRATIVE_WARNCHECK_SKIP_CLEAN=<包名> 时故意漏清一个包。 + const skipClean = process.env.GENARRATIVE_WARNCHECK_SKIP_CLEAN; + for (const pkg of packages) { + if (skipClean && pkg.name === skipClean) continue; + cleanArgs.push('-p', pkg.name); + } + const clean = cargo(cleanArgs, env); const result = spawnSync(bin, [...args, '--message-format=json'], { cwd: repoRoot, encoding: 'utf8', maxBuffer: 256 * 1024 * 1024, + env, }); if (result.error) throw result.error; + + const wanted = new Map(packages.map((pkg) => [normalizeId(pkg.id), pkg.id])); + const rebuilt = new Set(); const seen = new Map(); + const artifacts = new Map(); + let messageTotal = 0; for (const line of (result.stdout ?? '').split('\n')) { const trimmed = line.trim(); if (!trimmed.startsWith('{')) continue; @@ -139,82 +241,184 @@ function collectWarnings(profile) { } catch { continue; } + if (payload.reason === 'compiler-message') messageTotal += 1; + if (payload.reason === 'compiler-artifact') { + const id = normalizeId(payload.package_id); + if (wanted.has(id)) { + artifacts.set(id, payload.fresh === false ? 'rebuilt' : 'fresh'); + if (payload.fresh === false) rebuilt.add(id); + } + continue; + } if (payload.reason !== 'compiler-message') continue; const message = payload.message ?? {}; if (message.level !== 'warning') continue; const text = message.message ?? ''; - // ts-rs 的宏展开提示不是 lint,长期存在且与代码质量无关,不计入门禁。 if (text.includes('failed to parse serde attribute')) continue; - if (message.spans?.length && /generated \d+ warnings?/u.test(text)) - continue; const primary = (message.spans ?? []).find((span) => span.is_primary) ?? message.spans?.[0]; if (!primary) continue; + // cargo 的 span 路径对 workspace 成员是**相对该成员根目录**的(如 src/main.rs), + // 所以先按 manifest 所在目录拼,再回退到仓库根。 + const packageDir = dirname(resolve(repoRoot, profile.manifest)); + const candidates = [ + resolve(packageDir, primary.file_name), + resolve(repoRoot, primary.file_name), + ]; + const absolute = + candidates.find((candidate) => existsSync(candidate)) ?? candidates[0]; + const path = relative(repoRoot, absolute).replaceAll('\\', '/'); + if (!isFirstParty(profile, path)) continue; const key = { - path: normalizePath(primary.file_name), - symbol: symbolOf(text), - lint: lintOf(message.code), + path, + symbol: /`([^`]+)`/u.exec(text)?.[1] ?? text.slice(0, 80), + lint: message.code?.code ?? 'unknown', }; const id = `${key.path}|${key.symbol}|${key.lint}`; if (!seen.has(id)) seen.set(id, { ...key, line: primary.line_start, message: text }); } - // 非 JSON 输出里的硬错误(编译不过)也算失败。 - const stderr = result.stderr ?? ''; - return { warnings: [...seen.values()], exitCode: result.status, stderr }; + return { + warnings: [...seen.values()], + rebuilt: [...rebuilt], + artifacts, + exitCode: result.status, + stderr: result.stderr ?? '', + cleanCmd: cleanArgs, + cleanExit: clean.status, + cleanOut: `${clean.stdout ?? ''}${clean.stderr ?? ''}`.trim(), + artifactDump: [...artifacts.entries()].map( + ([id, state]) => `${id} → ${state}`, + ), + messageCount: messageTotal, + }; } function keyOf(entry) { return `${entry.path}|${entry.symbol}|${entry.lint}`; } -const baseline = loadBaseline(); +function defaultProfiles() { + if (requested.length > 0) return requested; + return Object.keys(PROFILES).filter((name) => + PROFILES[name].platforms.includes(process.platform), + ); +} + +const baseline = existsSync(baselinePath) + ? JSON.parse(readFileSync(baselinePath, 'utf8')) + : { schema: 1, profiles: {} }; const report = {}; let hadNew = false; -let hadFailure = false; +let hadIncomplete = false; for (const name of defaultProfiles()) { - const profile = PROFILES[name]; - if (!profile) { + const profile = { ...PROFILES[name], name }; + if (!PROFILES[name]) { console.error( `[rust-warnings] 未知 profile:${name}(可用:${Object.keys(PROFILES).join(', ')})`, ); process.exit(2); } - const { warnings, exitCode, stderr } = collectWarnings(profile); + const dir = targetDirFor(name); + const env = { ...process.env, CARGO_TARGET_DIR: dir }; + const packages = packageIds(profile); + const { + warnings, + rebuilt, + artifacts, + exitCode, + stderr, + cleanCmd, + cleanExit, + cleanOut, + artifactDump, + messageCount, + } = collectWarnings(profile, packages, env); const known = new Map( (baseline.profiles[name]?.warnings ?? []).map((entry) => [ keyOf(entry), entry, ]), ); - const fresh = warnings.filter((entry) => !known.has(keyOf(entry))); + // 还没有基线条目的 profile = **首次采集**:只打印清单、不判失败(例如 agc-linux 只能由 CI 首跑采集)。 + const collectOnly = !baseline.profiles[name]; + const fresh = collectOnly + ? [] + : warnings.filter((entry) => !known.has(keyOf(entry))); const gone = [...known.values()].filter( (entry) => !warnings.some((w) => keyOf(w) === keyOf(entry)), ); + // **完整性断言 = fresh 断言**:本 profile 的每个 first-party 包都必须在本轮被 clean 后真的重编 + // (出现 compiler-artifact 且 fresh=false)。否则测量不完整(热目录下未重编的 crate 不会重现存量 + // 告警,会给出「新增 0」的假答案)⇒ exit 1。注意:**不**用「条数少于基线」当不完整——真实的清理 + // 会让条数变少,那是正常结果(走「存量减少」提示)。 + const incomplete = + packages.length === 0 || + packages.some((pkg) => !rebuilt.includes(normalizeId(pkg.id))); report[name] = { description: profile.description, + targetDir: dir, + rebuilt: `${rebuilt.size}/${packages.length}`, + artifacts: [...artifacts.entries()].map(([id, state]) => `${id}:${state}`), total: warnings.length, new: fresh, gone, + incomplete, }; if (fresh.length > 0) hadNew = true; - if (exitCode !== 0 && warnings.length === 0) hadFailure = true; + if (incomplete || (exitCode !== 0 && warnings.length === 0)) + hadIncomplete = true; + if (updateBaseline) { baseline.profiles[name] = { description: profile.description, command: profile.command.join(' '), + targetDirPolicy: + 'profile 专属目录(默认 /genarrative-warncheck/;可用 GENARRATIVE_WARNCHECK_TARGET_DIR 覆盖)', + scope: `只收 first-party 告警:${profile.firstParty.join(', ')}`, + baselineNote: + name === 'agc-linux' + ? '本机(Windows)无法编译 Linux 档,条目留空,由 CI 首跑采集后再 --update-baseline 入册。' + : undefined, warnings: warnings .map(({ path, symbol, lint }) => ({ path, symbol, lint })) .sort((a, b) => keyOf(a).localeCompare(keyOf(b))), }; } + if (!asJson) { console.log(`=== ${name}:${profile.description}`); - console.log(` 命令:${profile.command.join(' ')}`); + console.log(` target 目录:${dir}`); console.log( - ` 当前告警 ${warnings.length} 条 / 基线 ${known.size} 条 → 新增 ${fresh.length},存量减少 ${gone.length}`, + ` 命令:${cleanArgsText(profile)} 然后 ${profile.command.join(' ')}`, + ); + if (process.env.GENARRATIVE_WARNCHECK_DEBUG) { + const dump = [` [dump] 包集 ${packages.length} 个:`]; + for (const pkg of packages) + dump.push( + ` name=${pkg.spec} id=${pkg.id}`, + ` manifest=${pkg.manifestPath}`, + ); + dump.push(` [dump] clean:${cleanCmd.join(' ')} → exit ${cleanExit}`); + if (cleanOut) + dump.push(...cleanOut.split('\n').map((line) => ` ${line}`)); + dump.push(' [dump] artifact(package_id → fresh):'); + for (const line of artifactDump) dump.push(` ${line}`); + dump.push( + ` [dump] compiler-message 总数 ${messageCount} 条(其中 first-party 告警 ${warnings.length} 条)`, + ); + const missing = packages + .filter((pkg) => !rebuilt.includes(normalizeId(pkg.id))) + .map((pkg) => `${pkg.name} (${pkg.id})`); + dump.push( + ` [dump] 未重编的成员 ${missing.length} 个:${missing.join(' | ') || '(none)'}`, + ); + console.log(dump.join('\n')); + } + console.log( + ` 本次重编 ${rebuilt.length}/${packages.length} 个包 · 当前 first-party 告警 ${warnings.length} 条 / 基线 ${known.size} 条 → 新增 ${fresh.length},存量减少 ${gone.length}`, ); for (const entry of fresh) { console.log( @@ -226,30 +430,37 @@ for (const name of defaultProfiles()) { console.log( ` [已消除·可更新基线] ${entry.path} | ${entry.lint} | ${entry.symbol}`, ); - if (exitCode !== 0 && warnings.length === 0) { + if (incomplete) { console.error( - ` [失败] cargo 退出码 ${exitCode}(编译不过,先修编译)`, + ` [失败] 测量不完整:${packages.length - rebuilt.length} 个本 profile 的包本次未被重编,读到的告警数不可信。` + + `\n 重跑一次;仍失败就删除 target 目录(${dir})后重试。`, + ); + } else if (exitCode !== 0 && warnings.length === 0) { + console.error( + ` [失败] cargo 退出码 ${exitCode}(编译不过,先修编译)\n${stderr.split('\n').slice(-15).join('\n')}`, ); - console.error(stderr.split('\n').slice(-20).join('\n')); } } } +function cleanArgsText(profile) { + return `cargo clean -p <本 profile 的 ${profile.firstParty.join(' / ')} 包>`; +} + if (updateBaseline) { writeFileSync(baselinePath, `${JSON.stringify(baseline, null, 2)}\n`, 'utf8'); if (!asJson) - console.log(`\n[rust-warnings] 基线已更新:scripts/warning-baseline.json`); + console.log('\n[rust-warnings] 基线已更新:scripts/warning-baseline.json'); } - if (asJson) console.log(JSON.stringify(report, null, 2)); -if (hadFailure) process.exit(1); +if (hadIncomplete) process.exit(1); if (hadNew && !updateBaseline) { if (!asJson) { console.log( - '\n[rust-warnings] 有基线之外的新告警:请先修掉;确实是「存量的一部分」时,用', + '\n[rust-warnings] 有基线之外的新告警:先修掉;确实是存量的一部分时用', ); console.log( - ' node scripts/check-rust-warnings.mjs --profile= --update-baseline 入册并提交基线。', + ' node scripts/check-rust-warnings.mjs --profile= --update-baseline 入册。', ); } process.exit(1); diff --git a/scripts/pre-push-rust-warnings.mjs b/scripts/pre-push-rust-warnings.mjs deleted file mode 100644 index 5f16adec1..000000000 --- a/scripts/pre-push-rust-warnings.mjs +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env node -// pre-push 的 Rust 告警检查入口:只在「本次推送的提交确实碰了 Rust 代码」时才跑, -// 避免无关推送(纯文档/前端)被编译检查拖慢。 -// -// 与 CI 共用同一份检查实现:scripts/check-rust-warnings.mjs(单一真源)。 -// 平台差异:Windows 跑 `agc-windows` + `server-rs`;Linux/macOS 只跑 `server-rs` -// (AGC 壳的 Windows 生产口径只能在 Windows 上编;Linux 档由 CI 的 Rust warning check job 覆盖)。 -// -// 用法(由 .husky/pre-push 调用,stdin 为 `local_ref local_sha remote_ref remote_sha` 行): -// node scripts/pre-push-rust-warnings.mjs < changes.txt - -import { spawnSync } from 'node:child_process'; -import { readFileSync } from 'node:fs'; -import { dirname, resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); -const ZERO = /^0+$/u; -const RUST_RELEVANT = /(\.rs$|Cargo\.toml$|Cargo\.lock$)/u; - -const stdin = readFileSync(0, 'utf8'); -const pushed = []; -for (const line of stdin.split('\n')) { - const [localRef, localSha, remoteRef, remoteSha] = line.trim().split(/\s+/u); - if (!localRef || !localSha || ZERO.test(localSha)) continue; - pushed.push({ localRef, localSha, remoteRef, remoteSha }); -} - -function git(...args) { - const result = spawnSync('git', args, { cwd: repoRoot, encoding: 'utf8' }); - return result.status === 0 ? (result.stdout ?? '').trim() : ''; -} - -const changed = new Set(); -for (const { localSha, remoteSha } of pushed) { - let base = ZERO.test(remoteSha ?? '') ? '' : remoteSha; - if (!base) { - // 新分支/首次推送:用与 origin/master 的合并基点作为比较基线;取不到就用该提交的父提交。 - base = - git('merge-base', 'origin/master', localSha) || - git('rev-parse', `${localSha}^`); - } - if (!base) continue; - for (const path of git('diff', '--name-only', `${base}..${localSha}`).split( - '\n', - )) { - if (path) changed.add(path); - } -} - -const relevant = [...changed].filter((path) => RUST_RELEVANT.test(path)); -if (relevant.length === 0) { - console.log( - `[rust-warnings] 本次推送未触碰 Rust 代码(${changed.size} 个文件),跳过告警检查。`, - ); - process.exit(0); -} - -const profiles = - process.platform === 'win32' ? ['agc-windows', 'server-rs'] : ['server-rs']; -console.log( - `[rust-warnings] 本次推送触碰 Rust 文件 ${relevant.length} 个,检查 profile: ${profiles.join(', ')}`, -); -const args = [ - 'scripts/check-rust-warnings.mjs', - ...profiles.map((name) => `--profile=${name}`), -]; -const result = spawnSync(process.execPath, args, { - cwd: repoRoot, - stdio: 'inherit', -}); -if (result.status !== 0) { - console.error( - '[rust-warnings] 推送被拦下:请先处理上面的新增告警(详见 dev 运维文档「Rust 编译告警门禁」)。', - ); - process.exit(result.status ?? 1); -} diff --git a/scripts/warning-baseline.json b/scripts/warning-baseline.json index 2d592ac3e..97e9fc7be 100644 --- a/scripts/warning-baseline.json +++ b/scripts/warning-baseline.json @@ -4,2254 +4,87 @@ "agc-windows": { "description": "AGC 壳:Windows + 三编辑器 feature 的生产口径(只有 Windows 本机可跑 → 仅 pre-push 覆盖)", "command": "cargo check --locked --features cocos-editor-execute,unity-editor-execute,godot-editor-execute --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml", + "targetDirPolicy": "profile 专属目录(默认 /genarrative-warncheck/;可用 GENARRATIVE_WARNCHECK_TARGET_DIR 覆盖)", + "scope": "只收 first-party 告警:apps/ai-game-creator-shell/src-tauri", "warnings": [ { - "path": "src/command_exec.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/command_exec.rs", "symbol": "resolve_project_bootstrap_spec_at", "lint": "dead_code" }, { - "path": "src/command_exec.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/command_exec.rs", "symbol": "run_project_bootstrap_command_at", "lint": "dead_code" }, { - "path": "src/export/draft/taonier/mod.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/export/draft/taonier/mod.rs", "symbol": "TaonierArtifactPackage", "lint": "unused_imports" }, { - "path": "src/export/draft/taonier/registry.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/export/draft/taonier/registry.rs", "symbol": "read_form", "lint": "dead_code" }, { - "path": "src/export/draft/taonier/script.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/export/draft/taonier/script.rs", "symbol": "package_json_relative", "lint": "dead_code" }, { - "path": "src/game_package_upload.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/game_package_upload.rs", "symbol": "ensure_staging_path_in_dir", "lint": "dead_code" }, { - "path": "src/game_package_upload.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/game_package_upload.rs", "symbol": "GAME_PACKAGE_UPLOAD_PROGRESS_EVENT", "lint": "unused_imports" }, { - "path": "src/game_package_upload/runtime.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/game_package_upload/runtime.rs", "symbol": "GAME_PACKAGE_UPLOAD_PROGRESS_EVENT", "lint": "dead_code" }, { - "path": "src/project.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/project.rs", "symbol": "bootstrap::*", "lint": "unused_imports" }, { - "path": "src/project/bootstrap.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/project/bootstrap.rs", "symbol": "BOOTSTRAP_PACKAGE_MAX_BYTES", "lint": "dead_code" }, { - "path": "src/project/bootstrap.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/project/bootstrap.rs", "symbol": "ProjectBootstrapResult", "lint": "dead_code" }, { - "path": "src/project/bootstrap.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/project/bootstrap.rs", "symbol": "read_bootstrap_file", "lint": "dead_code" }, { - "path": "src/project/bootstrap.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/project/bootstrap.rs", "symbol": "run_project_bootstrap_at", "lint": "dead_code" }, { - "path": "src/project/verification.rs", + "path": "apps/ai-game-creator-shell/src-tauri/src/project/verification.rs", "symbol": "run_project_verification_with_commit_at", "lint": "dead_code" } ] }, - "agc-linux": { - "description": "AGC 壳:Linux target + 三编辑器 feature(CI 覆盖)", - "command": "cargo check --locked --features cocos-editor-execute,unity-editor-execute,godot-editor-execute --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml", - "warnings": [ - { - "path": "account_api.rs", - "symbol": "AGC_CLIENT_MARKER_HEADER", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "AGC_CLIENT_MARKER_VALUE", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "API_RESPONSE_ENVELOPE_HEADER", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "API_RESPONSE_ENVELOPE_VERSION", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "ClientProfileReferralInviteCenter", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "HTTP_TIMEOUT", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "MAX_REDEEM_CODE_CHARS", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "Path", - "lint": "unused_imports" - }, - { - "path": "account_api.rs", - "symbol": "build_client", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "cli::*", - "lint": "unused_imports" - }, - { - "path": "account_api.rs", - "symbol": "confirm_wechat_profile_recharge_order", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "create_profile_recharge_order", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "describe_account_request_failure", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "endpoint", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "identity", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "name", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "new", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "path", - "lint": "unused_variables" - }, - { - "path": "account_api.rs", - "symbol": "project_root", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "read_profile_membership_upgrade_quote", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "read_profile_recharge_center", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "read_profile_referral_invite_center", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "read_profile_wallet_ledger", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "redeem_profile_reward_code", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "report", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "request_json", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "require_session", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "run", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "source", - "lint": "dead_code" - }, - { - "path": "account_api.rs", - "symbol": "std::collections::BTreeSet", - "lint": "unused_imports" - }, - { - "path": "account_api.rs", - "symbol": "std::io", - "lint": "unused_imports" - }, - { - "path": "account_api.rs", - "symbol": "std::mem::drop", - "lint": "unknown" - }, - { - "path": "account_api.rs", - "symbol": "super::*", - "lint": "unused_imports" - }, - { - "path": "account_api.rs", - "symbol": "tauri::Emitter", - "lint": "unused_imports" - }, - { - "path": "account_api.rs", - "symbol": "token", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "ACL_REPAIR_GATE", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "ACL_REPAIR_POLICY", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "AclRepairGateResult", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "AclRepairGate", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "AclRepairKey", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "AclRepairOutcome", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "AclRepairPolicy", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "Entry", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "LeaderGuard", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "Repaired", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "clear_acl_repair_denials", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "complete", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "cooldown_for", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "lock", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "next_leader_id", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "prune", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "recorded_at", - "lint": "dead_code" - }, - { - "path": "acl_repair_gate.rs", - "symbol": "self", - "lint": "unused_imports" - }, - { - "path": "agent.rs", - "symbol": "Digest", - "lint": "unused_imports" - }, - { - "path": "agent.rs", - "symbol": "Sha256", - "lint": "unused_imports" - }, - { - "path": "agent.rs", - "symbol": "codex", - "lint": "dead_code" - }, - { - "path": "agent.rs", - "symbol": "game_creator_claude_code_cli_version_identity", - "lint": "dead_code" - }, - { - "path": "agent/art_manifest.rs", - "symbol": "content", - "lint": "dead_code" - }, - { - "path": "agent/claude_code_cli.rs", - "symbol": "Arc", - "lint": "unused_imports" - }, - { - "path": "agent/claude_code_cli.rs", - "symbol": "claude_agent", - "lint": "dead_code" - }, - { - "path": "agent/claude_code_cli.rs", - "symbol": "memory::*", - "lint": "unused_imports" - }, - { - "path": "agent/claude_code_cli.rs", - "symbol": "model", - "lint": "dead_code" - }, - { - "path": "agent/claude_code_cli.rs", - "symbol": "role", - "lint": "unused_variables" - }, - { - "path": "agent/claude_code_cli.rs", - "symbol": "stream", - "lint": "dead_code" - }, - { - "path": "agent/codex_app_server/execution.rs", - "symbol": "AtomicUsize", - "lint": "unused_imports" - }, - { - "path": "agent/codex_app_server/execution.rs", - "symbol": "bind", - "lint": "dead_code" - }, - { - "path": "agent/codex_app_server/execution.rs", - "symbol": "fixture", - "lint": "dead_code" - }, - { - "path": "agent/codex_app_server/mod.rs", - "symbol": "PermissionsExt", - "lint": "unused_imports" - }, - { - "path": "agent/codex_app_server/mod.rs", - "symbol": "app_data", - "lint": "unused_variables" - }, - { - "path": "agent/codex_app_server/mod.rs", - "symbol": "launch", - "lint": "unused_variables" - }, - { - "path": "agent/codex_app_server/mod.rs", - "symbol": "local_app_data", - "lint": "unused_variables" - }, - { - "path": "agent/codex_app_server/mod.rs", - "symbol": "previous", - "lint": "dead_code" - }, - { - "path": "agent/codex_app_server/mod.rs", - "symbol": "title", - "lint": "dead_code" - }, - { - "path": "agent/codex_cli.rs", - "symbol": "configure_windows_background_tokio_command", - "lint": "dead_code" - }, - { - "path": "agent/codex_cli.rs", - "symbol": "runtime_config_dir", - "lint": "unused_variables" - }, - { - "path": "agent/direct_patch.rs", - "symbol": "PATCH_EXECUTOR_FLAG", - "lint": "dead_code" - }, - { - "path": "agent/direct_patch.rs", - "symbol": "quoted_argument_units", - "lint": "dead_code" - }, - { - "path": "agent/direct_runtime/mod.rs", - "symbol": "Capture", - "lint": "dead_code" - }, - { - "path": "agent/direct_runtime/mod.rs", - "symbol": "SYSTEM_PROMPT", - "lint": "dead_code" - }, - { - "path": "agent/direct_tool_bridge.rs", - "symbol": "execute_godot_editor_code", - "lint": "dead_code" - }, - { - "path": "agent/direct_tool_bridge.rs", - "symbol": "execute_unity_editor_code", - "lint": "dead_code" - }, - { - "path": "agent/direct_tool_bridge.rs", - "symbol": "list_local_project_files", - "lint": "dead_code" - }, - { - "path": "agent/generation.rs", - "symbol": "append_static_smoke_manual_trace_step", - "lint": "dead_code" - }, - { - "path": "agent/generation.rs", - "symbol": "append_static_smoke_manual_trace_step", - "lint": "unused_imports" - }, - { - "path": "agent/generation.rs", - "symbol": "validate_game_html_smoke", - "lint": "dead_code" - }, - { - "path": "agent/generation/canvas_generation.rs", - "symbol": "UploadTicket", - "lint": "dead_code" - }, - { - "path": "agent/generation/canvas_generation.rs", - "symbol": "generate_local_project_asset", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_attribute_value", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_has_attribute", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_non_executable_container_end", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_raw_text_element_name", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_script_executes_in_modern_browser", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_script_is_module", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_script_type_is_executable", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_tag_ends_element", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_tag_end", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_tag_name_has_boundary", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "html_tag_starts_element", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "is_html_ascii_whitespace", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "javascript_is_syntactically_valid", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "javascript_source_type", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "nested_html_element_end", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "next_named_html_tag", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "raw_text_html_element_close", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "raw_text_html_element_end", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "validate_canvas_rendering_html", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "validate_closed_game_script_blocks", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "validate_executable_inline_javascript_syntax", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "validate_non_placeholder_game_html", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "validate_playable_game_html", - "lint": "dead_code" - }, - { - "path": "agent/generation/game_html_validation.rs", - "symbol": "validate_safe_game_html_runtime", - "lint": "dead_code" - }, - { - "path": "agent/generation/trace.rs", - "symbol": "Audio", - "lint": "dead_code" - }, - { - "path": "agent/generation/trace.rs", - "symbol": "LimitedLocalCommandResult", - "lint": "dead_code" - }, - { - "path": "agent/thread_manager/dispatch.rs", - "symbol": "auth_session::*", - "lint": "unused_imports" - }, - { - "path": "asset_generation_tasks.rs", - "symbol": "rename_local_game_project", - "lint": "dead_code" - }, - { - "path": "asset_generation_tasks.rs", - "symbol": "set_asset_generation_task_app_handle", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "CanvasExportMetadata", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "DEFAULT_EDITOR_BASE_URL", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "DeleteLocalProjectAssetResult", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "ImportCanvasExportResult", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "LocalProjectAssetReferenceVersion", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "MAX_CANVAS_EXPORT_BYTES", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "MAX_CANVAS_EXPORT_FILES", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "ReadLocalProjectAssetReferencesResult", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "SyncCanvasProjectAssetsResult", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "asset_referencing_versions", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "build_canvas_project_url", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "delete_manifest_asset_at", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "extract_canvas_export_zip_files", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "import_canvas_export_at", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "infer_canvas_export_media_type", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "normalized_asset_id", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "normalized_zip_entry_name", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "read_canvas_export_metadata_from_zip", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "read_manifest_asset_references_at", - "lint": "dead_code" - }, - { - "path": "assets.rs", - "symbol": "sync_canvas_project_assets_at", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "ClientLoginCodeView", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "SendCodeResponse", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "complete_login", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "current_session_origin", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "initialize_auth_session", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "login_client_with_password", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "login_client_with_phone_code", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "logout_client_session", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "read_client_auth_state", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "refresh_client_auth_session", - "lint": "dead_code" - }, - { - "path": "auth_session.rs", - "symbol": "send_client_phone_login_code", - "lint": "dead_code" - }, - { - "path": "browser/process.rs", - "symbol": "from_launch", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "GameCreatorLlmConfigStatus", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "check_game_creator_llm_config_from_config", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "check_game_creator_llm_config", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "game_creator_llm_status_lines", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "game_creator_preview_registry", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "run_cli_command", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "start_local_game_preview_at", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "stop_local_game_preview_for_root", - "lint": "dead_code" - }, - { - "path": "cli.rs", - "symbol": "take_cli_runtime_config_dir", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "PROJECT_COMMAND_SENSITIVE_GIT_PATHSPECS", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "PROJECT_COMMAND_SENSITIVE_RG_GLOBS", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "argument_matches_option", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "argument_matches_short_option", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "project_command_git_argument_contains_sensitive_object_path", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "project_command_git_path_is_sensitive", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "validate_cargo_arguments", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "validate_git_arguments", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "validate_node_arguments", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "validate_npm_arguments", - "lint": "dead_code" - }, - { - "path": "command_exec.rs", - "symbol": "validate_rg_arguments", - "lint": "dead_code" - }, - { - "path": "command_sandbox_trampoline.rs", - "symbol": "CONTROL_FD", - "lint": "dead_code" - }, - { - "path": "command_sandbox_trampoline.rs", - "symbol": "is_process_session_trampoline_mode", - "lint": "unused_imports" - }, - { - "path": "command_sandbox_trampoline.rs", - "symbol": "random_nonce", - "lint": "dead_code" - }, - { - "path": "command_sandbox_trampoline.rs", - "symbol": "read_frame_if_available", - "lint": "dead_code" - }, - { - "path": "command_sandbox_trampoline.rs", - "symbol": "run_process_session_trampoline", - "lint": "dead_code" - }, - { - "path": "command_sandbox_trampoline.rs", - "symbol": "run_trampoline", - "lint": "dead_code" - }, - { - "path": "command_sandbox_trampoline.rs", - "symbol": "terminate_target", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "AUTOMATIC_PROJECT_NAME_MAX_PROMPT_CHARS", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "GAME_CREATOR_CONFIG_WRITE_LOCK", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "GameCreatorAppConfigView", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "LocalAgentMemoryResult", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "LocalGameMemoryResult", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "LocalProjectDirectoryStatus", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "RenameLocalProjectResult", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "append_local_conversation_message", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "build_automatic_project_name_prompt", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "clear_game_creator_acl_elevation_denials", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "clear_windows_acl_repair_denials", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "closest_existing_project_picker_directory", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "create_automatic_local_game_project_at", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "game_creator_app_config_view", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "game_creator_project_manifest_error", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "game_creator_project_name", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "get_local_game_manifest_sync", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "import_local_godot_project", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "inspect_local_project_directory_sync", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "is_agent_trace_read_path", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "is_chinese_project_name_character", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "is_game_creator_project_directory", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "is_local_project_directory_non_empty", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "is_supported_project_art_media_resource", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "is_supported_project_audio_resource", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "is_supported_project_model_resource", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "load_game_creator_app_config_for_write", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "normalize_suggested_project_name", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "persist_game_creator_app_config", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "project_directory_modified_at", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "read_game_creator_app_config", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "read_local_agent_memory_at", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "read_local_conversation", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "read_local_game_memory_at", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "read_local_project_image_preview_at", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "read_local_project_media_preview_at", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "read_local_project_resource_canvas_layout", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "read_project_permission_policy", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "recent_game_creator_run_trace", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "rename_local_game_project_if_unchanged", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "run_limited_local_command_at", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "select_game_creator_model_inner", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "select_game_creator_model", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "serialize_game_creator_app_config_for_renderer_write", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "update_existing_config_overlay_fields", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "update_local_project_resource_canvas_layout", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "validate_requested_game_project_creation_root", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "write_game_creator_app_config", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "write_game_creator_config_batch", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "write_local_agent_memory_at", - "lint": "dead_code" - }, - { - "path": "commands.rs", - "symbol": "write_local_game_memory_at", - "lint": "dead_code" - }, - { - "path": "commands/desktop.rs", - "symbol": "AgentConversationSessionListResult", - "lint": "dead_code" - }, - { - "path": "commands/desktop.rs", - "symbol": "stored_project_creation_directory", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "DEFAULT_GAME_CREATOR_APP_CONFIG_JSON", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "GAME_CREATOR_REQUIRED_LLM_AGENT_IDS", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "GameCreatorAgentLlmConfigStatus", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "build_game_creator_llm_client_from_config", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "check_game_creator_agent_llm_config_values", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "check_game_creator_codex_app_server_available", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "check_game_creator_codex_cli_available", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "check_game_creator_codex_config", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "check_game_creator_llm_config_values", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "game_creator_claude_code_cli_llm_route_error", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "game_creator_llm_agent_status_definitions", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "game_creator_private_path_allows_auto_elevation", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "inspect_game_creator_runtime_config_dir", - "lint": "dead_code" - }, - { - "path": "config.rs", - "symbol": "normalize_windows_policy_path", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "CreateUiDesignDocFromImagesInput", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "CreateUiDesignDocFromImagesInput", - "lint": "unused_imports" - }, - { - "path": "desktop.rs", - "symbol": "GameCreatorGuiRunnerShutdownFailure", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "GameCreatorGuiRunnerShutdownOutcome", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "UiDesignDocCreated", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "create_ui_design_doc_from_images", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "is_process_session_child_mode", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "migrate_workspace_preferences", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "publish_local_project_game", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "read_game_distribution_publication", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "read_taonier_export_hash", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "read_taonier_export", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "read_workspace_preferences", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "read_xhs_minitool_export_hash", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "read_xhs_minitool_export", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "recognize_ui_impl", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "remember_recent_workspace", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "remove_recent_workspace", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "resolve_game_creator_gui_runner_shutdown", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "run_process_session_child", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "run_taonier_export_build", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "run_xhs_minitool_export_build", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "save_taonier_export_form", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "save_xhs_minitool_export_form", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "separation::separate_ui_impl", - "lint": "unused_imports" - }, - { - "path": "desktop.rs", - "symbol": "set_chat_prompt_polish_reminder_disabled", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "set_client_server_selection", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "set_platform_maintenance_app_handle", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "set_project_creation_directory", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "stop_local_game_preview_on_exit", - "lint": "dead_code" - }, - { - "path": "desktop.rs", - "symbol": "upload_platform_media_asset", - "lint": "dead_code" - }, - { - "path": "editor_adapters.rs", - "symbol": "managed_editor_rpc", - "lint": "dead_code" - }, - { - "path": "editor_adapters/execution.rs", - "symbol": "execute_managed_editor_code", - "lint": "dead_code" - }, - { - "path": "environment_check/web_creation/ownership.rs", - "symbol": "job_name", - "lint": "dead_code" - }, - { - "path": "error_report/submit.rs", - "symbol": "validate_session", - "lint": "dead_code" - }, - { - "path": "export/draft/taonier/commands.rs", - "symbol": "LAST_FAILURE", - "lint": "dead_code" - }, - { - "path": "export/draft/taonier/commands.rs", - "symbol": "MAX_LOGGED_FAILURE_CHARS", - "lint": "dead_code" - }, - { - "path": "export/draft/taonier/commands.rs", - "symbol": "clear_failure", - "lint": "dead_code" - }, - { - "path": "export/draft/taonier/commands.rs", - "symbol": "log_failure", - "lint": "dead_code" - }, - { - "path": "export/draft/taonier/commands.rs", - "symbol": "read_content_hash", - "lint": "dead_code" - }, - { - "path": "export/draft/taonier/commands.rs", - "symbol": "read_content", - "lint": "dead_code" - }, - { - "path": "export/draft/taonier/commands.rs", - "symbol": "run_build", - "lint": "dead_code" - }, - { - "path": "export/draft/taonier/commands.rs", - "symbol": "save_form", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "CreatedGame", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "CreatedVersion", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "GameDistributionPublicationDraft", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "GameDistributionPublicationImageDraft", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "GameDistributionPublicationReadResult", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "GameDistributionPublishResult", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "GameDistributionReadError", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "GamePackageUploadOutcome", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "GamePackageUploadRequest", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "MAX_GAME_PRICE_MUD_POINTS", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "MAX_SAFE_VERSION_NUMBER", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "PACKAGE_UPLOAD_PROGRESS_EVENT", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "SubmittedVersionSummary", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "SubmittedVersion", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "bound_publication_result", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "build_publication_draft", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "clear_publication_binding", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "current_scoped_session", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "describe_distribution_request_failure", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "emit_publish_progress", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "fetch_frozen_metadata", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "first_publish_state", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "game_package_upload_staging_dir", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "multipart_image_part", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "parse_input_modes", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "parse_orientation", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "pick_non_empty", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "progress_event_payload", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "publish_multipart_form", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "request_json_for_read", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "request_multipart", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "require_platform_session", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "resolve_preview_url", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "scoped_request", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "send_json_request", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "stage_publish_package", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "unavailable_state", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "upload_staged_game_package", - "lint": "dead_code" - }, - { - "path": "game_distribution_publish.rs", - "symbol": "write_publication_binding", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "CHUNK_MAX_ATTEMPTS", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "CHUNK_RETRY_DELAY", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "ChunkUploadError", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "MAX_CHUNK_BYTES", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "PackageUploadState", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "ReadUploadState", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "UPLOAD_OFFSET_HEADER", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "UPLOAD_STAGING_DIR_NAME", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "complete_upload", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "current_access_token", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "platform_request", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "read_chunk", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "read_upload_state", - "lint": "dead_code" - }, - { - "path": "game_package_upload/runtime.rs", - "symbol": "upload_chunk", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "AgentGroupDefinition", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "AgentRoleDefinition", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "GAME_CREATOR_AGENT_GROUP_DEFINITIONS", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "GameCreatorLlmAgentStatusDefinition", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "LocalGameProjectRevisionStatus", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "PROJECT_SUPERVISOR_AGENT_DEFINITION", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "classify_game_creator_gui_runner_shutdown_error", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "game_creator_gui_run_event_requests_runner_shutdown", - "lint": "dead_code" - }, - { - "path": "main.rs", - "symbol": "llm_catalog::load_game_creator_llm_models", - "lint": "unused_imports" - }, - { - "path": "main.rs", - "symbol": "platform_asset_upload::upload_platform_media_asset", - "lint": "unused_imports" - }, - { - "path": "platform_asset_upload.rs", - "symbol": "PlatformAssetUploadResult", - "lint": "dead_code" - }, - { - "path": "platform_asset_upload.rs", - "symbol": "confirm_object", - "lint": "dead_code" - }, - { - "path": "platform_asset_upload.rs", - "symbol": "confirm_route", - "lint": "dead_code" - }, - { - "path": "platform_asset_upload.rs", - "symbol": "request_ticket", - "lint": "dead_code" - }, - { - "path": "platform_asset_upload.rs", - "symbol": "upload_object", - "lint": "dead_code" - }, - { - "path": "platform_asset_upload.rs", - "symbol": "upload_route", - "lint": "dead_code" - }, - { - "path": "platform_maintenance.rs", - "symbol": "platform_maintenance_event_test_count", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "GAME_CREATOR_PREVIEW_REGISTRY", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "filter_preview_status_for_project", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "get_local_game_preview_status_at", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "get_local_game_project_revision_at", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "preview_open_url", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "set_running", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "start_local_game_preview_at_revision", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "stop_local_game_preview_if_matches_at", - "lint": "dead_code" - }, - { - "path": "preview.rs", - "symbol": "validate_preview_open_project", - "lint": "dead_code" - }, - { - "path": "process_session/model.rs", - "symbol": "PROCESS_SESSION_CHILD_MODE", - "lint": "dead_code" - }, - { - "path": "process_session/model.rs", - "symbol": "PROCESS_SESSION_OWNER_PID_ENV", - "lint": "dead_code" - }, - { - "path": "process_session/model.rs", - "symbol": "run_process_session_bridge_child", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "PROCESS_SESSION_BRIDGE_ENDPOINT_ENV", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "PROCESS_SESSION_BRIDGE_NONCE_ENV", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "ProcessSessionBridgeServer", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "ProcessSessionBridge", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "ProcessSessionExecVerdict", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "ProcessSessionSandboxReadyVerdict", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "ProcessSessionTerminalVerdict", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "abort_staged_child", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "encode_hex", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "nonce_hex", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "peer_credentials", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "start_owner_monitor", - "lint": "dead_code" - }, - { - "path": "process_session_bridge.rs", - "symbol": "valid_failure_kind", - "lint": "dead_code" - }, - { - "path": "project/filesystem.rs", - "symbol": "acl_repair_attempted", - "lint": "dead_code" - }, - { - "path": "project/memory.rs", - "symbol": "GAME_CREATOR_PROJECT_SUPERVISOR_MEMORY_PATH", - "lint": "dead_code" - }, - { - "path": "project/memory.rs", - "symbol": "agent_role_memory_relative_path_for_task", - "lint": "dead_code" - }, - { - "path": "project/memory.rs", - "symbol": "agent_role_memory_relative_path", - "lint": "dead_code" - }, - { - "path": "project/memory.rs", - "symbol": "memory_file_path", - "lint": "dead_code" - }, - { - "path": "project/verification.rs", - "symbol": "validate_project_game_entry", - "lint": "dead_code" - }, - { - "path": "runner/client.rs", - "symbol": "endpoint_path", - "lint": "dead_code" - }, - { - "path": "runner/client.rs", - "symbol": "set_external_agent_runner_config_dir", - "lint": "dead_code" - }, - { - "path": "src/command_exec.rs", - "symbol": "resolve_project_bootstrap_spec_at", - "lint": "dead_code" - }, - { - "path": "src/command_exec.rs", - "symbol": "run_project_bootstrap_command_at", - "lint": "dead_code" - }, - { - "path": "src/export/draft/taonier/mod.rs", - "symbol": "TaonierArtifactPackage", - "lint": "unused_imports" - }, - { - "path": "src/export/draft/taonier/registry.rs", - "symbol": "read_form", - "lint": "dead_code" - }, - { - "path": "src/export/draft/taonier/script.rs", - "symbol": "package_json_relative", - "lint": "dead_code" - }, - { - "path": "src/game_package_upload.rs", - "symbol": "GAME_PACKAGE_UPLOAD_PROGRESS_EVENT", - "lint": "unused_imports" - }, - { - "path": "src/game_package_upload.rs", - "symbol": "ensure_staging_path_in_dir", - "lint": "dead_code" - }, - { - "path": "src/game_package_upload/runtime.rs", - "symbol": "GAME_PACKAGE_UPLOAD_PROGRESS_EVENT", - "lint": "dead_code" - }, - { - "path": "src/project.rs", - "symbol": "bootstrap::*", - "lint": "unused_imports" - }, - { - "path": "src/project/bootstrap.rs", - "symbol": "BOOTSTRAP_PACKAGE_MAX_BYTES", - "lint": "dead_code" - }, - { - "path": "src/project/bootstrap.rs", - "symbol": "ProjectBootstrapResult", - "lint": "dead_code" - }, - { - "path": "src/project/bootstrap.rs", - "symbol": "read_bootstrap_file", - "lint": "dead_code" - }, - { - "path": "src/project/bootstrap.rs", - "symbol": "run_project_bootstrap_at", - "lint": "dead_code" - }, - { - "path": "src/project/verification.rs", - "symbol": "run_project_verification_with_commit_at", - "lint": "dead_code" - }, - { - "path": "template_library.rs", - "symbol": "unique_project_path", - "lint": "dead_code" - }, - { - "path": "tests/mod.rs", - "symbol": "TEST_PROJECT_COUNTER", - "lint": "dead_code" - }, - { - "path": "tests/mod.rs", - "symbol": "TestConfigGuard", - "lint": "dead_code" - }, - { - "path": "tests/mod.rs", - "symbol": "final_tool_plan_response", - "lint": "dead_code" - }, - { - "path": "tests/mod.rs", - "symbol": "replace_test_local_config", - "lint": "dead_code" - }, - { - "path": "tests/mod.rs", - "symbol": "spawn_mock_llm_server_responses_with_capture", - "lint": "dead_code" - }, - { - "path": "tests/mod.rs", - "symbol": "spawn_mock_llm_server_responses", - "lint": "dead_code" - }, - { - "path": "tests/mod.rs", - "symbol": "test_local_config_path", - "lint": "dead_code" - }, - { - "path": "tests/mod.rs", - "symbol": "write_test_local_config", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "ResolvedDesignImage", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "UiDesignDocumentImage", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "UiDesignImageReference", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "create_ui_design_document_file", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "design_image_media_type", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "drop_manifest_assets", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "initialize_ui_design_state_with_images_at", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "next_ui_design_path", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "prepare_design_images", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "require_image_media_type", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "resolve_design_image", - "lint": "dead_code" - }, - { - "path": "ui_editor/agent_tools/creation.rs", - "symbol": "rollback_created_document", - "lint": "dead_code" - }, - { - "path": "ui_editor/commands/recognition.rs", - "symbol": "required_tool_call_arguments", - "lint": "dead_code" - }, - { - "path": "windows.rs", - "symbol": "launcher_window_url", - "lint": "dead_code" - }, - { - "path": "windows.rs", - "symbol": "percent_encode_query_value", - "lint": "dead_code" - }, - { - "path": "windows.rs", - "symbol": "validate_workspace_window_project_path", - "lint": "dead_code" - }, - { - "path": "windows.rs", - "symbol": "workspace_window_url", - "lint": "dead_code" - }, - { - "path": "workspace_preferences.rs", - "symbol": "WORKSPACE_PREFERENCES_CHANGED_EVENT", - "lint": "dead_code" - }, - { - "path": "workspace_preferences.rs", - "symbol": "read_preferences_for_app", - "lint": "dead_code" - }, - { - "path": "workspace_preferences.rs", - "symbol": "update_preferences_for_app", - "lint": "dead_code" - }, - { - "path": "workspace_preferences.rs", - "symbol": "with_preferences_lock", - "lint": "dead_code" - }, - { - "path": "workspace_preferences.rs", - "symbol": "workspace_preferences_path", - "lint": "dead_code" - } - ] - }, "server-rs": { - "description": "server-rs workspace(Linux/Windows 都可跑)", + "description": "server-rs workspace(Linux/Windows 都可跑;CI 与 pre-push 共用)", "command": "cargo check --locked --workspace --all-targets --manifest-path server-rs/Cargo.toml", + "targetDirPolicy": "profile 专属目录(默认 /genarrative-warncheck/;可用 GENARRATIVE_WARNCHECK_TARGET_DIR 覆盖)", + "scope": "只收 first-party 告警:server-rs", "warnings": [] } } -} \ No newline at end of file +}