From b1377572d6b756a834e2cbbd8fd093df9091993f Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Fri, 11 Sep 2026 18:12:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=A1=E5=87=86=E8=B5=84=E6=BA=90=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=E7=9A=84=20PRD=E3=80=81=E9=AA=8C=E6=94=B6=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E3=80=81=E6=8A=80=E6=9C=AF=E6=96=B9=E6=A1=88=E4=B8=8E?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=AE=B0=E5=BF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PRD §5.3 补实现口径:替换落盘 = 改绑定 + 追加新版本、子版本绑定 = 源绑定去掉源素材并保证替换素材在集合里、前后身份用推导记录、三项兼容性逐条判据与 sizeSpecEqual 的降级声明、失败即拒绝、入口与可见效果;同时标注 :364-373 的 ProjectResourceDescriptor 是历史四分类形状(其 width/height/durationMs 在 manifest 里并不存在) - PRD §5.4 前的版本章节与 §6 P1、§7.4 第 4 条按当前状态校准:替换已实施,但版本聚焦态仍不提供创建/替换/切换/回滚按钮,资源替换入口在资源卡工具条 - PRD 新增 §7.8 P1 资源替换验收六条(入口放行判据、候选禁用与原因、只追加写入形状、两条绑定路径、拒绝零副作用、成功后切版本但不重载预览) - 【测试用例】AGC资源工作台V3端到端验收:删掉「PRD L387 兼容性三项属 C6 取消范围」那句(改为明确不属于),更新 §7.3 工具条 opt-in 清单,补三条已知边界(运行画面不因改绑定而变、候选弹窗不加载缩略图、picker 在 AGC 首次使用),§8 覆盖与不覆盖范围补资源替换 - 【技术方案】AI游戏创作智能体App实施计划::669 的「本阶段不提供版本创建、替换、切换」与 :641 的布局切片范围按当前状态校准,并在文末新增「2026-09-11 AGC 资源工作台 V3:版本级资源替换」一节,写全命令、写入语义、前后身份推导口径、三项兼容性判据与降级声明、入口、成功后行为与验证数字 - decision-log 新增一条(背景 / 决策 / 恒等绑定硬约束 / 判据 / 降级 / 边界 / 影响范围 / 验证方式 / 关联文档):说明本次按 PRD §3.2 / §5.3 恢复「替换后创建下一迭代版本」,与 2026-09-10 那条「不创建新版本、替换功能整条取消」的口径关系,以及 C6 的候选/队列/审核仍不做 - Issue #309 的三处口径(C1 决策、贯穿性决策 6、验收总纲的「不创建新版本 / 不产生新版本」)按远程写确认规则**未擅自改动**,需要在用户确认后再改 --- ...AI游戏创作】项目开发工作台PRD-2026-07-20.md | 30 ++++++++++++++++--- .../shared-memory/decision-log.md | 13 ++++++++ ...案】AI游戏创作智能体App实施计划-2026-06-24.md | 15 ++++++++-- ...用例】AGC资源工作台V3端到端验收-2026-09-11.md | 14 +++++---- 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md b/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md index fd081e991..e90bacadc 100644 --- a/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md +++ b/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md @@ -187,10 +187,10 @@ idle -> focused(document|art|audio|version) -> idle - 文档:合法 Agent 文本回执直接使用对话投影内容;项目文件只允许读取当前 manifest 已登记资产或已完成任务产物中的 Markdown、文本、JSON、YAML、TOML,必须经过 `file.read` auto 权限、相对路径、项目边界、普通文件、符号链接 / 硬链接、读取漂移、2 MiB、UTF-8 与扩展名白名单校验。正文使用不执行 HTML、不加载远程图片、不产生可点击外链的安全 Markdown 渲染,并在中央画布内独立滚动;读取失败显示错误空态。聊天侧 `/read` 回执中的文件正文必须作为代码块渲染为 `
`,以便用户审阅源码字面量但不执行其中的 HTML;Markdown 渲染使用 `react-markdown` 的 `skipHtml`,依赖库对代码 span / fenced code 的文本转义;不得在整段 Markdown 上预转义 HTML,否则会把代码中的 `` 双重转义为字面量 `<tag>`。
 - 美术:PNG、JPEG、WEBP、GIF、SVG、AVIF、BMP、MP4、WebM、MOV 只在资源卡本体中按既有受控读取、文件签名与解码门禁展示;中央详情不重复加载或放大图片 / 视频本体。SVG 继续拒绝脚本、事件处理器、外部资源引用和实体声明。
 - 音频:只读取 manifest 已登记音频或已成功导入且登记到 manifest 的附件,按文件签名接受 MP3、WAV、OGG / Opus、M4A、AAC、FLAC;聚焦态展示实际格式、浏览器解码后的时长以及带播放进度和暂停能力的内置播放器。音频任务声明中的未登记路径继续不得读取或播放。
-- 版本:只展示 manifest 中正式、不可变的迭代版本记录;版本卡展示项目修订、创建原因与父版本,聚焦态同时展示直接子版本和资源绑定。点击版本卡后高亮仍存在于当前资源投影中的引用资源;缺失历史资源只保留绑定身份,不生成幽灵资源卡。资源替换仍留给后续切片。
+- 版本:只展示 manifest 中正式、不可变的迭代版本记录;版本卡展示项目修订、创建原因与父版本,聚焦态同时展示直接子版本和资源绑定。点击版本卡后高亮仍存在于当前资源投影中的引用资源;缺失历史资源只保留绑定身份,不生成幽灵资源卡。资源替换(2026-09-11 实施)不在版本聚焦态提供,入口在资源卡选中工具条:选中被**当前版本**绑定的素材后替换成另一已登记素材,落盘为「追加下一迭代版本 + 新绑定」,详见 §3.2 / §5.3。
 - mentor 最新决定:资源聚焦不提供工具栏,也不提供工具侧边栏。
 - 音频:只读取 manifest 已登记音频或已成功导入且登记到 manifest 的附件,按文件签名接受 MP3、WAV、OGG / Opus、M4A、AAC、FLAC;聚焦态展示实际格式、浏览器解码后的时长以及带播放进度和暂停能力的内置播放器。音频任务声明中的未登记路径继续不得读取或播放。
-- 版本:只展示 manifest 中正式、不可变的迭代版本记录;版本卡展示项目修订、创建原因与父版本,聚焦态同时展示直接子版本和资源绑定。点击版本卡后高亮仍存在于当前资源投影中的引用资源;缺失历史资源只保留绑定身份,不生成幽灵资源卡。资源编辑只允许追加继承源绑定并记录提示词的子版本,不允许原地替换或修改源版本。
+- 版本:只展示 manifest 中正式、不可变的迭代版本记录;版本卡展示项目修订、创建原因与父版本,聚焦态同时展示直接子版本和资源绑定。点击版本卡后高亮仍存在于当前资源投影中的引用资源;缺失历史资源只保留绑定身份,不生成幽灵资源卡。资源编辑只允许追加继承源绑定并记录提示词的子版本,不允许原地替换或修改源版本;资源替换同样不改既有版本,而是追加一条 `resource-replacement` 子版本(§5.3)。
 - 资源聚焦不提供通用工具栏或工具侧边栏;图片聚焦态允许一个明确的“精修资源”业务动作进入素材创作无限画布,该动作不是在聚焦容器中内嵌编辑器或恢复通用工具栏。
 - 点击资源后,中央主视窗从 `resource-overview.list` 切换为 `resource-overview.focused.document / art / audio / version`,左侧平台导航、右侧 Supervisor 对话和底部 Agent 状态栏保持原位;聚焦容器以路径、类型、来源任务、依赖层级、同类型上下游和版本字段为首屏主体,不使用页面级浮层或可拖动标题栏。文档正文与按意图加载的音频控制位于元数据之后。
 - 焦点转换以稳定资源 ID 为准。只有从资源列表进入详情或从一个资源 ID 切换到另一个 ID 时聚焦详情 region;同一资源 ID 因 manifest 更新而重新投影时,不得抢走详情内音频 / 视频控件、文档链接或收起按钮的当前焦点。
@@ -384,8 +384,21 @@ type ProjectVersionResourceReplacement = {
 };
 ```
 
+> `ProjectResourceDescriptor.category` 是**历史形状**(旧四分类轴),已被本节上方 2026-09-10 / 2026-09-11 的六分类收口取代;实现以 manifest `assets[].category` 的六分类与读时自愈口径为准,本 DTO 只保留作名词参照。`width / height / durationMs` 也只在该历史形状里存在,manifest 资产表今天并没有这些字段(见下方 `sizeSpecEqual` 的降级声明)。
+
 三项兼容性必须同时为 true 才能创建下一版本。
 
+替换实现口径(2026-09-11):
+
+- **落盘 = 改绑定 + 追加新版本**:新版本 `createdReason='resource-replacement'`、`parentVersionId` 指向被替换的源版本;既有版本记录一个字节不改,走 §5.4 的只追加写入边界。子版本的 `resourceBindings` = 源版本绑定集合**去掉源素材**,并保证**替换素材在集合里**(替换素材是源版本创建之后才登记时,按源素材原来的位置插回);恒等绑定口径下不能把源素材那条槽位改写成替换素材,替换素材若在源版本创建时就已登记、本来就在集合里,改写会撞「资源槽位重复」。
+- **替换前后资源身份用推导记录**(不新增 manifest / 跨端契约字段,依据 §5.4 的版本字段表):父版本里有 `asset:{sourceResourceId}` 绑定是「替换前」,子版本里有 `asset:{replacementResourceId}` 绑定是「替换后」,配对由 `parentVersionId` + `createdReason` 确定;差异 `父 − 子 = {源素材}`,`子 − 父 = {替换素材}`(替换素材在源版本创建时就已登记时 `子 − 父` 为空集,此时版本记录无法单独反推配对)。
+- **三项兼容性判据**(后端权威,前端只呈现,不重算):
+  - `categoryEqual`:两侧资产的功能分类相等,用**读时自愈**口径(见本节 2026-09-11 收口)。Rust 侧与之逐分支一致的实现是 `game_creation_app_asset_category_with_read_time_healing`。
+  - `subtypeEqual`:两侧 `kind` 的 canonical 值相等(别名表见 `GAME_CREATION_APP_CANONICAL_ASSET_KINDS` / `canonical_game_creation_app_asset_kind`)。
+  - `sizeSpecEqual`:**规范化媒体格式相等,且「任一方有事实的维度必须相等」**(`imageSequenceFrames[0]` 的宽高、`imageSequenceDurationMs`;两个维度都无事实时不阻断)。**降级声明**:manifest 资产表没有 `width / height / durationMs` 字段,且现役写入侧(上传、派生、画板回传、生成回流)几乎全部写 `imageSequenceFrames: None`,因此该项**在真实数据上退化为「媒体格式相等」**(`png ↔ webp` 会判为不同而被拒绝)。这是刻意接受的最小实现;要支持跨图片格式替换,必须先给 manifest asset 增尺寸字段并在写入侧回填(跨端契约变更),届时把「缺失即未知」的口径写进契约。
+- **失败即拒绝**:任一项不为 true、源版本不存在、源版本未绑定该素材、替换素材未登记、替换素材与源素材相同、`expectedProjectId` / `expectedProjectRevision` CAS 冲突,都必须拒绝并说明原因;拒绝时 manifest 与项目 revision 都不变,界面不得出现成功态。
+- **入口与可见效果**:入口在资源卡选中工具条,只对「manifest 资产 + 被当前版本绑定」的素材放行;候选弹窗列出全部候选、不兼容项渲染但禁用并给出原因。替换成功后当前版本选择切到新版本,但**不自动重载 / 重启运行中的预览**(§3.2 末条);按 §7.4 的口径,改绑定不做运行时资源重映射,运行画面本身不会因改绑定而变化。
+
 ### 5.4 游戏迭代版本(P1)
 
 阶段六实现状态(2026-08-13 更新):正式版本业务真相扩展在本地项目 `.agent/manifest.json` 的可选 `versions` 字段中;旧项目字段缺失时等价于空列表,不根据 checkpoint、布局 sidecar、静态检查、失败试玩或单独的 `game-creator-project-revision.v1` 自动伪造版本。版本数组只允许追加,已有记录不得删除、重排或修改;首轮没有版本创建按钮。自主首板只有在当前 revision 的 `preview.validate` 已成功形成持久试玩回执后,才幂等追加首条 `initial` 版本,并绑定当时 manifest 中全部已登记资源;同一完成态恢复不得重复创建。已有正式版本时,后续试玩通过不自动追加版本,仍由明确的资源派生事务创建子版本。
@@ -473,7 +486,7 @@ type ProjectAgentMudPointAttribution = {
 
 - 已实施依赖/类型两套坐标持久化、首次默认不重叠布局、历史坐标跨重启恢复、自动协调 CAS 冲突处理与资源卡手动拖动。
 - 资源关系线在布局持久化验收通过后单独实施,不与本切片捆绑伪造完成。
-- 已实施正式版本不可变模型、版本卡、父子关系与引用资源高亮;“编辑资源”可追加继承源绑定并记录提示词的子版本,资源直接替换、运行版本切换和兼容性迁移仍待后续切片。
+- 已实施正式版本不可变模型、版本卡、父子关系与引用资源高亮;“编辑资源”可追加继承源绑定并记录提示词的子版本;资源替换(2026-09-11)已按 §3.2 / §5.3 实施为「改绑定 + 追加 `resource-replacement` 子版本」,入口在资源卡选中工具条;运行版本切换(C7)已完成;兼容性迁移仍待后续切片。
 - 素材创作无限画布阶段一按权威专题一次交付图片导入、编辑、生成、导出、草稿恢复、正式本地回写、即时投影和焦点竞态闭环。
 - 高级抠图、图集、角色动画、视频时间线编辑和音频波形级编辑按后续切片实施;当前视频走源引用派生,音频只做语义重制。
 
@@ -530,7 +543,7 @@ type ProjectAgentMudPointAttribution = {
 1. manifest 缺少 `versions` 时旧项目正常打开且不显示伪造版本;存在合法记录时,固定“项目版本”分区按追加顺序显示稳定版本卡。
 2. 根版本、父版本和直接子版本关系在卡片或聚焦态可见;悬空父版本、自引用、重复 ID、非递增修订、倒退时间、重复 slot 和超限数字均失败关闭。
 3. 点击版本卡后,当前 manifest 中仍存在的绑定资产卡被高亮;历史已删除资产只在版本详情保留 ID,不创建幽灵卡,也不把 External Editor resource ID 猜成 manifest asset ID。
-4. 版本聚焦态展示身份、修订、创建原因、父子关系、创建时间和 slot 绑定;“编辑资源”只追加继承源绑定并记录提示词的子版本,不提供原地替换、切换、回滚或运行按钮。
+4. 版本聚焦态展示身份、修订、创建原因、父子关系、创建时间和 slot 绑定;“编辑资源”只追加继承源绑定并记录提示词的子版本,不提供原地替换、切换、回滚或运行按钮。资源替换**也不在版本聚焦态提供**:它的入口是资源卡选中工具条(§5.3),并且同样不原地改既有版本,而是追加一条新版本;本条限制的是版本聚焦态这个容器,不限制资源卡入口。
 5. 任意现有 manifest 写入只能保留磁盘版本前缀并追加新记录;存储边界以跨进程专用锁串行覆盖旧状态读取、前缀校验、安装和回读,修改、删除、重排或并发旧快照覆盖已有版本时写入失败。
 6. 版本选择和高亮不写 manifest、布局 sidecar 或 project revision;dependency / type 两种布局都可显示绑定高亮,既有依赖关系 SVG 语义不变。
 
@@ -582,6 +595,15 @@ type ProjectAgentMudPointAttribution = {
 8. 右侧正式钱包入口在普通工作台和 UI Editor 子路由都始终可见、键盘可达并能打开余额、充值与使用详情;路由切换不得使入口消失或失去交互。
 9. “资源依赖 / 资源类型”以连通分段按钮呈现,点击与键盘操作均只保留一个选中项;使用 Tab 定位和键盘切换时焦点指示清晰、完整,不被容器边界或 `overflow` 裁切。
 
+### 7.8 P1 资源替换验收
+
+1. 入口只对「manifest 资产 + 被当前版本绑定」的素材渲染;未绑定素材(版本创建后才登记、或不属于当前版本绑定集合)一律不出现入口,也不出现"点了没反应"的假按钮。
+2. 候选弹窗列出后端返回的全部候选,不兼容项**渲染但禁用**并显示不等维度(分类 / 类型 / 尺寸规格);不得隐藏不兼容候选,不得合成非候选素材,不得在前端重算兼容性判据。
+3. 写入后的 manifest:既有版本记录逐项不变(含 `projectRevision` / `resourceBindings` / `createdAt`),新版本追加在末尾,`createdReason='resource-replacement'`、`parentVersionId` 指向源版本、`projectRevision` 严格大于父版本且等于推进后的项目 revision。
+4. 子版本绑定 = 源版本绑定去掉源素材并保证替换素材在集合里;不得出现重复 `slotId`。替换素材在源版本创建后才登记时,子父差异恰好"一减一增"且顺序稳定。
+5. 三项兼容性任一为 false、源版本不存在、源版本未绑定该素材、替换素材未登记、替换素材与源素材相同、`expectedProjectId` / `expectedProjectRevision` 冲突,都必须在写入前拒绝;拒绝时 manifest、`versions` 与项目 revision 都不变,投影里不得出现新的版本卡或新的"当前使用"高亮。
+6. 成功后重读 manifest 并把当前版本选择切到新版本;**不**自动重载或重启运行中的预览(§3.2 末条),也不做运行时资源重映射。可见变化只有:版本下拉多一条「资源替换 · 时间」、资源卡"当前使用"高亮移到替换素材、`@` 面板"当前版本素材"更新。
+
 ## 8. 非目标
 
 - 当前不开放“新增资源”产品入口。图片精修候选保持私有且不污染资源总览;“设为最终图”只允许保持原 asset ID、以新正式文件和事务方式切换 manifest 指针,不原地覆写旧文件。其他资源编辑继续追加派生 asset 或子版本。
diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md
index 1432ae9e9..156567094 100644
--- a/docs/project-memory/shared-memory/decision-log.md
+++ b/docs/project-memory/shared-memory/decision-log.md
@@ -8364,3 +8364,16 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
 - 不做什么:不新增替代导航、不做栏目下拉/分段控件、不改 `resourceBookModel` 的 `main / child + category` 目标模型、不改每「排序模式 + 栏目」独立 viewport 的既有约定、不动 sidecar schema 与跨端契约。
 - 验证方式:新增反向守卫用例(`资源栏目大纲` 标签、`.game-resource-outline` 类名、对应 `