Files
Genarrative/docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md
T
kdletters 5e16837f3d
Project CI / Repository checks (push) Successful in 1m34s
Project CI / Frontend tests (push) Successful in 3m5s
Project CI / Backend tests (push) Successful in 4m12s
Project CI / Native shell tests (push) Failing after 10m55s
恢复游戏创作 External Editor 配置入口
普通 Launcher、开发工作台和独立 game-chat 统一显示 External Editor 配置。

补齐配置可见性、密码输入和持久化回归测试。

同步配置静态门禁、PRD、技术合同与共享决策。
2026-08-12 18:43:55 +08:00

67 KiB
Raw Blame History

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

更新时间:2026-08-11(资源卡预览、分区布局与依赖聚类,图片素材无限画布及全类型非破坏性资源编辑收口;现有 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
  • 右侧 Supervisor 和底部 Agent 状态栏常驻;窗口不得缩小到破坏该结构。
  • 浏览器窄屏样式只作为开发兼容,不属于本版本产品合同。

3.2 版本与资源替换

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

3.3 资源布局

  • “按依赖”和“按类型”分别保存画布位置。
  • 当前只允许 dependency / type 自动布局与资源卡点击,不提供资源卡手动拖动入口。
  • 切换布局模式后恢复该模式 sidecar 中已有坐标;历史手动坐标只读恢复,不删除、不重置、不迁移。
  • 新资源首次进入某个布局时才执行默认不重叠排版;已有坐标不得被自动排序覆盖。
  • 依赖布局使用资源生成/引用关系;类型布局按资源大类、子类型、尺寸规格排序。
  • 资源分区由资源投影固定,前端交互不能改变分类。
  • 资源卡手动拖动、拖动持久化、拖动性能与冲突后的重新拖动提示全部暂缓,不作为当前产品合同或验收条件。

3.3.1 资源管理三个串行阶段

  1. 阶段一“资源卡本体化”:dependency / type 两种布局共用同一个资源卡组件和预览调度器。图片与安全 SVG 直接显示主体并保留透明棋盘底;视频显示首个可解码画面并可在卡内播放;音频使用清晰的音频视觉和独立播放键;文档显示安全纯文本摘要或稳定类型占位;项目版本不伪造媒体,只显示稳定版本视觉和必要的父子 / 绑定状态。中央详情以元数据、Rust 权威依赖关系和版本信息为主,不重复放大图片、SVG 或视频;文档正文和按用户意图读取的音频控件位于元数据之后。
  2. 阶段二“分区独立缩放”(已完成)同时包含互不替代的分区可视高度和内容倍率。文档、项目版本、美术资源、音乐音效资源的标题栏分别保留高度减小 / 恢复 / 增大,并新增 50%..200% 内容缩放减小 / 百分比复位 / 增大;触摸板捏合、Ctrl/Cmd + wheel 与按钮使用同一倍率模型,普通双指滚动仍只滚动。高度与倍率都以 projectId + layoutMode + category 隔离并只保留在当前会话内存;倍率以分区 viewport 中的手势中心为锚点,逻辑 x / y180×128 本体尺寸和媒体比例不变。最小高度固定容纳标题操作与至少一排卡片,最大高度以中央资源画布当前可用高度为上限。分区保持正常文档流,后续分区由外层资源画布滚动访问,单区内容在缩放后仍只在该区内部滚动。两类表现态都不修改 manifest、game-creator-resource-layout.v1、布局 CAS 或资源身份,不重建媒体控件、不抢走焦点,也不恢复卡片拖动。
  3. 阶段三“依赖布局聚类”(已完成):仅在 dependency 模式中,按固定资源分区对当前 Rust 只读图返回的同类型精确引用边和同类型聚合任务流做弱连通分组;任务流以流节点连接其成员,绝不展开成资源笛卡尔积,但只作为布局邻近提示,不绘制虚线、不进入画布关系说明。dependencyDepth 是唯一横向层级权威;每个相关簇先按“最小深度 -> 最小稳定资源 ID”排序,再在同层进行固定两轮由左至右、由右至左的中位数扫描,平局回退稳定资源 ID;同 SCC/环成员保持连续,环后资源继续按 Rust 深度推进。孤立资源是稳定单例组,紧凑排在相关簇之后,簇之间保持固定留白。跨分类 read model 关系不改变 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 数值微调

  • 数值修改立即写入当前项目的编辑态配置。
  • 当前已拉起的体验预览和测试切片不热更新;必须重新拉起后才能消费新值。
  • 自然语言新增数值项只能映射到预定义参数注册表,不允许生成或修改代码。

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 和审批语义不因入口分流而改变。

  • 项目工作台继续保留左侧平台导航、中央主视窗、右侧 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 工作台独有语义。
  • 客户端正式产品仍只按 1280×800 横屏合同交付;更窄浏览器样式只负责不崩溃和开发兼容,不改成移动端创作工作台。
  • 普通用户界面不默认展示内部错误码或本机绝对路径;External Editor 配置只进入独立“运行时配置”对话框,不与素材画布主要动作并列,确需诊断的信息进入受控详情或开发模式。
  • 素材画布的“素材名称”是用户可编辑的正式输出名称;“资源用途”是 manifest subtype,不向普通用户开放自由文本。新增资源默认“普通游戏美术”,可从普通游戏美术、统一视觉规范、游戏界面原型、核心美术图集四项中选择;精修资源继承源用途且不可改。导出格式继续限定 PNG/JPEG/WebP。工具动作与保存设置分层展示,“保存到项目”在 1280×800 和窄容器中都必须完整可见。

3.8 现有 Godot 项目

  • 首页和项目组复用同一个“打开 Godot 项目”动作,用户选择的目录必须包含普通文件 project.godot
  • 该目录直接成为当前项目根;后续文件读取、修改、命令 cwd、对话、Runtime 和最近项目记录都绑定这个根目录,不复制工程,也不建立 game/assets/memory/exports/ 平行目录。
  • 首次打开只在项目根创建 .agent/ 元数据;已有 .agent/manifest.json 时读取并保留。Godot 源码、场景、资源和项目配置继续使用原目录结构。
  • Godot 项目使用 standard Run Profile,避免套用 Web 原型的 game/index.html、本地 HTTP 预览和自主 Web 游戏完成门;本期不提供 Godot 内嵌运行预览。

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 渲染,并在中央画布内独立滚动;读取失败显示错误空态。
  • 美术: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-11):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' | 'version' | 'art' | 'audio';
    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=falsemanuallyPlaced=true 仅用于兼容历史 sidecar 和保留底层合同;当前界面不会因指针操作新增该值。
  • 同一份布局中 resourceId 必须唯一。持久层允许暂时存在当前资源投影中没有的旧 ID,因为 Agent 文本成果等资源可能晚于 manifest 恢复;前端协调后必须在下一次成功写入中清除已确认失效的坐标。
  • 单份布局最多保存 4096 个位置,序列化文件不得超过 2 MiBresourceId 最多 512 个 Unicode 字符,x / y 取值范围固定为 0..=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 前端布局与协调合同

  • 资源卡是可点击按钮,只负责选择资源并让中央主视窗进入当前唯一资源聚焦状态;不得绑定卡片级 pointerdown / pointermove / pointerup / pointercancel 拖动处理器。
  • 指针移动不得修改卡片 x / y、不得产生拖动预览、不得更新依赖线几何,也不得提交手动布局 CAS。卡片 title、cursor、touch-action 和 class 不得暗示可拖动。
  • dependency 默认布局按 Rust 返回的 dependencyDepth 形成横向层级;同层仅在所属固定分区内按精确引用、聚合 task-flow 的稳定邻接、连通簇和固定两轮中位数扫描确定纵向次序,随后寻找第一个不重叠位置。task-flow 只作为聚合超边参与分组和排序,不能生成资源两两边。dependency 自动布局使用专用 48px 列间走线区和 40px 行间走线区;相关簇以本簇最大层行数为高度,资源较少的层在该高度中居中,避免菱形 / 分叉关系一侧极短、另一侧过长。type 默认布局继续使用原有 16px 行列间距,并固定按“资源子类型 -> 媒体类型 -> 名称 -> 资源 ID”稳定排序。布局模型的 subtype 必填:manifest 资产使用 asset.kind,任务产物、导入附件与 Agent 文本成果分别使用稳定的 task-artifactattachmentagent-result,不得以缺失值或显示文案兜底;资源协调签名必须包含 subtype。卡片尺寸、间距和 0..=1_000_000 坐标上限由前后端同名合同维护。超深依赖仍保留原始 dependencyDepth 业务真相,但显示坐标在上限列确定性饱和并纵向避让;自动布局在 IPC 前必须保证全部 x / y 合法,不能向 Tauri 永久重放必然失败的坐标。
  • type 模式资源集合变化时保留全部仍存在的坐标,只为新 ID 计算默认位置,并删除已确认失效的旧 ID。dependency 模式只永久保留 manuallyPlaced=true 的历史坐标;manuallyPlaced=false 属于可派生自动位置,在 Rust 关系图首次就绪、dependencyDepth 或资源拓扑身份签名(精确引用端点和聚合 task-flow 成员)变化后按最终拓扑确定性重算。签名以稳定资源 ID 的规范端点 / 成员序列生成固定大小摘要,不使用显示名称或浏览器测量值;自动重算不得移动手动坐标,协调结果与持久布局逐项一致时不得产生 CAS 写入。
  • 搜索或筛选只隐藏卡片,不删除、压缩或重排其坐标;清空搜索后恢复原位置。
  • 窗口尺寸变化只改变可视范围和分区滚动边界,不回写或裁切持久坐标。当前客户端继续以 1280×800 横屏合同验收。
  • 分区高度和内容倍率都不属于逻辑布局几何。资源卡始终使用原 x / y180×128 逻辑尺寸;内容 plane 只在显示层按 50%..200% 变换,并用同比例 frame 形成真实滚动范围。标题栏后的分区 viewport 使用内部滚动暴露缩放后的卡片,整个分区继续参与外层正常文档流。触摸板捏合、Ctrl/Cmd + wheel 与缩放按钮共享倍率状态,普通 wheel 不缩放;Ctrl/Cmd + wheel 必须由可取消的原生 { passive: false } 监听处理并真实取消 WebView 默认缩放。搜索、项目或 mode 切换均不得把倍率写回布局。分区内部滚动按 projectId + mode + category 隔离,外层资源画布按 projectId + mode 隔离,二者在详情开关、模式与项目切换后分别恢复。
  • 打开项目、切换 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 二维拖动、移动阈值、拖动态 class、乐观手动坐标与结束时单次 CAS 提交暂缓。
  • 手动意图折叠、冲突后丢弃旧手动坐标、重新拖动提示和 4096 卡片拖动帧预算暂缓,不进入当前验收。
  • 已有 Hook 手动意图、命令式 SVG preview、sidecar 字段和 Rust 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。每个固定分区在自己的 .game-resource-plane 内持有一个 SVG,SVG 与卡片直接消费同一逻辑坐标、卡片尺寸、CSS scale 和 viewport scroll;端点主路径不得再通过 getBoundingClientRect 拼接全局屏幕坐标。SVG 位于资源卡底层并设置 pointer-events: none,不得引入 D3、React Flow 等图表库,也不得阻断卡片点击。
  • asset-reference 表示精确资源引用;只有两端属于同一固定资源分类时才进入前端布局邻接、无障碍关系说明和 SVG,使用明亮橙色实线与实心箭头。跨分类引用仍可存在于 Rust read model,但资源管理画布不得绘线、不得以它形成布局簇或边界偏置。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 分区最多构造一个 ResizeObserver,四区总数最多四个;observer 只维护该分区的逻辑 viewport,不测量或重建卡片屏幕端点。dependency section 额外提供至少 64px 右侧视觉 gutter,确保最右侧自环和箭头可完整滚动显示,但不得修改卡片坐标或布局 sidecar。
  • 分区高度、分区内部滚动和窗口 resize 在各分区内通过单一 requestAnimationFrame 调度器合并逻辑 viewport 更新,不得在每个 scroll event 中同步重算。浏览器以分区 viewport 原生裁剪同属该 plane 的 SVG 和卡片,因此线段不能穿过标题栏或泄漏到其它分区;一端可见时绘制入向 / 出向边界继续线,两端都离屏时不渲染。项目 / mode 切换或卸载时必须清理对应 observer、scroll 与 window resize 监听。
  • 阶段五不改变手动位置边界:已有 manuallyPlaced=true 坐标原样保留,资源引用新增或变化只允许重新派生 manuallyPlaced=false 的自动坐标;任务流继续按任务对与资源分区聚合,禁止为了布局分组生成资源笛卡尔积,且不进入 SVG。

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

实现状态(2026-08-10):当前资源投影已收口到固定的“文档 -> 项目版本 -> 美术资源 -> 音乐音效资源”四区。文档接收受支持的 UTF-8 文档/代码和合法 Agent 文本回执;项目版本只接收显式 ProjectVersionResourceSummary read model,未知任务产物不得兜底为版本;美术接收图片、SVG、动画和视频类产物;音频接收 manifest 资产、上传登记资产和已完成任务 artifacts 明确声明的音频产物。无法识别的二进制任务产物和附件不进入资源画布。受控读取、中央聚焦、失败空态与媒体播放不改变 manifest 真相;编辑成功后只追加新的 asset 或版本子记录。

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

type ProjectResourceDescriptor = {
  resourceId: string;
  category: 'document' | 'version' | 'art' | 'audio';
  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-03):正式版本业务真相扩展在本地项目 .agent/manifest.json 的可选 versions 字段中;旧项目字段缺失时等价于空列表,不根据 checkpoint、布局 sidecar、预览记录或 game-creator-project-revision.v1 自动伪造版本。版本数组只允许追加,已有记录不得删除、重排或修改;首轮没有版本创建按钮,也不自动把当前编辑态登记为版本。

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. 资源卡 title、cursor、touch-action 与 class 只表达可点击;Pointer Down / Move / Up / Cancel 不改变坐标、不产生拖动预览、不提交手动布局 CAS,点击仍打开当前资源详情。
  4. 两个窗口基于同一 revision 执行资源自动协调写入时最多一个成功;失败方收到 conflict 与最新完整布局,界面不静默覆盖成功方结果。
  5. 布局文件缺失的旧项目可以无迁移打开;损坏、未知 schema、身份冲突、超限和链接文件失败关闭,且原文件不被空布局覆盖。
  6. 布局读写不改变 manifest、游戏项目 mutation revision、Runtime verification、Agent 权限与预览状态。
  7. 1280×800 最小横屏下全部资源可通过分区滚动访问,不出现页面级横向或纵向溢出,右侧对话和底部 Agent 状态栏保持可见。

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 继续验证拓扑、聚合复杂度和自动布局性能;拖动局部更新与真实 Chromium 拖动帧预算暂缓,不作为当前验收条件。最右侧自环与箭头仍需完整显示。
  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 必须位于拥有相应资源卡的 .game-resource-plane 内,以同一逻辑坐标随原生滚动和 CSS scale 同步移动;滚动 / 缩放不得通过异步 DOM 屏幕测量重新绑定端点。分区 viewport 原生裁剪本区 SVG,不使用四区 viewport 并集裁剪;一端离屏时只显示对应方向、带同语义箭头的边界继续线,不保留指向已裁剪卡片的悬空主路径,两端离屏时隐藏。搜索隐藏精确引用任一端点时整边隐藏。

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. 四个分区均可独立缩小、放大和恢复默认高度;任一分区变化时其它分区高度、资源卡尺寸和媒体比例不变。到达上下限时对应按钮同时具备正确的 disabled 视觉与辅助技术语义。
  2. 高度、倍率和分区内部滚动按 projectId + dependency|type + document|version|art|audio 隔离,外层资源画布位置按 projectId + dependency|type 隔离;切换模式、切换项目和打开 / 关闭资源详情后,分别恢复当前会话中的内外滚动位置,且键盘焦点不被无关重置。
  3. 最小高度可操作标题控制并完整容纳至少一排卡片;最大高度不超过中央资源画布当前可用高度。窗口变小后超界尺寸被永久夹取到新上限,后续放大窗口不自动恢复旧超界值。
  4. 分区放大只在正常文档流中下推后续分区,不使用浮层、绝对定位、负 margin 或 z-index 覆盖。分区内容超出时内部可滚动,外层画布仍可滚动访问其它分区,1280×800 无页面级溢出。
  5. dependency 线在高度、分区内部滚动、外层滚动和窗口 resize 后仍与可见卡片端点对齐;单端卡片被分区 viewport 裁掉时只保留边界继续线,不保留悬空主路径,两端都被裁掉时隐藏,线段不穿过标题栏。滚动与 resize 在每个分区内使用单一 requestAnimationFrame 合帧,每个分区 plane 最多创建一个 ResizeObserver 并在卸载时清理全部监听。
  6. 高度操作不调用 update_local_project_resource_canvas_layout,不改 manifest、不更新 sidecar revision;阶段一的图片 / 视频 / 音频 / 文档 / 版本卡片、单媒体播放与中央详情回归全部通过。

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 素材创作无限画布阶段一至五最终验收

实现状态(2026-08-12):当前产品切片禁用“新增资源”,只从现有资源进入非破坏性编辑。图片进入中央 refine 画布,其他现役类型进入统一派生编辑壳;取消恢复、正式 manifest/revision 实时合并、依赖图重建、dependency/type 双布局协调和三阶段自动定位已经接通。command/event 任意顺序按项目、commit、event 与 revision 去重;低 revision、旧 graph/layout 和失效 focus generation 均不能倒灌。Tauri 远端媒体编辑固定使用 AppData 私有 editorApi.baseUrl/apiKey 访问 /api/external/v1/*,普通 Launcher、开发工作台和独立 game-chat 的“运行时配置”都可编辑这两个字段;不把 Key 传入 WebView、项目事实、账本、日志或普通错误,素材画布工作区自身不提供凭据输入。重启恢复只继续原 operation,不以新请求、新幂等键或新 operationId 替代结果未知的旧任务。

  1. 网站与 Tauri 实际 import 同一份 @genarrative/image-canvas-core@genarrative/image-canvas-react,客户端没有复制的主站画布目录;viewport、selection、变换、renderer 与 history 算法位于共享层,宿主只保留事件接线与 adapter 副作用。
  2. “新增资源”在当前产品切片中保持禁用;“编辑资源”只接受现有资源。图片 refine 保留原资产与原文件、创建新资产,并用规范 referenceResourceIds 登记直接血缘;其他类型同样只追加派生文件/asset 或子版本,不覆盖、删除或重排源记录。
  3. 草稿 schema、revision、容量、项目身份、OS 锁、CAS、恢复副本和媒体引用符合权威专题;损坏、未知 schema、身份错配和超限均失败关闭。应用重启后必须按 projectId + intent + sourceAssetId + active status 从正式 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. Tauri 远端媒体编辑只使用发布 AppData 私有 External v1 配置;后端按 owner 预扣/退款泥点并返回可轮询 operation。凭据失效、余额不足、平台生成配置故障和远端失败必须在画布内可见;生成状态不得因固定高度或 overflow 裁剪而消失,终态后刷新钱包余额。
  10. 素材画布生成账本的服务身份固定为 service-origin-v1,绑定规范化 External base URL 的服务指纹,不绑定 Developer API Key;确认面板只展示去除路径与凭据的服务 origin。无法用当前 Key 验证的升级前 Key-bound 账本在任何网络动作前显示当前服务 origin 并要求用户确认;确认挑战过期、账本变化或 base URL 变化均失败关闭。确认后 accepted/running 只恢复原 GETprepared 只可精确重放冻结的原 POST。全类型资源编辑复用相同显式确认迁移:旧 Key-bound 指纹无法验证时确认前保持零网络动作,确认后已存在 operationId 的任务只 GET 原 operation,尚未受理的冻结请求才可复用原幂等键精确 POST。
  11. 资源编辑恢复面板必须为独立 modal,展示后端权威队列的全部 operation。用户可继续任意可恢复项;remote-failed 只允许显式移出活动队列,并保留私有账本审计;reconciliation-required 只读展示对账。读取失败必须提供重试,不得伪装空队列;操作后必须重读后端。
  12. remote-failed 已是远端明确终态,重启后不再 POST、不再轮询、不再扣费;archived 仅表示用户已将它移出活动恢复队列,不等于 committedresult-unknown、鉴权临时失败和 reconciliation-required 均不允许归档或重新生成。
  13. 派生资产提交必须通过 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 并进入对账。
  14. generation progress、草稿保存队列、生成/提交回包与延迟 loadDraft 必须共用单调 revision 门禁,低 revision 不得覆盖已落地的新草稿。Shift 指针与键盘选择必须与共享 core 一致;单选自身 Shift 不能清空选择,已选多图层普通指针拖动应保持并同步移动选择集。零位移不得产生 undo、documentVersion 或草稿保存。
  15. 失败 UI 必须按 generation / draft-save / asset-commit / recovery / cancellation 五类 operation 显示可访问名称与安全动作。只有生成失败可以保留参数并“返回修改/重新确认”;草稿、CAS、提交、恢复和取消故障不得出现会发起新生成的按钮。任何非 editing 生命周期都必须同时禁用或 inert 背景画布/顶部工具栏,并由生成 handler 再次校验当前状态;modal 遮罩、视觉 disabled 或旧闭包都不能充当业务门禁。
  16. 派生子版本 journal 必须冻结 project revision before/after 身份和目标 after 记录。manifest 已有目标子版本但 journal 缺失时失败关闭;旧 journal 缺少 revision 身份且当前 revision 已推进、无法证明是同一事务写入时进入人工对账,不得把现状猜测为已提交。
  17. 文本、SVG 与 Agent 回执编辑必须在调用 Provider 前持久化 request-issuedProvider 成功正文必须在解析、格式校验和 staging 之前原子写入私有 durable handoff,并绑定原 operation、请求指纹和内容摘要。issued 后缺少可信 handoff 只能对账,已有可信 handoff 则只消费原正文,两者都不得再次调用 Provider。401/403 只表示当前凭据不能继续授权,不能把已受理 operation 改写为永久对账;修正 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 没有登录会话时继续显示真实登录门禁,不为视觉测试增加绕过入口。

8. 非目标

  • 当前不开放“新增资源”产品入口;现有资源只允许非破坏性编辑并追加新文件、asset 或子版本,源记录不覆盖、删除或重排。
  • 资源总览不实现资源卡手动拖动、通用聚焦工具栏/侧边栏、资源直接替换、运行版本切换、版本回滚、运行模块扩展、测试切片、运行态消费版本、数值参数或泥点归因。
  • 素材创作不实现高级蒙版/毛发级抠图、图集、角色动画、视频时间线或音频波形级编辑;图片画布提供现役编辑闭环,其他类型使用统一非破坏性派生面板。
  • 资源聚焦、搜索、筛选、dependency/type mode 与分区滚动/倍率均为当前会话态;素材创作 viewport 和图层状态使用独立草稿 schema,不能混用资源总览 sidecar。
  • 不修改 SpacetimeDB schema。
  • 不开放普通用户 Agent.md/Skill。
  • 不自动确认 Agent 动作,不自动触发可能扣费的生成。
  • 不把当前项目工作台推广为其它玩法的默认创作模式。