修复游戏创作工作流与UI图集事务

将固定图片规则降为默认合同并允许Supervisor持久委派扩展UI图集
修复条件Graph路由、终态投影、steer窗口和manifest只读刷新
将UI主图、切片、manifest与Agent DB审计收口为可恢复事务
加固跨平台句柄、journal重放、残留隔离和Agent DB容量门禁
补充工作流、事务恢复、Provider与项目夹具回归
同步技术方案与团队共享决策
This commit is contained in:
2026-08-07 19:27:14 +08:00
parent f113326973
commit 00053cf1d3
22 changed files with 10362 additions and 499 deletions
@@ -1,5 +1,39 @@
# 决策记录
## 2026-08-07 UI 图集固定输出续跑与跨平台整组回滚
- 背景:UI 图集 durable 续跑在主图已经安装后仍会把同一 cohort 当成“初次覆盖”拒绝;进程若中断在 cohort 的 backup / publish 边界,`.previous / .replacement` 没有 UI 专用恢复入口。live rollback 又复用原事务 suffix,在 Windows 已存在 `.previous.<suffix>` 时会因目标存在而无法恢复主图。最后一条 `canvas.asset_generate` 审计追加错误也曾被 UI 分支吞掉,留下已登记但无完整审计的半成功合同。
- 决策:`ui-spritesheet + outputPath` 在项目写锁内扫描与该输出一一对应的 cohort 残留;canonical cohort 存在时,先完整校验同源清单、连续切片、稳定身份、PNG 尺寸和双摘要,再清理至多一组可信残留;canonical 缺失时只允许恰好一组可信 previous 恢复,多组、replacement-only 或任一不可信目录 / 文件失败关闭。恢复和清理还必须匹配项目 manifest 已登记主图的 `resourceId`,并把校验、删除和 no-replace 恢复绑定到同一目录句柄,不能在 pathname 复核后操作可能已被外部进程替换的目录。durable 主图已安装后,只有当前 cohort 与同一次结果的 source、resourceId、清单和全部 PNG 字节完全一致时才按幂等成功继续登记。
- 原子性:UI 首次本地写入前即要求主图具有非空 `resourceId / assetObjectId`、切片非空,且每片具有非空唯一身份、PNG 格式、有效尺寸、内容摘要和规范像素摘要。live rollback 使用新的唯一 rollback suffix 恢复快照,成功后再安全清理原事务残留;UI 的 `asset.register / asset.update` 与 `canvas.asset_generate` 审计共享同一 `transactionId`。后续环节失败时外层事务恢复主图、cohort 和项目资产登记,并向 append-only Agent DB 追加使用 terminal reserve 的 `canvas.asset_generate.rollback` 终态补偿;本地恢复或补偿审计失败必须进入 reconciliation。
- durable journal:事务先在同一锚定 `.agent/runtime` parent 下创建 `.preparing`,完整冻结旧主图 / manifest、目标 manifest、asset audit 和 canvas audit 后,以 no-replace 原子发布为 active。已有 journal 不能信任自身派生字段:恢复时重新计算目标登记、assetId、recordType、两条审计、旧快照摘要和存在性,并按 prepared / committed / rollback-requested / rolled-back 状态验证精确允许 child 集合;未知 child、内部矛盾、active / preparing 并存或终态组合冲突全部进入 reconciliation。committed 后的清理中断只继续清理并做 terminal replay,不重新安装或追加 `asset.update`。
- 句柄与残留:previous cohort 的已验证目录句柄跨 publish 错误、rollback 和 cleanup 保留;目录 residue 先退休为事务私有名称再删除,文件型 previous / replacement / discard 先通过 retained parent 做 no-replace 隔离并复核冻结字节,再清理 retired 叶子。Windows 的目录创建、child 读写、rename、CAS 与删除都逐级使用相对 retained handle,避免回到绝对 pathname。
- Agent DB:终态精确审计在 append lock 内运行;先修复可确认的 torn tail,再对全文件执行物理字节和记录数上限并做精确记录匹配。32 MiB 尾窗只适用于普通有界读取,不能作为 committed / rolled-back 的 durable 证明。
- 验证:定向 Rust 回归覆盖 Windows destination-exists 模拟、单组 previous 恢复、已发布 canonical 清理残留、文件删除竞态、retired residue、未知 journal child、preparing 部分创建、五个 rollback 崩溃阶段、未登记 / 他源身份拒绝、父目录 pathname 替换、多组 / 损坏残留拒绝、已安装同源 cohort 续跑、首次身份与切片元数据拒绝、成功审计同事务、最终审计失败后的整组回滚补偿,以及 Agent DB 超尾窗、torn tail 和物理容量门禁。
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。
## 2026-08-06 额外 UI 图集主图、切片 cohort 与资产登记整组提交
- 背景:额外 UI 图集的主图曾先于切片安装和登记;cohort 发布失败又被降级为 `sliceWarning`,会把新主图与旧切片留在同一项目。repair 只核对清单 schema/source,也无法证明旧 cohort 真正属于当前已登记主图。
- 决策:`ui-spritesheet` 的主图、与该主图一一对应的切片 cohort 和项目 manifest 资产登记作为一个外层事务。UI 切片写入失败不再降级告警;切片发布、资产登记或后续审计失败时整组恢复旧主图、旧 cohort 与旧登记。repair 前必须证明旧清单 `sourceResourceId` 等于当前 Canvas 主图登记,`slices` 非空、路径连续且身份唯一,并逐文件核对普通文件类型、尺寸、内容摘要和规范像素摘要。
- 路径边界:额外 UI 图集输出继续允许精确委派的独立 PNG,但不得覆盖 `assets/art-spec.png`、`assets/ui-prototype.png`、`assets/art-spritesheet.png` 或核心/UI 派生切片目录。Runtime 从项目 manifest 枚举每一张已登记 `ui-spritesheet`,推导其专属切片目录,并在请求前与 durable 结果提交前对输出路径执行 ASCII 大小写不敏感的双向祖先 / 后代冲突检查,避免额外主图通过任意文件名的派生目录覆盖既有 cohort。
- 验证:定向 Rust 回归覆盖外层资产登记失败后三类状态整组恢复,cohort 发布失败恢复,缩容 repair 清理旧尾部,错误主图身份、空/不连续清单、摘要不符和非普通文件拒绝,以及固定路径的大小写别名拒绝。
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。
## 2026-08-06 待确认账本区分任务上下文路径与真实工具输入
- 背景:Supervisor 任务正文可明确写出当前项目绝对路径;当 Provider 同轮返回两个以上只读动作时,durable action batch 会把原始任务正文复制进每个 pending record。旧校验对整个 record 搜索项目根路径,导致相对路径的 `asset.list / project.search / file.list` 也在批次预检阶段被误报为“工具输入包含项目绝对路径”,根 Run 在第一次实际动作前失败。
- 决策:敏感字段、API Key 与 secret token 继续检查完整 pending record 和任务上下文;项目绝对路径校验只豁免 pending record 中复制的原始 `task` 字段,`plan`、`thinking`、`observations`、`action.reason / action.input` 及其它 pending 字段仍检查。任务正文可以标识当前项目,但工具 reason / input 仍必须使用项目相对路径。Provider batch、恢复、确认与 action fingerprint 合同不变。
- 验证:覆盖“只有原始任务正文包含项目根、其余 pending 字段与工具输入均为相对路径”通过,以及 `plan`、`thinking`、`observations` 或工具 action 自身包含项目绝对路径时继续拒绝;保留全部敏感信息拒绝回归。
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。
## 2026-08-06 图片固定合同作为默认值,Supervisor 可通过 durable 委派扩展 UI 图集槽位
- 背景:`art-asset-plan` 能正确理解 Supervisor 要求的额外运行时 UI 图集,但 `canvas.asset_generate` 仍按 Agent ID 强制改写为 `assets/art-spritesheet.png`,导致语义决策被静态规则替代;直接复用核心图集切片提交还会覆盖玩家、目标、场景和反馈四张玩法切片。
- 决策:三类 canonical 图片合同继续作为默认值且无委派时失败关闭。只有运行中的 Project Supervisor 通过 durable static delivery 委派 `art-asset-plan`,`expectedArtifacts` 同时保留 canonical `assets/art-spritesheet.png` 并精确声明额外 PNG 路径,父子 task、session、run、action 派生 delegationId、source 和 delivery 状态全部闭合时,才允许以 `assetKind=ui-spritesheet` 扩展输出槽位。授权在外部请求前和 durable 结果本地提交前各复核一次;替换仍要求原 delivery 已认领且只有唯一 repair。
- 产物边界:`ui-spritesheet` 复用 External Editor icon-spritesheet、`art-spec` 稳定资源引用、透明 Alpha 与 PNG 校验,但使用独立 UI 组件描述;canonical 主图 `assets/ui-spritesheet.png` 的切片清单保持为 `assets/ui-spritesheet-slices/manifest.json`,其它额外主图使用与主图同目录、由完整主图文件名确定的 `<主图文件名>-slices/manifest.json`。每个主图只拥有自己的切片 cohort;初次生成不得替换既有 cohort,只有已通过 durable repair 授权且旧清单 `source` 精确绑定同一路径时才整体替换。任何 UI cohort 都不得进入 game-chat 核心四切片严格合同或写入 `assets/art-spritesheet-slices/*`。普通专业 Agent 直调、伪造 `delegated-*`、未声明路径、终态父 run 或 canonical 路径非 canonical 参数继续拒绝。
- 验证:正向覆盖 durable Supervisor 委派解析、UI kind/catalog、18 类 UI 组件描述、真实透明图集路由和独立切片 manifest;负向覆盖无委派固定合同、canonical 四切片隔离与父 run 终态撤权,并保留既有 art-spritesheet 确定性路由回归。
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。
## 2026-08-03 资源管理阶段七以完整 CI 与可重复界面合同收口
- 背景:飞书资源管理需求的阶段零至阶段六已经分别完成资源卡禁拖、固定资源投影、中央聚焦、安全文档 / 媒体预览、依赖深度与正式版本只读模型;最后需要统一复核需求边界并用当前主分支完整门禁排除集成回归。
@@ -93,7 +93,11 @@ cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml struc
npm run test -- apps/ai-game-creator-shell/tests/agentRuntimeModel.test.ts apps/ai-game-creator-shell/tests/appSurface.test.ts
```
game-chat 条件快车道仍采用七任务口径,但执行顺序由持久合同控制。父 Run 与全部 child Run 共用 4200 秒软预算和 4500 秒累计硬上限;Supervisor 首轮先调用 `agent.route_manifest`,决策前零 child。`audit-existing-first` 的首波仅为 `design-director + code-director`,已登记但无效的旧派生视觉不得阻断这两项审计启动;code-director 必须先 `asset.list`,读取 Supervisor 已持久化的 authoritative 决策,再提交正式资产覆盖合同。覆盖完整时跳过图片生成,存在缺口时只开放缺口对应 owner,`regenerate-art` 才强制重新开放两个美术 owner;已登记但校验失败的固定资产只允许当前路由绑定的 canonical owner 原位替换。新生成仍按 `art-spec.png -> art-spritesheet.png + 独立切片` 推进,最后才允许 code-prototype 写入或局部修复入口。软预算后只允许使用已登记图集、当前 resourceId 对应切片清单的确定性本地 fallback、`game.static_smoke` 和 `preview.validate`;不得退回普通生图、猜测 atlas 网格或纯代码核心画面。完成门要求活动 Canvas 分别绘制 player、blocks-and-targets、obstacles-and-scene、feedback-effects 四类不同切片;整图 `<img>`、CSS background、完整图集直绘、单个猜测裁切和路径诱饵均失败。对应定向测试至少包括:决策前零 child、旧无效视觉不阻断首波、首波无美术 child、code-director 收到真实持久策略、完整覆盖零生成、仅缺图集只运行 `art-asset-plan`、无效已登记资产由 owner 原位替换、art spec 缺失导致引用合同失效时同时补齐两个槽位、显式重做原位替换两个正式资产、旧 root/fingerprint/缺口或重复路由失败关闭,以及补齐后恢复 code-prototype。
game-chat 条件快车道仍采用七任务口径,但执行顺序由持久合同控制。父 Run 与全部 child Run 共用 4200 秒软预算和 4500 秒累计硬上限;Supervisor 首轮先调用 `agent.route_manifest`,决策前零 child。`audit-existing-first` 的首波仅为 `design-director + code-director`,已登记但无效的旧派生视觉不得阻断这两项审计启动;code-director 必须先 `asset.list`,读取 Supervisor 已持久化的 authoritative 决策,再提交正式资产覆盖合同。`code-director` 的 manifest 任务仍是只读协调合同,但 `agent.route_manifest` 是该角色唯一额外允许的持久路由动作;只读动作门禁不得拒绝它并与完成门形成重复规划死循环,其他只读专业 Agent 仍不得调用。覆盖完整时跳过图片生成,存在缺口时只开放缺口对应 owner,`regenerate-art` 才强制重新开放两个美术 owner;已登记但校验失败的固定资产只允许当前路由绑定的 canonical owner 原位替换。新生成仍按 `art-spec.png -> art-spritesheet.png + 独立切片` 推进,最后才允许 code-prototype 写入或局部修复入口。软预算后只允许使用已登记图集、当前 resourceId 对应切片清单的确定性本地 fallback、`game.static_smoke` 和 `preview.validate`;不得退回普通生图、猜测 atlas 网格或纯代码核心画面。完成门要求活动 Canvas 分别绘制 player、blocks-and-targets、obstacles-and-scene、feedback-effects 四类不同切片;整图 `<img>`、CSS background、完整图集直绘、单个猜测裁切和路径诱饵均失败。对应定向测试至少包括:决策前零 child、旧无效视觉不阻断首波、首波无美术 child、code-director 收到真实持久策略、完整覆盖零生成、仅缺图集只运行 `art-asset-plan`、无效已登记资产由 owner 原位替换、art spec 缺失导致引用合同失效时同时补齐两个槽位、显式重做原位替换两个正式资产、旧 root/fingerprint/缺口或重复路由失败关闭,以及补齐后恢复 code-prototype。
项目状态刷新必须是纯读:`get_local_game_manifest` 不得通过 `read_manifest_for_project` 无条件回写整份 `.agent/manifest.json`。否则 GUI 在专业任务终态投影前读到的 `running` 快照,可能在 Runtime 已写入 `completed` 后再次覆盖任务状态,导致 scheduler 重复恢复同一终态 child。seed-task 规范化读取也只在内容确实变化时落盘;正式 manifest mutation 继续由持有项目写锁的 Runtime 路径负责。
运行中追加 steer 恰好打断上下文窗口边界时,`continuation_for_game_creator_agent_runtime_steer` 必须把该边界视为新窗口起点,清零窗口轮次与观察指纹后再继续。否则跳过的 checkpoint 会让 `windowCompletedLoops` 跨窗口累加;后续 Provider retry 恢复会把 Runtime 自己写出的 context bundle 判为无效并错误终止同一 Run。
失败续跑还必须覆盖同 Session 同 source 继承、跨 Session / 跨 source 不继承、首次与连续 successor 的 effective task / contract / scheduler 一致性,以及中英文纯继续短语使用同一识别函数。非占位入口的新 `code-prototype` 必须先产生本人 mutation 再 smoke;连续只读 smoke 不得收束。占位 fallback 只允许显式支持的真实玩法模板,俄罗斯方块必须验证棋盘、下落、旋转、锁定和消行语义,未知玩法必须失败关闭。