diff --git a/apps/ai-game-creator-shell/src/view/project-development/index.tsx b/apps/ai-game-creator-shell/src/view/project-development/index.tsx index f13f6d657..4f91d2ecc 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/index.tsx +++ b/apps/ai-game-creator-shell/src/view/project-development/index.tsx @@ -8603,9 +8603,23 @@ export default function ProjectDevelopmentView({ setResourceWorkbenchNotice( `已提交「${input.assetName}」,生成在后台继续,进度见「生成任务」`, ); - // 终局由 `onSettled` 收口(成功落卡 / 失败收口 / 即时失败重开面板),这里只吞掉拒绝, - // 避免出现未处理的 Promise 拒绝。面板由它自己的 `onClose` 同步收起。 - void queue.submit(task).catch(() => undefined); + // 终局由 `onSettled` 收口;如果队列自身在提交前抛出,则没有 settlement 可等, + // 不能让任务卡在“已派发”并静默吞掉 IPC / 调度错误。 + void queue.submit(task).catch((error) => { + const message = `生成任务提交失败:${projectDevelopmentErrorMessage(error)}`; + resourceGenerationPlaceholdersRef.current.failTask( + task.taskId, + message, + ); + if (dispatchedImmediately) { + setResourceGenerationDraft({ + initialKind: input.kind, + kinds: [input.kind], + draftId, + }); + } + setResourceWorkbenchNotice(message); + }); }, [resourceGenerationPlaceholders], ); @@ -8972,9 +8986,29 @@ export default function ProjectDevelopmentView({ setResourceWorkbenchNotice( `已提交「${input.assetName}」,生成在后台继续,进度见「生成任务」`, ); - // 终局由 `onSettled` 收口(成功落卡 / 失败收口 / 即时失败重开面板),这里只吞掉拒绝, - // 避免出现未处理的 Promise 拒绝。 - void queue.submit(task).catch(() => undefined); + // 终局由 `onSettled` 收口;队列自身的提交异常没有 settlement,必须显式收口并保留 + // IPC / 调度正文,否则任务会永远停在“已派发”。 + void queue.submit(task).catch((error) => { + const message = `生成任务提交失败:${projectDevelopmentErrorMessage(error)}`; + resourceGenerationPlaceholdersRef.current.failTask( + task.taskId, + message, + ); + if (dispatchedImmediately) { + setResourceAssetGenerationPanelReopen({ + draftId, + draft: { + content: input.content, + assetName: input.assetName, + aspectRatio: input.aspectRatio, + imageSize: input.imageSize, + }, + error: message, + }); + setResourceAssetGenerationPanel({ action, draftId }); + } + setResourceWorkbenchNotice(message); + }); }, [manifest.assets, resourceGenerationPlaceholders], ); diff --git a/docs/project-memory/shared-memory/pitfalls.md b/docs/project-memory/shared-memory/pitfalls.md index 587969793..0d65fe239 100644 --- a/docs/project-memory/shared-memory/pitfalls.md +++ b/docs/project-memory/shared-memory/pitfalls.md @@ -5,7 +5,7 @@ ## 2026-10-06 AGC 失败终态与 CC/MCP 边界不能吞掉协议、清理和 I/O 错误 - **现象**:DirectProject 的 `turn.completed(status=failed)` 若跨 IPC 丢失 `failure` 载荷,前端会只收口回合而不显示任何说明;Claude Code sidecar 的非 UTF-8 stderr、进程树清理失败、会话表锁损坏,以及 MCP loopback 服务退出、插件能力桥超时、损坏 manifest,会分别被压成空 detail、继续成功取消、伪造 hash projectId 或静默不广告插件。 -- **现行口径**:失败载荷缺失显示明确的协议错误;旧历史里的已知通用失败句明确标成“历史错误事件未记录具体错误正文”,不伪装成当前仍在吞错;CC 清理、stderr 解码、会话锁都保留原始正文;MCP server / capability bridge 失败写入统一应用日志,MCP manifest / journal / 时间 / metadata 读取失败返回具体错误;完成判定在把素材缺失归因于“未引用平台图”前先验证源码、manifest 和已登记图片的 I/O/PNG 错误。切片文件是可选投影,完整 spritesheet 不因无切片而误失败。 +- **现行口径**:失败载荷缺失显示明确的协议错误;旧历史里的已知通用失败句明确标成“历史错误事件未记录具体错误正文”,不伪装成当前仍在吞错;CC 清理、stderr 解码、会话锁都保留原始正文;MCP server / capability bridge 失败写入统一应用日志,MCP manifest / journal / 时间 / metadata 读取失败返回具体错误;完成判定在把素材缺失归因于“未引用平台图”前先验证源码、manifest 和已登记图片的 I/O/PNG 错误;资源生成队列提交异常直接收口失败并恢复可重试草稿。切片文件是可选投影,完整 spritesheet 不因无切片而误失败。 - **验证**:`cargo test agent::claude_code_cli::tests::` 14 passed;`cargo test agent::direct_tools_mcp::tests::` 34 passed;`cargo test agent::direct_runtime::tests::` 92 passed;`npx vitest run tests/directThreadChat.test.ts tests/directTurnFailure.test.ts` 64 passed;另有损坏 manifest 回归用例 1 passed。新失败正文仍经既有脱敏边界处理。 - **关联**:`agent/claude_code_cli.rs`、`agent/direct_tools_mcp.rs`、`agent/direct_runtime/mod.rs`、`agent/thread_manager/dispatch.rs`、`chat/conversation/directThreadChat.ts`。