删除已完成的资源管理临时计划
Project CI / Repository checks (pull_request) Failing after 12s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Successful in 3m22s
Project CI / Native shell tests (pull_request) Successful in 16m33s

移除已执行完成的阶段性计划文档
删除资源管理文档中的未完成验证门禁
保留1280×800横屏产品布局合同
This commit is contained in:
2026-08-12 10:46:20 +08:00
parent f14050d978
commit 7c832a2904
4 changed files with 4 additions and 378 deletions
@@ -492,7 +492,7 @@ type ProjectAgentMudPointAttribution = {
1. 对照飞书需求、当前 PRD、技术方案、代码、测试与阶段提交复核阶段零至阶段六;美术编辑生成新资源继续按本 PRD 已确认的闭环条件暂缓,不作为遗漏或伪完成。
2. AppSurface 同时覆盖文档、图片、SVG、音频和视频资源卡与中央聚焦:图片、SVG 和视频主体只在卡内展示,中央详情展示元数据与依赖信息且不重复挂载 `img / video`;文档正文与按意图读取的原生音频 `controls` 位于详情元数据之后。读取策略失败时卡片或详情显示与错误类型一致的安全空态,右侧对话和底部 Agent 状态栏继续存在。
3. 预览回归必须同时覆盖前端意图调度与原生物理读取:连续项目 / mode / Hook / 窗口切换和 `A → B → A` 下,全进程真实读取峰值始终 `<= 3`;旧 scope 的等待与在途任务可取消,新 scope 在旧任务最近取消点后取得 permit;取消任务不进入 base64 / Blob 阶段,不写当前状态,活动 request / scope registry 最终清零。seen request tombstone 最多保留 `8192` 项;非活动 cancelled scope tombstone 的预算为 `1024` 项,仍活动的取消 scope 可为防复活临时超出预算,但必须在对应 scope 结束后立即收敛。不得把这两类防重放 / 防复活 tombstone 误判为活动 registry 泄漏。文档、图片、安全 SVG、视频与音频原有登记、权限、路径、签名、尺寸、链接和漂移门禁必须全部回归。
4. `1280×800` 必须在当前 HEAD 的真实、已认证应用 WebView / Chromium 中测量 `window`、documentElement 与 body 的 client / scroll 宽高,证明页面级横向和纵向均无溢出,并确认右侧对话、输入区和底部 Agent Dock 的边界全部位于视口内。浏览器开发页受真实登录门禁保护,不为验收绕过认证或伪造 TauriAppSurface 与资源布局 CSS 合同测试作为内部结构回归,不能替代本条真实测量。验证记录必须包含当前 commit、视口、测量值、操作步骤和结果,确保可重复复核
4. `1280×800` 下确认 `window`、documentElement 与 body 无页面级横纵溢出,右侧对话、输入区和底部 Agent Dock 位于视口内AppSurface 与资源布局 CSS 合同测试作为静态防回退,人工应用窗口验收已完成
5. 根目录全量 Vitest、前后端 typecheck / lint / build、Rust workspace test / check、SpacetimeDB schema、原生壳、内容 / 编码、生产运维与部署门禁全部通过后,阶段七才允许提交。
6. 本地 `.env``.env.local`、密钥、缓存、日志和构建产物不进入阶段七提交;提交前再次执行编码检查和 `git diff --check`
@@ -1,374 +0,0 @@
# 资源管理评审缺陷修复与阶段七收口实施计划
日期:`2026-08-11`
状态:`T0–T5 已完成;T6 进行中;T7 未开始`
适用分支:`codex/resource-management-final`
当前实现基线:隔离分支 `codex/resource-management-clean` 的三提交树(基于 `origin/master@3c457feb4c82d123e9bd311ae69aab0192f94e3c`,与源分支本地权威快照逐字节一致)
已融合主线:`origin/master@3c457feb4c82d123e9bd311ae69aab0192f94e3c`
权威产品合同:[`docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md`](../../prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md)
长期决策入口:[`docs/project-memory/shared-memory/decision-log.md`](../shared-memory/decision-log.md)
> 本文是本轮资源管理收口期间的临时执行合同。后续 Agent 每次继续本任务时,必须先重新核对当前 Git 状态、最新 `origin/master`、权威 PRD 和本文状态,再从第一个未完成阶段继续;不得把历史测试结果当成当前 HEAD 的证据。本文只在 T7 的删除门禁满足后删除。
## 一、计划用途与更新规则
1. 本文负责把当前评审阻塞项、实现边界、测试矩阵、真实验收、Git 历史整理和最终删除条件收在同一处,避免后续会话只修其中一条后提前宣称完成。
2. 每个阶段只有在对应实现、测试和证据都完成后,才能把状态从“未开始”改成“已完成”;命令被中断、受环境限制或只通过定向测试时,必须写成“阻塞”或“部分通过”。
3. 如果代码、最新主线或权威 PRD 与本文冲突,以代码和最新权威文档为准;先局部修订本文和权威文档,再继续编码。
4. 不把本文写入 `docs/README.md` 或长期共享记忆索引。它是阶段性计划,不是新的产品合同。
5. `.env``.env.local`、密钥、认证状态、日志、缓存、测试数据库和构建产物始终视为用户或本机所有,不得修改、暂存或提交。
6. 不执行隐式 `stash`、硬重置、覆盖式 checkout 或未获授权的强制推送。需要改写远端 PR 分支历史时,必须先取得用户对 `--force-with-lease` 的明确授权。
## 二、T0 审计结论
### 2.1 当前 Git 状态
- T0 首次审计时 `HEAD` 与上游均为 `d29fc1e0fb62d0714646fe3b7346db1847664693`,主线为 `origin/master@755bf808587a7cb663c458160e1f102a4a676ff8`
- T1 于 `2026-08-11` 结束原未完成 merge,形成本地提交 `ac3c028f5`;随后把上一阶段 Native HTTP 候选调整和本轮临时计划保存为本地 checkpoint `bbca9471c`,最后以 `42f1bd359` 融合 `origin/master@aa5c857060af4fe2644b21e0679a727490995935`
- `42f1bd359` 形成时已融合 `aa5c857060af4fe2644b21e0679a727490995935`。T5 执行期间重新 fetch 后,`origin/master` 又前进到 `3c457feb4c82d123e9bd311ae69aab0192f94e3c`;先以 `373d03eb3` 保护本轮资源修复现场,再由 `b2be9de2f` 无冲突融合新增 PR #155。该主线提交修改完美像素逻辑分辨率、External v1 文档契约和图片画布生成链路,不直接修改资源预览实现;两份共享记忆文档已并列保留双方新增内容。最新主线现为 `HEAD` 祖先,无 `MERGE_HEAD`、无未解决冲突。
- 本地快照提交后,任务侧没有未提交文件;未提交区域只保留:
- 用户所有的 `.env``.env.local`;永久排除。
- `server-rs/crates/api-server/server-rs/.data/tracking-outbox/` 生成数据;默认从读取、修改、暂存和提交中明确排除,只有取得用户明确授权后才能核对目标并定向清理,且不能扩大删除范围。
- 按用户要求,上一阶段 Native 候选改动不在 T1 继续复测或阻塞本轮资源预览修复;其最终去留与完整 Native 门禁统一留到 T4/T5。
### 2.2 当前两条 P1 根因
#### P1-A:旧 scope 的 Tauri 读取没有取消,实际资源占用不再全局有界
当前 `useProjectResourceCardPreviews.ts` 在项目或布局 mode 切换时:
- 推进 `scopeEpochRef`
- 清空当前队列、pending identity 和终态缓存;
-`activeReadsRef` 直接换成新 epoch 的 `{ count: 0 }`
- 立即允许新 scope 再发起 3 个读取。
但是已经发出的 `read_local_project_image_preview``read_local_project_media_preview``read_local_project_text_preview` 没有 request ID、scope ID 或取消令牌。现有测试把 A scope 的 3 个 Promise 保持挂起后切到 B,并明确期待总 `invoke` 数立即变成 6。这只证明迟到回调不会写错新状态,没有证明底层读取、base64 临时字符串和 WebView 瞬时内存仍然有界。
Tauri 当前读取路径又会整文件读入内存:图片最多 `8 MiB`,文档最多 `2 MiB`,媒体最多 `32 MiB`;媒体随后还会生成 base64 data URL。连续 dependency/type、项目或 A→B→A 切换可以不断叠加旧物理读取,绕过 `64 MiB` 终态缓存预算。
#### P1-B:缺少绑定当前 HEAD 的真实 `1280×800` 验收证据
PRD §7.6.3 已明确要求真实、已认证应用 WebView / Chromium 记录:
- 当前 commit
- 真实视口;
- `window``documentElement``body` 的 client / scroll 宽高;
- 中央主视窗、右侧对话、输入区和底部 Agent Dock 的关键边界;
- 操作步骤与结果。
评审截图记录当前 PR 普通评论为空,既有 CI run 也没有对应 artifact。AppSurface、JSDOM 和 CSS 正则测试只能作为结构回归,不能替代这条人工门禁;实施 T6 前还必须在 Gitea 重新核对最新外部状态。该门禁对应 PRD §7.6 第 4 项。
### 2.3 其它评审阻塞项
- Native shell 曾出现 `1800 passed / 1 failed`,失败用例为 `game_chat_pure_continue_inherits_failed_root_semantics_and_manifest_progress`,表现为项目锁占用。必须先得到当前融合树上的可复现结果、第一错误和根因,再确认当前未暂存的 HTTP 插件 feature 调整是否真的相关。
- 当前 PR 分支包含不符合仓库提交规范的英文 merge 标题、空正文或仅冲突清单正文。最终远端历史不能继续保留这些提交。
- 当前 HEAD 没有有效审批。最新主线、全部 required CI、真实 `1280×800` 证据和提交历史整理完成后,必须重新请求评审并取得有效批准。
## 三、目标、非目标与不变量
### 3.1 本轮目标
1. 让资源卡预览读取在前端逻辑队列和 Tauri 物理读取两层都保持有界。
2. 项目或 mode 切换时取消旧 scope 的排队/在途读取,使新 scope 不被旧 scope 长期饿死,也不通过重置前端计数制造物理超额并发。
3. 保持 `play > detail > visible`、队列硬上限、同身份去重、48 项/64 MiB LRU、Blob URL 回收、transient/permanent 分类与 A→B→A 隔离。
4. 融合最新主线并解决当前 merge,不回退主线新增的现有 Godot 项目入口和其它现役能力。
5. 修复或证伪 Native shell 单测失败,跑完当前工作流要求的全部门禁。
6. 在最终 PR HEAD 上完成真实、已认证 `1280×800` 测量并记录可复核证据。
7. 用中文标题和逐行中文正文整理 PR 分支历史,重新取得 required CI 与有效评审。
### 3.2 明确非目标
- 不恢复资源卡拖动,不新增手动拖动持久化。
- 不修改 manifest、项目版本结构、Rust 资源依赖图、SpacetimeDB schema、资源布局 sidecar schema 或布局 CAS。
- 不改变 `dependencyDepth` 的 Rust 权威地位,不在前端重新推导业务真相。
- 不放宽项目根、manifest/任务登记、`file.read` 策略、普通文件/链接、签名、尺寸、读取漂移或安全 SVG 门禁。
- 不新增平行资源页面、第二套预览系统或通用任务调度框架。
- 不把真实登录信息、项目绝对路径、Cookie 或本机验收资料提交到仓库。
### 3.3 必须保持的现有合同
| 合同 | 必须保持的结果 |
| --- | --- |
| 前端优先级 | `play > detail > visible`;主动请求可替换最低优先级排队预取 |
| 前端逻辑队列 | 总上限 `96`;可见性预取保留主动请求槽位 |
| 终态缓存 | 最多 `48` 项且最多 `64 MiB`;媒体按 Blob 字节、文档按 UTF-8 字节计入 |
| IPC 载荷 | data URL 只作临时传输;进入 React 状态前转 Blob URL |
| 回收 | 淘汰、资源删除、项目/mode 切换、身份变化和卸载均撤销 Blob URL |
| 身份 | `projectPath + projectId + mode + resourceId + category + path + mediaType` 全量绑定 |
| 异步隔离 | 旧 epoch 的 then/catch/finally 不写入、不释放也不扣减新 scope 状态 |
| 媒体行为 | 搜索隐藏、切换视图/项目/mode、详情打开或资源删除时暂停旧媒体 |
| 安全读取 | 原有三条 Tauri command 名称与全部安全门禁不变 |
## 四、冻结的修复方案
### 4.1 两层调度边界
前端继续负责“用户意图与展示状态”,Tauri 新增唯一的进程级物理读取管理器负责“真实并发与取消”:
```text
资源卡可见/详情/播放意图
-> 前端优先级队列(96play > detail > visible
-> Tauri requestId + scopeId
-> 原生全局读取管理器(所有窗口/项目/mode 合计最多 3 个 permit
-> 权限/登记/路径/签名/漂移门禁
-> 有界分块读取与取消检查
-> data URL 临时回传
-> Blob URL + 48 项/64 MiB 终态 LRU
```
前端的 3 槽只用于当前 Hook 的逻辑泵;原生 3 槽才是跨 scope、跨 Hook、跨窗口的物理上限。任何旧 scope 都不能因为前端重置计数而获得额外物理读取槽。
### 4.2 scope 与 request 身份
- 每次 Hook 挂载和每次 `projectPath + projectId + mode` 变化都生成新的不透明 `scopeId`;A→B→A 的第三个 scope 不复用第一个 A 的 ID。
- 每个实际 IPC 读取生成唯一 `requestId`,并继续携带完整资源身份。
- 三个现有读取命令保留命令名,只增加内部调度所需的 `scopeId/requestId` 参数;不得把三个安全读取入口合并成新的宽泛文件读取命令。
- 新增窄职责 `cancel_local_project_resource_preview_scope` 命令,只接受不透明 scope ID,不接受路径,也不读取文件。
- 重复 request ID 失败关闭;取消未知或已经结束的 scope 幂等成功,避免卸载与切换竞态制造用户错误。
### 4.3 原生取消与全局并发
- 在 Tauri app state 中注册唯一 `ProjectResourcePreviewReadManager`,全进程共享 `3` 个 permit。
- 等待 permit 的任务必须同时等待 scope 取消;旧 scope 一旦取消,尚未取得 permit 的任务立即退出,不进入文件读取。
- 已取得 permit 的任务使用共享取消令牌,并在以下边界检查取消:命令入口、权限/manifest 登记复核后、打开文件后、每个固定上限读取块之间、媒体签名/图片结构检查前、漂移复核前和 base64 编码前。
- 物理 permit 只能由对应原生任务在结束或确认取消后释放;前端 scope 切换不得直接释放原生 permit。
- 读取使用固定小块并继续受现有 `2/8/32 MiB` 文件上限约束。取消后的字节缓冲和临时 base64 不进入返回值;取消不得生成 Blob URL。
- 原生取消返回稳定的内部取消类别。当前 scope 的真实失败仍按 transient/permanent 规则展示;旧 scope 或明确取消结果静默收口,不能显示成当前资源失败。
- 原生管理器必须在成功、失败、取消、panic/join error 和窗口卸载路径清理活动 request/scope 注册,不能形成永久活动 registry 泄漏;seen request tombstone 最多保留 `8192` 项;非活动 cancelled scope tombstone 的预算为 `1024` 项,仍有请求的已取消 scope 必须临时钉住,最后一个请求结束后立即重新收敛。
### 4.4 新 scope 不被旧 scope 饿死
- scope 切换时,前端先推进 epoch、停止媒体、清理队列/缓存并向原生管理器发送旧 scope 取消,再泵入新 scope 请求;取消命令不阻塞 React 提交。
- 新请求可以立即进入原生等待队列;旧排队任务会因取消退出,旧在途任务在最近的分块取消点释放 permit,新 scope 随即取得槽位。
- 不采用“每个 scope 自己拥有 3 个物理槽”的方案,也不采用仅靠忽略 Promise 结果的伪取消。
- 如果实施中发现某个平台普通文件读取无法在合理边界内执行协作取消,必须暂停并补充平台级可中断方案;不得退回无限叠加旧读取。
### 4.5 文档先行修正
编码前先局部修正以下权威文档:
- PRD §3.3.2:把“每个 scope 获得独立并发计数”改为“每个 scope 拥有独立逻辑状态/epoch,但物理读取使用进程级全局 3 槽并可取消旧 scope”。
- PRD §7.6:加入跨 scope 物理并发、取消确认、连续切换和无旧 base64/Blob 残留验收。
- `decision-log.md` 当前资源管理决策:区分逻辑 epoch 与物理全局调度,纠正会允许 6 个未完成读取并存的旧表述。
- `pitfalls.md`:新增“读预览与 CAS 写入不同,不能只丢弃旧 Promise 后重置物理槽”的长期排障结论。
- AI 游戏创作 App 技术方案中与资源预览并发/验收重复的段落同步到同一口径。
## 五、预计改动范围
| 文件 | 预计职责 |
| --- | --- |
| `apps/ai-game-creator-shell/src/view/project-development/useProjectResourceCardPreviews.ts` | 生成 scope/request ID、发送取消、保留优先级队列与 epoch 防线、静默处理取消 |
| `apps/ai-game-creator-shell/src/view/project-development/resourceCardPreviewModel.ts` | 仅在需要时补充窄的调度常量/类型;不承载原生业务规则 |
| `apps/ai-game-creator-shell/src-tauri/src/resource_preview_scheduler.rs` | 新增进程级 3 槽、活动 scope/request registry、等待取消与清理,以及 `8192 / 1024` 两类有界 tombstone;不读取任意路径 |
| `apps/ai-game-creator-shell/src-tauri/src/resource_inspect.rs` | 文档/媒体分块读取与取消检查,保留稳定读取和安全 SVG 门禁 |
| `apps/ai-game-creator-shell/src-tauri/src/image_inspect.rs` | 图片预览读取接入同一取消探针,保留尺寸/签名/漂移门禁 |
| `apps/ai-game-creator-shell/src-tauri/src/commands.rs` | 三个读取命令接入 manager,并增加窄 scope 取消命令 |
| `apps/ai-game-creator-shell/src-tauri/src/main.rs` | 注册 app state 与取消 command |
| `apps/ai-game-creator-shell/tests/useProjectResourceCardPreviews.test.ts` | 改写错误的“6 个挂起读取即成功”用例并补连续切换/取消/ABA 回归 |
| `apps/ai-game-creator-shell/src-tauri/src/tests/project_tools.rs` 及 scheduler 单测 | 覆盖全局并发、排队取消、分块取消、活动 registry 清理、两类 tombstone 有界淘汰和安全门禁回归 |
| AppSurface/相关前端测试 | 证明卡片、详情、播放、搜索隐藏与资源切换没有回归 |
| PRD、技术方案、decision log、pitfalls | 同步最终合同与已验证经验 |
如实际实现需要修改 manifest、资源图、布局 sidecar、SpacetimeDB、外部 API 或媒体安全策略,立即停止并重新评审;这些不属于本计划的默认授权范围。
## 六、阶段执行顺序
### T1:收口当前 merge 与工作区所有权
1. 再次获取并核对最新 `origin/master`;若主线已越过当前融合基线 `aa5c857060af4fe2644b21e0679a727490995935`,更新本文基线后重新审计差异。
2. 检查 staged merge diff,确认所有冲突解析同时保留资源管理合同和主线 Godot 项目入口。
3. 单独审计未暂存的 Native shell 候选修复;只有复现结果支持因果时才纳入。
4. 永久排除 `.env``.env.local` 与 tracking-outbox;未取得用户明确授权时不得读取、删除、暂存或提交 tracking-outbox,获授权后也只能核对明确目标并定向清理,不触碰其它目录。
5. 以中文标题和逐行中文正文结束本地融合,保留一个可回退的本地集成锚点;暂不推送。
退出条件:merge 已结束、最新主线是祖先、无未解决冲突、用户配置未进入 index、`git diff --check` 和 staged diff 审计通过。
### T2:先修正文档合同
1. 按 §4.5 更新 PRD、技术方案、decision log 和 pitfalls。
2. 明确取消类别、全局 3 槽、scope/request 身份、分块取消点、活动 registry 清理、seen request `8192` 硬上限、cancelled scope `1024` 非活动预算与活动钉住后收敛语义,以及现有安全门禁。
3. 确认文档没有把 AppSurface/CSS 测试写成 `1280×800` 实测替代品。
退出条件:文档已经具体到可以直接指导 TypeScript/Rust 字段、状态和测试,不再保留“独立 scope 物理 3 槽”的歧义。
### T3:实现可取消的全局预览读取
1. 先实现并单测原生 scheduler、取消令牌和清理守卫。
2. 把图片、文档、媒体读取改成可检查取消的有界分块读取;保持所有安全门禁和大小上限。
3. 将三个 Tauri command 接入原生 manager,注册取消 command 与 app state。
4. 前端生成唯一 scope/request ID,在切换和卸载时取消旧 scope;保留当前优先级、LRU、Blob 回收与 epoch 防线。
5. 对取消和旧 scope 结果执行静默收口;当前 scope 的真实 transient/permanent 错误行为不变。
退出条件:任意时刻原生实际读取不超过 3;旧 scope 取消后新 scope 能取得槽位;取消任务不编码 data URL、不创建 Blob URL、不污染新 scope。
### T4:补齐本轮资源预览回归
> 2026-08-11 用户补充执行顺序:上一阶段 Native shell 候选故障暂不复测、不阻塞本轮资源预览缺陷修复;先完成并定向验证本轮改动,Native 单项与全量门禁统一保留到 T5 最终验证。
#### 前端/跨层必测矩阵
- `play > detail > visible` 和 96 队列硬上限不回归。
- 48 项/64 MiB 双重 LRU、连续媒体浏览和 Blob URL 恰好一次回收不回归。
- A→B 时旧 scope 被取消,不能再把 6 个未取消读取并存当成成功标准。
- A→B→A、项目切换、dependency/type 快速连续切换至少覆盖多轮;旧 then/catch/finally、取消 ACK 和活动 request registry 清理均不能改写新 scope;两类 tombstone 继续按 `8192 / 1024` 上限有界保留和淘汰。
- 3 个旧读取挂起时切换 scope:原生活动数峰值始终 `<= 3`,B 在旧读取确认取消后启动,旧任务不进入 base64/Blob 阶段。
- 取消发生在等待 permit、读取首块后、读取末块前、签名/结构检查前和 base64 前时都可安全退出。
- 文档/图片/安全 SVG/视频/音频的登记、策略、类型、大小、链接、漂移和替换门禁全部回归。
- 搜索隐藏立即暂停、详情与播放意图、资源身份变化、卸载和 AppSurface 展示不回归。
退出条件:本轮新增/改写的前端、scheduler、安全读取与 AppSurface 回归全部通过;旧 scope、取消 ACK 和异常/崩溃清理不污染新 scopeNative shell 仍明确留在 T5,不能把“暂缓”写成“已通过”。
### T5:全量本地门禁
进入全量命令前,先单独运行旧 Native shell 失败用例:
```bash
cargo test --locked --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml game_chat_pure_continue_inherits_failed_root_semantics_and_manifest_progress -- --test-threads=1 --nocapture
```
若失败,记录第一错误、锁路径、持有者生命周期和最小复现,不先假设是 flaky;同时核对当前 `tauri-plugin-http` feature 调整是否存在直接因果,无因果则从本分支排除该候选改动。定向用例连续通过后再运行完整 Tauri suite 与 `npm run check:native-shells`,不能用单测通过替代完整门禁。
按从窄到宽顺序执行并记录 commit、命令、通过数和失败原因:
```bash
npm run test -- apps/ai-game-creator-shell/tests/useProjectResourceCardPreviews.test.ts apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts
npm run ai-game-creator-shell:typecheck
cargo test --locked --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --test-threads=1
npm run ai-game-creator-shell:check
npm run lint
npm run test
npm run build
npm run check:content
npm run check:server-rs-ddd
npm run bgfilter-worker:smoke-test
npm run check:production-health-patrol
npm run check:production-api-release
npm run check:production-api-deploy
cargo test --locked --workspace --no-fail-fast --manifest-path server-rs/Cargo.toml
cargo check --locked -p api-server --all-targets --manifest-path server-rs/Cargo.toml
cargo check --locked -p spacetime-module --manifest-path server-rs/Cargo.toml
npm run check:native-shells
npm run check:encoding
git diff --check
```
若环境导致 `listen EPERM`、网络依赖下载或真实认证阻塞,必须把它与源码失败分开记录,并在允许的环境重跑对应 required gate;不得把“被中断/被沙箱阻塞”写成通过。
按用户补充要求,最终生产实现树完成上述全量 native 门禁后,若后续只修改测试夹具的确定性而不改变生产实现,可以只运行直接受影响的定向回归、格式与静态检查;T6 推送后的 required CI 仍必须在最终干净提交上全量通过。该窄例外不能用于替代生产代码、依赖图或运行时合同变化后的完整门禁。
退出条件:PRD §7.6 第 5 项对应的本地门禁全部通过,或仅剩必须由 Gitea runner/真实登录环境完成且已明确记录的外部门禁。
### T6:整理提交历史、推送并完成真实验收
#### 干净历史
1. 基于最终最新 `origin/master` 在隔离 worktree 构造干净分支,把最终资源管理树按逻辑提交移植过去;不使用破坏当前用户工作区的 reset/checkout。
2. 最终 PR 历史不得包含 `d29fc1e0f``647820825``189e5bb59` 等不合规提交。
3. 每个提交使用中文标题,标题后逐行写明修改内容。例如:
```text
修复资源预览跨范围并发泄漏
增加原生全局有界预览读取与取消协议
保持资源安全读取和终态缓存回收合同
补齐跨范围取消与内存边界回归测试
```
资源管理实现与合同、Runtime 测试夹具竞态、Native HTTP 的 OS 自动代理隔离必须分别成组;第三组已由同一源码树上的 A/B 门禁证明必要,不能再混入资源管理提交或省略因果记录。
- 第一组:资源管理实现、前端/Tauri/AppSurface 测试、PRD/技术方案、临时计划,以及 `decision-log.md` 的资源管理 hunk。
- 第二组:`main_loop_tests.rs`、`autonomous_completion_contract_tests.rs` 与 `canvas_generation.rs` 的 Runtime / HTTP 测试夹具确定性修复。
- 第三组:`Cargo.toml`、`Cargo.lock`、`check-native-shells.mjs` 与 `decision-log.md` 的 HTTP 边界 hunk。
`decision-log.md` 横跨第一、第三组,必须按 hunk 暂存;当前本地 checkpoint 不进入最终第四组,全部折叠进上述逻辑提交。
4. 推送前逐文件暂存,只包含任务代码/文档;`.env`、`.env.local`、tracking-outbox、日志、缓存和构建产物必须从暂存和提交中明确排除。tracking-outbox 只有取得用户明确授权后才允许定向清理。
5. 对同一 PR 分支的历史替换只使用带精确旧 OID 的 `--force-with-lease=<ref>:<oid>`,且执行前必须获得用户明确授权并重新用 `git ls-remote` 核对远端 lease;lease 漂移立即停止,禁止退化为 `--force`,也禁止先普通推送当前不合规历史。
#### Gitea required CI
最终远端 commit 必须同时通过:
- `Project CI / Repository checks (pull_request)`
- `Project CI / Frontend tests (pull_request)`
- `Project CI / Backend tests (pull_request)`
- `Project CI / Native shell tests (pull_request)`
任一 job 失败时,先记录失败 job、第一错误、根因和计划,再修复并重跑;不得只重跑到偶然绿色或跳过 required context。
#### 真实 `1280×800` 验收
只在已推送、CI 对应的当前 HEAD 上执行:
1. 使用真实已认证应用 WebView 或 Chromium,正常登录并打开真实本地项目工作台;不绕过认证,不伪造 Tauri,不把 Cookie/Token 写入证据。
2. 把内容视口设为精确 `1280×800`,确认 `window.innerWidth === 1280`、`window.innerHeight === 800`。
3. 至少记录以下值:
- `window.innerWidth/innerHeight/devicePixelRatio`
- `document.documentElement.clientWidth/clientHeight/scrollWidth/scrollHeight`
- `document.body.clientWidth/clientHeight/scrollWidth/scrollHeight`
- `.game-project-workbench`、`.game-workbench-stage`、`.game-workbench-chat`、`.project-supervisor-composer`、`.game-agent-dock` 的 `getBoundingClientRect()`
- 每个关键矩形是否满足 `left/top >= 0` 且 `right <= innerWidth`、`bottom <= innerHeight`。
4. 操作 dependency/type 切换、四分区内外滚动、分区高度/倍率、搜索过滤、文档详情、音频播放、图片/SVG/视频卡和退出详情;确认右侧对话、输入区与底部 Dock 全程在视口内,页面级横向/纵向均无溢出。
5. 在 PR 普通评论记录最终 commit、平台/WebView 或 Chromium 版本、视口、全部测量值、关键操作、结果和必要截图。截图只作辅助,数值记录才是门禁证据。
退出条件:四个 required CI 全绿,真实测量评论已绑定当前 PR HEAD,且重新请求评审后取得有效批准。
### T7:删除本文并对最终 HEAD 再验收
只有以下条件全部满足时才删除本文:
- [ ] P1-A 的全局有界取消实现和全部回归已完成。
- [ ] Native shell 阻塞已解决,全部本地门禁已通过。
- [ ] 最新主线已经成为 PR 分支祖先且无未解决冲突。
- [ ] 不合规历史已经从远端 PR 分支移除。
- [ ] 四个 required CI 在删除前的代码完成 commit 上全部通过。
- [ ] 删除前的代码完成 commit 已有真实 `1280×800` 证据和有效批准。
- [ ] 没有剩余评审线程、未记录风险或待实现功能被伪称完成。
删除本文后使用单独中文提交,例如:
```text
删除已完成的资源管理临时计划
移除已全部执行完成的阶段性计划文档
保留权威 PRD 技术方案与长期决策记录
```
由于删除会产生新的最终 HEAD,删除提交推送后必须再次:
1. 跑四个 required CI
2. 在同一真实环境复核并记录最终 commit 的 `1280×800` 数值(可以引用相同步骤,但必须写出新 commit 和实际结果);
3. 确认 Gitea 没有因新提交撤销审批;如审批失效,重新请求并取得批准;
4. 确认仓库最终树中不存在本文,且 `.env`、`.env.local`、tracking-outbox、日志、缓存和构建产物均未提交;tracking-outbox 仍保持排除,除非用户另行明确授权定向清理。
最终退出条件:计划文档已删除,删除后的最终 HEAD 通过全部 required CI、真实测量和有效审批,PR 无未解决阻塞项。
## 七、阶段状态表
| 阶段 | 状态 | 完成证据 |
| --- | --- | --- |
| T0 审计并冻结计划 | 已完成 | 2026-08-11 核对 Git、PRD、前端 Hook、Tauri 读取链路、现有测试与评审截图 |
| T1 收口 merge 与工作区所有权 | 已完成 | `b2be9de2f` 已无冲突融合 `origin/master@3c457feb4c82d123e9bd311ae69aab0192f94e3c`,最新主线为 `HEAD` 祖先;`.env`、`.env.local` 与 tracking-outbox 始终排除 |
| T2 修正文档合同 | 已完成 | PRD、技术方案、decision log 与 pitfalls 已明确逻辑 scope、进程级全局 3 槽、scope/request 身份、分块取消点、活动 registry 清理、`8192 / 1024` tombstone 有界淘汰和安全读取不变量;编码检查与 `git diff --check` 通过 |
| T3 实现全局有界取消 | 已完成 | 新增全进程共享 3 permit scheduler、活动 scope/request registry、seen request `8192` 项硬上限,以及 cancelled scope `1024` 项非活动预算与活动钉住后收敛;permit 和 registration guard 由真实 blocking 任务持有,外层 future abort 不提前释放物理槽或切断取消;三条既有读取命令接入 `spawn_blocking` 和 64 KiB 分块取消,Hook 与 Supervisor 成果图片入口均使用唯一 scope/request 并在切换或卸载时取消;跨窗口 ID fallback 也使用随机熵避免同毫秒碰撞 |
| T4 本轮资源预览回归 | 已完成 | Hook `10/10`、scheduler `8/8`、resource inspect `4/4`、AppSurface `368/368`、Supervisor 成果图片定向 `1/1`、图片 base64 取消与自动读取策略定向用例通过;新增 outer future abort、cancel 可达性、tombstone 收敛与精确取消错误反例。三条 main-loop 竞态和 pure-continue 用例定向通过,回执夹具同时等待父子 execution lane 收口;shell typecheck、ESLint、`cargo fmt --check`、编码检查、`git diff --check` 通过 |
| T5 全量本地门禁 | 已完成 | 最新主线融合后,`npm run lint` 全部子门禁通过;`npm run test` 为 `206 files / 2812 passed / 8 skipped / 0 failed`build、content、server-rs DDD 通过;server-rs workspace 中 api-server `894 passed / 6 ignored`、spacetime-module `230 passed / 1 ignored`、platform-llm `131 passed`、shared-contracts `72 passed`,两个 cargo check 通过;BgFilter worker `4/4`、production health patrol、release 与 deploy 四项 Frontend CI 门禁通过。A 组为显式关闭插件默认 feature 的 `eee777651` 最终生产实现树,完整 `npm run check:native-shells` 通过:Tauri 主测试 `1775 passed / 14 ignored`integration `2/2 + 14/14`agent-run smoke、两套 release build 与最终扫描通过。B 组只把 `tauri-plugin-http` 恢复为默认 feature 并运行同一命令:前端 `644/644`、Runtime Core `19/19`、platform-llm `134 passed / 1 ignored`、shared-contracts `11/11` 后,该次 Tauri 结果为 `1760 passed / 15 failed / 14 ignored`;首错把预期 transport/outcome-unknown 改写成代理 `502` 且出现 `Go-http-client/1.1`,其它失败不在本文逐项宣称根因。恢复 A 后 `Cargo.toml` 与 `Cargo.lock` 均重新等同 `eee777651`Cargo feature 复核证明默认插件会把 `reqwest/system-proxy` 合并到全部原生客户端,故该独立边界保留并在 T6 单独成组。定向复验另发现非阻塞 listener 接受的请求 stream 可在 macOS 继承非阻塞状态,测试 helper 已在读取前显式恢复 blocking 并继续保留 10 秒超时;按用户允许的测试夹具窄验证边界,响应丢失与精确重放两条直接回归随后各 `1/1` 通过。tracking-outbox 最后一次已记录为 `512` 个并明确排除;最终 feature 图无 `system-proxy`,编码、Rustfmt、Node 语法与 `git diff --check` 通过 |
| T6 干净历史、远端 CI、真实验收与批准 | 进行中 | 已确认 `origin/master@3c457feb4c82d123e9bd311ae69aab0192f94e3c` 未漂移;本地权威快照已提交,隔离分支 `codex/resource-management-clean` 已构造“资源管理实现与合同 / Runtime 与 HTTP 测试夹具竞态 / Native HTTP 系统代理隔离”三组中文提交,并通过 tree hash、逐字节 diff、无 merge、洁净工作树及 `.env*` / tracking-outbox 排除核对。远端覆盖推送尚未获用户授权,禁止执行;required CI、真实 `1280×800` 与有效审批尚未执行 |
| T7 删除计划并复验最终 HEAD | 未开始 | 待补 |
## 八、最终完成定义
- 资源预览物理读取跨 scope、跨项目、跨 mode 和跨窗口始终全局 `<= 3`,旧 scope 可取消且不再累积 base64/Blob 瞬时内存。
- 当前优先级、队列、LRU、Blob 回收、媒体暂停、失败重试、ABA epoch 和全部安全读取门禁无回归。
- 最新主线已融合,现有 Godot 项目入口及其它主线能力无回归。
- Native shell 单项和全量门禁均通过,四个 Gitea required job 均为最终 HEAD 的绿色结果。
- 最终 HEAD 的真实、已认证 `1280×800` 数值证据可在 PR 评论复核,AppSurface/CSS 测试没有冒充该证据。
- PR 历史中的提交标题和正文符合中文规范,远端分支改写经过授权且使用 `--force-with-lease`。
- `.env`、`.env.local`、密钥、认证资料、tracking-outbox、日志、缓存和构建产物没有进入提交。
- 本临时计划已按 T7 删除;最终 PR 仍保留同步后的权威 PRD、技术方案、decision log 和 pitfalls。
@@ -4,9 +4,9 @@
- 背景:资源管理第一轮实现后,人工验证继续暴露 WebView 默认缩放、预览队列饥饿、过滤后媒体残留播放、外层滚动串 scope、超深依赖坐标越过 Rust 上限和暂时错误无法重试等问题。部分 PRD / 技术方案仍描述第一轮的中央媒体预览、单全局 Overlay 和统一 section scope,已经与第二轮代码及验收结论冲突。
- 决策:以当前代码、2026-08-10 最新资源管理决定和第二轮人工验证为正式合同。`Ctrl/Cmd + wheel` 使用原生 `{ passive: false }` 委托监听;预览固定 `play > detail > visible` 且总队列上限 `96`,主动请求可替换最低优先级预取;终态缓存同时限制为 `48` 项与 `64 MiB`IPC data URL 立即转成可撤销 Blob URL;项目 / mode 使用单调 scope epoch 隔离逻辑队列、缓存与异步回调,但物理读取由 Tauri 进程级唯一 `3` 槽管理器统一限制。每次挂载或 scope 切换生成不复用的 `scopeId`,每次 IPC 读取生成唯一 `requestId`;切换和卸载通过窄取消命令中止旧 scope 的排队 / 分块读取,取消任务不得进入 base64 / Blob 阶段。成功、失败和取消后清理活动 request / scope registry,同时保留有界 tombstoneseen request 上限 `8192`;非活动 cancelled scope 预算 `1024`,活动取消 scope 为防复活可临时钉住,结束后立即重新收敛。搜索隐藏立即暂停媒体;外层滚动按 `projectId + mode`、内层按 `projectId + mode + section` 隔离;前后端坐标共同限制为 `0..=1_000_000`,超深 dependency 只饱和显示列并保留原始深度;失败预览区分 transient / permanent,仅用户意图重试 transient。
- 展示边界:图片、安全 SVG 和视频主体只在资源卡内展示;中央详情以元数据、同类型依赖和版本信息为主,文档正文与按意图读取的音频控件保留。每个分区拥有自己的 SVG plane;单端离屏显示边界继续线,两端离屏隐藏。`1280×800` 需要已认证 WebView / Chromium 的当前 HEAD 真实测量,CSS 正则测试不能冒充实测证据
- 展示边界:图片、安全 SVG 和视频主体只在资源卡内展示;中央详情以元数据、同类型依赖和版本信息为主,文档正文与按意图读取的音频控件保留。每个分区拥有自己的 SVG plane;单端离屏显示边界继续线,两端离屏隐藏。`1280×800` 横屏下页面级无溢出,CSS 正则测试仅作为静态防回退;人工已完成应用 WebView 验收
- 兼容与边界:不修改 manifest、Rust 资源图、SpacetimeDB、sidecar schema、布局 CAS 或媒体安全读取门禁;不恢复资源卡拖动。过期文档在同一次变更内同步修正,避免实现通过测试但评审继续依据旧合同。
- 验证方式:新增原生 wheel 取消、队列优先级 / 硬上限、Blob / 总字节 LRU、连续媒体浏览、挂起旧 scope / ABA epoch、原生全局活动峰值 `<= 3`、等待与分块取消、取消前无 base64 / Blob、活动 registry 清零及 `8192 / 1024` tombstone 有界淘汰、transient 重试、过滤后暂停、外层滚动 scope、坐标边界及 Rust 安全读取回归;继续运行 AppSurface、纯布局模型、Tauri 定向测试、编码检查和 `git diff --check`真实 `1280×800` 是自动测试外的跨文件人工门禁,必须由当前 HEAD 的已认证 WebView / Chromium 实测并在 PR 评论中记录;记录缺失时不得声称阶段七完成
- 验证方式:新增原生 wheel 取消、队列优先级 / 硬上限、Blob / 总字节 LRU、连续媒体浏览、挂起旧 scope / ABA epoch、原生全局活动峰值 `<= 3`、等待与分块取消、取消前无 base64 / Blob、活动 registry 清零及 `8192 / 1024` tombstone 有界淘汰、transient 重试、过滤后暂停、外层滚动 scope、坐标边界及 Rust 安全读取回归;继续运行 AppSurface、纯布局模型、Tauri 定向测试、编码检查和 `git diff --check`人工已完成 `1280×800` 应用 WebView 验收
- 关联文档:`docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md``docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`
## 2026-08-10 任务流退出画布连线且 dependency 层间距为精确引用留走线区
@@ -19,7 +19,7 @@
- 现象:代码已经改成分区内 SVG plane 和卡内媒体,文档仍要求单全局 Overlay 或中央大图;CSS 正则和浅层 AppSurface 测试保持绿色,但真实 Tauri WebView 仍会默认缩放、主动预览请求饥饿、过滤后媒体继续播放或超深布局反复提交非法坐标。
- 原因:第一轮编码时同步编写的 PRD / 技术方案被后续代码修复绕过,第二轮只改实现和局部测试,没有把新验证结论回写正式合同。React 合成 wheel 事件、单例滚动 ref、只按数量限制的 base64 缓存、跨 scope 共用的活动读取计数、无优先级有界队列和前后端不同坐标边界又分别跨越浏览器、会话状态与 IPC 边界,浅层文本断言无法证明运行时行为。
- 处理:每轮验证后按“当前代码 + 最新决策 + 真实运行证据”同步修订 PRD、技术方案、决策记录和回归测试。原生可取消事件要直接断言 `defaultPrevented`;队列验证主动请求替换预取;预览 data URL 只作临时传输并转为可撤销 Blob URL,LRU 同时限制项目数和总字节;项目 / mode 切换推进 epoch,旧 `finally` 不得扣减新 scope;媒体状态同时核对可见集合;滚动分别按内外 scope 保存;坐标合同由共享 TS 与 Rust 同边界维护;暂时 / 永久错误在模型中显式分类。
- 验证:运行定向 hook / AppSurface / 纯布局 / Rust 边界测试,再执行类型检查、编码检查和 `git diff --check`。涉及窗口几何和 WebView 行为时,还必须在当前 HEAD 的已认证 `1280×800` WebView / Chromium 中记录 `window`、document、body 和关键容器测量CSS 正则只保留为静态防回退门。
- 验证:运行定向 hook / AppSurface / 纯布局 / Rust 边界测试,再执行类型检查、编码检查和 `git diff --check`。涉及窗口几何和 WebView 行为时,结合实际 `1280×800` 应用窗口进行人工检查CSS 正则只保留为静态防回退门。
- 关联:`apps/ai-game-creator-shell/src/view/project-development/index.tsx``apps/ai-game-creator-shell/src/view/project-development/useProjectResourceCardPreviews.ts``apps/ai-game-creator-shell/src/view/project-development/resourceCanvasLayoutModel.ts``apps/ai-game-creator-shell/src-tauri/src/project/resource_layout.rs``docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md`
## 预览读取不能像放弃旧 CAS 回调一样直接重置并发槽