Files
Genarrative/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md
T
k88936 01e057d047
Project CI / Frontend tests (push) Successful in 3m37s
Project CI / Backend tests (push) Failing after 4m13s
Project CI / Native shell tests (push) Failing after 4m11s
Project CI / Repository checks (push) Successful in 3m24s
Feat/AGC对话渲染markdown (#281)
before:
 ![image.png](/attachments/ca6f46f7-dcbd-4132-bad2-cf5c83c49096)

after:
 ![shotmd-1788500615.jpg](/attachments/719539a1-9dfb-412a-a9b9-298547b1791c)
![shotmd-1788500598.jpg](/attachments/4656815f-caca-4325-bca3-b29fe5742b6e)

考虑到在AGC场景下不是很有理由, 暂不实现链接, 图片, 内嵌html

---------

Co-authored-by: 段舒康 <kdletters@qq.com>
Reviewed-on: #281
Co-authored-by: 王德宇 <kvtodev@outlook.com>
Co-committed-by: 王德宇 <kvtodev@outlook.com>
2026-09-08 22:03:37 +08:00

74 KiB
Raw Blame History

AI 游戏创作项目开发工作台 PRD

更新时间:2026-08-23(右侧 Supervisor 对话气泡、可访问对比度与过程卡布局收口;资源卡预览、分区布局、非破坏性资源编辑及 Godot 双根合同保持不变)

1. 产品定位

项目开发工作台是 AI 游戏创作独立客户端中承接“做游戏”后的唯一项目级工作区,不是单独的新页面,也不新建第二套项目、资产、Agent 或预览系统。

工作台固定由四个区域组成:

  1. 左侧平台导航。
  2. 中央主视窗。
  3. 右侧 Project Supervisor 对话与确认区。
  4. 底部专业 Agent 状态栏。

中央主视窗明确区分“资源总览画布”“素材创作无限画布”和“运行测试”三个状态。资源总览与素材创作不是两套项目页:前者负责 manifest 资源投影、依赖关系和类型布局,后者负责单个图片素材的无限画布创作;两者共用当前工作台中央区域。正式预览始终在客户端当前窗口内展开,只允许载入当前项目启动的 127.0.0.1:<port> 本地 HTTP 预览,不调用系统外部浏览器。

2. 创作工具平台接入声明

  • 工作台模式:对话式 Project Supervisor 项目工作台,属于 Agent 原生创作例外。
  • 例外原因:该工作台负责跨策划、美术、程序、数值、音频和发布专业组的持续协作,结构化表单不能覆盖多轮项目开发与确认恢复。
  • 复用边界:图片、音频、上传、素材库、画板和外部生成继续复用现有平台能力,不在工作台内新建平行资产系统。
  • 创作链路:做游戏入口 -> 本地项目工作台 -> 资源/运行迭代 -> 导出或后续发布链路。
  • 业务真相:项目 manifest、Agent Runtime、持久对话、本地预览状态和后端计费投影;前端只保存短生命周期展示态。
  • 当前切片不新增玩法 playId、公开作品 read model、发布路由或 SpacetimeDB schema。

3. 已确认产品决策

3.1 预览与窗口

  • 游戏预览直接在当前客户端窗口内展开。
  • 客户端仅交付横屏,默认窗口为 1280×800,最小窗口为 1280×720
  • 右侧 Supervisor 和底部 Agent 状态栏常驻;窗口不得缩小到破坏该结构。
  • 浏览器窄屏样式只作为开发兼容,不属于本版本产品合同。

3.2 版本与资源替换

  • 可运行版本不可变。
  • 替换版本引用资源时创建下一迭代版本,不原地修改既有版本。
  • 新版本必须记录 parentVersionId、替换前后资源身份和创建原因。
  • 当前运行中的版本不消费尚未生成的新版本变更。

3.3 资源布局

  • “按依赖”和“按类型”分别保存画布位置。
  • dependency / type 自动布局与资源卡手动拖动并存;空项目分区展览仍只提供分区空态。
  • 切换布局模式后恢复该模式 sidecar 中已有坐标;历史手动坐标只读恢复,不删除、不重置、不迁移。
  • 新资源首次进入某个布局时才执行默认不重叠排版;已有坐标不得被自动排序覆盖。
  • 依赖布局使用资源生成/引用关系;类型布局按资源大类、子类型、尺寸规格排序。
  • 资源分区由资源投影固定,前端交互不能改变分类。
  • 非空资源页支持资源卡手动拖动:超过移动阈值后乐观更新坐标与依赖线,结束时提交一次手动布局 CAS;拖动后的点击不触发详情。空画布拖拽仍只平移 viewport。

3.3.1 资源管理三个串行阶段

  1. 阶段一“资源卡本体化”:dependency / type 两种布局共用同一个资源卡组件和预览调度器。图片与安全 SVG 直接显示主体并保留透明棋盘底;图片卡按真实纵横比在统一边界内计算展示矩形,视频、音频、文档和项目版本继续使用稳定固定卡片。资源详情是叠加在原画板上的非模态独立卡片,以元数据、Rust 权威依赖关系和版本信息为主;打开详情不得卸载“按依赖 / 按类型 / 复位”等现役画布级动作、资源卡、依赖连线或重置 viewport、搜索和排序模式。
  2. 阶段二“分区独立缩放”是历史实现;2026-08-22 起仅在项目完全没有任何资源投影时保留“按类型式分区展览”作为空态。任一栏目出现资源后,dependency / type 两种模式均切换为栏目分页画布,默认停留在固定栏目顺序中的第一个非空栏目;大纲展示全部栏目,空栏目计数为 0 且可打开空画布,不再提供分区高度、分区滚动和分区倍率操作。
  3. 阶段三“依赖布局聚类”(已完成):仅在 dependency 模式中,按固定资源分类对当前 Rust 只读图返回的同类型精确引用边和同类型聚合任务流做弱连通分组;任务流以流节点连接其成员,绝不展开成资源笛卡尔积,但只作为布局邻近提示,不绘制虚线、不进入画布关系说明。dependencyDepth 是唯一横向层级权威;每个相关簇先按“最小深度 -> 最小稳定资源 ID”排序,再在同层进行固定两轮由左至右、由右至左的中位数扫描,平局回退稳定资源 ID;同 SCC/环成员保持连续,环后资源继续按 Rust 深度推进。孤立资源是稳定单例组,紧凑排在相关簇之后,簇之间保持固定留白。当前栏目内同类型精确引用参与布局并在该栏目 SVG 中显示;跨分类引用不参与布局,也不在分栏画布中强行连线。搜索只隐藏卡片及任一端点被隐藏的橙色精确引用边,不重算组或压缩坐标。历史 manuallyPlaced=true 坐标继续原样保留并参与自动坐标避让。聚类是可派生表现,不新增 manifest 字段、sidecar schema、SpacetimeDB 表或第二套依赖真相。

3.3.2 本体化资源卡交互与性能合同

  • 卡片默认可视区域不再显示文件名、资源名称、来源、路径、任务和媒体类型等详细文本。这些字段继续进入搜索索引和中央详情;卡片“打开详情”入口的可访问名称必须包含稳定可辨识的资源名与类别。
  • 卡片外层是非交互容器;“打开详情”与“播放 / 暂停”必须是可分别键盘聚焦的同级按钮,禁止在 <button> 中嵌套 <button>。播放键不选择资源、不打开详情。
  • 同一时间最多播放一个卡片音频或视频。打开详情、切换布局模式、切换项目、进入运行视图、搜索 / 筛选隐藏当前资源、当前资源被删除或资源身份 / 路径变化时,必须暂停旧媒体并收口待播放意图;卡片卸载还必须执行防御性暂停。同资源 ID 的无关 manifest 更新不得重建控件或抢走焦点。
  • 图片、视频首帧和项目文档只在卡片进入资源画布可见区及小幅预取边界后读取;音频只在用户点击播放后读取。前端逻辑调度器必须使用有界并发、同身份去重、有界 LRU 淘汰,不允许按全部投影同步启动读取。play > detail > visible 是固定调度优先级;可见性预取不得占满全部队列容量或静默丢弃播放 / 详情请求,主动请求进入硬上限队列时必须替换最低优先级的排队预取并优先执行。终态预览缓存同时受 48 项和 64 MiB 总载荷双重上限约束,媒体按解码后的 Blob 字节、文档按 UTF-8 字节计入;Tauri 返回的 data URL 只允许作为 IPC 临时载体,进入 React 状态前必须转换为可撤销的 Blob URL。LRU 淘汰、资源删除、项目 / mode 切换和卸载都必须 revokeObjectURL,不能让 base64 字符串或失效 Blob 长期占用 WebView。
  • 卡片读取继续调用 read_local_project_image_previewread_local_project_media_previewread_local_project_text_preview;项目边界、manifest / 任务登记、file.read 策略、普通文件 / 链接、签名、尺寸和读取漂移门禁不变。每个 Hook 挂载及每次 projectPath + projectId + mode 变化必须生成不复用的 scopeId,每个实际读取生成唯一 requestId;每个队列任务和结果继续绑定完整的 projectPath + projectId + mode + resourceId + category + path + mediaType。前端 scope epoch 只隔离逻辑队列、缓存和异步回调;三个读取命令在 Tauri 进程中共用唯一的全局 3 槽物理读取管理器,不能因项目、mode、Hook 或窗口不同获得额外物理槽。scope 切换或卸载必须调用窄职责 cancel_local_project_resource_preview_scope,使等待 permit 和分块读取中的旧任务协作取消;旧 epoch 的 then / catch / finally 仍不得写入、释放或扣减新 scope 的前端状态,A → B → A 也不得复用第一轮 A 的 scope、请求或迟到结果。
  • 原生读取必须在命令入口、权限 / 登记复核后、打开文件后、每个固定上限读取块之间、签名 / 图片结构校验前、漂移复核前和 base64 编码前检查取消。取消的排队任务不得打开文件,取消的在途任务不得生成 data URL 或 Blob URL;全局 permit 只能在对应原生任务结束后释放。重复 requestId 失败关闭,取消未知或已完成 scope 幂等成功;成功、失败和取消均必须清理活动 request / scope registry。为防止近期 request ID 重放和已取消 scope 复活,原生管理器继续保留有界 tombstoneseen request 最多 8192 项;非活动 cancelled scope 的保留预算为 1024 项,仍有请求的已取消 scope 必须临时钉住,最后一个请求结束后立即重新淘汰到预算内。明确取消只静默收口旧 scope,当前 scope 的真实 transient / permanent 失败语义不变。
  • 安全读取失败、图片解码失败或视频无可解码画面时,卡片展示稳定类型占位,不挂载破图,不降级为项目外 URL 或裸路径读取。滚动可见性不得自动重试已失败预取;读取漂移、文件替换和通用暂时失败标记为 transient,用户再次打开详情或点击播放时可以显式重试。超尺寸、损坏、类型不支持和不安全 SVG 等永久失败继续缓存且不得用“关闭后重试”误导用户。

3.4 运行视窗与数值微调

  • 运行视窗必须占满中央工作区为游戏保留的可用区域。loopback 预览页通过客户端本地 preview server 注入的只读尺寸桥上报文档实际宽高;宿主只接受当前 iframe、当前 loopback origin 的固定版本消息,并将完整游戏文档等比缩放、居中放入视窗。iframe 首次适配后发生的真实内容增高或缩短仍必须被接受;仅浏览上下文宽高回灌或内容宽高未变化时保持当前状态,不触发重复渲染。

  • 窗口或中央区域尺寸变化后必须重新测量和适配;内容已经放得下时保持 1:1,不得无故放大。游戏文档宽高超过视窗时缩小整体画面,不显示 iframe 横向或纵向滚动条,也不得用单纯裁切替代完整展示。尺寸桥以根布局 ResizeObserver 为主,并在页面可见时每 500ms 至多探测 512 个元素作为绝对定位溢出的低频兜底;探测截断时不得用部分样本下调尺寸,viewport 耦合的 100vh / 100% / bottom / right 布局也不得形成自反馈。相同测量结果去重,不监听整页属性、文本或子节点突变;桥不读取项目正文、不修改 manifest、游戏文件或运行业务状态。桥脚本只能注入到真实 HTML 标签上下文,不能把脚本、样式、模板或注释中的 </body> / </html> 文本误判为结束标签;省略结束标签的 UTF-8 HTML 仍需安全注入。

  • 运行视窗下方继续保留“信息展示”和“数值微调”区域标题及原有面板高度;没有真实资源信息或已登记微调项时,内容区域保持空白,不显示示例字段、默认数值、未载入控件或功能说明,也不得因内容为空压缩两个面板。Agent 对话标题栏不显示头像图标,“与陶泥儿的对话”及副标题按标题栏左侧对齐,钱包和审批入口继续位于右侧。

  • 数值修改立即写入当前项目的编辑态配置。

  • 当前已拉起的体验预览和测试切片不热更新;必须重新拉起后才能消费新值。

  • 自然语言新增数值项只能映射到预定义参数注册表,不允许生成或修改代码。

3.5 专业 Agent

现有六个专业组为:

group 普通用户名称 当前职责
design 策划组 玩法规格、界面原型、规则与验收口径
art 美术组 角色、场景、UI、动画和美术素材
code 程序组 可运行原型、模块实现和工程验证
balance 数值组 速度、生命、得分和难度参数
audio 音频组 背景音乐、音效和音频资源
publishing 发布组 质量评审、试玩、打包和发布准备
  • 底栏默认突出策划、美术、程序三组。
  • 允许在同一底栏展开数值、音频、发布组,不删除既有专业组。
  • 状态、当前任务和完成进度来自真实 manifest/Runtime。
  • 泥点消耗必须来自后端计费归因投影;无数据时显示“未统计”,不得用前端估算。

3.6 审批与扩展能力

  • 默认档位为严格审批。
  • P0 只有严格审批是有效运行合同。
  • 高风险审批依赖未确定的 Rank 算法,作为低优先级待解决事项。
  • 无需审批只有在 Runtime、计费、副作用、sandbox 和 reconciliation 均支持对应策略后才能开放。
  • 未开放选项使用“视觉不可用但可点击说明原因”,不使用无法触发说明的原生 disabled
  • 普通用户暂不开放 Agent.md 编辑和自定义 Skill 安装;后续必须先定义来源审核、版本、权限、沙箱和回滚合同。

3.7 主站 UI 对齐与共享视觉边界

实现状态(2026-08-10):主站与 Tauri 已完成同源 chrome 接入。Tauri 现有中央素材画布直接消费共享动作按钮、工具栏、工具组和分隔符;工作台外围继续保留四区结构,并以平台 token 统一中央壳、Supervisor、Agent Dock、状态提示和主要操作。当前普通用户入口禁用“新增资源”,现有资源“编辑资源”按图片、SVG、视频、音频、文档/代码、Agent 回执和项目版本分流,所有结果均以新 asset 或子版本保存。生成、保存、登录、计费、草稿、manifest、Runtime 和审批语义不因入口分流而改变。

2026-08-23:项目开发工作台取消顶部账户资产预留空间,资源管理主视窗与 Agent 对话从窗口顶端铺开;泥点余额 / 充值入口复用既有账户组件并放置在 Agent 对话标题栏右上角,对话标题在该视窗顶部居中。

  • 项目工作台继续保留左侧平台导航、中央主视窗、右侧 Project Supervisor 和底部专业 Agent 状态栏四区结构;主站图片编辑器只作为视觉语言和共享画布组件的事实源,不把其素材库侧栏、账号业务或云端项目外壳整体搬入客户端。
  • 平台主题事实源固定为 packages/shared/src/theme.css。画布通用 chrome 固定落在 @genarrative/image-canvas-react,主站与 Tauri 必须直接 import 同一组件和作用域样式;客户端不得复制 src/components/image-editor/,也不得导入主站完整 src/index.css
  • 第一批共享 chrome 固定覆盖画布动作按钮、工具栏、工具分组和分隔符。按钮的默认、悬停、键盘焦点、选中、禁用和主次色语义由共享层表达;宿主只提供图标、文案、事件与业务禁用条件。
  • 主站账号、钱包、服务端项目、云端素材库和生成面板仍留在网站宿主;客户端本地项目、manifest、Runtime、审批、草稿、生成与正式提交仍留在 Tauri 宿主。共享视觉组件不得读取这些业务事实。
  • 客户端 UI 对齐采用“同视觉、同组件、保留四区布局”,不复制主站整页布局。资源总览、运行视图和 Supervisor 对话继续是 Game Agent 工作台独有语义。
  • 工作台四区作为同一应用工作面直接衔接,外层不使用卡片圆角或留白间距。中央主视窗与右侧 Supervisor 使用各自的平台区域底色,并以稳定的竖向分隔线明确边界;不通过外层圆角容器、阴影或区块间缝重新包装四区。
  • 右侧正式钱包入口属于客户端宿主 chrome,在普通项目工作台与 UI Editor 子路由中都必须持续可见、键盘可达且可操作,不得因进入素材编辑壳或隐藏全局 chrome 而丢失余额、充值和使用详情入口。
  • 资源总览的“资源依赖 / 资源类型”视图切换使用连通的分段按钮组,相邻选项共享边界并保持唯一选中语义。每个分段都必须有清晰的键盘焦点指示,焦点环不得被分段容器的圆角或 overflow 裁切。
  • 右侧 Supervisor 对话中,用户消息使用右对齐、最大宽度受限的主题暖色气泡,assistant 消息保持左对齐;消息换行不得产生水平溢出,执行过程卡继续占满消息区可用宽度。消息列表必须约束在右侧对话列内并独立滚动,不得覆盖中央资源或运行视图;提交按钮必须保留随状态变化的可访问名称。气泡正文在 light / dark 平台主题下均须满足 WCAG AA 普通文本 4.5:1 对比度。
  • 客户端正式产品仍只按最小 1280×720 横屏合同交付,并保留 1280×800 默认窗口与既有基线验收;更窄浏览器样式只负责不崩溃和开发兼容,不改成移动端创作工作台。
  • 工作台顶部播放按钮在桌面视窗中水平居中;资源管理视窗触发播放时直接切换到运行视窗并启动本地预览,不再弹出 game.run_local 二次确认。
  • 创建模式素材画布的“素材名称”是用户可编辑的正式输出名称;“资源用途”是 manifest subtype,不向普通用户开放自由文本。新增资源默认“普通游戏美术”,可从普通游戏美术、统一视觉规范、游戏界面原型、核心美术图集四项中选择。图片精修继承源名称和用途,不显示创建模式保存设置;候选图片只从选中图片的“设为最终图”提交。精修顶栏只保留返回、导入、定位当前最终图、撤销和重做,删除进入图片上下文工具栏,通用 AI 生成只保留给创建模式。图片输出统一使用 PNG;创建模式工具动作与保存设置分层展示,“保存到项目”在 1280×800 和窄容器中都必须完整可见。
  • 首页创作输入区与“最近项目”之间不展示共享项目状态文本,“最近项目”标题下也不追加解释性副标题;默认、成功、进行中或失败状态均不得在该位置形成文字行,项目管理页继续保留自己的状态反馈。

3.8 现有 Godot 项目

  • 首页和项目组统一使用“打开项目”,不提供独立 Godot 按钮。用户选择的目录作为工作区根;系统先检查根目录,再检查一层直接子目录中的普通文件 project.godot。根目录命中优先;一层发现多个 Godot 工程时必须提示歧义,不猜测目标。
  • 工作区根始终绑定文件读取、修改、命令 cwd、对话、Runtime 和最近项目记录;.agent/、Agent DB 与日志也只写在这里。project.godot 所在目录额外以 godotProjectRoot 记录为相对工作区的 . 或单层目录名,不把项目作用域切到 Godot 子目录。
  • 首次打开只在工作区根创建 .agent/ 元数据;已有 .agent/manifest.json 时读取并按当前唯一文件布局校准 godotProjectRoot。Godot 源码、场景、资源和项目配置继续使用原目录结构,不复制工程,也不建立 game/assets/memory/exports/ 平行目录。
  • Godot 项目使用 standard Run Profile,避免套用 Web 原型的 game/index.html、本地 HTTP 预览和自主 Web 游戏完成门;本期不提供 Godot 内嵌运行预览。

3.9 项目管理页

  • 项目页采用“标题与状态 + 本地搜索 + 打开项目 / 新建项目 + 紧凑项目表格”的桌面信息架构。可以参考成熟项目管理器的信息层级和密度,但不得复制 Unity 等外部产品的品牌、Logo、深色皮肤、专有图标、列名或文案;页面继续使用 Genarrative 平台主题和陶泥儿客户端壳。
  • 表格只展示现有权威数据:项目名称与工作区绝对路径、GameAgent / Godot 类型、目录 / manifest / 最近 Runtime 状态和行级操作。当前目录检查合同没有修改时间、编辑器版本、收藏或云状态,前端不得伪造这些列。
  • 可打开项目的主行点击后进入项目;显示目录和从最近列表移除收进键盘可达的行尾更多菜单。Escape 关闭菜单并把焦点还给触发按钮;移除只修改本机 WebView 最近项目记录,不删除磁盘文件。
  • 搜索只在已加载项目行中匹配名称、路径、类型、Godot 相对根和状态,不改 localStorage、不触碰项目目录、不新增后端或 Tauri 命令。无匹配状态提供清除搜索;真正空状态仍只引导用户使用顶部打开或新建,不追加第三个目录选择入口。
  • 正式视觉验收只覆盖 1280×720 最小横屏和 1280×800 默认窗口:工具栏保持单行,表头与项目列对齐,项目列表内部滚动,document/body 不出现页面级横向或纵向溢出。截图必须使用含 Web、Godot 和无效状态的 populated fixture;视频必须演示搜索、清除、行尾菜单及可观察的项目操作结果,不能只录静止页面或无结果点击。

4. 工作台状态机

4.1 主视窗

resource-overview
  -> asset-canvas.create(当前临时禁用,不向普通用户开放)
  -> asset-canvas.refine(静态图片“编辑资源”)
  -> resource-editor.deriveSVG、视频、音频、文档/代码、Agent 回执“编辑资源”)
  -> resource-editor.version-branch(项目版本“编辑资源”)
  -> run(存在 runnableVersion 且 loopback preview 可启动)

asset-canvas.create|refine
  -> resource-overview(取消、保留草稿退出或保存投影完成)

run.playing
  -> run.paused(用户暂停或切片结束)
  -> resource-overview(先暂停当前预览表现,再切换视图)

run.paused
  -> run.playing(继续当前切片)
  -> run.relaunching(数值或版本编辑态发生变化)
  -> resource-overview

运行入口不可用时仍允许点击,显示“当前无可运行版本”,但不切换状态。素材创作的完整 opening/editing/generating/saving/cancelling/failed/recovering 状态、草稿身份和迟到结果门禁以 【技术方案】客户端素材创作无限画布阶段一合同-2026-08-05.md 为准。

4.2 测试切片

idle -> starting -> playing -> paused -> completed
                     |          |
                     +-> failed +-> playing

completed -> starting(nextSlice)
  • 单个切片完成后自动进入 paused
  • 上一项/下一项会停止当前切片并启动目标切片。
  • 数值编辑态变化后,当前切片标记 stale;重新拉起前不消费新值。

4.3 资源聚焦

idle -> focused(document|art|audio|version) -> idle
  • 文档:合法 Agent 文本回执直接使用对话投影内容;项目文件只允许读取当前 manifest 已登记资产或已完成任务产物中的 Markdown、文本、JSON、YAML、TOML,必须经过 file.read auto 权限、相对路径、项目边界、普通文件、符号链接 / 硬链接、读取漂移、2 MiB、UTF-8 与扩展名白名单校验。正文使用不执行 HTML、不加载远程图片、不产生可点击外链的安全 Markdown 渲染,并在中央画布内独立滚动;读取失败显示错误空态。聊天侧 /read 回执中的文件正文必须作为代码块渲染为 <pre><code>,以便用户审阅源码字面量但不执行其中的 HTML;Markdown 渲染使用 react-markdownskipHtml,依赖库对代码 span / fenced code 的文本转义;不得在整段 Markdown 上预转义 HTML,否则会把代码中的 <tag> 双重转义为字面量 &lt;tag&gt;
  • 美术:PNG、JPEG、WEBP、GIF、SVG、AVIF、BMP、MP4、WebM、MOV 只在资源卡本体中按既有受控读取、文件签名与解码门禁展示;中央详情不重复加载或放大图片 / 视频本体。SVG 继续拒绝脚本、事件处理器、外部资源引用和实体声明。
  • 音频:只读取 manifest 已登记音频或已成功导入且登记到 manifest 的附件,按文件签名接受 MP3、WAV、OGG / Opus、M4A、AAC、FLAC;聚焦态展示实际格式、浏览器解码后的时长以及带播放进度和暂停能力的内置播放器。音频任务声明中的未登记路径继续不得读取或播放。
  • 版本:只展示 manifest 中正式、不可变的迭代版本记录;版本卡展示项目修订、创建原因与父版本,聚焦态同时展示直接子版本和资源绑定。点击版本卡后高亮仍存在于当前资源投影中的引用资源;缺失历史资源只保留绑定身份,不生成幽灵资源卡。资源替换仍留给后续切片。
  • mentor 最新决定:资源聚焦不提供工具栏,也不提供工具侧边栏。
  • 音频:只读取 manifest 已登记音频或已成功导入且登记到 manifest 的附件,按文件签名接受 MP3、WAV、OGG / Opus、M4A、AAC、FLAC;聚焦态展示实际格式、浏览器解码后的时长以及带播放进度和暂停能力的内置播放器。音频任务声明中的未登记路径继续不得读取或播放。
  • 版本:只展示 manifest 中正式、不可变的迭代版本记录;版本卡展示项目修订、创建原因与父版本,聚焦态同时展示直接子版本和资源绑定。点击版本卡后高亮仍存在于当前资源投影中的引用资源;缺失历史资源只保留绑定身份,不生成幽灵资源卡。资源编辑只允许追加继承源绑定并记录提示词的子版本,不允许原地替换或修改源版本。
  • 资源聚焦不提供通用工具栏或工具侧边栏;图片聚焦态允许一个明确的“精修资源”业务动作进入素材创作无限画布,该动作不是在聚焦容器中内嵌编辑器或恢复通用工具栏。
  • 点击资源后,中央主视窗从 resource-overview.list 切换为 resource-overview.focused.document / art / audio / version,左侧平台导航、右侧 Supervisor 对话和底部 Agent 状态栏保持原位;聚焦容器以路径、类型、来源任务、依赖层级、同类型上下游和版本字段为首屏主体,不使用页面级浮层或可拖动标题栏。文档正文与按意图加载的音频控制位于元数据之后。
  • 焦点转换以稳定资源 ID 为准。只有从资源列表进入详情或从一个资源 ID 切换到另一个 ID 时聚焦详情 region;同一资源 ID 因 manifest 更新而重新投影时,不得抢走详情内音频 / 视频控件、文档链接或收起按钮的当前焦点。
  • 显式收起或按 Escape 后恢复进入前的搜索条件、dependency / type 布局模式、资源画布滚动位置和选中资源,并优先把键盘焦点还给原触发资源卡;这些只属于当前前端会话,不写入布局 sidecar。若资源已经被后台删除,必须清理 stale focused / selected ID、关闭详情并把焦点落到“搜索项目资源”,不得落到 body。项目切换和进入运行视图必须取消旧项目的焦点恢复意图。
  • 资源管理阶段四至阶段七交付上述受控读取、媒体展示、正式版本展示和引用高亮;2026-08-05 起图片编辑闭环生效,2026-08-10 起全类型非破坏性派生与版本子分支覆盖旧的只读限制。入口必须与草稿或 operation 恢复、正式事务提交、referenceResourceIds 血缘、新资源即时投影、两份布局和焦点竞态一次实现,不能只打开一个没有回写的面板。

4.4 历史成果与当前状态

  • “当前工作状态”只展示当前 Supervisor run 下的专业 Runtime。
  • “项目已有成果”按项目持久保存,不随 Supervisor run 切换而清空。
  • Agent 文本成果只认可带合法 agent-finalization-<32 lower hex> messageId 的 assistant 消息。
  • 新 run 失败、待确认或未完成时继续展示最近一次成功成果;新的成功 finalization 才替换同 Agent 的旧成果。
  • 文本回执不得冒充图片、音频、项目文件或 manifest asset。

5. 数据合同

以下合同先冻结字段语义;P0 只实现标注为 P0 的部分。

5.1 工作台中央状态(素材创作阶段一目标合同)

type ProjectWorkbenchViewState = {
  schemaVersion: 'game-creator-workbench-view.v2';
  projectId: string;
  centerState:
    | { kind: 'resource-overview' }
    | {
        kind: 'asset-canvas';
        sessionId: string;
        draftId: string;
        intent: 'create' | 'refine';
        sourceAssetId: string | null;
      }
    | { kind: 'run' };
  approvalMode: 'strict' | 'risk' | 'none';
  expandedAgentGroups: Array<'balance' | 'audio' | 'publishing'>;
};

game-creator-workbench-view.v1.mode='resources' 读取时只映射到 resource-overviewmode='run' 映射到 run;旧状态不能合成 asset-canvas 草稿。sessionId 是本次进入流程的短生命周期 UUID,draftId 是本地可恢复草稿 UUID。create 必须没有源资产,refine 必须绑定当前 manifest 中唯一图片资产。approvalMode 仍只有 strict 可有效写入;其它值只能作为不可用选项展示。

5.2 资源画布布局(P1

实现状态(2026-08-22):dependency / type 双模式通过项目内 CAS sidecar 独立持久化;dependency 模式由 Tauri Rust 只读构建关系拓扑与确定性依赖深度、前端 SVG 派生几何,图结构和线段均不写入布局 sidecar。依赖图加载完成前设布局初始化屏障,避免以临时 dependencyDepth=0 生成并持久化错误坐标。非空资源总览支持自动布局、资源卡点击与手动拖动;素材创作无限画布独立支持 viewport 与图层变换,分区高度/倍率与 sidecar 完全分离。

type ProjectResourceCanvasLayout = {
  schemaVersion: 'game-creator-resource-layout.v1';
  projectId: string;
  mode: 'dependency' | 'type';
  revision: number;
  positions: Array<{
    resourceId: string;
    section: 'document' | 'art' | 'audio' | 'code' | 'version';
    x: number;
    y: number;
    manuallyPlaced: boolean;
  }>;
  updatedAt: number;
};

两个 mode 是两份独立坐标集合;独立客户端的本地项目持久层以 projectId + mode 做 CAS 更新。

5.2.1 字段语义

  • x / y 是相对所属 section 内容原点的 CSS 像素坐标,落盘前四舍五入为整数;坐标不使用 viewport、页面或资源详情浮层坐标系。
  • updatedAt 是持久层生成的 Unix 毫秒时间戳,前端不得自行覆盖。
  • revision0 开始;布局文件不存在时读取接口合成 revision=0 / positions=[],首次成功写入返回 revision=1,后续每次成功 CAS 写入递增 1。JSON / Tauri / TypeScript 全链路合法范围固定为 0..=9_007_199_254_740_991Number.MAX_SAFE_INTEGER),读取、返回或提交负数、小数、非有限值与超限整数都必须失败关闭。
  • 新资源第一次进入某个 mode 时由默认布局写入 manuallyPlaced=false。用户在当前栏目画布中拖动资源卡并成功释放后写入 manuallyPlaced=true;后续资源投影和 dependency 自动重算必须保留这些手动坐标。
  • 同一份布局中 resourceId 必须唯一。持久层允许暂时存在当前资源投影中没有的旧 ID,因为 Agent 文本成果等资源可能晚于 manifest 恢复;前端协调后必须在下一次成功写入中清除已确认失效的坐标。
  • 单份布局最多保存 4096 个位置,序列化文件不得超过 2 MiBresourceId 最多 512 个 Unicode 字符,x / y 取值范围固定为 -1_000_000..=1_000_000

5.2.2 本地存储与业务边界

独立客户端把两份布局保存为项目内 UI sidecar:

.agent/workbench/resource-layouts/
├─ dependency.json
└─ type.json
  • 文件名必须与 payload 的 mode 一致;payload 的 projectId 必须与当前 .agent/manifest.json 一致。
  • 布局只属于工作台 UI 状态,不写入 manifest,不增加游戏项目 mutation revision,不使 Runtime verification 失效,不触发权限确认,也不作为 Agent 产物、资产或 Git 提交依据。
  • 写入复用项目安全路径解析、普通文件 / 链接校验和原子 JSON sidecar 安装能力;使用资源布局专用系统文件锁串行化 read-check-write,不用前端进程内互斥替代跨窗口锁,也不长期占用 Agent Runtime 的项目 mutation 锁。.layout.lock 是持久锁入口,Unix 互斥跟随 flock 文件描述符,Windows 互斥跟随不共享的文件句柄;进程退出由操作系统释放,应用不得按 mtime、PID 文本或其它 stale 启发式删除锁文件。
  • 主文件损坏、schema 不支持、身份不匹配、文件超限或安全文件检查失败时必须失败关闭,不得把默认空布局覆盖到原文件。若原子安装留下可验证的恢复副本,读取时可按既有 sidecar 恢复规则恢复后再返回。
  • 本切片不把布局同步到 api-server、SpacetimeDB、云端账号或其它设备。

5.2.3 Tauri 命令合同

type ReadProjectResourceCanvasLayoutInput = {
  projectPath: string;
  mode: 'dependency' | 'type';
};

type UpdateProjectResourceCanvasLayoutInput = {
  projectPath: string;
  expectedProjectId: string;
  mode: 'dependency' | 'type';
  expectedRevision: number;
  positions: ProjectResourceCanvasLayout['positions'];
};

type UpdateProjectResourceCanvasLayoutResult =
  | {
      status: 'updated';
      layout: ProjectResourceCanvasLayout;
    }
  | {
      status: 'conflict';
      layout: ProjectResourceCanvasLayout;
    };
  • 读取命令固定为 read_local_project_resource_canvas_layout,返回当前 mode 的完整布局;文件不存在时返回合成的 revision 0 布局,不为只读操作创建目录或文件。
  • 更新命令固定为 update_local_project_resource_canvas_layout。调用方只提交当前已读取布局的 expectedProjectId 身份栅栏,不提交 projectId / revision / updatedAt 的权威新值;Tauri 必须先只读确认项目存在、manifest 有效且 projectId 与栅栏一致,随后获取系统锁并在锁内复核 projectId、重新读取当前布局,再生成新的 revision 与时间戳。路径被其它窗口重建为新项目时,旧窗口必须在任何布局副作用前失败。不存在目录、普通非项目目录或损坏 manifest 均不得先创建 .agent/workbench、锁文件或布局文件。
  • expectedRevision 与锁内 revision 相同才允许原子写入并返回 updated;不同时不得写文件,返回 conflict 和锁内最新完整布局。前端不得通过解析错误字符串识别 CAS 冲突。
  • Rust 内部 revision 使用 u64,但 JSON / Tauri 合同统一限制为 0..=9_007_199_254_740_991,每次成功必须严格递增;持久值或 expectedRevision 超限时必须拒绝,当前值达到上限时失败关闭并保持原文件字节不变,不得把超出 JavaScript 安全整数范围的值返回前端或用于 CAS。
  • 项目无效、布局损坏、字段校验失败和文件系统错误继续作为安全、可理解的 Tauri command error 返回;错误不得包含配置、凭据或项目外绝对路径。

5.2.4 前端布局与协调合同

  • 资源卡容器负责拖动,内部“打开详情”和媒体控制仍可点击。Pointer 距离小于 5px 时保持点击语义;超过阈值后按当前 viewport scale 换算世界坐标,乐观更新卡片 x / yis-dragging class 与依赖线拖动预览。拖动可越过所属 section 原点,坐标允许落在 -1_000_000..=1_000_000
  • 指针释放且拖动已改变时提交一次 manuallyPlaced=true 的布局 CASpointer cancel 恢复起始坐标且不提交。拖动后的释放点击被抑制,不打开资源详情。
  • dependency 默认布局按 Rust 返回的 dependencyDepth 形成横向层级;同层仅在所属固定分区内按精确引用、聚合 task-flow 的稳定邻接、连通簇和固定两轮中位数扫描确定纵向次序,随后寻找第一个不重叠位置。task-flow 只作为聚合超边参与分组和排序,不能生成资源两两边。dependency 自动布局使用专用 48px 列间走线区和 40px 行间走线区;相关簇以本簇最大层行数为高度,资源较少的层在该高度中居中,避免菱形 / 分叉关系一侧极短、另一侧过长。type 默认布局继续使用原有 16px 行列间距,并固定按“资源子类型 -> 媒体类型 -> 名称 -> 资源 ID”稳定排序。布局模型的 subtype 必填:manifest 资产使用 asset.kind,任务产物、导入附件与 Agent 文本成果分别使用稳定的 task-artifactattachmentagent-result,不得以缺失值或显示文案兜底;资源协调签名必须包含 subtype。卡片尺寸、间距和 -1_000_000..=1_000_000 坐标范围由前后端同名合同维护。超深依赖仍保留原始 dependencyDepth 业务真相,但显示坐标在上限列确定性饱和并纵向避让;自动布局在 IPC 前必须保证全部 x / y 合法,不能向 Tauri 永久重放必然失败的坐标。
  • type 模式资源集合变化时保留全部仍存在的坐标,只为新 ID 计算默认位置,并删除已确认失效的旧 ID。dependency 模式只永久保留 manuallyPlaced=true 的历史坐标;manuallyPlaced=false 属于可派生自动位置,在 Rust 关系图首次就绪、dependencyDepth 或资源拓扑身份签名(精确引用端点和聚合 task-flow 成员)变化后按最终拓扑确定性重算。签名以稳定资源 ID 的规范端点 / 成员序列生成固定大小摘要,不使用显示名称或浏览器测量值;自动重算不得移动手动坐标,协调结果与持久布局逐项一致时不得产生 CAS 写入。
  • 搜索或筛选只隐藏卡片,不删除、压缩或重排其坐标;清空搜索后恢复原位置。
  • 窗口尺寸变化只改变当前栏目的可视范围,不回写或裁切持久坐标,也不因资源 extent 或 resize 把已平移的 viewport 拉回内容边界。当前客户端继续以 1280×800 横屏合同验收。
  • 任一可见资源出现后,普通用户资源管理固定使用 设计文档 -> 美术资源 -> 音乐音效 -> 项目版本 四栏目分页画布;游戏代码仍保留在内部资源、布局和依赖事实中,但不进入普通资源画布的导航、分页、卡片、搜索或详情入口。每个可见栏目按 projectId + mode + category 保留独立 viewport,普通 wheel 切换栏目,Ctrl/Cmd + wheel 以指针位置为锚点缩放当前无限画布,空白拖动只平移当前栏目;非空状态不提供分区高度、分区内部滚动或分区内容倍率。搜索和详情开关不得重置 viewport,项目、mode 或栏目切换只恢复各自会话状态,显式复位才重新适配当前栏目内容。
  • 首次载入项目中的既有资源不显示未读标识。当前会话内,非当前栏目出现稳定 ID 的新资源时,在对应栏目名称右上角显示红点;当前栏目新增资源不显示红点,用户通过点击、滚轮或程序跳转进入该栏目后立即清除。未读状态只属于当前前端会话,并按 projectPath + projectId 隔离,切换项目时清空,不写入 manifest、布局 sidecar 或后端。
  • 打开项目、切换 mode 或当前 mode 首次出现新资源时执行“读取 -> 协调 -> 必要时 CAS 写入”;dependency 模式必须先等待与当前 projectPath + projectId + resource inputs 匹配的 Rust 图进入 readyfailed 终态,等待期间不得创建 fallback、读取 sidecar、协调资源或入队保存。failed 只允许以空图降级初始化一次。项目或 mode 已切换后返回的旧异步结果必须丢弃。
  • 同一 projectPath + projectId + mode 的首次读取与资源集合协调必须分开:资源集合变化不得取消已经发出的读取或保存。当前 scope 内资源自动协调写入使用单写者 FIFO,任一时刻最多一个 CAS 在途,后一笔必须使用前一笔成功返回的 revision。切换项目或 mode 后,旧 scope 的在途请求不能阻塞新 scope 队列;前端放弃旧请求槽位并丢弃其迟到响应,后端继续依靠 expectedProjectId + expectedRevision + 系统锁 仲裁已发出的请求。
  • 自动协调 CAS 冲突时直接载入返回的最新布局;仍需协调时可以基于权威 revision 最多追加 2 次重试,持续跨窗口写入时不得无限自旋。当前提示只说明“布局已在其他窗口更新”,不得要求用户重新拖动。
  • 缺少 Tauri bridge 的浏览器开发态可以保留当前会话内布局用于界面测试,但不得宣称已经持久保存。

5.2.5 手动拖动合同

  • Pointer Events 使用 5px 移动阈值,拖动期间指针捕获到卡片,画布普通滚轮仍切栏目,Ctrl/Cmd + wheel 仍以真实画布指针位置缩放。
  • 拖动提交沿用现有单写者 FIFO 与 CAS 冲突重试;冲突提示沿用“布局已在其他窗口更新”,用户可重新拖动。历史 manuallyPlaced=true 坐标仍优先保留。
  • 资源卡拖动统一调用现役 Hook 手动意图、命令式 SVG preview、sidecar 字段和 Rust CAS:拖动期间只更新当前会话预览,成功释放后提交一次手动布局 CAS,取消或未超过阈值不写入。

5.2.6 资源依赖关系图层

  • 阶段五实现状态(2026-08-03):dependency 自动排列同时消费任务 DAG 与精确资源引用。Rust 把可信 producer 的任务深度作为资源深度下限,再对 asset-reference 图做迭代式 SCC 压缩与确定性层级传播;被引用资源位于引用资源之前,同一引用环共享稳定深度,环后资源继续递增,没有引用关系的资源保持默认不重叠位置。布局深度通过独立 dependencyDepths 返回,不能把 producer assignment 冒充全部资源的布局结果。
  • producerMappingTruncated=true 只关闭依赖有界 Agent DB 审计的 producerAssignmentstaskFlowscyclicTaskIds。Rust 返回的 dependencyDepths 仍是 manifest / 精确引用 read model 的权威结果,前端必须过滤未知资源、负数、非整数和非安全整数后继续消费;不得因 producer 截断清空全部深度,也不得在前端重算替代深度。referenceEdges、connection index 中的 reference 关系、cyclicResourceIds 和 unresolved reference 继续保持可信。
  • 图层只在 dependency 模式挂载;type 模式不得渲染 SVG、连线或 marker。切换 mode、切换项目或卸载工作台时必须销毁旧图层,并清理尺寸观察和窗口事件监听。
  • 输入固定为当前栏目资源投影的卡片身份 / 栏目内坐标与 Tauri Rust 返回的 ProjectResourceGraph 只读 DTO;Rust 负责资源过滤、去重、迭代式环检测、SCC 压缩后的确定性依赖深度、任务流聚合和一跳连接索引,前端只负责 DTO 防御归一化、当前栏目 viewport 变换与原生 SVG path / marker。dependency 当前栏目持有一个覆盖该栏目内容的 SVG,SVG 与卡片直接消费同一坐标和 viewport transform;端点主路径不得通过 getBoundingClientRect 拼接屏幕坐标。SVG 位于资源卡底层并设置 pointer-events: none,不得引入 D3、React Flow 等图表库,也不得阻断卡片点击。
  • asset-reference 表示精确资源引用;当前可见且两端均属于当前栏目的引用进入该栏目 SVG 和无障碍关系说明,使用明亮橙色实线与实心箭头。只有同分类引用参与自动布局邻接,跨分类引用不形成布局簇、边界偏置或分栏连线。GameCreationAppAssetManifestEntry.source.referenceResourceIds 中的外部资源 ID 必须先唯一匹配另一项资产的 source.resourceId,再映射为当前资源卡 ID;缺失、重复或已删除的目标均不得渲染幽灵连线。
  • task-flow 表示同一资源类型内的任务产物流转,但资源画布不再绘制灰色虚线或任务流 marker,也不把它加入 aria-describedby 关系说明。它只按 sourceTaskId -> targetTaskId + section 作为聚合超边参与 dependency 连通簇和中位数排序,禁止对上下游资源生成笛卡尔积邻接;详情仍可展示 Rust read model 已证明的任务信息。
  • 画布资产 producer 只能来自 agent.runtime.canvas.asset_generateassetId -> agentId 审计且 agentId 必须存在于当前 manifestExternal Editor source.taskId 属于平台生成任务命名空间,禁止当作 manifest task ID。证据缺失、冲突或有界审计读取未覆盖时不生成对应 task flow,不猜测归属。
  • 图模型必须对资源引用图和完整任务依赖图做迭代式环检测,不得用无界递归遍历;参与环的可见边保留渲染并标记 cyclic,环本身不能造成重复生成或死循环。
  • 资源自引用的起点与终点为同一张卡片时,必须绘制在卡片外侧的可见闭环并保留箭头,不得让路径穿过卡片后被底层 SVG 层级遮挡。
  • 搜索只允许为当前可见端点生成几何;任一精确引用端点隐藏时该橙线隐藏。task-flow 不产生显示几何,搜索也不因此重排布局。
  • 同类型精确引用按稳定边 ID 和对端次序为同一卡片同侧的多条边分配独立端口;横向层级可用时优先左右连接,同列或横向间隙不足时才上下连接。同轴端点直接用直线,需转向时使用正交线段与最大 10px 的小圆角,不使用大范围贝塞尔控制柄。端口顺序不使用显示名称、随机数或浏览器枚举顺序,相同输入必须产生相同路径。资源点击只进入中央聚焦并保留当前选中卡片,不改变依赖卡片或连线的颜色、线宽与透明度;关系线始终直接展示,不提供点击后的上下游高亮或无关线弱化。
  • 资源卡 Pointer Move 不改变基础 positions 或 SVG 几何。连线只随布局读取、资源自动协调、搜索、项目切换或 section origin 变化而更新。
  • 当前 dependency 栏目平面最多构造一个 ResizeObserverobserver 只维护当前栏目 viewport,不测量或重建卡片屏幕端点。栏目 extent 必须为最右侧自环和箭头保留视觉 gutter,但不得修改卡片坐标或布局 sidecar。
  • 非空资源页的普通滚轮固定切换栏目;拖拽平移、Ctrl/Meta + 滚轮缩放和窗口 resize 共用当前栏目 viewport 变换。原生 { passive: false } wheel 监听必须阻止 WebView 默认滚动或缩放,并对连续滚轮事件做节流。完全空项目的分区展览保留原生分区滚动。项目 / mode 切换或卸载时必须清理 observer、wheel 与 window resize 监听。
  • 阶段五保留已有 manuallyPlaced=true 坐标;资源卡拖动成功释放会将该卡片写为 manuallyPlaced=true,后续资源引用新增或变化只重新派生 manuallyPlaced=false 的自动坐标。任务流继续按任务对与资源分区聚合,禁止为了布局分组生成资源笛卡尔积,且不进入 SVG。

5.3 资源类型与替换兼容性(P1

实现状态(2026-08-29):内部资源投影仍识别“设计文档、美术资源、音乐音效、游戏代码、项目版本”五类事实,但普通用户资源画布只展示“设计文档 -> 美术资源 -> 音乐音效 -> 项目版本”四个栏目;游戏代码不进入画布导航、分页、卡片、搜索或详情入口。设计文档接收受支持的 UTF-8 文档、代码资产中的文档类型和合法 Agent 文本回执;项目版本只接收显式 ProjectVersionResourceSummary read model,未知任务产物不得兜底为版本;美术资源接收图片、SVG、动画和视频类产物;音乐音效接收 manifest 资产、上传登记资产和已完成任务 artifacts 明确声明的音频产物;游戏代码继续接收 Direct Codex / 任务产物登记的 HTML、CSS 和 JavaScript,底层文件、manifest 事实、生成/编辑/运行能力、项目版本引用与依赖关系不变。无法识别的二进制任务产物和附件不进入资源画布。受控读取、中央聚焦、失败空态与媒体播放不改变 manifest 真相;编辑成功后只追加新的 asset 或版本子记录。

资源身份固定使用 manifest asset ID、正式 version ID、Agent ID + run ID 或已导入资源稳定路径;显示标题、来源文案变化不得改变 resourceId,从而避免布局、依赖边、选择和聚焦状态因改名失效。

type ProjectResourceDescriptor = {
  resourceId: string;
  category: 'document' | 'art' | 'audio' | 'code' | 'version';
  subtype: string;
  width?: number;
  height?: number;
  durationMs?: number;
  format: string;
};

type ProjectVersionResourceReplacement = {
  sourceVersionId: string;
  sourceResourceId: string;
  replacementResourceId: string;
  compatibility: {
    categoryEqual: boolean;
    subtypeEqual: boolean;
    sizeSpecEqual: boolean;
  };
};

三项兼容性必须同时为 true 才能创建下一版本。

5.4 游戏迭代版本(P1

阶段六实现状态(2026-08-13 更新):正式版本业务真相扩展在本地项目 .agent/manifest.json 的可选 versions 字段中;旧项目字段缺失时等价于空列表,不根据 checkpoint、布局 sidecar、静态检查、失败试玩或单独的 game-creator-project-revision.v1 自动伪造版本。版本数组只允许追加,已有记录不得删除、重排或修改;首轮没有版本创建按钮。自主首板只有在当前 revision 的 preview.validate 已成功形成持久试玩回执后,才幂等追加首条 initial 版本,并绑定当时 manifest 中全部已登记资源;同一完成态恢复不得重复创建。已有正式版本时,后续试玩通过不自动追加版本,仍由明确的资源派生事务创建子版本。

type GameIterationVersion = {
  versionId: string;
  parentVersionId: string | null;
  projectRevision: number;
  resourceBindings: Array<{ slotId: string; resourceId: string }>;
  createdReason: 'initial' | 'resource-replacement' | 'agent-revision';
  createdAt: number;
};

type GameCreationAppManifest = {
  // 既有字段省略
  versions?: GameIterationVersion[];
};
  • versions 按追加顺序保存。第一条必须是 initial + parentVersionId=null;后续记录必须引用数组中更早出现的父版本,创建原因不能再是 initial,从而天然排除自引用、悬空父版本和父子环。
  • projectRevisioncreatedAt 必须是 JavaScript 安全非负整数;子版本的修订必须严格大于父版本,创建时间不得早于父版本。
  • 同一版本内 slotId 唯一;resourceId 固定保存 manifest asset ID,不保存资源卡显示名称、External Editor resource ID、路径或布局 ID。历史资源已不在当前 manifest 时仍保留原绑定,但界面不为其合成资源卡。
  • Tauri manifest 存储边界在每次写入前校验完整版本图,并与磁盘中的旧 versions 前缀逐项比较;只允许追加新记录,已有记录被修改、删除或重排时写入失败且原文件保持不变。
  • 版本卡标题由稳定追加序号生成,卡片与聚焦态展示 versionId / projectRevision / createdReason / parentVersionId;聚焦态额外展示直接子版本和全部 slot 绑定。点击版本卡只高亮当前投影中唯一匹配 asset:<resourceId> 的资源卡,不修改版本或资源。

5.5 测试切片与数值参数(P2

type GameTestSlice = {
  sliceId: string;
  versionId: string;
  title: string;
  order: number;
  startCondition: string;
  endCondition: string;
  status: 'idle' | 'starting' | 'playing' | 'paused' | 'completed' | 'failed';
};

type GameTunableParameterDefinition = {
  parameterId: string;
  label: string;
  valueType: 'integer' | 'number' | 'boolean' | 'enum';
  min?: number;
  max?: number;
  step?: number;
  enumValues?: string[];
  writePath: string;
  codeMutationAllowed: false;
};

参数写入立即增加编辑态 revision;当前 preview/slice 保持旧 revision,并显示“需要重新拉起”。

5.6 Agent 泥点归因(P2

type ProjectAgentMudPointAttribution = {
  projectId: string;
  agentGroup: 'design' | 'art' | 'code' | 'balance' | 'audio' | 'publishing';
  chargedMudPoints: number;
  refundedMudPoints: number;
  netMudPoints: number;
  asOf: number;
};

该投影只能由后端账本聚合产生。

6. 分阶段范围

P0:当前实施切片

  • 复用现有四区工作台壳。
  • 资源/运行切换与客户端内 loopback 预览。
  • 固定四类资源投影、只读资源画布与中央主视窗资源聚焦;资源聚焦工具栏 / 工具侧边栏及后续媒体能力暂缓。
  • Supervisor 正式会话、上传、Runtime 确认与安全错误。
  • 当前 run 专业状态与项目历史成果分离。
  • 默认三专业组,并可展开另外三组。
  • 严格审批有效;风险/无需审批可点击查看未开放原因。
  • 与主站图片编辑器一致的平台轻色主题、共享画布 chrome 与 1280×800 横屏边界。

P1

  • 已实施依赖/类型两套坐标持久化、首次默认不重叠布局、历史坐标跨重启恢复、自动协调 CAS 冲突处理与资源卡手动拖动。
  • 资源关系线在布局持久化验收通过后单独实施,不与本切片捆绑伪造完成。
  • 已实施正式版本不可变模型、版本卡、父子关系与引用资源高亮;“编辑资源”可追加继承源绑定并记录提示词的子版本,资源直接替换、运行版本切换和兼容性迁移仍待后续切片。
  • 素材创作无限画布阶段一按权威专题一次交付图片导入、编辑、生成、导出、草稿恢复、正式本地回写、即时投影和焦点竞态闭环。
  • 高级抠图、图集、角色动画、视频时间线编辑和音频波形级编辑按后续切片实施;当前视频走源引用派生,音频只做语义重制。

P2

  • 测试切片正式协议与恢复。
  • 参数注册表、立即写编辑态和预览重新拉起。
  • 泥点归因 read model。
  • Agent.md/Skill 安全合同。
  • 高风险审批 Rank 与无需审批运行合同。

7. 验收

7.1 P0 验收

  1. 1280×800 下页面无横向或纵向溢出,输入框与 Agent Dock 始终可见。
  2. 运行入口不可用时点击给出原因;可用时只在客户端内打开 loopback 预览。
  3. 当前 Supervisor run 变化后,旧成功 Agent 文本成果仍可查看;普通失败 assistant 不进入资源区。
  4. 底栏默认显示策划、美术、程序,可展开数值、音频、发布;状态与任务来自真实 Runtime/manifest。
  5. 风险审批和无需审批不能改变运行策略,点击后明确提示尚未开放;严格审批继续使用现有 Runtime 门禁。
  6. 不显示伪造泥点、伪造资源完成度、伪造图片或外部浏览器成功提示。
  7. 未识别任务产物不进入“项目版本”,只有正式版本 read model 可以生成版本卡;资源显示名称变化不改变资源身份。
  8. 点击任一资源后只替换中央主视窗,右侧对话与底部 Agent 状态栏保持原位;收起或按 Escape 退出后恢复原搜索、布局模式、滚动位置、选中资源和触发资源卡键盘焦点。
  9. 当前 Supervisor 运行期间 manifest 新增资产、任务状态、预览状态和正式版本后,工作台无需重开项目即可同步更新资源列表、依赖图输入、运行入口和版本卡;旧项目迟到回调不得覆盖当前项目。
  10. 实时 manifest 验收必须捕获真实 App Tauri listener,并让 get_local_game_manifest 在非 Supervisor Agent 的 Runtime / manifest 失效事件后返回新快照;测试不得直接调用 onManifestChange 冒充数据源。读取合并、旧项目迟到响应和项目切换隔离必须分别有回归证据。
  11. 音频或视频控件获得焦点后,同一资源 ID 的 manifest 更新不得把焦点移回详情 region;当前资源被删除后详情关闭、focused / selected ID 清理且焦点落到资源搜索框。显式收起与 Escape 的原卡片焦点和滚动恢复继续成立。

7.2 P1 资源画布布局持久化验收

  1. 同一项目在 dependency 与 type mode 分别读取并协调布局,关闭并重启客户端后恢复各自 sidecar 坐标;历史 manuallyPlaced=true 坐标保持不变。
  2. 新资源进入任一 mode 时获得不重叠默认位置,现存资源坐标保持逐项不变;删除资源后,下一次成功写入不再包含已确认失效的 ID。
  3. 资源卡 Pointer Down / Move / Up / Cancel 支持移动阈值、拖动预览、依赖线同步与结束时一次手动布局 CAS;未超过阈值或点击媒体控制时保留原点击语义。
  4. 两个窗口基于同一 revision 执行资源自动协调写入时最多一个成功;失败方收到 conflict 与最新完整布局,界面不静默覆盖成功方结果。
  5. 布局文件缺失的旧项目可以无迁移打开;损坏、未知 schema、身份冲突、超限和链接文件失败关闭,且原文件不被空布局覆盖。
  6. 布局读写不改变 manifest、游戏项目 mutation revision、Runtime verification、Agent 权限与预览状态。
  7. 1280×720 最小横屏下完全空项目可通过分区展览查看全部栏目,非空项目可通过栏目大纲和滚轮访问全部栏目(包括空栏目),不出现页面级横向或纵向溢出,右侧对话和底部 Agent 状态栏保持可见;1280×800 继续作为默认窗口基线。

7.3 P1 资源依赖关系图验收

  1. dependency 模式在当前栏目中显示两端均属于该栏目且当前可见的合法精确引用,并使用对画布背景至少 3:1 对比度的橙色实线箭头;聚合任务流只参与同类型布局,不绘制灰色虚线或 marker。type 模式没有图层或连线。
  2. 精确引用只接受唯一有效的外部资源 ID 映射,删除或不存在的资源不产生幽灵连线。
  3. 多资源任务依赖按资源类型拆分后只形成布局超边,以 O(S+T) 成员关系参与聚类,不产生 S×T 邻接、SVG 主线或端点分支;跨分类精确引用不参与布局聚类,也不在分栏画布中显示。
  4. 资源引用环和无资源产物参与的任务环都可被有限遍历识别,界面不死循环。
  5. 搜索触发端点过滤;资源点击不改变上下游卡片或任何连线的视觉状态,资源卡指针移动不更新线段,点击与中央聚焦行为不回归。
  6. 切换布局模式或项目后旧 SVG、ResizeObserver 与窗口监听全部清理;图层从不写入 layout sidecar、manifest 或其它持久化。
  7. 4096 资源链式 fixture 继续验证拓扑、聚合复杂度和自动布局性能;拖动局部更新只影响当前卡片和依赖线,不重算全图布局。最右侧自环与箭头仍需完整显示。
  8. Rust 图读取延迟时,dependency sidecar 在图进入 ready / failed 前没有读取或写入;首次布局直接使用 Rust 返回的最终 producer 与 dependency depth。Agent DB 有界读取截断时 producer、task flow 与 cyclicTaskIds 失败关闭,精确 manifest 引用及 Rust 返回的合法 dependencyDepths 继续到达布局层。重新打开包含深度 0 / 1 / 2 自动坐标的旧布局时不得降成全 0 或持久化扁平布局;手动位置逐项不变,自动位置按最终拓扑协调且相同结果不增加 revision。
  9. 依赖 SVG 作为装饰层不可聚焦并对辅助技术隐藏;画布通过关联的视觉隐藏文本逐条说明当前可见的橙色精确引用,搜索过滤或模式切换后文本与可见关系同步变化。task-flow 不进入该关系说明。
  10. 精确引用使用橙色实线和可见箭头;dependency 自动卡片之间保留横向 48px、纵向 40px 走线区,相关簇的窄层按本簇最大层高度居中。不同横向层级且卡片间有空间时使用左右端口优先的横线,同列、同深度或横向空间不足时才使用上下端口纵向降级。同行 / 同列直接连线,需要转向时只使用正交线段与最大 10px 小圆角。同一卡片同侧的多条精确引用按稳定边 ID 与对端位置分配不同端口;自引用继续在卡片右侧外绕,箭头端点与卡片保留固定显示间隙。
  11. 当前栏目 SVG 必须位于拥有该栏目 dependency 资源卡的内容平面内,以同一栏目坐标随 viewport 平移和缩放同步移动;滚动 / 缩放不得通过异步 DOM 屏幕测量重新绑定端点。栏目 viewport 裁剪 SVG 与卡片,搜索隐藏精确引用任一端点时整边及对应无障碍说明同时隐藏。

7.4 P1 正式项目版本阶段六验收

  1. manifest 缺少 versions 时旧项目正常打开且不显示伪造版本;存在合法记录时,固定“项目版本”分区按追加顺序显示稳定版本卡。
  2. 根版本、父版本和直接子版本关系在卡片或聚焦态可见;悬空父版本、自引用、重复 ID、非递增修订、倒退时间、重复 slot 和超限数字均失败关闭。
  3. 点击版本卡后,当前 manifest 中仍存在的绑定资产卡被高亮;历史已删除资产只在版本详情保留 ID,不创建幽灵卡,也不把 External Editor resource ID 猜成 manifest asset ID。
  4. 版本聚焦态展示身份、修订、创建原因、父子关系、创建时间和 slot 绑定;“编辑资源”只追加继承源绑定并记录提示词的子版本,不提供原地替换、切换、回滚或运行按钮。
  5. 任意现有 manifest 写入只能保留磁盘版本前缀并追加新记录;存储边界以跨进程专用锁串行覆盖旧状态读取、前缀校验、安装和回读,修改、删除、重排或并发旧快照覆盖已有版本时写入失败。
  6. 版本选择和高亮不写 manifest、布局 sidecar 或 project revisiondependency / type 两种布局都可显示绑定高亮,既有依赖关系 SVG 语义不变。

7.5 资源栏目分页无限画布验收

  1. 完全空项目继续显示四个可见栏目的分区展览;任一可见栏目出现资源后,dependency / type 都切换为固定四栏目分页画布,悬浮 Dock、底部下一页标题和普通 wheel 可访问全部可见栏目,空栏目也可打开空画布;游戏代码栏目和代码卡片不出现。
  2. 每个 projectId + dependency|type + document|art|audio|version 组合保留独立 viewport;隐藏代码资源的历史内部坐标和 sidecar 会话状态不被删除或重写,切换栏目、模式、项目和打开 / 关闭详情后恢复对应可见栏目平移与缩放,窗口 resize、媒体测量和资源 extent 变化不得重置用户 viewport。
  3. 当前栏目允许空白拖动无限平移;Ctrl/Cmd + wheel 以指针为锚点缩放,显式复位按包含负坐标资源在内的完整 bounds 适配内容。非空状态不显示分区高度、分区内部滚动或分区内容倍率操作。
  4. 资源卡超过 5px 阈值后进入拖动,预览和 dependency 线同步移动;成功释放只提交一次 manuallyPlaced=true CAS,取消、移出释放、媒体控制点击和未超过阈值均不写布局。
  5. dependency 引导线消费当前栏目的同类型精确引用,并与卡片共享同一 viewport transform;平移、缩放、拖动预览、搜索和 resize 后端点保持对齐,type 模式不渲染引导线。
  6. 栏目分页、viewport 和资源卡拖动只修改工作台会话状态或资源布局 sidecar,不改 manifest、项目 mutation revision、Runtime verification、Agent 权限和预览状态;图片、SVG、视频、音频、文档、任务产物、Agent 回执、项目版本卡片及非模态详情回归全部通过,游戏代码仅保留内部事实而不进入普通资源画布。

7.6 阶段七完整验收

  1. 对照飞书需求、当前 PRD、技术方案、代码、测试与阶段提交复核资源管理阶段零至阶段六及素材创作阶段;图片、SVG 和视频主体只在资源卡中展示,中央详情以元数据和依赖信息为主,文档正文与按意图读取的音频控件保留。
  2. AppSurface 覆盖资源卡媒体预览、资源聚焦、素材创作无限画布、全类型非破坏性编辑、恢复 modal、右侧对话和底部 Agent 状态栏;视频使用 controlspreload="metadata",读取失败显示安全空态。
  3. 预览调度、布局 scope、CAS、项目切换和 1280×800 无页面溢出均须通过对应定向测试、真实登录门禁和编码/diff 门禁验证。
  4. 根目录全量 Vitest、前后端 typecheck / lint / build、Rust workspace test / check、SpacetimeDB schema、原生壳、内容 / 编码、生产运维与部署门禁全部通过后,阶段七才允许提交。
  5. 本地 .env.env.local、密钥、缓存、日志和构建产物不进入阶段七提交;提交前再次执行编码检查和 git diff --check

7.6 素材创作无限画布阶段一至五最终验收

  1. 网站与 Tauri 实际 import 同一份 @genarrative/image-canvas-core@genarrative/image-canvas-react,客户端没有复制的主站画布目录;viewport、selection、变换、renderer 与 history 算法位于共享层,宿主只保留事件接线与 adapter 副作用。
  2. “新增资源”在当前产品切片中保持禁用;“编辑资源”只接受现有资源。图片 refine 为稳定 sourceAssetId 保存一个持续精修草稿和多个私有 draft-media 候选;只有用户显式“设为最终图”时才安装新的正式 PNG,并保持原 asset ID 不变、事务化更新其 manifest localPath/mediaType。候选图不进入 manifest 或资源总览。其他类型继续只追加派生文件/asset 或子版本。
  3. 草稿 schema、revision、容量、项目身份、OS 锁、CAS、恢复副本和媒体引用符合权威专题;损坏、未知 schema、身份错配和超限均失败关闭。应用重启后必须按 projectId + intent + sourceAssetId + 可恢复/可继续状态 从正式 sidecar 唯一发现原 refine 草稿并保留 draftId、候选图和生成占位,同时生成新 sessionId;零条才允许创建,多条必须进入对账,不得依赖进程内 Map 或按时间猜测。
  4. 正式提交携带 expectedProjectId + expectedRevision + expectedDraftRevision + commitId + idempotencyKey,按事务快照/journal/ledger、文件、manifest/revision、回读、ledger/draft、事件顺序完成;首个快照、全部快照、journal 写入、文件、manifest、revision、验证和 ledger 各崩溃阶段均有确定结果,未发布快照残留只在证明正式文件、manifest 与 revision 均未变化时清理。
  5. 保存成功后不刷新、不重开项目即可进入 manifest 投影、依赖图、dependency/type 布局和允许时的选中定位;切项目、切中央状态、改选择或改搜索后的迟到结果不得抢焦点。
  6. 搜索/筛选隐藏新资源时保留条件,明确提示“新资源已保存,当前筛选条件下不可见”,只通过显式动作清除条件并定位。
  7. 现有资源编辑、生成、保存、取消、失败和恢复必须覆盖权威专题 §13 中与当前非破坏性编辑切片对应的验收矩阵;只完成画布 UI 或只完成本地写文件都不能算正式闭环。
  8. 自动定位必须分别证明资源已投影、dependency/type 两份布局都 settled 且存在目标位置、目标卡 DOM 已提交;搜索隐藏走显式清除/定位,任何 commit 最多自动聚焦一次。
  9. 普通素材画布生成账本的服务身份固定为 official-platform-v1 + 官方 origin + ownerUserId,不绑定 Access Token;高级 External v1 账本只绑定显式服务 origin,不绑定 Developer API Key。两种模式的 accepted/running 都只恢复原 GETprepared 只可精确重放冻结的原 POST、原正文和原幂等键。普通模式退出或换号后提升账号 generation,中止并脱离旧请求;旧账号账本在新账号下零网络、零安装,只有重新登录同一 owner 后才可恢复。不能通过更换 Token、Key、URL、请求正文或 operationId 绕过该隔离。
  10. 资源编辑恢复面板必须为独立 modal,展示后端权威队列的全部 operation。用户可继续任意可恢复项;remote-failed 只允许显式移出活动队列,并保留私有账本审计;reconciliation-required 只读展示对账。读取失败必须提供重试,不得伪装空队列;操作后必须重读后端。
  11. remote-failed 已是远端明确终态,重启后不再 POST、不再轮询、不再扣费;archived 仅表示用户已将它移出活动恢复队列,不等于 committedresult-unknown、鉴权临时失败和 reconciliation-required 均不允许归档或重新生成。
  12. 派生资产提交必须通过 durable asset transaction journal 串起最终文件、manifest 和 project revision。任一崩溃阶段恢复后只有一份派生文件、一条 manifest assetrevision 精确推进一次;manifest 已写而 revision 未写时只前向补 revision,无法证明的组合进入人工对账。journal 已证明目标 asset、媒体和 target revision 写入后,即使后续合法提交继续推进 manifest/revision,也应按目标 asset 精确身份与 currentRevision >= targetRevision 补齐 ledger/draft,不得要求整个 manifest 永远等于历史 after 快照。durable committed 后遗留的 staging 只有在 staging/正式媒体摘要一致,且 manifest 中按 asset ID 或路径唯一命中并与 journal asset 精确相等时才尽力删除;删除失败不降级已提交结果,身份或媒体漂移则保留 staging 并进入对账。
  13. generation progress、草稿保存队列、生成/提交回包与延迟 loadDraft 必须共用单调 revision 门禁,低 revision 不得覆盖已落地的新草稿。Shift 指针与键盘选择必须与共享 core 一致;单选自身 Shift 不能清空选择,已选多图层普通指针拖动应保持并同步移动选择集。零位移不得产生 undo、documentVersion 或草稿保存。
  14. 失败 UI 必须按 generation / draft-save / asset-commit / recovery / cancellation 五类 operation 显示可访问名称与安全动作。生成是任务级状态:排队、运行、失败和对账不得用全屏遮罩终结画布;失败占位保留原参数并允许重新修改。草稿、CAS、最终图提交、恢复和取消故障不得出现会发起新生成的按钮。真实写入和恢复阶段仍由 handler、revision 与锁负责门禁,视觉 disabled、旧闭包或遮罩不能充当业务门禁。
  15. 派生子版本 journal 必须冻结 project revision before/after 身份和目标 after 记录。manifest 已有目标子版本但 journal 缺失时失败关闭;旧 journal 缺少 revision 身份且当前 revision 已推进、无法证明是同一事务写入时进入人工对账,不得把现状猜测为已提交。
  16. 文本、SVG 与 Agent 回执编辑必须在调用 Provider 前持久化 request-issuedProvider 成功正文必须在解析、格式校验和 staging 之前原子写入私有 durable handoff,并绑定原 operation、请求指纹和内容摘要。issued 后缺少可信 handoff 只能对账,已有可信 handoff 则只消费原正文,两者都不得再次调用 Provider。普通模式首次 401 只允许当前账号 generation 的单飞 refresh,成功后以更高 generation CAS 安装 Token,并使用原正文、原幂等键重试一次;refresh 失败、换号或再次 401 时保留原 operation,停止网络。403 不触发 refresh。高级 External v1 模式修正 Developer Key 后仍只查询或恢复原 operation。

7.7 主站 UI 对齐验收

  1. packages/image-canvas-react 暴露共享画布动作按钮、工具栏、工具分组和分隔符;主站图片编辑器直接消费这些组件,旧网站组件只允许保留薄适配,不得继续维护另一份按钮可访问性或选中态实现。
  2. 共享样式全部使用 .genarrative-image-canvas* 作用域并消费 --platform-* / --image-canvas-brand-* tokenTauri 不导入主站完整 src/index.css,主站也不复制共享样式回业务 CSS。
  3. 客户端接入完成后,1280×800 下中央画布工具栏保持单行或受控横向收纳,中文动作不得逐字换行;聊天输入、主要保存动作和底部 Agent Dock 始终可见,document/body 不产生页面级溢出。
  4. 主站现有图片编辑器的按钮名称、tool selection、hover/focus/pressed/disabled 行为与工具栏位置不因共享抽取回归;网站账号、钱包、素材库、生成和导出逻辑不下沉共享层。
  5. 客户端生成、保存、取消、恢复、登录失效与余额不足只更换视觉承载,不改变 Host Port 调用、幂等身份、草稿 CAS、manifest/revision、Runtime 审批或钱包刷新语义。
  6. 阶段一、二冻结合同并让主站消费共享 chrome;2026-08-06 的阶段三至五已经完成客户端中央区、Supervisor 和 Agent Dock 的正式换肤、定向测试与 1280×800 验收。独立 Vite 没有登录会话时继续显示真实登录门禁,不为视觉测试增加绕过入口。
  7. 普通工作台和 UI Editor 子路由均不显示工作面外层圆角或区块留白;中央区与右侧 Supervisor 的区域底色可辨识,竖向分隔连续、无错位。
  8. 右侧正式钱包入口在普通工作台和 UI Editor 子路由都始终可见、键盘可达并能打开余额、充值与使用详情;路由切换不得使入口消失或失去交互。
  9. “资源依赖 / 资源类型”以连通分段按钮呈现,点击与键盘操作均只保留一个选中项;使用 Tab 定位和键盘切换时焦点指示清晰、完整,不被容器边界或 overflow 裁切。

8. 非目标

  • 当前不开放“新增资源”产品入口。图片精修候选保持私有且不污染资源总览;“设为最终图”只允许保持原 asset ID、以新正式文件和事务方式切换 manifest 指针,不原地覆写旧文件。其他资源编辑继续追加派生 asset 或子版本。
  • 资源总览不实现通用聚焦工具栏/侧边栏、运行版本切换、版本回滚、运行模块扩展、测试切片、运行态消费版本、数值参数或泥点归因;资源详情仅为不影响背景画板的非模态卡片。
  • 素材创作不实现高级蒙版/毛发级抠图、图集、角色动画、视频时间线或音频波形级编辑;图片画布提供现役编辑闭环,其他类型使用统一非破坏性派生面板。
  • 资源聚焦、搜索、筛选、dependency/type mode 与分区滚动/倍率均为当前会话态;打开详情不得改变这些状态。素材创作 viewport、候选图层、generation 占位和最后最终图提交投影使用独立草稿 schema,不能混用资源总览 sidecar。
  • 不修改 SpacetimeDB schema。
  • 不开放普通用户 Agent.md/Skill。
  • 不自动确认 Agent 动作,不自动触发可能扣费的生成。
  • 不把当前项目工作台推广为其它玩法的默认创作模式。