diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md
index 56de09ed7..edd6b128a 100644
--- a/docs/project-memory/shared-memory/decision-log.md
+++ b/docs/project-memory/shared-memory/decision-log.md
@@ -8270,3 +8270,22 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 帧对齐:`imageSequenceFrames` 里**真正指向被改名文件**的本地帧对齐到新路径;判据是 `imageSrc` 为本地相对路径(非绝对路径、非带 scheme 的地址、非反斜杠路径),目录与旧文件目录一致且文件名与旧名一致(大小写不敏感)。同目录但指向别的文件的帧保持原样,避免改名连带改坏其它引用;`kind` / `mediaType` / `source` / `category` / `tags` 全部不变。
- 已知中间状态:本切片只落 Rust 侧,前端调用方与 UI 在其他工作包;在 UI 落地前 `npm run ai-game-creator-shell:typecheck` 会因 `check-config.mjs` 要求“每个 Tauri 命令都有 App invoke 调用方”而失败,这是刻意保留的中间状态,**不要**把该命令加进 native-only 白名单来换绿。
- 验证:`cargo test --bin genarrative-ai-game-creator-shell asset_rename` 9/9 通过(成功改名与 id 不变、同名空操作、空名 / 分隔符 / `..` 拒绝、跨目录拒绝、扩展名不一致拒绝、目标同名冲突拒绝、assetId 与文件缺失拒绝、manifest 写失败回滚、同目录帧对齐);`cargo check --all-targets` 通过;AGC 前端 69 个测试文件 / 1049 用例全绿。
+
+## 2026-09-10 AGC 资源画布基础能力收口:撤销重做、资源面板、上传与显式下载
+
+- **撤销重做**:作用于**资源卡布局**,不是图层也不是素材。`features/resource-canvas/resourceCanvasHistoryModel.ts` 是纯函数有界快照栈(`capture` / `push` / `undo` / `redo` / `clear`,外加"只回写差异位置"的 `resolveResourceCanvasRestoreEntries`),快照只含坐标与 `manuallyPlaced`;写回复用现役 `commitPosition` 手动 CAS 写链。**不回滚素材文件**(素材不可变是硬约束)。快捷键 `Ctrl/Cmd+Z`、`Ctrl/Cmd+Shift+Z`、`Ctrl+Y`,输入框内不拦截;项目切换清空历史。明确**不**复用 `packages/image-canvas-core` 的 `CanvasHistorySnapshot`(它与 layers/dialogs 强耦合,套到卡片布局上会引入错误的语义)。
+- **资源面板**:`features/resource-canvas/ResourceCanvasPanelView.tsx` 是**独立浮层面板**(自带 dialog 层,不追加在其它面板下方),承载预览网格 / 上传 / 下载 / 多选;多选**直接读写画布同一份 `selectedResourceIds`**,不建第二套选择状态。
+- **上传**:`` → `upload_local_asset`(落 `assets/uploads/-` 并登记 manifest)→ 回读 manifest 刷新;只接受图片/音频/视频。
+- **下载改为显式保存链路**(关键决策):AGC 未注册 `on_download`,`` 在 WebView2 里拿不到"确实落盘"的证据,所以**不做**浏览器式下载。改为前端 `@tauri-apps/plugin-dialog` 的 `save()` 取目标路径 + 新 Tauri 命令 `save_local_project_asset_file(projectPath, relativePath, destinationPath)` 复制文件;`capabilities/main.json` 需 `dialog:allow-save`。Rust 侧校验项目根、相对路径归一化、源必须是真实普通文件(拒绝符号链接与目录)、目标非空且父目录存在、目标不能是目录,64 KiB 分块流式复制(不进整文件内存)。
+- **验证**:`asset_export` 5 条(成功复制含内容一致与 byteLen、缺失源拒绝、空目标拒绝、父目录不存在拒绝等)+ `resourceCanvasHistoryModel` 7 条;AGC 全量 1092 passed / 4 skipped / 0 failed;共享组件 1385 passed。
+- **关联**:`apps/ai-game-creator-shell/src/features/resource-canvas/`、`src-tauri/src/project/asset_export.rs`、`apps/ai-game-creator-shell/src-tauri/capabilities/main.json`。
+
+## 2026-09-10 AGC 运行模块版本切换、参考图弹窗与标签库
+
+- **版本状态唯一一份**:`activeVersionId` 放在 `features/app-shell/WorkspaceLauncher.tsx` 的 `WorkspaceLauncherShell`(它同时渲染资源画布与 supervisor,能同时喂两边),再经 `App.tsx` 的 `activeVersionId` prop 传给 `ProjectWorkspaceChatPane` / `SupervisorChatOnlyView` / `ResourceReferenceInput`。换项目、或选中的版本已不在 manifest(例如被连带删除)时清回 `null`(= 最新版本)。**不新建第二套版本状态**,`App.tsx` 的 `chatActiveVersionId` 占位只是接线点。
+- **版本入口**:运行模块 `game-run-surface` 右上角 `GameRunVersionPicker`,数据只来自 manifest `versions[]`,**没有版本时整块不渲染**;展示口径统一为共享映射 `ITERATION_VERSION_LABELS` / `formatIterationVersionLabel`(`initial` 初始版本 / `resource-replacement` 资源替换 / `agent-revision` 智能体修订 + 创建时间)。
+- **切换版本对预览做了什么**:只改记录层状态并复用既有 `onPlay`(`requestCurrentProjectPlay`)重载当前预览,模式为"运行中"时才触发。**不做运行时资源重映射**——素材不可变,版本之间没变的资源本来就是同一份磁盘文件。若要做到"历史版本独有的资源集合被运行时按版本加载",需要新的版本化资源解析机制(版本化清单 + 预览进程按版本解析路径),本轮**未做也已登记**。
+- **参考图弹窗**:`src/components/image-editor/ImageCanvasProjectAssetPickerDialog.tsx`(独立弹窗、网格卡片、多选、逐个取消、已选计数、清空只清当前选择、取消不改原选择),入口挂在生成 composer 参考图来源菜单的"从项目素材中选择"(`onRequestProjectAssetPicker` 不传就不出现,原有两条来源路径不动)。筛选条抽到共享层 `packages/shared/src/components/PlatformResourceFilterBar.tsx`,画布与弹窗共用同一受控组件但**各自持有独立筛选状态**。**快照**:确认时把选中素材转成 `CharacterReferenceImage`(`sourceAssetId` = 素材 id)走既有 `createGenerationInputReference` 落进 `generationInputs.references`(`refType: 'asset'`),随既有提交链路持久化,**零后端改动**。
+- **标签库**:`packages/shared/src/contracts/gameCreationAppAssetTagLibrary.ts` 纯派生(沿用写入路径的 `normalizeGameCreationAppAssetTags` 归一化,按"使用次数降序 → 标签 `zh-CN` 升序"稳定排序并带 `assetIds`),**不新增持久化字段**;画布按标签筛选与 `category` 筛选可叠加,且与 `@` 面板、参考图弹窗的筛选状态互相独立。
+- **素材重命名前端**:入口挂在资源卡选中工具条的 `extraActions`(与"分类与标签"并列),严格按 `invoke('rename_local_project_asset', { input: { projectPath, assetId, newFileName } })` 三字段调用(Rust 侧 `deny_unknown_fields`),成功后复用既有 `reloadManifestAfterAssetCommand` 刷新卡片与 `@` 面板显示名。上文记录的"重命名只落 Rust 侧"的**已知中间状态到此结束**:前端调用方已落地。
+- **验证**:`typecheck`(含 `check-config`)exit 0;AGC 全量 1092 passed / 4 skipped / 0 failed;共享组件 1385 passed;`cargo check --all-targets` 通过;编码检查与 `git diff --check` 干净。