融合最新主分支并保留账号隔离修复

保留 Direct v4 显式重生成与一等切片资源能力
融合账号主体绑定、会话租约和结果未知对账语义
禁止审计成功未知后回滚现场或重复生成
合并 CharacterAnimation、旧资源下载和当前绑定解析
同步共享文档中的两组现役架构约束
This commit is contained in:
2026-08-24 01:46:51 +08:00
42 changed files with 9221 additions and 516 deletions
@@ -108,6 +108,9 @@
- 第一批共享 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` 默认窗口与既有基线验收;更窄浏览器样式只负责不崩溃和开发兼容,不改成移动端创作工作台。
- 普通用户界面不默认展示内部错误码或本机绝对路径,也不展示 External Editor Base URL 或 Developer API Key;官方服务地址由客户端构建固定,远端编辑自动使用当前陶泥儿登录态。仅独立 standalone game-chat release 或显式高级自定义模式在隔离配置页维护 External v1 URL/Key,确需诊断的信息进入受控详情或开发模式。
@@ -567,6 +570,9 @@ type ProjectAgentMudPointAttribution = {
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. 非目标
@@ -14374,3 +14374,17 @@
- 账本迁移:资源 canonical 身份从历史 manifest `resourceId` 收口到本地 asset ID 时,旧账本只在 source asset、路径和 SHA-256 一致时可白名单恢复;新请求仍只信任本地 canonical 身份。
- 集成边界:`resource_editor`、素材画布参考准备、`canvas.asset_generate` 的 art-spec 派生和直连只读恢复统一消费当前 principal binding;PR 176 rebase 后必须删除或整合其局部 canonical cache,不能保留第二套账号身份系统。External v1 的项目、素材目录和项目资源创建接口新增可选 `Idempotency-Key` 请求头并同步 OpenAPI;客户端用 binding key 派生稳定值,服务端按 `owner + 接口命名空间 + key` 生成稳定 ID,同键同正文返回原记录、同键异正文冲突。
- 验收:至少覆盖 A 生成到本地后切 B 重登记、B 请求零 A 远端 ID、重启后复用 B、切回 A 复用 A、两个同名本地项目隔离、项目改名不漂移、源 SHA 或 kind 变化重登记、A 在途任务切 B 零网络,以及 sidecar 零凭据和身份篡改失败关闭。
## 2026-08-23 Direct Codex 显式重生成与切片一等资源
- 决策:`taonier_prepare_game_art` 使用 `reuse-or-create | regenerate` 两态合同;旧调用缺省复用,只有用户显式重做或换风格才允许重生成。`regenerate` 只绕过本地完整包复用,不绕过未决 External Editor operation;旧账本 prompt 与本次 prompt 不一致时必须进入结果未知/对账,零新 POST。
- 重生成前置门:`regenerate` 只要求旧规范图和背景图可下载、可解码、来源一致且有可信登记,以便完整恢复两项旧字节和 manifest entry;历史主图集、私有回执、公开清单或 canonical 切片可以缺失。八个严格路径及受管顶层 asset identity 必须按真实状态逐项冻结为 `Present/Some` 或 `Missing/None`,不能把缺失状态伪造成空内容。只有规范图或背景图缺失/无效时才提示先用 `reuse-or-create` 修复基础素材。
- 整包事务:`regenerate` 在任何付费阶段前持久化绑定意图摘要与稳定 `clientTurnId` 的客户端私有 v4 workflow;状态固定为 `resetting / in-progress / compensating / completed`,专用 `direct-codex-art` 跨进程执行锁覆盖整个付费生命周期。每个已安装阶段立即持久化旧字节、旧 manifest entry 与新结果双 CAS 锚点,后续阶段失败时可跨进程重启继续补偿,但不删除已完成阶段账本。`completed` 必须持久化有界且脱敏的完整工具结果,同一 `clientTurnId` 的完成回包丢失只等值重放该结果、零新 POST。新的显式用户回合先以 `completed -> resetting` 持久化目标身份,再清理旧账本并转为 `in-progress`,不删 workflow。只有零阶段账本、零替换锚点的孤立 `in-progress` 空壳允许新回合原子接管;未知版本、旧 v2/v3 及其余冲突全部失败关闭,旧字段不得通过 serde 缺省静默升级。
- 恢复入口:通用恢复扫描与 Direct 回合启动前置恢复都必须发现 `resetting`、`compensating` 和带替换锚点的 `in-progress`,并在专用执行锁内清阶段、补偿和中性化。补偿恢复旧文件并清除本地 replacement CAS 锚点,但保留已 `prepared / accepted` 的阶段账本、原 `Idempotency-Key / operationId`;同冻结意图续跑必须复用原请求身份,未知账本在文件 mutation 前失败关闭。冻结意图一致时,新进程 invocation 可接管未完成阶段;`completed` 以原始外层 `clientTurnId` 等值回放,不受模型 brief 重采样影响。App 在 Direct 调用前幂等持久化原始 User 消息与稳定回合 ID,Tauri 在成功返回及 `completed` 事件前以同一回合 ID 幂等持久化 assistant 终态,项目重开只续跑最近一条真正未回答的合法原始回合。
- 资源投影:工具返回主包路径、已登记切片路径、安全 `resources` 身份,并分开保留普通 warning 与 slice warning。标准核心图集首次创建和重生成都必须严格提交恰好四张 canonical 切片;alpha、可见像素、规范像素唯一、Canvas resource/asset identity 唯一任一不满足即失败。旧项目补登记与已有完整登记都必须由客户端私有回执交叉验证,不能把可编辑公开清单或顶层 manifest 中的自述身份单独升级为权威源;部分登记要么按私有回执事务补全,要么明确 warning。规范图只作 reference,不再计为运行态平台素材。
- 隐私投影:成功结果中的普通 warning 与 slice warning 也必须逐条经过宿主路径、凭据、URL 脱敏及长度限制,不能只保护错误分支。
- 权限边界:开放的是 `regenerate / registered resources / playtest` 等产品语义,不是原始最高权限。`regenerate` 只由当前请求最新一条原始 User 消息授权并绑定客户端稳定 `clientTurnId`;模型参数、MCP 自动批准和缺失 clientTurnId 都失败关闭。授权输入先对完整原文做 Unicode NFKC 与撇号规范化,随后整串必须完整匹配审核过的独立立即执行指令,只允许句号/感叹号收尾;不得剥离引号、方括号或代码片段,动作前后也不得携带 brief、条件、否定、选择、确认、费用、延迟或其它文本。复杂风格需求先单独描述,再由下一条独立确认消息授权,不能用开放式 deny 词表推断付费同意。同一进程重复水合相同 stable turn 时,“回合仍在运行”只作为非终态占用提示,不得以该 turn 的稳定 assistant messageId 持久化并覆盖原执行结果。DirectProject 的 cwd、sandbox writable root 与文件批准根只允许 canonical 且非 symlink/reparse point 的真实 `game/`,canonical 项目根的原生 OS 路径字节和权威 manifest `projectId` 经域标签及独立长度前缀编码后共同绑定连接池与 thread 身份;项目根、`assets/`、`.agent/` 不可写,网络关闭,命令、MCP 扩权和额外权限批准全部拒绝。受控 `agc_tools` 只在客户端内部从同一真实 `game/` cwd 反查已校验的 canonical 项目根,不把项目根加入 Codex writable roots。Codex 不获得任意 Tauri invoke、Token/Key/Cookie;`resources` 也只投影稳定身份与相对路径,不返回 prompt、provider route、URL 或绝对路径。
- 验收边界:程序证明切片真实 alpha、可见像素、内容唯一、稳定身份和实际渲染;背景语义、无缝地面、实体含义与绘制尺寸继续由工具图片和双视口试玩验收,不把 prompt 描述外推为视觉事实。game-chat 的有效旧包语义替换仍是独立 replace route,不能复用 Direct 开关或伪装为 missing。
- Direct 恢复 claim:同一 App 实例重复水合相同 stable turn 并收到“仍在运行”时,必须释放该 `projectPath + clientTurnId` 的恢复 claim,且不得写稳定 assistant 终态。后续显式刷新对话可按原身份重新读取或续跑;不新增无界自动重试。
- 严格图集崩溃收口:workflow 在严格图集调用前先持久化 `strictSpritesheetPending` 并冻结底层严格事务覆盖的九项旧合同身份;旧路径可精确冻结为缺失。Provider 完成结果先绑定原 retained stage ledger。恢复在同一项目锁内对账严格事务;只有新九项合同、规范图/背景图替换锚点与 retained spritesheet result 三者一致才补写 `completed`,旧九项合同才允许补偿。旧合同判定、写 `compensating`、恢复两项素材与登记、回读和清锚点必须在同一项目锁内,重启已有 `compensating` 也重新判定;第三种混合、漂移或 foreign result 状态进入 reconciliation。不能在主图集与四切片已整体提交后仍按两文件 rollback 制造混合包;若中断前阶段告警尚未进入 durable completed result,恢复结果追加“原阶段告警无法完整重放”的明确 warning,不静默清空。
- Direct 对话恢复从新到旧扫描全部合法 User 回合,遇到较新已回答回合继续向前,不得丢失更早未回答回合。成功返回时 Rust 已先持久化 assistant,前端冗余 append 失败也不得重跑 Provider;普通错误终态的显式 append 失败后,恢复 claim 必须保持到 React fallback writer 对同一稳定 assistant messageId 的写入明确成功或失败,不能在 writer 尚在途时按旧 `/history` 快照重跑。fallback 成功后释放 claim;fallback 失败时跳过该 writer 的无界迟到重试并释放 claim,后续显式 `/history` 才可复用原稳定 `clientTurnId`。终态收敛后删除 claim,避免长会话无界增长。
@@ -4857,3 +4857,14 @@
- Runner 跨 GUI 陷阱:WebView 的 `authGeneration` 会随 GUI 进程重启从较低值重新开始,但 busy Runner 可能仍持有旧 GUI 的高 generation。只用 generation CAS 会把新账号安装误判为过期;只把 OS owner 锁当作授权,或保留独立 `platform.session.install/clear` 入口,又会让 Runner 在单次 IPC 丢失后继续使用旧账号。Runner 协议 v7 由 owner 锁创建随机 epoch,每次会话变更先推进 durable revision claim,并且只允许与 claim 完全匹配的 `runner.attach_gui_owner` 安装会话。Runner 要持续比对 claim,失配立即清空平台会话并拒绝 Runtime 请求;GUI 同步失败还要隔离或停止旧 Runner,不能只向前端报错。
- 验证:用真实平台会话 fixture 覆盖 A→B→重启→A,逐个断言 B 的 URL、请求体和稳定引用中没有 A 的 project/resource/object ID;另测同名 localProjectId 隔离、改名不漂移、源摘要变化、非 refine 参考、视频 committed objectKey、art-spec 派生以及在途 operation 切号零网络。Runner 回归还要覆盖高 generation 旧 epoch 被低 generation 新 epoch 正确替换、迟到旧 epoch/revision attach 失败关闭、claim 改写或同步失败后旧 Runner 零 Runtime 请求。Developer Key fixture 不能替代平台账号隔离证据。
- 关联:`apps/ai-game-creator-shell/src-tauri/src/project/external_editor_bindings.rs`、`project/resource_editor.rs`、`project/asset_canvas/generation.rs`、`agent/generation/canvas_generation.rs`、`agent/direct_runtime.rs`。
## Direct 美术工具不能把“包存在”当成“本次已生成”(2026-08-23)
- 现象:用户明确要求重做美术或切换游戏主题,工具仍立即返回 `assets/art-spec.png`、`assets/direct-game-background.png`、`assets/art-spritesheet.png`;新需求没有 Provider operation,游戏继续使用旧图。切片虽然已经落盘,也可能不出现在资源管理或工具结果中。
- 原因:旧 Direct 工具只有 `brief`,完整包校验成功后无条件短路;固定阶段账本恢复又未比较本次生成 prompt。切片只写文件和切片清单,未作为顶层 manifest asset 投影;工具桥只返回三条主路径并丢失切片与 warning。
- 处理:显式重做使用 `mode=regenerate`,普通请求使用 `reuse-or-create`。重生成必须由当前最新 User 消息明确授权并绑定客户端稳定 `clientTurnId`。授权先对完整原文做 Unicode NFKC 与撇号规范化,随后整串必须完整匹配审核过的独立立即执行指令,只允许句号/感叹号收尾;不得剥离引号、方括号或代码片段,动作前后也不得携带 brief、条件、否定、选择、确认、费用、延迟或其它文本。风格需求先单独描述,再由下一条独立“请重新生成美术”消息确认;不要靠扩充 deny 同义词推断付费同意。同一调用完成回包丢失只从 `completed` 持久结果等值重放,不能因重试再次扣费。App 必须在 Direct 调用前落盘原始 User 消息和回合 ID,Tauri 必须在成功返回前幂等落盘同 ID assistant 终态;同进程重复水合若命中“回合仍在运行”,只能显示瞬时占用提示,不得以稳定 assistant messageId 写成终态并抢占原执行的成功回复。恢复扫描与启动前置恢复必须发现 `resetting / compensating / anchored in-progress` 并在专用锁内恢复,重开项目只续跑真正未回答的原身份。整条付费链必须持有专用跨进程执行锁;换新回合时先持久化 `resetting` 再清理旧阶段账本,不得通过删除 workflow 留出无主窗口。崩溃补偿只恢复旧文件并清 replacement CAS 锚点,已 `prepared / accepted` 阶段账本、原 `Idempotency-Key / operationId` 必须保留,同冻结意图续跑复用旧请求;未知账本在文件 mutation 前失败关闭。只有没有任何阶段账本和替换锚点的孤立 workflow 空壳可原子接管;旧 schema 和其余冲突失败关闭。遇到 prompt 或当前 art-spec 身份不一致的未决账本必须保留原 operation 并返回对账错误。Direct app-server 可写边界只限真实 canonical `game/`,canonical 项目根的原生 OS 路径字节与权威 manifest `projectId` 经域标签和独立长度前缀编码后共同绑定连接池和 thread 身份,不得写项目根、`assets/`、`.agent/`,也不得获得网络、命令、MCP 或权限扩权;受控工具如果需要项目级客户端状态,只能从同一真实 `game/` cwd 经相同校验内部反查项目根,不能扩大模型可写根。标准图集首次创建和重生成都要求四张透明、可见、像素及平台身份唯一的 canonical 切片;工具只回传通过私有回执、公开清单、源图和顶层登记交叉验证的 `slicePaths` 与安全 `resources`。部分/opaque/重复/缺回执切片必须告警,不能把公开清单或顶层自述身份当作 Canvas 权威。
- 验收:不要把规范图当运行态素材,也不要用 prompt 证明图片内容。程序门检查透明/可见像素、唯一性、来源、登记和源码/双视口渲染;背景排除实体、无缝地面、管道或角色尺寸等仍需观察返回图与真实试玩截图。Direct 修复不能外推为 game-chat 已支持有效旧包强制替换。
- 同进程恢复补充:命中“同一 stable turn 仍在运行”后除禁止写 assistant 终态外,还必须删除当前 App 实例的恢复 claim。这样原调用随后成功时显式刷新能读取其终态,随后失败时也能按相同 `clientTurnId` 再次续跑;不要靠重载 WebView 清理进程内 claim,也不要用无界定时轮询制造并发调用。
- 严格图集崩溃补充:规范图和背景图的两文件 rollback 不覆盖严格图集事务已经整体修改的 `.agent/manifest.json`、私有回执、公开清单、主图集、四切片和切片清单。必须在严格调用前持久化 pending 及九项旧合同身份;重启恢复先对账底层严格事务,完整新合同直接收口完成,完整旧合同才补偿前两阶段,混合或漂移状态失败关闭。不要在严格提交成功后局部恢复前两张图。
- 部分旧包补充:rollback 的规范图/背景图必须保存旧字节与旧 manifest entry,不能把这两项缺失隐式当成空内容;显式 `regenerate` 因此只在这两项可信可回滚时开放。历史主图集、私有回执、公开清单或 canonical 切片可以缺失,但八个严格路径与受管顶层 asset identity 必须逐项冻结其真实 `Present/Some` 或 `Missing/None` 状态,补偿也必须恢复相同存在性。不要因为旧美术包缺切片而阻断重生成,也不要把本轮新建的严格文件误记成旧文件。
- 对话扫描与 claim 补充:历史中出现 `User A / User B / Assistant B` 时,B 已回答不代表 A 已回答,扫描必须继续寻找 A。成功 Direct 回复在 Rust 返回前已经落盘,前端冗余 append 失败不能据此重跑;普通错误回复的显式落盘失败时,恢复 claim 要保持到 React fallback writer 的同一 messageId append 明确收敛。writer 成功或明确失败后才释放;失败路径要停止该消息的自动迟到重试,再由显式 `/history` 复用原 stable turn。终态后及时删除 claim,避免 Set 无界增长。
@@ -1,5 +1,16 @@
# AI 游戏创作智能体 App 实施计划
## 2026-08-23 AGC 资源生成补齐(视频 / 动画 / 音效 / 背景音乐)
- 统一资源编辑命令新增 `generationMode=create|derive`:`create` 用于无源生成视频、音效和背景音乐,`derive` 保持现有“基于已有资源派生”。视频新建请求不再携带 `referenceVideoSrcs`;音效 / 背景音乐新建使用同款文本生成端点,但提示词前缀改为“生成新音频”。
- 图片资源新增“生成动画”派生入口:复用 `/api/external/v1/editor/character-animations/generations`(账号模式自动映射 `/api/editor/character-animations/generations`),以源图片的稳定 objectKey、真实宽高和固定 `seedance2.0-fast / 720p / same / 32帧 / 4秒` 参数提交;完成后下载 `previewVideoPath` 预览视频并以 `character-animation` 资源类型登记为本地 MP4/WebM 媒体,避免只保存首帧。
- 本地 manifest 资产模型新增 `imageSequenceFrames` 与 `imageSequenceDurationMs`:角色动画完成时把远端 `frames` 与 `durationSeconds` 随账本持久化,恢复或重新提交后仍写回 manifest,前端资源投影同步暴露。
- 资源页顶部新增“生成视频 / 生成音效 / 生成背景音乐”三个入口,图片聚焦态新增“生成动画”按钮;统一资源编辑面板按 `generationMode` 显示“新建媒体资源”或“编辑现有资源”。
- 新建视频 / 音效 / 背景音乐时,先复用 `prepare_external_canvas_generation_context` 创建或匹配同名画板项目与素材库目录,并在生成请求中携带 `projectId / assetFolderId / canvasCompletion`,结果同时进入平台画布 / 素材库与本地 manifest。
- durable 账本新增 `remoteLegacyPublicPath` 字段(旧账本默认缺省),用于角色动画预览视频的换签下载与恢复;资源提交、轮询、下载、manifest 提交和恢复队列继续复用既有资源编辑事务链。
- 资源编辑请求指纹纳入 `generationMode`,同一 `operationId` 换生成模式重试时不再按旧账本模式恢复;旧账本继续通过 legacy 指纹兼容。
- 去背景(`/api/editor/images/background-removals`)仍缺 External v1 契约,不在本次补齐范围;本次只补视频 / 角色动画 / 音效 / 背景音乐。
## 2026-08-19 UI Editor 节点右键菜单
## 2026-08-20 UI Editor 最终预览互斥子节点
@@ -194,7 +205,7 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创
- 模式升级:`agentMode` 扩为 `codex_app_server / codex_cli / provider`,新默认为 `codex_app_server`;V1.51 的一次性 `codex exec` 保留为显式兼容模式,HTTP Provider 保留为非 Responses 配置及故障回退模式。
- 进程与节点:External Runner 按“有效 Agent LLM 凭据/Responses 路由 + `projectId/agentId/sessionId/runId`”隔离长期 `codex app-server --stdio`,即每个权威节点 run 直接持有自己的 Codex CLI 子进程与 ephemeral thread,每次完整权威请求映射 turn。同一节点 turn 串行,节点之间进程级隔离;单节点连接失败不得使其它节点同时失去终态。Codex thread 不写 durable recovery;节点完成、重启、retry、handoff 和 finalization 仍只认 AGC 账本。
- LLM 配置:`apiKind` 始终只接受 `openai_responses`;非空 Key 转换为 app-server model provider,base URL 生效,Key 仅走专用环境变量;空 Key 只桥接用户 Codex `auth.json`,不继承环境 `CODEX_API_KEY`。设置面板在 app-server 模式继续显示并保存 model、effort、stream、全局/逐 Agent Key 与路由配置;`openai_chat / anthropic` 明确提示切 `provider`,不得悄悄忽略。`stream=true` 接入 app-server 文本 delta;`webSearchEnabled=true` 因唯一 ToolHost 边界明确拒绝。
- LLM 配置:`apiKind` 始终只接受 `openai_responses`;非空 Key 转换为 app-server model provider,base URL 生效,Key 仅走专用环境变量;空 Key 只桥接用户 Codex `auth.json`,不继承环境 `CODEX_API_KEY`。设置面板在 app-server 模式继续显示并保存 model、effort、stream、全局/逐 Agent Key 与路由配置;`openai_chat / anthropic` 明确提示切 `provider`,不得悄悄忽略。`stream=true` 接入 app-server 文本 delta;`webSearchEnabled=true` 只允许 DirectProject 经客户端审核的 `agc_web_search` 使用,不得启用 Codex 原生 webSearch 或任意网络。
- 安全与取消:临时 cwd、隔离 `CODEX_HOME` 与 OS HOME、read-only、network off、never approval,并在启动前关闭 web/multi-agent/shell/browser/plugin/image 等原生能力;取消从 turn-start pending 阶段就跟踪且只 interrupt 当前 turn。已发送 turn 后连接断开或终态丢失进入 reconciliation,只关闭当前节点进程且不重放同一 request slot;明确 failed/interrupted 不按 transport 重试。
- 资源与退出:app-server pool 按实际凭据快照/base URL/API kind/CLI 版本和节点 run 身份隔离并做有界 LRU;空 AppData Key 必须读取同一份有界 `auth.json` 字节来生成池指纹并桥接隔离登录态,继承的 `CODEX_API_KEY` 始终移除,node thread 也只淘汰 inactive LRU。Runner 正常、强制和 watchdog 退出都显式关池,Linux child 绑定 parent-death signal,防止强杀 Runner 后遗留带凭据孤儿进程。stdout NDJSON 与 stderr 无换行记录均有硬上限;stderr 原文不写入诊断,只记录固定分类、总字节数、SHA-256 和可取得的退出状态。
- 旧配置迁移:既有 AppData 若没有 `agentMode`,只有全局和逐 Agent 路由均为 `openai_responses` 时迁移到 `codex_app_server`;存在 `openai_chat / anthropic` 时显式保留 `provider`,避免打开项目自动恢复时把所有节点批量写成 `invalid-config`。用户确认端点支持 Responses 后,可在设置中显式切换并保留原 model/base URL/API Key。
@@ -1176,8 +1187,8 @@ game-project/
- 普通项目对话只由一个 project-bound Codex app-server thread 执行。客户端系统提示词只放最小工程合同、当前游戏源码有界快照、项目 prompts 和审核 Skill 索引;不再批量读取项目 `.codex/.agents/.hermes` Skill 正文,也不恢复 Supervisor、专业 Agent 或 harness。
- 首页恢复“做游戏 / 做素材 / 做方案”三个创作类型,默认“做游戏”。该选择与设置页的 Agent Runtime 模式无关;每次首页提交仍只自动创建一个新项目并进入项目工作台。用户正文原样进入项目对话,`game|art|doc` 仅作为受限结构化首轮上下文传给同一 Codex thread,不拼接“初始意图”文案、不产生首页对话、不切换 Provider 或恢复旧 Runtime 编排。
- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。
- DirectProject 只连接客户端内置的 `agc_tools` STDIO MCP,工具固定为审核引用读取、标准陶泥儿美术准备和 desktop/mobile 浏览器试玩。MCP 进程只做协议;真实浏览器和付费 External v1 调用通过随机 loopback 地址回到客户端主进程,因此不复制 GUI 登录态、开发者 Key 或项目路径到模型上下文。三项工具固定自动批准,通用 shell、任意网络、多 Agent、插件和外部 MCP 继续关闭。
- `llm.webSearchEnabled=true` 在 `codex_app_server` 模式下不启用 Codex 原生 webSearch,也不打开浏览器能力;它只把第四项受控工具 `agc_web_search` 加入 DirectProject 的 `agc_tools` 目录。该工具由客户端主进程固定访问 Bing RSS,强制 20 秒超时、禁用代理与重定向、限制查询 400 字符和最多 5 条结果,解析后仅返回去 HTML 的有界标题 / 摘要 / 公网 HTTPS 链接,拒绝 loopback、私网、凭据 URL 和非 HTTPS 结果。搜索摘要按不可信网页内容注入提示词,只能作为资料引用,不能当作用户或系统指令执行;开关关闭时工具不出现在 MCP 目录。
- DirectProject 只连接客户端内置的 `agc_tools` STDIO MCP,基础工具固定为审核引用读取、标准陶泥儿美术准备和 desktop/mobile 浏览器试玩;`webSearchEnabled=true` 时才追加受控联网搜索。MCP 进程只做协议;真实浏览器、付费 External v1 调用和受控搜索通过随机 loopback 地址回到客户端主进程,因此不复制 GUI 登录态、开发者 Key 或项目路径到模型上下文。已登记工具固定自动批准,通用 shell、Codex 原生 webSearch、任意网络、多 Agent、插件和外部 MCP 继续关闭。
- `llm.webSearchEnabled=true` 在 `codex_app_server` 模式下只把 `agc_web_search` 加入 DirectProject 的 `agc_tools` 目录,并作为 app-server 连接池隔离键;关闭时目录与 MCP 环境白名单均不含该能力。客户端主进程只允许固定 Bing RSS 出站请求,禁用代理和重定向,设置 20 秒超时、400 字符查询上限、512 KiB 响应上限和最多 5 条结果;解析后仅向模型返回去 HTML 的有界标题、摘要和公网 HTTPS 链接,拒绝 loopback、私网、带凭据 URL 和非 HTTPS 结果。网页结果始终标记为不可信资料,只能引用,不能作为用户或系统指令执行。
- 陶泥儿生成继续复用既有私有 Key、持久幂等账本、operation 恢复、来源/下载/PNG 解码和 manifest 登记。完整可信图集缺切片可以继续,固定四切片只是推荐路径;凭据失效、来源不明或结果未知时失败关闭,不能自动换 Key 或重新扣费。
- 自定义 LLM API Key 路由只在 DirectHome/DirectProject 经 loopback `/responses` 流式代理转发。代理不注入 Key,只要求请求自带 Bearer,并剥离开发网关错误携带的 `X-Codex-*` ChatGPT 账户额度头,防止隔离 app-server 把 API Provider 误判为余额 0;旧 ToolHost 保持原 Provider 行为。
@@ -1227,3 +1238,19 @@ game-project/
- 统一根 lock 出现 `@tauri-apps/api`、`@tauri-apps/plugin-*` 或 `@openai/codex` 是 AGC workspace 的合法聚合结果,不代表根 H5 或 Desktop 获得这些能力。配置门禁必须按 workspace manifest/lock entry 判断归属。
- npm 默认 hoist。Vite/Vitest 对 `@cubone/react-file-manager` 的已发布 ESM bundle、AGC TypeScript/Tauri CLI 和 Windows `@openai/codex-win32-x64` sidecar 解析必须兼容 workspace 本地与根提升位置,不得硬编码依赖只存在于 `apps/ai-game-creator-shell/node_modules`。
- Windows game-chat release 仍必须核对固定 Codex 文件和 SHA-256 manifest;Linux 根 lock 与 typecheck 通过不能替代 Windows sidecar 打包 smoke。完整安装、锁与 CI 口径见 [`npm workspaces 统一依赖边界`](./【技术方案】npm-workspaces统一依赖边界-2026-08-21.md)。
## 2026-08-23 Direct Codex 美术包显式重生成与切片投影
- `agc_tools.taonier_prepare_game_art` 的请求模式固定为 `reuse-or-create | regenerate`。缺省使用 `reuse-or-create`,完整且可信的本地包继续零付费复用;只有用户显式要求重做、替换或切换视觉风格时使用 `regenerate`,并绕过完整包短路,按规范图、背景图、透明图集顺序生成和原位替换。`regenerate` 的旧包前置门只要求规范图和背景图已经可下载、可解码、来源一致且存在可信 manifest 登记,使两项旧字节与登记可以完整 rollback;历史主图集、私有回执、公开清单或 canonical 切片可以缺失。客户端必须把八个严格路径的实际存在性和摘要,以及其中受管顶层 asset identity,逐项冻结为 `Present/Some` 或 `Missing/None`,不能把缺失状态伪造成空文件或虚假登记。规范图或背景图任一缺失或身份无效时才失败关闭并提示先用 `reuse-or-create` 修复基础素材。
- 显式重生成不放宽 External Editor 幂等与未知态边界。固定阶段已有 `prepared / accepted` 账本时,本次生成 prompt 必须与账本冻结 prompt 一致才可恢复;不一致返回 `platform-generation-result-unknown` 并保留原 `Idempotency-Key / operationId` 对账,禁止把旧结果解释为新意图,也禁止另起付费 POST。
- 整包重生成在首个付费阶段前建立客户端私有 v4 workflow,状态固定为 `resetting / in-progress / compensating / completed`,并同时绑定意图摘要和客户端稳定 `clientTurnId`。专用 `direct-codex-art` 跨进程执行锁覆盖整个付费重生成生命周期,但不持有通用项目写锁等待网络。规范图和背景图替换后立即持久化旧字节、旧 manifest entry 与本轮双 CAS 锚点;任一后续阶段失败时进入 `compensating`,可在进程重启后继续恢复旧文件及旧登记。已成功阶段的生成账本继续保留;`completed` 持久化经脱敏和数量 / 长度限制的完整工具结果,同一 `clientTurnId` 回包丢失时必须等值重放且零新 POST。新的显式用户回合先持久化目标回合所有的 `resetting` workflow,再清理上一轮三阶段账本并转回 `in-progress`,任一崩溃点都不得出现无 workflow 窗口。只有尚无任何阶段账本且无替换锚点的孤立 `in-progress` 空壳允许被新回合原子接管;其余身份冲突、未知版本以及缺少新恢复字段的旧 v2/v3 workflow 均失败关闭,不能用 serde 缺省值把旧状态升级成可执行状态。
- 恢复扫描必须把 `resetting`、`compensating` 和仍带替换锚点的 `in-progress` 识别为可恢复状态,并在 Direct app-server 启动前持有同一专用执行锁完成阶段清理、补偿和中性化。补偿只恢复旧文件并清除本地 replacement CAS 锚点;已 `prepared / accepted` 的阶段账本、原 `Idempotency-Key` 与 `operationId` 必须保留,同冻结意图续跑复用原请求身份,未知账本在文件 mutation 前失败关闭。冻结意图一致但进程 invocation 已变化时允许安全接管本轮;`completed` 则以外层原始 `clientTurnId` 为权威,忽略模型重采样 brief 并等值回放。客户端必须在启动 Direct Codex 前幂等落盘原始 User 消息与稳定回合 ID;最终 assistant 回复必须在 Tauri 成功返回和 `completed` 事件前,以同一稳定回合 ID 幂等写入项目主对话,重启后项目对话只续跑真正未回答的原始回合,不能生成新身份或重复应用已完成代码修改。
- workflow 在调用严格图集事务前必须先持久化 `strictSpritesheetPending`,并冻结严格事务覆盖的九项旧合同身份:`.agent/manifest.json` 中受管 asset identity、客户端私有回执、公开 `assets/manifest.art.json`、主图集、四张 canonical 切片和公开切片清单;旧路径允许按真实状态冻结为缺失。异步 Provider 返回终态后,客户端必须先把脱敏且可恢复的完成结果绑定到原 retained stage ledger,再允许本地严格事务提交。恢复在同一项目写锁内完成底层严格事务对账与 workflow CAS;若九项新合同与当前规范图身份完整一致、规范图/背景图替换锚点属于本轮,且私有回执的 resource/asset/task identity 与本轮 retained spritesheet 完成结果一致,才保留整组新结果并补写 `completed`。若九项仍逐项精确等于冻结的旧合同,严格合同判定、写入 `compensating`、恢复规范图/背景图与登记、回读验证和清除锚点必须全部位于同一项目锁内;`compensating` 重启也必须重新验证旧合同。任一文件存在性、摘要、顶层 asset identity、retained result 或 CAS 处于第三种状态时进入本地 reconciliation,保留 workflow、阶段账本和文件现场,禁止制造新旧混合包或重新付费。恢复若只能证明完整新合同而无法重建中断前尚未持久化的阶段告警,完成结果必须追加明确恢复告警,不能用空 warning 集合伪装为原阶段没有告警。
- 工具完成结果同时返回主包 `assetPaths`、实际成功持久化的 `slicePaths`、安全身份投影 `resources`,并把普通 `warnings` 与 `sliceWarnings` 分开。每张本地切片都以真实 Canvas `resourceId / assetObjectId / taskId` 和源图集 `sourceResourceId` 登记为顶层 manifest asset;同路径替换保留本地 asset ID。严格图集事务继续覆盖主图、四张 canonical 切片、公开切片清单、私有回执和 `.agent/manifest.json`,失败时整组恢复。旧项目缺顶层切片登记时只能由客户端私有回执授权补登记;可编辑的公开切片清单不能单独成为 `.agent` Canvas 身份来源。
- `regenerate` 授权只取当前请求中最新一条原始 `role=User` 消息,并绑定外层稳定 `clientTurnId`;引号或代码中的按钮文案/示例、历史消息、模型自行填写的 `mode`、MCP 自动批准和缺失 clientTurnId 均不能形成付费替换授权。授权判定先对完整原文做 Unicode NFKC 与常见撇号规范化,随后整串必须完整匹配审核过的独立立即执行指令,只允许句号/感叹号收尾;不得剥离引号、方括号或代码片段,动作前后也不得携带 brief、条件、否定、选择、确认、费用、延迟或任意其它文本。复杂风格需求必须先在非付费消息中描述,再由下一条独立“请重新生成美术”确认消息签发授权;不能靠开放式 deny 词表猜测当前付费同意。工具桥只保留授权判定和摘要,不保存或回传用户原文。同一进程重复水合相同 `clientTurnId` 时,“回合仍在运行”只属于瞬时占用状态,前端不得以稳定 assistant messageId 将其写成终态;原执行的成功回复仍由 Tauri 在返回前持久化。DirectProject app-server 的 cwd、sandbox writable root 和文件变更批准根统一收窄到经 canonical 校验且非 symlink/reparse point 的真实 `game/`;canonical 项目根的原生 OS 路径字节与权威 manifest `projectId` 通过域标签和各自长度前缀编码后共同进入 Direct 连接池和 thread 身份,稳定符号链接改指其它项目、同路径重建项目、不同非 UTF-8 路径或内嵌 NUL 的项目 ID 都不能复用旧连接。项目根、`assets/` 与 `.agent/` 不可写,网络关闭,命令执行、MCP 扩权和额外权限申请一律拒绝。受控 `agc_tools` 子进程只能从同一真实 `game/` cwd 经相同权限校验反查 canonical 项目根供客户端内部桥使用,不能把该根加入 Codex writable roots。`resources` 只返回本地 asset/path/kind/media type、Canvas project/resource/asset/task ID 与 reference resource IDs,不返回 prompt、model、provider route、绝对路径、URL、Token、Cookie 或 API Key。
- 成功响应中的 `warnings / sliceWarnings` 与错误响应采用同一脱敏边界:逐条移除宿主绝对路径、凭据与 URL,并设置固定长度上限;非阻断告警不成为绕开错误分支隐私保护的旁路。
- Direct 同进程重复水合若收到“同一 stable turn 仍在运行”,必须释放当前 App 实例的恢复 claim;该结果不落 assistant 终态,后续显式刷新对话可按原 `clientTurnId` 再次读取已落盘回复或续跑,不要求重载整个 WebView,也不启动无界自动轮询。
- 对话恢复从新到旧扫描全部合法 Direct User 回合;较新的 User 已有稳定 assistant 时必须继续寻找更早未回答回合,不能提前结束扫描。普通成功回复或普通错误回复若终态 assistant 持久化失败,同样必须释放当前 App 实例的恢复 claim,使后续显式 `/history` 能以原稳定 `clientTurnId` 重试;claim 只表示当前实例内正在恢复,不能成为磁盘终态的替代品。
- Direct 的运行态素材验收不再把 `assets/art-spec.png` 当作背景、角色、道具或反馈;规范图只作为派生 reference。标准核心图集无论首次创建还是显式重生成,都必须原子取得恰好四张 canonical 独立切片后才算本次生成成功;每张切片必须有真实 alpha、可见像素、唯一规范像素内容及唯一 Canvas `resourceId / assetObjectId`。旧项目只在私有回执与公开清单、当前源图和顶层登记完全一致时投影四条 `slicePaths`;部分、opaque、重复或缺回执状态只返回 warning,不得猜测或伪造衍生素材。
- 机器门只证明 PNG、真实 alpha、非空可见像素、切片像素唯一、稳定平台身份、顶层登记及源码/双视口实际渲染。背景是否混入实体、地面是否无缝、素材语义是否匹配、最终绘制尺寸是否满足玩法仍由 Codex 检查工具图片和 desktop/mobile 试玩截图;prompt 约束本身不算通过证据。
- 本节只修 Direct Codex 工具链。`project-supervisor-game-chat` 对“已有有效包但用户显式要求视觉替换”的 replace route 仍需独立 Goal Contract 与授权设计,不能把语义不兼容伪装为结构缺失,也不在本次变更中放宽。