Merge branch 'master' into fix/perfect_pixel_check
Project CI / Repository checks (pull_request) Failing after 49s
Project CI / Frontend tests (pull_request) Successful in 3m32s
Project CI / Backend tests (pull_request) Successful in 4m25s
Project CI / Native shell tests (pull_request) Failing after 11m39s

This commit is contained in:
2026-08-12 21:38:21 +08:00
21 changed files with 914 additions and 91 deletions
@@ -1,5 +1,14 @@
# 决策记录
## 2026-08-12 Agent 失败原因使用稳定分类贯穿 Runtime 与正式展示面
- 背景:Codex app-server 的 failed turn 已携带 `turn.error.codexErrorInfo`,但适配器曾丢弃该字段并写固定失败句;Runtime、事件 `publicText`、最近任务、game-chat 阶段记录和多个 Agent 卡片又各自用固定文案覆盖已有安全原因。自主构建 final-reply 已形成确定性完成文案时还对任意错误 fallback 成成功,导致鉴权、额度、上下文、策略、sandbox、配置或网络失败可能被伪装为完成。
- 决策:app-server 只消费协议稳定错误分类和 HTTP 状态,不公开 `message / additionalDetails`;Runtime 持久私有诊断继续脱敏,正式 conversation、失败事件 `publicText`、阶段记录、最近任务和所有 Agent 卡片统一从封闭分类派生可行动中文摘要。失败事件只允许后端 `publicText` 进入正式活动详情,缺失时使用固定安全 summary,私有 `detail` 不得展示;旧 Supervisor 与专业 Agent 失败 conversation 也必须经过同一安全映射。`needs-reconciliation` 是停止自动推进并等待人工处置的终态,显示为“待核对”,不得归为普通运行中或普通完成;未知错误保留固定安全兜底。自主构建确定性 final-reply fallback 只允许稳定 `empty-response / deserialize` 回复形状错误,任何鉴权、额度、上下文、策略、sandbox、配置、网络或上游错误都保持失败。
- 安全边界:不得把 Provider 正文、URL/query、API Key、Token、Cookie、本地绝对路径、fingerprint、字符数或 `[redacted ...]` 占位符放入正式 UI、conversation、事件 `publicText` 或阶段记录。前端只消费后端稳定分类或已通过严格门禁的公共摘要,不从自由文本猜测敏感上游错误。
- 未完成恢复项:isolated join 唤醒、isolated child result 发布、manifest terminal projection 和 terminal-unknown reconciliation 在持久化自身失败时仍需要独立 durable marker 与重启扫描协议;这些跨崩溃窗口必须单独设计和验证,不能用 best-effort 事件或日志冒充已恢复。
- 验证方式:覆盖 Codex 分类与敏感诱饵、失败事件公共摘要、最近任务与各正式卡片、game-chat 阶段记录、待核对状态、final-reply fallback 白名单及 malformed 响应完整重试;运行 Rust 定向测试、前端模型/AppSurface 定向测试、Shell typecheck、编码和 diff 门禁。
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`
## 2026-08-10 资源管理评审阻塞项按第二轮正式合同修复
@@ -48,7 +48,7 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创
- Supervisor 持久决策与单主条件美术:game-chat 的关键词、用户是否报告“美术未接入”、占位状态和当前资产探测只形成 `advisoryOnly=true` 的补充上下文,不得直接重置 Graph、预完成美术节点、选择复用/生成分支或继承历史试玩类型。当前根 Run 没有持久化 Supervisor 决策时,scheduler 不启动任何 childSupervisor Provider 只通过 auto-safe 的 `agent.route_manifest` 提交 `game-chat-workflow-decision.v2``intentSummary` 是 Supervisor 自行理解并持久化的用户意图,`strategy=audit-existing-first` 只是固定安全执行策略,两者不得混用。此动作不能审计、生成、委派或替代后续判断,也不能把整体视觉重做解释成整套美术的强制重生成;成功后 Runtime 只启动唯一 `code-prototype` 主 Agent。升级恢复时严格校验 v1 sidecar 的旧 fingerprint,并从完成合同绑定的有效任务恢复 `intentSummary`;旧 `code-director` coverage/route 只作为迁移输入,不作为当前完成证据,必须由同一根 Run 的 `code-prototype` 重新 `asset.list` 后原位替换为单主合同。确定性 `code-prototype` Run 仅兼容已知 canonical task 文本版本,其余 task/binding/root 身份继续失败关闭;升级前已运行的 fixed-graph 美术 child 不再具备任何 mutation 或生图权限。主 Agent 必须以当前正式资产、Canvas 登记、私有图集合同、四张语义切片和 art manifest 判断真实缺口;完整覆盖时直接接入,不得生成或扣费。只有可证实缺失 `art-spec` 或核心 spritesheet 时,主 Agent 才可对相应 `art-director``art-asset-plan` 建立一条 durable 委派;每次最多一个活跃美术 child,child 仅可写 `assets/**`,不得修改 `game/**` 或接入/验收游戏。若两个槽位都缺失,必须先完成 `art-director`,由同一主 Run 认领其 `EvidenceReady` delivery 后,才能委派依赖规范图的 `art-asset-plan`;失败或未就绪 delivery 不得消耗不可重试的图集委派槽位。主 Agent 认领必要回执后继续同一 Run 完成素材接入、原玩法语义校验、`game.static_smoke` 与桌面/移动 `preview.validate`。绝对硬截止对嵌套美术 child 继续核验 `root -> code-prototype -> agent-delegate` 完整身份并保留未知外部生成的 reconciliation 证据。Runtime 只负责校验根/父子身份、当前 revision、路径、Canvas 登记、缺口/路由 fingerprint、写入范围及完成证据;纯“继续”仍走既有正式 continuation 合同,普通美术措辞不得借用更老项目的具体试玩场景。不得以增加 loop 预算、伪造 revision、机械改写 manifest 或重放历史图片 action 代替 Supervisor 决策和程序侧审计。
- ready-task 对账取消续跑:未知工具结果仍停在 `needs-reconciliation` 且禁止自动重放;人工核对后显式取消原 child,保留 cancel tombstone,旧 child 和旧父 Run 按真实终态收口。若随后创建同 Session、同 Supervisor source、同有效任务语义的 continuation,新完成合同只对同时具有历史 `failed / needs-reconciliation`、最终 `cancelled` 和 durable tombstone 的 ready-task,把当前 manifest 对应 failed 节点恢复为 pending,并由 scheduler 创建全新 child Run。manifest 的读取、failed 筛选、每任务一次的 child journal 索引、证据重验和写回必须位于同一项目写锁域;较新的无 child 根 Run 只有在 durable journal 精确表明为旧 failed Graph 在进入调度前即失败时才能跨过,scheduler 自身失败必须阻断借用更老 tombstone。普通失败、无 tombstone、不同 source/Session/任务语义或证据冲突均保持失败关闭;不得复活旧 pending action、补造 observation 或把取消任务标成 completed。
- 完成门静态分析预算:Canvas 视觉门必须先做只会提前拒绝的词法预检。经典或模块脚本同时不含大小写精确的 `import``export` 字节序列时,不运行模块依赖语义分析;纯 `export ... from` / `export * from` 仍须进入正式模块图分析。当前脚本不含目标文件名或任一已绑定 DOM 图片元素 ID 时,先低成本解码 `\\xNN``\\uNNNN``\\u{...}`、简单转义和续行;解码后仍无候选才不运行完整 Canvas alias / 函数可达性分析,解码不确定则保守进入 Oxc。存在任一候选时仍执行原 parser、semantic binding、解码后的 computed 属性/StringLiteral 路径、可达 `drawImage`、可见 Canvas、路径大小写和动态 namespace 写入门禁;HTML 中存在某个绑定元素不得使所有无关 JavaScript 单元进入重分析,禁止把词法命中当作通过条件。
- Provider 故障展示:Provider retry 的“是否可重试”继续使用 `upstream-5xx` 等稳定类别判断,但 durable retry record 保留安全的精确 `upstream-<HTTP status>` 身份。等待态必须从真实 record 显示 HTTP 状态、`nextAttempt/maxRetries` 与当前持久退避剩余秒数,例如“Provider 上游返回 HTTP 503,准备自动重试 1/3;预计 8 秒后重试”;不得以动画或前端自增计时伪造 attempt。重试耗尽的 Runtime 私有错误只保存 `kind/httpStatus/fingerprint/chars/retryAttempt/maxRetries/retryState`,前端和持久 conversation 仅在字段顺序、范围、状态一致且无尾随正文时派生“上游服务返回 HTTP 503;自动重试已耗尽(3/3)”;其它错误使用固定安全摘要。Provider 响应正文、URL/query、凭据、本地绝对路径、fingerprint、字符数和 `[redacted ...]` 占位符均不得进入用户可见消息。
- Provider 故障展示:Provider retry 的“是否可重试”继续使用 `upstream-5xx` 等稳定类别判断,但 durable retry record 保留安全的精确 `upstream-<HTTP status>` 身份。等待态必须从真实 record 显示 HTTP 状态、`nextAttempt/maxRetries` 与当前持久退避剩余秒数,例如“Provider 上游返回 HTTP 503,准备自动重试 1/3;预计 8 秒后重试”;不得以动画或前端自增计时伪造 attempt。重试耗尽的 Runtime 私有错误只保存 `kind/httpStatus/fingerprint/chars/retryAttempt/maxRetries/retryState`,前端和持久 conversation 仅在字段顺序、范围、状态一致且无尾随正文时派生“上游服务返回 HTTP 503;自动重试已耗尽(3/3)”`codex_app_server` 收到 failed turn 时必须读取协议 `turn.error.codexErrorInfo`,按上下文超限、会话预算、用量、鉴权、请求、策略、sandbox、会话恢复和连接 / HTTP 状态生成封闭稳定分类;不得丢弃该字段后统一写“turn 执行失败”,也不得把 `message / additionalDetails` 原文公开。自主构建已有本地确定性完成文案时,也只允许 `empty-response / deserialize` 这类回复形状错误使用 fallback;鉴权、额度、上下文、策略、sandbox、配置、网络和上游错误必须保持失败,禁止用完成文案掩盖。正式面、阶段记录、Runtime 活动详情和持久 conversation 从稳定分类派生同一份可行动中文摘要;失败事件活动详情只消费后端 `publicText`,缺失时退回固定安全 summary,禁止公开私有 `detail`。旧 Supervisor 与专业 Agent 失败 conversation 必须在展示时经过相同安全映射。`needs-reconciliation` 是停止自动推进、轮询和活跃计数并等待人工处置的终态,明确显示为待核对,不能显示为普通运行中或已完成;未知分类仍使用固定安全兜底。Provider 响应正文、URL/query、凭据、本地绝对路径、fingerprint、字符数和 `[redacted ...]` 占位符均不得进入用户可见消息。
- 跨轮阶段记录:game-chat 父 run 进入真实 completed / failed / cancelled 终态后,客户端等待唯一 `code-prototype` 主 Run 及其所有必要美术委派都已形成真实终态,再把本轮、主 Agent 进度、是否复用/补齐素材、最新试玩 / 静态检查、最近返工决定和已登记成果图片路径整理成一条 `【Supervisor 阶段记录】` 项目 assistant 消息。父 run 先终态而 child 或 manifest 仍在 hydration 时不得以陈旧快照提前归档,要暂存终态 Runtime 并在状态刷新后重试。页面初始 hydration 若直接读到缺少阶段记录的真实终态 run,也必须补写,但 `idle` 不是可归档终态。每个“项目 + 父 run”最多追加一次,进入现有 `conversation.write` 权限与项目 conversation 持久化链路,下一轮及重载后继续保留。阶段记录不是 Supervisor Runtime 正式回复,不写入 Agent Session、不增加 final assistant 数量,也不逐条复制原始事件或内部正文。
- 图片成果:当前 manifest 新增或恢复已登记的 PNG / JPEG / WebP 资源时,聊天消息流同步显示 Runtime-owned “Supervisor 成果图片”卡,最多展示最新 4 张并随 manifest 原位更新。图片必须通过现有 `read_local_project_image_preview` 读取,只允许当前授权项目中 `assets/` 下的已登记资源,继续执行 `file.read` auto 权限、真实格式、大小、尺寸、普通文件、祖先目录和项目根边界校验;前端只接受返回路径、媒体类型和 `data:` 前缀与请求完全一致的结果。缩略图点击后使用独立模态查看器,支持按钮与滚轮缩放、指针拖拽、双击 / 按钮复位、Esc / 按钮 / 遮罩关闭,移动端占满视口;不得在聊天卡下方追加展开区。图片卡不写入 conversation,不解析 assistant 文本中的任意 Markdown / 绝对路径,也不开放 `.agent` 验收截图读取。
- Run 接管:External Runner 模式下首次提交可能返回“旧 canonical state + 新 `acceptedRunId`”;页面必须以 `acceptedRunId` 作为本轮权威身份,在 state 尚未切换时显示“已投递,正在同步 Agent Runner”,并允许该 run 的 Tauri event 或轮询结果接管。不得把旧 idle state 当作本轮结果、过滤新 run 事件,自动预览授权也必须绑定 `acceptedRunId`
@@ -197,7 +197,7 @@ V1.47 在只读工具边界和 batch v3/v2/v1 恢复终审修复后的最新独
V1.17 计划快照随 `game-creator-runtime-context-bundle.v3` 持久化,v2 在通过原身份、revision 和 verification gate 校验后从当前 Runtime state 补齐计划字段继续恢复;计划元数据本身不推进项目 revision、不改变 verification gate,也不触发项目权限确认。开发 UI 和 CLI 有界展示 revision、说明与完整 8 步;正式用户的 Supervisor 只展示完成数、当前步骤、等待对象、下一步和协作数量的紧凑摘要。恢复、same-run steer 和真实 Provider 的完整验收矩阵以 Runtime V1.17 章节为准;2026-07-16 已在当前 v5 context 上完成正式 `openai_chat / gpt-5.5` 的同 run steer + Runner 强杀恢复专项,门禁状态为 PASS。
2026-07-18 起,正式项目工作台的总控与策划 / 美术 / 程序 Agent 状态统一投影当前 Supervisor 父 run 的真实 Runtime;专业 Agent 只有在 `parentRunId` 精确匹配该父 run 时才可进入当前项目状态列表。普通项目页在 Tauri event 之外必须保留只读轮询,兜底独立 Runner 无法可靠投递 App event 的情况;短暂读取失败时保留最后一份可信快照,不得清空或倒退界面状态。正式面只展示真实运行阶段、计划完成数 / 总数、最近更新时间、失败、待确认与待回答等紧凑状态;专业 Agent 的确认或拒绝必须同时绑定真实 `agentId + runId + actionId``manifest.tasks` 只能在没有匹配 Runtime 时作为回退,不得覆盖真实 Runtime;正式面不展示内部 `currentAction``observation`、工具计划正文、Provider 错误原文、fingerprint 或字符计数transport / timeout / 鉴权 / 限流等失败只映射为可理解的安全文案,也不得根据 manifest 或动画伪造生产中、进度百分比或完成状态。当前父 run 或专业状态集合变化时 Runtime 状态区回到顶部,总控摘要在内部滚动期间保持可见。
2026-07-18 起,正式项目工作台的总控与策划 / 美术 / 程序 Agent 状态统一投影当前 Supervisor 父 run 的真实 Runtime;专业 Agent 只有在 `parentRunId` 精确匹配该父 run 时才可进入当前项目状态列表。普通项目页在 Tauri event 之外必须保留只读轮询,兜底独立 Runner 无法可靠投递 App event 的情况;短暂读取失败时保留最后一份可信快照,不得清空或倒退界面状态。正式面只展示真实运行阶段、计划完成数 / 总数、最近更新时间、失败、待确认与待回答等紧凑状态;专业 Agent 的确认或拒绝必须同时绑定真实 `agentId + runId + actionId``manifest.tasks` 只能在没有匹配 Runtime 时作为回退,不得覆盖真实 Runtime;正式面不展示内部 `currentAction``observation`、工具计划正文、Provider 错误原文、fingerprint 或字符计数transport / timeout / 鉴权 / 限流、Codex 稳定错误分类,以及验证、预期产物、权限策略、预算、恢复对账和持久化等常见 Runtime 失败必须映射为可理解、可行动的安全文案;底部子 Agent 状态卡在失败时直接展示同一安全摘要,不能只写“失败”或“子 Agent 任务失败”。不得根据 manifest 或动画伪造生产中、进度百分比或完成状态。当前父 run 或专业状态集合变化时 Runtime 状态区回到顶部,总控摘要在内部滚动期间保持可见。
2026-07-19 起,当前父 run 下的专业 Agent 进入 `failed` 后,正式工作台必须提供“在当前项目重试”恢复入口,不得要求用户新建项目。重试必须精确核对原 `agentId + runId + parentRunId`,复用原 task、active Session 和父 run 归属,同时生成新的专业 Agent runId;新 run 继承已持久化的上下文和父子绑定,不覆写旧失败 run 的审计事实,也不得把 UI 重试解释为底层 transport 根因已修复。`agent.resume` 默认 `confirm` 不变:自动 retry command 继续执行 auto gate;正式失败卡按钮自身是本次明确确认,使用 deny-only 的 confirmed retry command。按钮必须原卡即时显示“正在提交重试”、受理或安全错误;若 Supervisor 已为同一 delegation 准备合同 repair,则该按钮优先确认既有 repair,避免重复派发。