From 3369f76b16c6c114295da310eea9a39505bc0f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Mon, 5 Oct 2026 16:30:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=B7=A5=E4=BD=9C=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=20.export=20=E5=8F=AA=E6=8E=92=E9=99=A4=E5=9C=A8?= =?UTF-8?q?=E5=BF=AB=E7=85=A7=E5=90=8C=E6=AD=A5=E4=B9=8B=E5=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - filesystem.rs 新增 PROJECT_SNAPSHOT_SYNC_ONLY_EXCLUDED_COMPONENTS(当前只有 .export):导出注册表、打包脚本拷贝、icon 与 zip 产物都能从项目源码重跑出来,不进项目快照同步。 - 刻意不并入通用排除列表:那份列表同时是 Agent 的写入门禁(agent/direct_patch.rs 直接拿它拒绝路径,agc_apply_patch 报「不得修改受保护或排除路径」),并进去会让 code agent 写不了 .export/ 下的适配脚本。 - project_snapshot 测试补齐两侧口径:.export/* 必须被同步排除,且不得被通用口径排除。 --- .../src-tauri/src/project/filesystem.rs | 21 ++++++++++++++++++- .../src-tauri/src/project_snapshot/tests.rs | 14 +++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/project/filesystem.rs b/apps/ai-game-creator-shell/src-tauri/src/project/filesystem.rs index bb5b21789..d7b6ddac4 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/project/filesystem.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/project/filesystem.rs @@ -416,6 +416,9 @@ pub(crate) fn should_skip_project_snapshot_path(relative_path: &str) -> bool { * * 其余排除项在 `.agent` 内同样生效:版本库、依赖与构建目录、凭据目录、敏感后缀、 * `.env*` 与凭据类文件名一律不参与同步;符号链接与重解析点在扫描阶段单独跳过。 + * + * 另外,同步还多认 `PROJECT_SNAPSHOT_SYNC_ONLY_EXCLUDED_COMPONENTS`(`.export`):本机派生 + * 的导出工作目录不进同步,但 Agent 仍要能读写它。 */ pub(crate) fn should_skip_project_snapshot_sync_path(relative_path: &str) -> bool { project_snapshot_path_is_excluded(relative_path, true) @@ -488,6 +491,18 @@ const PROJECT_SNAPSHOT_EXCLUDED_SUFFIXES: &[&str] = &[ /// 随快照同步;其它数据库与转储后缀仍然排除。 const PROJECT_AGENT_STATE_DATABASE_SUFFIXES: &[&str] = &[".db", ".db-wal", ".db-shm"]; +/** + * 只对快照同步生效的排除组件。 + * + * 不能并进上面的通用列表:那份列表同时是 Agent 的写入门禁(`agent/direct_patch.rs` 直接拿它 + * 拒绝路径),而 `.export` 恰恰必须让 code agent 能写——导出注册表、打包脚本拷贝都由它生成。 + * 放进去会让 `agc_apply_patch` 回「不得修改受保护或排除路径」,首次适配直接卡死。 + * + * `.export` 是本机派生的导出工作目录:注册表、脚本拷贝、icon 与 zip 产物都能从项目源码重跑 + * 出来,zip 动辄数 MB,因此不进快照同步;换机或恢复后重新适配即可。 + */ +const PROJECT_SNAPSHOT_SYNC_ONLY_EXCLUDED_COMPONENTS: &[&str] = &[".export"]; + fn project_snapshot_path_is_excluded(relative_path: &str, include_agent_state: bool) -> bool { let components = relative_path .split('/') @@ -497,7 +512,11 @@ fn project_snapshot_path_is_excluded(relative_path: &str, include_agent_state: b if components.iter().any(|component| { PROJECT_SNAPSHOT_EXCLUDED_COMPONENTS.contains(&component.as_str()) && !(include_agent_state && component == ".agent") - }) { + }) || (include_agent_state + && components.iter().any(|component| { + PROJECT_SNAPSHOT_SYNC_ONLY_EXCLUDED_COMPONENTS.contains(&component.as_str()) + })) + { return true; } let Some(file_name) = components.last() else { diff --git a/apps/ai-game-creator-shell/src-tauri/src/project_snapshot/tests.rs b/apps/ai-game-creator-shell/src-tauri/src/project_snapshot/tests.rs index 73a7209c2..ae318018f 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/project_snapshot/tests.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/project_snapshot/tests.rs @@ -214,6 +214,11 @@ fn project_snapshot_sync_policy_keeps_agent_state_and_still_blocks_credentials() "node_modules/pkg/index.js", "game/dist/bundle.js", "secrets/key.pem", + // 导出工作目录整体不进快照:zip 与脚本拷贝都能从项目源码重新跑出来。 + ".export/xhs-minitool.zip", + ".export/xhs-minitool.json", + ".export/xhs-minitool.pack.mjs", + ".EXPORT/xhs-minitool.zip", "", ] { assert!( @@ -226,6 +231,15 @@ fn project_snapshot_sync_policy_keeps_agent_state_and_still_blocks_credentials() assert!(should_skip_project_snapshot_path(".agent/manifest.json")); assert!(should_skip_project_index_path(".agent/manifest.json")); assert!(should_skip_project_index_path(".agent/agent.db")); + + // `.export/` 只排除在快照同步之外:通用口径同时是 Agent 的写入门禁 + // (`agc_apply_patch` 直接拿它拒路径),一并拒掉会让 code agent 写不了适配脚本。 + assert!(!should_skip_project_snapshot_path( + ".export/xhs-minitool.pack.mjs" + )); + assert!(!should_skip_project_snapshot_path( + ".export/xhs-minitool.json" + )); } #[test]