Merge branch 'master' into fix/artagent-sub-modal-style
This commit is contained in:
@@ -190,6 +190,15 @@
|
||||
- 验证方式:以当前 run 成功 `preview.validate` revision N 后断言 iframe 自动出现且 server 归 Tauri registry;再完成 revision N+1,断言 server 进程和 loopback origin 不变、iframe 重新加载新内容且所有响应为 `no-store`。Runner registry 单独 running 不得让页面显示预览;相同 / 更低 revision 不得刷新;停止预览后顶部必须显示“预览未启动”;构建产物和安装信息必须为 `0.1.1`。
|
||||
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。
|
||||
|
||||
## 2026-08-03 开放 Issue 115、118、127、128 的修复边界
|
||||
|
||||
- AGC 的 MCP 目录以 server 为隔离单元:可选 server 的连接、tools/list、工具归一化或聚合容量失败只关闭该 server,required server 仍失败关闭;MCP schema 包入原生 action 后只沿 subschema 关键词重定位当前 document 根的 JSON Pointer fragment,`default / const / examples / enum` 等数据值、命名 anchor 与 `$id` resource 内 fragment 保持不变。Anthropic strict 不由 `apiKind` 单独推断:AGC 只对官方 HTTPS endpoint 与 Claude 4.5+ 版本化 model id 显式开启,旧模型、未知别名和兼容网关默认关闭。开启后使用官方支持关键词白名单生成专用传输 schema,剔除不受支持的约束但不修改调用方原 schema;未知关键词、不可解析 / 递归 `$ref` 或请求复杂度超限时保持 non-strict。最后一个工具设置 ephemeral prompt-cache breakpoint;usage 统计把 cache creation / read token 一并计入 prompt 和 total。
|
||||
- Windows 私有 ACL 检查复用 `Get-Item` 对象的 `GetAccessControl()`,避免从 PowerShell 7 启动时继承的模块路径让 Windows PowerShell 5.1 的 `Get-Acl` 加载不兼容模块;静态配置门禁禁止重新引入该命令。
|
||||
- 编辑器持久化的 `prompt` 统一表示规范化用户意图;provider `actual_prompt` 只保留在 resource / asset 审计字段,系统 prompt 不进入跨资源检索字段。角色和图标的透明图、切片继承源用户 prompt;本次只修新写入,不迁移历史记录,不修改 SpacetimeDB schema。
|
||||
- 画布收到生成完成等较新权威快照时,必须把同项目待保存或在途的本地布局重放到新 revision:后端资源与生成终态优先,本地布局编辑优先;后端新增项合入,后端删除项和用户本地删除项均不得复活,合并后立即进入既有串行 CAS 保存队列。
|
||||
- 生成器合并必须把 `status / composerOpen / generatedLayerId / errorMessage / generation timestamps / characterAnimationResult` 视为后端生命周期事实;生成完成快照继续保持 `composerOpen=false`,不得被本地在途快照重新展开。提示词、参数和占位位置等本地布局编辑继续保留。
|
||||
- 同项目权威快照刷新不得无条件选择第一张图层:当前仍有效的单选、多选和生成占位选择保持,已删除的选择过滤,本来未选择时保持空选;只有首次载入或切换到另一项目时才默认选择第一张可用图层。生成完成结果需要用户显式点击后才进入选中态,后台完成回包不能偷走用户当前焦点。
|
||||
|
||||
## 2026-07-30 Provider 503 等待与耗尽状态使用严格字段派生的安全摘要
|
||||
|
||||
- 背景:game-chat 的进度卡只显示“等待 Provider upstream-5xx 瞬态故障退避到期”,没有 HTTP 状态、重试次数或等待时间;重试耗尽后,Runtime 和持久 conversation 又可能直接展示 `fingerprint/chars` 或 `<absolute-path> [redacted sensitive context]`,用户既无法判断是否在恢复,也看不到可操作的失败原因。
|
||||
@@ -5490,8 +5499,8 @@
|
||||
- 复用决策:窗口固定使用 `project-supervisor + autonomous-game-build`,复用 active Session、External Runner、持久 conversation、确认 / 追问链路和共享 `PreviewRegistry`;不新增玩法入口、后端 API、会话库、Runner 或预览服务。原 `supervisor-chat` 继续使用 `standard` profile 并保持纯聊天语义。
|
||||
- Run 身份决策:External Runner 接受新任务后,命令响应中的 canonical `state` 允许暂时仍是上一轮 idle,而 `acceptedRunId` 才是新任务的权威身份。GUI 必须暂存该身份并开启轮询、放行对应 Runtime event,直到新 state 接管后再清除;自动预览授权同样绑定 `acceptedRunId`。忽略该字段会造成任务实际运行但界面永久显示“等待输入”。
|
||||
- 状态决策:页面只聚合当前 Supervisor 父 run 及其直接委派专业 Agent 的事件,稳定去重后默认显示最新 4 条、可展开至 20 条;事件只作状态投影,不写入 conversation。无当前项目的有效 `running` PreviewRegistry 状态时只显示聊天;运行后桌面端显示“游戏 2 / 聊天 1”,移动端上下排列。iframe 只接受当前授权项目的 `http://127.0.0.1:*`,继续复用现有 CSP 和 sandbox 合同,远程 URL、`file://`、手填地址或陈旧 manifest 状态均失败关闭。
|
||||
- 进度证据决策:聊天消息流内增加单条 Runtime-owned “Supervisor 进度播报”,从当前 run 的 manifest 任务图、结构化计划、真实 loop、直接委派 Agent 和持久事件确定性派生,聚合迭代轮次、当前工作、活跃专业 Agent、试玩 / 静态测试、返工、代码修改和截图检查。该卡同一 run 原位更新,不调用模型、不写 conversation、不制造额外 assistant 记录;详情有界并移除绝对路径,不展示 Provider 元数据、指纹或原始内部正文。顶部原始事件列表继续保留以便核验。
|
||||
- 跨轮记录决策:只有当前 game-chat 窗口确实观察过活跃态的父 run,在其终态正式 conversation 刷新完成后才追加一次 `【Supervisor 阶段记录】` 项目 assistant 消息;内容只保留轮次、任务 / 计划完成度、最新测试、最近返工和成果图片路径。记录按“项目 + 父 run”内存幂等,继续经过 `conversation.write` 策略并写入项目 conversation,因此下一轮和重载后仍可见;已终态旧 run 在窗口启动时不回填,避免重复。该项目记录不进入 Supervisor Agent Session,不改变 Runtime 唯一 final assistant 合同。
|
||||
- 进度证据决策:聊天消息流内增加单条 Runtime-owned “Supervisor 进度播报”,从当前 run 的 manifest 任务图、结构化计划、真实 loop、直接委派 Agent 和持久事件确定性派生,聚合迭代轮次、当前工作、活跃专业 Agent、试玩 / 静态测试、返工、代码修改和截图检查。该卡同一 run 原位更新,不调用模型、不写 conversation、不制造额外 assistant 记录;详情有界并移除绝对路径,不展示 Provider 元数据、指纹或原始内部正文。顶部原始事件列表继续保留以便核验。2026-08-01 补充的逐条公开输出是独立的 `eventId + publicText` conversation 消息,不改变该进度卡自身不落盘的约束。
|
||||
- 跨轮记录决策:父 run 进入真实 `completed / failed / cancelled` 终态且 `code-prototype / preview-readiness / preview-playtest` 三个阶段全部终态后,追加一次 `【Supervisor 阶段记录】` 项目 assistant 消息;内容只保留本轮、任务 / 计划完成度、最新测试、最近返工和成果图片路径。Runtime 先终态而 manifest 尚未刷新时暂存候选,manifest 刷新后补写;页面启动时若首个可见快照已是终态,也必须补齐缺失记录,但 `idle` 不得被当作真实终态。记录按“项目 + 父 run”内存幂等,继续经过 `conversation.write` 策略并写入项目 conversation,因此下一轮和重载后仍可见。该项目记录不进入 Supervisor Agent Session,不改变 Runtime 唯一 final assistant 合同。
|
||||
- 图片成果决策:manifest 中已登记的 PNG / JPEG / WebP 项目资源通过既有 `read_local_project_image_preview` 安全读取,并在聊天流中以单张 Runtime-owned “Supervisor 成果图片”卡原位展示,最多 4 张。只接受当前项目 `assets/` 已登记路径及返回身份完全一致的 data URL,不从自然语言或 Markdown 解析任意路径,不读取 `.agent` 验收截图,不写 conversation;切换项目、资源移除、读取失败或解码失败时立即移除图片或显示固定失败状态。缩略图点击进入独立模态查看器,支持 50%–400% 按钮 / 滚轮缩放、指针拖拽、复位和 Esc / 遮罩 / 按钮关闭,移动端全屏,不在聊天消息下方内联展开。
|
||||
- 授权决策:用户成功提交本轮自主生成需求,即授予“当前项目 + 当前 Supervisor 父 run”一次性 `preview.start`;授权只把项目路径与 accepted parent runId 持久化到客户端本地状态,允许 App / WebView 重启恢复,不新增后端接口。首版产物完成后仍经现有权限、项目写锁、审计与 PreviewRegistry 链路启动;成功、显式 deny、非瞬时失败、父 run 在首版完成前终止或切换项目后消费或清除授权。首版完成投影与专业任务写入并发时,`preview.start` 可能暂时命中项目写锁;该错误不得提前标记“已尝试”或清空授权,应在释放锁后重试,最终仍只成功启动一次。项目或 Agent 策略的显式 deny 始终优先,不因页面授权而降级。
|
||||
- 验证方式:定向覆盖 debug / release 入口分流、项目选择和切换隔离、父 run 事件聚合、首版只启动一次、deny 优先、预览停止后隐藏、loopback / sandbox 安全以及桌面 / 移动响应式布局。
|
||||
@@ -5708,7 +5717,7 @@
|
||||
- 背景:旧创作模板退役时误把新版 `/creation`、桌面公共侧边栏和“我的”完整资料页一起缩减;只恢复视觉后,现役 profile client 又经 `rpg-entry` barrel 把旧作品库、旧 runtime request 和展示模型重新带入 Vite 与 TypeScript 图。
|
||||
- 决策:桌面端继续使用原平台公共结构,一级导航固定为 `创作 / 项目 / 我的`;顶栏保留编辑器项目 / 素材搜索、泥点入口和账号胶囊;“我的”全宽保留资料编辑、陶泥号、三项统计、充值、兑换码、社区、反馈、通用设置、API Key 和法律信息。搜索只面向编辑器项目与公开编辑器素材,不恢复旧公开作品搜索。
|
||||
- 依赖边界:公共 dashboard、钱包、充值、兑换码、邀请码、API Key 和设置请求迁入 `services/platform-entry`,公共账单展示迁入现役 profile model。Vite 新增退役模块 graph 门禁,ESLint 对现役源码禁止导入旧目录;目录 watch ignore、Tailwind source、tsconfig include 和 tree-shaking 都不能作为依赖隔离证明。
|
||||
- 路由与响应式边界:`/creation`、`/project`、`/profile` 都是可刷新、可前进 / 后退的稳定路由;桌面端使用侧边栏,移动端必须提供同样 `创作 / 项目 / 我的` 的三项底部 dock,不得因隐藏桌面侧边栏而丢失移动导航。
|
||||
- 路由与响应式边界(2026-08-03 纠正):`/creation`、`/project`、`/profile` 都是稳定路由,但旧模板退役不授权扩大移动端创作范围。桌面端使用 `创作 / 项目 / 我的` 侧边栏;移动端底部 dock 只保留“我的”,直达 `/creation`、`/project`、`/editor/canvas` 或从首页触发项目 / 画布动作时统一显示桌面端提示,不挂载创作主页、项目列表或图片画布。2026-07-18 同批加入的移动端三入口口径无效,不作为产品决策依据。
|
||||
- 公共设置边界:`runtime_setting` 保持原表结构与历史数据,但它是音乐音量和平台主题的现役账号级公共能力,不归入旧玩法数据壳。鉴权后的 `GET/PUT /api/runtime/settings` 必须经 `spacetime-client` 调用 `get_runtime_setting_or_default` / `upsert_runtime_setting_and_return`;保留该路由不构成恢复旧 runtime API 的先例。
|
||||
- 编译门禁:除旧业务目录外,`src/uiAssets.ts`、`src/types.ts`、`src/types/**`、`src/services/runtimeAudioFeedback.ts` 和 `src/services/publicWorkCode.ts` 也是顶层退役 module,必须同时退出 Vite module graph、TypeScript、ESLint 和 Vitest;`/audio/**`、`/chat.png`、`/fusion-pixel.ttf` 及旧 pixel / story-tab / 玩法 CSS 不得进入 dev 服务或生产产物。验收时必须同时检查 `tsc --listFilesOnly`、Vite 依赖图 / 产物和退役资产路径,不能只依赖 tree-shaking。
|
||||
- Rust 产物边界:`module-runtime` 继续承载账号、钱包、公共设置、追踪和 feature gate,但 `CreationEntry*`、旧公开作品、存档、浏览历史与游玩统计 DTO / command / mapper / 规则必须退出实际 rlib;只保留历史表需要的 `RuntimeBrowseHistoryThemeMode`、完整保序的钱包流水来源枚举等持久化 ABI。`check:server-rs-ddd` 必须执行 `check:module-runtime-artifact`,同时验证旧符号和字面量为零、必要 ABI 仍存在,不能以源码存在 `#[cfg(any())]` 或路由未挂载代替产物证明。
|
||||
@@ -5876,9 +5885,10 @@
|
||||
|
||||
## 2026-07-31 game-chat 每条输出入聊天、试玩后收束与平台图集引用
|
||||
|
||||
- 背景:game-chat 的 ready response 之前只作为 transient stream 展示,刷新或事件 / 轮询重放时可能丢失;自主构建完成后仍可能继续进入发布任务;配置 External Editor API 时,原型 HTML 也可能不实际使用平台生成的 Canvas 美术资源。
|
||||
- 决策:game-chat 为每条 Supervisor ready 输出分配由 `runId + requestSlot + responseRevision` 组成的稳定 `runtime-response:*` 消息 ID,并在事件、轮询、StrictMode 和 hydration 中按 ID 幂等固化到聊天框;普通 `supervisor-chat` 不改变。可信 source `project-supervisor-game-chat` 的 seed task 截断在 `preview-playtest`,试玩成功后完成门只验收保留任务、最新 revision、`game.static_smoke` 和 `preview.validate`,不再调度 `publish-strategy` / `publish-package`,GUI / CLI 仍执行完整 DAG。
|
||||
- 美术资源门禁:External Editor API 有效时,`code-prototype` 必须通过 `asset.list` 核对 Canvas 登记的 `assets/art-spritesheet.png`,并在 `game/index.html` 真实引用该文件;manifest、文件或 HTML 引用任一缺失均拒绝完成。确定性 Provider fixture 也必须带该引用,不能用占位内容绕过门禁。
|
||||
- 背景:game-chat 的 ready response 之前只作为 transient stream 展示,专业 Agent 的 `final-reply` 只进入各自私有 conversation,刷新或事件 / 轮询重放时项目聊天可能丢失这些输出;自主构建完成后仍可能继续进入发布任务;配置 External Editor API 时,原型 HTML 也可能不实际使用平台生成的 Canvas 美术资源。
|
||||
- 决策:game-chat 为 Supervisor ready 输出、四阶段专业 Agent `final-reply` 和每条后端批准公开的 Runtime 输出分配稳定消息 ID,并在事件、轮询、StrictMode 和 hydration 中按 ID 幂等固化到项目聊天。专业回复只接受 `art-director / code-prototype / preview-readiness / preview-playtest` 的 `requestKind=final-reply` 且 `status=ready|committed`;`art-asset-plan` 不属于五分钟首版阶段,其回复不进入 game-chat 项目聊天。tool-plan 与流式半成品不进入聊天。Runtime 事件由 Rust 在写事件时生成唯一 `eventId` 和可选 `publicText`,前端只消费这两个字段,不重新解释 `summary / detail`;无公开投影的 legacy、Provider、Runner、tool payload、路径、指纹、哈希和敏感字段不得写 conversation。`append_local_conversation_message` 通过顶层 `messageId` 使用后端幂等追加。普通 `supervisor-chat` 不改变。可信 source `project-supervisor-game-chat` 的 seed task 截断在 `preview-playtest`,试玩成功后完成门只验收保留任务、最新 revision、`game.static_smoke` 和 `preview.validate`,不再调度 `publish-strategy` / `publish-package`,GUI / CLI 仍执行完整 DAG。`agent.schedule_ready` 同样必须按当前父 Run 的持久 source/profile 走 source-aware scheduler,不得回退通用完整 DAG;`task.list` 必须隐藏两个发布节点及其 ready/count 投影,`agent.delegate` 必须根据 root binding 拒绝直接委派这两个节点,所有绑定读取错误均失败关闭。
|
||||
- 单轮语义:Runtime 的 `loopIteration` 是同一父 Run 内的 Provider / 工具循环,不是用户可见的游戏版本轮次;game-chat 的进度卡、当前工作和最新状态统一显示“本轮”,不显示根或专业 Agent 的内部“第 N 轮”,完整 GUI / CLI pre-publish 任务图仍可显示 `x/14`,首版快车道改为四阶段 `x/4`,终态后移除运行中进度卡。`preview-playtest` 与全部完成门满足且非验证屏障清零后,Runtime 以确定性最终回复完成结构化计划并立即结算父 Run,不再把“是否继续”交给下一次 Provider tool-plan。
|
||||
- 美术资源门禁:live10 实测透明 `icon-spritesheet` 的生成和后处理超过 `300` 秒,不能纳入 game-chat 五分钟首版。game-chat 改为由 `art-director` 通过一次平台 `images/generations` 生成并登记 `assets/art-spec.png`,`code-prototype` 必须把它显著用于用户可见的主要背景、玩家和目标;未配置 External Editor API、生成或登记失败、文件缺失、HTML 未引用或可见画面未使用均拒绝完成。普通 GUI / CLI autonomous 继续执行完整 DAG,并以正式透明 `assets/art-spritesheet.png` 及其真实引用作为原有美术硬门。
|
||||
- 验证:`agentRuntimeModel.test.ts` 10 项通过;新增 Rust source allowlist、game-chat parent completion 与 Canvas spritesheet reference 合同测试通过;`cargo fmt --check`、`npm run check:encoding`、`git diff --check` 通过。两项既有 Windows `os error 32` 文件锁竞态仍单独记录,未归因于本次改动。
|
||||
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。
|
||||
|
||||
@@ -5888,3 +5898,40 @@
|
||||
- 决策:预览的业务失败与浏览器基础设施失败分流。基础设施失败按稳定 kind 持久化并立即失败结束当前 run;preview readiness/playtest 的 manifest 完成分别绑定当前 revision smoke 和根合同 browser receipt,read-only 文本交付不能绕过。
|
||||
- 决策:game-chat 的 client-owned Runner 在活动任务期间禁止关闭客户端;关闭前复用既有 durable idle 真相源,避免另建 UI busy 状态。用户明确暂停/取消并达到 idle 后再退出,不能靠重启后自动重放未知 Provider 结果。
|
||||
- 决策:规范 Agent reasoning 默认由角色职责分层,显式 per-Agent patch 优先;配置状态对外展示实际 timing/retry,避免全局文件、per-Agent resolver 与历史 run snapshot 混淆。
|
||||
|
||||
## 2026-08-01 game-chat 首版四阶段快车道与美术硬门
|
||||
|
||||
- 决策:game-chat 首版只投影 `art-director`、`code-prototype`、`preview-readiness`、`preview-playtest` 四个阶段,页面进度显示 `x/4`;四个专业 Agent 的安全 `final-reply` 均逐条进入项目聊天,`art-asset-plan` 不进入进度、阶段记录或 final-reply 投影。完整 GUI / CLI 任务图仍保留原有节点和执行语义,内部 Provider / child loop 不作为用户轮次。
|
||||
- 预算:父 Run 接受请求后以 `240` 秒作为首版软预算;父 Run、所有 child Run、等待、回收和确定性验收共享 `300` 秒累计硬上限。硬上限是从 root `bound_at` 计算的绝对 deadline,必须包住 Provider、图片生成、文件写入、静态检查、`preview.validate` 和 final-reply 的在途等待;超时先强制持久化 `failed` 终态,再清理 pending action、Provider batch、confirmation、recovery 和进程会话,不能留下 `needs-reconciliation` 悬空态。软预算后不再扩展 Provider 规划,只能运行受控 fallback、`game.static_smoke` 和 `preview.validate`;硬上限未形成当前 revision 的通过证据时必须失败关闭,单轮确定性收束也必须复核累计时间,不能在上限后补写 completed。
|
||||
- Provider:首版最多一次 Provider 规划 / 写入请求,禁止同一首版自动传输重试、第二次 tool-plan 或无限 repair。Provider 结束后由 Runtime 按当前 revision 依次执行确定性静态 smoke 与浏览器试玩。
|
||||
- 兜底:fallback HTML 必须自包含、无远程运行依赖,从 `ready` 开始并真实绘制 Canvas,持续更新 `playable-web-game-state.v1`,提供键盘 / 触控、start / primary-action / restart 和胜负状态;primary-action 后可保持 `playing`,restart 后可稳定恢复 `ready | playing`,不得开始前固定 `lost` 或用固定失败充当完成。fallback 只有在 `assets/art-spec.png` 已有效登记并真实存在时才能生成,而且必须把该平台图片显著绘制为主要背景、玩家和目标;不得以纯 Canvas 视觉绕过平台图片硬门。
|
||||
- 美术边界:live10 已证明正式透明 `icon-spritesheet` 的后处理无法稳定收进 `300` 秒。game-chat 首版必须配置可用的 External Editor API,由 `art-director` 发起一次平台 `images/generations` 并登记 `assets/art-spec.png`,再由 `code-prototype` 在用户可见画面中把该图片作为主要背景、玩家和目标真实加载和绘制。图片必须可完整解码,引用必须从 `game/index.html` 正确解析到登记路径;活动 Canvas 上同一资源至少包含一次背景级和两次实体级的可达 `drawImage`,隐藏 Canvas、诱饵路径和永不执行函数均不能过门。未配置 API,或生成、登记、文件、引用、可见使用任一缺失时都必须失败关闭,不得写 completed 或 `single_round_converged`。普通 GUI / CLI autonomous 继续正式透明 `assets/art-spritesheet.png` 的完整 DAG,不采用 game-chat 的 `art-spec.png` 快车道。
|
||||
- Windows preview 稳定性:非阻塞 listener 接受连接后必须先把 accepted socket 恢复为阻塞模式,再有界读完拆分到达的请求头;完整响应 `flush + shutdown(Write)` 后执行短时有界 drain。Chromium speculative socket 导致的 `ConnectionAborted / ConnectionReset / Interrupted / TimedOut` 归为可继续监听的瞬时 accept 错误;单个中止连接不得令后续 `preview.validate` 复用或重建时连续得到 `net::ERR_SOCKET_NOT_CONNECTED`。
|
||||
- Runtime 恢复确认:GUI 自动扫描 `agent.resume` 前必须先用只读方式判断是否存在可恢复任务或 durable recovery artifact;全新项目与已完全终态、无任何恢复工作的项目直接返回空结果,不弹出“恢复未完成 Runtime 任务”;一旦存在 task、retry、handoff、finalization、pending action 或 reconciliation 等可恢复工作,仍必须经过原 `agent.resume` policy 门禁,不得通过吞掉 policy error 绕过确认。
|
||||
- 每条输出入聊天:事件文件中的原始 `summary / detail` 仍是私有 Runtime 证据,不可由前端直接持久化。Rust 只对白名单用户进度生成 `publicText`,同时为每次真实追加生成 `eventId`;action 重放沿用 action 身份,普通事件使用进程、毫秒与单调序列组成唯一身份。前端把 `eventId + publicText` 和四阶段专业 Agent 的 durable final reply 作为独立 assistant 消息,按顶层 `messageId` 幂等写入项目 conversation;重载恢复、轮询与实时事件并发不得重复或漏掉当前已观察输出。
|
||||
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。
|
||||
|
||||
## 2026-08-03 game-chat 开发态前后端同源与快车道恢复
|
||||
|
||||
- 启动决策:`npm run agc` 与 `npm run agc:game-chat` 统一先经外层 Node 启动器预检 `3080`。在 marker 尚不能证明 worktree 归属时,任何已占用的 3080 都不得复用,并必须在原生窗口创建前失败关闭;Tauri CLI 退出后必须收束已启动的客户端进程树,不允许终端已退出但窗口与 Runner 仍假在线。
|
||||
- 首波决策:普通 GUI / CLI 的正式 16 节点 DAG 与 game-chat 首版 lane 都只把 `design-director / art-director / code-director` 作为首波 ready Agent。正式 DAG 的 `design-foundation` 等待策划与美术 Director,`code-prototype` 等待程序 Director 及数值、美术、音频三条底层产物链;game-chat 则在三个 Director 全部完成后才启动 `code-prototype`,再串行执行静态检查和试玩。首波以外的非 repair 底层 Agent 只能由依赖就绪调度或上层明确返工合同按需激活。
|
||||
- Runtime 决策:game-chat 六任务 lane、平台美术、单轮收束和自动预览只由持久 `project-supervisor-game-chat` root source 启用。hydration 对 `Pending` 的容忍只适用于当前 source-aware lane 的三个零依赖首波任务,不再硬编码单个历史任务。页面进度、阶段记录和 final-reply 白名单统一使用六项任务与 `x/6`。
|
||||
- 显式协作合同:autonomous 的旧 `code-prototype + quality-review` 首批合同退出。显式 project collaboration policy 或持久 batch 恢复若进入首批 `agent.delegate` 路径,只允许且要求三个 Director 各一次;策划与程序 Director 是只读规划且 `expectedArtifacts=[]`,美术 Director 是非只读规范图任务且必须交付 `assets/art-spec.png`。任何非 repair 底层委派与 isolated child 都在首批失败关闭;默认 manifest DAG 仍是唯一自动首轮执行链,不额外复制三个 Director 委派。
|
||||
- 输出决策:保留未提交 `streaming / ready` 的当前 revision 门;已提交的专业 Agent final reply 继续使用既有 durable response-stream 身份,后续项目 revision 变化不再隐藏早期阶段回复。
|
||||
- 关联:`apps/ai-game-creator-shell/scripts/start-tauri-dev.mjs`、`start-dev-stack.mjs`、`src-tauri/src/agent/runtime_protocol/autonomous_completion.rs`、`response_stream.rs`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。
|
||||
|
||||
## 2026-08-03 托管 MCP 未鉴权响应提供安全接入引导
|
||||
|
||||
- 决策:`/api/external/v1/mcp` 缺少、格式错误或无法验证 Bearer API Key 时继续返回相同 HTTP `401`,并增加 `WWW-Authenticate: Bearer realm="genarrative-external-editor"` 与机器可读 `details.guide`。引导只说明 Bearer Header 格式、登录后在「开发者 API Key」创建密钥、原始密钥只显示一次、凭据不得进入聊天或仓库、配置后重试 `initialize`,以及公开 manifest、Skill 与 OpenAPI 地址。
|
||||
- 安全边界:三种鉴权失败不得通过 code、message、details 结构差异暴露 Key 是否存在;未鉴权响应不得包含 MCP tools、resources、owner 或内部鉴权诊断。其它 External v1 业务路由继续使用原通用 401,不继承 MCP 专用引导。
|
||||
- 关联:`server-rs/crates/api-server/src/external_api_auth.rs`、`server-rs/crates/api-server/src/modules/external_api.rs`、`docs/openapi/genarrative-external-v1.openapi.json`、`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md`。
|
||||
## 2026-07-31 External v1 生成统一异步并提供托管 MCP 与完整 Skill 包
|
||||
|
||||
- 异步契约:External v1 的图片生成、图片编辑、图标图集、UI 素材提取、角色动画、视频、音效和背景音乐八类 POST 固定持久化入 `external_generation_job` 并返回 HTTP `202 + operationId/statusUrl/pollAfterMs`;不受站内 `GENARRATIVE_EXTERNAL_GENERATION_MODE=inline` 影响。每次逻辑生成必须携带稳定 `Idempotency-Key`,网络结果未知或调用方轮询超时时复用原键和原 operationId,不得换键重提。
|
||||
- 发布窗口兼容:AI 游戏创作桌面客户端严格按 HTTP 状态分流生成首响应;旧服务 `200` 只作为已经完成且含可下载媒体的同步结果消费,旧图集允许从顶层 `spritesheetImageSrc` 换签下载且无效值不得遮蔽可用 `objectKey`;新服务 `202` 必须取得 `operationId` 后轮询,轮询间隔按 OpenAPI 限制在 `250..=5000ms`,其他 2xx 失败关闭。Runtime 在 POST 前原子持久化精确请求体、请求 SHA-256 与稳定幂等键,`202` 后先原子追加 `operationId` 并回读一致再查询;重启时 `accepted` 账本只恢复 GET,`prepared` 表示提交结果未知并禁止自动 POST。生成 POST 使用独立三十五分钟等待预算且不自动重提;game-chat 仍受父 run 五分钟总截止约束,但截止时若 `canvas.asset_generate` 已进入 executing,客户端与预览照常退出,Runtime 保留 pending action、provider batch、生成账本与 `needs-reconciliation`。响应丢失、旧 `200` 结果损坏、`202` 缺 operationId、轮询超时、状态损坏、透明派生失败或外部完成后的本地提交失败统一投影为不可自动重生的对账边界。非阻断 general warning 继续消费结果并与 `sliceWarning` 分别展示。权威 External v1 OpenAPI 仍只声明新异步 `202`,不把部署过渡兼容公开成正式双协议。
|
||||
- 查询与结果:新增 owner-safe `GET /api/external/v1/generations/{operationId}`。`queued/running` 返回 phase/progress,`completed` 返回 compact 稳定 artifact 引用,`failed` 返回脱敏错误,跨 owner 按不存在处理。compact result 允许 objectKey、resource/asset ID、assetObjectId、尺寸、媒体类型、taskId 和告警;禁止完整 project/canvas、Data URL、Blob URL、临时 signed URL、内部 provider 原文和 lease/fencing 控制字段。
|
||||
- 客户端 durable 查询约束:私有生成账本同时绑定 base URL/API Key 配置指纹,指纹不一致不查询旧 operation。旧 `200` 兼容结果只持久恢复允许字段和安全媒体引用。operation 明确 failed 的账本保留到 pending observation 和 Provider batch 终态落盘后再清理。生成提交只有契约明确的 `400 / 401 / 403` 可判定为入队前拒绝并清理 prepared 账本;其它非成功状态一律保留账本进入对账。账本路径解析、扫描和删除逐级拒绝符号链接,非法控制路径失败关闭。
|
||||
- MCP:新增托管 `/api/external/v1/mcp`,使用现有 External API Key Bearer 鉴权和无协议 session 的 Streamable HTTP JSON direct 模式。MCP tools 从同一 OpenAPI operation 形成并复用 External REST router;生成 tool 显式要求 `idempotencyKey`,另有统一任务查询 tool。MCP resources 提供使用说明、OpenAPI、Skill 入口 `SKILL.md` 和 `references/capability-routing.md`、`references/api-operations.md`、`references/authentication-and-safety.md`、`references/requests-and-outputs.md` 四篇稳定 reference;日后新增 reference 时必须同步新增独立 resource。MCP Agent 直接调用托管 tools,不安装 CLI,也不将脚本、测试或 workflow 暴露为 MCP resources。禁止开放内部 SpacetimeDB MCP、worker procedure、controller 或队列控制面。
|
||||
- Agent 发现:新增公开 `agent-integration.json`、`skill/SKILL.md` 和 `skill.zip`。manifest 同时声明 MCP、OpenAPI、完整 Skill archive、SHA-256 和包内清单;archive 必须包含 `SKILL.md`、上述四篇 references、stdlib Python helper 和 `agents/openai.yaml` 七个声明文件,不能只提供 OpenAPI JSON,也不能包含 API Key、本机路径或个人配置。完整 `skill.zip` 只供不支持 MCP 或需要本地文件上传编排的 Agent 使用,不作为 MCP resource。
|
||||
- 兼容边界:这是基于「截至 2026-07-31 尚无外部第三方存量调用方」接受的 v1 原地 breaking change;一旦出现外部活跃 Key、公开契约或联调方,后续破坏性变更必须保留兼容、经过弃用期或升级 `/api/external/v2`。
|
||||
- 关联文档:`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md`、`docs/technical/【后端架构】外部生成Worker化方案-2026-06-03.md`、`.codex/skills/genarrative-external-editor-api/SKILL.md`。
|
||||
|
||||
@@ -67,7 +67,7 @@ npm run agc:build:game-chat-release
|
||||
|
||||
该命令启用 Rust `game-chat-release` feature,并配合编译期前端入口锁定生成独立 NSIS 包。当前专用 release 版本为 `0.1.1`;产物的 `productName` 为 `Genarrative Game Chat`,`identifier` 为 `world.genarrative.ai-game-creator.game-chat`,安装身份和 AppData 不与普通 AI 游戏创作客户端混用。独立包直接渲染本地 `GameChatReleaseApp`,绕过平台 `AuthenticatedClient`,进入本地项目工作台不依赖 `api-server`;普通 `npm run agc`、`npm run agc:dev`、debug game-chat 和 `npm run agc:build` 继续走既有认证入口与配置。
|
||||
|
||||
game-chat 的用户可见 preview 必须由 Tauri 客户端 `PreviewRegistry` 持有。External Runner 和 Tauri 的 registry、server 句柄与 running 状态是进程内资源,不得互相推断或把 Runner 验证用 server 直接交给 iframe。当前 accepted Supervisor 父 run 下真实 `preview-playtest` scheduler child 首次给出结构化成功证据、且其 revision 精确等于项目当前 revision 后,客户端才消费一次性授权并启动一个 Tauri preview server,随后自动显示 iframe;`preview.start` 必须携带 `expectedRevision`,Tauri 在取得项目写锁后再次原子比对。same-run steer 授权必须记录授权前 revision / validation cursor 和唯一 generation ID,旧证据、旧 policy await 或旧 start 返回均不能清除新授权。同一 run 的更高 validated revision 只刷新原 iframe,不能重复 `preview.start` 或新增 server,相同 / 更低 revision 不刷新;同 revision 的最新失败证据必须关闭该 revision 的可玩判定。preview HTTP 的 HTML、脚本、样式、资源和错误响应都必须返回 `Cache-Control: no-store`。没有 Tauri 用户预览时,顶部状态必须显示“预览未启动”,不能只写“未启动”。
|
||||
game-chat 的用户可见 preview 必须由 Tauri 客户端 `PreviewRegistry` 持有。External Runner 和 Tauri 的 registry、server 句柄与 running 状态是进程内资源,不得互相推断或把 Runner 验证用 server 直接交给 iframe。当前 accepted Supervisor 父 run 下真实 `preview-playtest` scheduler child 首次给出结构化成功证据、且其 revision 精确等于项目当前 revision 后,客户端才消费一次性授权并启动一个 Tauri preview server,随后自动显示 iframe;`preview.start` 必须携带 `expectedRevision`,Tauri 在取得项目写锁后再次原子比对。same-run steer 授权必须记录授权前 revision / validation cursor 和唯一 generation ID,旧证据、旧 policy await 或旧 start 返回均不能清除新授权。同一 run 的更高 validated revision 只刷新原 iframe,不能重复 `preview.start` 或新增 server,相同 / 更低 revision 不刷新;同 revision 的最新失败证据必须关闭该 revision 的可玩判定。preview HTTP 的 HTML、脚本、样式、资源和错误响应都必须返回 `Cache-Control: no-store`。服务端必须在有界 read timeout、总 header 字节和 header 行数内读完请求头再响应,避免 Windows 因未读请求字节产生 abortive RST;`accept` 遇到 Chromium speculative socket 的 `ConnectionAborted / ConnectionReset / Interrupted / TimedOut` 时继续监听,不能让一个瞬时连接中止整个 preview server。没有 Tauri 用户预览时,顶部状态必须显示“预览未启动”,不能只写“未启动”。
|
||||
|
||||
`generic-v1` 的真实试玩必须从 `ready` 且正整数 level 开始;start 推进到 `playing` 后,必须先持续观察 2 秒并取得至少 8 个实际样本,期间保持 `playing`,以确认玩家获得正常操作机会;随后点击唯一可见、启用且真实可交互的 `data-playtest-id="primary-action"`,由该控件触发真实主要玩法操作,并以 sequence 相对点击前严格推进证明操作已被接受。操作被接受前进入 `won | lost` 代表玩家没有获得正常操作机会,必须失败;操作被接受后的单次 `lost` 是合法结局,但不能成为所有受控尝试的唯一结果。若主要操作后仍为 `playing`,则继续观察 3 秒并取得至少 12 个实际样本;`won` 可提前证明非失败推进。之后 restart 必须推进 sequence、恢复到 `ready | playing`,并持续观察 3 秒、取得至少 12 个实际样本;若首轮结果为 `lost`,重开稳定后必须再执行一次必要的 start、2 秒 / 8 样本操作机会和真实 primary-action,第二次必须进入或保持 `playing`(再观察 3 秒 / 12 样本且不得转为 `lost`)或进入 `won`。两次受控尝试都固定 `lost` 代表无法正常推进的恶性 bug,必须失败。各观察窗口内 sequence 不得回退,restart 窗口只能保持 `ready | playing`。样本数和观察时长必须同时满足,窗口末端必须强制再读取一次有效状态,不能靠前段样本数提前通过。selector、时长、样本门槛、终态边界、非失败推进、窗口末端覆盖、required assertions 和 sequence 规则都属于 scenario fingerprint。旧 fingerprint 回执在读取和 plan liveness 检查时按 stale missing 处理,让同一 run 可重新 `preview.validate`;身份、digest、路径或内容完整性篡改仍失败关闭,最终完成门仍须现场重算当前 fingerprint 并严格拒绝旧证据。
|
||||
|
||||
@@ -81,7 +81,11 @@ cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml real_
|
||||
|
||||
修改 game-chat release flavor 后,至少执行壳配置门禁、AppSurface game-chat 定向测试、前端类型检查、AppData / 诊断日志 / release flavor 相关 Rust 定向测试、`npm run check:encoding` 和 `git diff --check`。打包 smoke 必须确认:安装信息和产物版本为 `0.1.1`;无参数启动直接进入且只能停留在 game-chat 页面;停止或断开 `api-server` 后本地工作台仍能打开;普通 dev / release 与 debug game-chat 仍走原认证入口;独立 AppData 生效。预览 smoke 应先让当前 run 成功验证 revision N,确认 Tauri registry 启动一个 server 且 iframe 自动出现;在 validate 后、start 取得锁前推进项目 revision,必须确认原子 `expectedRevision` 门禁拒绝启动且授权保留等待新证据;再验证 revision N+1,确认 server 进程和 loopback origin 不变、iframe 显示新版本且响应为 `no-store`。same-run steer 还要覆盖旧验证不消费新授权、旧异步 attempt 不清新 generation;Runner registry 单独 running、失败 / 相同 / 更低 revision 均不能触发用户预览或重复刷新,停止后顶部显示“预览未启动”。独立包退出时必须通过 `runner.shutdown_for_client_exit` 先进入 draining 再结束本 boot,保留 durable sidecar 供下次 reconciliation,不把中断任务写成 completed;Windows Runner 必须 `CREATE_SUSPENDED -> AssignProcessToJobObject -> ResumeThread`,分配或恢复失败时 kill + wait,客户端持有 kill-on-close Job 兜底,关闭主窗口后 Runner、MCP、command、ConPTY 及其后代都应消失。普通 dev / release 和 CLI 继续使用 `runner.shutdown_if_idle`。
|
||||
|
||||
game-chat 迭代还必须确认三条行为:每条 Supervisor ready 输出都以 `runId + requestSlot + responseRevision` 组成的 durable message ID 固化在聊天框,事件 / 轮询 / hydration 重放不重复;可信 `project-supervisor-game-chat` 一轮完成 `preview-playtest` 后直接收束,不调度 `publish-strategy` / `publish-package`;配置 External Editor API 时,`code-prototype` 的 `game/index.html` 实际引用已由 Canvas 登记的 `assets/art-spritesheet.png`,缺少登记、文件或引用必须失败关闭。对应定向测试至少包括:
|
||||
game-chat 迭代还必须确认以下行为:Supervisor ready 输出、`art-director / code-prototype / preview-readiness / preview-playtest` 四个专业 Agent 的 durable `final-reply`,以及 Rust 明确生成 `eventId + publicText` 的每条公开 Runtime 输出都作为独立 assistant 消息逐条固化在项目聊天;`art-asset-plan` 不进入进度、阶段记录或 final-reply 投影。消息通过顶层 `messageId` 幂等追加,事件 / 轮询 / hydration 重放不重复。前端禁止从原始 `summary / detail`、tool plan、Provider / Runner 元数据、命令输出或路径自行拼接持久消息;UI 把一个父 Run 统一显示为“本轮生成进度”,最新状态也不得暴露内部“第 N 轮”,完整 GUI / CLI 任务图可显示 `x/14`,首版快车道显示 `x/4`,终态不保留运行中进度卡;可信 `project-supervisor-game-chat` 一轮完成 `preview-playtest` 后直接收束,不请求下一次 Provider tool-plan;所有调度入口(包括 `agent.schedule_ready`、`task.list` 结果驱动的直接 `agent.delegate`)均不得暴露或启动 `publish-strategy` / `publish-package`。game-chat 必须配置可用的 External Editor API,由 `art-director` 通过一次平台 `images/generations` 生成并登记 `assets/art-spec.png`,`code-prototype` 必须把它显著用于用户可见的主要背景、玩家和目标;未配置 API 或缺少任一环节都必须失败关闭。普通 GUI / CLI autonomous 继续正式透明 `assets/art-spritesheet.png` 的完整 DAG。对应定向测试至少包括:
|
||||
|
||||
game-chat 首版快车道采用独立四阶段口径:只显示 `art-director`、`code-prototype`、`preview-readiness`、`preview-playtest` 的 `x/4`,不把完整 DAG 或内部 loop 计入分母。父 Run 与全部 child Run 共用 240 秒软预算和 300 秒累计硬上限;首版最多一次 Provider 规划 / 写入请求,软预算后只能运行确定性的本地 fallback、`game.static_smoke`、`preview.validate`,硬上限内未通过完成门必须失败,证据在上限后到齐也不得写 `single_round_converged`。live10 实测正式透明 `icon-spritesheet` 后处理超过 300 秒,因此 game-chat 改为一次平台 `images/generations` 生成并登记 `assets/art-spec.png`;fallback 只有该图片有效登记且真实存在时才允许生成,并必须把它显著绘制为主要背景、玩家和目标。未配置 External Editor API、图片生成失败、缺少 Canvas / manifest 登记、文件、HTML 引用或用户可见绘制时必须在 300 秒内失败关闭,绝不误报 completed。普通 GUI / CLI 继续正式透明 `assets/art-spritesheet.png` 的完整 DAG。对应定向测试至少包括:
|
||||
|
||||
game-chat GUI 恢复还要覆盖两类竞态:root Runtime 先终态、manifest 四阶段后终态时,必须等到四任务最终状态后仅持久化一条 `【Supervisor 阶段记录】`;页面初始 hydration 直接读到真实终态时也要补写缺失记录,但不得把 `idle` 当作完成。同时,GUI 启动的 `agent.resume` 自动扫描必须先做只读恢复工作预检:新项目或无 task / retry / handoff / finalization / pending / reconciliation 工作的已终态项目不弹确认,存在任何 durable recovery artifact 则仍必须命中 `agent.resume` policy。
|
||||
|
||||
```bash
|
||||
npm run test -- apps/ai-game-creator-shell/tests/agentRuntimeModel.test.ts --run
|
||||
@@ -591,7 +595,7 @@ npm run check:server-rs-ddd
|
||||
|
||||
- 移动端优先,再兼容网页端。
|
||||
- 页面只展示后端返回的状态,不自行计算结论型业务状态。
|
||||
- 现役一级入口为 `/creation`、`/project`、`/profile`,桌面侧边栏和移动端底部 dock 都固定显示“创作 / 项目 / 我的”。`/creation` 只读取图片编辑器项目与 `GET /api/editor/showcase/resources`,不得重新接入旧模板入口配置、旧作品架或专属运行态。
|
||||
- 现役稳定路由为 `/creation`、`/project`、`/profile`。桌面侧边栏固定显示“创作 / 项目 / 我的”;移动端底部 dock 只显示“我的”,并对 `/creation`、`/project`、`/editor/canvas` 及页面内项目 / 画布动作统一显示桌面端提示,不挂载创作工具、项目列表或图片画布。桌面端 `/creation` 只读取图片编辑器项目与 `GET /api/editor/showcase/resources`,不得重新接入旧模板入口配置、旧作品架或专属运行态。
|
||||
- 旧创作模板目录和顶层旧业务模块必须持续退出 Vite、TypeScript、ESLint 与 Vitest;旧 `/api/creation-entry/config`、模板 API、公开作品详情和运行态 API 必须保持未挂载。SpacetimeDB 历史表、迁移白名单与必要兼容类型只作为数据壳保留,不得据此恢复业务逻辑。
|
||||
- 优先复用现有面板、抽屉、弹窗,不新建独立大系统。
|
||||
- 不在 UI 中默认写功能说明类文本。
|
||||
|
||||
@@ -3970,6 +3970,14 @@
|
||||
- 处理:先以 CAS 单独 commit `queued -> executing`,成功后才调 ToolHost;调用返回后再 commit observation。恢复见到 executing 或 ToolHost 返回 Unknown 时只能进入 reconciliation,不得自动重执行。重复 resume 不得继续增 revision 或重复 event。
|
||||
- 验证:在“ToolHost 已调用、observation commit 失败”处注入故障,序列化快照并用新 engine 重载;断言重复 resume 后 ToolHost 计数仍为 1,且只有显式 reconcile observation 才恢复 running。
|
||||
|
||||
## Runtime pending 恢复不能让大型 async frame 共用默认 worker 栈(2026-08-03)
|
||||
|
||||
- 现象:Supervisor collaboration durable isolated spawn 恢复测试在默认 Tokio worker 栈下稳定 `stack overflow`;单独运行同样失败,提高 `RUST_MIN_STACK` 后通过。
|
||||
- 原因:不是业务递归。debug 构建中 pending action continuation、后台 task queue 和 Agent 主循环各自形成大型 async poll frame;恢复路径在同一次 poll 调用链直接进入下一层状态机,累计超过 worker 默认栈。
|
||||
- 处理:整个 pending continuation、它进入的后台主循环,以及完成、取消或失败后 drain 同 Agent 后续队列时,都必须跨越独立 Tokio task 轮询边界,使上层 poll 先退栈后再轮询下一层状态机。传入边界的 future 必须先装箱;若泛型 helper 直接持有大型 future,即使随后 `spawn`,调用方 async frame 仍会把它保留在默认 worker 栈上。边界必须保留结构化取消语义;当前使用 boxed future 与 `JoinSet`,父 continuation 被丢弃时同步 abort 子任务。不得只增大 CI 的 `RUST_MIN_STACK`,否则生产默认栈仍可能崩溃。
|
||||
- 验证:失败用例必须在未设置 `RUST_MIN_STACK` 时通过;同时覆盖 policy batch 全组、拒绝 pending 后重规划并 drain 下一任务,以及 pending/cancellation 回归,证明恢复不重复生成 isolated spawn、队列继续推进且父任务取消不遗留后台子任务。
|
||||
- 关联:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/pending_execution.rs`。
|
||||
|
||||
## Provider 可扩展不能用一个全局 protocol 枚举代替实例隔离
|
||||
|
||||
- 现象:把 `openai_chat / openai_responses / anthropic` 直接当 Provider 身份,注册第二个同协议 endpoint 时发生 ID 冲突;或为方便调用把 API Key、base URL、raw-log 目录放进全局状态,并行请求后日志串目录。
|
||||
@@ -3998,3 +4006,55 @@
|
||||
- 处理:改外部 v1 响应前先确认 `external_api_key` 是否已有非内部账号的活跃密钥。仍无调用方时可按现行豁免直接改,但必须同步更新接入方案的「版本与兼容策略」;已有调用方时按该节规则择一处理(兼容值 / 弃用期 / 升 v2),只改 JSON 不构成合规变更。
|
||||
- 验证:`external_editor_api.rs` 的 openapi 断言只校验 schema 形状,不校验兼容性,通过不等于契约安全;判定 breaking 与否以「删字段、移出 required、收窄类型、改语义、新增必填」为准。
|
||||
- 关联:`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md`、`docs/openapi/genarrative-external-v1.openapi.json`、`server-rs/crates/api-server/src/external_editor_api.rs`、`server-rs/crates/api-server/src/modules/external_api.rs`。
|
||||
|
||||
## Tauri beforeDevCommand 失败不等于已启动客户端会自动退出(2026-08-03)
|
||||
|
||||
- 现象:旧 worktree 的 AGC Vite 长期占用 `127.0.0.1:3080`,marker 仍指向旧 API;新 worktree 启动 game-chat 后,配套后端在新端口 ready,随后 `beforeDevCommand` 因代理 target 不匹配返回非零,终端已经回到提示符,但原生客户端和它启动的 Runner 仍存活。客户端 WebView 实际加载旧 Vite,因此当前 master 的界面优化看起来全部缺失。
|
||||
- 原因:Tauri 的字符串 `beforeDevCommand` 默认 `wait=false`。只要固定 `devUrl` 上已有可访问页面,Tauri CLI 可以在配套启动脚本完成前创建原生窗口;旧实现又直接从 npm 启动 Tauri CLI,没有在 CLI leader 退出后继续持有其 PGID / Windows 进程树。`start-dev-stack.mjs` 虽会在后端 ready 后识别 marker/API 错配,但检查时机已经晚于窗口创建,且只清理自己登记的后端和 Vite。
|
||||
- 处理:`dev` 与 `game-chat` 统一先进入 `start-tauri-dev.mjs`,在启动 Tauri CLI 前无副作用检查 3080。现有 marker 只有 API target,不能证明监听器属于当前 worktree,因此任何已存在的 3080 都失败关闭,不主动杀不能证明归属的旧服务,也不因 target 看似匹配而复用。Tauri CLI 使用独立 POSIX 进程组,任意退出后按负 PGID 先 TERM、有界等待、再 KILL;Windows 固定调用 `taskkill /PID <pid> /T /F`。`start-dev-stack.mjs` 自己的后端 / Vite 独立组也在返回前有界收束。
|
||||
- Linux 容器边界:最小化 CI 容器的 PID 1 可能不回收孤儿后代,进程组在所有可执行成员退出后仍只剩 `Z` 僵尸;此时 `kill(-pgid, 0)` 仍成功,不能据此把已经完成的收束误报为失败。Linux 等待逻辑在 signal 探活后必须核对 `/proc/<pid>/stat`,只把同 PGID 的非 `Z / X` 成员视为存活;`/proc` 不可读时继续使用原保守判断,macOS 等其它 POSIX 平台仍只走 signal 探活。
|
||||
- 验证:定向测试必须覆盖旧 marker target 在 CLI spawn 前被拒绝、target 看似匹配仍拒绝无归属 Vite、非 HTTP 3080 失败、预检调用顺序、CLI leader 先退出后同 PGID 客户端仍收到 TERM、忽略 TERM 时升级 KILL,以及 Windows taskkill 的 `/PID /T /F` 参数。人工复验旧 worktree 占用 3080 时,新命令不得启动后端或弹出新窗口;正常启动后退出,确认 Tauri 客户端、Runner 和本轮自有后端 / Vite 均按生命周期收束。
|
||||
- 关联:`apps/ai-game-creator-shell/scripts/start-tauri-dev.mjs`、`apps/ai-game-creator-shell/scripts/start-dev-stack.mjs`、`apps/ai-game-creator-shell/tests/start-tauri-dev.test.ts`、`apps/ai-game-creator-shell/tests/start-dev-stack.test.ts`。
|
||||
|
||||
## game-chat 快车道首波与已提交回复不能被后续 revision 破坏(2026-08-03)
|
||||
|
||||
- 现象:首波从单个美术任务扩展为三个 Director 后,hydration 若仍只容忍 seed lane 的第一个任务在 manifest 短暂恢复 `Pending` 时收束,另外两个已启动 Director 会被卡住。另外默认 `llm.stream=false` 下的专业 final reply 虽已由 finalization 提交,但后续阶段推进项目 revision 后,早期回复会从 Runtime 查询中消失。
|
||||
- 原因:hydration 例外把“首波”错误收窄成了单个固定或数组第一项任务;`visible_game_creator_agent_runtime_response_stream_at` 又把未提交流的 revision 新鲜度门误用到了已终态提交的 durable final reply。
|
||||
- 处理:从当前 root source 的 seed lane 动态解析全部零依赖首波任务,只对这些 child 容忍 hydration `Pending`,后续 code prototype / preview 仍严格要求 Running/Completed。`streaming / ready` 仍要求当前 revision,`committed` 回复改为依据 finalization 的稳定身份查询,不随后续项目 revision 失效。
|
||||
- 验证:覆盖 `design-director / art-director / code-director` 三个 Pending 首波 child 均可投影 Completed、`code-prototype` Pending 仍被拒绝;非流式专业 Agent 在 finalization 前无 stream,提交后形成 committed stream,再推进项目 revision 后仍可查询且正文不变。
|
||||
- 关联:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/autonomous_completion.rs`、`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/response_stream.rs`。
|
||||
## 异步生成结果未知时不能换幂等键重提(2026-07-31)
|
||||
|
||||
- 现象:生成提交发生客户端超时、连接中断或响应丢失后,调用方创建新的 `Idempotency-Key` 再提交一次;原任务其实已经入队,最终造成重复生成、重复扣费和重复画布 / 素材库写入。
|
||||
- 原因:把“客户端没有收到结果”误判为“服务端没有受理”,又没有持久保留逻辑请求的幂等键和服务端返回的 `operationId`。托管 MCP 若绕过 External REST router 直接调用 worker 或 SpacetimeDB,也会形成第二套去重与状态语义。
|
||||
- 处理:一次逻辑生成只分配一个稳定幂等键。桌面 Runtime 在 POST 前先把精确请求体、SHA-256 和幂等键原子写入私有生成账本并回读一致;收到 `202 + operationId` 后先把账本升级为 `accepted` 再轮询。重启时 `accepted` 只恢复 GET,`prepared`、响应丢失、`202` 缺 operationId、轮询超时和状态损坏都进入 `needs-reconciliation`,绝不自动 POST。game-chat 五分钟硬截止可以结束本轮、关闭预览和客户端,但 executing 的 `canvas.asset_generate` 必须保留 pending action、provider batch 与生成账本;旧 `200` 图集的 `spritesheetResource` 允许为空,此时只在顶层 `spritesheetImageSrc` 是有效下载引用时优先使用,否则回退可用 `objectKey`。`postprocess-failed-source-preserved` 进入不可自动重生的对账边界;其它 non-blocking warning 继续消费成功结果并单独展示。旧 `200` 兼容不改变权威 External v1 的异步契约。MCP 生成工具必须把 `idempotencyKey` 映射到同一 REST header,并复用同一 External router、owner 和任务账本。
|
||||
- 补充:不能把“accepted 分支里没有生成 POST”误当成 GET-only 恢复。若读取账本前仍重做项目/素材目录准备、输出路径预检或请求正文构造,恢复仍可能创建远端资源或在查询 operation 前失败。恢复必须直接使用 durable snapshot;清理必须最后删除 pending 身份锚点,活动 orphan 不得自动删除。完整恢复 future 还要在默认 Tokio worker 栈下验证,不能靠测试环境调大 `RUST_MIN_STACK` 掩盖栈溢出。
|
||||
- 加固:durable snapshot 必须绑定不含明文凭据的 base URL/API Key 配置指纹,配置漂移时连 GET 也必须阻断。accepted operation 明确 failed 也不能在 observation 持久化前删账本。旧 `200` durable result 只保留允许字段与安全 objectKey/相对路径,签名 URL、query/fragment 和未知字段不落盘。提交只有契约明确的 `400 / 401 / 403` 可证明未入队并清理 prepared 账本;超时、冲突、限流、网关错误及其它意外状态均保留账本进入对账。账本根目录、扫描和删除必须通过受控路径解析逐级拒绝符号链接,不能让项目内链接把清理目标指向项目外。
|
||||
- 验证:覆盖“服务端已入队但提交响应丢失”后原键重试仍返回同一 operation、换 owner 不可见、查询最终只出现一份 completed result 和一次计费 / 写回;MCP 与 REST 对同一 owner、同一请求和同一键必须命中同一 operation。
|
||||
- 关联:`server-rs/crates/api-server/src/external_generation.rs`、`server-rs/crates/api-server/src/external_mcp.rs`、`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md`。
|
||||
|
||||
## api-server 嵌入仓库外资源时必须同步容器构建上下文(2026-07-31)
|
||||
|
||||
- 现象:本地 `cargo test` 可以编译 MCP 与 Skill 下载模块,但 api-server 镜像在 Rust 编译阶段报 `include_str!` 找不到 OpenAPI 或 Skill 文件。
|
||||
- 原因:本地工作树包含完整仓库,而容器 Rust builder 原先只复制 `server-rs/` 和 `public/`;crate 中向上引用的 `docs/openapi/`、`.codex/skills/` 不会自动进入镜像构建文件系统。
|
||||
- 处理:凡 api-server 通过 `include_str!` 使用仓库根目录资源,都要在 `deploy/container/api-server.Dockerfile` 的 builder 阶段显式复制对应权威目录;不要再复制一份内容到 crate 内形成平行事实源。
|
||||
- 验证:除本地 Cargo 测试外,检查 Dockerfile 构建上下文覆盖所有 `include_str!` 相对路径;新增或移动嵌入资源时同步更新容器 COPY 和接入文档。
|
||||
- 关联:`deploy/container/api-server.Dockerfile`、`server-rs/crates/api-server/src/external_mcp.rs`、`server-rs/crates/api-server/src/external_skill_api.rs`、`docs/openapi/genarrative-external-v1.openapi.json`。
|
||||
|
||||
## 权威画布快照不能清掉本地待保存或在途布局(2026-08-03)
|
||||
|
||||
- 现象:用户拖动、缩放、改层序、背景色或 viewport 后,生成完成回包立即覆盖画布;450ms 防抖尚未触发或布局保存仍在途时,编辑静默丢失,undo 也可能被生成保护项阻断。
|
||||
- 原因:服务端 revision 只能排序已提交事实,本地未落库布局没有 revision;直接清空 pending save 并整体应用权威快照等同于把“服务端更新更晚”误判成“服务端知道本地编辑”。
|
||||
- 处理:保留同项目最新本地 dirty snapshot,权威回包先更新资源和生成终态,再按稳定 item ID 合并本地布局字段并基于新 revision 保存。旧权威项在新快照缺失表示后端删除,不能从 pending 或在途旧输入复活;新权威项必须合入,本地删除的旧项不能从权威回包复活。
|
||||
- 生成器边界:`composerOpen` 与 `status / generatedLayerId / errorMessage` 一样属于后端生命周期事实;生成完成快照要求保持面板关闭时,不得被本地在途快照重新展开。提示词、参数和占位位置等本地布局编辑继续保留。集成测试夹具必须模拟后端真实完成快照:既有布局保持原位,完成结果层追加到末尾。同项目权威刷新还必须保留仍有效的单选、多选、生成占位选择或空选,只过滤已删除目标,不得无条件降成第一张图层的单选;首次载入 / 项目切换才设置默认选择。不要只跑 persistence Hook 单测,必须同时运行图片画布生成集成测试,覆盖完成后面板关闭、显式选择结果、背景清选和合并后 CAS 保存。
|
||||
- 验证:分别覆盖防抖 pending、真实在途成功与 409、后端新增、后端删除、本地删除、viewport、背景色和生成面板完成态;运行 `npm run test -- src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx`。
|
||||
|
||||
## Provider schema 能力不能从统一工具标记直接推断(2026-08-03)
|
||||
|
||||
- 现象:把 OpenAI 风格 `strict` 原样透传给完整 Anthropic 工具目录,单个 schema 不支持的约束或全请求工具 / optional / union 上限会让整次 planning 返回 400。
|
||||
- 处理:能力不能从 `apiKind=anthropic` 推断;只对已验证 endpoint/model 显式开启,AGC 当前仅自动识别官方 HTTPS endpoint 与 Claude 4.5+ 版本化 model id,旧模型、未知别名和第三方兼容网关默认关闭。协议适配层用官方支持关键词白名单生成 Anthropic 专用传输 schema,对已知不支持约束仅从传输副本剔除,未知关键词、不可解析 / 递归 `$ref` 和复杂度超限均失败关闭为 non-strict,不删工具或修改调用方原 schema。真实 live 样例应包含 `$defs/$ref` 嵌套 schema,并使用官方 Anthropic endpoint,第三方兼容网关不能替代官方能力证据。
|
||||
|
||||
## 可选 MCP server 的坏目录不能拖垮全部工具(2026-08-03)
|
||||
|
||||
- 现象:可选 server 已成功连接,但返回超限 schema、重复 tool identity 或要求未支持 task-mode 时,整个 MCP catalog 和本轮 Agent planning 一起失败。
|
||||
- 处理:连接、tools/list、工具归一化与聚合容量都使用同一 required / optional 边界。optional 将该 server 投影为 `connected=false + error + tool_count=0`,required 保持失败关闭;被包入 `action.input` 的 `$ref` 只重定位当前 document 根的 `#` / `#/...` JSON Pointer,命名 anchor、外部 URI 与带 `$id` 的 schema resource 内 fragment 不得改写。
|
||||
|
||||
@@ -21,7 +21,7 @@ Genarrative / 陶泥儿是一个 AI 原生互动内容与小游戏平台,把 A
|
||||
- 小程序 WebView 外壳:`miniprogram/`。
|
||||
- 法律文本:`media/files/user_agreement.md`、`media/files/privacy_policy.md`、`media/files/disclaimer.md`。
|
||||
|
||||
桌面端侧边栏和移动端底部 dock 的一级入口统一为 `创作 / 项目 / 我的`。`/creation` 是独立创作工具主页,`/project` 是画布项目入口,`/profile` 是“我的”稳定路由,继续承载账号、钱包、统计和通用设置等平台公共能力;刷新及浏览器前进 / 后退必须保持当前入口与选中态一致。
|
||||
桌面端侧边栏的一级入口为 `创作 / 项目 / 我的`;移动端底部 dock 只保留 `我的`。`/creation` 是桌面端独立创作工具主页,`/project` 是桌面端画布项目入口,`/profile` 是桌面端和移动端共用的“我的”稳定路由,继续承载账号、钱包、统计和通用设置等平台公共能力。移动端直达 `/creation`、`/project` 或 `/editor/canvas`,以及从首页触发项目 / 画布动作时,只显示桌面端创作提示,不挂载对应工具页面。
|
||||
|
||||
## 当前后端路线
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
- 涉及中文文本时注意 UTF-8 编码和乱码排查。
|
||||
- 涉及后端时遵循 DDD 分层,不把业务真相下沉到前端或临时兼容层。
|
||||
- `packages/shared` 用于前后端 DTO、公开契约及跨页面复用的无业务真相 UI 组件和纯工具;不得把领域规则、后端副作用或正式状态放入其中。
|
||||
- 修改 `/api/external/v1` 的路由、HTTP 方法、请求 / 响应 DTO、请求头、状态码、鉴权或异步语义时,必须同批更新 `docs/openapi/genarrative-external-v1.openapi.json` 和对应契约测试;Rust 实现与 OpenAPI 未对齐时不得完成、提交或发布。
|
||||
- `maincloud` / `Maincloud` / `MAINCLOUD` 相关代码、脚本、测试、环境变量、命令和文档要求均视为历史残留,禁止新增、运行或引用;API smoke 统一使用 `npm run dev:api-server` 与 `/healthz`。
|
||||
- 涉及 SpacetimeDB 表结构、发布或迁移时,先看 `SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md` 和 `SPACETIMEDB_TABLE_CATALOG.md`。
|
||||
- 涉及生产发布、服务器配置、Jenkins Job 重建或回滚时,先看 `PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md`。
|
||||
|
||||
Reference in New Issue
Block a user