diff --git a/README.md b/README.md index 29bd49c26..740ad78b4 100644 --- a/README.md +++ b/README.md @@ -83,11 +83,12 @@ npm run check:encoding ## 文档入口 -`docs/` 已在 `2026-05-15` 完成压缩整理,旧 PRD、设计、审计、阶段计划和技术流水账不再作为实现依据。当前只读取: +`docs/` 已在 `2026-08-25` 按当前代码与运行态重新收口。旧 PRD、设计、审计、阶段计划和技术流水账不再作为实现依据;专题文档的现役清单统一从 `docs/README.md` 进入: - [docs/README.md](./docs/README.md):当前文档总入口。 - [docs/【项目基线】当前产品与工程约束-2026-05-15.md](./docs/【项目基线】当前产品与工程约束-2026-05-15.md):产品、命名、UI、协作和废弃路线。 - [docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md](./docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md):DDD 边界、API 分组、SpacetimeDB schema 规则和表目录。 -- [docs/【玩法创作】平台入口与玩法链路-2026-05-15.md](./docs/【玩法创作】平台入口与玩法链路-2026-05-15.md):创作入口、草稿架和各玩法当前口径。 +- [docs/【玩法创作】平台入口与玩法链路-2026-05-15.md](./docs/【玩法创作】平台入口与玩法链路-2026-05-15.md):平台现役入口、项目页和画布链路。 - [docs/【开发运维】本地开发验证与生产运维-2026-05-15.md](./docs/【开发运维】本地开发验证与生产运维-2026-05-15.md):本地启动、检查、部署、埋点和运营查询。 +- [docs/project-memory/README.md](./docs/project-memory/README.md):团队共享的当前项目记忆、决策和未关闭事项。 - [UI_CODING_STANDARD.md](./UI_CODING_STANDARD.md):像素 UI 资产与编码规范。 diff --git a/TRACKING.md b/TRACKING.md deleted file mode 100644 index 40ab2e64d..000000000 --- a/TRACKING.md +++ /dev/null @@ -1,177 +0,0 @@ -# 图片画布编辑器 Lovart 化执行跟踪 - -更新时间:`2026-06-23` - -## 目标 - -- 先落文档、测试用例和进度跟踪文件。 -- 再实施 `/editor/canvas` 的 Lovart 风格画布交互、缩放二级菜单、吸附线、元数据窗口、真实生成 / 修改入口和工程 / 画布持久化。 - -## 拆分口径 - -- `docs/technical/【前端架构】图片画布编辑器前端拆分计划-2026-06-17.md` 中的二十七个“阶段模块”是原始计划项,用来描述目标边界。 -- 本文件验证记录里的“执行批次”按每次实际修改、验证、提交和推送递增,包含原始计划项落地、计划外回归修复、组件复用、测试迁移和后续模型收口。 -- 因此“第四十一执行批次”不代表原始计划有四十一个阶段;它表示已完成并推送的第四十一次前端拆分相关增量。 -- 当前原始二十七个计划项已经覆盖到第二十七阶段模块,后续执行批次属于对已拆模块的深化收口或回归修复。 - -## 进度 - -| 工作项 | 状态 | 记录 | -| --- | --- | --- | -| 文档 | 已完成 | 已补领域词、技术方案和后端表 / API 边界。 | -| 测试用例 | 已完成 | 已补前端交互测试和 editor project client 测试。 | -| 后端持久化 | 已完成 | 已新增 editor project/resource 表、SpacetimeDB procedure、spacetime-client facade 与 api-server BFF。 | -| 前端交互 | 已完成 | 已实现缩放菜单、工具模式、Space 抓手、中键平移、吸附线、元数据弹窗和右侧真实修改结果。 | -| 素材库增强 | 已完成 | 已实现账号级素材库持久化、文件夹新建 / 折叠 / 重命名 / 删除、多文件上传、拖拽定向上传、素材框选与批量删除。 | -| 画布增强 | 已完成 | 已实现拖拽上传到画布并创建图层、图层打组、Ctrl/Cmd 滚轮缩放、普通滚轮纵向滚动和小地图拖拽移动视图。 | -| 前端拆分 | 进行中 | 已新增前端拆分计划,抽出类型、画布模型、生成模型、导出模型和素材 / 图层整合侧栏视图,主视图保留状态编排与跨画布状态机。 | -| 验证 | 已完成 | 聚焦测试、类型检查、Rust 检查、schema guard、编码检查、diff 空白检查和浏览器 smoke 已通过。 | - -## 待办清单 - -- [x] 更新图片画布编辑器技术方案,明确 v2 范围。 -- [x] 补充 `/editor/canvas` 领域词,区分图片画布工程和单图资产编辑。 -- [x] 添加前端组件交互测试。 -- [x] 添加 editor project API client 测试。 -- [x] 新增 `editor_project`、`editor_canvas` 与 `editor_project_resource` 表。 -- [x] 同步 SpacetimeDB migration 表清单、生成绑定和后端架构表目录。 -- [x] 新增 api-server `/api/editor/projects*` BFF。 -- [x] 接入前端自动保存与资源创建 API。 -- [x] 实现 Lovart 风格缩放菜单和快捷键。 -- [x] 实现 AI 画布底部工具栏、工具模式和临时抓手。 -- [x] 实现核心吸附线和拖拽吸附。 -- [x] 实现生成资源元数据窗口和真实修改右侧结果。 -- [x] 执行并记录验证命令。 -- [x] 新增 `/project` 项目页,接入项目列表、单项重命名 / 删除、批量选择和批量删除。 -- [x] 接入“我的”页项目入口与 `/editor/canvas?projectid=` 精准加载。 -- [x] 新增账号级素材库表、API、前端服务和编辑器接入。 -- [x] 素材文件夹支持新建、折叠、重命名和删除。 -- [x] 上传按钮与拖拽上传均支持多文件;拖到文件夹 / 素材行进入对应文件夹,拖到画布进入默认文件夹并创建图层。 -- [x] 素材选择模式支持框选多选和批量删除。 -- [x] 图层面板支持对当前选中图层打组并持久化 groupId。 -- [x] 小地图支持拖拽移动画布视图。 -- [x] 滚轮语义调整为普通滚轮纵向滚动,Ctrl/Cmd 滚轮缩放并阻止浏览器缩放。 - -## 决策记录 - -- `/editor/canvas` 的长期领域对象命名为“图片画布工程的画布入口”。 -- project 保存工程元数据;canvas 保存 viewport 与图层布局;资源表保存 OSS 引用和上传 / 生成元数据。 -- 本期工程与资源持久化真实落库;图片生成 / 修改已接入 api-server VectorEngine BFF,暂不接入计费和队列进度。 -- `适合视图` 的语义为显示画布所有可见元素。 -- 吸附范围为核心对齐:左右 / 上下边缘和水平 / 垂直中心线。 -- 缩放控件采用 Lovart 风格百分比按钮和二级菜单。 - -## 验证记录 - -- `npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx` -- `npm run test -- src/services/image-editor/editorProjectClient.test.ts` -- `npm run test -- src/routing/appPageRoutes.test.ts` -- `npm run typecheck` -- `cargo check -p spacetime-client --manifest-path server-rs/Cargo.toml` -- `cargo check -p api-server --manifest-path server-rs/Cargo.toml` -- `npm run check:spacetime-schema` -- `npm run check:encoding` -- `git diff --check` -- Headless Playwright smoke:`http://127.0.0.1:10000/editor` 可展示画布、缩放菜单、底部工具栏和图片工具栏;只启动 `dev:web` 时 `/api/*` 代理 500 属于未启动后端的预期现象。 -- 2026-06-23 规范图选择回归修正:角色规范槽只接受画布中的规范图,图标素材与 UI 设计规范槽只接受图标规范图;选择普通角色图、图标图或其它不合格图片时不写回引用,并在画板顶部显示 warning toast。已验证:`npm run test -- src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-12 Lovart 布局修正 smoke:`http://127.0.0.1:10000/editor` 已移除左侧竖向工具栏和右侧独立图层栏;素材、已生成文件、图层统一收在左侧可折叠面板,中央画布和周边面板保持浅色一体布局;截图留存于 `output/playwright/editor-left-integrated-light.png`。 -- 2026-06-12 外圈背景修正 smoke:`http://127.0.0.1:10000/editor` 的编辑器宿主和画布根容器已铺成同一块白色工作台,不再通过圆角边框露出底部平台背景;截图留存于 `output/playwright/editor-no-outer-background.png`。 -- 2026-06-12 画布背景与原生菜单修正 smoke:`http://127.0.0.1:10000/editor` 已拦截编辑器区域右键菜单,禁用长按文本选择 / iOS callout,并移除画布网格线与棋盘格底纹;截图留存于 `output/playwright/editor-plain-background.png`。 -- 2026-06-12 Lovart 面板与外层 padding 修正:`/editor` 外层 `platform-ui-shell` 已按 `image-editor` stage 使用 `p-0 bg-white`,其它页面保留原 padding;已生成文件和图层改为画布左下入口按钮触发的浮层面板,不再堆叠在左侧素材栏;浏览器样式检查确认 shell padding 为 `0px`、画布背景无 `background-image`,截图留存于 `output/playwright/editor-lovart-panel-popup-final.png`。 -- 2026-06-12 侧栏切换修正:删除“已生成文件”入口,删除侧栏内展开 / 折叠按钮;画布左下仅保留“素材”和“图层”入口,二者复用同一个左侧栏,点击当前已打开入口会关闭侧栏。 -- 2026-06-12 工具栏能力修正:删除底部“局部修改工具”入口;上传工具接入隐藏文件选择并将图片加入画布图层;图片浮动工具栏的删除按钮改为真实删除当前图层。 -- 2026-06-12 生成工具修正:移除拼图素材的生成图 mock 元数据,使其作为普通素材显示;底部生成工具改为先打开生成图片对话框,再进入生成中状态并把生成结果加入画布,生成结果保留元数据与修改入口。 -- 2026-06-13 真实生图修正:`/api/editor/images/generations` 和 `/api/editor/images/edits` 统一走 api-server VectorEngine `gpt-image-2` BFF;前端不再创建 mock 成功图,生成 / 修改失败会留在对话框内显示错误;生成图右上角 `{}` 元数据按钮可直接点击打开元数据窗口。 -- 2026-06-13 素材库修正:素材栏按文件夹分组,文件夹支持折叠和新建;上传入口可定向到当前文件夹,上传素材进入素材库并支持删除,内置素材只保留添加和重命名。 -- 2026-06-13 生图鉴权修正:编辑器工程和真实生图请求不再使用禁止 refresh 的局部鉴权策略,可通过 refresh cookie 静默补 access token;真实生图遇到 401 / 403 时弹窗显示“请先登录后再生成图片”,不再暴露后端 requestId 主文案。 -- 2026-06-13 Lovart 生图交互修正:纯文本生图不再使用居中弹窗,点击底部生成工具后在画布中心显示 `Image Generator` 占位框,并在占位框下方显示跟随式生成输入框、参考图入口、比例和模型占位按钮;生成成功后真实图片落在占位框位置。 -- 2026-06-13 Lovart 生图 smoke:`http://127.0.0.1:10003/editor` 点击底部生成工具后已显示画布内占位框和底部浮动输入框,截图留存于 `output/playwright/editor-lovart-generation-composer.png`。 -- 2026-06-13 生图占位交互修正:`Image Generator` 占位框支持拖拽移动,生成输入框跟随占位框;生成成功图层沿用拖拽后的占位位置,生成输入框继续锚定在新生成图片下方,点击其它图片或画布空白不会自动关闭。 -- 2026-06-13 生图锚定 smoke:`http://127.0.0.1:10003/editor` 中占位框拖拽前后坐标从 `(616,217)` 到 `(712,289)`,生成输入框同步从 `(516,571)` 到 `(612,643)`,保持锚定在生成对象下方;截图留存于 `output/playwright/editor-generation-composer-anchored.png`。 -- 2026-06-13 Lovart 小地图与背景色修正:画布左下角补回背景色圆点、小地图开关和小地图预览;小地图展示图层缩略分布与当前视口框,点击执行显示所有元素,背景色菜单可切换工作区底色且不恢复网格 / 棋盘底纹。 -- 2026-06-13 小地图与背景色 smoke:`http://127.0.0.1:10003/editor` 可见左下角小地图、背景色按钮和小地图开关;切换暖灰后画布工作区 `background-color` 为 `rgb(243, 240, 234)`,`background-image` 仍为 `none`;截图留存于 `output/playwright/editor-minimap-background-warm.png`。 -- 2026-06-13 路由与数据归属修正:图片画布页面路由改为 `/editor/canvas`;新增 `editor_canvas` 表作为 project 下的画布数据表,当前工程创建时同步创建默认画布,保存 layout 时写入默认画布,API 响应同时返回 `project.canvas` 和兼容顶层 `viewport/layers`。 -- 2026-06-13 项目页修正:新增 `/project` 作为图片画布工程列表入口;从“我的”页进入项目页,项目卡片进入 `/editor/canvas?projectid=`,并补齐项目列表、重命名、删除和批量删除 API。`GET /api/editor/projects` 在重启后的 api-server 上返回未登录 401,不再是旧进程的 405;`/project` 前端路由 smoke 可渲染项目页白底布局。 -- 2026-06-14 组件复用修正:项目页重命名弹窗改为复用 `UnifiedModal`、`PlatformTextField` 和 `PlatformActionButton`,删除项目页局部 modal / input 样式,避免同类弹窗和表单 chrome 重复实现。 -- 2026-06-14 组件复用修正:新增 `PlatformFloatingMenu` / `PlatformFloatingMenuItem`,项目卡片右下角更多菜单改为复用平台浮层菜单原语;验证命令:`npm run test -- src/components/common/PlatformFloatingMenu.test.tsx src/components/project/ProjectGalleryView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:`PlatformFloatingMenu` 增加菜单标签和四向定位,编辑器顶部缩放菜单改为复用同一浮层菜单原语;验证命令:`npm run test -- src/components/common/PlatformFloatingMenu.test.tsx src/components/project/ProjectGalleryView.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:编辑器生成图元数据弹窗改为复用 `UnifiedModal`,不再手写元数据弹窗遮罩、dialog role 和关闭按钮;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/UnifiedModal.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:编辑器“修改图片”弹窗改为复用 `UnifiedModal`,删除编辑器局部 modal backdrop、dialog role、header 和关闭按钮样式;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/UnifiedModal.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:新增 `PlatformBatchActionToolbar`,项目页选择模式底部批量操作栏改为复用平台批量工具栏原语;验证命令:`npm run test -- src/components/common/PlatformBatchActionToolbar.test.tsx src/components/project/ProjectGalleryView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:项目页读取失败提示改为复用 `PlatformStatusMessage`,页面局部错误样式只保留布局间距;验证命令:`npm run test -- src/components/project/ProjectGalleryView.test.tsx src/components/common/PlatformStatusMessage.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:编辑器生成 / 修改流程中的生成中与失败提示改为复用 `PlatformStatusMessage`,删除局部状态条颜色和错误变体样式;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformStatusMessage.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:编辑器画布背景色菜单改为复用 `PlatformFloatingMenu` 和 `PlatformFloatingMenuItem`,删除局部菜单容器定位 / 边框 / 阴影样式;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformFloatingMenu.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:编辑器“修改图片”弹窗提交按钮改为复用 `PlatformActionButton`,删除局部提交按钮颜色、边框和禁用态样式;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformActionButton.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 组件复用修正:项目卡片预览改为复用 `PlatformMediaFrame`,删除项目页局部预览框比例、图片填充和背景样式;验证命令:`npm run test -- src/components/project/ProjectGalleryView.test.tsx src/components/common/PlatformMediaFrame.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-14 素材库与画布持久化修正:新增 `editor_asset_folder` / `editor_asset` 账号级素材库表、SpacetimeDB procedure、spacetime-client facade 和 api-server `/api/editor/assets*` BFF;编辑器接入文件夹新建 / 折叠 / 重命名 / 删除、素材重命名 / 删除、多文件上传、拖拽定向上传、拖入画布生成图层、素材框选批量删除、图层打组、小地图拖拽、普通滚轮纵向滚动与 Ctrl/Cmd 滚轮缩放。验证命令:`npm run spacetime:generate -- --rust-only`、`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/services/image-editor/editorProjectClient.test.ts`、`npm run typecheck`、`npm run check:spacetime-schema`、`npm run check:encoding`、`cargo check -p spacetime-client -p api-server --manifest-path server-rs/Cargo.toml`、`git diff --check`。 -- 2026-06-14 组件复用修正:编辑器 `EditorIconButton` 改为委托 `PlatformIconButton` 的薄包装,保留编辑器局部 class 与调用方式,但不再维护重复的原生图标按钮可访问性和基础 chrome;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorPrimitives.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformIconButton.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:编辑器生成输入框的提交按钮改为复用 `PlatformActionButton`,仅保留生成器局部尺寸和 Lovart 式浅灰覆盖,不再直接维护原生 submit 按钮基础 chrome;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformActionButton.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:编辑器生成输入框的“参考图”按钮改为复用 `PlatformIconButton variant="surfaceFloating"`,用 children 承载短标签,仅保留生成器局部尺寸和浅灰覆盖;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformIconButton.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:编辑器生成图右上角元数据角标改为复用 `PlatformIconButton asChild="spanButton"`,保留嵌套在图层按钮内的合法 DOM 结构,同时把 Enter / Space 键盘触发和 `darkMini` chrome 收口到共享组件;验证命令:`npm run test -- src/components/common/PlatformIconButton.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:编辑器画布内生成输入框和“修改图片”弹窗提示词改为复用 `PlatformTextField variant="textarea"`,删除编辑器里按标签选择器手写 textarea 基础输入 chrome 的做法,仅保留生成器局部尺寸和 Lovart 式覆盖;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformTextField.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:新增 `PlatformInlineOptionButton`,编辑器生成输入框里的比例和模型选择 pill 改为复用平台内联选项按钮原语,删除两个局部按钮重复维护基础 inline chrome 的做法;验证命令:`npm run test -- src/components/common/PlatformInlineOptionButton.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:`PlatformEmptyState` 增加 `asChild="button"` 形态,项目页空列表“新建项目”卡片改为复用平台空态原语,避免项目页单独维护可点击空态卡片基础 chrome;验证命令:`npm run test -- src/components/common/PlatformEmptyState.test.tsx src/components/project/ProjectGalleryView.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:编辑器顶部缩放百分比触发器改为复用 `PlatformInlineOptionButton`,让缩放菜单入口和生成器比例 / 模型 pill 共用“当前选项触发菜单”的按钮原语;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformInlineOptionButton.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:编辑器左下面板 dock 的画布背景色入口改为复用 `PlatformIconButton`,用色块作为 icon 承载当前背景色,和素材 / 图层 / 小地图入口保持同一图标按钮原语;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformIconButton.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:编辑器素材侧栏的新建文件夹、文件夹重命名和素材重命名输入框改为复用 `PlatformTextField`,输入框局部样式改为明确 class 覆盖,不再按 `input` 标签选择器重复维护基础输入 chrome;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformTextField.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:编辑器侧栏素材和图层缩略图通过 `SidebarMediaItem` 改为复用 `PlatformMediaFrame`,删除缩略图内部图片填充的重复 CSS,统一媒体预览框和 fallback 结构;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorPrimitives.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformMediaFrame.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:画布图片 hover 尺寸标签改为复用 `PlatformPillBadge tone="lightOverlay"`,局部 CSS 只保留定位和深色覆盖,不再重复维护 badge 的圆角、字号和基础排版;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformPillBadge.test.tsx`、`npm run typecheck`。 -- 2026-06-14 组件复用修正:生成跟随框的关闭按钮改为复用 `PlatformIconButton variant="surfaceFloating"`,编辑器薄包装 `EditorIconButton` 增加 variant 透传,删除局部关闭按钮基础 chrome;验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorPrimitives.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/common/PlatformIconButton.test.tsx`、`npm run typecheck`。 -- 2026-06-16 编辑器回归修正:工程 / 素材 / 上传等编辑器请求恢复全局 401 / 403 登录弹窗;未登录上传会先弹登录并在登录后续传;画布背景入口恢复为 `画布背景设置` 面板,支持预设色、自定义颜色、HEX 输入、非法值不应用、恢复默认和 Escape 关闭。验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/services/image-editor/editorProjectClient.test.ts`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器 smoke:`http://127.0.0.1:10006/editor/canvas` 未登录打开 `账号入口`,登录后上传素材成功,背景面板打开后点击“暖灰”使画布背景变为 `rgb(243, 240, 234)`。 -- 2026-06-17 前端拆分第一执行批次:新增 `ImageCanvasEditorTypes`、`ImageCanvasEditorModel`、`ImageCanvasGenerationModel` 和 `ImageCanvasExportModel`,把类型、画布快照 / 吸附 / 背景、生成输入快照和导出元数据规则从 `ImageCanvasEditorView` 抽出;新增模型层单测,主视图从 8286 行降至 7054 行。 -- 2026-06-17 浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录打开工程和未登录上传均弹出 `账号入口`;关闭登录后点击 `画布背景色` 打开 `画布背景设置` 面板,点击 `暖灰` 后画布背景为 `rgb(243, 240, 234)`;登录开发账号后上传图片成功进入 `项目素材`,`AI画布工具栏` 保持可见。 -- 2026-06-17 前端拆分第二执行批次:新增 `ImageCanvasSidebarView`,把素材 / 图层共用左侧整合面板从主视图抽出;上传链路、登录弹窗、素材拖到画布、持久化、图层历史和右键菜单状态机仍保留在主视图,避免过度拆分。验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/ImageCanvasEditorPrimitives.test.tsx`、`npm run typecheck`。 -- 2026-06-17 侧栏拆分浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录刷新弹出 `账号入口`;`画布背景色` 打开 `画布背景设置` dialog,包含预设、自定义颜色、HEX 和恢复默认;使用临时开发账号登录后上传图片成功进入 `项目素材`,点击素材可添加到画布,切换 `图层` 侧栏后能看到同一图片图层,`AI画布工具栏` 保持可见。 -- 2026-06-17 前端拆分第三执行批次:新增 `ImageCanvasStageView`,把画布工作区视觉树、图层渲染、生成占位框、右键菜单、左下 dock、小地图和底部 AI 工具栏从主视图抽出;拖拽 / 缩放、历史、上传、登录、生成提交、素材持久化和右键命令仍保留在主视图,避免拆散状态机。 -- 2026-06-17 舞台拆分浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录刷新弹出 `账号入口`;关闭登录后点击 `画布背景色` 打开完整 `画布背景设置` dialog,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)`;使用临时开发账号密码登录后上传 `smoke.png` 成功进入 `项目素材`,点击素材添加到画布,切换 `图层` 后显示同一图层,图片浮动工具栏、小地图和 `AI画布工具栏` 保持可见。 -- 2026-06-17 前端拆分第四执行批次:新增 `ImageCanvasGenerationComposerView`,把生成图片、生成规范、生成角色形象、生成图标素材、快速编辑、角色动画和修改图片弹窗从主视图抽出;生成提交、上传 input、引用选择、占位框拖拽、结果回写、历史和画布状态机仍保留在主视图。验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/ImageCanvasEditorPrimitives.test.tsx`、`npm run typecheck`。 -- 2026-06-17 生成面板拆分浏览器回归:`http://127.0.0.1:10003/editor/canvas` 清空浏览器数据后未登录刷新弹出 `账号入口`;关闭登录后 `画布背景色` 打开 `画布背景设置`,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)`;点击 `生成工具` 后画布显示 `Image Generator` 占位框和 `生成图片` 跟随对话框,`AI画布工具栏` 保持可见;使用临时开发账号密码登录后上传素材成功,点击素材可添加到画布,切换 `图层` 面板可看到对应图层。 -- 2026-06-17 前端拆分第五执行批次:新增 `ImageCanvasLayerCommandModel`,把右键图层目标解析、复制 / 粘贴 / 创建副本、层级移动、分组 / 解组、显隐、锁定、翻转和删除的数据规则从主视图抽出;主视图只保留历史、选中态、菜单关闭、元数据清理和导出下载副作用。验证命令:`npm run test -- src/components/image-editor/ImageCanvasLayerCommandModel.test.ts src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/ImageCanvasEditorPrimitives.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录刷新弹出 `账号入口`,背景入口打开完整 `画布背景设置` 面板;登录后上传素材成功,点击素材可加入画布,图片右键打开 `图片功能面板`,创建副本、水平翻转、锁定和隐藏均生效,`AI画布工具栏` 保持可见。 -- 2026-06-17 前端拆分第六执行批次:新增 `ImageCanvasInteractionModel`,把适合视图、中心缩放、普通滚轮纵向滚动、Ctrl / Cmd 滚轮缩放、坐标换算、框选命中、平移、生成占位框拖拽、图层拖拽吸附、小地图投影、小地图点击定位和小地图拖拽视图移动的纯规则从主视图抽出;主视图保留事件、pointer capture、history、生成对象回写、选中态和状态更新。验证命令:`npm run test -- src/components/image-editor/ImageCanvasInteractionModel.test.ts src/components/image-editor/ImageCanvasEditorModel.test.ts src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/ImageCanvasEditorPrimitives.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 登录态刷新后素材、画布图层、小地图和 `AI画布工具栏` 保持可见,Ctrl 滚轮从 110% 缩放到 121%,普通滚轮不改变缩放,浏览器控制台无 passive wheel 错误。 -- 2026-06-17 新增素材持久化修正:素材库图片、上传到画布、生成图、修改图和图标素材加入画布时会先用当前图层快照更新本地画布,再在资源创建完成后立刻保存带真实 `resourceId` 的 layout,避免资源创建异步返回时把空 `layers` 写回工程。验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录弹出 `账号入口`,登录后上传素材、点击素材加入画布并刷新,画布图片和 `AI画布工具栏` 均保持可见。 -- 2026-06-17 前端拆分第七执行批次:新增 `useCanvasHistory`,把画布历史快照、撤销、重做、历史栈长度限制和 `canUndo` / `canRedo` 派生状态从主视图抽出;主视图只在具体动作前捕获历史,并注入恢复快照后的菜单 / hover / 框选 / 拖拽清理。验证命令:`npm run test -- src/components/image-editor/useCanvasHistory.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`。 -- 2026-06-17 前端拆分第八执行批次:新增 `useImageCanvasProjectPersistence`,把项目加载、`projectId` 状态、未就绪资源队列、工程资源创建、资源创建后即时保存和 450ms 自动保存从主视图抽出;新增 hook 单测锁定新增图层资源创建后保存真实 `resourceId` 的 layout。验证命令:`npm run test -- src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`。 -- 2026-06-17 前端拆分第九执行批次:新增 `useCanvasGenerationDialogs`,把画布生成对象的 active / inactive 注册表、归档、激活、按 id 更新 / 删除、按图层清理和生成中最新占位框查询从主视图抽出;主视图继续保留生成提交、结果落图、quick edit 和跨图层副作用。同步把 `画布背景设置` 调整为 Lovart 式紧凑色板弹层。验证命令:`npm run test -- src/components/image-editor/useCanvasGenerationDialogs.test.tsx src/components/image-editor/useCanvasHistory.test.tsx src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 清空会话后未登录弹出 `账号入口`,关闭后点击 `画布背景色` 显示色域、色相条、圆形预设和 HEX 输入,点击 `生成工具` 后画布显示 `Image Generator` 占位框和 `生成图片` 对话框,`AI画布工具栏` 保持可见。 -- 2026-06-17 前端拆分第十执行批次:新增 `useImageCanvasAssetLibrary`,把账号级素材库加载、文件夹新建 / 折叠 / 重命名 / 删除、素材重命名 / 删除、素材选择模式、框选、多选删除、素材拖到文件夹和素材库 401 登录弹窗从主视图抽出;主视图继续保留上传读取、上传进度、拖到画布坐标、画布图层创建和工程资源持久化。新增 hook 单测覆盖素材库归一化、401 登录、新建文件夹临时 id 替换、素材移动、删除回调和多选删除。验证命令:`npm run test -- src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录刷新弹出 `账号入口`,背景面板点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,点击 `生成工具` 后生成占位和 `生成图片` 对话框出现且 `AI画布工具栏` 保持可见;登录临时开发账号后上传图片成功进入 `项目素材`,点击素材加入画布,切换 `图层` 可看到对应图层,控制台无前端 error。 -- 2026-06-17 前端拆分第十一执行批次:新增 `ImageCanvasFileModel` 和 `useImageCanvasUploadWorkflow`,把隐藏上传 input、上传目标分发、未登录续传、上传占位卡片、素材落库、拖到画布建层、生成参考图上传从主视图抽出;主视图保留画布 drop 外层判断和项目资源持久化注入。验证命令:`npm run test -- src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录刷新弹出 `账号入口`,登录临时开发账号后 `画布背景设置` 面板点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,点击 `生成工具` 后显示 `Image Generator` 占位框和 `生成图片` 对话框且 `AI画布工具栏` 保持可见;上传图片后素材数增加,点击素材加入画布,切换 `图层` 面板可看到 2 个图层,登录后控制台无前端 error。 -- 2026-06-17 前端拆分第十二执行批次:新增 `ImageCanvasGenerationLayerModel`,把普通生图、修改图片、快速编辑和图标素材批量生成结果落画布的图层 id、临时 resourceId、标题、位置、原始分辨率尺寸、zIndex、source metadata、源图关联和 `generationInputs` 纯规则从主视图抽出;主视图继续负责 API 提交、生成对象状态、资源持久化、选中态、侧栏和适合视图副作用。验证命令:`npm run test -- src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 清空会话后未登录刷新弹出 `账号入口`,登录临时开发账号后 `画布背景设置` 面板保留色相 / 自定义颜色 / 预设 / HEX / 恢复默认,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,点击 `生成工具` 后显示 `Image Generator` 占位框和 `生成图片` 对话框且 `AI画布工具栏` 保持可见;真实上传图片后素材数从 2 增至 3,登录后控制台无前端 error。 -- 2026-06-17 前端拆分第十三执行批次:新增 `useImageCanvasAssetExportWorkflow`,把画布素材导出状态、单图右键导出、整包 ZIP 组包、图片去重、读取失败记录、metadata / manifest 和下载链接副作用从主视图抽出;主视图保留右键目标解析和状态提示渲染。验证命令:`npm run test -- src/components/image-editor/useImageCanvasAssetExportWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 清空会话后未登录刷新弹出 `账号入口`,登录临时开发账号后下载按钮启用,点击后触发真实下载 `未命名画布-画布素材-20260617.zip` 并显示导出状态;背景设置点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,点击 `生成工具` 后 `生成图片` 对话框出现且 `AI画布工具栏` 保持可见,登录后控制台无前端 error。 -- 2026-06-17 前端拆分第十四执行批次:新增 `useImageCanvasLayerCommands`,把画布剪贴板、右键目标解析、复制 / 剪切 / 粘贴、创建副本、层级移动、分组 / 解组、显隐、锁定、翻转、删除选中图层、按 id 删除和单图导出委托从主视图抽出;主视图保留菜单定位、画布事件、生成、上传、项目持久化和实际导出下载。验证命令:`npm run test -- src/components/image-editor/useImageCanvasLayerCommands.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 清空会话后未登录刷新弹出 `账号入口`,关闭后 `画布背景色` 打开完整 `画布背景设置`,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,点击 `生成工具` 后 `Image Generator` 占位框、`生成图片` 对话框和 `AI画布工具栏` 均可见;登录临时开发账号后新标签素材、画布图层、返回项目入口、小地图和底部工具栏可见,控制台无前端 error。 -- 2026-06-17 前端拆分第十五执行批次:新增 `useImageCanvasGenerationWorkflow`,把生成入口、规范 / 角色 / 图标 / 修改 / 快速编辑 / 角色动画状态机、真实生成提交、结果落图、失败恢复和删除图层后的生成态清理从主视图抽出;主视图保留画布事件、浮层定位、上传、项目资源持久化和历史捕获。验证命令:`npm run test -- src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 清空会话后未登录刷新弹出 `账号入口`,关闭登录后 `画布背景色` 打开完整 `画布背景设置` 面板,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;点击 `生成工具` 后 `Image Generator` 占位框、`生成图片` 对话框和 `AI画布工具栏` 均可见;登录临时开发账号后上传素材成功,素材数增加,点击素材可加入画布,切换 `图层` 面板可看到对应图层,登录后控制台无前端 error。 -- 2026-06-17 上传鉴权回归修正:普通素材上传入口在未登录时先打开 `账号入口`,不再先弹系统文件选择器;登录后用户再次点击上传即可打开文件选择器,避免浏览器拦截登录后异步触发的系统选择器。拖拽 / 已选中文件的续传逻辑仍保留,角色 / 图标生成参考图仍作为本地引用上传,不强制登录。验证命令:`npm run test -- src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录刷新弹出 `账号入口`,`画布背景色` 打开完整 `画布背景设置`,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;未登录点击侧栏上传直接弹登录,不出现文件选择器;登录后再次点击上传可以打开文件选择器并上传成功,素材计数从 4 增至 5,`AI画布工具栏` 保持可见。 -- 2026-06-17 前端拆分第十六执行批次:新增 `useImageCanvasEditorChrome`,把项目标题 / 重命名、侧栏开关、当前工具、缩放菜单、背景设置、小地图和背景 HEX 状态从主视图抽出;主视图继续保留上传 / 生成 / 键盘 Escape 的跨工作流编排。新增 hook 单测覆盖重命名、鉴权登录、背景色输入、面板开关和工具状态;主视图从 2039 行降至 1966 行。验证命令:`npm run test -- src/components/image-editor/useImageCanvasEditorChrome.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`。 -- 2026-06-17 前端拆分第十七执行批次:新增 `useImageCanvasViewportControls`,把视口状态、画布尺寸、小地图投影、适合视图、中心缩放、滚轮语义、坐标换算和小地图移动从主视图抽出;主视图继续保留图层拖拽、框选、生成占位拖拽、上传 drop 和历史触发时机。验证命令:`npm run test -- src/components/image-editor/useImageCanvasViewportControls.test.tsx src/components/image-editor/ImageCanvasInteractionModel.test.ts src/components/image-editor/useCanvasHistory.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录刷新弹出 `账号入口`,登录后素材 / 画布 / 小地图和底部工具栏可见;普通滚轮不改变缩放,Ctrl 滚轮从 `100%` 到 `110%`;背景设置点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见,登录后控制台无前端 error。 -- 2026-06-17 前端拆分第十八执行批次:新增 `useImageCanvasStageInteractions`,把画布舞台 pointer 状态机、选择 / 框选、多选拖拽、生成占位拖拽、抓手 / Space 临时抓手 / 中键平移、小地图 click / drag 分流和吸附线状态从主视图抽出;主视图继续保留上传 drop、右键菜单、生成提交、项目持久化和工具栏动作分流。新增 hook 单测覆盖多选拖拽、框选、临时抓手、生成占位和小地图分流;主视图从 1802 行降至 1452 行。验证命令:`npm run test -- src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasViewportControls.test.tsx src/components/image-editor/ImageCanvasInteractionModel.test.ts src/components/image-editor/useCanvasHistory.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录刷新和未登录上传均弹出 `账号入口`,登录后素材 / 画布 / 小地图和底部工具栏保持可见;`画布背景设置` 点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;普通滚轮不改变缩放,Ctrl 滚轮从 `146%` 到 `161%`;抓手 / 文字 / 选择工具可连续切换;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见,关闭对话框后占位图保留,登录后控制台无前端 error。 -- 2026-06-17 前端拆分第十九执行批次:新增 `useImageCanvasCanvasDropWorkflow`,把画布区域 drag over / drag leave / drop 分流从主视图抽出,覆盖素材库图片拖入画布、本地文件拖入画布、无关拖拽不拦截、默认文件夹选择和画布遮罩清理;主视图继续注入素材建层、文件上传、drop 点换算和素材移动高亮清理。新增 hook 单测覆盖拖拽入画布细节,主视图从 1452 行降至 1405 行。验证命令:`npm run test -- src/components/image-editor/useImageCanvasCanvasDropWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasViewportControls.test.tsx src/components/image-editor/ImageCanvasInteractionModel.test.ts src/components/image-editor/useCanvasHistory.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 登录态刷新后素材 / 画布 / 小地图和底部工具栏可见,真实鼠标拖拽素材库图片到画布时出现 `添加到画布` 遮罩,松手后画布图层数量从 4 增至 5;`画布背景设置` 点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;抓手工具可切回选择工具,登录后控制台无前端 error。 -- 2026-06-17 前端拆分第二十执行批次:新增 `ImageCanvasMetadataModalView`,把图片信息弹窗从主视图抽出,承载图片类型、生成输入、参考图、模型、分辨率、Provider、Task 和 Object 信息渲染;主视图只保留 `metadataLayer` 状态和关闭回调。同步修复未登录进入编辑器时项目 / 素材接口抢跑 401、`重置画布视图` 点击事件误传给适合视图函数的问题。新增组件单测覆盖生成图 metadata、上传图 fallback 和关闭回调,新增 hook / 主视图测试覆盖未登录不请求受保护素材 / 工程数据和重置按钮回归;主视图从 1405 行降至 1337 行。验证命令:`npm run test -- src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/ImageCanvasMetadataModalView.test.tsx src/components/image-editor/useImageCanvasEditorChrome.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 清空会话后直接弹出 `账号入口`,且未登录状态下没有发起 `/api/editor/*` 请求;登录临时开发账号后 `重置画布视图` 无控制台错误,`画布背景设置` 保持 Lovart 式白色浮层,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)`,上传素材可加入画布,右上角图片信息按钮可打开不透明白底元数据弹窗,关闭后 `AI画布工具栏` 仍可见。 -- 2026-06-17 前端拆分第二十一执行批次:新增 `useImageCanvasKeyboardShortcuts`,把 Ctrl / Cmd + Z 撤销、Ctrl / Cmd + Shift + Z 重做、Shift 状态、Backspace / Delete 删除、Escape 关闭临时面板和 Space 临时抓手从主视图抽出;主视图继续注入图层删除、生成对话框、快速编辑和 chrome 面板 setter。新增 hook 单测覆盖输入框忽略快捷键、删除选中图层、删除生成占位、Escape 保留生成中面板、Space 和 Shift;主视图从 1337 行降至 1250 行。验证命令:`npm run test -- src/components/image-editor/useImageCanvasKeyboardShortcuts.test.tsx src/components/image-editor/ImageCanvasMetadataModalView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/components/image-editor/useImageCanvasCanvasDropWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasViewportControls.test.tsx src/components/image-editor/ImageCanvasInteractionModel.test.ts src/components/image-editor/useCanvasHistory.test.tsx src/components/image-editor/useImageCanvasEditorChrome.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10003/editor/canvas` 未登录直接弹出 `账号入口` 且未抢跑 `/api/editor/*`,登录后 `/api/editor/assets/library` 和 `/api/editor/projects/recent` 为 200,`AI画布工具栏` 与 `画布面板入口` 可见,viewport 背景为 `rgb(248, 250, 252)` 且 `background-image: none`;按住 Space 从 `文字工具` 临时切到 `抓手工具`,松开恢复 `文字工具`;`画布背景设置` 点击 `暖灰` 后背景变为 `rgb(243, 240, 234)`;点击 `生成工具` 后 `Image Generator` 占位框、`生成图片` 对话框和 `AI画布工具栏` 同时可见,登录后控制台无前端 error。 -- 2026-06-18 生成中占位图删除确认:画布生成占位框增加删除按钮,删除 `generating` 状态占位图时统一弹出 `删除生成中的占位图` 二次确认,并提示 `已消耗的泥点不会返还`;空闲占位仍直接删除。键盘 Backspace / Delete 删除生成占位也改走同一请求入口,避免绕过提示;确认删除后清理选中态、右键菜单并切回选择工具,已删除的生成任务即使后续返回结果也不会落图。验证命令:`npm run test -- src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasKeyboardShortcuts.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:本地 Vite + Chrome CDP 打开 `/editor/canvas`,点击 `生成图片` 创建生成中占位,删除按钮弹出确认框,取消后占位保留,确认后占位移除且提示包含泥点不返还。 -- 2026-06-17 前端拆分第二十二执行批次:新增 `useImageCanvasAssetPointerDragBridge`,把素材卡片 pointer 拖拽到画布 / 文件夹的全局监听、拖拽激活、画布 drop 提示、文件夹高亮、移动素材、加入画布和点击抑制从主视图抽出;主视图继续负责素材库事实、画布建层、历史和工程资源持久化。同步恢复 `账号入口` 认证弹窗 portal 渲染,避免全屏画布遮住登录弹窗;`画布背景设置` 调整为独立白色浮层,包含当前色、色域、色相、自定义颜色、预设网格、HEX 输入和恢复默认。验证命令:`npm run test -- src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasKeyboardShortcuts.test.tsx src/components/image-editor/ImageCanvasMetadataModalView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/components/image-editor/useImageCanvasCanvasDropWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasViewportControls.test.tsx src/components/image-editor/ImageCanvasInteractionModel.test.ts src/components/image-editor/useCanvasHistory.test.tsx src/components/image-editor/useImageCanvasEditorChrome.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/auth/PlatformAuthModalShell.test.tsx src/components/auth/AuthGate.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 未登录打开直接显示 `账号入口`;登录临时开发账号后 `画布背景设置` 显示当前色、色域、色相、自定义颜色、预设、HEX 和恢复默认,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;上传图片进入 `项目素材`,真实 pointer 拖拽素材到画布后图层数从 0 到 1 且 `AI画布工具栏` 保持可见;新建 `SmokeFolder` 后真实 pointer 拖拽素材到文件夹,`项目素材` 变 0、`SmokeFolder` 变 1,素材执行移动而非拷贝。控制台仅有未登录 refresh 401,登录后编辑器 API 均为 200。 -- 2026-06-17 前端拆分第二十三执行批次:新增 `ImageCanvasOverlayModel`,把生成输入框锚定、图标素材生成面板宽度、选中图片工具栏边界、快速编辑面板和角色动画面板定位从主视图抽出为纯模型;主视图继续保留生成 / quick edit / 角色动画状态机和舞台编排。新增模型单测覆盖锚定优先级、生成中隐藏、icon 宽度、工具栏 clamp、quick edit / 角色动画边界和生成 dialog 模式识别;主视图从 1182 行降至 1133 行。验证命令:`npm run test -- src/components/image-editor/ImageCanvasOverlayModel.test.ts src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run test -- src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasEditorChrome.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasOverlayModel.test.ts src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasKeyboardShortcuts.test.tsx src/components/image-editor/ImageCanvasMetadataModalView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/components/image-editor/useImageCanvasCanvasDropWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasViewportControls.test.tsx src/components/image-editor/ImageCanvasInteractionModel.test.ts src/components/image-editor/useCanvasHistory.test.tsx src/components/image-editor/useImageCanvasEditorChrome.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/auth/PlatformAuthModalShell.test.tsx src/components/auth/AuthGate.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 未登录打开显示 `账号入口`,登录后 `画布背景设置` 点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见;素材库已有素材真实 pointer 拖入画布后图层数从 0 到 1,工具栏保持可见,截图留存于 `output/playwright/editor-overlay-model-regression-20260617.png`。 -- 2026-06-17 前端拆分第二十四执行批次:新增 `useImageCanvasAssetCanvasBridge`,把删除素材清理画布图层、素材加入画布、素材 pointer 拖入画布 / 文件夹、画布 drag/drop 分流和文件拖入画布参数组装从主视图抽成素材到画布桥接 hook;主视图继续保留素材库事实、上传读取、工程资源持久化和历史触发。新增 hook 单测覆盖素材建层、pointer drop 入画布和删除素材清理关联图层 / 选中态;主视图从 1133 行降至 1086 行。验证命令:`npm run test -- src/components/image-editor/useImageCanvasAssetCanvasBridge.test.tsx src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasCanvasDropWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 清空会话后未登录直接显示 `账号入口`;登录临时开发账号后 `画布背景设置` 是完整设置面板,包含当前色、色域、色相、自定义颜色、预设、HEX 和恢复默认,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,HEX 输入 `#ffffff` 后变为白色,按 Escape 关闭面板;登录后上传图片请求 `/api/editor/assets` 返回 200,素材库出现上传素材,`AI画布工具栏` 保持可见。 -- 2026-06-17 前端拆分第二十五执行批次:新增 `ImageCanvasStageControllerModel` 和 `useImageCanvasStageController`,把舞台派生状态、生成 / 选中浮层位置、右键菜单目标、空白画布右键、图层右键和清空画布焦点从主视图抽出;主视图继续保留工具切换、上传 / 生成入口、图层命令、项目持久化和舞台 pointer 状态机。新增模型和 hook 单测覆盖选中 / 生成锚定、右键菜单位置、显示 / 解锁判断、清空焦点和空白 / 图层右键菜单;主视图从 1086 行降至 993 行。验证命令:`npm run test -- src/components/image-editor/ImageCanvasStageControllerModel.test.ts src/components/image-editor/useImageCanvasStageController.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/useImageCanvasEditorChrome.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/routing/appPageRoutes.test.ts`、`npm run typecheck`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 清空会话后未登录直接显示 `账号入口`,关闭登录后 `画布背景色` 打开完整 `画布背景设置` dialog,包含色相、自定义颜色、预设、HEX 和恢复默认;点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,`AI画布工具栏` 保持可见,截图留存于 `output/playwright/editor-stage-controller-smoke-20260617.png`。 -- 2026-06-17 前端拆分第二十六执行批次:新增 `ImageCanvasTopbarView`,把返回项目入口、项目标题展示 / 重命名表单、下载画布素材按钮和导出状态提示从主视图抽出;主视图继续保留 chrome hook、项目持久化、导出工作流和实际导出副作用。新增组件单测覆盖返回入口、标题编辑入口、重命名提交 / 取消、导出按钮禁用 / 启用和导出状态提示;主视图从 993 行降至 905 行。验证命令:`npm run test -- src/components/image-editor/ImageCanvasTopbarView.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/useImageCanvasAssetExportWorkflow.test.tsx src/components/image-editor/useImageCanvasEditorChrome.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 未登录直接显示 `账号入口`,顶栏返回项目入口、项目名、`画布` 标签和下载按钮均可见;关闭登录后打开 `画布背景设置`,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,`AI画布工具栏` 保持可见,截图留存于 `output/playwright/editor-topbar-smoke-20260617.png`。 -- 2026-06-17 前端拆分第二十七执行批次:新增 `useImageCanvasGenerationSurface`,把生成 Composer JSX、生成工具切换分流、普通生图 / 图标生成 / 快速编辑 / 角色动画浮层定位从主视图抽出;`useImageCanvasGenerationWorkflow` 继续负责生成状态机和真实 API 提交。同步移除 `ImageCanvasStageControllerModel` 中重复的生成锚点 / Composer 位置派生,避免舞台控制器和生成表面重复持有生成浮层职责;主视图从 905 行降至 793 行。rebase 到远端 `支持规范参考图输入` 后,生成表面继续透传角色形象规范和常规参考图入口,并把左下 dock / 底部工具栏层级提到 Composer 之上,避免生成输入框盖住常用工具和背景面板。验证命令:`npm run test -- src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/ImageCanvasStageControllerModel.test.ts src/components/image-editor/useImageCanvasStageController.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 未登录直接显示 `账号入口`,关闭登录后 `画布背景设置` 保持完整面板,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见,再点击 `生成角色形象` 能打开包含 `角色形象规范` 和 `常规参考图` 的对话框,控制台仅有未登录 refresh 401。 -- 2026-06-17 上传侧栏回归修正:上传工作流移除上传到画布后强制切换 `图层` 侧栏的副作用,保留新增素材卡、创建画布图层和选中新图层。验证命令:`npm run test -- src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 登录后点击 `上传到项目素材` 上传图片,左侧仍显示 `素材` 且 `打开素材` 为 pressed;把图片文件 drop 到 `画布工作区` 后素材库和画布图层均出现 `canvas-drop-sidebar-smoke.png`,新图层被选中,`打开素材=true`、`打开图层=false`,`AI画布工具栏` 保持可见,登录后控制台无 error。 -- 2026-06-17 前端拆分第二十八执行批次:继续收口 `ImageCanvasGenerationComposerView`,新增 `ImageCanvasGenerationImageOptionsView`、`ImageCanvasSpecGenerationPanelView`、`ImageCanvasIconSpritesheetComposerView`、`ImageCanvasQuickEditPanelView` 和 `ImageCanvasCharacterAnimationPanelView`,把图片生成参数、生成规范、图标素材生成、快速编辑图片和角色动画面板从 Composer 内联 JSX 抽出;Composer 降至 707 行,继续保留生成模式分流、角色引用菜单 portal 和修改图片弹窗编排。新增子视图单测覆盖参数切换、规范表单、图标规范菜单 / 描述列表、快速编辑和角色动画状态。验证命令:`npm run test -- src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 未登录显示 `账号入口`,关闭后点击 `生成工具` 能看到 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏`;点击 `生成角色形象` 能看到 `生成角色形象` 面板和 `角色形象规范`;点击 `生成规范` 后选择 `角色形象规范` 能打开 `生成规范` 面板并显示 `提交生成规范`;点击 `生成图标素材` 能打开 `生成图标素材` 面板、图标规范操作和素材描述列表,控制台仅有未登录 refresh 401。 -- 2026-06-17 前端拆分第二十九执行批次:继续收口 `ImageCanvasStageView`,新增 `ImageCanvasBottomToolbarView`、`ImageCanvasPanelDockView`、`ImageCanvasContextMenusView` 和 `ImageCanvasSelectedLayerToolbarView`,把底部 AI 工具栏、左下缩放 / 背景 / 小地图控制坞、画布 / 图片右键菜单和选中图片浮动工具栏从 StageView 内联 JSX 抽出;StageView 降至 538 行,继续保留画布世界、图层和生成占位渲染,所有 pointer / 多选 / 拖拽 / 生成状态机仍在既有 hook 中。新增子视图单测覆盖工具切换、缩放 / 背景 / 小地图控制、右键菜单命令和选中图片工具栏接线。验证命令:`npm run test -- src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录弹出 `账号入口`,关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框、`画布面板入口` 和 `AI画布工具栏` 均可见;点击 `生成规范` 后页面级 `生成规范类型` 菜单可见。控制台仅有预期的未登录 `/api/auth/refresh` 401,截图留存于 `output/playwright/editor-stage-view-split-smoke-20260617.png`。 -- 2026-06-17 前端拆分第三十执行批次:新增 `ImageCanvasEditorShellView`,把编辑器最外层 section、隐藏上传 input、素材拖拽预览、侧栏 / 顶栏 / 舞台 / 元数据弹窗组合从 `ImageCanvasEditorView` 抽成页面壳;主视图继续保留所有 hook 状态编排、上传 / 生成 / 拖拽 / 项目持久化和跨模块副作用,只把已经组装好的 `sidebarProps`、`topbarProps`、`stageProps` 和 `metadataProps` 交给 shell 渲染。新增 shell 单测覆盖上传 input、拖拽预览坐标兜底、顶栏 / 舞台 / 工具栏 / 元数据弹窗装配;主视图降至 777 行。验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`,关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`返回项目页面`、`画布面板入口` 和 `AI画布工具栏` 均可见;点击 `生成工具` 后 `Image Generator` 和 `生成图片` 对话框可见;点击 `生成规范` 后页面级 `生成规范类型` 菜单可见。控制台仅有预期的未登录 `/api/auth/refresh` 401,截图留存于 `output/playwright/editor-shell-split-smoke-20260617.png`。 -- 2026-06-17 前端拆分第三十一执行批次:继续收口 `ImageCanvasSidebarView`,新增 `ImageCanvasAssetLibraryPanelView` 和 `ImageCanvasLayerPanelView`,把素材库文件夹 / 拖拽上传 / 素材选择模式与图层列表 / 右键入口拆成两个完整 surface;侧栏外壳只保留标题、计数和当前 tab 分流。同步把 `ImageCanvasEditorView.test.tsx` 中纯侧栏输入框 chrome 断言迁到 `ImageCanvasSidebarView.test.tsx`,保留主视图重命名、建文件夹、上传、删除、API 调用和画布集成断言。验证命令:`npm run test -- src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/useImageCanvasEditorChrome.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx -t "switches the shared sidebar between assets and layers"`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 2026-06-17 前端拆分第三十二执行批次:继续收口 `ImageCanvasGenerationComposerView`,新增 `ImageCanvasBasicGenerationComposerView`、`ImageCanvasCharacterGenerationComposerView` 和 `ImageCanvasEditGenerationModalView`,把普通生图跟随框、角色形象生成面板和修改图片弹窗从 Composer 内联 JSX 中抽出;Composer 降至 312 行,只保留生成模式分流、portal 菜单和各面板装配。新增三组子视图单测覆盖普通生图 prompt / 参考图 / 提交 / 关闭、角色参考图菜单 / 状态恢复 / 提交、修改图片弹窗提示词 / 失败 / 关闭。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口` 且控制台仅有预期 `/api/auth/refresh` 401;关闭登录后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`打开图层` 切换后侧栏显示 `图层`,`AI画布工具栏` 仍可见;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和底部工具栏均可见。 -- 2026-06-17 前端拆分第三十三执行批次:继续收口 `ImageCanvasAssetLibraryPanelView`,新增 `ImageCanvasAssetFolderSectionView` 和 `ImageCanvasAssetRowView`,把素材库文件夹头 / 文件夹 drop 区域、素材卡片 / 上传进度 / 重命名 / 选择模式从素材库父面板中拆成两个完整 surface;素材库父面板降至 279 行,只保留素材列表容器、新建文件夹表单、批量操作栏和框选遮罩。新增素材行单测覆盖普通点击加入画布、选择模式改为选中、重命名 Enter 提交和上传中禁用 / 进度显示。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口` 且控制台仅有预期 `/api/auth/refresh` 401;默认素材栏显示 `项目素材` 文件夹、上传入口和底部 `AI画布工具栏`;关闭登录后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`打开图层` 切换后侧栏显示 `图层`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和底部工具栏均可见。 -- 2026-06-17 前端拆分第三十四执行批次:继续收口 `ImageCanvasStageView`,新增 `ImageCanvasWorldView`,把画布世界表面、吸附参考线、可见图层排序 / 悬浮 / 选中 / 锁定 / 生成态、元数据角标、框选矩形、生成占位框和浮动生成状态从 StageView 内联 JSX 中抽出;StageView 降至 324 行,继续保留 viewport 宿主、drop overlay、左下 dock、底部工具栏、右键菜单和选中图片工具栏装配。新增 world view 单测覆盖隐藏图层过滤、悬浮尺寸、生成态、元数据按钮、吸附线、框选矩形和生成占位框事件。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasWorldView.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`,`AI画布工具栏` 保持可见;`打开图层` 切换后侧栏显示 `图层`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和底部工具栏均可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第三十五执行批次:继续收口 `useImageCanvasGenerationWorkflow`,新增 `ImageCanvasGenerationSubmissionModel`,把普通生图、修改图片、规范生成和角色形象生成的请求 payload、标准化 prompt、结果图层标题 / assetKind 和 generationInputs 快照构建从 workflow hook 中抽成纯模型;workflow hook 保留对话状态、真实 API 调用、图片引用解析、结果落图、选中和 fit 副作用,避免拆散生成生命周期。新增模型单测覆盖普通生图、修改图、带参考图的规范生成、带规范 / 常规参考图的角色生成和缺失源图异常;`useImageCanvasGenerationWorkflow` 从 1167 行降至 1104 行。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第三十六执行批次:继续收口 `useImageCanvasUploadWorkflow`,新增 `ImageCanvasUploadModel`,把上传目标文件夹解析、上传中素材占位卡、上传到画布的临时图层、无效 drop 坐标兜底和图片真实尺寸回填坐标计算从 hook 中抽成纯模型;upload workflow hook 保留登录恢复、文件读取、真实素材创建 API、上传进度状态和生成面板参考图写入副作用。新增模型单测覆盖文件夹兜底、占位素材、画布落点、非法坐标兜底和真实尺寸修正;`useImageCanvasUploadWorkflow` 从 546 行降至 510 行。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框、`上传到项目素材` 入口和 `AI画布工具栏` 均可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第三十七执行批次:继续收口 `useImageCanvasAssetLibrary`,新增 `ImageCanvasAssetLibraryModel`,把素材分组、可选择素材筛选、全选状态、素材 / 文件夹重命名、文件夹折叠、本地新建文件夹占位、持久化文件夹替换、本地删除素材、删除文件夹回默认文件夹、选择集合切换、批量删除和本地移动素材到文件夹从 hook 中抽成纯模型;asset library hook 继续保留加载账号素材库、后端 CRUD 调用、登录弹窗、DOM 框选和素材拖拽命中生命周期。新增模型单测覆盖分组 / 选择、重命名 / 折叠 / 本地文件夹、本地文件夹持久化替换、删除文件夹回默认文件夹、全选 / 批量删除和本地移动;`useImageCanvasAssetLibrary` 从 609 行降至 573 行。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/useImageCanvasAssetLibrary.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`打开图层` 切换后侧栏显示 `图层`,点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见;切回 `打开素材` 后侧栏显示 `素材` 且 `上传到项目素材` 入口可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第三十八执行批次:继续收口 `useImageCanvasGenerationWorkflow`,扩展 `ImageCanvasGenerationSubmissionModel`,把图标素材批量生成的规范校验 / 描述清洗 / 请求 payload / generationInputs,以及角色动画生成的 prompt 清洗 / objectKey 优先源图 / 尺寸 / 价格 / 模型参数从 workflow hook 中抽成纯模型;workflow hook 继续保留对话状态、真实 API 调用、生成结果落图、失败恢复和角色动画面板生命周期。新增模型单测覆盖图标缺少规范、图标空描述、图标描述 trim / 参考快照,以及角色动画 trim、objectKey 源图和价格计算;`useImageCanvasGenerationWorkflow` 从 1104 行降至 1075 行。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`打开图层` 切换后侧栏显示 `图层`,点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见;点击 `生成图标素材` 后 `Icon Generator` 占位和 `生成图标素材` 面板可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第三十九执行批次:开始拆分 `ImageCanvasEditorView.test.tsx` 巨型集成测试,新增 `ImageCanvasEditorView.test-utils` 共享默认工程 / 素材库 mock、认证上下文、pointer / dataTransfer / deferred helper 和生命周期 setup;新增 `ImageCanvasEditorAssetsIntegration.test.tsx`,把素材库默认文件夹去重、文件夹折叠 / 新建 / 重命名 / 删除、素材重命名 / 拖拽移动、多文件上传、未登录续传、上传占位、401 登录、素材选择模式、删除素材同步清理画布图层、素材框选、画布 drop 上传和素材库拖入画布等集成用例从主测试文件迁出;`ImageCanvasEditorView.test.tsx` 从 4817 行降至 3741 行。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`打开图层` 切换后侧栏显示 `图层`,点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第四十执行批次:继续拆分 `ImageCanvasEditorView.test.tsx` 巨型集成测试,新增 `ImageCanvasEditorGenerationIntegration.test.tsx`,把画布生图占位 / 生成提交、生成错误与未登录、规范生成、角色形象生成、图标素材生成、角色动画、快速编辑、生成图元数据和修改结果等生成相关集成用例从主测试文件迁出;`ImageCanvasEditorView.test.tsx` 从 3741 行降至 1419 行,主测试保留工程加载、导出、画布基础交互、右键菜单、侧栏、缩放、小地图、工具切换、吸附和历史。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`打开图层` 切换后侧栏标题为 `图层`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第四十一执行批次:继续收口 `useImageCanvasGenerationWorkflow`,新增 `ImageCanvasGenerationDialogModel`,把普通生图 / 规范 / 角色形象 / 图标素材生成对话框草稿、修改图片 / 快速编辑 / 角色动画面板草稿、角色 / 图标参考选择、规范表单更新、图标描述更新、角色动画时长更新以及生成器失焦 / 关闭规则从 hook 中抽成纯模型;workflow hook 保留真实 API 调用、生成结果落画布、侧栏 / 工具 / 选中态副作用和错误回写。新增模型单测覆盖各类草稿、失败态清理、引用选择、描述限制、动画时长和 composer 可见性;`useImageCanvasGenerationWorkflow.ts` 从 1075 行降至 870 行。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`打开图层` 切换后侧栏标题为 `图层`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第四十二执行批次:继续收口 `useImageCanvasStageInteractions`,新增 `ImageCanvasStageInteractionModel`,把 pointer button / client / id 归一化、画布框选初始状态、抓手平移拖拽状态、多选图层选择与图层拖拽初始状态、生成器 composer 随图层点击显隐、生成占位拖拽状态、小地图拖拽状态和拖拽阈值从 hook 中抽成纯模型;stage hook 保留 DOM 事件拦截、pointer capture / release、React 状态写入、拖拽移动执行和回调副作用。新增模型单测覆盖 pointer 兜底、中键识别、框选 / 平移状态、多选 toggle、组拖拽初始层快照、生成器 composer 规则、生成占位状态和小地图 click / drag 分流;`useImageCanvasStageInteractions.ts` 从 610 行降至 521 行。只读子代理复核结论:当前没有同一轮必须顺手拆的第二个明显大块,`ImageCanvasEditorView.tsx` 已主要是组合层,generation / asset / upload hooks 剩余复杂度多为异步编排或持久化副作用,后续应随具体需求再拆,避免过度碎片化。统一验证命令:`npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/useImageCanvasStageInteractions.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;`打开图层` 切换后侧栏标题为 `图层`;点击 `生成工具` 后 `Image Generator`、`生成图片` 对话框和 `AI画布工具栏` 均可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第四十三执行批次:继续收口 `useImageCanvasGenerationWorkflow`,新增 `useImageCanvasGenerationSubmissionWorkflow`,把普通生图 / 修改图 / 图标素材批量生成 / 快速编辑 / 角色动画的提交 API、提交中 / 失败 / 完成状态回写、生成结果落画布、选中图层、切换图层侧栏、适合视图和 last image model 记忆从入口 workflow 中抽成生成提交流水线 hook;原 workflow 保留生成入口、菜单开关、画布选取引用、表单字段更新、生成器关闭和删除图层后的状态清理,避免把 UI 选择态和提交态混在一起。新增 hook 单测覆盖 quick edit 成功 / 失败、edit 成功清理 modal、生成使用最新移动占位、icon 缺规范校验、icon 成功批量落图并记住模型、角色动画 completed / failed 状态机;同步修复新测试文件的 mock 隔离,避免 `vi.clearAllMocks()` 清空并行集成测试的调用记录;`useImageCanvasGenerationWorkflow.ts` 从 870 行降至 499 行。统一验证命令:`npm run test -- src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx`、`npm run test -- src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`;浏览器回归:`http://127.0.0.1:10007/editor/canvas` 临时 `XDG_CONFIG_HOME` 下 Chrome headless 打开成功,未登录显示 `账号入口`;关闭后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;点击 `生成工具` 后 `Image Generator` 占位、`生成图片` 对话框和 `AI画布工具栏` 均可见,控制台仅有预期的未登录 `/api/auth/refresh` 401。 -- 2026-06-17 前端拆分第四十四执行批次:继续收口 `useImageCanvasAssetLibrary`,扩展 `ImageCanvasAssetLibraryModel`,把素材文件夹坐标命中、素材拖拽目标文件夹置顶判断、素材框选起点 / 移动 / 反向拖拽矩形归一化、框选只命中 uploaded 素材和框选启动规则从 hook 中抽成纯几何模型;asset library hook 保留 DOM 查询、dataset 读取、pointer capture / release、React 状态写入、后端 CRUD 和登录弹窗副作用,避免把 DOM 与服务调用塞进模型。新增模型单测覆盖文件夹边界命中、列表外返回空、文件夹 header 视野外置顶、反向框选归一化、边缘相交命中、忽略 built-in / unknown 素材;只读子代理复核同意优先抽 Rect/Point + folder hit + pinned + marquee selection,不继续拆新 hook。验证命令:`npm run test -- src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/useImageCanvasAssetLibrary.test.tsx`、`npm run test -- src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasAssetCanvasBridge.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx`。 -- 2026-06-17 前端拆分第四十四执行批次验证补充:统一编辑器回归命令 `npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasAssetCanvasBridge.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx` 通过 33 个文件 / 219 个测试;`npm run typecheck`、`npm run check:encoding`、`git diff --check` 均通过。浏览器回归:`http://127.0.0.1:10007/editor/canvas` 使用 Playwright CLI headless 打开成功,未登录显示 `账号入口`;关闭登录后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;默认素材侧栏显示 `素材` / `项目素材` / `上传到项目素材`,切换 `打开图层` 后侧栏显示 `图层`,点击 `生成工具` 后 `Image Generator` 占位、`生成图片` 对话框和 `AI画布工具栏` 均可见;网络请求仅有预期未登录 `/api/auth/refresh` 401,其余 editor smoke 相关请求正常。 -- 2026-06-17 前端拆分第四十五执行批次:继续收口 `useImageCanvasUploadWorkflow`,扩展 `ImageCanvasUploadModel`,把生成参考图上传后的 dialog 状态转换从 hook 中抽成纯模型:统一创建上传参考图对象、将 failed 生成面板恢复为 idle、按 `spec-reference` / `character-spec` / `character-reference` / `icon-spec` 写入对应引用字段,并保持不匹配 dialog 不变;upload workflow hook 继续保留文件筛选、Data URL 读取、文件 input、未登录素材上传续传、真实素材创建 API、上传进度和画布落图副作用。新增模型单测覆盖参考图 fallback label、failed 状态清理、规范 / 角色 / 图标参考图写入和角色参考图追加;局部验证命令:`npm run test -- src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx`。 -- 2026-06-17 前端拆分第四十五执行批次验证补充:统一编辑器回归命令 `npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasAssetCanvasBridge.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx` 通过 33 个文件 / 223 个测试;`npm run typecheck`、`npm run check:encoding`、`git diff --check` 均通过。浏览器回归:`http://127.0.0.1:10007/editor/canvas` 使用 Playwright CLI headless 打开成功,未登录显示 `账号入口`;关闭登录后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;默认素材侧栏显示 `素材` / `项目素材` / `上传到项目素材`,切换 `打开图层` 后侧栏显示 `图层`,点击 `生成工具` 后 `Image Generator` 占位、`生成图片` 对话框和 `AI画布工具栏` 均可见;网络请求仅有预期未登录 `/api/auth/refresh` 401,其余 editor smoke 相关请求正常。只读子代理复核生成提交链路后建议暂停继续硬拆,除非后续新增生成模式再考虑按“生成成功后的落图提交事务”抽内部 hook。 -- 2026-06-17 前端拆分第四十六执行批次:继续收口 `useImageCanvasUploadWorkflow`,扩展 `ImageCanvasUploadModel`,把素材上传生命周期中的文件夹展开、读取成功 / 失败、上传中、持久化资产替换、上传失败、图片尺寸回写和画布图层绑定持久化素材抽成纯模型;upload workflow hook 继续保留文件筛选、Data URL 读取、登录弹窗、真实素材创建 API、Image 尺寸读取、画布落图和 React setter 编排。新增模型单测覆盖上传占位卡各阶段状态、持久化后清理上传态、尺寸回写和图层绑定;局部验证命令:`npm run test -- src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx`。 -- 2026-06-17 前端拆分第四十六执行批次验证补充:统一编辑器回归命令 `npm run test -- src/components/image-editor/ImageCanvasStageInteractionModel.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts src/components/image-editor/ImageCanvasAssetLibraryModel.test.ts src/components/image-editor/ImageCanvasUploadModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts src/components/image-editor/ImageCanvasAssetRowView.test.tsx src/components/image-editor/ImageCanvasSidebarView.test.tsx src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasCharacterGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx src/components/image-editor/ImageCanvasEditorShellView.test.tsx src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx src/components/image-editor/ImageCanvasPanelDockView.test.tsx src/components/image-editor/ImageCanvasContextMenusView.test.tsx src/components/image-editor/ImageCanvasSelectedLayerToolbarView.test.tsx src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx src/components/image-editor/ImageCanvasGenerationImageOptionsView.test.tsx src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasAssetLibrary.test.tsx src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasAssetPointerDragBridge.test.tsx src/components/image-editor/useImageCanvasAssetCanvasBridge.test.tsx src/components/image-editor/ImageCanvasEditorAssetsIntegration.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx src/components/image-editor/ImageCanvasEditorView.test.tsx` 通过 33 个文件 / 228 个测试;`npm run typecheck`、`npm run check:encoding`、`git diff --check` 均通过。浏览器回归:`http://127.0.0.1:10007/editor/canvas` 使用系统 Chrome headless 打开成功,未登录显示 `账号入口`;默认素材侧栏显示 `素材` / `项目素材`;关闭登录后 `画布背景设置` 可打开,点击 `暖灰` 后 viewport 背景为 `rgb(243, 240, 234)` 且 `background-image: none`;切换 `打开图层` 后侧栏显示 `图层`;点击 `生成工具` 后 `Image Generator` 占位、生成表单控件和 `AI画布工具栏` 均可见;除预期未登录 `/api/auth/refresh` 401 外无额外 API 失败或控制台错误。 diff --git a/UI_CODING_STANDARD.md b/UI_CODING_STANDARD.md index e7d8e0a30..89bbb2970 100644 --- a/UI_CODING_STANDARD.md +++ b/UI_CODING_STANDARD.md @@ -1,6 +1,6 @@ # UI Coding Standard -> **当前文档入口**:项目文档已压缩到 `docs/README.md` 和 4 份当前文档;UI 资产和 9-slice 规则以本文为准,平台级 UI 约束见 `docs/【项目基线】当前产品与工程约束-2026-05-15.md`。 +> **当前文档入口**:项目文档总入口为 `docs/README.md`;UI 资产和 9-slice 规则以本文为准,平台级 UI 约束见 `docs/【项目基线】当前产品与工程约束-2026-05-15.md`,专题方案只从总入口读取。 ## Goal diff --git a/docs/README.md b/docs/README.md index ed80b114f..7b24f1cda 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,76 +1,59 @@ # 文档总览 -`docs/` 只把当前融合文档和仍在维护的专题文档作为实现依据。旧创作模板、旧创作入口及其专属服务文档仅保留为历史材料,不再要求继续实现或兼容。 +本目录只把当前实现依据、公开契约和仍在维护的专题合同作为入口。代码、当前文档与项目记忆冲突时,以当前代码和最新专题文档为准;未列入下表的材料不作为实现依据。 ## 必读入口 1. [Agent 工作入口与执行准则](./【协作规范】Agent工作入口与执行准则-2026-06-22.md) 2. [当前产品与工程约束](./【项目基线】当前产品与工程约束-2026-05-15.md) 3. [server-rs 与 SpacetimeDB 数据契约](./【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md) -4. [平台入口与玩法链路](./【玩法创作】平台入口与玩法链路-2026-05-15.md) -5. [本地开发验证与生产运维](./【开发运维】本地开发验证与生产运维-2026-05-15.md) -6. [AI 游戏创作项目开发工作台 PRD](./prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md) -7. [AI 游戏创作智能体 App 实施计划](./technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md) -8. [客户端素材创作无限画布阶段一合同](./technical/【技术方案】客户端素材创作无限画布阶段一合同-2026-08-05.md) +4. [本地开发验证与生产运维](./【开发运维】本地开发验证与生产运维-2026-05-15.md) +5. [项目记忆入口](./project-memory/README.md) -团队长期约定、决策、流程和排障摘要统一从 [项目记忆入口](./project-memory/README.md) 读取。代码、当前融合文档与项目记忆冲突时,以代码和最新融合文档为准。 +## 当前产品与平台 -## 当前专题 +- [当前产品与工程约束](./【项目基线】当前产品与工程约束-2026-05-15.md):现役入口、账号钱包、UI 和后端分层。 +- [平台入口与玩法链路](./【玩法创作】平台入口与玩法链路-2026-05-15.md):只描述现役平台壳与旧模板退役边界。 +- [外部 OpenAPI 与 API Key 接入方案](./【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md) +- [External v1 OpenAPI](./openapi/genarrative-external-v1.openapi.json):公开 HTTP 契约唯一机器可读来源。 -### AI 游戏创作与 Agent Runtime +## AI 游戏创作与 Agent Runtime -- [AI 游戏创作智能体 App 实施计划](./technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md) -- [立项策划 Agent(Fast GDD)技术方案](<./technical/【技术方案】立项策划Agent(Fast GDD)-2026-08-10.md>) -- [AI 游戏创作 Agent Runtime V1.1](<./technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md>) +- [AI 游戏创作智能体 App 实施计划](./technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md):当前 DirectProject、受控语义工具、UI workflow、资源和运行时合同。 +- [项目开发工作台 PRD](./prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md):当前工作台页面和验收边界。 +- [立项策划 Agent(Fast GDD)](<./technical/【技术方案】立项策划Agent(Fast GDD)-2026-08-10.md>):当前策划入口、审批和恢复合同。 +- [GameAgent 资源自由画板与快速编辑](./technical/【技术方案】GameAgent资源自由画板与快速编辑-2026-08-20.md) +- [UI 工作流资源桥接与 Runtime 执行](./【技术方案】UI工作流资源桥接与Runtime执行-2026-08-24.md) +- [UI 编辑器 Godot 容器布局](./technical/【技术方案】UI编辑器Godot容器布局模型-2026-08-18.md) +- [UI 编辑器子节点显示规则](./technical/【技术方案】UI编辑器子节点显示规则-2026-08-18.md) +- [UI 编辑会话模块边界](./technical/【前端架构】UI编辑会话模块边界-2026-08-19.md) -### 图片编辑器与 Agent +## 图片画布与媒体 - [客户端素材创作无限画布阶段一合同](./technical/【技术方案】客户端素材创作无限画布阶段一合同-2026-08-05.md) -- [图片画布编辑器 MVP 接入方案](./technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md) -- [图片画布编辑器前端拆分计划](./technical/【前端架构】图片画布编辑器前端拆分计划-2026-06-17.md) -- [图片画布游戏场景生成链路](./technical/【技术方案】图片画布游戏场景生成链路-2026-08-04.md) -- [画板音乐生成入口设计](./【编辑器】画板音乐生成入口设计-2026-06-18.md) -- [SFX 生成优化 V2.0 任务拆解](./project-memory/plans/【实施计划】SFX生成优化V2.0任务拆解-2026-08-06.md) -- [SFX 生成优化 V2.0 T6 测试与发布门禁](./【实施记录】SFX生成优化V2.0T6测试与发布门禁-2026-08-07.md) -- [音频生成 Composer 恢复共享分流方案](./project-memory/plans/【前端重构】音频生成面板恢复共享分流方案-2026-08-06.md) -- [BGM 提示词优化 T6 测试与发布门禁](./【实施记录】BGM生成提示词优化T6测试与发布门禁-2026-08-05.md) +- [图片画布结构化持久化与迁移回滚](./【编辑器】图片画布结构化持久化与迁移回滚方案-2026-07-19.md) +- [编辑器生成结果原子提交与幂等重放](./technical/【后端架构】编辑器生成结果原子提交与幂等重放方案-2026-08-06.md) +- [画板音乐生成入口](./【编辑器】画板音乐生成入口设计-2026-06-18.md):BGM/SFX 共享视图、独立业务规则和当前发布门禁。 - [画布 Agent 对话面板](./【编辑器】画布Agent对话面板-2026-07-03.md) - [画布 Agent 会话消息存 OSS](./adr/【ADR】画布Agent会话消息存OSS-2026-07-03.md) -- [图片画布撤销范围与操作提示方案](./【图片画布】撤销范围与操作提示方案-2026-07-17.md) +- [编辑器模型定价配置](./【编辑器】模型定价配置管理方案-2026-06-22.md) + +## 后端、运维与测试 + +- [BgFilter 受限资源调度方案](./technical/【后端架构】BgFilter受限资源调度方案-2026-07-21.md) +- [SpacetimeDB 连接池取消安全](./【后端架构】SpacetimeDB连接池租约Drop兜底与取消安全-2026-06-11.md) +- [Jenkins 容器预览部署控制面](./technical/【开发运维】Jenkins容器预览部署控制面技术方案-2026-08-15.md) - [浏览器内 AI Web 工程沙箱预览](./technical/【技术方案】浏览器内AIWeb工程沙箱预览方案-2026-06-13.md) - [AI Web 工程 Runner 安全模型](./technical/【安全模型】AIWeb工程Runner与预览隔离威胁模型-2026-06-13.md) - -### 后端与公开数据 - -- [外部生成 Worker 化方案](./technical/【后端架构】外部生成Worker化方案-2026-06-03.md) -- [BgFilter 受限资源调度方案(同步内部 HTTP 原地等待版)](./technical/【后端架构】BgFilter受限资源调度方案-2026-07-21.md) -- [统一公开作品 Read Model 设计](./technical/【后端架构】统一公开作品ReadModel设计-2026-05-26.md) -- [外部 OpenAPI 与 API Key 接入方案](./【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md) -- [SpacetimeDB 连接池取消安全](./【后端架构】SpacetimeDB连接池租约Drop兜底与取消安全-2026-06-11.md) - -### 后台、宿主壳与运维 - -- [Dashboard 运营看板方案](./technical/【后台管理】Dashboard运营看板方案-2026-06-23.md) -- [Jenkins 容器预览部署控制面](./technical/【开发运维】Jenkins容器预览部署控制面技术方案-2026-08-15.md) -- [后台多账号与 Tab 访问权限](./technical/【后台管理】多账号与Tab访问权限方案-2026-07-14.md) -- [宿主壳能力统一协议](./【前端架构】宿主壳能力统一协议-2026-06-17.md) -- [Expo React Native 与 Tauri 宿主壳方案](./【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md) -- [Pingora 独立网关试点](./technical/【开发运维】Pingora独立网关试点-2026-06-11.md) -- [本地 SSH 服务器管理面板](./technical/【开发运维】本地SSH服务器管理面板技术方案-2026-06-11.md) - -### 测试与协作 - - [npm workspaces 统一依赖边界](./technical/【技术方案】npm-workspaces统一依赖边界-2026-08-21.md) - [React 组件测试准则](./technical/【前端测试】React组件测试准则-2026-06-26.md) -- [AI Web 工程静态预览验收清单](./technical/【测试用例】AIWeb工程静态预览MVP验收清单-2026-06-13.md) -- [当前阶段规划](./planning/README.md) +- [宿主壳能力统一协议](./【前端架构】宿主壳能力统一协议-2026-06-17.md) +- [Expo React Native 与 Tauri 宿主壳方案](./【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md) -## 历史文档边界 +## 维护规则 -- 旧创作模板、旧创作入口、旧运行态和旧素材生成方案不再从本页索引,也不再作为修复目标。 -- `maincloud`、旧 Node/Express/PostgreSQL/Go 后端和人工 `spacetime --root-dir` 口径均已废弃。 -- 历史文档不得覆盖当前融合文档、代码契约或 `docs/project-memory/shared-memory/decision-log.md` 中更新的决策。 - -## 命名规则 - -后续新增 Markdown 文档文件名使用 `【标签名】中文标题-日期.md`。历史文件不做无关批量重命名;本次涉及的旧文档可直接删除或在当前入口中取消引用。 +- 当前文档只保留稳定合同、公开契约和仍在推进的专题;一次性计划、实施记录和已关闭实验完成后删除或融合,不再长期堆积。 +- `docs/project-memory/shared-memory/` 只保存长期有效的概览、决策、流程和踩坑;`plans/`、`todos/` 仅保存仍开放且有明确下一门禁的事项。 +- 修改 `/api/external/v1` 必须同步 OpenAPI 和契约测试;修改 SpacetimeDB schema 必须同步 migration、表目录、绑定和 schema 检查。 +- 旧模板、旧公开作品、旧运行态和旧后端路线不因历史源码或数据表仍存在而恢复入口。 +- 新增 Markdown 使用 `【标签名】中文标题-YYYY-MM-DD.md` 命名;不要把个人配置、密钥、Token、日志或构建产物写入文档。 diff --git a/docs/design/CHILD_MOTION_DEMO_WARMUP_LEVEL_DESIGN_2026-05-09.md b/docs/design/CHILD_MOTION_DEMO_WARMUP_LEVEL_DESIGN_2026-05-09.md deleted file mode 100644 index 759ba7813..000000000 --- a/docs/design/CHILD_MOTION_DEMO_WARMUP_LEVEL_DESIGN_2026-05-09.md +++ /dev/null @@ -1,505 +0,0 @@ -# 儿童动作识别互动玩法 Demo 热身关开发文档 - -> 日期:2026-05-09 -> 适用范围:儿童动作识别互动玩法 Demo 的固定启动热身关 -> 文档性质:玩法 Demo 开发设计文档 -> 说明:本文整理当前已确认的热身关内容、体验、流程和热身数据记录要求。 - -## 1. 热身关定位 - -热身关是 Demo 启动后的固定流程,用于在正式进入后续趣味学习关前完成以下事项: - -- 调用摄像头; -- 识别用户和环境; -- 引导用户来到建议互动位置; -- 教学基础交互方式; -- 确认用户可在互动空间内完成左右移动和挥手; -- 记录用户左右移动距离和挥动手臂空间,作为后续关卡的空间边界与行为坐标; -- 完成后进入关卡选择。 - -热身关不接入创作模块,不作为可配置玩法模板提供给创作者。 - -## 2. 屏幕与设备适配 - -本产品适用于电视屏幕、电脑屏幕等环境。 - -热身关制作表达使用横屏比例。 - -## 3. 画面基础表现 - -用户进入热身关后,摄像头被调用,并开始识别用户和环境。 - -画面基础表现如下: - -1. 在屏幕中央位置的地面生成预设的绿色圆环,作为建议位置的指引。 -2. 将用户的实际位置生成为更细的白色描边小人指示器,作为用户在画面中的标识。 -3. 只对摄像头背景做虚化处理,用于表达对用户隐私的保护、屏蔽周围环境干扰,并营造空间感。 - -## 4. 通用检测与引导规则 - -### 4.1 不允许跳过 - -热身关每个步骤都必须由用户完成,不允许跳过,也不允许系统自动进入下一步。 - -### 4.2 引导动画播放规则 - -每个动作等待 3 秒后可以播放引导动画。 - -当前不设置最长等待时间。 - -### 4.3 绿色圆环完成规则 - -用户到达绿色圆环后,绿色圆环进入 2 秒选中状态。 - -用户需要在绿色圆环内保持停留 2 秒,才算完成该圆环位置检测。 - -### 4.4 左右距离映射规则 - -“约半米”的左右移动距离,技术上以角色剪影移动距离为准。 - -该距离后续会根据实际体验继续调校。 - -### 4.5 手势区分规则 - -招手 / 摆手、挥动左手、挥动右手三类动作需要有动作区分。 - -手势检测仅对肢体进行区分,不对手部细节进行区分。 - -### 4.6 手势引导规则 - -挥动哪只手,就使用对应手的引导。 - -## 5. 热身关完整流程 - -### 5.1 进入热身关 - -#### 画面表现 - -- 摄像头被调用。 -- 系统识别用户和环境。 -- 屏幕中央位置的地面出现预设绿色圆环。 -- 用户实际位置以更细的白色描边小人指示器形式显示。 -- 只对摄像头背景做虚化处理,保留空间感。 - -#### 屏幕文字与语音 - -屏幕中上方浮现文字,同时语音播报: - -```text -欢迎你,小朋友,见到你真开心 -``` - -随后继续播报: - -```text -来圆圈这里和我打个招呼吧 -``` - -首句展示完成后停顿 2 秒,再展示第二句。该步骤不展示“来到圆圈这里”大标题。 - -#### 检测逻辑 - -系统检测用户是否到达屏幕中央绿色圆环位置。 - -用户到达圆环后,绿色圆环进入 2 秒选中状态。用户保持停留 2 秒后,该步骤完成。 - -#### 完成反馈 - -用户完成中央圆环位置检测后: - -- 播放圆圈消失特效; -- 进入招手手势教学步骤。 - ---- - -### 5.2 招手教学 - -#### 画面表现 - -播放招手的手势引导,引导猫咪整体位于上半屏幕、字幕 UI 下方。 - -若用户进入该步骤后 3 秒仍未完成动作,可以播放引导动画。 - -#### 检测逻辑 - -系统检测用户是否完成招手 / 摆手手势。 - -该动作与后续挥动左手、挥动右手需要有动作区分,但仅对肢体进行区分,不对手部细节进行区分。 - -#### 完成反馈 - -用户完成招手 / 摆手手势后,进入下一步。 - ---- - -### 5.3 热身说明 - -#### 屏幕文字与语音 - -```text -你好呀小朋友,为了你玩的安全和开心,先来和我一起热个身吧 -``` - -播放完成后进入左右移动热身步骤。 - ---- - -### 5.4 向左一步 - -#### 屏幕文字与语音 - -```text -向左一步 -``` - -#### 画面表现 - -屏幕中心向左一个身位,约半米的地面位置,出现新的绿色圆圈。 - -“约半米”技术上以角色剪影移动距离为准,后续根据体验调校。 - -#### 检测逻辑 - -系统检测用户是否到达该绿色圆圈位置。 - -用户到达圆环后,绿色圆环进入 2 秒选中状态。用户保持停留 2 秒后,该步骤完成。 - -#### 完成反馈 - -用户完成后播放鼓励语: - -```text -真棒 -``` - -同时记录本次向左移动距离,作为后续关卡中的左侧空间边界参考。 - -完成后进入“回到中间来”。 - ---- - -### 5.5 回到中间来(一) - -#### 屏幕文字与语音 - -```text -回到中间来 -``` - -#### 画面表现 - -场地中心位置出现绿色圆圈。 - -#### 检测逻辑 - -系统检测用户是否到达场地中心绿色圆圈位置。 - -用户到达圆环后,绿色圆环进入 2 秒选中状态。用户保持停留 2 秒后,该步骤完成。 - -#### 完成反馈 - -用户完成后播放鼓励语: - -```text -真棒 -``` - -完成后进入“向右一步”。 - ---- - -### 5.6 向右一步 - -#### 屏幕文字与语音 - -```text -向右一步 -``` - -#### 画面表现 - -屏幕中心向右一个身位,约半米的地面位置,出现新的绿色圆圈。 - -“约半米”技术上以角色剪影移动距离为准,后续根据体验调校。 - -#### 检测逻辑 - -系统检测用户是否到达该绿色圆圈位置。 - -用户到达圆环后,绿色圆环进入 2 秒选中状态。用户保持停留 2 秒后,该步骤完成。 - -#### 完成反馈 - -用户完成后播放鼓励语: - -```text -真棒 -``` - -同时记录本次向右移动距离,作为后续关卡中的右侧空间边界参考。 - -完成后进入“回到中间来”。 - ---- - -### 5.7 回到中间来(二) - -#### 屏幕文字与语音 - -```text -回到中间来 -``` - -#### 画面表现 - -场地中心位置出现绿色圆圈。 - -#### 检测逻辑 - -系统检测用户是否到达场地中心绿色圆圈位置。 - -用户到达圆环后,绿色圆环进入 2 秒选中状态。用户保持停留 2 秒后,该步骤完成。 - -#### 完成反馈 - -用户完成后播放鼓励语: - -```text -真棒 -``` - -完成后进入左手挥动教学。 - ---- - -### 5.8 挥动左手 - -#### 屏幕文字与语音 - -```text -挥动左手 -``` - -#### 画面表现 - -播放伸展手臂挥动左手的手势引导。 - -若用户进入该步骤后 3 秒仍未完成动作,可以播放引导动画。 - -#### 检测逻辑 - -系统检测用户是否完成挥动左手手势。 - -该手势检测仅对肢体进行区分,不对手部细节进行区分。 - -#### 完成反馈 - -用户完成后播放鼓励语: - -```text -真棒 -``` - -同时记录用户挥动左手的空间,保存为该用户对应的行为坐标。 - -完成后进入右手挥动教学。 - ---- - -### 5.9 挥动右手 - -#### 屏幕文字与语音 - -```text -挥动右手 -``` - -#### 画面表现 - -播放伸展手臂挥动右手的手势引导。 - -若用户进入该步骤后 3 秒仍未完成动作,可以播放引导动画。 - -#### 检测逻辑 - -系统检测用户是否完成挥动右手手势。 - -该手势检测仅对肢体进行区分,不对手部细节进行区分。 - -#### 完成反馈 - -用户完成后播放鼓励语: - -```text -真棒 -``` - -同时记录用户挥动右手的空间,保存为该用户对应的行为坐标。 - -完成后进入热身结束。 - ---- - -### 5.10 热身结束 - -#### 进入条件 - -用户完成挥动右手后,直接进入热身结束阶段。 - -#### 完成反馈 - -播放热身结束特效、上浮字幕和语音: - -```text -真厉害,你是我见过最聪明的小朋友 -``` - -随后继续播放: - -```text -别走开,现在开始我们的游戏吧 -``` - -热身关结束,进入关卡选择。 - -## 6. 流程状态表 - -| 顺序 | 步骤 | 屏幕文字 / 语音 | 画面表现 | 检测目标 | 完成后反馈 | -|---:|---|---|---|---|---| -| 1 | 进入热身关 | 欢迎你,小朋友,见到你真开心;来圆圈这里和我打个招呼吧 | 中央地面绿色圆环;用户更细白色描边小人指示器;摄像头背景虚化 | 用户到达中央圆环并保持 2 秒 | 圆圈消失特效 | -| 2 | 招手教学 | 同上流程延续 | 招手手势引导;等待 3 秒可播放引导动画 | 招手 / 摆手 | 进入下一步 | -| 3 | 热身说明 | 你好呀小朋友,为了你玩的安全和开心,先来和我一起热个身吧 | 保持热身引导状态 | 无新增动作检测 | 进入移动热身 | -| 4 | 向左一步 | 向左一步 | 左侧约半米处绿色圆圈 | 用户到达左侧圆环并保持 2 秒 | 真棒;记录左侧空间边界 | -| 5 | 回到中间来 | 回到中间来 | 中心位置绿色圆圈 | 用户到达中心圆环并保持 2 秒 | 真棒 | -| 6 | 向右一步 | 向右一步 | 右侧约半米处绿色圆圈 | 用户到达右侧圆环并保持 2 秒 | 真棒;记录右侧空间边界 | -| 7 | 回到中间来 | 回到中间来 | 中心位置绿色圆圈 | 用户到达中心圆环并保持 2 秒 | 真棒 | -| 8 | 挥动左手 | 挥动左手 | 伸展手臂挥动左手手势引导;等待 3 秒可播放引导动画 | 挥动左手 | 真棒;记录左手挥动空间 | -| 9 | 挥动右手 | 挥动右手 | 伸展手臂挥动右手手势引导;等待 3 秒可播放引导动画 | 挥动右手 | 真棒;记录右手挥动空间;进入热身结束 | -| 10 | 热身结束 | 真厉害,你是我见过最聪明的小朋友;别走开,现在开始我们的游戏吧 | 热身结束特效 | 无新增动作检测 | 进入关卡选择 | - -## 7. 固定文案与语音清单 - -以下文案需要作为屏幕中上方浮现文字,并同步语音播报。 - -```text -欢迎你,小朋友,见到你真开心 -来圆圈这里和我打个招呼吧 -你好呀小朋友,为了你玩的安全和开心,先来和我一起热个身吧 -向左一步 -真棒 -回到中间来 -真棒 -向右一步 -真棒 -回到中间来 -真棒 -挥动左手 -真棒 -挥动右手 -真厉害,你是我见过最聪明的小朋友 -别走开,现在开始我们的游戏吧 -``` - -## 8. 需要开发支持的识别能力 - -热身关当前流程需要支持以下识别能力: - -1. 摄像头调用; -2. 用户识别; -3. 环境识别; -4. 用户实际位置识别; -5. 用户是否到达中央绿色圆环位置; -6. 用户是否在绿色圆环内持续保持 2 秒; -7. 用户是否到达左侧约半米绿色圆环位置; -8. 用户是否到达右侧约半米绿色圆环位置; -9. 招手 / 摆手手势识别; -10. 挥动左手识别; -11. 挥动右手识别; -12. 用户左右移动距离记录; -13. 用户挥动手臂空间记录。 - -## 9. 需要开发支持的表现能力 - -热身关当前流程需要支持以下表现能力: - -1. 横屏比例显示; -2. 摄像头背景虚化; -3. 用户位置生成更细的白色描边小人指示器; -4. 屏幕中央地面绿色圆环; -5. 左侧约半米地面绿色圆环; -6. 右侧约半米地面绿色圆环; -7. 绿色圆环 2 秒选中状态; -8. 圆圈消失特效; -9. 招手手势引导; -10. 伸展手臂挥动左手手势引导; -11. 伸展手臂挥动右手手势引导; -12. 热身结束特效; -13. 上浮字幕; -14. 语音播报。 - -## 10. 热身数据记录要求 - -热身关需要记录以下数据,用于后续关卡的空间边界和行为坐标判断。 - -### 10.1 左右空间边界 - -用户完成向左一步后,记录该移动距离,作为后续关卡中的左侧空间边界。 - -用户完成向右一步后,记录该移动距离,作为后续关卡中的右侧空间边界。 - -后续关卡中,当用户身体主体覆盖安全边界线时,对应侧屏幕边缘出现虚影提醒。 - -后续关卡中,当用户身体主体超出安全边界线时: - -1. 关卡内容暂停; -2. 屏幕虚化; -3. 屏幕中央地面出现绿色圆圈; -4. 屏幕提示文案: - -```text -小朋友,要注意安全哦 -``` - -5. 用户需要回到中心绿色圆圈并保持 2 秒后,才能继续游戏内容。 - -### 10.2 手臂挥动空间 - -用户完成挥动左手后,记录用户挥动左手的空间,保存为该用户对应的行为坐标。 - -用户完成挥动右手后,记录用户挥动右手的空间,保存为该用户对应的行为坐标。 - -## 11. 热身关完成条件 - -热身关完成条件为用户按顺序完成以下流程: - -1. 到达中央圆环位置并保持 2 秒; -2. 完成招手 / 摆手手势; -3. 到达左侧约半米圆环位置并保持 2 秒; -4. 记录左侧空间边界; -5. 回到中央圆环位置并保持 2 秒; -6. 到达右侧约半米圆环位置并保持 2 秒; -7. 记录右侧空间边界; -8. 回到中央圆环位置并保持 2 秒; -9. 完成挥动左手; -10. 记录左手挥动空间; -11. 完成挥动右手; -12. 记录右手挥动空间; -13. 播放热身结束特效和结束语音; -14. 进入关卡选择。 - -## 12. 数据保存方式 - -左右空间边界和手臂挥动空间仅在当前 Demo 体验会话内保存。 - -这里的“当前 Demo 体验会话”指用户本次打开并体验 Demo 的过程。当用户关闭 Demo、刷新页面、退出当前体验流程、重新进入 Demo,或更换设备后,系统不再沿用上一次热身记录的数据,需要重新完成热身关并重新记录。 - -采用仅当前 Demo 体验会话内保存的原因: - -1. 每名用户的身高、体型、动作幅度不同,安全边界和行为坐标会发生变化。 -2. 当前 Demo 不做特定用户识别,无法确认下一次体验的是否仍是同一名用户。 -3. 用户所处的体验环境可能变化,包括房间大小、摄像头位置、屏幕位置和站立距离。 -4. 为保证安全,每次体验都需要重新对环境和距离进行安全检查。 - -## 13. 后续待确认事项 - -当前暂无待确认事项。 diff --git a/docs/design/TAONIER_BRAND_LOGO_CONCEPTS_2026-05-13.md b/docs/design/TAONIER_BRAND_LOGO_CONCEPTS_2026-05-13.md deleted file mode 100644 index d2be0b328..000000000 --- a/docs/design/TAONIER_BRAND_LOGO_CONCEPTS_2026-05-13.md +++ /dev/null @@ -1,1680 +0,0 @@ -# 陶泥儿品牌 Logo 概念稿 - -> 本稿是围绕候选产品名“陶泥儿”的品牌视觉探索,不替代当前已冻结的“百梦”正式命名口径。若后续确认更名,需要另起产品命名、前后端文案和商标检索落地方案。 - -## 1. 品牌定位归纳 - -“陶泥儿”适合承接的不是传统陶艺或儿童黏土,而是“把灵感塑形成可玩内容”的 AI 创作平台隐喻。 - -核心关键词: - -- 精品:作品不是随手糊出来,而是经过 AI 辅助打磨、可被消费和传播的轻精品内容。 -- UGC:用户是主要造物者,平台降低创作门槛。 -- 创作:从一句脑洞、一个梗、一张图,生成小游戏、互动作品或可分享内容。 -- 裂变与梗:名字要支持“开捏”“捏个梗”“捏个小游戏”这类用户语言。 -- 轻度休闲:体验应松弛、即时、好玩,不走硬核生产工具气质。 -- AI:AI 是塑形能力,不是冷冰冰的技术标签。 - -推荐品牌主张: - -```text -把脑洞捏成小游戏 -``` - -备选表达: - -```text -捏个脑洞,马上开玩 -AI 开捏,人人会创作 -随手造梗,随心开玩 -``` - -## 2. 生成原则 - -本稿包含多轮 Logo 概念:早期批次使用仓库 GPT-image-2 / VectorEngine 工作流生成无文字图标,锚点底座与抽象泥胚批次使用确定性矢量脚本生成 SVG / PNG。当前新主线已切换为“抽象泥胚角色”:保留陶泥人 / 陶泥手办 / 吉祥物的生命感和 IP 延展性,但不再直接画人体,而是把它压缩成一个可被记住的几何陶泥主标。 - -原因: - -- AI 生图直接生成中文品牌字容易出现笔画错误,不适合作为正式字标。 -- 当前阶段更适合先确定图形符号方向,再由设计师或前端继续做矢量化、字标搭配和多尺寸适配。 -- 当前主线已停止此前软泥合拍、旋涡、糖果粉绿、锚点底座和具象小人方向,改以“非人形抽象陶泥角色 / 泥胚手办符号”为原型,强调可记住、可延展、可做 IP 的品牌主标。 -- 图标需要优先服务 App icon、平台左上角品牌、分享卡片和加载页,而不是一次性海报图。 - -生成文件: - -```text -public/branding/taonier-logo-v3-concepts/ -├─ taonier-logo-v3-contact-sheet.png -├─ taonier-v3-finger-spark.png -├─ taonier-v3-seed-pop.png -├─ taonier-v3-magic-dot.png -├─ taonier-v3-work-gem.png -└─ taonier-v3-soft-t.png - -public/branding/taonier-logo-magic-dot-concepts/ -├─ taonier-logo-magic-dot-contact-sheet.png -├─ taonier-magic-dot-orbit.png -├─ taonier-magic-dot-seal.png -├─ taonier-magic-dot-squish.png -├─ taonier-magic-dot-mold.png -└─ taonier-magic-dot-bloom.png - -public/branding/taonier-logo-anchor-concepts/ -├─ taonier-logo-anchor-contact-sheet.png -├─ taonier-anchor-core.svg -├─ taonier-anchor-core.png -├─ taonier-anchor-soft-slab.svg -├─ taonier-anchor-soft-slab.png -├─ taonier-anchor-work-stack.svg -├─ taonier-anchor-work-stack.png -├─ taonier-anchor-clay-drop.svg -├─ taonier-anchor-clay-drop.png -├─ taonier-anchor-creation-base.svg -├─ taonier-anchor-creation-base.png -├─ taonier-anchor-app-token.svg -└─ taonier-anchor-app-token.png - -public/branding/taonier-logo-clay-mascot-concepts/ -├─ taonier-logo-clay-mascot-contact-sheet.png -├─ taonier-clay-mascot-little-maker.png -├─ taonier-clay-mascot-figurine-token.png -├─ taonier-clay-mascot-soft-doll.png -├─ taonier-clay-mascot-creator-totem.png -├─ taonier-clay-mascot-idol-mask.png -└─ taonier-clay-mascot-pocket-figure.png - -public/branding/taonier-logo-geometric-concepts/ -├─ taonier-logo-geometric-contact-sheet.png -├─ taonier-geometric-offset-core.svg -├─ taonier-geometric-offset-core.png -├─ taonier-geometric-mold-chip.svg -├─ taonier-geometric-mold-chip.png -├─ taonier-geometric-pinched-tile.svg -├─ taonier-geometric-pinched-tile.png -├─ taonier-geometric-dual-plate.svg -├─ taonier-geometric-dual-plate.png -├─ taonier-geometric-dot-gate.svg -├─ taonier-geometric-dot-gate.png -├─ taonier-geometric-work-knot.svg -└─ taonier-geometric-work-knot.png - -public/branding/taonier-logo-hands-concepts/ -├─ taonier-logo-hands-contact-sheet.png -├─ taonier-hands-v2-cradle.png -├─ taonier-hands-v2-clap.png -├─ taonier-hands-v2-bowl.png -├─ taonier-hands-v2-seal.png -└─ taonier-hands-v2-pop.png - -public/branding/taonier-logo-squish-concepts/ -├─ taonier-logo-squish-contact-sheet.png -├─ taonier-squish-v2-pulse.png -├─ taonier-squish-v2-bounce.png -├─ taonier-squish-v2-spark-gap.png -├─ taonier-squish-v2-comet.png -└─ taonier-squish-v2-token.png - -public/branding/taonier-logo-spiral-reference-concepts/ -├─ taonier-logo-spiral-reference-contact-sheet.png -├─ taonier-spiral-reference.jpg -├─ taonier-spiral-soft-squish.png -├─ taonier-spiral-candy-roll.png -├─ taonier-spiral-star-core.png -├─ taonier-spiral-bouncy-clay.png -├─ taonier-spiral-creation-whirl.png -└─ taonier-spiral-soft-token.png - -public/branding/taonier-logo-broad-concepts/ -├─ taonier-logo-broad-contact-sheet.png -├─ taonier-broad-soft-portal.png -├─ taonier-broad-work-embryo.png -├─ taonier-broad-game-mold.png -├─ taonier-broad-soft-totem.png -└─ taonier-broad-creation-spark.png - -public/branding/taonier-logo-fresh-concepts/ -├─ taonier-logo-fresh-contact-sheet.png -├─ taonier-fresh-wheel-imprint.png -├─ taonier-fresh-mold-window.png -├─ taonier-fresh-dot-dice.png -├─ taonier-fresh-pocket-world.png -├─ taonier-fresh-stage-window.png -└─ taonier-fresh-punch-hole.png - -public/branding/taonier-logo-punch-hole-concepts/ -├─ taonier-logo-punch-hole-contact-sheet.png -├─ taonier-punch-locked-shape.png -├─ taonier-punch-stable-icon.png -├─ taonier-punch-hole-balance.png -├─ taonier-punch-color-inlay.png -├─ taonier-punch-mono-test.png -└─ taonier-punch-app-token.png - -public/branding/taonier-logo-punch04-color-concepts/ -├─ taonier-logo-punch04-color-contact-sheet.png -├─ taonier-punch04-warm-ink-core.png -├─ taonier-punch04-navy-game-core.png -├─ taonier-punch04-cream-window.png -├─ taonier-punch04-clay-gradient-flat.png -├─ taonier-punch04-mint-shadow.png -└─ taonier-punch04-negative-tile.png - -public/branding/taonier-logo-ref04-locked-color-concepts/ -├─ taonier-logo-ref04-locked-color-contact-sheet.png -├─ taonier-ref04-locked-warm-ink.png -├─ taonier-ref04-locked-blue-ink.png -├─ taonier-ref04-locked-plum-ink.png -├─ taonier-ref04-locked-green-ink.png -├─ taonier-ref04-locked-shrink-core.png -└─ taonier-ref04-locked-soft-charcoal.png - -public/branding/taonier-logo-ref04-warm-star-concepts/ -├─ taonier-logo-ref04-warm-star-contact-sheet.png -├─ taonier-ref04-warm-star-terracotta.png -├─ taonier-ref04-warm-star-caramel.png -├─ taonier-ref04-warm-star-cocoa.png -├─ taonier-ref04-warm-star-rust.png -├─ taonier-ref04-warm-star-olive.png -└─ taonier-ref04-warm-star-plum.png - -public/branding/taonier-logo-ref04-warm-sparkle-v2-concepts/ -├─ taonier-logo-ref04-warm-sparkle-v2-contact-sheet.png -├─ taonier-ref04-warm-sparkle-terracotta.png -├─ taonier-ref04-warm-sparkle-rust.png -├─ taonier-ref04-warm-sparkle-caramel.png -├─ taonier-ref04-warm-sparkle-cocoa.png -├─ taonier-ref04-warm-sparkle-clay-quiet.png -└─ taonier-ref04-warm-sparkle-plum.png - -public/branding/taonier-logo-ref04-palette-transfer/ -├─ taonier-logo-ref04-palette-transfer-contact-sheet.png -└─ taonier-ref04-palette-transfer-warm-yellow-sparkle.png - -public/branding/taonier-logo-abstract-mascot-concepts/ -├─ taonier-logo-abstract-mascot-contact-sheet.png -├─ taonier-abstract-mascot-clay-bean.svg -├─ taonier-abstract-mascot-clay-bean.png -├─ taonier-abstract-mascot-mold-baby.svg -├─ taonier-abstract-mascot-mold-baby.png -├─ taonier-abstract-mascot-dot-face.svg -├─ taonier-abstract-mascot-dot-face.png -├─ taonier-abstract-mascot-soft-totem.svg -├─ taonier-abstract-mascot-soft-totem.png -├─ taonier-abstract-mascot-clay-seed.svg -├─ taonier-abstract-mascot-clay-seed.png -├─ taonier-abstract-mascot-work-puppet.svg -└─ taonier-abstract-mascot-work-puppet.png - -public/branding/taonier-logo-abstract-mascot-v2-concepts/ -├─ taonier-logo-abstract-mascot-v2-contact-sheet.png -├─ taonier-abstract-mascot-v2-clay-sprite.svg -├─ taonier-abstract-mascot-v2-clay-sprite.png -├─ taonier-abstract-mascot-v2-pinch-orbit.svg -├─ taonier-abstract-mascot-v2-pinch-orbit.png -├─ taonier-abstract-mascot-v2-seed-totem.svg -├─ taonier-abstract-mascot-v2-seed-totem.png -├─ taonier-abstract-mascot-v2-soft-mold.svg -├─ taonier-abstract-mascot-v2-soft-mold.png -├─ taonier-abstract-mascot-v2-clay-orb.svg -├─ taonier-abstract-mascot-v2-clay-orb.png -├─ taonier-abstract-mascot-v2-work-glyph.svg -└─ taonier-abstract-mascot-v2-work-glyph.png - -public/branding/taonier-logo-abstract-mascot-image2-concepts/ -├─ taonier-logo-abstract-mascot-image2-contact-sheet.png -├─ taonier-image2-clay-spirit-glyph.png -├─ taonier-image2-pinched-seed-mascot.png -├─ taonier-image2-soft-totem-creature.png -├─ taonier-image2-clay-pocket-token.png -├─ taonier-image2-work-core-puppet.png -└─ taonier-image2-mold-blob-companion.png - -public/branding/taonier-logo-abstract-mascot-minimal-concepts/ -├─ taonier-logo-abstract-mascot-minimal-contact-sheet.png -├─ taonier-minimal-clay-core.png -├─ taonier-minimal-clay-token.png -├─ taonier-minimal-seed-glyph.png -└─ taonier-minimal-mold-bud.png - -public/branding/taonier-logo-flat-concepts/ -├─ taonier-logo-flat-contact-sheet.png -├─ taonier-flat-play-clay.png -├─ taonier-flat-spark-clay.png -├─ taonier-flat-meme-smile.png -├─ taonier-flat-loop-mold.png -└─ taonier-flat-seal-blocks.png - -public/branding/taonier-logo-concepts/ -├─ taonier-logo-contact-sheet.png -├─ taonier-clay-spark.png -├─ taonier-play-mold.png -├─ taonier-meme-bubble.png -├─ taonier-creation-loop.png -└─ taonier-premium-seal.png -``` - -生成脚本: - -```text -scripts/generate-taonier-logo-concepts.mjs -scripts/generate-taonier-hands-logo-concepts.mjs -scripts/generate-taonier-squish-logo-concepts.mjs -scripts/generate-taonier-spiral-logo-concepts.mjs -scripts/generate-taonier-spiral-contact-sheet.py -scripts/generate-taonier-anchor-logo-concepts.py -scripts/generate-taonier-clay-mascot-logo-concepts.mjs -scripts/generate-taonier-clay-mascot-contact-sheet.py -scripts/generate-taonier-geometric-logo-concepts.py -scripts/generate-taonier-abstract-mascot-logo-concepts.py -scripts/generate-taonier-abstract-mascot-v2-logo-concepts.py -scripts/generate-taonier-abstract-mascot-image2-logo-concepts.mjs -scripts/generate-taonier-abstract-mascot-image2-contact-sheet.py -scripts/generate-taonier-abstract-mascot-minimal-logo-concepts.mjs -scripts/generate-taonier-abstract-mascot-minimal-contact-sheet.py -``` - -## 当前主线:抽象泥胚角色 - -用户最新反馈明确:仍然以陶泥人、陶泥手办、抽象角色 / 吉祥物为主方向,但设计时不一定使用人体形象,造型要更简单、更几何、更扁平、更有创意。因此本轮把方向校正为“抽象泥胚角色”:不是完整小人,也不是纯几何系统图标,而是一枚像有生命的陶泥作品主标。 - -设计判断: - -- 保留:陶泥手办的亲和力、可爱度、IP 延展、被捏出的生命感。 -- 削弱:头身四肢、复杂五官、头像感、儿童黏土课和插画感。 -- 强化:单一剪影、偏心孔洞、星核、捏痕、少色、扁平矢量和小尺寸识别。 - -### A. 极简抽象泥胚批次 - -这一批使用 VectorEngine `gpt-image-2-all` 生成,prompt 明确约束“不要人形、不要脸、不要手脚”,只保留一个主轮廓、一个孔洞 / 作品核和一个小星点,用于寻找更像主 Logo 的自由轮廓。 - -![陶泥儿 Logo 极简抽象泥胚总览](../../public/branding/taonier-logo-abstract-mascot-minimal-concepts/taonier-logo-abstract-mascot-minimal-contact-sheet.png) - -本批次结论: - -```text -首选:01 泥芯主标 -强备选:03 泥种图符 -可爱但偏通用:02 泥标小偶 -不建议主标:04 模胚小芽 -``` - -`01 泥芯主标` 的优势是陶泥容器感、偏心黑孔和小星点比较集中,既有手捏陶泥的名字联想,也不像头像或人形。风险是口沿让它略像陶罐,后续人工矢量化时应压低“罐口”形态,让外轮廓更像被捏出的泥胚。 - -`03 泥种图符` 更接近“会呼吸的陶泥种子”,白色主体、黑色偏心孔和底部陶土色关系稳定,适合作为主标第二方向。后续应减少渐变和阴影,保留白泥主体、偏心孔、星核和底部陶土捏痕。 - -### B. image-2 抽象角色自由稿 - -这一批继续走 VectorEngine `gpt-image-2-all`,目标是找更有灵气的“非人形陶泥角色”轮廓。它不作为最终矢量稿,而是给后续人工重绘提供轮廓和气质参考。 - -![陶泥儿 Logo image-2 抽象角色总览](../../public/branding/taonier-logo-abstract-mascot-image2-concepts/taonier-logo-abstract-mascot-image2-contact-sheet.png) - -本批次结论: - -```text -灵气参考:01 泥灵符号 -造型参考:04 口袋泥符 -不建议主标:02 捏胚小偶、03 软陶图灵、05 作品泥偶、06 模团伙伴 -``` - -`01 泥灵符号` 最有“被捏出生命感”的味道,卷角和星核有记忆点,但黑色 App icon 底、角标和渐变需要重绘压平。它适合提炼成“软泥主体 + 星核 + 两个陶土捏点”的辅助参考。 - -`04 口袋泥符` 轮廓足够简单,中心星核清楚,但橙色主体过大,陶泥儿的亲和力偏向通用贴纸。它可以作为色彩和 Q 感参考,不建议直接定稿。 - -### C. 确定性矢量抽象泥偶批次 - -这一批由本地脚本直接生成 SVG / PNG,优点是结构可控、可进入后续矢量微调;缺点是灵气弱于 image-2 自由稿。 - -![陶泥儿 Logo 抽象泥偶 V2 总览](../../public/branding/taonier-logo-abstract-mascot-v2-concepts/taonier-logo-abstract-mascot-v2-contact-sheet.png) - -本批次结论: - -```text -可矢量化基准:01 陶泥小灵 -结构备选:04 软模团子 -成熟符号参考:05 泥芯圆偶 -暂不优先:02 捏孔泥偶、03 星胚图腾、06 作品泥符 -``` - -`01 陶泥小灵` 是当前最接近“非人形小陶泥角色”的可控矢量基准:单体轮廓、偏心陶土捏痕、星核和底部压扁站姿都成立。后续应删除单眼或将其改成更抽象的泥点,避免重新回到头像方向。 - -`04 软模团子` 更像一个被捏过的模具符号,品牌主标感强,但角色感稍弱。它适合和 `01 泥芯主标` 结合:保留模具切口和中心作品核,减少底部横条。 - -### D. 第一轮抽象泥偶批次 - -![陶泥儿 Logo 抽象泥偶总览](../../public/branding/taonier-logo-abstract-mascot-concepts/taonier-logo-abstract-mascot-contact-sheet.png) - -这一批验证了“抽象角色”方向,但多数方案仍偏头像、面具或机器人。仅 `01 陶泥豆偶` 和 `06 作品泥灵` 的轮廓关系可保留为参考,其余不建议继续。 - -## 3. 几何抽象历史探索 - -用户一度反馈“陶泥人 / 手办”方向不喜欢,不一定要人形,希望更简单、更几何、更有创意。因此本轮曾转向确定性几何符号:少元素、强轮廓、可注册感、适合 App icon,同时保留“陶泥、捏痕、泥点、模具、作品核”的隐喻。后续用户澄清并不是要放弃陶泥人 / 手办 / 吉祥物精神,而是不要直接画人体;因此本节降级为历史探索和辅助符号库,不再作为当前主线。 - -![陶泥儿 Logo 几何抽象总览](../../public/branding/taonier-logo-geometric-concepts/taonier-logo-geometric-contact-sheet.png) - -生成脚本: - -```text -scripts/generate-taonier-geometric-logo-concepts.py -``` - -生成文件: - -```text -public/branding/taonier-logo-geometric-concepts/ -├─ taonier-geometric-offset-core.svg -├─ taonier-geometric-offset-core.png -├─ taonier-geometric-mold-chip.svg -├─ taonier-geometric-mold-chip.png -├─ taonier-geometric-pinched-tile.svg -├─ taonier-geometric-pinched-tile.png -├─ taonier-geometric-dual-plate.svg -├─ taonier-geometric-dual-plate.png -├─ taonier-geometric-dot-gate.svg -├─ taonier-geometric-dot-gate.png -├─ taonier-geometric-work-knot.svg -├─ taonier-geometric-work-knot.png -└─ taonier-logo-geometric-contact-sheet.png -``` - -### 3.1 偏心泥孔 - -![偏心泥孔](../../public/branding/taonier-logo-geometric-concepts/taonier-geometric-offset-core.png) - -定位:当前几何主线首选。 - -这个方向像一块被冲孔和按压过的软陶牌,偏心大孔和小泥点形成记忆点,整体足够简单,也不像人形、手办或插画。它能表达“作品核 / 泥点 / 可塑形模具”,适合作为成熟 App 主标继续打磨。 - -建议用途:主 Logo 首选、App icon、favicon。 - -### 3.2 模芯切片 - -![模芯切片](../../public/branding/taonier-logo-geometric-concepts/taonier-geometric-mold-chip.png) - -定位:更硬朗的平台符号。 - -这个方向有“模具芯片 / 作品切片”的感觉,平台和工具属性更强,但陶泥软感弱一些。适合做技术感更强的备选。 - -建议用途:平台入口、创作工具标识、主 Logo 备选。 - -### 3.3 捏痕方标 - -![捏痕方标](../../public/branding/taonier-logo-geometric-concepts/taonier-geometric-pinched-tile.png) - -定位:最贴合“被捏过”的几何符号。 - -这个方向两侧被挤压出缺口,中间作品核清楚,和“陶泥被捏塑”关联最强。风险是整体稍像 UI 控件或票券,需要后续让外轮廓更独特。 - -建议用途:主 Logo 强备选、生成按钮、品牌辅助图形。 - -### 3.4 双片合模 - -![双片合模](../../public/branding/taonier-logo-geometric-concepts/taonier-geometric-dual-plate.png) - -定位:表达两片材料合模成型。 - -这个方向动作感强,能看出上下两片材料夹出中心作品核。但红绿双条偏 UI 化,后续需要减少按钮感。 - -建议用途:生成动效、创作成功态,不建议直接做主 Logo。 - -### 3.5 泥点入口 - -![泥点入口](../../public/branding/taonier-logo-geometric-concepts/taonier-geometric-dot-gate.png) - -定位:入口 / 生成门方向。 - -这个方向有“泥点落入入口,作品生成”的隐喻,但略像锁、包或门。适合作为创作入口图标,不建议作为唯一主标。 - -### 3.6 作品结点 - -![作品结点](../../public/branding/taonier-logo-geometric-concepts/taonier-geometric-work-knot.png) - -定位:作品网络和多点共创。 - -这个方向几何清楚,但更像系统模块图标,陶泥儿名字关联弱。适合作为作品关系、模板组合、共创系统的辅助标识。 - -## 4. 陶泥人 / 手办角色历史探索 - -用户明确要求停止此前锚点底座方向,改以“陶泥人、陶泥手办、抽象角色 / 吉祥物”为主线重新设计。新方向的核心不是做复杂 IP 插画,而是把一个小陶泥角色压缩成可当 Logo 使用的品牌符号:轮廓简单、有陶泥手捏感、有一点灵感 / 作品星核,并能继续延展成表情、动效和 IP。 - -![陶泥儿 Logo 陶泥人角色总览](../../public/branding/taonier-logo-clay-mascot-concepts/taonier-logo-clay-mascot-contact-sheet.png) - -> 2026-05-14 用户反馈该批不喜欢,不一定要人形,造型需要更简单和几何;本节降级为历史探索,不再作为当前主线。 - -生成脚本: - -```text -scripts/generate-taonier-clay-mascot-logo-concepts.mjs -scripts/generate-taonier-clay-mascot-contact-sheet.py -``` - -生成文件: - -```text -public/branding/taonier-logo-clay-mascot-concepts/ -├─ taonier-clay-mascot-little-maker.png -├─ taonier-clay-mascot-figurine-token.png -├─ taonier-clay-mascot-soft-doll.png -├─ taonier-clay-mascot-creator-totem.png -├─ taonier-clay-mascot-idol-mask.png -├─ taonier-clay-mascot-pocket-figure.png -└─ taonier-logo-clay-mascot-contact-sheet.png -``` - -### 4.1 陶泥小人 - -![陶泥小人](../../public/branding/taonier-logo-clay-mascot-concepts/taonier-clay-mascot-little-maker.png) - -定位:最直观的陶泥人方向。 - -这个方向轮廓极简、记忆点强,胸前星点能承接“脑洞成型”。风险是剪影略像通用姜饼人,需要进一步把头身比例和手臂做得更像“被捏出的软陶角色”。 - -建议用途:主 Logo 备选、IP 原型、表情包和启动动效参考。 - -### 4.2 陶泥手办 - -![陶泥手办](../../public/branding/taonier-logo-clay-mascot-concepts/taonier-clay-mascot-figurine-token.png) - -定位:最接近完整吉祥物手办。 - -这个方向亲和、可爱、手办感强,但作为主 Logo 略像完整角色插画,细节和体积感偏多。后续若沿它继续,应大幅压缩五官、手臂和底座。 - -建议用途:IP 形象、运营视觉、品牌吉祥物,不建议未经简化直接做主 Logo。 - -### 4.3 软陶团子 - -![软陶团子](../../public/branding/taonier-logo-clay-mascot-concepts/taonier-clay-mascot-soft-doll.png) - -定位:软萌治愈方向。 - -这个方向更像一团软陶团子,亲和感强,但主标识别点偏弱,容易进入普通治愈头像或玩具形象。中心泥点可以保留,外轮廓需要更独特。 - -建议用途:新手引导、空状态、IP 辅助形象。 - -### 4.4 造物泥偶 - -![造物泥偶](../../public/branding/taonier-logo-clay-mascot-concepts/taonier-clay-mascot-creator-totem.png) - -定位:当前角色主线的主 Logo 首选。 - -这个方向最接近“角色 + 品牌图腾”的平衡:剪影简单、黑底识别强、中心星核明确,既有小陶泥人的亲和感,也不会过度像插画或头像。 - -优点: - -- 图腾化程度最高,适合继续矢量化。 -- 中央星核能承接 AI 生成、作品成型和精品内容。 -- 角色感存在,但没有复杂表情和具象服饰。 - -风险: - -- 头部和身体连接处仍需人工优化,让它更像陶泥手捏而不是普通小人。 -- 周围小星点应在正式主标中删减,只保留一个核心星核。 - -建议用途:当前主 Logo 首选、App icon、启动动效、IP 主体基础。 - -### 4.5 陶泥面偶 - -![陶泥面偶](../../public/branding/taonier-logo-clay-mascot-concepts/taonier-clay-mascot-idol-mask.png) - -定位:面偶 / 头像化方向。 - -这个方向做出了陶泥面偶的收藏感,但人物感、服饰感和头像感都偏强,容易变成具体角色头像,而不是平台主标。 - -建议用途:IP 角色探索,不建议作为主 Logo 主线。 - -### 4.6 口袋泥人 - -![口袋泥人](../../public/branding/taonier-logo-clay-mascot-concepts/taonier-clay-mascot-pocket-figure.png) - -定位:最适合 App icon 的小泥人方向。 - -这个方向造型简洁,黑底白形识别快,旁边金色泥点和星点能强化“泥点 / 灵感”记忆。它比 04 更轻快,比 01 更不像普通姜饼人。 - -建议用途:App icon 强备选、移动端启动图标、品牌小形象。 - -## 5. 锚点底座参考图历史探索 - -用户明确要求停止此前软泥合拍、旋涡、糖果粉绿等方向,改以新的黑底白标参考图为原型重做。新参考图的核心不是“可爱软泥”,而是“一个泥点落到作品底座上”:上方圆点代表泥点 / 灵感,中间竖线代表落点 / 生成锚点,下方叠层代表作品、小游戏或创作底座。 - -这一组使用确定性矢量方式生成,优先保留黑底白标的克制感和成熟 App icon 气质,再少量测试金色泥点作为品牌识别。 - -> 2026-05-14 用户已要求停止锚点底座方向,本节降级为历史探索,不再作为当前主线。 - -![陶泥儿 Logo 锚点底座参考图总览](../../public/branding/taonier-logo-anchor-concepts/taonier-logo-anchor-contact-sheet.png) - -生成脚本: - -```text -scripts/generate-taonier-anchor-logo-concepts.py -``` - -生成文件: - -```text -public/branding/taonier-logo-anchor-concepts/ -├─ taonier-anchor-core.svg -├─ taonier-anchor-core.png -├─ taonier-anchor-soft-slab.svg -├─ taonier-anchor-soft-slab.png -├─ taonier-anchor-work-stack.svg -├─ taonier-anchor-work-stack.png -├─ taonier-anchor-clay-drop.svg -├─ taonier-anchor-clay-drop.png -├─ taonier-anchor-creation-base.svg -├─ taonier-anchor-creation-base.png -├─ taonier-anchor-app-token.svg -├─ taonier-anchor-app-token.png -└─ taonier-logo-anchor-contact-sheet.png -``` - -### 5.1 泥点锚标 - -![泥点锚标](../../public/branding/taonier-logo-anchor-concepts/taonier-anchor-core.png) - -定位:最贴近新参考图的主 Logo 首选。 - -这个方向保留“圆点 + 竖向落点 + 菱形作品底座 + 下层托底”的核心结构,整体克制、稳、识别快。它已经不再依赖软萌插画,而是更像一个可长期使用的产品符号。 - -优点: - -- 与新参考图原型一致性最高。 -- 黑底白标小尺寸识别强,适合 App icon、favicon、启动页。 -- “泥点落到作品底座”能承接泥点、AI 生成、作品成型三层语义。 - -风险: - -- 当前底座菱形偏硬,后续可让转角更像被压出的软泥层。 -- 左侧小点需要确认是品牌特征还是噪音,正式版可以保留或删除。 - -建议用途:当前主 Logo 第一候选、品牌顶栏、App icon。 - -### 5.2 软泥层台 - -![软泥层台](../../public/branding/taonier-logo-anchor-concepts/taonier-anchor-soft-slab.png) - -定位:更柔和的底座版本。 - -这个方向把底座做成略带弧度的软泥层,更贴近“陶泥儿”的名字,但轮廓相对没 01 清楚。适合继续测试“更软,但不回到旧软萌路线”的平衡。 - -建议用途:主 Logo 备选,适合做品牌温度版。 - -### 5.3 作品叠层 - -![作品叠层](../../public/branding/taonier-logo-anchor-concepts/taonier-anchor-work-stack.png) - -定位:最强调 UGC 作品库和多玩法承载。 - -这个方向比 01 多一层底座,能表达“一个灵感生成多个作品 / 多个小游戏层”。优势是平台感强,风险是线条略多,小尺寸时比 01 更拥挤。 - -建议用途:平台主标强备选、作品库 / 创作中心辅助标识。 - -### 5.4 泥点落印 - -![泥点落印](../../public/branding/taonier-logo-anchor-concepts/taonier-anchor-clay-drop.png) - -定位:加入品牌色的泥点版本。 - -这个方向把上方泥点和中心落点改成暖黄色,品牌记忆更强,也更贴合“泥点”货币 / 消费单位。但如果主标追求极简高级,金色可能需要降饱和或只保留上方圆点。 - -建议用途:App icon 彩色版、泥点体系标识、会员 / 奖励场景。 - -### 5.5 创作底座 - -![创作底座](../../public/branding/taonier-logo-anchor-concepts/taonier-anchor-creation-base.png) - -定位:更抽象、更像生成台的版本。 - -这个方向弱化了封闭菱形,强调开放式底座和生成落点。它更像“创作工具 / 生成器”符号,但少了 01 的完整徽标感。 - -建议用途:生成入口、创作按钮、工作台辅助图形。 - -### 5.6 泥点应用标 - -![泥点应用标](../../public/branding/taonier-logo-anchor-concepts/taonier-anchor-app-token.png) - -定位:更接近正式 App icon 的双色版本。 - -这个方向在黑蓝底上使用奶白主形和金色泥点,记忆点更强,也更像可直接落地的应用图标。后续需要测试金色小点在 24px / 32px 下是否仍然清楚。 - -建议用途:App icon 彩色候选、移动端启动图标。 - -## 6. V3-03 软泥合拍 v2 - -这一组回到用户认可的“软泥合拍”参考,不再追求具体手感。核心保留上下两团软泥、中央星点、轻快合拍的生动感,同时明确避开手、眼睛、聊天气泡和表情包。 - -![陶泥儿 Logo 软泥合拍 v2 总览](../../public/branding/taonier-logo-squish-concepts/taonier-logo-squish-contact-sheet.png) - -> 2026-05-14 用户已要求停止此前方向,本节及后续软泥合拍、旋涡、V3、V2、V1 均降级为历史探索,不再作为当前主线。 - -### 6.1 软泥合拍 - -![软泥合拍](../../public/branding/taonier-logo-squish-concepts/taonier-squish-v2-pulse.png) - -定位:当前最贴近参考方向的主 Logo 首选。 - -这个方向保留了上下两团软泥和中央星点,整体干净、生动、年轻,没有手的老气问题,也没有播放器或聊天工具联想。 - -优点: - -- 与用户认可的原始参考最接近。 -- 抽象但不冷,亲和且容易做动效。 -- 元素少,小尺寸可继续优化。 - -风险: - -- 形体还可以更有专属轮廓,避免变成通用软块组合。 - -建议用途:主 Logo 优先打磨方向、启动动效、生成按钮。 - -### 6.2 弹力成型 - -![弹力成型](../../public/branding/taonier-logo-squish-concepts/taonier-squish-v2-bounce.png) - -定位:动感和弹性更强的版本。 - -这个方向有轻快的挤压感,但线条和高光更接近动态图标或运营图,正式主 Logo 需要进一步去掉装饰线。 - -建议用途:生成动效、交互反馈、品牌运动语言。 - -### 6.3 星隙合拍 - -![星隙合拍](../../public/branding/taonier-logo-squish-concepts/taonier-squish-v2-spark-gap.png) - -定位:品牌记忆点最强的主标备选。 - -这个方向用中间负形星建立强记忆点,比 01 更像一个可注册的标志。它的优势是“符号性强”,但白色星隙较大,后续需要优化比例,让上下软泥更像合拍而不是被星形切开。 - -建议用途:主 Logo 强备选,适合继续做专业矢量微调。 - -### 6.4 合拍星流 - -![合拍星流](../../public/branding/taonier-logo-squish-concepts/taonier-squish-v2-comet.png) - -定位:传播和裂变感。 - -这个方向的星流表达“梗 / 作品被传播出去”,但短线让画面稍碎,更适合运营动效而不是静态主标。 - -建议用途:分享成功、生成完成、活动视觉。 - -### 6.5 成型软标 - -![成型软标](../../public/branding/taonier-logo-squish-concepts/taonier-squish-v2-token.png) - -定位:成熟 App icon 方向。 - -这个方向最像完整的 App icon,收束度高、成熟度好。但它有一点眼睛 / 观察 / 球形标识的风险,需要通过中心点、上下轮廓和色彩微调降低误读。 - -建议用途:App icon 备选,不建议未经微调直接定稿。 - -## 7. V3-03 上下手感延展 - -这一组顺着用户反馈中“03 更像上下两只手”的方向继续打磨。目标是把“托住灵感、合掌成型”的感觉做成品牌符号,而不是具体手掌插画。 - -用户进一步评审后认为 01 “掌心星核”太具象,手感明显、手形难看且老气。该方向整体降级为历史探索,不建议继续作为主 Logo 主线。 - -![陶泥儿 Logo 上下手感延展总览](../../public/branding/taonier-logo-hands-concepts/taonier-logo-hands-contact-sheet.png) - -### 7.1 掌心星核 - -![掌心星核](../../public/branding/taonier-logo-hands-concepts/taonier-hands-v2-cradle.png) - -定位:上下手感方向的主 Logo 首选。 - -这个方向最直接地保留了“上下两只手托住灵感”的感觉,同时仍是抽象软形。中央星核建立视觉焦点,能够承接“用户把脑洞交给 AI,一起捏成作品”的产品隐喻。 - -优点: - -- “托住 / 合捏 / 成型”的动作最明确。 -- 亲和力强,远离播放器、聊天和表情包联想。 -- 适合做轻微动效:上下软掌合拢,星核亮起。 - -风险: - -- 左侧线条有一点真实手指感,正式矢量化时应减少指节暗示,让它更像软泥托形。 - -建议用途:主 Logo 备选首选、生成按钮、启动动效、AI 共创标识。 - -### 7.2 合掌成型 - -![合掌成型](../../public/branding/taonier-logo-hands-concepts/taonier-hands-v2-clap.png) - -定位:最简洁、最主流的上下手感方案。 - -这个方向用上下两片大软形和中心圆点表达“合掌成型”,小尺寸识别会比 01 更稳。它的问题是整体有一点“眼睛 / 观察”联想,后续需要调整中心圆点和上下弧线比例。 - -建议用途:主 Logo 强备选,适合继续做专业矢量微调。 - -### 7.3 软掌托碗 - -![软掌托碗](../../public/branding/taonier-logo-hands-concepts/taonier-hands-v2-bowl.png) - -定位:创作容器和生成氛围。 - -这个方向更有场景感,像从掌心托出一个创意容器。它亲和、丰富,但装饰星点和喷溅线稍多,主 Logo 使用前需要大幅精简。 - -建议用途:创作页空状态、生成中插画、运营视觉。 - -### 7.4 双掌印记 - -![双掌印记](../../public/branding/taonier-logo-hands-concepts/taonier-hands-v2-seal.png) - -定位:完整、稳重、有泥印感的主标备选。 - -这个方向把上下软形合成一个圆润印记,中间负形有“被捏出”的感觉。它比 01 更不像真实手,也比 02 更有陶泥儿的“印记 / 成型”心智。 - -建议用途:主 Logo 备选;若后续想降低“手”的直观性,可以优先打磨这一版。 - -### 7.5 掌心开捏 - -![掌心开捏](../../public/branding/taonier-logo-hands-concepts/taonier-hands-v2-pop.png) - -定位:传播感和动效感。 - -这个方向更像“掌心弹出灵感”,年轻、轻松,适合做动效,但静态 Logo 里短线和星点稍碎。 - -建议用途:生成成功动效、活动视觉、引导页,不建议直接做主 Logo。 - -## 8. 横向发散造型补充 - -这一组在既有 V3 / 上下手感 / 一捏成型之外继续横向发散,刻意避开上一轮已经降级的播放键、聊天气泡、褐色陶土主色和碎元素。它更关注“平台入口、作品胚、游戏模芯、软体图腾、合捏火花”等造型。 - -![陶泥儿 Logo 横向发散总览](../../public/branding/taonier-logo-broad-concepts/taonier-logo-broad-contact-sheet.png) - -### 8.1 软泥入口 - -![软泥入口](../../public/branding/taonier-logo-broad-concepts/taonier-broad-soft-portal.png) - -定位:最接近“AI 创作入口”的平台符号。 - -这个方向像一枚被捏开的柔软门洞,中心星核留白明确,能承接“打开陶泥儿,进入创作”的心智。它保留了软泥和托举感,但没有真实手指、播放键或聊天气泡联想。 - -建议用途:主 Logo 强备选、创作首页入口、启动页核心动效。 - -### 8.2 作品胚芽 - -![作品胚芽](../../public/branding/taonier-logo-broad-concepts/taonier-broad-work-embryo.png) - -定位:精品作品和内容生长方向。 - -这个方向更像一颗正在成型的作品核,色彩偏青绿,整体高级、温和。它的产品语义更偏“作品孵化 / 创意生长”,和轻休闲小游戏的即时感弱一些。 - -建议用途:作品库、精选内容、创作者中心辅助标识;不建议优先做主 Logo。 - -### 8.3 游戏模芯 - -![游戏模芯](../../public/branding/taonier-logo-broad-concepts/taonier-broad-game-mold.png) - -定位:最强调“可玩”和小游戏平台属性。 - -这个方向把软泥主形和极简方向键 / 方块负形结合,能快速传达“生成出来的是可玩的互动作品”。深色底和强对比适合 App icon,但图形中的游戏控件联想较强,后续需要避免变成泛游戏平台图标。 - -建议用途:App icon 备选、玩法入口、游戏运行态品牌露出。 - -### 8.4 软体图腾 - -![软体图腾](../../public/branding/taonier-logo-broad-concepts/taonier-broad-soft-totem.png) - -定位:Taonier / 陶泥儿首字母感探索。 - -这个方向试图从软体纵向图腾里建立长期品牌记忆。它比普通字母标更柔软,也有捏塑感,但当前轮廓仍略像抽象数字或符号,正式使用前需要人工矢量重构。 - -建议用途:英文辅助标、favicon 探索、品牌图腾备选。 - -### 8.5 开捏火花 - -![开捏火花](../../public/branding/taonier-logo-broad-concepts/taonier-broad-creation-spark.png) - -定位:最稳定的“合捏生成”抽象主标备选。 - -这个方向把上下 / 左右的软形收成一个完整外轮廓,中心星核简洁,既能表达“开捏”,又比原始括号式结构更完整。它是本轮横向发散里最值得继续打磨的方向。 - -建议用途:主 Logo 强备选、生成按钮、AI 成功态和启动动效。 - -### 8.6 本轮未稳定产出的方向 - -`泥点皇冠`、`陶字负形` 和 `作品星轨` 的提示在本地 VectorEngine `gpt-image-2-all` 上多次超过 10 分钟仍未返回。后续若继续探索这些方向,建议先把 prompt 压短到单一造型,再单张运行,不要与批量任务混跑。 - -## 9. V3-03 一捏成型延展 - -这一组专门沿 V3 “一捏成型”继续打磨。目标是保留“两个软形触点 + 中央作品核”的成型瞬间,同时降低括号感、碰撞特效感和功能按钮感。 - -![陶泥儿 Logo 一捏成型延展总览](../../public/branding/taonier-logo-magic-dot-concepts/taonier-logo-magic-dot-contact-sheet.png) - -### 9.1 捏合星核 - -![捏合星核](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-orbit.png) - -定位:一捏成型方向的主标首选。 - -这个方向最稳地保留了“左右合拢、中央成型”的核心动作,中心青绿色星核形成了明确焦点,整体比原 V3-03 更完整,也没有明显播放器、聊天或表情联想。 - -优点: - -- 结构清楚,第一眼能看出“合拢生成”。 -- 元素少,小尺寸适配潜力好。 -- 中央星核可以做加载、生成成功、发布完成等动效延展。 - -风险: - -- 左右软形仍有一点括号感,后续矢量化可把外轮廓做得更不对称、更像被捏塑的软泥。 - -建议用途:主 Logo 备选首选、AI 生成按钮、启动动效核心符号。 - -### 9.2 成型印记 - -![成型印记](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-seal.png) - -定位:完整主标感最强的延展方向。 - -这个方向把左右触点收成一个更完整的软形图腾,减少了“两个括号”的割裂感。视觉上更像独立品牌符号,但也因此少了一点“捏合动作”的即时感。 - -建议用途:主 Logo 强备选;若选择它,后续应去掉背景底色并强化中心负形星点。 - -### 9.3 软泥合拍 - -![软泥合拍](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-squish.png) - -定位:轻松、年轻、动效友好。 - -这个方向的上下软形更活泼,适合表达“啪嗒一下成型”。但静态 Logo 中的黄色星点和短线略像特效贴纸,主标使用前需要继续简化。 - -建议用途:生成中动效、运营图、互动反馈,不建议直接定为主 Logo。 - -### 9.4 灵感模口 - -![灵感模口](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-mold.png) - -定位:最有“模口 / 造物容器”意味。 - -这个方向图形独特,和“从软泥模口里生成作品”的隐喻贴合。但外形复杂度比 01、02 更高,边缘细节在小尺寸下可能损失。 - -建议用途:主 Logo 备选探索,适合继续做专业矢量简化。 - -### 9.5 捏开灵感 - -![捏开灵感](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-bloom.png) - -定位:温和、包裹、生成容器。 - -这个方向亲和、平衡,但整体像眼睛 / 容器 / 开合结构,陶泥儿的“捏”动作弱一些。 - -建议用途:AI 生成入口、等待态、创作容器辅助图形。 - -## 10. 软泥合拍换色微调 - -这一轮不再改结构,也不改角度,只基于用户最认可的 `03 软泥合拍` 原图做配色和 Q 感微调。目标是保住“上下两团软泥 + 中央星点”的记忆点,只通过更甜、更轻、更亮的色彩关系,让它更像一个主流、亲和、容易记住的品牌符号。 - -![陶泥儿 Logo 软泥合拍换色总览](../../public/branding/taonier-logo-squish-recolor-variants/taonier-squish-recolor-contact-sheet.png) - -生成脚本: - -```text -scripts/generate-taonier-squish-recolor-variants.py -``` - -生成文件: - -```text -public/branding/taonier-logo-squish-recolor-variants/ -├─ taonier-squish-recolor-original-plus.png -├─ taonier-squish-recolor-candy-mint.png -├─ taonier-squish-recolor-peach-jelly.png -├─ taonier-squish-recolor-pop-bright.png -├─ taonier-squish-recolor-coral-soda.png -├─ taonier-squish-recolor-bubble-q.png -└─ taonier-squish-recolor-contact-sheet.png -``` - -推荐结论: - -- `02 糖果薄荷`:最均衡,保留原 03 的识别度,同时更轻、更甜。 -- `06 泡泡Q感`:最软萌,Q 感最强,适合做年轻化主视觉。 -- `04 亮彩出圈`:对比更强,适合传播场景和更醒目的入口图标。 -- `01 原版提亮`:最稳,几乎不改结构,适合作为保守版基线。 - -这一轮的结论是:如果后续只允许做“颜色修改或轻微可爱化”,优先沿原 03 继续做色彩细化,而不是重做造型。这样最能保住用户已经认可的那一下“软泥合拍”感觉。 - -## 11. 螺旋参考图延展 - -这一轮引入一张粗圆头黑白螺旋参考图,提取的是“向心旋转、包裹、揉合”的动势,而不是复刻黑白旋涡本身。生成时继续沿用前面认可的粉红、薄荷青、暖黄星点和软泥合拍语言,避免变成加载图、太极、棒棒糖或通用旋涡。 - -![陶泥儿 Logo 螺旋参考图延展总览](../../public/branding/taonier-logo-spiral-reference-concepts/taonier-logo-spiral-reference-contact-sheet.png) - -生成脚本: - -```text -scripts/generate-taonier-spiral-logo-concepts.mjs -scripts/generate-taonier-spiral-contact-sheet.py -``` - -生成文件: - -```text -public/branding/taonier-logo-spiral-reference-concepts/ -├─ taonier-spiral-reference.jpg -├─ taonier-spiral-soft-squish.png -├─ taonier-spiral-candy-roll.png -├─ taonier-spiral-star-core.png -├─ taonier-spiral-bouncy-clay.png -├─ taonier-spiral-creation-whirl.png -├─ taonier-spiral-soft-token.png -└─ taonier-logo-spiral-reference-contact-sheet.png -``` - -推荐结论: - -- `06 旋合软标`:最接近“原 03 软泥合拍 + 螺旋动势”的融合,整体完整,主标潜力最高。 -- `01 软泥旋合`:保留 Q 感和中心星点,亲和、可爱,适合继续做更扁平的人工矢量化。 -- `04 Q弹泥涡`:软萌感强,风险是中心星点偏贴纸感,适合做运营或启动动效参考。 -- `02 糖果泥卷`、`05 创作星涡`:最贴近参考图,但也最容易被误读成加载图、糖果卷或通用旋涡,主 Logo 优先级低于 01 / 06。 - -这一轮的结论是:螺旋参考图可以增强“AI 把灵感揉合成作品”的生成感,但主标不宜过分旋涡化。后续如果沿这条线继续,应以 `06 旋合软标` 为基准,把螺旋缝隙和上下软泥关系做得更像陶泥儿专属符号。 - -## 12. V3 抽象主标候选 - -V3 根据评审反馈重新避开了五个问题:播放三角、褐色陶土主色、聊天气泡 / 表情包、循环符号,以及过多碎元素。方向转为更抽象、更亮眼、更像长期主 Logo 的符号。 - -![陶泥儿 Logo V3 概念总览](../../public/branding/taonier-logo-v3-concepts/taonier-logo-v3-contact-sheet.png) - -### 12.1 灵感捏痕 - -![灵感捏痕](../../public/branding/taonier-logo-v3-concepts/taonier-v3-finger-spark.png) - -定位:主 Logo 首选。 - -这个方向用醒目的珊瑚红软形、指纹捏痕和星点负形建立记忆点。它不再依赖“陶泥的褐色”,而是用“被捏过的痕迹”表达陶泥儿的核心动作:用户把脑洞捏成作品。 - -优点: - -- 第一眼足够醒目,远离旧版褐色和播放器感。 -- 指纹捏痕有独特性,能承接“人人创作”和“亲手塑形”。 -- 元素少,适合继续矢量化和小尺寸适配。 - -风险: - -- 指纹弧线后续需要进一步简化,避免在 24px 以下变糊。 -- 星点比例要克制,避免变成普通灵感图标。 - -建议用途:主 Logo、App icon、平台顶栏、启动页、生成按钮。 - -### 12.2 脑洞种子 - -![脑洞种子](../../public/branding/taonier-logo-v3-concepts/taonier-v3-seed-pop.png) - -定位:创意生长与新手友好。 - -这个方向从“灵感发芽”切入,比陶泥更偏创造生命力。它亲和、可爱,但容易让用户联想到教育、植物、儿童启蒙或种植类产品。 - -建议用途:新手引导、创作孵化、儿童 / 寓教于乐支线,不建议作为主 Logo。 - -### 12.3 一捏成型 - -![一捏成型](../../public/branding/taonier-logo-v3-concepts/taonier-v3-magic-dot.png) - -定位:AI 把灵感合成为作品的瞬间。 - -这个方向很简洁,用左右两个软形触点和中心星点表达“捏合”。它避开了播放器和聊天气泡,也能做动效,但静态图形目前稍像碰撞特效或括号,需要继续重绘增强独特轮廓。 - -建议用途:生成按钮、AI 施法动效、主 Logo 备选微调方向。 - -### 12.4 作品胶囊 - -![作品胶囊](../../public/branding/taonier-logo-v3-concepts/taonier-v3-work-gem.png) - -定位:精品内容和作品沉淀。 - -这个方向更稳、更精品,青绿色也比褐色更吸睛。但整体像水滴、宝石或通用内容图标,和“捏”这个动作的关系弱。 - -建议用途:精选作品、作品库、创作者中心,不建议优先做主 Logo。 - -### 12.5 软体 T 形 - -![软体 T 形](../../public/branding/taonier-logo-v3-concepts/taonier-v3-soft-t.png) - -定位:英文辅助名 / Taonier 的抽象首字母。 - -这个方向试图做更品牌化的抽象符号,但当前形体还不够自然,也未形成足够强的“陶泥儿”心智。若未来英文名确定为 `Taonier` 或类似形式,可以继续沿这个方向做专业字母标重绘。 - -建议用途:英文标识探索,不作为当前主 Logo 首选。 - -## 13. V2 扁平矢量候选 - -第一批图形偏 3D 和拟物,更适合作为吉祥物、运营图或启动页气氛图,不适合作为长期主 Logo。V2 已把约束收紧为扁平、矢量、少元素、强轮廓和小尺寸可识别。 - -![陶泥儿 Logo 扁平概念总览](../../public/branding/taonier-logo-flat-concepts/taonier-logo-flat-contact-sheet.png) - -### 13.1 扁平开捏 - -![扁平开捏](../../public/branding/taonier-logo-flat-concepts/taonier-flat-play-clay.png) - -定位:最直接的主 Logo 候选。 - -这个方向用一团柔软陶泥承载播放符号,用户一眼能理解“点开玩 / 马上玩”,同时外形保留“捏出来”的不规则软泥感。 - -优点: - -- 识别速度最快,移动端小尺寸也成立。 -- 符合主流 App Logo 语言,亲和、不重、不技术冷。 -- 和“把脑洞捏成小游戏”的主张绑定最强。 - -风险: - -- 播放符号是常见母题,后续矢量化时要通过不规则软泥外轮廓、颜色和字标形成独特资产。 - -建议用途:主 Logo 首选、App icon、平台顶栏、分享卡片角标。 - -### 13.2 灵感泥星 - -![灵感泥星](../../public/branding/taonier-logo-flat-concepts/taonier-flat-spark-clay.png) - -定位:AI 创作与灵感生成。 - -这个方向比“扁平开捏”更品牌化,中心负形星点表达灵感、AI 生成和创意爆发。它没有播放符号那么直白,但更容易和“陶泥儿”的创作平台气质绑定。 - -优点: - -- 图形更简洁,品牌记忆点强。 -- 陶泥心智、AI 灵感和精品感比较平衡。 -- 适合未来扩成字标、启动页和生成态动效。 - -风险: - -- 对“小游戏/马上玩”的表达弱于播放符号。 - -建议用途:主 Logo 强备选、创作首页、AI 生成按钮和品牌主视觉。 - -### 13.3 造梗笑泥 - -![造梗笑泥](../../public/branding/taonier-logo-flat-concepts/taonier-flat-meme-smile.png) - -定位:社交传播和玩梗亲和力。 - -这个方向的气泡与笑脸非常亲和,适合表达“分享快乐”和“造梗”。但它和聊天、社区类产品的通用图形过近,作为主 Logo 可能会让用户误判产品品类。 - -建议用途:社区、评论、分享、活动贴纸,不建议做主 Logo。 - -### 13.4 共创泥环 - -![共创泥环](../../public/branding/taonier-logo-flat-concepts/taonier-flat-loop-mold.png) - -定位:AI 与用户共创闭环。 - -这个方向表达共创与循环,但生成结果带有偏柔和彩虹渐变的视觉倾向,与“陶泥儿”的软泥名称关联不够直观,也不如 01/02 容易记住。 - -建议用途:创作流程、共创能力、生成进度辅助图形。 - -### 13.5 精品泥印 - -![精品泥印](../../public/branding/taonier-logo-flat-concepts/taonier-flat-seal-blocks.png) - -定位:精品作品和内容集合。 - -这个方向像内容平台或作品库入口,能表达图片、用户、游戏等多形态内容。但图形元素较多,主标识别不如 01/02 凝练。 - -建议用途:精选作品、作品集、创作者中心、内容品质标识。 - -## 14. V1 立体探索 - -### 14.1 灵感陶团 - -![灵感陶团](../../public/branding/taonier-logo-concepts/taonier-clay-spark.png) - -定位:AI 共创与灵感造物。 - -这个方向把“陶泥”作为主视觉,内部用发光火花和节点表达 AI 赋能。它最贴“陶泥儿”名字本身,也能说明平台不是普通小游戏集合,而是从灵感生成作品的创作容器。 - -优点: - -- 与“陶泥儿”的名称绑定最强。 -- 有 AI、创作、造物的综合含义。 -- 适合启动页、品牌介绍、创作首页空状态。 - -风险: - -- 小尺寸下细节偏多,需要后续矢量化时压缩节点和纹理。 -- 如果色彩处理不当,会回到手工陶艺联想。 - -建议用途:品牌主视觉备选、官网/启动页、创作入口图形。 - -### 14.2 开玩模具 - -![开玩模具](../../public/branding/taonier-logo-concepts/taonier-play-mold.png) - -定位:把脑洞捏成小游戏。 - -这个方向用软陶捏出播放符号,最直接地连接“创作”和“马上玩”。它比单纯陶泥团更有产品动作,也更适合轻休闲、小游戏、短内容传播。 - -优点: - -- 识别强,小尺寸也清楚。 -- 与轻度休闲小游戏的关系最直接。 -- 适合作为 App icon 和主 Logo 图形。 - -风险: - -- 播放符号相对常见,需要后续在外轮廓、捏痕和色彩上做独特性。 -- 如果三角形过硬,会削弱“陶泥儿”的柔软感。 - -建议用途:主 Logo 首选、App icon、分享卡片角标、加载态图形。 - -### 14.3 造梗气泡 - -![造梗气泡](../../public/branding/taonier-logo-concepts/taonier-meme-bubble.png) - -定位:社交传播、玩梗、裂变。 - -这个方向把陶泥变形成聊天气泡和表情,强调“梗”和“传播”。它最有社交平台感,也适合表情包、活动贴纸和运营视觉。 - -优点: - -- 传播感强,年轻、轻松、容易做 IP 化。 -- 能承接社区、评论、分享和玩梗场景。 -- 比较容易延展成贴纸和表情包。 - -风险: - -- 偏软萌,可能削弱“精品 AI 创作平台”的质感。 -- 作为主 Logo 容易显得像聊天或表情产品。 - -建议用途:社区模块、活动运营、IP 辅助形象,不建议作为唯一主 Logo。 - -### 14.4 共创回路 - -![共创回路](../../public/branding/taonier-logo-concepts/taonier-creation-loop.png) - -定位:AI 与用户共同迭代生成。 - -这个方向用软陶带形成循环和造物轨迹,表达“灵感 -> AI 塑形 -> 用户修改 -> 作品传播”的闭环。它比其他方向更抽象,也更有平台级和工具级气质。 - -优点: - -- 高级、简洁,避免儿童化。 -- 适合表达 AI 共创、迭代和作品循环。 -- 可用于创作者工作台或生成进度标识。 - -风险: - -- 与“陶泥儿”名称的直观关联较弱。 -- 缺少小游戏和玩梗的即时识别。 - -建议用途:创作流程标识、AI 共创能力图标、品牌辅助图形。 - -### 14.5 精品泥印 - -![精品泥印](../../public/branding/taonier-logo-concepts/taonier-premium-seal.png) - -定位:精品内容、作品认证、创作者成果。 - -这个方向像一个被压印的软陶徽章,中间有方块和火花,比较适合表达“作品被打磨成型”。它的内容平台感强于游戏入口感。 - -优点: - -- 精品感和作品库气质较强。 -- 适合作品认证、精选、创作者徽章。 -- 与“陶泥压印”隐喻相对自然。 - -风险: - -- 细节较多,主 Logo 小尺寸可读性不如“开玩模具”。 -- 徽章感偏静态,轻休闲的即时性稍弱。 - -建议用途:精选作品标识、创作者荣誉、内容品质标签。 - -## 15. 推荐结论 - -优先级建议: - -```text -当前主 Logo 首选:抽象泥胚角色 A-01 泥芯主标 -当前主 Logo 强备选:抽象泥胚角色 A-03 泥种图符 -可控矢量基准:抽象泥偶 V2-01 陶泥小灵 -结构辅助参考:抽象泥偶 V2-04 软模团子 -灵气辅助参考:image-2 B-01 泥灵符号 -历史探索保留:几何抽象、具象陶泥人 / 手办、锚点底座、软泥合拍、螺旋参考图延展、V3 / V2 / V1 批次 -``` - -当前应停止继续推进软泥合拍、旋涡、糖果粉绿、锚点底座和具象小人插画路线。新的主线不是放弃陶泥人 / 手办 / 吉祥物,而是把它们消解成“抽象泥胚角色”:用一个像有生命的陶泥主形、一个偏心孔洞 / 作品核和少量星点,形成更成熟、更可注册、更像主 Logo 的符号。 - -后续优先围绕 `A-01 泥芯主标` 做人工矢量重绘:保留陶泥容器 / 泥胚的温度、偏心黑孔和小星点,但弱化陶罐口沿,避免被误读成传统陶艺品牌。若希望更轻、更像会动的小泥种,则以 `A-03 泥种图符` 为第二主线。 - -## 16. 后续落地建议 - -1. 基于 `A-01 泥芯主标` 做专业矢量重绘:保留一个主形、一个偏心孔、一个小星点,删除渐变和拟物口沿,避免过度像陶罐。 -2. 基于 `A-03 泥种图符` 做第二主线:保留白泥主体、偏心黑孔、底部陶土捏痕和星核,压平成纯矢量色块。 -3. 参考 `V2-01 陶泥小灵` 做可控 SVG 版本:把单眼改成泥点或负形捏痕,确保不是头像。 -4. 同步做 24px / 32px / 64px 小尺寸测试,淘汰小尺寸下像陶罐、表情包、头像、UI 控件或通用系统图标的版本。 -5. 输出黑底彩色、白底彩色、纯黑白、favicon 四套应用版,确认主标能脱离 App icon 底色使用。 -6. 字标不要直接使用生图结果,应单独设计“陶泥儿”中文字标,并准备英文辅助名。 -7. 正式应用前做商标近似检索,重点覆盖第 9、35、38、41、42 类。 -8. 若确认替换“百梦”,再更新现有命名规范文档、前端品牌组件、HTML metadata、后台和后端默认文案。 - -## 17. 纯形状发散新批次 - -上一轮“横向发散”仍然被判定不好看,所以本轮不再沿用软手、星核、入口、胚芽等惯性母题,而是转向更硬、更图形化的 App 标志草案:陶轮、模具窗格、骰面、口袋、舞台窗和印模孔洞。 - -![陶泥儿 Logo 纯形状发散总览](../../public/branding/taonier-logo-fresh-concepts/taonier-logo-fresh-contact-sheet.png) - -### 17.1 陶轮印记 - -![陶轮印记](../../public/branding/taonier-logo-fresh-concepts/taonier-fresh-wheel-imprint.png) - -定位:旋转的创作轮盘。 - -这个方向有速度感,也更像成熟消费级 App 主标。它已经远离软手和星核语言,适合继续测试小尺寸识别。 - -### 17.2 模具窗格 - -![模具窗格](../../public/branding/taonier-logo-fresh-concepts/taonier-fresh-mold-window.png) - -定位:多种作品从同一个模具里生成。 - -这个方向的四宫格负形有平台承载感,也能表达拼图、视觉小说、小游戏等多内容形态。但它更像系统入口图标,主 Logo 使用前需要进一步抽象。 - -### 17.3 泥点骰面 - -![泥点骰面](../../public/branding/taonier-logo-fresh-concepts/taonier-fresh-dot-dice.png) - -定位:泥点、玩法和随机脑洞。 - -这个方向游戏化最强,识别速度快,适合作为玩法或泥点体系衍生图标。主 Logo 风险是会被误读成骰子或桌游。 - -### 17.4 口袋世界 - -![口袋世界](../../public/branding/taonier-logo-fresh-concepts/taonier-fresh-pocket-world.png) - -定位:把脑洞装进口袋随手开玩。 - -这个方向亲和、有随身感,但图形稍像小世界插画,主标凝练度弱于陶轮和印模孔洞。 - -### 17.5 叙事舞台窗 - -![叙事舞台窗](../../public/branding/taonier-logo-fresh-concepts/taonier-fresh-stage-window.png) - -定位:视觉小说、RPG 与互动叙事。 - -这一版垂类内容方向很明确,适合叙事模板或视觉小说品牌分支;作为陶泥儿全平台主标会偏窄。 - -### 17.6 印模孔洞 - -![印模孔洞](../../public/branding/taonier-logo-fresh-concepts/taonier-fresh-punch-hole.png) - -定位:极简印模与作品冲孔。 - -这个方向轮廓最干净,是本批次里最适合继续做专业极简图标化的一张。后续可以把黑色主形、孔洞比例和两块彩色辅形继续压缩。 - -### 17.7 未稳定完成 - -`灵感绳结` 在本地 VectorEngine 上超时;`贴纸折角` 请求返回 429,上游提示当前分组负载饱和。后续如果继续追这组,建议把 prompt 再缩短,并改成单张串行跑。 - -## 18. 06 印模孔洞延展 - -这一组只沿 `12.6 印模孔洞` 继续,不再扩散到新母题。生成时把原 06 作为参考图输入,目标是保住“黑色不规则冲孔 + 中央白洞 + 右上珊瑚 / 左下青蓝”的识别关系,同时测试它能不能成为更稳的品牌主标。 - -![陶泥儿 Logo 06 印模孔洞延展总览](../../public/branding/taonier-logo-punch-hole-concepts/taonier-logo-punch-hole-contact-sheet.png) - -### 18.1 原型锁定微调 - -![原型锁定微调](../../public/branding/taonier-logo-punch-hole-concepts/taonier-punch-locked-shape.png) - -定位:不改变 06 基本造型的保守基准。 - -这一张基本保留原 06 的主轮廓、孔洞、右上红块和左下青块,只把边缘和比例做得更顺。它满足“先别动 06 本体”的要求,也适合作为后续人工矢量化时的基准稿。 - -建议用途:06 方向的锁定版、和原图并排做微调比较。 - -### 18.2 稳定主标 - -![稳定主标](../../public/branding/taonier-logo-punch-hole-concepts/taonier-punch-stable-icon.png) - -定位:本批次最值得继续打磨的主标方向。 - -这一张比原 06 更稳,黑色主形更像完整 App 标志,孔洞比例也更利于小尺寸识别。它仍然保留右上红、左下青的双辅形关系,没有偏离 06 的核心记忆点。 - -建议用途:主 Logo 候选、后续 24px / 32px / 64px 小尺寸测试。 - -### 18.3 孔洞比例 - -![孔洞比例](../../public/branding/taonier-logo-punch-hole-concepts/taonier-punch-hole-balance.png) - -定位:负形节奏测试。 - -这一张把黑色环形做得更圆、更符号化,孔洞也更规整。优点是识别干净,风险是个性少了一点,容易变成通用圆环标。它更适合作为比例参考,不建议直接定稿。 - -建议用途:孔洞比例、黑形厚薄和小尺寸识别测试。 - -### 18.4 彩色嵌合 - -![彩色嵌合](../../public/branding/taonier-logo-punch-hole-concepts/taonier-punch-color-inlay.png) - -定位:更年轻、更有活力的彩色版。 - -这一张的红青辅形和黑色主形嵌合得更自然,也更有“从泥板里取出作品碎片”的感觉。问题是彩色面积偏大,主标定稿前需要压低红青比例,否则会削弱黑色冲孔主形的记忆点。 - -建议用途:品牌活力版、运营场景、后续彩色比例压缩参考。 - -### 18.5 单色测试 - -![单色测试](../../public/branding/taonier-logo-punch-hole-concepts/taonier-punch-mono-test.png) - -定位:商标和极简场景测试。 - -这一张去掉了彩色辅形,只剩黑色冲孔和白色孔洞,证明 06 的核心轮廓在单色下仍然成立。但它也少了陶泥儿年轻、轻游戏的平台气质,不建议作为唯一主标。 - -建议用途:单色商标、印刷、极小尺寸兜底。 - -### 18.6 应用图标 - -![应用图标](../../public/branding/taonier-logo-punch-hole-concepts/taonier-punch-app-token.png) - -定位:App icon 图形强化版。 - -这一张黑色主形更饱满,右上红块比较稳定,但中心孔洞趋向圆,个性弱于 01 / 02。它适合拿来测试 icon 外框和启动页,但主标优先级低于 `13.2 稳定主标`。 - -建议用途:App icon 包装测试、启动页核心图形参考。 - -本批次结论: - -```text -06 延展首选:13.2 稳定主标 -不改基本造型基准:13.1 原型锁定微调 -彩色活力参考:13.4 彩色嵌合 -单色兜底参考:13.5 单色测试 -暂不直接定稿:13.3 孔洞比例、13.6 应用图标 -``` - -## 19. 04 彩色嵌合配色与中孔延展 - -这一组继续沿 `13.4 彩色嵌合` 推进。目标不是重新造型,而是在保持“圆润主环 + 右上珊瑚红 + 左下青蓝 + 中央孔洞”的基本结构下,测试两件事:第一,中间原本偏黑的主形是否可以换成更柔和的深色;第二,中央空心区域能否加入作品核、内窗或拼片内容,让它不只是白洞。 - -![陶泥儿 Logo 04 彩色嵌合配色与中孔延展总览](../../public/branding/taonier-logo-punch04-color-concepts/taonier-logo-punch04-color-contact-sheet.png) - -### 19.1 暖墨填芯 - -![暖墨填芯](../../public/branding/taonier-logo-punch04-color-concepts/taonier-punch04-warm-ink-core.png) - -定位:本批次最稳的保守延展。 - -这一张基本保住了 04 的三块嵌合关系,把纯黑主形降到温暖深灰,中间加入奶油色作品核。它的优势是没有大幅改结构,整体也比原 04 没那么硬。风险是灰色主形的品牌冲击力弱于黑色,需要继续测试更深一点的暖墨色。 - -建议用途:04 结构不变的主标微调基准。 - -### 19.2 靛蓝作品核 - -![靛蓝作品核](../../public/branding/taonier-logo-punch04-color-concepts/taonier-punch04-navy-game-core.png) - -定位:互联网 App 感测试。 - -这一张把主形改成模块化靛蓝环,色彩干净,但它已经明显偏离 04 的有机冲孔形态,更像通用系统图标或应用商店图标。中间作品核成立,但整体不建议继续作为 04 主线。 - -建议用途:色彩参考,不作为造型参考。 - -### 19.3 奶油内窗 - -![奶油内窗](../../public/branding/taonier-logo-punch04-color-concepts/taonier-punch04-cream-window.png) - -定位:柔和亲和版。 - -这一张把黑色主形大幅柔化,中央内窗也更像内容容器。优点是亲和、轻,但主形和红青辅形边界太软,品牌主标的冲击力不足。 - -建议用途:可作为启动页、运营图或浅色主题参考。 - -### 19.4 陶盒彩芯 - -![陶盒彩芯](../../public/branding/taonier-logo-punch04-color-concepts/taonier-punch04-clay-gradient-flat.png) - -定位:彩芯方向的失败参考。 - -这一张虽然有中间彩色泥芯,但外轮廓和色块位置已经明显变成新图形,不再像 04。它说明中孔内容不能做太复杂,也不能让彩色辅形绕到主形四周。 - -建议用途:不继续。 - -### 19.5 薄荷深影 - -![薄荷深影](../../public/branding/taonier-logo-punch04-color-concepts/taonier-punch04-mint-shadow.png) - -定位:清爽配色强备选。 - -这一张保留了 04 的动势,但主形换成深青绿后,气质更轻、更年轻。中央奶油小芯也比较克制。问题是左下青块变大后有一点抢主体,后续若继续,应压缩左下辅形,让主形重新占主导。 - -建议用途:04 配色强备选、年轻化品牌色参考。 - -### 19.6 内嵌拼片 - -![内嵌拼片](../../public/branding/taonier-logo-punch04-color-concepts/taonier-punch04-negative-tile.png) - -定位:中孔内容过度设计的参考。 - -这一张中间拼片语义明确,但外形已经变成对称徽章,失去了 04 的柔软不规则感。它也说明“中间内容设计”不宜出现太多模块,否则会像玩法图标而不是品牌 Logo。 - -建议用途:不继续。 - -本批次结论: - -```text -04 延展优先:14.1 暖墨填芯 -04 配色强备选:14.5 薄荷深影 -亲和浅色参考:14.3 奶油内窗 -只作色彩/反例参考:14.2 靛蓝作品核、14.4 陶盒彩芯、14.6 内嵌拼片 -``` - -下一步如果继续沿 04 打磨,建议以 `14.1 暖墨填芯` 的结构为基准,把主形加深到接近墨黑但保留暖度;中间只放一个非常克制的奶油色作品核,不再加入复杂拼片或多色内容。 - -## 20. REF-04 锁形配色与中孔填充 - -这一组不再使用 image-2 重新生成轮廓,而是直接读取 `13.4 彩色嵌合` 的像素轮廓做锁形换色:外轮廓、右上珊瑚红块、左下青蓝块和中央孔洞边界都保持不变,只替换主形颜色,并在中孔内部加入极简内容。因此这一组更适合判断配色和中孔策略,不适合评估新造型。 - -![陶泥儿 Logo REF-04 锁形配色与中孔填充总览](../../public/branding/taonier-logo-ref04-locked-color-concepts/taonier-logo-ref04-locked-color-contact-sheet.png) - -### 20.1 暖墨作品核 - -![暖墨作品核](../../public/branding/taonier-logo-ref04-locked-color-concepts/taonier-ref04-locked-warm-ink.png) - -定位:最稳的锁形主标基准。 - -这一版把纯黑主形改成暖墨色,中孔加入单个奶油色作品核。它保留了 REF-04 的结构,同时削弱了原黑色的生硬感。当前最适合继续微调,后续可以把暖墨再压深一点,保留柔和但不丢识别。 - -### 20.2 蓝墨作品核 - -![蓝墨作品核](../../public/branding/taonier-logo-ref04-locked-color-concepts/taonier-ref04-locked-blue-ink.png) - -定位:年轻互联网感。 - -深蓝主形比黑色更轻,也和青色辅形更协调。问题是蓝色会把陶泥儿的“软泥 / 手作”心智拉向科技或工具感,需要靠字标和品牌色系统补回温度。 - -### 20.3 梅紫双芯 - -![梅紫双芯](../../public/branding/taonier-logo-ref04-locked-color-concepts/taonier-ref04-locked-plum-ink.png) - -定位:内容生成感测试。 - -梅紫主形有记忆点,中孔双芯能表达多内容生成,但中孔内容稍显图标化。若继续,应把双芯合并成一个更柔软的小作品核。 - -### 20.4 墨绿小芯 - -![墨绿小芯](../../public/branding/taonier-logo-ref04-locked-color-concepts/taonier-ref04-locked-green-ink.png) - -定位:清爽配色测试。 - -墨绿主形让整体更轻、更亲和,但左下青色和主形色相接近,层次不如暖墨和蓝墨清楚。适合作为品牌辅助色参考,不建议优先做主标。 - -### 20.5 缩孔填芯 - -![缩孔填芯](../../public/branding/taonier-logo-ref04-locked-color-concepts/taonier-ref04-locked-shrink-core.png) - -定位:中孔缩小和内容填充测试。 - -这一版在不改孔洞边界的前提下,用奶油色内芯视觉上缩小了空洞,并放入红青两点。它证明中孔可以适当填充,但红青两点会把画面带向功能图标,正式版应更克制。 - -### 20.6 柔炭陶珠 - -![柔炭陶珠](../../public/branding/taonier-logo-ref04-locked-color-concepts/taonier-ref04-locked-soft-charcoal.png) - -定位:温和品牌感。 - -柔炭主形比暖墨更松弛,中孔陶珠也比较亲和。缺点是整体对比变弱,放到 32px 以下可能不如 `15.1 暖墨作品核` 清楚。 - -本批次结论: - -```text -锁形首选:15.1 暖墨作品核 -年轻配色备选:15.2 蓝墨作品核 -中孔缩小参考:15.5 缩孔填芯 -亲和辅助参考:15.6 柔炭陶珠 -暂不优先:15.3 梅紫双芯、15.4 墨绿小芯 -``` - -如果下一轮继续打磨 REF-04,建议保持 `15.1` 的单个奶油作品核,不再增加多点、多拼片或复杂图形;主形颜色在暖墨和蓝墨之间继续找一个更有品牌识别的深色。 - -## 21. REF-04 暖色主形与中孔星星 - -这一组继续锁定 REF-04 原型轮廓,只做两项变化:把中间黑色主形换成温暖色系,并在空心位置绘制一枚星星。右上珊瑚红块、左下青蓝块和整体冲孔结构保持不变。 - -![陶泥儿 Logo REF-04 暖色主形与中孔星星总览](../../public/branding/taonier-logo-ref04-warm-star-concepts/taonier-logo-ref04-warm-star-contact-sheet.png) - -### 21.1 陶土星 - -![陶土星](../../public/branding/taonier-logo-ref04-warm-star-concepts/taonier-ref04-warm-star-terracotta.png) - -定位:最贴近“陶泥儿”名字的暖色版。 - -陶土棕主形保留了足够对比,中心浅金星也比较轻,不会把中孔填得太满。它是本批次最值得继续微调的方向。 - -### 21.2 焦糖星 - -![焦糖星](../../public/branding/taonier-logo-ref04-warm-star-concepts/taonier-ref04-warm-star-caramel.png) - -定位:更亮、更甜的暖色版。 - -焦糖色比陶土棕更年轻,但也更接近食品或糖果联想。若后续品牌想更轻松可继续测试,否则优先级低于 `16.1 陶土星`。 - -### 21.3 可可星章 - -![可可星章](../../public/branding/taonier-logo-ref04-warm-star-concepts/taonier-ref04-warm-star-cocoa.png) - -定位:星星更明确的版本。 - -这一版在星星外加了奶油底托,识别更清楚,但中孔内容稍重,容易像徽章或按钮。后续如果保留底托,应缩小 15% 到 20%。 - -### 21.4 赤陶星 - -![赤陶星](../../public/branding/taonier-logo-ref04-warm-star-concepts/taonier-ref04-warm-star-rust.png) - -定位:暖色强备选。 - -赤陶色比 16.1 更红,和右上珊瑚块的关系更统一。整体温暖、亲和,但主形和红块色差变小,正式版需要略微拉开明度。 - -### 21.5 橄榄星 - -![橄榄星](../../public/branding/taonier-logo-ref04-warm-star-concepts/taonier-ref04-warm-star-olive.png) - -定位:偏自然的配色测试。 - -橄榄色主形与青蓝辅形关系较近,星星用红色后视觉中心偏硬。它更像辅助配色,不建议作为主标优先方向。 - -### 21.6 梅紫星 - -![梅紫星](../../public/branding/taonier-logo-ref04-warm-star-concepts/taonier-ref04-warm-star-plum.png) - -定位:成熟温暖版测试。 - -梅紫主形有记忆点,但和“陶泥儿”的泥感关联弱一些,中心青星也让色彩关系变复杂。适合保留为备选参考,不建议优先推进。 - -本批次结论: - -```text -首选:16.1 陶土星 -强备选:16.4 赤陶星 -更轻甜参考:16.2 焦糖星 -星星底托参考:16.3 可可星章 -暂不优先:16.5 橄榄星、16.6 梅紫星 -``` - -下一轮建议以 `16.1 陶土星` 为基准,保持星星单独存在,不加复杂底托;主形颜色可以在陶土棕和赤陶棕之间继续找更有品牌记忆的暖色。 - -## 17. REF-04 暖色主形与四角闪光星 - -这一组修正上一批的星形:中孔不再使用五角星,而是使用参考图中那种上下左右尖出的四角闪光星,并保留少量短光芒。REF-04 的外轮廓、红青辅形和中孔边界继续锁定不变。 - -![陶泥儿 Logo REF-04 暖色主形与四角闪光星总览](../../public/branding/taonier-logo-ref04-warm-sparkle-v2-concepts/taonier-logo-ref04-warm-sparkle-v2-contact-sheet.png) - -本批次结论: - -```text -首选:17.1 陶土四角闪光 -强备选:17.2 赤陶四角闪光 -轻甜参考:17.3 焦糖四角闪光 -低干扰参考:17.5 安静闪光 -暂不优先:17.4 可可四角闪光、17.6 梅紫四角闪光 -``` - -其中 `17.1` 最接近“陶泥儿”的暖泥感,星形也更接近参考图的四角闪光;`17.5` 去掉了周围小光芒,更安静,但品牌动感弱一点。后续建议在 `17.1` 的基础上继续微调星星大小和主形陶土色深浅。 - -## 18. REF-04 造型锁定与参考配色迁移 - -这一版按用户指定执行单张定向调整:锁定 `15.1 暖墨填芯` 的造型与分区关系,把参考软泥合拍图的粉红、薄荷青和黄色闪光语言迁移过来。原中间黑色主形改为暖黄色,中心空洞使用参考图中的四角闪光星和短光芒填充。 - -![陶泥儿 Logo REF-04 造型锁定与参考配色迁移](../../public/branding/taonier-logo-ref04-palette-transfer/taonier-logo-ref04-palette-transfer-contact-sheet.png) - -生成文件: - -```text -public/branding/taonier-logo-ref04-palette-transfer/ -├─ taonier-logo-ref04-palette-transfer-contact-sheet.png -└─ taonier-ref04-palette-transfer-warm-yellow-sparkle.png -``` - -结论:这版最严格满足“图一造型不变 + 图二配色迁移 + 暖黄色主形 + 四角闪光填充”的要求。后续若继续打磨,建议只微调暖黄色主形的明度和星星大小,不再改变外轮廓。 - -## 22. REF-04 淡暖黄与四角闪光星 v4 - -这一组使用 image-2 继续修正上一版反馈:中间主形不再使用土黄、脏黄或偏橙的暖黄,而是改为更温暖、低饱和、淡淡的奶油纸黄色;中心星星继续以四角闪光星参考裁剪图为准,重点避免被拉伸成细十字。 - -![陶泥儿 Logo REF-04 淡暖黄与四角闪光星 v4 总览](../../public/branding/taonier-logo-ref04-palette-refine-v4-concepts/taonier-logo-ref04-palette-refine-v4-contact-sheet.png) - -生成文件: - -```text -public/branding/taonier-logo-ref04-palette-refine-v4-concepts/ -├─ taonier-logo-ref04-palette-refine-v4-contact-sheet.png -├─ taonier-ref04-palette-refine-v4-cream-paper.png -├─ taonier-ref04-palette-refine-v4-warm-ivory.png -├─ taonier-ref04-palette-refine-v4-soft-champagne.png -└─ taonier-ref04-palette-refine-v4-pale-butter.png -``` - -本批次判断: - -```text -优先看:22.1 奶油纸淡黄、22.4 淡黄油暖白 -可作为更轻柔参考:22.2 暖象牙淡黄 -色彩高级但识别略弱:22.3 淡香槟暖黄 -不再使用:18 旧版土黄 -``` - -`22.1` 和 `22.4` 的中间黄色已经明显脱离旧版土黄,星星也不再是细长十字;`22.3` 的颜色最淡、最柔和,但粉红和薄荷青辅色也被一起降得偏软,小尺寸品牌识别可能弱一些。image-2 仍会轻微软化 REF-04 的外轮廓,若下一步要完全锁死造型,应以本批次的淡黄色与星星比例为参考,再回到确定性换色脚本或矢量稿做最终收口。 - -## 23. REF-04 填平中孔与中央亮星 v5 - -这一组根据用户给出的修改参考继续使用 image-2 精修 04 图标:补全左侧曲线,让淡黄主形更完整;将中央白色空心区域用同色淡黄填平;最后把四角闪光星改为更明亮的黄色并放在中央。 - -![陶泥儿 Logo REF-04 填平中孔与中央亮星 v5 总览](../../public/branding/taonier-logo-ref04-palette-refine-v5-concepts/taonier-logo-ref04-palette-refine-v5-contact-sheet.png) - -生成文件: - -```text -public/branding/taonier-logo-ref04-palette-refine-v5-concepts/ -├─ taonier-logo-ref04-palette-refine-v5-contact-sheet.png -├─ taonier-ref04-palette-refine-v5-filled-centered-spark.png -├─ taonier-ref04-palette-refine-v5-smooth-left-small-spark.png -├─ taonier-ref04-palette-refine-v5-balanced-bright-spark.png -└─ taonier-ref04-palette-refine-v5-solid-core-no-hole.png -``` - -本批次判断: - -```text -最接近本轮要求:23.1 填心居中亮星、23.3 平衡亮星 -更克制参考:23.2 顺滑左弧小亮星 -星星偏大参考:23.4 实体主形亮星 -``` - -`23.1` 和 `23.3` 都完成了中孔填平和亮黄星居中,左侧曲线也比 v4 更完整;`23.2` 更安静,但星星没有短光芒,视觉记忆点弱一点;`23.4` 的星星更醒目,但比例稍大,后续若作为主标应把星星缩小约 10%。 diff --git a/docs/design/【前端体验】寓教于乐Toca式横向世界地图入口概念图-2026-05-23.md b/docs/design/【前端体验】寓教于乐Toca式横向世界地图入口概念图-2026-05-23.md deleted file mode 100644 index fa0de027e..000000000 --- a/docs/design/【前端体验】寓教于乐Toca式横向世界地图入口概念图-2026-05-23.md +++ /dev/null @@ -1,48 +0,0 @@ -# 寓教于乐 马路街区式横向世界入口概念图 - -更新时间:`2026-05-23` - -## 背景 - -寓教于乐板块需要继续探索图形化玩法入口。前一轮“乐园地图 / 世界地图”方向已被证明不够贴近参考图,本轮进一步收敛为“中央马路串联主题小建筑群街区”的结构,让每一屏都像一个可横向滑动的儿童小镇街区。 - -## 参考结论 - -从参考图和视频里提炼出的关键结构是: - -1. 每一屏都是一组主题小建筑群,不是稀疏乐园点位。 -2. 中央马路是主路径,汽车沿路通过,边缘继续延伸到下一屏。 -3. 建筑群贴着道路两侧聚合,形成清晰街区,而不是围绕中央广场或环形路径展开。 -4. 左右两边都要有明确“可继续探索”的出画感,方便后续做横向滑动世界。 - -## 目标 - -- 视觉上像可滑动的儿童街区地图。 -- 每一屏都能作为独立探索单元,并且能自然接到前后相邻屏。 -- 保持寓教于乐既有的卡通绘本风,不借用真实品牌乐园或现成 IP。 -- 适合后续叠加入口按钮、焦点框和中文标题。 - -## 本次概念方向 - -1. 识物认知主街 -2. 绘画创作工坊街 -3. 运动音乐街区 -4. 自然探索实验大道 - -## 推荐方向 - -优先推荐 `绘画创作工坊街` 与 `运动音乐街区`。这两条在当前批次里最接近“中央马路 + 两侧主题小建筑群 + 左右可延展”的参考结构。 - -## 生图脚本 - -- 生成脚本:`scripts/generate-edutainment-road-town-map-concepts.mjs` -- 输出目录:`output/imagegen/edutainment-road-town-map-concepts-20260523/` -- 风格参考:`public/child-motion-demo/picture-book-grass-stage.png` - -## 说明 - -本次产物是设计概念稿,不直接进入正式资源目录。后续如果继续收敛,可以以 `城市公园脊` 为母版,向左、向右补相邻屏幕的区域内容。 - -## 当前结论 - -乐园分区结构可以抛弃,后续所有概念都优先按“马路街区式一屏一屏延展”的结构继续迭代。 diff --git a/docs/design/【前端体验】寓教于乐电视端乐园地图入口概念图-2026-05-18.md b/docs/design/【前端体验】寓教于乐电视端乐园地图入口概念图-2026-05-18.md deleted file mode 100644 index 2b6c4fc1e..000000000 --- a/docs/design/【前端体验】寓教于乐电视端乐园地图入口概念图-2026-05-18.md +++ /dev/null @@ -1,36 +0,0 @@ -# 寓教于乐电视端乐园地图入口概念图 - -更新时间:`2026-05-18` - -## 背景 - -寓教于乐板块需要一个面向电视端 / 横屏大屏的图形化入口,整体感觉接近主题乐园地图,但必须保留 Genarrative 现有的明亮卡通绘本插画风,不借用任何真实品牌乐园或版权角色。 - -## 目标 - -- 远看像一个完整乐园地图,近看能分辨每个玩法入口。 -- 入口区域清晰分区,后续可以叠加焦点框、按钮和中文标题。 -- 中心和下方保留足够留白,适合遥控器焦点、儿童角色或主推荐位。 -- 风格保持和寓教于乐现有草地舞台资源一致。 - -## 本次概念方向 - -1. 环形乐园岛:中央草地广场 + 外圈入口环路。 -2. 展开绘本地图:横向展开的大绘本页,左右页自然衔接。 -3. 云朵空中岛:多个浮岛通过彩虹桥和云朵步道连接。 -4. 草地舞台地图:更接近实际运行态的横屏草地入口首屏。 - -## 推荐方向 - -优先推荐 `草地舞台地图` 作为后续落地主方向,因为它与现有寓教于乐草地舞台最接近,且中央下方留白最适合后续叠加交互焦点。 - -## 生图脚本 - -- 生成脚本:`scripts/generate-edutainment-tv-map-concepts.mjs` -- 默认尺寸:`2048x1152` -- 风格参考:`public/child-motion-demo/picture-book-grass-stage.png` -- 输出目录:`output/imagegen/edutainment-tv-map-entry-concepts-20260518/` - -## 说明 - -本次结果是设计概念稿,不直接进入 `public/` 正式资源目录。后续若要继续细化,可在同一脚本里增加新的横屏变体,并保持“不写文字、不露品牌 IP、绘本插画风”这三条底线。 diff --git a/docs/planning/README.md b/docs/planning/README.md deleted file mode 100644 index 489f4e02b..000000000 --- a/docs/planning/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# 规划与优先级 - -本目录保存仍处于推进中的阶段计划、并行任务拆分、可派发任务包和验收顺序。长期稳定的产品与架构口径仍以根部融合文档为准。 - -## 当前计划 - -- [【玩法创作】创作流程统一总计划-2026-05-30.md](./【玩法创作】创作流程统一总计划-2026-05-30.md):创作入口、统一创作页、统一生成页、结果页、发布、作品架、广场和运行态的阶段计划、进度记录、并行波次和可直接派发的任务包。 - -## 维护规则 - -- 计划文档只记录可执行阶段、负责人切分、验收门禁和当前状态。 -- 已经稳定为长期约定的内容,应同步沉淀到 `docs/【玩法创作】平台入口与玩法链路-2026-05-15.md` 或 `docs/project-memory/shared-memory/`。 -- 若代码事实与计划冲突,以代码和当前融合文档为准,并回写更新本目录。 diff --git a/docs/planning/【玩法创作】创作流程统一总计划-2026-05-30.md b/docs/planning/【玩法创作】创作流程统一总计划-2026-05-30.md deleted file mode 100644 index 7965fc065..000000000 --- a/docs/planning/【玩法创作】创作流程统一总计划-2026-05-30.md +++ /dev/null @@ -1,375 +0,0 @@ -# 创作流程统一总计划 - -更新时间:`2026-05-30` - -## 总览 - -| 项目 | 当前值 | -| --- | --- | -| 总轮次 | 5 | -| 当前轮次 | Round 4(已收口) | -| 当前阶段 | Phase 6 | -| 当前状态 | Phase 0~6 已收口;统一创作页已升级为 `UnifiedCreationWorkspace`,平台壳不再直接依赖旧工作台文件 | -| 当前并行波次 | 波次 D(验收与冻结) | -| 当前重点 | 后续新增玩法按仓库入口规范、当前开发运维文档和现役定向测试验收 | - -## 目标与范围 - -本计划统一 Genarrative 所有玩法的创作链路,不再只跟踪首批的拼图、抓大鹅和敲木鱼。最终目标是让各玩法按同一条平台链路交付: - -```text -创作入口 -> 统一创作页/工作台 -> 统一生成页 -> 结果页 -> 试玩 -> 发布 -> 统一作品详情/作品架/广场 -> 正式 runtime -``` - -统一不是把所有玩法 UI 做成同一个表单,而是统一阶段、契约、恢复、生成反馈、错误承接、发布后去向和验收门禁。各玩法工作台仍负责真实输入控件、资产槽位、校验和提交。 - -## 当前进度 - -| 阶段 | 状态 | 说明 | -| --- | --- | --- | -| Phase 0 总计划与门禁 | 已完成 | 本文档、`docs/planning/README.md`、`docs/README.md` 和 `docs/project-memory/shared-memory/document-map.md` 已补齐入口;后续按 phase 扩展门禁。 | -| Phase 1 首批统一壳 | 已收口 | `puzzle`、`match3d`、`jump-hop`、`wooden-fish` 已接入 `UnifiedCreationPage` / `UnifiedGenerationPage`,竖屏滚动和字段契约已回归。 | -| Phase 1 补充统一壳 | 已收口 | `jump-hop` 也已接入 `UnifiedCreationPage` / `UnifiedGenerationPage`,统一创作页现在接管拼图、抓大鹅、跳一跳和敲木鱼四条入口的可见外壳与滚动。 | -| Phase 2 契约与配置治理 | 已完成 | `creationTypes[].unifiedCreationSpec`、前端 fallback、后台配置校验和文档门禁已按现有测试与 schema 检查收口。 | -| Phase 3 剩余表单/图片工作台接入 | 已收口 | 跳一跳、宝贝识物、方洞结果页与首批普通工作台回归已通过;方洞、大鱼按当前形态纳入最小回归,后续若迁移工作台再单独立项。 | -| Phase 4 特殊工作台接入策略 | 已收口 | RPG、视觉小说、汪汪声浪的最小例外/闭环回归已通过,例外口径已落到平台总链路文档。 | -| Phase 5 结果页、发布、作品架与广场收口 | 已收口 | 结果页、发布、公开详情、推荐 runtime 与公开 read model 最小自动回归已通过,公开详情作者展示口径已统一。 | -| Phase 6 全链路验收与冻结 | 已收口 | 跨玩法 smoke、移动端优先验收、回归矩阵、长期维护规则和冻结证据已补齐。 | - -此表即总进度记录,后续每次 phase 收口、启动或回退时,只更新这里和下方任务状态。 - -当前已完成 Round 0~4 / Phase 0~6。后续新增玩法或统一链路改动以仓库入口规范、当前开发运维文档和现役定向测试为质量基线。 - -## 执行轮次 - -按可交付批次拆成 5 轮(Round 0~4)。当前已完成 Round 0~4,Round 4 / 波次 D 已作为冻结基线收口。 - -| 轮次 | 覆盖阶段 | 目标 | 状态 | -| --- | --- | --- | --- | -| Round 0 | Phase 0 | 补齐总计划、文档入口和并行任务表 | 已完成 | -| Round 1 | Phase 2 | 契约与配置治理 | 已完成 | -| Round 2 | Phase 3 + Phase 4 | 普通工作台并行接入,特殊工作台先定例外边界 | 已完成 | -| Round 3 | Phase 5 | 结果页、发布、作品架与广场收口 | 已完成 | -| Round 4 | Phase 6 | 全链路验收与冻结 | 已完成 | - -## 阶段拆分 - -### Phase 0:总计划与执行门禁 - -目标:让团队有一个唯一可查的总计划、进度表和并行任务清单。 - -状态:已完成。 - -- 新增本计划文档和 `docs/planning/README.md`,并在 `docs/README.md`、`docs/project-memory/shared-memory/document-map.md` 中补上规划入口。 -- 补齐 `当前进度`、`执行轮次` 和可并行任务表,后续每个 phase 完成后更新本文档的状态、验收命令和风险。 - -退出条件: - -- 文档入口可从 `docs/README.md` 找到。 -- 总计划包含阶段、进度、并行任务、验收和风险。 - -### Phase 1:首批统一壳收口 - -目标:用低风险的四条链路验证统一创作/生成壳。 - -- 范围:`puzzle`、`match3d`、`jump-hop`、`wooden-fish`。 -- 创作页统一经过 `UnifiedCreationPage`,工作台保留各自真实输入能力。 -- 生成页统一经过 `UnifiedGenerationPage` 和 `CustomWorldGenerationView`。 -- 竖屏滚动由统一创作页承担,避免内层滚动窗。 - -状态:已收口。 - -### Phase 2:契约与配置治理 - -目标:把统一创作页从前端“能渲染”推进到平台配置“可治理”。 - -- 明确 `unifiedCreationSpec` 的字段种类、必填语义、阶段映射和兼容 fallback。 -- 后台配置、前台读取和 `api-server` 路由熔断继续以 SpacetimeDB 入口配置为事实源。 -- 前端本地 fallback 只服务旧后端或本地异常,不作为新增玩法事实源。 -- 为字段契约、入口开放状态、阶段映射补自动测试。 - -退出条件: - -- `creation-entry config` 契约在前后端文档中闭合。 -- 新增玩法不能绕过统一入口配置接线。 - -状态:已完成。 - -验证:`npm run check:encoding`、`npm run typecheck`、`npm run admin-web:typecheck`、`npm run check:spacetime-schema` 和统一创作页 / 统一生成页相关测试已通过。 - -### Phase 3:剩余表单/图片工作台接入 - -目标:把结构相近的玩法先迁到统一创作与生成壳,扩大覆盖面。 - -候选范围: - -- 第一批直接迁移:`jump-hop`、`baby-object-match` -- 需要先做工作台形态评估:`square-hole`、`big-fish` -- 其它已经是表单/图片输入工作台、且无复杂多阶段编辑器的玩法 - -统一要求: - -- 继续复用 `CreativeImageInputPanel`、`CreativeAudioInputPanel` 等现有通用输入组件。 -- 不在工作台 UI 中默认写规则说明或功能解释。 -- 自动素材生成走统一生成页;没有自动生成的玩法需要明确跳过生成页的阶段策略。 -- 结果页和 runtime 不因迁移创作页而改业务真相。 -- `square-hole`、`big-fish` 先评估是否保留 Agent 形态还是迁到表单/图片工作台,再决定是否进入直接迁移实现。 -- `jump-hop` 已纳入统一创作壳,后续若要调整字段或视觉,只能在统一壳与工作台之间协同改,不再恢复独立入口壳。 - -退出条件: - -- 每个接入玩法都有创作页、生成页或跳过生成页的明确验收。 -- 移动端竖屏能从标题、表单滚动到提交按钮。 - -状态:已收口。 - -2026-05-30 回归记录: - -- `jump-hop`、`baby-object-match`、`big-fish`、`square-hole` 的核心工作台 / 结果页 / runtime 测试已补齐并通过。 -- `jump-hop` 结果页刷新恢复已补齐 `profileId -> getWorkDetail` 回读;直达 `/creation/jump-hop/result` 且缺少恢复参数时显示“跳一跳草稿未恢复”恢复面板,不再白屏。 -- `square-hole` 结果页的试玩 / 发布路径已补齐服务 mock 回归,确认保存成功后才触发试玩和发布回调。 -- 首批普通工作台回归通过:拼图、抓大鹅、敲木鱼、跳一跳、宝贝识物、方洞结果页。 -- 竖屏浏览器 smoke 已覆盖 `/creation/jump-hop`、`/creation/baby-object-match`、`/creation/square-hole`、`/creation/bark-battle`、`/creation/visual-novel`、`/creation/jump-hop/generating`、`/creation/jump-hop/result`、`/runtime/jump-hop`,截图保存在 `.app/browser-check/phase-flow-20260530/`。 - -### Phase 4:特殊工作台接入策略 - -目标:处理不能直接套表单/图片工作台的玩法,先定边界再迁移。 - -候选范围: - -- RPG / 自定义世界 -- 视觉小说 -- 汪汪声浪(`bark-battle`) -- 其它多阶段编辑器、对话式 Agent 或特殊创作流 - -统一要求: - -- 必须在玩法文档中写明“创作工具模式例外”。 -- 例外只影响工作台内部,不影响入口配置、生成反馈、结果页、发布、作品架、广场和 runtime 的平台主链路。 -- 对话式或多阶段编辑器仍需和统一作品、统一错误、统一生成完成反馈对齐。 -- `bark-battle` 默认按特殊工作台收口;若后续产品决策确认可完全表单化,再单独前移到 Phase 3,不在本轮默认假设里。 - -退出条件: - -- 每个特殊玩法都有例外声明、阶段映射和验收清单。 -- 没有新增平行入口系统、平行作品架或平行公开列表。 - -状态:已收口。 - -2026-05-30 回归记录: - -- RPG 例外边界指定 interaction 测试通过。 -- Bark Battle 创作入口、结果页试玩/发布和正式 runtime 指定 interaction 测试通过。 -- 视觉小说工作台、生成阶段、结果页和运行态测试通过,当时的视觉小说负向扫描无异常。 - -### Phase 5:结果页、发布、作品架与广场收口 - -目标:把“创作页统一”推进到“交付链路统一”。 - -- 发布成功默认进入统一作品详情或明确的 runtime 去向。 -- 草稿架能恢复生成中、失败、待发布和已发布状态。 -- 公开列表、发现流、详情页优先消费后端 read model 或 BFF 缓存。 -- 跨流程错误统一进入 `PlatformErrorDialog`,异步完成统一进入 `PlatformTaskCompletionDialog`。 -- 私有 generated 图片展示前必须换签。 - -退出条件: - -- 每个可发布玩法都有作品架、公开详情、广场或明确不公开声明。 -- 生成中刷新、失败重试、发布后回读和登录切换都有测试或手测记录。 - -状态:已收口。 - -2026-05-30 回归记录: - -- 发布到作品详情、已发布作品进入详情、体验按钮直达 runtime、详情 profile 回读指定 interaction 测试通过。 -- 拼图已发布作品进入首页和移动端游戏分类、Big Fish 公开隐藏口径、Match3D 推荐 runtime 资源回读指定 interaction 测试通过。 -- 公开详情作者展示统一为“公开昵称 · 陶泥号”,`PlatformWorkDetailView` 与公共作者展示 helper 测试已回归。 -- 本地 API smoke 已在重新拉起 `dev:spacetime` 和 `dev:api-server` 后通过:`GET http://127.0.0.1:8082/healthz` 返回 `{"ok":true,"service":"genarrative-api-server"}`。 - -### Phase 6:全链路验收与冻结 - -目标:形成后续新增玩法可复用的稳定门禁。 - -- 按玩法输出创作入口、生成页、结果页、试玩、发布、作品架、广场、runtime smoke 矩阵。 -- 当时补齐跨玩法回归 / 冒烟矩阵,不再只覆盖首批四条链路;当前执行入口已收敛到根 `package.json` 和开发运维文档。 -- 固化移动端竖屏优先验收,桌面端作为兼容验证。 -- 补齐“新增玩法接入 PRD 检查块”和代码评审检查清单。 - -退出条件: - -- 全部计划内玩法均有明确状态:已统一、例外接入、暂不接入。 -- `npm run typecheck`、`npm run check:encoding` 和对应玩法门禁通过。 - -状态:已收口。 - -2026-05-30 冻结记录: - -- Phase 2 自动回归通过:入口配置、统一字段 spec、统一创作页和统一生成页测试共 11 项。 -- Phase 3 自动回归通过:拼图、抓大鹅、敲木鱼、跳一跳、宝贝识物、大鱼、方洞结果页相关测试共 67 项;跳一跳直达结果页恢复测试通过。 -- Phase 4 / Phase 5 指定交互回归通过:RPG 例外边界、Bark Battle 闭环、作品详情、推荐 runtime、公开 read model 与跳一跳恢复相关 interaction 测试共 18 项。 -- Phase 5 详情 / 弹窗 / 作品架回归通过:公开详情、错误弹窗、反馈弹窗、作品展示 helper、作品架交互测试共 63 项。 -- 当时的视觉小说负向扫描、`npm run check:spacetime-schema`、`npm run check:encoding` 均通过。 -- API smoke 通过:`GET http://127.0.0.1:8082/healthz` 返回 `{"ok":true,"service":"genarrative-api-server"}`。 -- 竖屏浏览器 smoke 通过并保存截图:`.app/browser-check/phase-flow-20260530-round5/`,覆盖 `/creation/jump-hop`、`/creation/visual-novel`、`/creation/square-hole`、`/creation/bark-battle`、`/creation/baby-object-match`、`/creation/jump-hop/generating`、`/creation/jump-hop/result`、`/runtime/jump-hop`。 - -### Phase 6 补充:跨玩法最小验收口径 - -Phase 6 不再继续拆新波次,当前只把 Phase 2 到 Phase 5 的最小验证集合收束成一份可直接执行的门禁矩阵。建议顺序如下: - -| 阶段 | 最小命令 | 说明 | -| --- | --- | --- | -| Phase 2 | `npm run check:encoding`、`npm run typecheck`、`npm run admin-web:typecheck`、`npm run test -- src/components/platform-entry/platformEntryCreationTypes.test.ts src/components/unified-creation/unifiedCreationSpecs.test.ts src/components/unified-creation/UnifiedCreationPage.test.tsx src/components/unified-creation/UnifiedGenerationPage.test.tsx` | 校验入口配置、统一字段 spec、统一创作页和统一生成页。 | -| Phase 3 | `npm run test -- src/components/unified-creation/workspaces/PuzzleCreationWorkspace.interaction.test.tsx src/components/unified-creation/workspaces/Match3DCreationWorkspace.interaction.test.tsx src/components/unified-creation/workspaces/WoodenFishCreationWorkspace.test.tsx src/components/unified-creation/workspaces/JumpHopCreationWorkspace.test.tsx src/components/jump-hop-result/JumpHopResultView.test.tsx src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx src/components/edutainment-creation/BabyObjectMatchWorkspace.test.tsx src/components/edutainment-result/BabyObjectMatchResultView.test.tsx src/components/edutainment-runtime/BabyObjectMatchRuntimeShell.test.tsx src/components/big-fish-creation/BigFishAgentWorkspace.interaction.test.tsx src/components/big-fish-result/BigFishResultView.test.tsx src/components/big-fish-runtime/BigFishRuntimeShell.test.tsx`;`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "direct jump hop result route"` | 校验普通表单 / 图片 / 音频工作台仍按结构化 payload 提交,跳一跳结果页直达恢复不白屏,并把 BabyObjectMatch / BigFish 一并纳入最小回归。 | -| Phase 4 | `npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "opening RPG agent workspace does not refetch session snapshot in a render loop|create tab resumes agent workspace when draft has no compiled result yet|create tab resumes agent workspace when session has no draft profile even if summary counts look compiled|opening a compiled draft with a missing agent session falls back to draft hub"`、`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "create tab opens bark battle entry form from the template card|bark battle draft result can test before publish and publish to work detail|direct bark battle runtime public code opens published runtime"`、`npm run test -- src/components/visual-novel-creation/VisualNovelAgentWorkspace.test.tsx src/components/visual-novel-result/VisualNovelResultView.test.tsx src/components/visual-novel-runtime/VisualNovelRuntimeShell.test.tsx` | 校验特殊工作台例外、Bark Battle 公开闭环和视觉小说现役链路。 | -| Phase 5 | `npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "agent draft result publishes to gallery from publish panel|creation hub published work enters existing detail view|creation hub published work experience button enters world directly|creation hub published work start uses loaded detail profile instead of library summary"`、`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "published puzzle works appear on home and mobile game category channel|published big fish works stay hidden from platform home and mobile game category channel|home recommendation Match3D runtime keeps profile generated models when card summary is stale|home recommendation Match3D runtime passes top-level UI background assets|home recommendation Match3D runtime reloads detail when card only has UI assets"`、`npm run test -- src/components/platform-entry/PlatformWorkDetailView.test.tsx src/components/platform-entry/PlatformErrorDialog.test.tsx src/components/platform-entry/PlatformFeedbackView.test.tsx src/components/rpg-entry/rpgEntryWorldPresentation.test.ts`、`npm run test -- src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx` | 校验结果页、发布、作品架、公开详情、推荐 runtime 和公开 read model,并补公开详情作者展示口径与作品架恢复矩阵。 | - -如果这轮还改了 SpacetimeDB schema,追加 `npm run check:spacetime-schema`;如果还改了 API 路由、BFF、公开列表或 `/works/detail` 回读,追加 `npm run dev:api-server`,并另开终端从 `.app/dev-stack.json` 读取实际 `api-server` URL 后检查 `/healthz`。 - -## 可并行任务列表 - -| 任务 ID | 可并行 | 状态 | 任务 | 主要产出 | 依赖 | 建议 Owner | -| --- | --- | --- | --- | --- | --- | --- | -| T0-1 | 否 | 已完成 | 总计划与文档入口 | 本文档、`docs/planning/README.md`、文档索引更新 | 无 | 文档 owner | -| T1-1 | 否 | 已完成 | Phase 1 收口确认 | 三条首批链路验收记录、已知风险 | T0-1 | 前端 owner | -| T2-1 | 是 | 已完成 | `unifiedCreationSpec` 契约审计 | 字段种类、必填、阶段映射、fallback 规则 | T0-1 | 契约 owner | -| T2-2 | 是 | 已完成 | 后台入口配置治理 | 后台配置校验与配置说明 | T2-1 | 后台 owner | -| T2-3 | 是 | 已完成 | 前端入口读取与 fallback 测试 | 入口配置单测、异常兜底测试 | T2-1 | 前端 owner | -| T3-1 | 是 | 自动回归通过 | 跳一跳统一接入方案与实现 | 统一创作工作台、生成页迁移、验收 | T2-1 | 玩法 owner A | -| T3-2 | 是 | 自动回归通过 | 宝贝识物统一接入方案与实现 | 创作页/生成页迁移、验收 | T2-1 | 玩法 owner B | -| T3-3 | 是 | 最小回归通过 | 方洞工作台形态评估与迁移方案 | 保留 Agent 形态还是迁表单的决策、边界和风险清单 | T2-1 | 玩法 owner C | -| T3-4 | 是 | 最小回归通过 | 大鱼工作台形态评估与迁移方案 | 保留 Agent 形态还是迁表单的决策、边界和风险清单 | T2-1 | 玩法 owner D | -| T4-1 | 是 | 自动回归通过 | RPG 例外边界设计 | 例外声明、阶段映射、验收清单 | T2-1 | 特殊玩法 owner | -| T4-2 | 是 | 自动回归通过 | 视觉小说例外边界设计 | 例外声明、阶段映射、验收清单 | T2-1 | 特殊玩法 owner | -| T4-3 | 是 | 自动回归通过 | 汪汪声浪(bark-battle)统一/例外决策 | 接入或例外方案、验收清单 | T2-1 | 特殊玩法 owner | -| T5-1 | 是 | 最小回归通过 | 统一结果页能力矩阵 | 每个玩法结果页能力与缺口表 | T3/T4 方案稳定 | 结果页 owner | -| T5-2 | 是 | 最小回归通过 | 作品架恢复矩阵 | 生成中、失败、待发布、已发布恢复验收 | T3/T4 方案稳定 | 作品架 owner | -| T5-3 | 是 | 最小回归通过 | 公开 read model 对齐 | 广场/详情/分享码缺口与执行清单 | T3/T4 方案稳定 | 后端 owner | -| T5-4 | 是 | 最小回归通过 | 统一错误与完成反馈回归 | `PlatformErrorDialog`、`PlatformTaskCompletionDialog` 覆盖 | T3/T4 方案稳定 | 平台壳 owner | -| T5-5 | 是 | 自动回归通过 | 统一创作壳滚动收口 | `UnifiedCreationPage` 统一接管四条入口滚动、跳一跳纳入统一壳 | T3/T4 方案稳定 | 平台壳 owner | -| T6-1 | 否 | 已完成 | 全链路质量门禁扩展 | Phase 2 到 Phase 5 最小验证集合;现已收敛到根脚本和开发运维文档 | T3/T4/T5 完成 | QA owner | -| T6-2 | 否 | 已完成 | 全量验收与冻结 | 状态表、未接入声明、最终测试记录 | T6-1 | Release owner | - -并行原则: - -- T2 系列已完成,T3/T4 已进入回归;后续缺口修补仍不得绕过 T2 已固定的入口配置和统一 spec 规则。 -- T3 各玩法可并行,但同一文件同一时间只允许一个 owner,尤其是 `PlatformEntryFlowShellImpl.tsx`、路由和 shared contracts。 -- T5 可以在 T3/T4 各玩法方案稳定后分块并行,不必等所有玩法实现完再开始。 -- T6 必须串行收尾,避免验收矩阵和实际实现漂移。 - -## 可直接派发的任务包 - -任务包是执行层最小分工单元。每个包都可以单独开分支、单独验收;如果两个包需要改同一个公共文件,先由公共 owner 合并接口或壳层改动,再由玩法 owner 接入,避免互相覆盖。 - -| 包 ID | 可并行对象 | 状态 | 目标 | 不做什么 | 交付物 | 验收 | -| --- | --- | --- | --- | --- | --- | --- | -| P2-A 契约包 | 可与 P2-B、P2-C 并行 | 已完成 | 固定 `unifiedCreationSpec` 字段类型、必填、阶段映射、fallback 规则 | 不接新玩法,不改 UI 设计方向 | 前后端契约、配置字段文档、契约测试 | `npm run test -- src/components/unified-creation/unifiedCreationSpecs.test.ts src/components/platform-entry/platformEntryCreationTypes.test.ts`;涉及 schema 时追加 `npm run check:spacetime-schema` | -| P2-B 后台配置包 | 可与 P2-A、P2-C 并行 | 已完成 | 后台入口配置能编辑、校验、保存统一创作契约 | 不做玩法工作台迁移 | 后台表单、保存校验、异常提示、后台单测 | `npm run admin-web:typecheck`;`npm run test -- apps/admin-web/src/pages/AdminCreationEntrySwitchPage.test.tsx` | -| P2-C 前台读取包 | 可与 P2-A、P2-B 并行 | 已完成 | 前台从 `/api/creation-entry/config` 读取统一 spec,旧后端只走兜底 | 不把 fallback 当事实源,不恢复硬编码入口 | 入口派生、fallback 单测、统一创作/生成页回归 | `npm run test -- src/components/unified-creation/UnifiedCreationPage.test.tsx src/components/unified-creation/UnifiedGenerationPage.test.tsx` | -| P3-A 跳一跳接入包 | 可与 P3-B、P3-C、P3-D 并行 | 自动回归通过 | `jump-hop` 接入统一创作壳、生成页或明确跳过策略 | 不改正式 runtime 规则真相,不重做作品架 | 入口阶段映射、统一工作台接入、生成/结果跳转、竖屏验收 | 跳一跳相关单测、统一创作页回归、移动端 `/creation/jump-hop` smoke | -| P3-B 宝贝识物接入包 | 可与 P3-A、P3-C、P3-D 并行 | 自动回归通过 | `baby-object-match` 接入统一创作壳、生成页或明确跳过策略 | 不复制上传/历史素材逻辑 | 工作台接入、资产槽位复用、结果跳转、竖屏验收 | 宝贝识物相关单测、统一创作页回归、移动端 `/creation/baby-object-match` smoke | -| P3-C 方洞评估包 | 可与 P3-A、P3-B、P3-D 并行 | 部分回归通过 | 判断 `square-hole` 保留 Agent 形态还是迁表单/图片工作台 | 不直接大改实现 | 例外或迁移方案、字段清单、风险、验收用例 | 文档评审通过;若改代码,补对应工作台测试 | -| P3-D 大鱼评估包 | 可与 P3-A、P3-B、P3-C 并行 | 部分回归通过 | 判断 `big-fish` 保留 Agent 形态还是迁表单/图片工作台 | 不直接大改实现 | 例外或迁移方案、字段清单、风险、验收用例 | 文档评审通过;若改代码,补对应工作台测试 | -| P4-A RPG 例外包 | 可与 P4-B、P4-C 并行 | 自动回归通过 | 明确 RPG 对话式工作台如何接入统一阶段、错误、完成、发布去向 | 不把 RPG 当新增玩法默认模板 | 例外声明、阶段映射、刷新恢复和发布验收 | RPG 指定 interaction 测试、作品详情/进入世界回归 | -| P4-B 视觉小说例外包 | 可与 P4-A、P4-C 并行 | 自动回归通过 | 明确视觉小说特殊生成和结果页边界 | 不迁入外部平台社区、支付、榜单、回放 | 例外声明、上传资产口径、生成/结果/发布验收 | 视觉小说创作、结果和运行态相关测试 | -| P4-C 汪汪声浪决策包 | 可与 P4-A、P4-B 并行 | 自动回归通过 | 判断 `bark-battle` 是特殊工作台例外还是回到表单模式 | 不同时做两套入口 | 决策记录、阶段映射、发布和 runtime 验收 | Bark Battle 创作、发布、runtime 指定测试 | -| P5-A 结果页矩阵包 | 可与 P5-B、P5-C、P5-D 并行 | 最小回归通过 | 列清每个玩法结果页能力、缺口和最小补丁 | 不在结果页新增无需求的大功能 | 结果页能力矩阵、局部重试/上传/发布边界 | 对应结果页测试和手测记录 | -| P5-B 作品架恢复包 | 可与 P5-A、P5-C、P5-D 并行 | 最小回归通过 | 生成中、失败、待发布、已发布都能从作品架恢复 | 不只靠前端内存 notice | 作品摘要字段、作品架 adapter、恢复测试 | 作品架相关 interaction 测试;移动端草稿 Tab smoke | -| P5-C 公开 read model 包 | 可与 P5-A、P5-B、P5-D 并行 | 最小回归通过 | 公开列表、详情、分享和推荐 runtime 对齐后端 read model | 不让前端拼源表当事实源 | 后端 read model/BFF 缺口清单和实现 | 公开列表/详情/API smoke;必要时 `npm run dev:api-server` + `/healthz` | -| P5-D 统一反馈包 | 可与 P5-A、P5-B、P5-C 并行 | 最小回归通过 | 错误和异步完成统一进入平台弹窗 | 不在页面内重复裸错误 banner | `PlatformErrorDialog`、`PlatformTaskCompletionDialog` 覆盖矩阵 | 平台弹窗测试、跨流程失败/完成手测 | -| P6-A 门禁包 | 串行,依赖 P3/P4/P5 | 已完成 | 固化跨玩法自动测试、竖屏手测和 API smoke | 不继续接新玩法 | 冻结前命令集合;现已收敛到根脚本和开发运维文档 | 跨玩法回归与冒烟验证通过 | -| P6-B 冻结包 | 串行,依赖 P6-A | 已完成 | 更新总状态表,标记已统一、例外接入、暂不接入 | 不遗留“状态未知”玩法 | 总进度、风险清单、后续维护规则 | `npm run check:encoding`、关键门禁通过、文档索引有效 | - -### 并行执行注意事项 - -- 公共壳层 owner 统一负责 `PlatformEntryFlowShellImpl.tsx`、`appPageRoutes.ts`、入口阶段类型、共享 contract 和统一生成页主流程;玩法 owner 只接自己的工作台和映射。 -- 后端 schema owner 统一负责 SpacetimeDB 表、`migration.rs`、表目录和 bindings;玩法 owner 不单独改 schema 后跳过生成绑定。 -- 文档 owner 每轮只更新本计划的状态、波次和风险,不把一次性聊天记录写进长期文档。 -- 同一波次内如果发现计划和代码事实冲突,先改计划和对应融合文档,再继续实现;不要在代码里临时绕开统一链路。 - -### 依赖关系摘要 - -- 可以并行启动:`T3-1`、`T3-2`、`T3-3`、`T3-4`,其中 `T3-3` 和 `T3-4` 先做形态评估,`T3-1` 和 `T3-2` 可以直接进入实现。 -- 可以并行启动:`T4-1`、`T4-2`、`T4-3`,但它们只做例外边界和决策,不直接扩散到新的玩法实现。 -- `T5-1`、`T5-2`、`T5-3`、`T5-4` 可以并行预研,但最好等至少一批 Phase 3 / 4 方案稳定后再落代码。 -- `T6-1`、`T6-2` 必须串行,且都依赖 Phase 3 到 Phase 5 的验证结果。 - -## 并行波次 - -### 波次 A:先定契约 - -状态:已完成。 - -- `T2-1` `unifiedCreationSpec` 契约审计 -- `T2-2` 后台入口配置治理 -- `T2-3` 前端入口读取与 fallback 测试 - -说明:三项可以并行,先把统一创作入口的真值源、后台编辑面和前端兜底一起收紧。 - -### 波次 B:第一批迁移与例外评估 - -状态:自动回归已通过,遗留形态评估按缺口任务继续跟踪。 - -- `T3-1` `jump-hop` 统一接入 -- `T5-5` 统一创作壳滚动收口 -- `T3-2` `baby-object-match` 统一接入 -- `T3-3` `square-hole` 工作台形态评估 -- `T3-4` `big-fish` 工作台形态评估 -- `T4-1` `RPG` 例外边界设计 -- `T4-2` `视觉小说` 例外边界设计 -- `T4-3` `汪汪声浪(bark-battle)` 统一/例外决策 - -说明:`jump-hop`、`baby-object-match` 已完成最小接入回归;`square-hole`、`big-fish` 的形态评估继续按缺口任务跟踪;特殊工作台例外边界已完成最小回归。 - -### 波次 C:交付链路收口 - -状态:最小回归通过。 - -- `T5-1` 统一结果页能力矩阵 -- `T5-2` 作品架恢复矩阵 -- `T5-3` 公开 read model 对齐 -- `T5-4` 统一错误与完成反馈回归 - -说明:交付链路已按页面 / read model / 弹窗分块完成最小回归,后续只处理验收发现的真实缺口。 - -### 波次 D:验收与冻结 - -状态:已收口。 - -- `T6-1` 全链路质量门禁扩展 -- `T6-2` 全量验收与冻结 - -说明:必须串行,先补门禁再冻结状态表。 - -## 验收矩阵 - -每个玩法推进时至少记录: - -| 验收项 | 要求 | -| --- | --- | -| 创作入口 | 从创作 Tab 或直达 URL 能进入对应工作台,入口事实源来自 `/api/creation-entry/config`。 | -| 创作页 | 统一标题/阶段壳存在,工作台不重复渲染巨大旧标题,移动端可滚动到提交按钮。 | -| 输入控件 | 图片、音频、文本、选择器复用现有通用组件,不复制上传/历史图逻辑。 | -| 生成页 | 自动生成玩法使用统一圆环生成页;无生成页玩法有明确跳转策略。 | -| 结果页 | 能展示草稿、编辑作品信息、处理局部重生成、试玩和发布。 | -| 恢复 | 刷新、退出登录、生成中、失败、作品架恢复都有可观察行为。 | -| 发布与公开 | 发布后能进入统一详情或 runtime;公开列表/read model 不靠前端拼源表。 | -| runtime | 试玩与正式运行态区分清楚,正式业务真相以后端为准。 | -| 移动端 | 竖屏优先,无按钮遮挡、套滚动、文字溢出或固定底栏遮挡。 | - -## 统一约束 - -- 不恢复前端硬编码入口配置。 -- 不新建平行创作入口系统、平行作品架或平行公开列表。 -- 不把功能说明、规则说明或开发解释默认写进 UI 面板。 -- 不让前端承接发布、计分、胜负、资产持久化或公开状态等业务真相。 -- 后端仍按 `server-rs + Axum + SpacetimeDB` 和 DDD 分层推进。 -- 涉及 SpacetimeDB schema 时必须同步 migration、表目录、生成绑定,并运行 schema 检查。 - -## 推荐推进顺序 - -1. 将 Round 4 / Phase 6 作为当前冻结基线,后续只做同口径回归,不再新增波次。 -2. 对 Phase 3、Phase 4、Phase 5 只处理回归发现的真实缺口,不扩新玩法。 -3. 更新冻结状态表,明确每个玩法是已统一、例外接入还是暂不接入。 -4. 后续新增玩法默认遵循仓库入口规范、当前开发运维文档和现役定向测试,无需再补新的总计划轮次。 - -当前轮次看 Round 4 / Phase 6;Round 0~4 已作为历史完成记录保留。 diff --git a/docs/prd/BABY_OBJECT_MATCH_EDUTAINMENT_TEMPLATE_PRD_2026-05-11.md b/docs/prd/BABY_OBJECT_MATCH_EDUTAINMENT_TEMPLATE_PRD_2026-05-11.md deleted file mode 100644 index 95c74dd9e..000000000 --- a/docs/prd/BABY_OBJECT_MATCH_EDUTAINMENT_TEMPLATE_PRD_2026-05-11.md +++ /dev/null @@ -1,121 +0,0 @@ -# 宝贝识物寓教于乐模板 PRD 2026-05-11 - -## 1. 目标 - -新增寓教于乐内容线的创作模板: - -```text -宝贝识物 -``` - -创作者必须通过该模板创作并发布作品后,用户才能在寓教于乐板块体验对应关卡。 - -本模板只服务儿童动作 Demo 内容线,不把普通教育题材作品自动归入寓教于乐。 - -## 2. 创作输入 - -创作者必须填写两个物品名称: - -1. 物品 A 名称; -2. 物品 B 名称。 - -两个名称都必须去除首尾空白后非空。当前阶段不新增题材、难度、计时、失败次数、分数、体力或递增规则。 - -## 3. 生成规则 - -提交后生成一份宝贝识物草稿,草稿包含: - -1. 模板 ID:`baby-object-match`; -2. 模板名称:`宝贝识物`; -3. 两个物品; -4. 两个物品图; -5. 游戏视觉主题包; -6. 作品标签。 - -素材使用 VectorEngine `gpt-image-2` / image-2 生成。图片生成只能走后端接口,前端不得读取、拼接或暴露 `VECTOR_ENGINE_API_KEY`。 - -为降低生成成本,创作提交后只生成两张原始图片:一张 `2x2` 素材 sheet 和一张单独场景背景图。`2x2` 素材 sheet 固定包含左上物品 A、右上物品 B、左下篮子、右下礼物盒。服务端必须按固定格切图,并把物品、篮子和礼物盒转成透明 PNG。只有透明抠图后的两个物品素材才允许写入草稿 `itemAssets` 并进入游戏运行态。左右手位置指示器属于运行态默认规则,使用项目内置静态素材,不在每次创作时生成。 - -同一次创作还必须生成游戏视觉主题包,必需资源为背景环境、礼物盒、篮子。主题包必须继续保持寓教于乐插画风,并根据用户填写的两个物品关键词匹配主题:例如关键词偏动漫角色或玩具时,背景环境和元素可使用动漫、玩具主题;关键词偏水果时,背景环境和元素可匹配果园、自然主题;其它关键词按其语义匹配合适主题。主题包不得改变关卡玩法规则,不新增文字说明、额外按钮或额外判定规则。 - -视觉主题包的资源边界: - -1. 背景环境图不做透明抠图,但必须保证屏幕中间、中下方和底部左右篮子区域清爽,不遮挡放大后的物品、礼物盒和篮子; -2. 礼物盒资源从 `2x2` 素材 sheet 右下格切出,输出为透明 PNG,运行态按当前礼盒视觉的 2 倍尺寸展示,素材主体必须饱满清晰; -3. 篮子资源从 `2x2` 素材 sheet 左下格切出,输出为透明 PNG,运行态按当前篮子视觉的 1.5 倍尺寸展示,左右篮子仍固定为两个物品对应选项,篮子造型资源可以复用同一张主题篮子图;篮子切图不得保留手柄、篮口或边缘处的白底描边和抠图毛边; -4. 运行态左右手位置指示器使用内置默认静态素材,姿势为用户第一人称看到的半抓握手,不随创作关键词重新生成; -5. 礼物盒打开时的烟雾弹出特效由运行态 CSS 动效兜底;历史草稿如果已有 `smoke-puff` 资源可继续兼容读取,但新生成链路不再单独生成该资源。 - -当前本地 Demo 阶段已接入真实 image-2 资源链路。创作提交必须成功获得 `generationProvider = "vector-engine-gpt-image-2"` 的两个物品透明 PNG、背景环境图、礼物盒和篮子后,才能进入结果页、试玩或发布;若后端接口、登录态、VectorEngine 配置或上游生成失败,前端必须停留在生成失败状态并展示错误,不得静默回退为占位图。历史草稿中若仍存在 `generationProvider = "placeholder"` 的占位资源,结果页必须提示重新生成,试玩和发布前必须先补齐 image-2 资源。 - -## 4. 标签规则 - -发布作品必须携带精确标签: - -```text -寓教于乐 -``` - -标签识别只接受精确等于 `寓教于乐`。不接受 `儿童教育`、`动作教育`、`寓教于乐 ` 等近似标签。 - -宝贝识物草稿与发布 payload 中都必须保留该标签。发布后的公开展示、搜索、深链和入口开关继续遵循 `CHILD_MOTION_EDUTAINMENT_DISCOVER_ENTRY_2026-05-09.md`。 - -## 5. 结果页能力 - -结果页展示: - -1. 作品名称; -2. 两个物品名称; -3. 两个物品图; -4. 标签; -5. 保存草稿; -6. 发布; -7. 试玩。 - -结果页不展示长规则说明文案。试玩按钮直接进入宝贝识物首关本地运行态。 - -试玩按钮进入宝贝识物首关运行态,运行态消费当前草稿中的两个物品名称和两张物品图,不重新生成或改写物品内容。 - -若草稿包含视觉主题包,运行态还必须消费该主题包中的背景环境、礼物盒和篮子资源;左右手位置指示器始终使用内置默认静态素材。旧草稿或接口失败时允许回退到当前 CSS 绘本风兜底。历史草稿中若已有 UI 装饰、左右手或烟雾弹出特效资源,运行态仅做兼容读取或忽略,不作为新链路必需资源。 - -## 6. 发布后体验 - -发布完成后作品应进入寓教于乐内容线,并在寓教于乐入口开启时可被板块消费。 - -入口关闭时,发布作品完全不可见,不能通过推荐、发现普通频道、搜索、作品号、公开详情深链或浏览历史访问。 - -## 7. 与运行时线程的边界 - -本 PRD 同步约束首关运行态,已确认规则包括: - -1. 进入关卡后先展示两个目标物品:物品 A 居中展示 2 秒,名称 UI 与字体约为默认大小的 2 倍,随后物品和名称飞入左侧篮子预设位置,并在飞行过程中恢复为默认大小;左侧就绪后等待 1 秒,再展示物品 B 并飞入右侧篮子预设位置;全部就绪后等待 1 秒再进入礼物盒入场。 -2. 目标展示完成后,首次礼物盒自动打开并弹出首个随机物品;后续每次正确反馈完全结束后重新进入礼物盒入场。 -3. 每轮仅中间礼物盒跳出的物品随机;左右两侧篮子固定为当前草稿两个物品的顺序; -4. 下一关按钮当前占位; -5. 不新增用户未确认的计时、失败次数、分数、体力或难度递增。 -6. 屏幕中上方字幕固定为“将物品放入对应的篮子里”。 -7. 礼物盒位于屏幕中下方并按当前视觉放大一倍,首次进入关卡和每次正确反馈结束后的新轮次都从上方落下后自动打开。 -8. 屏幕下方左侧和右侧分别展示两个固定篮子,左侧固定使用草稿第一个物品图,右侧固定使用草稿第二个物品图。 -9. 左右篮子按当前视觉放大 50%,物品图标与篮子中心尽量对齐,物品图标下方展示对应物品名称 UI。 -10. 礼物盒打开时播放烟雾特效,中央物品从烟雾特效中弹出;物品弹出后礼物盒从舞台移除。 -11. 中央物品 UI 和左右篮子上方物品图标都使用固定正方形槽位,生成素材只在槽位内等比缩放;长条形物品不得拉伸外层 UI 框。 -12. 运行态实时展示用户左右手位置;任意一只手先接触中央物品 UI 后,中央物品绑定并跟随该手移动,手带物品进入左侧或右侧篮子区域时代表选择对应篮子;选篮不使用动作名判定,也不再使用左手固定选左篮、右手固定选右篮的规则。 -13. 正确时展示“真棒”字幕和正确特效;错误时展示“再想一想吧”字幕和错误特效,物品回到中央。 -14. 成功 20 次后展示“恭喜你!小朋友!”字幕和特效,并展示“再来一次”和“下一关”按钮。 -15. 当前本地 Demo 阶段音效与语音播报接口只预留调用点,不在前端写死外部硬件或服务接口。 - -## 8. 验收 - -1. 创作入口显示 `宝贝识物` 并可进入模板表单。 -2. 未填写任一物品名称时不能生成草稿。 -3. 生成草稿后进入结果页,展示两个物品名称和物品图。 -4. 生成草稿后包含视觉主题包,主题包含背景环境、礼物盒、篮子三类必需资源。 -5. 草稿标签中始终包含精确 `寓教于乐`。 -6. 发布 payload 始终包含精确 `寓教于乐`。 -7. 发布完成后出现分享弹窗或发布完成状态。 -8. 前端不读取或暴露 VectorEngine 密钥。 -9. 结果页试玩进入宝贝识物运行态,不再显示“试玩关卡正在接入中”。 -10. 运行态通过鼠标左键映射左手位置、鼠标右键映射右手位置;调试输入也必须先触碰中央物品,再拖入任一篮子完成选择。 -11. 成功 20 次后出现“再来一次”和“下一关”按钮。 -12. 使用长条形物品素材时,中央物品 UI 和篮子物品图标仍保持固定正方形槽位,只缩放物品本体。 -13. 运行态开局先完成两个目标物品的居中展示和飞入篮子动画,之后才出现礼物盒并进入首轮随机物品。 diff --git a/docs/prd/【玩法创作】拼消消玩法模板PRD-2026-05-30.md b/docs/prd/【玩法创作】拼消消玩法模板PRD-2026-05-30.md deleted file mode 100644 index 6adfb9a75..000000000 --- a/docs/prd/【玩法创作】拼消消玩法模板PRD-2026-05-30.md +++ /dev/null @@ -1,77 +0,0 @@ -# 拼消消玩法模板 PRD - -日期:`2026-05-30` - -## 目标 - -新增玩法模板 **拼消消**,工程域与 `playId` 均为 `puzzle-clear`,公开作品码前缀为 `PC-`。拼消消以拼图的交换 / 拖拽手感为原型,但运行态规则独立:玩家移动 1x1 卡牌碎片,把同一复合图案组拼成完整矩形后消除;消除产生空位后,由顶部对应纵列的卡牌准备区下落补位。 - -首版必须完成公开闭环: - -```text -创作入口 -> 轻表单工作台 -> 独立生成页 -> 结果页 -> 试玩 -> 发布 -> 统一作品详情 -> 正式 runtime -> 基础统计 / 作品架 / 广场 -``` - -## 创作工具平台接入声明 - -- 工作台模式:表单 / 图片输入创作工作台。 -- 创作链路:入口 -> 工作台 -> 生成页 -> 结果页 -> 试玩 -> 发布 -> 运行态。 -- 单图资产槽位: - - `board-background` / `ui-background` / `中央场地底图` / `boardBackgroundPrompt` 优先、空值时回退 `themePrompt`,并支持用户上传图 / 写回 `draft.boardBackgroundAsset`、`draft.boardBackgroundPrompt`、`work.boardBackgroundAsset` 与 `work.boardBackgroundPrompt` / 允许历史图 / 允许 AI 重绘。 - - 中央场地底图的字段名沿用平台表面口径,实际作用是玩家逐步消除清空中央棋盘后慢慢看到的主题目标图;AI 生成尺寸必须与中央棋盘一致,使用 1:1 正方形画面。prompt 必须强绑定主题、画面精致、强表现力并一眼体现主题,带来探索、揭开全貌和追求目标完成的感受;不得继续要求“画面干净”或“适合作为卡牌棋盘底图”。 -- 系列素材槽位: - - `batchId=puzzle-clear-pattern-atlas-v1`。 - - `sheetSpec`:4 张素材工作表,每张 `1024x1536` 竖版,后台按 `4 列 x 6 行` 裁切,每个 1x1 单元为 `256x256`;服务端再把切片合成一张 `10x10 / 2560x2560` 最终 atlas。复合图案组总数为 `35`,形状配比 `1x2=23`、`1x3=5`、`2x2=4`、`2x3=3`,总计 `95` 个 1x1 卡牌切片。 - - `slotSpecs`:每个复合图案组一个 `patternGroup`,服务端预排 `groupId`、`shape`、atlas 坐标和 1x1 切片坐标。 - - 切图规则:生图 prompt 只要求复合图案组能按 4x6 素材工作表均等切成 1x1 方形小份,不允许模型在图上绘制切分线、边框、网格线或裁切参考线;服务端按 sheet 布局直接裁出 1x1 卡牌碎片,校验每个编号占格数与领域图案组面积一致,再合成最终 atlas,写入 `patternGroups[]` 与 `cardAssets[]`。 - - 透明化规则:首版保留完整方形卡面,不强制透明化;若 provider 输出带边框、切分线、网格、裁切参考线或文字,生成任务失败并回写审计。 - - 失败回写:生成页写回 `generationStatus=failed` 与失败阶段;结果页保留重试入口。 - - 局部重生成:v1 允许整批 4 张素材工作表重试,不做单组局部重生。 -- API 命名空间:`/api/creation/puzzle-clear/...` 与 `/api/runtime/puzzle-clear/...`。 -- 业务真相:草稿、发布、runtime snapshot、胜负、补牌、防死局、统计均由后端裁决;前端只做动画和交互表现。 -- 创作工具模式例外:无。 -- 验证命令:`npm run check:encoding`、`npm run typecheck`、`npm run test -- src/services/puzzle-clear/puzzleClearLocalRuntime.test.ts`、`npm run test -- src/components/puzzle-clear-result/PuzzleClearResultView.test.tsx src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx`、`cargo test -p module-puzzle-clear --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server puzzle_clear --manifest-path server-rs/Cargo.toml -- --nocapture`;涉及 SpacetimeDB schema 后运行 `npm run spacetime:generate`、`npm run check:spacetime-runtime-access`、`npm run check:spacetime-schema`、`npm run check:server-rs-ddd`。 - -## 工作台字段 - -| 字段 | 契约字段 | 默认值 | 校验 | 落库 | -| --- | --- | --- | --- | --- | -| 作品标题 | `workTitle` | 空 | 必填,1-30 字 | session draft / work profile | -| 简介 | `workDescription` | 空 | 0-120 字 | session draft / work profile | -| 主题词 | `themePrompt` | 空 | 必填,1-80 字 | 生成 prompt 与草稿 | -| 场地底图主题词 | `boardBackgroundPrompt` | 空 | 0-80 字;为空时底图生成回退 `themePrompt` | session draft / work profile / 主题目标图生成 prompt | -| 中央场地底图 | `boardBackgroundAsset` | 空 | 上传或 AI 生成至少一种 | 单图资产槽位 | -| AI 生成底图 | `generateBoardBackground` | `true` | boolean | 生成编排参数 | - -规则参数不开放创作者编辑:棋盘尺寸、倒计时、消除次数、形状解锁、防死局发牌和半锁定规则固定。 - -## 运行规则 - -| 关卡 | 棋盘 | 目标消除 | 倒计时 | 解锁形状 | -| --- | --- | --- | --- | --- | -| 1 | 6x6 | 35 | 10 分钟 | 1x2、1x3、2x2、2x3 | - -- 开局每个小格子从背面翻向正面。 -- 可消除图由横向或纵向复合图案组组成,最小消除单位为两张图拼接。 -- 完成一个复合图案组后,该组所有 1x1 卡牌碎片消除。 -- 消除后空位按列由顶部卡牌准备区下落补齐。 -- 每次补牌至少保证掉落卡中有一张可以与场上剩余某张卡拼接,防止死局。 -- 非 2 格消除时,若场上已有局部完成的半锁定拼接组,补牌不得破坏它。 -- 半锁定拼接组可整体拖动;玩家用外部单格撞入组内某格时,只交换该格,组其余部分保留,组状态退回半完成。 -- 超时只判当前关失败,可重试当前关;完成 35 次目标并清空当前棋盘后整局完成。 - -## 结果页 - -结果页展示:素材 atlas、中央场地底图、发布状态、试玩入口和失败重试。结果页不写功能说明类文案,不开放规则编辑器,不新增排行榜配置。 - -## 统计 - -首版只记录正式 `published` run: - -- 开局。 -- 全局完成。 -- 当前关失败。 -- 耗时。 -- 消除统计。 - -草稿试玩不写正式统计,不进入排行榜;v1 不做排行榜。 diff --git a/docs/prd/【玩法创作】敲木鱼玩法模板PRD-2026-05-20.md b/docs/prd/【玩法创作】敲木鱼玩法模板PRD-2026-05-20.md deleted file mode 100644 index cec5df42a..000000000 --- a/docs/prd/【玩法创作】敲木鱼玩法模板PRD-2026-05-20.md +++ /dev/null @@ -1,409 +0,0 @@ -# 敲木鱼玩法模板 PRD 2026-05-20 - -## 1. 目标 - -新增一个可创作、可试玩、可发布的轻量休闲玩法模板: - -```text -敲木鱼 -``` - -模板按平台新增玩法 SOP 接入完整闭环: - -```text -创作入口 -> 工作台 -> 生成页 -> 结果页 -> 试玩 -> 发布 -> 运行态 -> 公开详情/分享 -``` - -首版默认屏幕中央展示内置卡通透明敲击物图案 `/wooden-fish/default-hit-object.png`。玩家点击运行态非功能区时触发一次敲击:播放敲击音效、敲击物图案执行被敲击动画,并在敲击物上方随机飘出一条祝福词。顶部只展示总数记录;子项计数收纳到总数卡片下方的折叠面板中,总数卡片点击后展开各子项计数,词条在面板中预置显示,未出现时初始值为 0,点击面板外收起。计数仅属于当前单次 run,不进入账号长期账本。 - -## 2. 模板定位 - -模板 ID: - -```text -wooden-fish -``` - -用户展示名: - -```text -敲木鱼 -``` - -公开作品号前缀: - -```text -WF-* -``` - -体验关键词: - -1. 单屏点击; -2. 轻量解压; -3. 飘字反馈; -4. 单局累计; -5. 可自定义敲击物、敲击音效和祝福词。 - -## 3. 与拼图创作流程的复用边界 - -可以复用: - -1. 创作入口配置、入口开关和作品架; -2. 表单/图片输入工作台; -3. 生成过程页和生成中恢复; -4. 结果页的返回编辑、局部重生成、试玩、发布; -5. 公开列表、公开详情、分享码和推荐流分发; -6. 平台资产对象、OSS 私有读取换签和音频资产持久化能力。 - -不复用: - -1. 拼图关卡、棋盘、拼块、排行榜和关卡推进语义; -2. 跳一跳地块图集和蓄力判定语义; -3. 抓大鹅物品消除、五视角图集和容器语义; -4. 任何长期功德账本、账号维度排行榜或全局累计。 - -## 4. 创作工具平台接入声明 - -- 工作台模式:表单/图片输入创作工作台 -- 创作链路:入口 -> 工作台 -> 生成页 -> 结果页 -> 试玩 -> 发布 -> 运行态 -- 单图资产槽位: - - `slotId=hit-object` - - `slotType=hit-object-image` - - `slotName=敲击物图案` - - 提示词来源:`hitObjectPrompt` 与可选 `hitObjectReferenceImageSrc` - - 写回字段:`hitObjectAsset` - - 是否允许历史图:允许 - - 是否允许 AI 重绘:允许;上传图只作为 image2 参考,最终运行态只消费 image2 生成图 - - `slotId=background` - - `slotType=background-image` - - `slotName=背景环境图` - - 提示词来源:第一步生成的敲击物图案与用户原始题材关键词 / 参考图主题 - - 写回字段:`backgroundAsset` - - 是否允许历史图:不单独选择;由敲击物图案生成链路派生 - - 是否允许 AI 重绘:允许;随敲击物图案一起重生成 -- 系列素材槽位:无;首版只有敲击物图案与背景环境图两个单图资产,不生成图集 -- 音频资产槽位: - - `slotId=hit-sound` - - `slotType=hit-sound-audio` - - `slotName=敲击音效` - - 来源:用户上传/麦克风录制音频,或使用默认木鱼音 - - 写回字段:`hitSoundAsset` - - 默认兜底:`/wooden-fish/default-hit-sound.mp3` -- API 命名空间: - - `/api/creation/wooden-fish/...` - - `/api/runtime/wooden-fish/...` -- 业务真相: - - 后端裁决并持久化 session、work profile、发布状态、run 摘要和公开投影; - - 前端只负责点击低延迟表现、音频播放、动画、飘字渲染和定期 checkpoint。 -- 创作工具模式例外:无 -- 验证命令: - - `npm run check:encoding` - - `npm run typecheck` - - `cargo test -p shared-contracts wooden_fish --manifest-path server-rs/Cargo.toml` - - `cargo test -p module-wooden-fish --manifest-path server-rs/Cargo.toml` - - `cargo check -p api-server --manifest-path server-rs/Cargo.toml` - - `npm run spacetime:generate` - - `npm run check:spacetime-schema` - - `npm run dev:api-server` 后检查 `/healthz` - -## 5. 创作输入 - -工作台提交结构化 payload,不提交聊天消息。 - -必填字段: - -1. `templateId = "wooden-fish"`; -2. `hitObjectPrompt`:用户想敲的对象关键词或描述,默认“默认敲击物图案,圆润木质质感,透明背景”; -3. `floatingWords[]`:祝福词,最多 8 条,不填或清空时使用默认祝福词。 - -可选字段: - -1. `hitObjectReferenceImageSrc`:上传或历史图引用,只能作为 image2 参考,不可直接进入运行态; -2. `hitSoundPrompt`:历史兼容字段,当前创作流程不再使用; -3. `hitSoundAsset`:用户上传、录音或默认音频资产。 - -结果页补录字段: - -1. `workTitle`:作品标题,默认值在结果页可编辑; -2. `workDescription`:作品简介; -3. `themeTags[]`:最多 6 个标签,样式对齐拼图结果页标签编辑器。 - -创作界面默认祝福词: - -```text -幸运 -``` - -用户可通过加号继续新增 7 个词条,总数最多 8 条。新增词条右侧提供减号 / 删除小按钮;默认的第一个词条保留为普通输入格。 - -`floatingWords[]` 保存词条名本身,不保存 `+1` 后缀;运行态每次敲击时再把飘字展示为“词条+1”。 - -## 6. 生成规则 - -### 6.1 敲击物图案、背景环境图与返回按钮图 - -默认模板在用户未自定义关键词且未上传参考图时,`compile-draft` 使用内置透明 PNG `/wooden-fish/default-hit-object.png` 写回 `hitObjectAsset`,`generationProvider="bundled-default"`。这张图来自 image2 对原始参考图的卡通风格化重绘,固定为模板默认资源,避免默认关键词在每次生成时改变造型。即使使用内置默认敲击物,首版仍需要生成 `backgroundAsset` 与 `backButtonAsset`,背景环境图和主题返回按钮图都使用默认敲击物作为主题和画风参考。 - -用户输入自定义关键词、上传参考图,或在结果页主动重生成敲击物时,`compile-draft` 与 `regenerate-hit-object` 必须先为敲击物图案生成 image2 单图资产,再基于新敲击物图案生成背景环境图,最后基于去绿后的敲击物主体和背景环境图生成主题返回按钮图,并由 `api-server` 注入写回 `hitObjectAsset`、`backgroundAsset` 与 `backButtonAsset`。前端 action 请求不得自带 `hitObjectAsset`、`backgroundAsset` 或 `backButtonAsset` 短路生成。如果用户上传参考图,后端只能把该图作为 image2 参考图或主题参考;运行态不得直接使用上传图。 - -敲击物图案生成流程固定为: - -1. 调用 VectorEngine `/v1/images/edits`,模型固定为 `gpt-image-2`; -2. multipart 参考图固定包含默认木鱼图 `/wooden-fish/default-hit-object.png`,作为基础结构和画风参考; -3. 若用户上传参考图,该图只作为新主题参考追加到同一次 image2 edits 请求,不直接进入运行态; -4. 尺寸固定 `1:1`,必须输出单一纯绿色 `#00FF00 / RGB(0,255,0)` 绿幕背景主体图,并显式禁止黑底、白底、棋盘格、纸板底或任何其它实底背景; -5. 提示词严格使用: - -```text -生成敲木鱼新样式,要求结构,画风与参考图保持高度一致,新样式颜色搭配使用新主题对应的颜色。尺寸1:1,先输出单一纯绿色 #00FF00 / RGB(0,255,0) 绿幕背景主体图,背景必须严格使用 #00FF00 / RGB(0,255,0) 且平整无纹理、无渐变、无阴影、无道具,主体完整居中,主体边缘必须干净,不要直接输出透明底。随后由服务端对绿色背景主体图做抠图去除绿色背景。最终结果只保留单个敲击物图案,禁止黑底、白底、棋盘格、纸板底或任何实底背景;主体本身不要使用与绿幕接近的纯绿色,若新主题天然包含绿色,请改用偏深、偏黄或偏蓝的绿色并与绿幕清晰区分。 -新主题为:(用户提供参考图或用户输入关键词) -``` - -敲击物图案落盘前,`api-server` 必须只对第一步生成的单一纯绿色 `#00FF00 / RGB(0,255,0)` 绿幕背景执行去绿处理,把绿色背景转成真实透明 alpha PNG;不得对黑底、白底或其它未知实底执行泛抠图,避免误伤玉米等主体像素。去绿处理必须保留主体内部深色结构和主题细节。 - -背景环境图生成流程固定为: - -1. 调用 VectorEngine `/v1/images/edits`,模型固定为 `gpt-image-2`; -2. multipart 参考图固定为第一步敲击物图案抠图完成后的透明图;默认未生成新敲击物时使用内置默认敲击物图案的透明兜底图; -3. 尺寸固定竖屏 `9:16`; -4. 背景环境图只适配新敲击物主题和画风,背景中不得包含新敲击物本体,也不得增加木槌互动物品;中央主体预留区必须保持干净,画面中央 40% 区域禁止出现主题主体、主体局部特写、主体轮廓影子、重复元素或主题主体的局部碎片;运行态的敲击物只在前端叠放,不允许出现在背景图提示词里。 -5. 提示词严格使用: - -```text -生成敲木鱼背景,要求主题、画风与参考图保持高度一致,背景元素和颜色搭配与主题对应,只生成竖屏背景环境图,不生成、不描绘、不暗示新木鱼物品本体,也不要出现木槌互动物品。尺寸竖屏9:16。参考图必须是第一步敲击物抠图完成后的透明图,不继承任何绿色底色、绿幕底色或纯绿色画布,并要求最终输出完整不透明的背景环境图。中央主体预留区必须保持干净,中央区域是运行态叠放敲击物的留白区域,画面中央 40% 区域禁止出现主题主体、主体局部特写、主体轮廓影子、重复元素或主题主体的局部碎片;主题元素只允许出现在外围氛围,不得把主题物品画在画面中央,也不要把主题物品作为背景中心装饰。 -主题为:(用户提供参考图或用户输入关键词) -``` - -返回按钮图生成流程固定为: - -1. 调用 VectorEngine `/v1/images/edits`,模型固定为 `gpt-image-2`; -2. multipart 参考图固定包含第一步去除绿色背景后的敲击物主体图,以及第二步生成的背景环境图; -3. 尺寸固定 `1:1`,必须输出单一纯绿色 `#00FF00 / RGB(0,255,0)` 绿幕背景主体图,后端落库前执行同一套去绿背景处理; -4. 按主题、画风、材质和配色生成左上角返回按钮图,但参考图只用于约束圆形底色和中央左箭头的颜色搭配,不得借鉴复杂造型、花纹、浮雕边、异形外框或装饰图案;按钮必须始终是标准圆形,主体视觉尺寸比当前模板再放大约 50%,圆形外沿必须有与主题色搭配的干净外描边,中央只保留单个清晰左箭头或返回箭头,不得包含文字、数字、水印、额外 UI 面板、木槌或敲击道具; -5. 提示词严格使用: - -```text -生成敲木鱼左上角返回按钮图。要求以参考图-去除绿色背景后的敲击物主体和背景环境图为主题、画风、材质和配色参考,但参考图只用来约束圆形底色和中央左箭头的颜色搭配,不要继承复杂造型、花纹、浮雕边、异形外框或装饰图案。按钮必须始终是标准圆形,整体像单个圆形图标,按钮主体在画布中的视觉尺寸比当前模板再放大约 50%,圆心居中,圆形外沿加一圈和主题色搭配的干净外描边,让它更像一个按钮,但仍然只保留一个清晰、简洁、居中的向左返回箭头,不要出现文字、数字、水印、按钮外标签、额外 UI 面板、木槌或敲击道具。尺寸1:1,输出单一纯绿色 #00FF00 / RGB(0,255,0) 绿幕背景主体图,背景必须严格使用 #00FF00 / RGB(0,255,0) 且平整无纹理、无渐变、无阴影。按钮主体边缘干净,后续由服务端扣除绿色背景;按钮底色不要使用与绿幕接近的纯绿色,若主题天然包含绿色,请仅在圆形底色上使用偏深、偏黄或偏蓝的主题绿色,并用更高对比的箭头颜色区分。 -主题为:(用户提供参考图或用户输入关键词) -``` - -落库链路固定为:`api-server` 调用 VectorEngine `/v1/images/edits` -> 服务端上传 OSS 私有对象 -> `confirm_asset_object` 登记资产对象 -> `bind_asset_object_to_entity` 绑定到 `entityKind='wooden_fish_work'`。敲击物绑定 `slot='hit_object'`、`assetKind='wooden_fish_hit_object'`,背景绑定 `slot='background'`、`assetKind='wooden_fish_background'`,返回按钮绑定 `slot='back_button'`、`assetKind='wooden_fish_back_button'`。写回时把 `legacyPublicPath` 分别写入 `hitObjectAsset.imageSrc`、`backgroundAsset.imageSrc` 与 `backButtonAsset.imageSrc`。不得只拼 `/generated-wooden-fish-assets/...` 占位路径;前端会对 generated legacy path 走 `/api/assets/read-url` 换签,OSS 中没有真实对象时图片无法显示。 - -默认图案要求: - -1. 中央主体使用 `/wooden-fish/default-hit-object.png`; -2. 透明背景; -3. 适合移动端居中展示; -4. 不包含 UI、按钮、说明文字、水印或品牌标识; -5. 图片主体需留出敲击动画缩放空间。 - -### 6.2 敲击音效 - -音效统一写回 `hitSoundAsset`。 - -写回规则: - -1. 若 payload 已包含上传/录音音频资产,`compile-draft` 跳过音效生成,直接持久化该资产; -2. 若 payload 已上传或录制音频,则直接写回 `hitSoundAsset`; -3. 麦克风录制音频在保存前由前端自动裁掉开头连续静音段;上传音频不做裁剪,裁剪失败时保留原始录音继续保存; -4. 若两者都没有,后端写回默认木鱼音 `/wooden-fish/default-hit-sound.mp3`; -5. 音效资产必须包含可播放地址、对象键、asset object id、来源和可选时长; -6. 通用创作音频接口当前对 `wooden_fish` 的 `hit_sound` 目标返回 `410 Gone`,不得在创作流程中按提示词生成音效; -7. `spacetime-client` 不得自行合成 `/generated-wooden-fish-assets/...` 音效占位路径;缺少真实 `hitSoundAsset` 时应使用默认木鱼音兜底展示与播放。 - -### 6.3 封面 - -首版封面使用 `hitObjectAsset.imageSrc` 作为 `coverImageSrc`。背景环境图与返回按钮图不作为封面图。 - -## 7. 契约草案 - -`WoodenFishDraft` 至少包含: - -1. `templateId = "wooden-fish"`; -2. `templateName = "敲木鱼"`; -3. `profileId`; -4. `workTitle`; -5. `workDescription`; -6. `themeTags[]`; -7. `hitObjectPrompt`; -8. `hitObjectReferenceImageSrc`; -9. `hitSoundPrompt`,历史兼容字段,当前创作流程恒为 `null`; -10. `floatingWords[]`; -11. `hitObjectAsset`; -12. `backgroundAsset`; -13. `backButtonAsset`; -14. `hitSoundAsset`; -15. `coverImageSrc`; -16. `generationStatus`。 - -`WoodenFishImageAsset` 至少包含: - -1. `assetId`; -2. `imageSrc`; -3. `imageObjectKey`; -4. `assetObjectId`; -5. `generationProvider`; -6. `prompt`; -7. `width`; -8. `height`。 - -`WoodenFishAudioAsset` 至少包含: - -1. `assetId`; -2. `audioSrc`; -3. `audioObjectKey`; -4. `assetObjectId`; -5. `source = uploaded | recorded | bundled-default`; -6. `prompt`; -7. `durationMs`。 - -`WoodenFishRunSnapshot` 至少包含: - -1. `runId`; -2. `profileId`; -3. `ownerUserId`; -4. `status = playing | finished`; -5. `totalTapCount`; -6. `wordCounters[]`; -7. `startedAtMs`; -8. `updatedAtMs`; -9. `finishedAtMs`。 - -## 8. API 草案 - -HTTP 路由: - -```text -POST /api/creation/wooden-fish/sessions -GET /api/creation/wooden-fish/sessions/{sessionId} -POST /api/creation/wooden-fish/sessions/{sessionId}/actions -GET /api/creation/wooden-fish/works -GET /api/creation/wooden-fish/works/{profileId} -POST /api/creation/wooden-fish/works/{profileId}/publish -GET /api/runtime/wooden-fish/works/{profileId} -POST /api/runtime/wooden-fish/runs -POST /api/runtime/wooden-fish/runs/{runId}/checkpoint -POST /api/runtime/wooden-fish/runs/{runId}/finish -GET /api/runtime/wooden-fish/gallery -GET /api/runtime/wooden-fish/gallery/{publicWorkCode} -``` - -动作类型: - -```text -compile-draft -regenerate-hit-object -replace-hit-sound -update-work-meta -update-floating-words -publish -start-run -checkpoint -finish -``` - -`compile-draft` 是长耗时动作。前端进入生成页后应展示可恢复进度;如果请求失败,标记失败前必须复读 session,确认后端是否已经生成并写回草稿。 - -敲木鱼创作请求在前端必须使用长等待窗口,避免 `createSession` 或 `executeAction` 仍沿用共享创作工厂默认的 15 秒超时。因为 `compile-draft` 会串行等待敲击物、背景、返回按钮三次 image2 和 OSS 落库,木鱼 client 需要单独配置与整条 image2 链路匹配的超时。本地测试中该 action 可能达到数分钟级;生成页进度必须按“整理草稿 -> 生成敲击物 -> 生成背景环境图 -> 生成返回按钮图 -> 写入正式草稿”展示,不展示“提示词生成音效”阶段,因为当前木鱼音效只支持上传、录音或默认音。 - -作品架使用 `GET /api/creation/wooden-fish/works` 读取当前用户草稿和已发布摘要,前端发布成功后必须刷新该列表和 `GET /api/runtime/wooden-fish/gallery` 公开列表,使刚发布作品立即出现在草稿 Tab 的已发布筛选和推荐 / 最新流中。 - -## 9. SpacetimeDB 表和 view - -新增表: - -1. `wooden_fish_agent_session`; -2. `wooden_fish_work_profile`,其中 `background_asset_json` 保存背景环境图资产快照,`back_button_asset_json` 保存主题返回按钮图资产快照; -3. `wooden_fish_runtime_run`; -4. `wooden_fish_event`。 - -新增 view: - -1. `wooden_fish_gallery_card_view`:公开列表卡片投影,只暴露已发布作品; -2. `wooden_fish_gallery_view`:公开详情兼容投影,包含图案、背景、返回按钮、音效和祝福词配置。 - -新增或调整表、procedure、view 后必须同步 `migration.rs`、后端表目录、生成 bindings,并执行 `npm run check:spacetime-schema`。 - -## 10. 结果页能力 - -结果页必须展示: - -1. 作品标题和简介; -2. 竖屏背景环境图预览; -3. 敲击物图案; -4. 敲击音效试听; -5. 祝福词配置; -6. 标签; -7. 试玩; -8. 发布; -9. 返回编辑。 - -结果页必须支持: - -1. 重生成敲击物图案; -2. 上传、录制或替换敲击音效;未提供时使用默认木鱼音; -3. 修改标题、简介和标签,并在试玩或发布前写回当前作品信息; -4. 修改祝福词,最多 8 条。 - -图案重生成是独立局部生成态,不得把已有可查看结果重新变成不可打开的全局生成中。音效替换只接受上传或录音资产,不触发提示词音效生成。 - -## 11. 运行态规则 - -运行态采用全屏单击模型。 - -功能区: - -1. 顶部总数记录卡和其下拉的子项计数器面板; -2. 设置、暂停、返回、发布分享等按钮; -3. 结果弹层和音频授权提示。 - -点击规则: - -1. 点击非功能区才算一次敲击; -2. 每次敲击立即本地累加 `totalTapCount`; -3. 随机等概率从 `floatingWords[]` 中取一个词条; -4. 子项计数面板中预置展示所有词条,未出现词条初始值为 0; -5. 后续同词条出现时对应计数器 +1; -6. 播放敲击音效; -7. 敲击物图案执行压缩、回弹或轻微震动动画; -8. 木鱼上方飘出“词条+1”并淡出,飘字只显示文字本体,不加底板、胶囊背景或说明面板。 - -运行态左上角返回按钮必须优先使用 `backButtonAsset` 渲染主题化按钮图;缺失时才回退通用图标按钮。运行态不提供右上角重开按钮。 - -音频播放: - -1. 前端使用 10 路小复音池; -2. 设置最小播放间隔,避免极端连点导致浏览器抖动; -3. 点击计数不能因为音频节流而丢失; -4. 签名 URL 未就绪时先静音表现,不请求裸 generated 私有路径。 - -后端只保存 run 摘要,不保存每次点击的完整明细;`checkpoint` 和 `finish` 都写入总敲击次数与词条计数快照。 - -## 12. 公开链路 - -平台首页推荐、发现、公开详情、搜索、已玩作品和公开试玩统一按 `sourceType='wooden-fish'` 与 `WF-*` 公开作品号识别敲木鱼作品。 - -公开列表优先消费 `wooden_fish_gallery_card_view` 订阅缓存。公开详情如果卡片摘要不足以进入运行态,必须补读完整 work profile。 - -历史已发布且 `generationStatus=ready` 的木鱼作品如果仅缺 `backButtonAsset`,运行态启动前必须补齐内置默认返回按钮 `/UI/11_left_arrow.png`,并持久写回 work profile;这类历史作品不应通过推荐流过滤隐藏。 - -## 13. 验收 - -1. 创作入口能看到 `敲木鱼` 模板; -2. 工作台可以填写敲击物描述、上传参考图、上传或录制音效、配置祝福词; -3. 提交后按默认木鱼参考图生成 image2 敲击物图案; -4. 提交后按新敲击物图案参考图生成 9:16 背景环境图; -5. 提交后按去绿后的敲击物主体和背景环境图生成主题返回按钮图; -6. 上传图不会直接进入运行态; -7. 用户上传或录制音效时直接持久化该资产,未提供时使用默认木鱼音; -8. 结果页能看到背景、图案、试听音效、编辑祝福词并试玩; -9. 运行态功能区点击不触发敲击; -10. 运行态左上角使用主题返回按钮图,右上角不出现重开按钮; -11. 非功能区点击会计数、播放音效、播放敲击动画并飘出无底板大号文字; -12. 顶部总数卡点击后展开子项计数器面板,面板内预置全部词条且未出现词条初始值为 0,面板外点击可收起; -13. 连点不丢计数; -14. `checkpoint` 和 `finish` 只保存单次 run 摘要; -15. 作品可以发布、进入公开列表和公开详情; -16. `WF-*` 公开作品号能进入分享和运行态; -17. `npm run check:encoding` 通过; -18. schema 变更后 `npm run check:spacetime-schema` 通过。 diff --git a/docs/prd/【玩法创作】跳一跳俯视角玩法模板PRD-2026-05-19.md b/docs/prd/【玩法创作】跳一跳俯视角玩法模板PRD-2026-05-19.md deleted file mode 100644 index 1df121a4c..000000000 --- a/docs/prd/【玩法创作】跳一跳俯视角玩法模板PRD-2026-05-19.md +++ /dev/null @@ -1,198 +0,0 @@ -# 跳一跳俯视角玩法模板 PRD 2026-05-19 - -## 1. 目标 - -`jump-hop` 重定义为竖屏俯视角平台跳跃游戏。创作者只输入主题,系统生成一张该主题的 `1024x1536` 立方体主题物体 UV 展开图集,按 `3列*6行` 容纳 18 个方块,每个方块内部再用自适应 blob+gradient 算法提取 top/front/right/back/left/bottom 六张面贴图;运行态使用 Three.js 复用标准 `1x1x1` 等比极小倒角立方体几何体,把六面贴图贴到立方体地板上组成无限平台流,同时使用陶泥儿 logo 透明 PNG 作为玩家角色。 - -首版目标: - -1. 创作输入只保留主题,标题、简介、标签和提示词由系统派生; -2. image2 只生成一张 `1024x1536` 地板 UV 展开图集,后端切成 18 组、共 108 张面贴图 PNG; -3. 角色不再单独生图,v1 使用 `public/branding/jump-hop-taonier-character.png` 陶泥儿 logo 透明 PNG; -4. 运行态每屏只展示 2 个地块:当前地块、目标地块,不再展示下一预览地块; -5. 操作方式为长按屏幕蓄力,松手后角色朝下一块地块中心方向弹出; -6. 只要落点未命中下一个地块,本局立即失败并冻结计时; -7. 成绩记录成功跳跃次数和游戏时长; -8. 排行榜按作品维度展示玩家 ID、成功跳跃次数和游戏时长,排序为成功跳跃次数降序、游戏时长升序、更新时间升序。 - -## 2. 模板定位 - -- 模板 ID:`jump-hop` -- 展示名:`跳一跳` -- 工程域:`jump-hop` -- 创作入口卡:`subtitle = 主题驱动平台跳跃`,`imageSrc = /creation-type-references/jump-hop.webp` -- 运行态:`Three.js 标准 1x1x1 等比极小倒角立方体地板 + Three.js Sprite 角色 + DOM HUD` -- 画面比例:移动端竖屏优先,桌面端居中承载 `9:16` -- 素材策略:18 个立方体主题物体 UV 展开包装 + Three.js 复用标准 1x1x1 等比立方体几何 + 陶泥儿 logo 透明角色 -- 渲染分层:Three.js 场景层复用一份标准 `1x1x1` 等比极小倒角立方体几何体,`tileAssets[]` 切片只作为主题身份方块包装贴图;单块立方体统一绕玩法竖直 Z 轴自转 45°,让运行态稳定露出顶面和两个侧面,不得做 Y 轴偏航或把 x/y/z scale 压成扁盒子;Three.js 方块模型边长在当前基础上视觉放大 1 倍,只改变模型显示尺寸,不改变平台中心点、随机间距和蓄力换算;后端命中 footprint 必须同步等于当前视觉可见顶面,不得隐藏收缩;运行态视角采用约 `1.69x` 近距相机和 45° 下压视角,每屏只保留当前地块和目标地块,当前脚下地块会根据目标方向偏向场地反侧,给下一块留出足够视野;地块从出现开始就使用自身真实规格,不再按当前 / 目标 / 远近或预览状态叠加倍率缩放,视觉远近只由相机和 Three.js 投影决定;Three.js 平台层、Three.js Sprite 角色和 DOM fallback 层必须保持屏幕 X 轴同向,禁止通过反向相机 `up` 或镜像容器把平台左右翻转;DOM 地块图片层只用于换签、预加载、WebGL 不可用和测试 fallback,Three.js 平台层 ready 后必须隐藏 DOM 地块图片和 DOM 阴影,退出地块只随相机推进自然离屏,不播放独立飞走动画,超过屏幕后再销毁,避免旧地块退出期露出被放大的平面 DOM 贴图;角色主路径使用 Three.js Sprite 承载陶泥儿透明 PNG,Sprite 脚点必须落在当前方块顶面中心高度并且绘制顺序高于地块,DOM 角色层仅在 WebGL 或角色贴图加载失败时兜底 - -本玩法不是横版平台跳跃,也不是关卡制闯关。平台从屏幕下方向上无限延展,目标地块永远在当前脚下地块的正 45 度或负 45 度方向随机出现。 - -## 3. 创作工具平台接入声明 - -- 工作台模式:表单输入创作工作台 -- 创作链路:入口 -> 工作台 -> 生成页 -> 结果页 -> 试玩 -> 发布 -> 运行态 -- 单图资产槽位:无独立角色图槽位;v1 固定使用陶泥儿 logo 透明 PNG 角色 -- 系列素材槽位: - - `batchId = jump-hop-tile-atlas` - - `sheetSpec = 1024x1536 / 3列*6行大单元 / 每格内自适应blob+gradient提取六面 / PNG / 纯洋红 #FF00FF 安全缝与外圈背景 / 后端切图为面贴图 PNG` - - `slotSpecs = tile-01 ... tile-18`,每个 tile 再包含 `top/front/right/back/left/bottom` 六个面 slot,所有 slot 必须对应唯一 OSS path / `assetObjectId` - - 切图规则:先通过 density 种子点精修自适应检测 3 列 6 行大单元边界(`SeedRefinement`);每个大单元内部先用 BFS 连通域提取主 blob、清除非主 blob 噪点,再对行 density 和列 height profile 做 gradient 分析检测边界(y0/y1/y2/y3、x0/x1/x2/x3),按此边界划分为 3x3 block 并保留 5 个有效 block,将含 Right+Back 的 block 从中点拆分为两块,对每个 block 取最大不透明矩形后缩放为 `256x256` 不透明 PNG - - 透明化规则:生成时要求纯洋红 key 安全缝和 UV 空位;后端先对图集做洋红去背(BFS 漫水 + 镂空洞检测),再对每个大单元内提取主 blob 后进行自适应面切分;切分后在 block 内取最大不透明矩形,消除透明边缘 - - 失败回写:生成失败时 session 保持 failed,可从生成页重试 - - 局部重生成:结果页允许重生成地板贴图图集,仍只调用一次 image2;前端展示生成图时以 `assetObjectId` 作为刷新键,避免同一路径重写后的旧签名或旧缓存 -- API 命名空间:`/api/creation/jump-hop/*`、`/api/runtime/jump-hop/*` -- 业务真相:后端裁决落点、失败、成功跳跃次数、冻结时长和排行榜 -- 创作工具模式例外:无 -- 验证命令:`npm run check:encoding`、`npm run typecheck`、`cargo test -p module-jump-hop --manifest-path server-rs/Cargo.toml` - -## 4. 创作输入 - -主题是唯一必填项。工作台不展示角色提示词、地块提示词、风格卡、难度卡、终点氛围或规则说明。 - -提交后系统自动派生: - -1. 作品标题:主题为空白修剪后的短标题,默认前缀不外露; -2. 作品简介:基于主题生成一句短简介; -3. 标签:`跳一跳`、`休闲` 和主题关键词; -4. 地板贴图提示词:围绕主题生成 18 个风格一致的立方体主题物体 UV 展开包装,每个包装由 top/front/right/back/left/bottom 六面组成,供 Three.js 标准 1x1x1 等比极小倒角立方体地板复用;实际 image2 prompt 使用“立方体主题物体 UV 展开包装图集 / cube object UV unwrap atlas”措辞,要求六面共同表达同一个完整方块化主题物体,例如水果主题要生成可一眼辨认的方块苹果、方块香蕉、方块橙子、方块西瓜等,而不是单纯生成平铺材质、抽象纹理、平台、跳台、地块成品、单张图重复六面或游戏界面资源; -5. 初始平台流参数:固定 v1 标准参数,不让创作者手工调规则。 - -## 5. 地板贴图图集 - -image2 只生成一张 `1024x1536` 竖版图片,画面为 `3列*6行` 均匀分布的立方体主题物体 UV 展开包装;实际提示词必须先约束“画面只包含 18 个用于跳一跳地板的立方体主题物体 UV 展开包装图”,并明确这是供 Three.js 标准 1x1x1 等比极小倒角立方体使用的 cube object UV unwrap atlas。每个大单元格代表一个完整方块化主题物体,并在固定 `4列*3行` UV 网中提供六张面贴图(AI prompt 侧不变);后端通过自适应 blob+gradient 算法检测面的实际位置并切图,不再依赖固定像素坐标均分。不是单纯材质贴片、单张图重复六面、地块成品图、跳板、物体剪影、游戏界面、棋盘、背包、装备栏或图标集页面。 - -图集要求: - -1. 每个大单元内部固定使用 `4列*3行` UV 网,只有六个位置有贴图:第 1 行第 2 列是 `top`;第 2 行第 1-4 列依次是 `left / front / right / back`;第 3 行第 2 列是 `bottom`;其它位置保持纯洋红 `#FF00FF`。以上为 AI 生图的 layout 要求(prompt 侧不变)。后端切图优先使用自适应 blob+gradient 算法检测面的实际像素区域,不依赖固定像素坐标均分;固定网格切片只作为测试对照和必要 fallback 参考。 -2. 每个面都是 full-bleed 不透明正方形贴图,四角、边缘和中心都要有可识别内容;六个面共同组成同一个完整方块化主题物体,不能把同一张纹理重复六次,也不能六面各画互不相关的小图标; -3. 贴图不生成已经渲染好的透视 3D 块体成品,不包含摄像机角度、已烘焙侧壁、已烘焙厚度、自身投影、接触阴影或烘焙高光;真实倒角、侧壁、透视和阴影由运行态 Three.js 生成; -4. 18 个方块来自同一主题、同一哑光手绘包装体系,但应表达不同方块化主题物体或明显不同的包装识别特征;水果主题要混排方块苹果、方块香蕉、方块橙子、方块西瓜、方块草莓、方块葡萄、方块奇异果、方块菠萝、方块柠檬、方块桃子、方块梨、方块蓝莓、方块芒果、方块椰子、方块火龙果、方块樱桃、方块哈密瓜、方块石榴,不要 18 个方块都只是同一种果皮、果肉或叶脉纹理; -5. 大单元之间、UV 空位、六面之间和画布外圈为纯洋红 `#FF00FF`,方便后端安全切图; -6. 不包含角色、文字、水印、UI、游戏面板、棋盘、背包、装备栏、按钮、标题、外层边框、可见网格线、场景背景、落地投影、接触阴影、方形阴影、方形底板、白底、灰底或黑底; -7. 贴图不能跨格、贴边串色或进入相邻格;每个面贴图应尽量铺满自己的 UV 面,纯洋红只作为安全缝、UV 空位和外圈 key 色。 - -大单元切片顺序固定为: - -```text -tile-01 tile-02 tile-03 -tile-04 tile-05 tile-06 -tile-07 tile-08 tile-09 -tile-10 tile-11 tile-12 -tile-13 tile-14 tile-15 -tile-16 tile-17 tile-18 -``` - -每个 `tile-XX` 再切出 `top/front/right/back/left/bottom` 六个面贴图并写入 `tileAssets[].faceAssets`。历史兼容字段 `imageSrc/imageObjectKey/assetObjectId` 保存 top 面;旧作品没有完整 `faceAssets` 时只走 DOM 图片 / 原型兜底层,不再把单张旧贴图强行贴到 Three.js 立方体所有面,避免旧平面素材被误表现成 UV 贴歪。运行态随机使用这 18 个地块作为后续平台外观。起点地块可复用第一个切片,其余平台从完整池中随机选择。 - -## 6. 运行态规则 - -### 6.1 平台流 - -运行态从底部初始地块开始,后续地块持续向屏幕上方生成。每次相机窗口只保留 2 个地块可见: - -1. 当前地块; -2. 目标地块。 - -服务端保存当前 run 的路径缓冲,并在每次成功落地后按同一 seed 补齐后续地块。每个后续地块只能生成在当前地块的正 45 度或负 45 度方向上,世界坐标必须满足 `abs(next.x - current.x) == next.y - current.y`,左右方向由 seed 随机决定。当前版本已有的最远相邻地块间距作为各难度 `max_gap` 上限;每次新地块距离由 seed 在 `max_gap * 55%` 到 `max_gap` 之间随机,保证相对距离永远大于 0 且不会超过当前最大手感距离。前端只展示服务端快照,不自行生成正式路径;当前两块可见窗口必须按服务端真实相邻距离缩放屏幕投影,最大距离仍落在当前版本固定的左上 / 右上 45 度位置,较近距离则沿同一 45 度方向靠近当前脚下地块。当前脚下地块仍根据目标方向偏向目标反侧,避免前方同时暴露两块地块。角色开局时脚点必须锚定在初始地块顶面中心;Three.js 角色层通过立方体顶面高度定位脚点,DOM fallback 也使用同一顶面中心屏幕锚点,不得额外把角色吸附到地块侧面或阴影中心。 - -### 6.2 操作 - -1. 用户按住当前地块或画面开始蓄力; -2. 长按时长形成蓄力值,达到 `maxChargeMs` 后封顶; -3. 松手后角色从当前真实脚点出发,朝下一块地块顶面中心方向弹出; -4. 蓄力值决定跳跃距离,用户拖拽方向不决定跳跃方向; -5. 前端提交 `dragDistance`,并为兼容后端契约提交由角色当前真实脚点指向下一块地块顶面中心推导出的 `dragVectorX/dragVectorY`;这些方向字段不得来自用户手指拖拽方向。 - -手感参数固定由后端 `module-jump-hop` 提供:`chargeToDistanceRatio = 0.004`。该值表示蓄力时长到世界跳跃距离的换算系数;旧作品运行时若仍携带其它系数,开局归一化为 `0.004`。契约中的 `dragDistance` 语义是前端提交的蓄力值;`dragVectorX/dragVectorY` 仅用于兼容当前后端请求结构,玩法语义上不表示用户拖拽方向。 - -松手后前端必须立即生成 `visualJump`,用当前角色真实脚点作为起点、前端预测真实落点作为终点,播放约 `560ms` 的角色飞行动画;视觉预测必须使用当前显示窗口的 current/next 地块作为方向来源,即使后端最新 run 已提前返回,也不能拿新 run 目标配旧窗口角色导致下一跳反向;角色从当前真实脚点沿下一块地块顶面中心方向弹向预测真实落点,蓄力阶段角色只做垂直压缩,不沿目标方向拉长。当前调参验证阶段,按住蓄力时允许显示一枚实时预测落点指示器,位置必须复用同一套前端预测结果:先按真实脚点到下一块顶面中心计算 `landedX/landedY`,再把该世界坐标投影到当前窗口和 Three.js 顶面脚点屏幕位置;不得用当前地块中心或屏幕线性插值替代。松手或取消时隐藏指示器,不参与后端裁决、不写入作品配置。成功落地后必须保留 `lastJump.landedX/landedY` 对应的真实落点偏移,不得强制吸附回目标地块中心;落地后可以轻量回弹,但不能把角色位置拉离真实落点。动画期间显示窗口保持在本次起跳前的 2 块布局,动画路径不得等待后端新 run。若后端新 run 晚于飞行动画返回,角色必须停在预测真实落点等待;新 run 到达后应先使用后端真实落点对齐显示态,成功跳跃在飞行动画结束后保留约 `300ms` 落地停顿,再进入约 `1440ms` 的相机推进过渡,避免角色刚落地就立刻拉镜头。推进过渡中,地块层和角色层必须放在同一个相机层里统一位移,不允许 p1/p2 单独改 `top/left` 做过渡;旧当前地块只随相机推进保留在屏幕后方,不单独执行飞走动画,玩家继续向前跳时再被新的相机推进自然带出屏幕并销毁,新目标地块从上方自然露出,避免角色和地块不同步或闪现。相机推进必须同时携带 X/Y 偏移,从旧真实落点位置斜向滑到新当前地块聚焦位置,不允许先横向瞬切居中后再只做纵向滑动。地块从出现开始保持自身真实尺寸,不得通过当前 / 目标 / 远近 / 预览状态附加 CSS `scale(...)` 或深度倍率;推进期只做统一相机层位移,远近变化交给相机和 Three.js 真实投影。当前地块高亮不得额外通过 CSS `scale` 放大。该动画只属于表现层,命中、失败、成功跳跃次数和冻结时长仍以后端裁决为准。 - -### 6.3 判定 - -1. 目标永远是当前地块后的下一个地块; -2. 真实落点沿角色当前真实脚点到下一块地块顶面中心方向计算;开局脚点等于初始地块顶面中心,成功跳跃后脚点等于后端 `lastJump.landedX/landedY`,不得回退到当前地块中心; -3. 落点进入下一个地块完整可见顶面 footprint,则成功;footprint 使用当前路径里该地块 `width/height` 按 45° 顶面投影得到的完整菱形区域,必须严格和当前视觉方块顶面一致,不得再额外收缩或放宽; -4. 落点未进入下一个地块完整可见顶面 footprint,则失败;地块侧面、底面、投影阴影和旧半径范围都不算正确落点;旧 `landingRadius/perfectRadius` 字段仅保留兼容读写,不再作为当前 v1 成功判定; -5. 失败后状态改为 `failed`,计时冻结; -6. v1 没有通关状态、combo、perfect 或生命数。 - -### 6.4 计分与时间 - -- 成功跳跃次数:每成功落到下一个地块后 `+1`; -- 游戏时长:`startedAtMs` 到 `finishedAtMs`,失败时冻结; -- 运行中时长由前端根据服务端 `startedAtMs` 展示; -- 失败后只展示冻结时长。 - -## 7. 排行榜 - -排行榜按作品维度生成。每位玩家只保留 1 条最佳记录。 - -排序规则固定为: - -```text -successfulJumpCount desc -> durationMs asc -> updatedAt asc -``` - -展示字段: - -1. rank; -2. displayName; -3. successfulJumpCount; -4. durationMs; -5. updatedAt。 - -排行榜 UI 禁止展示 `user_id` / `playerId` 这类内部身份键。后端可以继续用 `playerId` 做作品维度最佳成绩去重和 `viewerBest` 匹配,但 HTTP 响应必须补齐 `displayName`;已登录用户读取账号 `displayName`,匿名游客展示为“游客玩家”,账号失效或无法解析时展示为“失效玩家”。 - -草稿试玩可以展示本地结果,但正式排行榜只消费后端 run 记录。匿名 runtime guest 也按 guest subject 作为 playerId 参与当次作品维度排行。 - -## 8. 结果页 - -结果页展示: - -1. 陶泥儿 logo 透明角色预览; -2. 18 个地块资源池预览; -3. 首屏 2 块平台预览; -4. 试玩; -5. 发布; -6. 返回编辑; -7. 重生成地块。 - -结果页不再展示角色图片生成槽位,也不提供独立角色重生成。 - -## 9. 契约要点 - -公开语义保留: - -1. `themeText`; -2. `tileAtlasAsset`; -3. `tileAssets[]`; -4. `defaultCharacter`; -5. `path.platforms[]` 作为服务端路径缓冲; -6. `currentPlatformIndex`; -7. `successfulJumpCount`; -8. `startedAtMs` / `finishedAtMs` / `durationMs`; -9. `leaderboard`。 - -旧语义处理: - -1. `characterAsset` 仅作为角色描述兼容字段,不再表示生成图片;前端固定使用陶泥儿 logo 透明 PNG; -2. `score` 兼容映射为成功跳跃次数; -3. `combo` 固定为 0,不作为公开玩法语义; -4. `cleared` 状态不再由 v1 产生; -5. 旧 finite path 只作为服务端路径缓冲兼容形态。 - -## 10. 验收 - -1. 创作页只显示主题输入; -2. 生成链路只调用一次地板贴图图集 image2,不再调用角色生图; -3. 地板贴图图集为 `1024x1536 / 3列*6行`,后端通过自适应 blob+gradient 算法切出 18 组、共 108 张面贴图 PNG; -4. 结果页不依赖旧角色图片槽; -5. 运行态为竖屏俯视角,首屏保持 2 个地块可见; -6. 长按蓄力值影响落点距离,角色初始脚点在初始地块顶面中心,跳跃方向固定朝下一块地块中心,目标地块始终位于当前脚下地块的正 45 度或负 45 度方向; -7. 未落到下一个地块立即失败; -8. 成功跳跃次数累加,失败后计时冻结; -9. 排行榜按成功跳跃次数优先排序; -10. 作品可保存、发布、分享并从公开入口启动。 -11. 运行态 Three.js 地板必须只在 `tileAssets[].faceAssets` 六面贴图完整时启用 Three 平台层;玩法坐标把 Z 轴作为立方体竖直高度,因此材质数组按 Three group 顺序写入 `right / left / back / front / top / bottom`,把逻辑 `top` 精确映射到 `+Z` 顶面,并按每面 UV 朝向做必要的翻转校正;六面贴图通过换签或 blob 异步解析时,Three.js 平台 mesh 的刷新签名必须包含 top/front/right/back/left/bottom 六个 texture URL,任一面 URL 变化都要触发材质重建,不能只监听旧单图 `imageSrc`。旧作品没有完整 `faceAssets` 时使用 DOM 图片 / 原型兜底层,不使用单图 3D 贴面 fallback。立方体统一绕玩法竖直 Z 轴自转 45°,让玩家稳定看到顶面和两个侧面,不做 Y 轴偏航,不得把 x/y/z 缩放成扁盒子;Three.js 方块模型边长视觉放大 1 倍,但平台中心点、随机间距和蓄力换算均保持原规则;后端命中 footprint 必须与当前视觉顶面完整对齐;地块材质使用 `alphaTest` 裁边但不得放进透明材质队列,避免透明排序把地块画到角色之上;角色主路径使用 Three.js Sprite 并与平台共用同一屏幕坐标投影,Sprite 脚点必须按当前方块半高抬到顶面中心高度,绘制顺序必须高于地块,DOM 角色仅作为 WebGL 或角色贴图加载失败兜底;相机保持约 `1.69x` 近距 45° 下压视角,当前脚下地块根据目标方向偏向场地反侧,可见当前 / 目标两块地板之间的屏幕间距必须形成正负 45 度关系;所有地块从出现开始保持真实规格,不按距离、深度或预览状态做倍率缩放;长按蓄力、计时刷新和角色位置更新不得销毁重建透明画布、平台贴图预加载层或角色层。 -12. 同等世界距离的蓄力换算必须使用 `0.004` 系数,松手后必须先看到角色飞行动画,再保留约 `300ms` 落地停顿,随后看到地块窗口前移;成功落地显示必须保留真实落点偏移,且正确落点范围必须严格等于下一块地块完整可见顶面 footprint。 diff --git a/docs/project-memory/README.md b/docs/project-memory/README.md index 8245289d0..6c1fb53b7 100644 --- a/docs/project-memory/README.md +++ b/docs/project-memory/README.md @@ -1,8 +1,8 @@ # 项目记忆目录 -本目录保存可以进入 Git 的项目级长期知识,供开发者和 Agent 读取。`.hermes/` 只保留 Hermes 工具专用资源,不再作为项目知识库。 +本目录只保存可以通过 Git 共享、并且对当前开发仍有效的项目知识。`.hermes/` 只放 Hermes 工具资源,不作为项目知识库。 -## 目录结构 +## 当前结构 ```text docs/project-memory/ @@ -15,18 +15,20 @@ docs/project-memory/ │ ├─ decision-log.md │ ├─ pitfalls.md │ └─ handoff-template.md -├─ plans/ -└─ todos/ +├─ plans/ # 仅限正在执行的短期计划 +└─ todos/ # 仅限仍开放且有退出条件的事项 ``` ## 使用原则 -- 开发前先读 `AGENTS.md`;复杂任务继续读取 `docs/【协作规范】Agent工作入口与执行准则-2026-06-22.md`,再按任务读取 `docs/project-memory/shared-memory/` 和当前 `docs/` 文档。 -- 长期有效的架构约定、接口变化、排障经验、开发流程和协作规则写入 `shared-memory/`。 -- 阶段性计划写入 `plans/`,已确定但暂未实施的共享 TODO 写入 `todos/`。 -- 如果本目录内容与代码或最新 `docs/` 冲突,以代码和最新 `docs/` 为准,并同步修正过期记忆。 +- 开发前先读 `AGENTS.md`;复杂任务再读 Agent 执行准则、共享记忆和任务对应的当前专题文档。 +- 稳定架构、接口、流程和排障边界写入 `shared-memory/`;同一事实只保留一个当前口径,细节放在权威专题文档。 +- `plans/` 只保存正在执行、具有明确剩余项和验收门禁的计划;完成或作废后立即删除,稳定结论融合进当前专题或共享记忆。 +- `todos/` 只保存真实开放、有人接手即可执行的事项;每项应写明状态、下一决策点和关闭条件。已退役对象不保留未来 TODO。 +- 分支、提交、测试轮次和阶段流水账不进入长期记忆;需要追溯时使用 Git 历史。 +- 若本目录与代码或最新 `docs/` 冲突,以代码和最新专题为准,并在同次变更中修正记忆。 - 禁止写入个人配置、API Key、Token、Cookie、会话记录、认证文件、本地私密路径、构建产物、日志、缓存和数据库 dump。 ## RAG 索引 -本目录是 Agent 本地 RAG 的高权重索引源。RAG 主要用于 Agent 检索上下文,不替代人工阅读入口或正式文档地图。索引脚本位于 `scripts/rag/`,本地生成的 `.rag/` 数据不提交 Git。 +本目录是本地 RAG 的高权重索引源,但检索结果只作为候选上下文。索引脚本位于 `scripts/rag/`;运行时依赖和 `.rag/` 数据默认不安装、不提交,启用前需先征得用户确认。 diff --git a/docs/project-memory/plans/【前端重构】音频生成面板恢复共享分流方案-2026-08-06.md b/docs/project-memory/plans/【前端重构】音频生成面板恢复共享分流方案-2026-08-06.md deleted file mode 100644 index 5abe42b8a..000000000 --- a/docs/project-memory/plans/【前端重构】音频生成面板恢复共享分流方案-2026-08-06.md +++ /dev/null @@ -1,188 +0,0 @@ -# 音频生成 Composer 恢复共享分流方案 - -日期:`2026-08-06` - -状态:`已实施` - -## 一、目标 - -图片画布的音效与背景音乐恢复使用同一个音频 composer。`ImageCanvasGenerationComposerView.tsx` 内只保留一个 `ImageCanvasAudioGenerationComposerView`,并在组件内定义: - -```ts -const isSoundEffect = dialog.mode === 'audio-sound-effect'; -``` - -`isSoundEffect === true` 渲染现有 SFX 分支,`isSoundEffect === false` 渲染现有 BGM V1 分支。删除完整的独立 BGM composer 文件,但保留确有独立职责的 BGM 纯模型、助手 controller 和预设跑马灯组件。 - -这次只调整前端视图组织方式,不改变任何生成契约、业务规则、请求时序、计费或持久化语义。 - -## 二、范围与非目标 - -### 2.1 必须保留的 BGM 能力 - -- `gpt_description_prompt` 可见原文、Unicode `White_Space` canonicalization 和 200 字生成限制。 -- 30 个预设、字符计数、AI 补全、一键简化和单层交换式撤销。 -- AI 处理锁、同步正式提交锁、`generating` 锁和迟到响应隔离。 -- 稳定 dialog ID、账号 / 项目 scope 校验和按 dialog ID 写回。 -- 固定 `Suno`、当前动态泥点价格和隐藏 `make_instrumental` 的现状。 - -### 2.2 必须保持不变的现有 SFX 能力 - -- 固定 Vidu `audio1.0`,Prompt 同值映射到现有 `prompt + sound` 请求字段。 -- `2–10` 秒、步长 `1` 秒、默认 `5` 秒。 -- 当前 Prompt 规范化、全空白时回退“游戏音效”、1500 字限制、价格和失败态。 -- 现有提交 callback、生成占位和完成链路。 -- SFX 中不出现 Suno、BGM 预设、AI 补全、一键简化、BGM 字符计数或撤销。 - -### 2.3 本次明确不做 - -- 不实现 SFX V2 独有的一键优化、自动中译英、ElevenLabs、自动时长、30 秒、Loop 或 SFX 预设。 -- 不修改 BGM 或 SFX 需求原文。 -- 不修改 BFF、队列、`platform-audio`、External v1、OpenAPI、SpacetimeDB schema、计费或重试。 -- 不把 BGM Prompt controller 泛化为音频通用 controller。 -- 不新建配置驱动的 composer 框架、第二套音频组件或其它顺带重构。 - -## 三、当前问题 - -当前 `ImageCanvasGenerationComposerView.tsx` 分别渲染 SFX 内部组件和 `ImageCanvasBackgroundMusicGenerationComposerView.tsx`。这层完整视图拆分让同一个音频入口形成两套 composer 边界,而 SFX V2 需求已经表明预设、AI 写回、撤销和锁定等交互并非 BGM 永久独占,继续用“BGM 专属交互较多”作为完整组件分叉理由不再成立。 - -同时,最近一次合并把共享架构中的 `isSoundEffect` 条件表达式带回了当前 SFX-only 组件,却没有带回变量定义,形成 `isSoundEffect is not defined`。该问题不是增加一个局部常量后就可以收口的长期架构问题;本次重构应恢复单一音频组件,使变量与它控制的两个分支重新处于同一组件边界。 - -## 四、目标结构 - -```text -ImageCanvasEditorView -└─ useImageCanvasGenerationSurface - └─ ImageCanvasGenerationComposerView - └─ ImageCanvasAudioGenerationComposerView - ├─ isSoundEffect === true → 现有 SFX UI 与行为 - └─ isSoundEffect === false → 现有 BGM V1 UI 与行为 - └─ ImageCanvasBackgroundMusicPresetMarquee -``` - -继续保留的 BGM 专项模块: - -- `ImageCanvasBackgroundMusicPromptModel.ts`:canonicalization、计数、动作资格和 dialog 类型收窄。 -- `useImageCanvasBackgroundMusicPromptAssist.ts`:按 dialog ID 隔离的异步助手状态与提交锁。 -- `ImageCanvasBackgroundMusicPresetModel.ts`:30 个预设与追加规则。 -- `ImageCanvasBackgroundMusicPresetMarquee.tsx`:展开、滚动、hover、触摸和 reduced-motion。 - -删除的完整视图模块: - -- `ImageCanvasBackgroundMusicGenerationComposerView.tsx` -- `ImageCanvasBackgroundMusicGenerationComposerView.test.tsx` - -删除测试文件不等于删除覆盖;其中全部用例必须迁入总 composer 测试。 - -## 五、实现边界 - -### 5.1 单一渲染入口 - -`ImageCanvasGenerationComposerView` 对 `audio-sound-effect` 与 `audio-background-music` 只保留一个渲染条件和一个 `ImageCanvasAudioGenerationComposerView` 调用。组件内部以 `isSoundEffect` 选择两棵现有表单子树,不为本次重构新造配置层。 - -共享组件使用基于 dialog ID 与 mode 的稳定 `key`。连续切换 BGM dialog 时,预设展开、滚动、hover 和触摸状态不得继承;从 SFX 切到 BGM 时,音效时长菜单状态也不得泄漏。 - -### 5.2 Hook 与类型安全 - -- React Hook 不得放进 `isSoundEffect` 条件分支。`useState`、`useRef`、`useId` 和 `useImageCanvasFloatingOptionDismiss` 保持固定调用顺序。 -- `GenerateDialogState` 不是可判别联合。BGM 分支继续通过 `toBackgroundMusicGenerationDialog` 取得带稳定 ID 的 `BackgroundMusicGenerationDialogState`。 -- BGM 缺少稳定 ID 或 `backgroundMusicPromptAssist` 时失败关闭,不渲染不完整的 BGM 表单;SFX 不依赖这两个条件。 - -### 5.3 两套状态写回不得合并 - -- SFX 继续走现有 `setGenerateDialog` 路径,保持按 mode 更新、失败态复位和时长写回语义。 -- BGM 继续走 `updateCanvasGenerationDialogById(dialog.id, updater)`,不能降级成只比较 mode。助手响应、预设、撤销和提交锁仍按稳定 dialog ID 隔离。 -- `backgroundMusicPromptAssist` 可以继续由 surface 传给共享 composer,但只允许 BGM 分支读取或调用。 - -### 5.4 锁定与提交资格不得串用 - -|分支|锁定条件|生成资格| -|---|---|---| -|SFX|沿用现有 `dialog.status === 'generating'`|沿用现有 SFX 提交入口和默认 Prompt 规则| -|BGM|AI processing、`submitting` 或 `generating` 任一成立|沿用 canonical Prompt 的有效字符与 `1–200` code point 规则| - -BGM 使用 `PlatformTextField + readOnly + aria-invalid`;SFX 继续使用 `AutoGrowTextArea + disabled`。本次不统一这两个输入控件,也不改错误、可访问名称或按钮文案。 - -## 六、预计代码改动 - -|文件|最小改动| -|---|---| -|`ImageCanvasGenerationComposerView.tsx`|恢复共享 `ImageCanvasAudioGenerationComposerView` 与 `isSoundEffect`;移入现有 BGM JSX、常量和依赖;删除独立 BGM import 与双渲染入口| -|`ImageCanvasGenerationComposerView.test.tsx`|迁入独立 BGM composer 的全部测试,并增加双 mode 隔离与切换回归| -|`ImageCanvasBackgroundMusicGenerationComposerView.tsx`|删除| -|`ImageCanvasBackgroundMusicGenerationComposerView.test.tsx`|覆盖迁完后删除| -|`useImageCanvasBackgroundMusicPromptAssist.ts`|只修正指向独立 composer 的历史注释;不改 controller 行为| - -以下生产文件预计不改:`useImageCanvasGenerationSurface.tsx` 的现有 props 接线、BGM Prompt / 预设模型、预设跑马灯、submission workflow、submission model、dialog model、`src/index.css` 的现有 BGM 样式,以及全部后端代码。 - -如实施时发现必须超出该清单才能保持现有行为,应先停下并重新确认边界,不能借本次组件归并顺带重构。 - -## 七、测试迁移与回归矩阵 - -### 7.1 BGM 原覆盖完整迁移 - -独立组件测试中的下列覆盖必须逐项迁入 `ImageCanvasGenerationComposerView.test.tsx`: - -- canonical preview 计数、超限展示和不改写输入框。 -- 0 / 1 / 2 个有效字符及 200 / 201 / 2000 / 2001 边界。 -- 补全、简化、撤销和预设按正确 dialog ID 路由。 -- `preparePreset` 拒绝时不写回,预设成功时沿用追加和清快照语义。 -- 助手错误与生成错误的展示顺序。 -- Suno、泥点价格、生成允许 / 拒绝。 -- `completing`、`simplifying`、`submitting`、`generating` 锁定。 -- 完整单层撤销按钮矩阵和现有可访问属性。 - -### 7.2 mode 隔离与切换 - -- SFX 渲染时不存在 BGM 控件,也不存在本次明确排除的 SFX V2 控件。 -- BGM 渲染时不存在 Vidu 和音效时长控件。 -- SFX 仍保持 `audio1.0`、2–10 秒、默认 5 秒、当前价格和既有提交参数。 -- BGM dialog A 展开预设后切到 dialog B,局部展开与滚动状态不继承。 -- SFX 与 BGM 相互切换时,菜单、锁和 Prompt 助手状态不跨 mode 泄漏。 -- 缺少稳定 ID 或 controller 的 BGM 失败关闭;同样条件不影响 SFX 正常渲染。 - -### 7.3 最小验证命令 - -```powershell -npm run test -- src/components/image-editor/ImageCanvasGenerationComposerView.test.tsx src/components/image-editor/ImageCanvasBackgroundMusicPromptModel.test.ts src/components/image-editor/ImageCanvasBackgroundMusicPresetModel.test.ts src/components/image-editor/ImageCanvasBackgroundMusicPresetMarquee.test.tsx src/components/image-editor/useImageCanvasBackgroundMusicPromptAssist.test.tsx -npm run test -- src/components/image-editor/useImageCanvasGenerationSurface.test.tsx src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx -npm run typecheck -npm run check:encoding -git diff --check -``` - -删除旧测试文件后,还要确认测试收集清单中不再引用它。若本次改动触发其它现有图片画布测试失败,只修复由共享 composer 归并直接造成的回归,不扩大到无关模块。 - -## 八、实施顺序 - -1. 在总 composer 内恢复共享音频组件、`isSoundEffect` 和单一音频渲染入口。 -2. 原样迁入 BGM 分支,保留按 ID 写回、锁定、错误顺序、Suno 与预设行为。 -3. 迁移独立 BGM 组件测试,并补齐 SFX/BGM 隔离与切换用例。 -4. 删除独立 BGM composer 及其测试文件,修正相关注释与文档引用。 -5. 运行定向测试、typecheck、编码检查和差异检查;实现完成后再把实际结果补入 T6 后续记录。 - -## 九、完成定义 - -- 两个音频 mode 均从同一个 `ImageCanvasAudioGenerationComposerView` 渲染,且组件内存在唯一的 `isSoundEffect` 分流。 -- 独立完整 BGM composer 文件和独立测试文件已删除,原测试覆盖无遗漏地迁入总 composer。 -- BGM V1 所有已交付能力与正式提交语义不变。 -- 现有 SFX UI、Prompt、Vidu、时长、价格、校验和提交链路无回归。 -- 没有实现任何 SFX V2 独有功能,没有修改需求原文或后端契约。 -- 规定的定向测试、typecheck、编码检查和 `git diff --check` 全部通过。 - -## 十、实施结果 - -2026-08-06 已按本文边界完成: - -- `ImageCanvasGenerationComposerView.tsx` 恢复唯一 `ImageCanvasAudioGenerationComposerView`,由组件内 `isSoundEffect` 分流;BGM 继续按稳定 dialog ID 写回,SFX 继续走原 `setGenerateDialog` 路径。 -- 删除 `ImageCanvasBackgroundMusicGenerationComposerView.tsx`,保留 BGM Prompt / 预设纯模型、助手 controller 和预设跑马灯。 -- 把独立组件全部用例迁入 `ImageCanvasGenerationComposerView.test.tsx` 后删除旧测试文件;总 composer 现有 50 项测试同时覆盖 BGM 完整动作矩阵和 SFX/BGM 控件、状态、dialog 切换隔离。 -- 只修正 `useImageCanvasBackgroundMusicPromptAssist.ts` 的组件归属注释;没有修改 controller、surface、submission workflow、样式、后端、契约或需求原文,也没有实现 SFX V2 独有功能。 - -实际验证: - -- Prompt / 预设 / controller / 总 composer:`121/121`。 -- surface 与 submission workflow:`72/72`。 -- `npm run typecheck`、变更文件 ESLint、Prettier、`npm run check:encoding` 和 `git diff --check`:全部通过。 - -2026-08-06 已执行共享 composer 归并后的浏览器视觉 smoke,未发现阻断性问题;本轮未创建真实音频生成任务或产生扣费。 diff --git a/docs/project-memory/plans/【实施计划】AGC无人值守游戏生成可靠性收口-2026-08-13.md b/docs/project-memory/plans/【实施计划】AGC无人值守游戏生成可靠性收口-2026-08-13.md deleted file mode 100644 index dcb8784f5..000000000 --- a/docs/project-memory/plans/【实施计划】AGC无人值守游戏生成可靠性收口-2026-08-13.md +++ /dev/null @@ -1,248 +0,0 @@ -# AGC 无人值守游戏生成可靠性收口实施计划 - -日期:`2026-08-13` - -## 1. 目标 - -本次收口的验收对象不是单个报错点,而是一次完整的用户任务: - -> 用户提交一段游戏需求后,不再确认权限、不再补充“继续”、不再手工重试,AGC 在有界时间内自动产出一版可玩的游戏,并完成当前 revision 的静态验证与桌面、移动双视口真实试玩;若外部依赖或环境确实不可恢复,则必须自动收束为带安全原因的明确失败,不能永久停留在运行中、待确认或等待某个专业 Agent。 - -“产出了一份 HTML”不等于完成。最终完成必须同时满足: - -1. 权威入口产物存在、非占位且可解析。 -2. 游戏具备真实主要玩法,而不是装饰按钮或固定奖励假体。 -3. `playable-web-game-state.v1`、start、primary-action、restart 合同可由真实浏览器执行。 -4. 当前 revision 通过 `game.static_smoke`。 -5. 当前 revision 通过 desktop 与 mobile `preview.validate`。 -6. Runtime、manifest、产物和验证回执的终态一致。 - -## 2. 当前失败基线 - -本次复现暴露的不是孤立实现缺陷,而是生成控制面的系统性断链: - -- 普通工作台提交使用 `project-supervisor-gui`,进入固定专业任务图;一个单 HTML MVP 也会被美术、音频等前置依赖阻塞。 -- 工作台仍展示“严格审批”,运行期间可以进入 `waiting-for-confirmation` 或要求用户继续,不满足无人值守目标。 -- `game.static_smoke` 失败时,持久回执可能只剩 `safeDetail=null`、`detailUnavailable=true`;同一 owner 看不到失败项,只能猜测修补。 -- 可修复的验证失败可能结束旧任务、留下空队列或失败卡片,未保证回到同一主 Run 继续“诊断 -> 修复 -> 重验”。 -- 子任务可以先报告 completed,再在投影阶段发现正式产物缺失,造成 Runtime 终态、manifest 状态和文件事实不一致。 -- `execution-owner` 对应进程消失后,持久 Runtime 仍可能显示 running,缺少自动对账和续跑闭环。 - -直接 Codex 能在数分钟内生成明显更完整的可运行雏形,说明首要瓶颈是 Runtime 的路由、反馈和验收控制,而不是基础模型完全不具备实现能力。 - -## 3. 范围 - -### 3.1 本次必须完成 - -1. **默认单主生成路由** - - 持久路由前零 child;持久路由后只启动 `code-prototype`。 - - 美术只在 `asset.list` 证明精确缺口后动态委派,且一次只处理一个依赖槽。 - - 保留 `project-supervisor-gui` 给显式专业 DAG/开发诊断入口,不再作为普通生成默认值。 - -2. **无人值守安全策略** - - 该模式不得进入普通 `waiting-for-confirmation` 或 `waiting-for-user-input`;模型信息不足时先采用目标合同允许的安全默认值。 - - 越界路径、任意命令、发布、凭据、系统设置和未列入白名单的外部副作用继续失败关闭,不能为了“无人值守”扩大权限。 - -3. **可操作的验证诊断与自动修复循环** - - `game.static_smoke` 失败回执向同一 run owner 返回脱敏、结构化的失败码、检查项、项目相对路径和有界说明。 - - 公共聊天和跨 owner 回执只展示安全摘要,不泄露绝对路径、命令原始输出、密钥、URL query 或内部 fingerprint。 - - 可修复失败必须回到同一 `code-prototype` Run,继续修改后按“脚本解析 -> static smoke -> desktop/mobile preview.validate”顺序重验。 - - 相同 revision、相同失败指纹无新 mutation 时不得无限重试;命中停滞门后明确失败。 - -4. **完成投影与正式产物一致性** - - owner 子任务进入 completed 投影前,逐项验证其声明的正式 artifact 存在、非空,并对 JSON/PNG/HTML 执行已有格式门。 - - 只读验证任务不得声明由自己写入的正式文件产物。 - - 产物缺失时不能把 manifest 写成 completed;必须产生可修复 blocker 并由主 Run 接管,或在不可恢复时明确 failed。 - - 根 Run 只有在当前任务图、正式产物、static smoke 和双视口试玩全部对齐后完成。 - -5. **Runner 消失后的自动对账** - - 读取 `execution-owner` 时同时核对 boot identity 与进程存活性,不能只相信 JSON 中的 PID。 - - owner 已消失且 durable task 仍为可恢复活跃态时,新 Runner 启动/项目 hydration 自动恢复队列;不能永久显示 running。 - - 外部副作用结果未知时进入 `needs-reconciliation` 并保留证据,不能盲目重做;纯 Provider、项目内文件和验证动作可以按现有 durable checkpoint 安全续跑。 - - 对账与恢复必须幂等,同一 run 不产生重复 child、重复消息或重复付费生成。 - -6. **有界端到端验收** - - 用确定性 Provider/工具夹具覆盖“首次 smoke 失败 -> 同主 Run 取得具体诊断 -> 修复 -> smoke 通过 -> 双视口试玩通过 -> completed”。 - - 覆盖 owner 中途消失后新 boot 自动续跑,最终只产生一个根终态。 - - 任何人工确认、人工澄清、固定专业 DAG 等待、旧 revision 验证复用或 console error 都使 E2E 失败。 - -### 3.2 本次不做 - -- 不直接修改用户下载目录中的失败示例;它只作为复现样本。 -- 不把直接 Codex 生成的某个三消 HTML固化成平台模板。 -- 不恢复已退役的主站玩法入口、公开作品系统或旧创作模板后端。 -- 不允许任意 shell、项目外路径写入、自动发布或自动消费未知外部付费能力。 -- 不以隐藏错误、自动点击确认或延长预算冒充可靠性修复。 - -## 4. 目标状态机 - -```text -accepted - -> route-pending - -> code-prototype-running - -> asset-audit - -> optional-art-delivery - -> implementation - -> syntax/static-validation - -> desktop-mobile-playtest - -> completed - -可修复失败: -validation-failed -> owner-repairing -> validation - -进程中断: -owner-lost -> recovery-scan -> same-run-resumed - -外部结果未知: -owner-lost -> needs-reconciliation -> explicit terminal/recovered - -不可恢复或停滞: -any active state -> failed (safe terminal reason) -``` - -普通无人值守生成路径禁止出现: - -```text -waiting-for-confirmation -waiting-for-user-input -fixed-art/audio dependency wait -running with a dead owner and no recovery record -completed with missing artifacts or stale validation -``` - -## 5. 实施切片 - -### 切片 A:入口和路由收敛 - -主要位置: - -- `apps/ai-game-creator-shell/src/App.tsx` -- `apps/ai-game-creator-shell/src/features/agent-runtime/model.ts` -- `apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/task_start.rs` - -实施内容: - -- 把 source 选择抽成可测试的纯函数,避免 UI 分支再次漂移。 -- 保持显式专业/CLI 调试来源不变。 -- 调整工作台状态投影,不再向默认用户展示固定专业 DAG 和无效“严格审批”承诺。 - -### 切片 B:无人值守权限与失败反馈 - -主要位置: - -- `runtime_tools/policy.rs` -- `runtime_actions/provider_action_batch.rs` -- `runtime_tools/command_ops.rs` -- `runtime_actions/action_audit.rs` -- `runtime_actions/provider_request_builders.rs` - -实施内容: - -- 对该来源的确认型动作做“安全自动执行或明确拒绝”二分,不能挂起等待。 -- 为 `command.run_limited/game.static_smoke` 定义稳定的 safe detail schema。 -- 保证同 owner 的下一轮 Provider context 能读取失败项,公共 UI 仍只拿安全摘要。 -- 增加失败指纹与 revision liveness 测试,阻止无 mutation 重复 smoke。 - -### 切片 C:完成门和恢复对账 - -主要位置: - -- `runtime_protocol/autonomous_completion.rs` -- `runtime_driver/task_start.rs` -- `runtime_driver/recovery_scan.rs` -- `runner/project_owner.rs` -- `runner/recovery.rs`(以实际调用边界为准) - -实施内容: - -- 将 artifact 合同校验前移到 terminal projection。 -- 对完成声明、manifest 状态和文件事实做一次原子/锁内判断。 -- owner 丢失时按 durable action 类型判断 same-run resume 或 reconciliation。 -- 恢复后重新核对当前 revision,旧 smoke/试玩回执不能过门。 -- 缩短无进展窗口;预算只限制时间,不能替代完成门。 - -### 切片 D:端到端门禁和权威文档 - -主要位置: - -- `apps/ai-game-creator-shell/tests/appSurface.test.ts` -- Runtime Rust 定向测试模块 -- `docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md` -- `docs/project-memory/shared-memory/development-workflow.md` -- `docs/project-memory/shared-memory/decision-log.md` -- 必要时 `docs/project-memory/shared-memory/pitfalls.md` - -实施内容: - -- 增加无确认、失败自修复、artifact 真实性和 owner-loss 恢复测试。 -- 增加确定性 E2E;真实 Provider smoke 作为现场验收,不把 mock E2E 说成真实生成已经成功。 -- 把新的默认路由、无人值守安全边界和复验命令写回权威文档。 - -## 6. 验收矩阵 - -| 场景 | 预期结果 | -|---|---| -| 素材完整 | 零美术委派、零额外扣费 | -| 缺少规范图和图集 | 先规范图后图集,一次一个 delivery,主 Run 认领后继续 | -| 项目内文件修改、static smoke、preview validate | 在可信 autonomous binding 下不等待人工确认 | -| 请求任意系统命令或项目外写入 | 明确 blocked/failed,不执行,也不挂起等待确认 | -| 首次 JS/static smoke 失败 | 同一 owner 得到结构化失败项,修改后自动重验 | -| 连续同 revision 同错误 | 停滞门阻断重复猜测,明确失败或回到可行动步骤 | -| 子任务回复 completed 但 artifact 缺失 | manifest 不得 completed;产生修复 blocker | -| 最后 mutation 后只存在旧验证 | 根 Run 不得 completed,强制重验当前 revision | -| Runner 在 Provider/文件动作间退出 | 新 boot 幂等恢复同 run,不重复 child/消息 | -| Runner 在未知付费外部动作中退出 | `needs-reconciliation`,不自动重复扣费 | -| 最终完成 | 无 console error;static + desktop/mobile playtest 均属于当前 revision | - -## 7. 验证命令 - -按实际改动范围至少运行: - -```bash -npm --prefix apps/ai-game-creator-shell run typecheck -npm run test -- apps/ai-game-creator-shell/tests/agentRuntimeModel.test.ts apps/ai-game-creator-shell/tests/appSurface.test.ts --run -cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml autonomous_completion_contract -- --nocapture --test-threads=1 -cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml action_receipt -- --nocapture --test-threads=1 -cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml project_execution_owner -- --nocapture --test-threads=1 -npm run check:encoding -git diff --check -``` - -如果完整 Rust suite 受既有 Windows 文件锁影响,必须单独复跑新增 filter,并在交付中如实记录完整门仍不干净;不能用定向通过替代全量结论。 - -现场真实验收还需要: - -1. 使用新的空项目提交一个明确、无需追问的小游戏需求。 -2. 全程不点击确认、不发送继续、不手工重试。 -3. 记录首个可玩版本耗时、Provider/工具轮数、委派数和失败修复次数。 -4. 核对最终 manifest、current revision、static receipt、desktop/mobile playtest receipt 和浏览器 console。 -5. 中途强制结束 Runner 一次,重新启动客户端后确认 same-run 自动续跑且没有重复付费动作。 - -## 8. 完成定义 - -只有以下条件全部满足,本计划才算实现完成: - -- 普通 GUI 默认进入单主快车道。 -- 一个确定性端到端夹具证明首次验证失败可由同一主 Run 自动修好并最终完成。 -- 一个 owner-loss 夹具证明新 boot 自动恢复且终态唯一。 -- 可信无人值守路径不存在普通人工确认或澄清等待。 -- completed 前 artifact、当前 revision static smoke 与双视口试玩均被强制复核。 -- 相关定向测试、类型检查、编码检查和 diff 检查通过。 -- 使用真实 Provider 的空项目 smoke 成功;若现场外部服务不可用,则代码可以提交为“实现完成、真实现场验收未完成”,不得宣称目标已完全达成。 - -## 9. 实施与验证记录(2026-08-15) - -在 `codex/agc-runtime-generation-reliability` 分支完成: - -- 可信 `code-prototype` 父 Run 可认领并观察直属美术 delivery、按 `delegationId` 精确读取合同;错误 Agent/Run、未知合同与身份篡改统一失败关闭。父 task/chain 无法证明但仍有活跃或已认领 delivery 时 completion 必须 blocked;Suppressed 且未形成 child 的失败前置记录不参与 capability、claim 与 completion barrier。 -- Windows `.agent/project.lock` 不再对最终 `create_new` 目标做 metadata 预检,delete-pending 的 5/32/33 统一进入有界竞争等待;新增 delete-pending 回归,复现真实 `create_new` ACCESS_DENIED 后证明等待可收束。 -- 真实 `gpt-5.6-sol / reasoningEffort=max` 隔离轮次:14 个 Provider 请求全部完成并闭合,无确认、追问、steer、路径/密钥/正文泄漏,Runner 与后代进程清理为零残留;在未配置 External Editor 的边界下 art-director 失败后由主 Run 认领并快速明确收束,未再次空转。 -- 待完成:用有效 External Editor 配置跑一轮完整 playable 真实验收;当前结果不能宣称现场完整生成已通过。 -- 2026-08-15 后续修复:Runtime 配置保存成功或失败均显示可见 toast;默认 `gpt-5.6-sol / reasoningEffort=max` 已同步到启动配置门禁,`check-config`、AGC typecheck 和运行时设置定向测试(6 项)通过。 - -## 10. 回滚边界 - -- 默认路由可回退到原 `project-supervisor-gui`,但不能同时保留两套普通入口形成随机分流。 -- 自动权限只由可信 source + root profile + binding fingerprint 共同启用;回滚时删除该窄例外,不修改全局策略默认值。 -- 新 safe detail schema 只增加脱敏诊断,不改变原始审计账本的权限边界。 -- 恢复逻辑只消费现有 durable task/action/profile/owner 记录,不删除 `.agent`、锁文件或用户产物。 diff --git a/docs/project-memory/plans/【实施计划】AGC直连Codex Runtime迁移-2026-08-15.md b/docs/project-memory/plans/【实施计划】AGC直连Codex Runtime迁移-2026-08-15.md deleted file mode 100644 index 66349723f..000000000 --- a/docs/project-memory/plans/【实施计划】AGC直连Codex Runtime迁移-2026-08-15.md +++ /dev/null @@ -1,419 +0,0 @@ -# AGC 直连 Codex Runtime 迁移实施计划 - -日期:`2026-08-15` - -## 1. 目标 - -新增一条面向普通 AGC 项目的“直连 Codex Runtime”链路:用户在项目聊天中输入需求,客户端把聊天内容、项目工作区和受限系统提示词直接交给 Codex app-server,由 Codex 自己完成理解、文件修改、命令执行、验证和回复。产品默认只使用 `codex_app_server`,不再让用户选择 Provider / CLI / Supervisor 模式。 - -本次迁移保留现有 Supervisor、专业 Agent、harness、real-E2E 和旧 Runtime 源码及测试,旧链路只作为开发诊断、回滚和历史数据读取能力,不再作为普通项目聊天的默认执行入口。 - -## 2. 当前问题证据 - -- `gameagent-20a04b8f` 首轮生成的入口触发 `ReferenceError: tick is not defined`,同时请求 `assets/art-spritesheet.png` 返回 404,`generic-v1` 的 `primary-action` 没有推进 sequence;Runtime 连续重试至 loop budget exhausted。 -- 同一项目重试时,视觉 Agent 访问 `http://localhost:3000/api/external/v1/editor/projects` 连接失败,导致 `canvas.asset_generate` 失败,父链最终仍只展示“项目总控 Agent 执行失败,请稍后重试”。 -- 这些失败来自 AGC 多层 Supervisor / child / harness / 完成门编排,而用户只需要一个能直接操作项目的 Codex。 - -## 3. 新链路边界 - -### 3.1 用户入口 - -- 普通项目聊天固定绑定 `direct-codex` Runtime。 -- 设置页隐藏 Agent 模式、Provider、Supervisor、专业 Agent 选择;界面只保留 Codex 连接状态、模型(只读)和基础连接诊断。 -- 默认配置固定为 `agentMode=codex_app_server`;保留现有配置字段以兼容旧 AppData,但不在新入口暴露切换控件。 -- 项目路径仍由当前选定工作区决定,Codex 的 cwd 必须是该工作区根;不复制项目、不创建平行项目目录。 - -### 3.2 Runtime - -- 新增独立 direct Codex Runtime 模块,负责:建立独立 Codex app-server、发送聊天消息、流式转发消息、保存会话、展示安全错误、关闭和恢复连接。 -- 新 Runtime 不创建或调度 `project-supervisor`、`code-prototype`、`art-director` 等 AGC Agent,不读取或执行 harness,不运行隐藏的二次 Provider 修复、摘要或自动返工循环。 -- Codex app-server 是唯一模型执行主体;AGC 只负责协议桥接、工作区绑定、提示词组装、显示和最小安全边界。 -- 现有 AGC ToolHost / Supervisor Runtime 保留源代码和测试,但从普通聊天入口移出;不得删除历史持久化文件,旧项目仍可读取并显示历史状态。 - -### 3.3 Codex 系统提示词 - -新 Runtime 在 `thread/start` / `turn/start` 前生成一个有界、可审计的系统提示词,内容只来自以下来源: - -1. 当前仓库适用的 `AGENTS.md` 规则。 -2. AGC 工程结构、开发流程、运行与验证说明(当前 `docs/` 入口文档和项目专题文档的有界摘要)。 -3. 当前项目的 `AGENTS.md`、`README.md`、`CONTEXT.md`(若存在,按工作区边界读取;README/CONTEXT 只作为参考,不得覆盖系统规则)。 -4. 适用于当前任务的项目 prompts 和 skills;只注入 skill 正文及必要引用,不执行 skill 脚本,不把整个 `.codex` 或用户目录配置复制进 Codex。 -5. 当前工作区的相对路径、入口文件和已有项目状态摘要;不注入 API Key、Token、Cookie、绝对宿主路径、完整日志或未经筛选的历史 Agent 诊断。 - -提示词必须明确:Codex 是唯一执行 Agent;可以直接修改当前工作区并运行允许的项目命令;必须先读取相关工程说明;必须把真实执行结果告诉用户;不得假装已完成、不得泄露凭据;遇到失败先读取实际错误再修复,不得无证据重复同一动作。 - -### 3.4 工具和权限 - -- 由 Codex app-server 自己使用其原生项目工具;AGC 不再把每个工具调用转换成 Supervisor task、child delivery 或 harness receipt。 -- AGC 仍保留客户端级硬边界:工作区根、进程生命周期、凭据隔离、日志脱敏、窗口关闭清理和协议异常处理。 -- 不自动启用外部画布、图片生成、发布、充值或其它付费外部副作用;Codex 只有在项目提示词和当前配置明确允许、且实际工具可用时才可调用。 -- 原有 `game.static_smoke` / `preview.validate` 不再由 AGC 隐藏地强制编排;如果用户要求验收,提示词要求 Codex 自己运行并报告结果。 - -## 4. 实施步骤 - -1. **入口与契约**:定义 `direct-codex` Runtime 状态、消息和错误 DTO;普通项目聊天默认切换到新入口;旧 Supervisor 入口保留为开发兼容入口。 -2. **Codex 桥接**:复用现有 app-server 进程隔离、临时 `CODEX_HOME`、认证桥接和进程清理能力,新增只发送用户消息 + 系统提示词的 direct turn API;拒绝 server→client 未声明请求和非消息原生 item。 -3. **提示词构建器**:按工作区边界读取 AGENTS / docs / prompts / skills,做大小、敏感信息和路径脱敏门禁,记录提示词来源 fingerprint,不记录正文。 -4. **前端收敛**:隐藏模式选择和 Supervisor/专业 Agent 展示,聊天区直接显示 Codex 流式消息、执行状态和可读失败原因;保留设置保存 Toast。 -5. **恢复与持久化**:direct session/run 使用独立 source 和稳定 messageId;断线恢复只恢复同一 Codex thread,不重新执行未知副作用;旧 Supervisor 任务不自动迁移成 direct turn。 -6. **失败可见性**:把 Codex 的安全错误分类为连接、鉴权、上下文、工具执行、命令验证和进程退出,并在 UI 展示具体可操作原因;禁止继续只显示“请稍后重试”。 -7. **文档与回滚**:同步技术方案、开发说明和运行配置说明,保留一个开发开关让维护人员读取旧 Runtime,但产品默认不可见。 - -## 5. 验收 - -- `npm --prefix apps/ai-game-creator-shell run typecheck` 通过。 -- 新 Runtime 单测覆盖:系统提示词来源/敏感信息过滤、工作区 cwd、Codex turn 透传、流式消息幂等、错误映射、断线恢复和进程清理。 -- fake app-server 协议测试证明:一次用户输入只产生一个 direct turn;无 Supervisor/child/harness 调度;API Key 不进入 argv、日志或提示词正文;server 请求被拒绝;native tool item 按协议处理。 -- AppSurface 测试证明:模式选择不可见、默认 Codex app-server、普通聊天消息直达 Codex、失败原因可见、旧项目历史仍可读。 -- `npm run check:encoding` 与 `git diff --check` 通过。 -- 显式 opt-in 的真实 Codex app-server smoke:在隔离项目中完成一次聊天、一次真实文件修改和一次用户可见回复;单独报告 Provider / Codex 网络与本机认证结果,不用旧 harness self-test 冒充。 - -## 6. 不做事项和回滚 - -- 不删除 Supervisor、专业 Agent、harness、真实 E2E 或旧 Runtime 源码;不批量迁移旧 `.agent` 状态。 -- 不把 Codex 原生工具能力无条件扩大为 AGC 的全局权限;安全边界仍由进程、工作区和配置隔离保证。 -- 新 Runtime 通过独立 source / feature flag 回滚到旧入口;回滚不重写用户项目文件、不删除 `.agent`、不重放未知外部动作。 - -## 7. 当前落地状态(2026-08-15) - -- 已新增 `direct_runtime` Tauri 链路:普通聊天直接调用 Codex app-server,cwd 绑定当前项目,使用 workspace-write 沙箱;旧 Supervisor/harness 源码未删除。 -- 已新增有界系统提示词构建器,注入项目规则、工程说明和执行约束,并屏蔽凭据与宿主私密信息。 -- 设置页已隐藏模式选择,保存配置时固定 `agentMode=codex_app_server`。 -- 已通过 `cargo check`、direct Runtime 单测、AGC typecheck、配置契约检查和 `git diff --check`。 -- 修复了 direct app-server 在隔离 `CODEX_HOME` 下的无人值守写入阻断:direct workspace 使用 `approvalPolicy=on-request`,AGC 对受限 file-change 请求自动接受;隔离 Codex 配置仅将当前工作区登记为 trusted,旧 Runtime 仍保持 `approvalPolicy=never`。 -- direct workspace 同时禁用 `shell_tool` / `unified_exec`,避免模型在无人审批策略下退回到被系统拒绝的 PowerShell/Python 命令;原生 file-change 仍由 Codex app-server 执行。 -- 新增仅在 `GENARRATIVE_AGC_DIRECT_DEBUG` 显式开启时输出的脱敏 app-server 事件/stderr 诊断;默认不输出正文或凭据,且覆盖 Bearer/API key/token 脱敏测试。 -- 已用当前 AGC Rust 二进制真实验收:在 `D:\Documents\Genarrative GameAgent\client-direct-codex-20260815` 先创建并删除测试 marker,再由 direct turn 实际写入 `game/index.html`、`game/style.css`、`game/game.js`;`node --check game/game.js` 通过。 -- 已用本地静态 HTTP 服务 + Playwright 打开生成结果:页面标题、Canvas、订单/金币/等级 UI 正常,点击棋盘得到真实“不消除”反馈,点击“整理货架”后金币从 `40` 变为 `20`。仅 favicon 404,不影响游戏入口。 -- 首页“自动创建项目”现已把首条完整需求交给 `chat_with_game_creator_direct_codex`,不再创建 Supervisor Session、不再启动 `start_game_creator_supervisor_runtime_task`;进入 direct 项目时也不再自动调用 `resume_game_creator_agent_runtime_tasks`,避免新项目显示无来源的 Resume。 -- AppSurface 定向测试锁定“自动建项目只发一次 direct Codex、显示 direct 回复、Supervisor start=0、Runtime resume=0”,并已实际通过。 -- 项目开发页中的 direct 组件现在会先 hydrate 外层已选工作区;已有项目不会在首条消息时误创建第二个自动目录。自动建项目或 direct Codex 连接失败后立即停在可见错误,不再落回旧 Supervisor Runtime。 -- 系统提示词会按工作区边界加载有界、脱敏的 `prompts` 与 `SKILL.md` 摘要,并附带内置 direct-game-creation skill;不会把 API Key、Cookie、auth.json、`.env` 或宿主绝对路径带入 Codex 上下文。Direct turn 成功后会刷新 AGC manifest 并尝试启动客户端本地预览,预览失败会把具体原因写入聊天和状态栏。 -- 系统提示词现作为 Codex `thread/start.baseInstructions` 发送,用户消息单独作为 `turn/start.input`,不再把 AGC 规则伪装成用户文本;仓库级 `AGENTS.md` 与 AGC 技术方案以编译期有界摘要随客户端提供,脱离源码 checkout 的项目也能获得工程约束。 -- direct Codex thread 按项目复用同一个进程内 ephemeral session,连续消息保留 Codex 上下文;客户端退出时统一关闭 direct app-server,连接中断后下一次消息会淘汰关闭节点并重新建立连接。 -- Codex app-server 的 `usage-limit`、鉴权、上下文超限、沙箱失败、终态未知等稳定错误现在映射为可行动的中文提示;工作台 direct 页面隐藏 Supervisor/专业 Agent 状态卡,保留单一 Codex 状态和真实错误。 -- 运行页已直接移除“测试切片”控制行及其本地播放/序号状态和样式,只保留游戏运行画面、信息展示与数值微调;AppSurface 合同同时锁定该控件不再渲染、对应 CSS 不再存在。 -- 当前 direct 产物是多文件入口,而历史 `validate_game_html_smoke` 仍按单文件内联 HTML 契约检查;本次 direct 链路不隐藏触发该旧门禁,若要把多文件产物纳入旧门禁需另行设计读取工作区文件的验证契约。 - -## 7.1 默认纯转发收口(2026-08-19) - -### 已确认偏差 - -- 虽然普通聊天已经调用 `chat_with_game_creator_direct_codex`,`direct_runtime` 仍会在每条消息前自行判断美术、在消息后强制浏览器试玩、二次整改和版本登记。 -- 这使“你好”“今天多少号”等非项目消息也被包装成游戏交付任务,用户看到了“准备运行当前本地游戏”“静态烟测”等旧 Runtime 痕迹;已有游戏的普通对话同样被强制拖入完整验收。 - -### 收口决策 - -1. 普通客户端默认链路固定为 `客户端消息 -> 同一项目 Codex app-server thread -> 原样可读回复`。客户端不根据关键词、文件存在性或模型回复推断/决定“新建、续做、生成美术、试玩、修复”。Codex 回合确实改动标准游戏文件后,客户端只按磁盘事实做资源与版本投影,不把投影本身当作另一次创作流程。 -2. 默认 direct turn 只负责:项目根边界、同线程复用、系统提示词/skills 注入、进程与凭据隔离、协议异常安全错误、消息显示,以及实际文件变更后的确定性客户端投影。它不自动调用陶泥儿生图、浏览器预览、static smoke、二次 LLM 或隐藏返工;没有文件变化的普通聊天不得修改 manifest、revision 或版本。 -3. Codex 是唯一执行主体:它根据用户消息、系统提示词、工程结构和自身可用工具判断是否聊天、修改已有游戏、创建游戏或执行验证;客户端不得恢复 Supervisor、专业 Agent、harness 或固定游戏流程作为补偿。 -4. 系统提示词必须清楚区分:非项目问题直接正常回答且不触碰工作区;项目修改按需要读写当前项目;用户明确要求生成/验收时由 Codex自行执行或如实说明工具限制。客户端不以“安全”为由把任意消息重写成生成任务。 -5. 回归验收至少覆盖同一实际项目中连续发送“你好”“今天多少号”:均不得触发平台美术、预览、试玩、版本登记或文件变更;再发送一个明确项目修改请求,必须仍复用同一 Codex thread 且由 Codex 自行处理,实际变更的 `game/` 文件随后应出现在客户端“游戏代码”和“项目版本”中。 - -## 7.2 当前桌面端验收的内置 Codex 侧车 staging 修复(2026-08-20) - -### 现场问题 - -- 当前 checkout 执行 `npm run agc` 后,前端 `127.0.0.1:3080`、本地 API `127.0.0.1:8082` 与 SpacetimeDB `127.0.0.1:3101` 均已健康,但桌面壳没有稳定出现。 -- 原因是 `src-tauri/build.rs` 每次 Cargo 构建都无条件覆盖 `src-tauri/resources/codex/win-x64/codex.exe` 与 `manifest.json`。Tauri dev watcher 将资源写入识别为源码变化,再次启动 Cargo 构建,形成“构建 -> 覆盖约 300 MiB 侧车 -> watcher 重建”的循环。 - -### 修复与验收计划 - -1. 内置 Codex 侧车继续从锁定的 npm 原生包 stage 到正式 bundle resource,保留版本与 SHA-256 完整性清单;但仅当二进制内容实际变化时复制,且仅当清单文本变化时写入。 -2. 不取消 `cargo:rerun-if-changed` 对上游侧车与声明文件的监听;上游升级仍必须触发重新 stage,运行时仍拒绝 hash 不匹配的内置可执行文件。 -3. 真实回归:从干净的本次 AGC dev 进程重启,确认一次必要的首次构建后不再出现连续的 `codex.exe changed` 重建,Tauri 窗口稳定打开;再完成 direct Codex 普通对话与项目修改的客户端验收。 - -## 7.3 首页自动创建项目与项目内对话收口(2026-08-20) - -### 收口契约 - -1. 首页保留单一“陶泥儿”创作输入口,并恢复“做游戏 / 做素材 / 做方案”三个创作类型,默认为“做游戏”。这三项只是用户显式选择的创作方向,不是 Agent Runtime 模式、Provider 选择或旧 Supervisor 路由;首页仍不渲染用户或助手消息气泡。 -2. 每次提交非空正文或附件时,客户端对且只对本次提交调用一次 `create_automatic_local_game_project`,在系统文档目录的 `Genarrative GameAgent/` 下分配唯一 `gameagent-*` 工作区;不弹目录选择器,也不复用最近项目。 -3. 工作区初始化后先把附件导入该项目,再立即进入项目开发工作台;用户原始正文作为 `initialPrompt` 原样交给 project-bound direct Codex thread,选中的 `creationType=game|art|doc` 作为独立结构化首轮上下文传入。客户端不得把类型改写为“初始意图”文本、不得把它拼进用户消息,也不得据此切换 Runtime。意图理解、是否修改工程以及后续验收均由项目内同一 Codex 自主完成,首页不运行 projectless Codex 对话。 -4. 项目工作台产品文案统一使用“陶泥儿”“智能创作”,不显示“项目总控”“自动执行”“Supervisor”或“专业 Agent”。客户端只做项目创建、附件导入和确定性投影,不恢复旧多 Agent Runtime。 -5. 首页的创建状态只显示在主输入区;“最近项目”使用独立静态说明,不能复用“正在创建工作区 / 正在回复 / 已回复”等全局状态。 - -### 验收合同 - -- 三个创作类型必须在桌面与窄视口下可见、可键盘操作并具有明确的选中态;切换类型同步更新输入占位与空输入提示,一次创建收口后恢复默认“做游戏”。 -- 普通文本、三类创作需求和带附件需求都必须先创建项目,再在 `陶泥儿项目对话` 中出现同一条原始用户消息与 Codex 回复;首轮 direct command 必须同时携带原样 `prompt` 和受限 `creationType`,`chat_with_game_creator_home_direct_codex` 不得暴露为首页 Tauri handler。 -- 连续点击或连续 Enter 只能创建一个工作区;创建进行中按钮禁用,但编辑器不得生成首页聊天气泡。 -- 附件必须经 `upload_local_asset` 写入新项目后再交给项目 Codex;不得只把附件元数据留在首页,也不得把浏览器本地路径写入聊天正文。 - -## 7.4 真实项目验收发现的 Codex 原生组件闭包(2026-08-20) - -- 真实创建项目时,Codex 0.147.0 能启动 app-server,但首轮文件修改明确失败为缺少 `codex-code-mode-host.exe`;项目只有初始化占位页,未生成游戏。 -- 根因是旧 staging 只复制 `bin/codex.exe`,没有保留同版本 npm 原生包依赖的 code-mode host、`rg`、command runner、sandbox setup 和 `codex-package.json` 相对布局。 -- Windows x64 内置资源现按固定白名单 stage 完整原生组件闭包;清单升级为 `genarrative-codex-sidecar.v2`,逐文件记录并校验 SHA-256,Tauri resources 保持 `bin/`、`codex-path/`、`codex-resources/` 布局。资源映射只属于 `tauri.windows.conf.json`,通用配置不得让其他平台在 Tauri build script 阶段校验 Windows 专属文件。API Key、登录状态和用户配置仍不进入安装包。 -- 同次真实验收还发现 direct 项目页的可访问名称残留“项目总控”;视觉文案虽已是“陶泥儿”,读屏仍会暴露旧产品模型。direct 分支现统一使用“陶泥儿项目对话 / 陶泥儿消息 / 陶泥儿实时回复 / 陶泥儿对话内容”,旧名称只保留给显式 legacy 诊断入口。 -- 修复后同一客户端已真实写入 `game/index.html`、`game/style.css`、`game/game.js`。客户端必须继续把这次真实文件变化确定性登记为游戏代码和项目版本;该步骤不启动 Supervisor、harness、平台美术或二次 LLM。 -- direct 产品入口的显式“播放”只做用户授权、本地路径/权限边界和预览服务器启动,不再先执行旧 `game.static_smoke` 的 Canvas-only 形态合同;DOM、Canvas、WebGL 及外链 `game.js` 均可进入客户端运行视图。显式 legacy `/smoke` 与旧诊断入口仍保留原严格检查,不能冒充真实浏览器试玩。 - -## 8. 陶泥儿美术闭环与资源分类收口(2026-08-16) - -### 问题 - -- 直连入口此前仅根据用户输入中的少量“游戏 + 创建”关键词决定是否调用陶泥儿生图;“做个三消模拟经营”等正常创作输入会绕过该判断,导致只有 HTML / CSS / JS 的项目仍被投影为已完成。 -- Codex app-server 没有陶泥儿平台的生图工具;单靠泛化系统提示词无法让它自行调用平台生成、下载、登记并回写美术资源。 -- 资源画布把 `text/html`、`text/css` 和 `text/javascript` 统一归为“文档”,混淆了玩法说明与可执行游戏代码。 - -### 现行契约 - -1. 直连 AGC 项目首次生成、或当前项目还没有已登记陶泥儿美术时,客户端按标准三阶段优先调用陶泥儿平台:先生成统一规范图 `assets/art-spec.png`,再以该规范图为参考生成 16:9 场景背景图 `assets/direct-game-background.png`,最后以同一规范图生成透明主图集 `assets/art-spritesheet.png`。`sliceLayout=grid-2x2` 与四份受合同保护切片继续作为标准美术包的推荐路径;不得把客户端猜测裁剪或自由连通域结果冒充平台切片。平台返回的主图片必须以 `source.kind=canvas` 登记,资源身份、图片可解码性和同 Canvas 项目关系继续失败关闭;图集源图可信可用但透明化或切片后处理缺失时,按第 13 节安全复用源图并继续同一 Codex thread,不因固定切片缺失终止整个游戏。 -2. 客户端把实际可用的规范图、背景图、主图集与切片相对路径、来源和用途作为不可变执行上下文提供给唯一 Codex。规范图作为风格根,其余平台素材应进入核心可玩画面;Codex 可以根据游戏结构选择合理的图集、切片、Canvas 或 WebGL 组织方式,不要求固定文件组合、固定 `drawImage` 次数或单一代码形态。平台素材不能只在回复中声明使用或只显示为旁侧缩略图,核心视觉也不能退化为 emoji、纯 CSS 或纯色占位图。 -3. 回合结束时客户端只确定性复核安全与最低来源边界:可信平台图片、身份与同 Canvas 关系成立,`game/index.html` 存在,游戏源码至少引用一份已登记陶泥儿图片。随后由受限 Chromium 对 desktop/mobile 做真实运行、截图、异常、交互及 Canvas/WebGL 图片渲染观察,并把缺口回灌同一 Codex thread 有界整改。固定四切片、固定文件名和固定 `drawImage` 次数不再阻断完成;最终仍未观察到平台素材进入任一视口核心渲染时才拒绝登记版本。详细契约以第 13 节为准。 -4. 资源画布增加“游戏代码”分区。HTML、CSS、JavaScript 和其它可执行源码进入该分区;玩法说明、配置和 Agent 文本回执仍归“文档”。已有资源布局若没有代码分区位置,将由现有布局 reconcile 自动补位。 -5. 产品界面只展示“陶泥儿”“智能创作”等产品术语;Codex app-server 仅保留为内部执行实现和开发诊断名称,不在普通项目聊天、首页创建状态或设置说明中直接暴露。 -6. 项目与首页 direct 系统提示词必须把对外产品身份固定为“陶泥儿”。询问身份、名称或能力时以陶泥儿自称,不把 Codex、ChatGPT、OpenAI、模型或通用 AI 助手当作名称;只有用户明确询问底层实现时才可说明内部使用 Codex app-server,并继续保持陶泥儿这一对外身份。direct 缺失 system message 时使用同一陶泥儿兜底,legacy ToolHost 的内部 Codex 技术提示保持独立。 -7. 每次直连回合在游戏代码复核与登记成功后,必须在项目写锁内推进一次 durable project revision,并以该 revision 创建首个 `initial-*` 或后续 `agent-*` 正式版本。禁止修改 manifest 后沿用旧 revision;外层工作台会把同 revision 的不同 manifest 判为冲突并拒绝投影,表现为磁盘已有游戏代码和版本、客户端仍显示 0 项。 -8. direct app-server 禁用 shell / unified exec 时仍必须能可靠修改已有游戏。每轮系统提示词在大段仓库文档之前注入当前 `game/index.html`、`game/style.css`、`game/game.js` 的有界脱敏快照,使 Codex 的原生 file-change 能基于真实旧内容生成补丁;不得退化为猜测变量名的盲补丁。回合前后以三个代码文件的内容指纹判断是否发生真实修改;无修改且 manifest 已同步的回合不得推进 revision 或伪造新项目版本。 - -### 验收 - -- Rust 单测覆盖:可信完整图集缺少固定切片仍可进入 Codex;只有规范图和背景图但历史图集不可安全恢复时不得重复发起付费生成;缺可信平台图片、来源身份不成立、PNG 不可解码或源码完全没有平台素材引用时继续拒绝完成。浏览器证据测试必须区分旁侧 `` 与 Canvas/WebGL 实际渲染,并证明 desktop/mobile 任一视口缺少核心素材观察都会回灌同 thread 整改。 -- 身份合同测试覆盖项目 prompt、首页 prompt 与 direct 缺省 baseInstructions 均以陶泥儿为对外身份,同时证明 legacy ToolHost 的内部 Codex fallback 未被改写。客户端完整重启后,用同一项目分别询问“你是谁”和“你是不是 Codex”,回复必须以陶泥儿自称;仅在第二问可补充底层执行技术。 -- 资源投影与 AppSurface 测试覆盖:`game/index.html`、`game/style.css`、`game/game.js` 显示于“游戏代码”,不再显示于“文档”。 -- 连续两次直连回合必须保留同一批游戏代码资产 ID,project revision 单调推进,并形成 `initial-* -> agent-*` 的父子版本链;外层资源管理在新 revision 到达后显示游戏代码和项目版本,不能停留在生成前快照。 -- 已有项目修改测试必须证明系统提示词包含有界当前游戏源码、敏感行被过滤,基于该上下文的 file-change 可以命中;Codex 明确未修改文件时,revision 与版本数量保持不变。 -- 真实客户端验收必须在新建空项目中看到实际成功生成或安全恢复的 `source.kind=canvas` PNG 位于“美术资源”,代码文件位于“游戏代码”,并在 desktop/mobile 运行画面的核心 Canvas/WebGL 路径中观察到至少一份已登记陶泥儿素材;标准四切片存在时应优先使用,但不存在时不能伪造,也不能据此单独判定游戏失败。 - -## 9. 直连创作阶段反馈与资源首屏预览(2026-08-17) - -### 问题 - -- 直连回合把陶泥儿美术生成、Codex 文件修改、manifest/版本登记放在一个 Tauri command 内。前端只能在 command resolve 后得到最终回复,用户会在数分钟内只看到笼统等待状态,随后突然出现运行画面。 -- 资源卡原本主要等待嵌套资源画布的 `IntersectionObserver` 通知。该嵌套滚动容器在首次进入时不稳定,失败后的可重试读取又不会因可见性回调自动重试,导致用户必须先进入详情才能看到卡片预览。 - -### 现行契约 - -1. direct Runtime 在不输出内部路径、Provider 或工具细节的前提下,复用 `game-creator-agent-progress` 发送安全的公开阶段:需求已接收、检查陶泥儿美术包、规范图、背景图、图集与切片、代码生成、项目版本登记和预览刷新。普通直连工作台按当前项目路径接收并即时显示该阶段;命令失败仍沿用现有安全错误映射,不把阶段进度伪装成已完成。 -2. 资源管理首次进入时主动请求最多 12 个可预览的非音频、非版本、非占位资源。请求仍服从三并发、96 项队列、48 项/64 MiB 缓存和原有身份失效规则;后续资源继续通过 `IntersectionObserver` 按滚动加载,详情与播放请求可提升优先级。首屏预取不改变权限策略,读取被拒绝时卡片必须保留安全错误状态。 -3. 验收必须同时证明:提交直连需求后立即可见“已提交需求,正在准备智能创作”,收到阶段事件后显示对应用户文案;真实普通 AGC 工作台首次打开既有项目时,无需进入详情即可显示游戏代码摘要以及陶泥儿规范图、场景背景图和核心图集的缩略图。 - -## 10. 平台已完成图集结果回收修复(2026-08-17) - -### 现场证据 - -- 空项目的规范图与场景背景图已通过当前平台登录态生成、登记;核心 `grid-2x2` 图集任务在平台侧进入完成态后,客户端显示“美术包生成失败”。 -- 失败文本表明客户端收到了 `completed`,却没有拿到可消费的 `result`。这不是未登录、未配置平台生图或背景图失败,也不能通过重新提交图集来处理,否则会造成重复扣点。 - -### 修复计划 - -1. 核对平台账号模式的 `/api/runtime/external-generation/jobs/{operationId}` 完成响应、通用外部 API 完成响应和持久化 `result_payload_json` 的真实包络;统一把完成结果映射为客户端可消费的 `result`,保持 `grid-2x2`、四类切片、资源和资产身份合同不变。 -2. 对已进入 `accepted/running/completed` 的本地图集账本只轮询并恢复同一个远端任务;仅 `prepared` 且未取得接受凭证时才以原幂等键重放。任何“结果暂不可读”都保留账本并进入可恢复状态,不发起新的付费请求。 -3. 后端增加 completed 队列结果的契约测试;原生端增加平台 completed 包络的回收、四切片严格验收和不重提回归;前端继续将内部错误转换为安全、可行动的中文提示。 -4. 先对现有失败项目执行同一任务的状态恢复,确认不会产生新的生成提交;再用当前客户端新建项目跑完整规范图、背景图、图集、四切片、代码、版本与预览闭环。真实验收未通过前,不把本次修复标记为完成。 - -## 11. 直连聊天记录持久化(2026-08-17) - -### 问题 - -- 普通直连创作会把用户输入、最终回复和失败提示都标记为运行时消息;项目对话保存器此前统一跳过这类消息。 -- 项目重新打开时已经会读取 `.agent/conversations/project.jsonl`,但直连问答从未写入该文件,因此客户端重启后只剩默认欢迎语。 - -### 现行契约 - -1. 每次直连提交生成一个仅用于项目对话的稳定回合标识,并把最终用户消息与最终助手消息分别写为 `direct-codex::user`、`direct-codex::assistant`。保存命令继续以 `messageId` 幂等,重试不得产生重复记录。 -2. 仅上述 role 与 ID 匹配的最终直连问答可以穿过运行时消息过滤并写入项目主对话;阶段进度、预览启动状态、流式中间内容及无稳定回合 ID 的运行时提示仍只保留在当前页面。 -3. 直连失败时,只保存已通过 `projectRuntimeVisibleError(...)` 转换的安全中文提示,禁止把 app-server、Provider、路径、认证或工具原始错误写入对话文件。 -4. 项目重新打开时继续复用既有主对话读取与 hydration。恢复聊天记录不代表 Codex app-server 的进程内 thread 能跨客户端恢复;下一条消息仍按现有直连会话策略发起。 - -### 验收 - -- AppSurface 覆盖成功与失败回合:用户消息和最终回复各保存一次、共享同一 turn 的不同 role ID;失败记录不含原始内部错误。 -- 重载同一项目时,`read_local_conversation` 返回已保存记录,聊天区恢复展示,不再次提交直连请求。 -- 真实桌面端验收:在同一项目完成一条直连问答,关闭并重新打开当前客户端后,用户输入和最终可见回复仍在项目聊天中。 - -### 并发写入约束 - -直连消息保存与首轮陶泥儿平台美术生成可能同时触发项目写锁。两者均为短时本地写入,直连美术生成的恢复锁、提交锁以及生成产物版本登记必须使用现有的有界等待锁;不能因为聊天记录保存占用项目锁的瞬时竞态而终止整轮游戏生成。 - -## 12. 顶部播放入口(2026-08-17) - -### 产品边界 - -1. 项目工作台顶部提供唯一面向普通用户的“播放”按钮;运行空态不再引导用户输入 `/run` 或 `/preview`。 -2. 播放按钮只负责进入运行视图并排入现有 `game.run_local` 确认流程,不新增一套预览启动实现,也不直接拼接或打开外部 URL。 -3. 现有聊天命令解析暂时保留为兼容入口和回归测试依据,但不再作为工作台产品引导。 - -### 运行合同 - -- 点击播放后仍需经过项目权限确认。 -- 确认后继续执行 `game.static_smoke`、`start_local_game_preview`、预览状态同步、manifest / run trace 刷新和 loopback iframe 安全校验。 -- 没有可运行原型时按钮禁用;运行视图仍由现有 `runAvailable` 判定控制。 - -### 验收 - -- 可运行项目的工作台顶部显示“播放”,点击后进入运行视图并排入 `game.run_local`。 -- 没有可运行原型时“播放”禁用。 -- 运行空态文案只提示点击顶部播放按钮,不出现 `/run` 或 `/preview`。 - -## 13. 直连 Codex 的 LLM 自主试玩验收与柔性美术合同(2026-08-17) - -### 13.1 分层边界 - -直连 Runtime 只把安全、权限、来源和不可逆副作用留在确定性门禁内:项目工作区与权限边界、凭据隔离、平台生成请求的幂等账本与未知结果恢复、持久文件事务、HTTP 完成包基本结构、图片下载/PNG 解码/可见像素、`source.kind=canvas`、资源身份与同 Canvas 项目关系。上述条件不满足时必须失败关闭,不能交给模型猜测或覆盖。 - -`grid-2x2`、固定四张切片、固定切片文件名、固定 `drawImage` 次数以及某一种 Canvas 代码形态不再是所有游戏的完成阻断合同。它们保留为“陶泥儿标准美术包”的推荐路径:平台返回完整透明主图集但切片后处理缺失时,仍可继续代码生成;已有切片可以被 Codex 优先使用,但客户端不得伪造切片或把缺失切片标记为已存在。若项目已有同一画布、身份可信且可解码的规范图和背景图,但历史核心图集无法恢复,客户端必须直接复用这两张素材继续 Codex 代码生成与试玩,不重新发起图集付费生成,也不为只读恢复失败阻断本轮。只有已用平台图片本身无法下载、解码、无可见像素、来源身份不可信或最终没有任何真实平台素材引用时才阻断。 - -### 13.2 同一 Codex thread 的有界自主验收 - -每个直连回合按以下最多三次 Codex turn 执行,不恢复 Supervisor、专业 Agent 或 harness: - -1. 首轮由 Codex 生成或修改当前工作区文件。 -2. 客户端先复核最低完成证明:`game/index.html` 是否存在,以及源码是否引用至少一个已登记的平台图片。该证明不满足时,不在版本登记阶段直接报错;客户端把脱敏的具体缺口回灌给同一 Codex thread,待其修复后才启动受限本地预览。该回灌不允许 Codex 修改 manifest、伪造素材或覆盖来源身份。 -3. 最低证明满足后,客户端启动受限本地预览,使用真实 Chromium 在 desktop 和 mobile 两个固定视口采集页面加载、Canvas、控制台/异常、失败请求、可见文本、截图和有限的真实交互探针;direct 链路不使用 `BrowserPlaytestScenario::GenericV1` 等固定玩法状态机,试玩结果只作为模型判断证据。 -4. 客户端把脱敏、结构化的浏览器证据及仍存在的最低完成证明缺口发送给同一 Codex thread。Codex 必须读取实际文件和证据,发现问题就直接修改并说明修复;若文件发生变化,客户端重新试玩。最新结果仍失败时最多再发送一次明确整改反馈,之后安全失败,不登记完成版本。 - -最终回复必须包含:检查过的文件、真实启动/试玩动作、desktop/mobile 观察、陶泥儿平台素材如何被实际使用、已修复问题和剩余风险。客户端只展示摘要,不把绝对路径、Token、签名 URL、Provider 原文或内部队列信息传给用户。 - -### 13.3 最低使用证明与完成条件 - -客户端只要求 `game/index.html` 存在,并能证明至少一个已登记、真实、平台来源的图片路径被游戏源码引用;不统计 `drawImage` 次数,不要求四类切片或固定代码形态。该最低证明失败必须先进入同 thread 有界整改,而不是在浏览器成功后才由版本登记阶段突然终止;若最终仍失败,才拒绝登记。 - -受限 Chromium 还会对已登记平台图片采集运行时使用观察:图片是否在真实 Canvas / WebGL 渲染调用中出现,以及是否只作为页面可见图片出现。该观察不依赖固定切片、固定文件名、特定棋盘结构或字符串计数,也不替代 Codex 对截图和玩法质量的判断;但若只观察到旁侧预览、未观察到核心渲染路径,客户端必须把这一明确缺口回灌给同一 Codex thread 要求整改,不能把“源码引用”或“旁侧缩略图”表述为素材已进入玩法。浏览器基础设施失败、页面无法加载、Canvas 完全不可见或出现未处理异常仍作为安全失败证据;其它质量问题交给同 thread 有界整改。 - -### 13.4 验收要求 - -- 定向 Rust 测试覆盖:完整主图集无切片可通过;来源/身份/PNG 解码/同 Canvas 约束仍失败关闭;源码合理引用任一平台素材可登记;无平台素材引用不能完成;系统提示词包含自主试玩与结构化报告要求。 -- fake app-server 测试覆盖:连续 direct turn 复用同一 thread,浏览器证据和整改反馈形成后续 `turn/start`,无 Supervisor/child/harness。 -- 真实客户端验收覆盖:当前 checkout 的 AGC 新建或打开直连项目,真实本地预览在 desktop/mobile 运行并至少执行一次可见交互;截图与结构化证据写入项目 `.agent/runtime` 证据目录;完成回复展示可读验收摘要。 - -### 13.5 透明后处理失败时的图集源图安全复用(2026-08-18) - -当陶泥儿 `art-spritesheet` 的远端生成已完成、源 PNG 已落在同一画布,但透明化或切片后处理失败时,直连 Runtime 可以在不重新提交、不重复扣费的前提下只读恢复该源图。恢复仅适用于规范图唯一绑定的核心图集:候选必须属于当前 Canvas、生成路由和种类匹配,且要么 `sourceResourceId` 精确指向当前规范图,要么只包含当前规范图的一项不可变参考。多个候选、外部参考、多参考、不可下载、非 PNG、透明或无可见像素一律失败关闭。 - -恢复成功后将完整图集作为可信平台素材继续交给同一 Codex thread;客户端不得伪造切片、不得把未生成的切片登记为存在。源图已确认由平台完成且只读恢复成功后,客户端清理同一 `agentId/runId` 的已完成生成账本;只读恢复失败、身份不唯一或结果仍未知时继续保留账本供对账,绝不删除后重发。若没有可安全恢复的历史图集、但规范图和背景图已经可信可用,直连生成可继续使用这两张素材并完成上述 LLM 自主验收,不再为只读恢复失败重发图集请求。 - -### 13.6 隔离验收进程的陶泥儿开发者凭据(2026-08-17) - -真实 CLI / Chromium 验收进程不能依赖已打开 GUI 的内存登录态,也不能复制 GUI 的 Cookie、access token 或 Runner 会话。直连 Runtime 首先只读取当前用户私有的 `~/.config/genarrative/external-editor-api.json`:其中保存一次性显示过的开发者 API Key,和可选的受信任陶泥儿 API origin;仓库、项目目录、`game-creator.config.json`、诊断、命令行参数和 Codex 系统提示词均不得出现该 Key。 - -当私有 Key 缺失但当前 GUI 已有陶泥儿账号会话时,客户端可按用户授权仅调用受保护的 `/api/profile/api-keys` 创建一个名称固定的本机直连 Key,并以原子写入和当前用户私有权限保存到上述文件。创建后,direct Runtime 的美术准备、只读图集恢复、素材换签、生成提交和轮询统一使用 External v1 路由及该 Key;不得混用账号 JWT 路由。若 Key 缺失且没有 GUI 会话,必须给出“先在客户端登录一次以创建本机开发者 Key”的可行动错误,而不是误报普通试玩失败。 - -开发者 Key 创建是唯一允许借用 GUI 登录态的受控设置动作;平台图像生成继续由既有幂等账本、同一 idempotency key 和未知结果恢复保护。真实验收必须至少用一个不带 GUI 内存登录态的新进程恢复同一项目,以证明该私钥链路可独立生成、下载并完成 Chromium desktop/mobile 试玩。 - -### 13.7 首次私钥引导的本机安全存储前置与可行动失败说明(2026-08-17) - -首次真实客户端验收表明,失败不是 GUI 登录态未同步:首次本机开发者凭据创建已经拿到远端响应,但 Windows 新建的私有目录 owner 是 `Administrators`,随后 TokenUser 私有 DACL 校验拒绝落盘。一次性显示的远端凭据无法恢复,旧顺序会留下孤儿凭据,因此不能用刷新登录态或自动重放掩盖。 - -1. 缺失本机开发者凭据时,客户端必须先准备并验证精确的私有存储目录,再请求远端创建凭据。仅当该精确目录由当前调用以原子创建成功时,才允许初始化 owner 为当前 TokenUser;已有目录必须先严格核对 owner,owner 匹配当前 TokenUser 时由客户端自动收紧为禁止继承且仅当前用户 Full Control,owner 不匹配时仍失败关闭,不自动接管、改 ACL、覆盖或删除。 -2. 若本机目录预检失败,客户端返回稳定的“本机开发者凭据存储目录未安全初始化;未创建远端凭据”分类,不请求远端创建接口、不发起美术生成、不写 operation 或账本,也不刷新登录态或自动重试。 -3. 远端响应后原子写入仍可能因并发或磁盘故障失败;该极窄路径必须单独分类为“凭据已创建但未能安全保存”,提示用户在账户开发者凭据页面撤销后再试,不能自动创建第二把凭据。诊断和正式 UI 只展示上述安全摘要与恢复建议,不包含 access token、开发者凭据、响应正文、绝对路径或签名 URL。 -4. 验收先在当前失败项目上恢复:对遗留的空且 owner 不匹配目录做可恢复隔离后,再复用同一项目发送“继续完成此前三消游戏”。成功标准包括本机私钥存在但不读取其内容、平台素材与版本登记完成、desktop/mobile Chromium 试玩证据和隔离进程恢复;此前已创建但无法恢复的远端孤儿凭据作为明确剩余风险,绝不自动撤销。 - -## 14. 审核 AGC Skill Pack、按需加载与真实工具内核(2026-08-20) - -### 14.1 目标架构 - -普通项目链路固定为 `薄 Runtime + Codex 唯一执行 + 按需 Skill + 真实工具`。Runtime 不再通过关键词、固定步骤或产物字符串计数替 Codex 判断用户意图,也不恢复 Supervisor、专业 Agent 或 harness;它只负责工作区、凭据、不可逆副作用、进程协议和确定性客户端投影。 - -系统提示词只保留最小核心约束、当前项目文件的有界快照和一份审核 Skill 索引。不得再把项目中的 `.codex/skills`、`.agents/skills`、`.hermes/skills` 全文批量拼入 64 KiB 提示词,也不得把主站全部 Skill 复制给普通游戏项目。完整 `SKILL.md` 与直接引用文件由 Codex 原生 Skill 机制在命中意图后按需读取。 - -### 14.2 审核索引与五类 Skill - -客户端内置 `agc-skill-pack.v1` 清单。每项只公开名称、用途、触发条件、所需工具、版本和内容 SHA-256;审核文本统一按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免编辑器产生的混合换行让同一 Git 内容在 Windows 与 Linux 上得到不同结果。审核文件的语义内容变化时必须在同次变更重算对应指纹并提升版本。启动时逐文件复核清单和编译进客户端的内容,任何缺失、额外文件、路径越界、非 UTF-8 内容或规范化后的指纹不匹配都失败关闭;路径边界显式拒绝反斜杠、Windows 盘符、UNC、绝对路径和 `..`,不能因测试运行在 Linux 就把 Windows 绝对路径当作普通相对文件名。审核包只包含: - -1. `agc-project-structure`:项目根、`game/`、`assets/`、`.agent/` 的职责和禁止创建平行项目的约束。 -2. `taonier-art-assets`:陶泥儿标准美术包、平台来源、警告语义和真实素材使用;`grid-2x2` 与四切片只是推荐路径,不是所有游戏的完成门。 -3. `agc-web-game-development`:根据当前需求自由选择 DOM、Canvas 或 WebGL,并完成可玩的 HTML/CSS/JavaScript 实现。 -4. `agc-browser-playtest`:调用客户端提供的真实双视口浏览器工具,读取截图、控制台、网络、Canvas/WebGL 和交互证据后自行修复。 -5. `agc-client-projection`:解释客户端如何按磁盘事实投影代码、素材、revision 和版本;Codex 不直接伪造或改写 manifest 中的平台身份。 - -`genarrative-external-editor-api` 的异步、凭据、operation 和 warning 语义经审核后融入 `taonier-art-assets`;不把原始主站技能目录直接暴露给游戏项目。`gpt-image-2-apimart` 只有在对应受控工具真正配置时才能作为显式备用能力,首版不以文字假装可用。`genarrative-play-type-integration`、SpacetimeDB、微信支付和其它主站工程 Skill 明确排除。 - -### 14.3 渐进加载实现 - -DirectProject app-server 启动前,把上述审核包安装到本次隔离 HOME 的 `.agents/skills/`;DirectHome 不安装项目创作 Skill,也不暴露项目工具。Codex 首轮只得到五项元数据和索引,不得到完整正文;触发后由原生 Skill 读取对应 `SKILL.md`,引用最多一层且只能命中清单文件。项目内任意 Skill 不再由 AGC 提示词构建器主动读取或拼接。 - -Skill 包版本与内容指纹参与 DirectProject app-server 连接池身份。客户端升级或 Skill 内容变化后必须建立新进程/新 thread,不能复用旧目录中的过期 Skill;同一版本的连续聊天仍复用同一 Codex thread。 - -### 14.4 真实工具与安全边界 - -DirectProject 仅配置客户端自身的本地 stdio MCP,首版暴露三个受控工具: - -- `agc_read_skill_resource`:只读取审核清单中某个 Skill 直接声明的一层 `references/*.md`;不接受绝对路径、`..`、未声明文件、主站 Skill、项目文件或宿主文件。它补足禁用通用 shell 后的渐进引用读取能力,不扩大工作区权限。 -- `taonier_prepare_game_art`:按 Codex 提供的游戏 brief 创建或恢复陶泥儿标准美术包。工具内部继续使用当前 External v1 请求、持久生成账本、稳定幂等键和 `operationId`;未知提交只轮询或以原请求/原 key 恢复,绝不因模型重试重新扣费。完整可信图集缺切片时返回 warning 并保留完整图集,不能伪造切片或阻断后续代码实现。 -- `agc_browser_playtest`:由当前客户端启动 loopback 预览和受限 Chromium,对 desktop/mobile 采集真实截图、页面状态、控制台异常、失败请求、Canvas/WebGL 图片使用与有限交互探针,并把结构化证据和截图作为工具结果返回 Codex。该工具不使用旧固定玩法 harness。 - -MCP 子进程复用当前客户端二进制的专用无窗口模式,从工作目录取得唯一项目根;命令行不传项目路径或凭据。它只处理 MCP 和审核引用读取;真实浏览器与付费美术通过随机 loopback 地址回到持有项目上下文的客户端主进程执行,避免 Codex 隔离用户环境阻断 Chrome,也避免把 GUI 登录态复制给子进程。陶泥儿开发者 Key 只由客户端主进程按受信任 origin 从当前用户私有文件读取并在内存中使用,不进入 Codex 环境变量、系统提示词、argv、项目文件、日志或工具结果。凭据缺失时工具返回可行动的“先在客户端登录并准备本机开发者 Key”,不得假装生成成功。 - -DirectHome 继续禁用 MCP、命令和写入。DirectProject 仍禁用通用 shell、任意网络和多 Agent;文件修改只走 Codex 受限原生能力,外部副作用只走上述本地工具。付费生成、路径权限、文件事务、图片下载/解码、来源身份和客户端投影继续由确定性代码守住。 - -### 14.5 验收合同 - -- Rust 单测:清单五项精确、SHA-256 匹配、路径无越界;新项目没有本地 Skill 目录仍能安装审核包;DirectHome 不安装;项目中的主站/SpacetimeDB/支付 Skill 不进入系统提示词。 -- 提示词测试:普通问候只包含索引,不包含任一完整 Skill 正文;美术 Skill 正文由 Codex 原生触发读取;API Key、Bearer、auth.json、宿主绝对路径不进入上下文。 -- fake app-server:DirectProject 配置本地 MCP 且 DirectHome 保持 `mcp_servers={}`;连续回合复用 thread;MCP item 可完成而不是被当成协议违规;无 Supervisor/child/harness。 -- MCP 协议测试:initialize、tools/list、tools/call 均为有界 JSON-RPC;未知工具、路径越界、缺凭据明确失败;美术调用复用同一账本/operation,不重复提交;浏览器调用返回双视口真实报告和截图内容。 -- 回归:typecheck、AppSurface、Rust 定向与完整串行测试、编码检查、rustfmt 和 diff check 全部通过。 -- 真实客户端:从当前 checkout 新建项目,由同一项目 Codex thread 自主选择陶泥儿美术 Skill、调用真实平台工具、写入游戏、调用真实浏览器试玩并按证据修复;客户端最终显示平台美术、游戏代码和项目版本。单独验证“你好”“今天多少号”不调用美术或浏览器工具、不改文件、不登记版本。 - -### 14.6 当前实施与验收状态(2026-08-20) - -- 五项审核 Skill 已由版本化清单和逐 Skill SHA-256 编译进客户端;DirectProject 初始化后显式调用 `skills/extraRoots/set` 与 `skills/list`,缺项或解析错误直接失败。DirectHome 不安装该包。项目内 `.codex/.agents/.hermes` Skill 正文不再被系统提示词批量拼接。 -- 本地 `agc_tools` MCP 已实际暴露 `agc_read_skill_resource / taonier_prepare_game_art / agc_browser_playtest` 三项工具并固定自动审批;引用读取严格限制为清单内一层 Markdown。真实 `gpt-5.6-sol max` 回合已读取 `agc-project-structure` 的直接引用并正确返回路径边界。 -- 浏览器和美术副作用由随机 loopback 工具桥回到客户端主进程;真实 Codex 工具调用已得到 desktop/mobile `readyState=complete`、整体 `passed=true` 与 2 张截图。普通“你好,今天多少号”真实回合只回答日期,游戏文件、manifest、revision 均未变化。 -- 开发网关会在 API Key Responses 成功响应中附带 `X-Codex-*` ChatGPT 额度头;隔离 app-server 会把它误判为余额 0。Direct conversation 现经只接受 Bearer `/responses` 的 loopback 流式代理转发,并剥离该组账户头;真实回合从 `usage-limit-exceeded` 恢复为完成。旧 ToolHost 不经过此代理。 -- 2026-08-21 真实客户端复跑已由当前登录会话为所选服务端建立新的私有开发者 Key;旧失效文件只改名保留,不读取、不打印也不提交。Codex 经 `taonier_prepare_game_art` 成功生成并登记 `assets/art-spec.png`、`assets/direct-game-background.png` 与 `assets/art-spritesheet.png`,三项均带平台 Canvas 来源身份。首次回合中第三个 `art-spritesheet` operation 已以稳定幂等键受理;重启客户端后只恢复该 operation,随后再次调用完整美术包时仍只有同一账本和 operation,三个 PNG 时间戳不变、账户泥点不再下降,工具两次均返回 `status=completed`、3 个 `assetPaths`、3 张图片且无 warning。 -- 同一真实项目已由 Codex 把平台背景、规范图棋子和核心图集实际接入 `game/index.html / style.css / game.js`。真实 Chromium 报告 `passed=true`:desktop/mobile 均为 `readyState=complete`、Canvas 非空、无 console error 与 exception;desktop 仅有非致命 `favicon.ico` 404。两张截图确认桌面和手机均完整显示甜点星球三消画面,且结构化运行时证据观察到平台图片进入渲染。 -- 真实复跑同时暴露并修复两个收尾缺陷:DirectProject 不能沿用普通 LLM 的 180 秒整回合超时,现改为 15 分钟基础空闲窗口、MCP 工具活动期 110 分钟空闲窗口、整个 turn 120 分钟硬上限;DirectHome 与旧 ToolHost 继续保持原超时。系统提示词和浏览器整改回灌同时明确 shell/unified_exec 被安全禁用时应使用已注入的游戏文件快照与结构化证据,不得误报“没有读取工具所以无法验收”,也不得要求 Codex 直接保存 `.agent` 版本。定向回归为 Direct Runtime 35/35、Codex app-server 23/23(另 1 项真实账号测试按设计 ignored)。 -- 最后一轮改后 GUI 复验在桌面控制被物理 Escape 中止后未继续自动操作;非 UI CLI 又因不继承 GUI 登录态而得到 `usage-limit-exceeded`。因此本节只把已落盘的真实生图、幂等复用和双视口浏览器证据记为已完成,不把改后最终聊天回复或新增项目版本伪报为已验收;下次从当前客户端发送普通项目消息即可复核新的等待窗口与证据回灌文案。 - -## 15. Direct Interaction Event v1 合同(2026-08-22) - -### 15.1 现役缺口与目标 - -现役 direct 链路虽然在 app-server 内部能接收消息增量,但普通项目聊天仍主要等待 Tauri command 完整返回后才展示助手正文;旧 `game-creator-agent-progress` 只能表达少量阶段,不能作为 direct 回合的正文增量、顺序、终态和隔离合同。本次新增 Direct Interaction Event v1,让用户在终态返回前看到安全活动状态和已产生的用户可见回复,不恢复 Supervisor 或引入第二个 Runtime 真相源。 - -### 15.2 事件与字段 - -Tauri 事件名固定为 `game-creator-direct-turn-update`,payload 只包含以下字段: - -- `projectPath`:发起回合的项目键,只用于本地路由与隔离,不渲染到用户文案。 -- `turnId`:本次 direct 提交的稳定回合标识,与项目键共同定位唯一的临时回复。 -- `sequence`:回合内严格递增的非负整数,用于拒绝重复、迟到和乱序回退。 -- `status`:只允许 `accepted | running | streaming | finalizing | completed | failed`。 -- `activity`:只允许 `request-accepted | understanding | project-inspection | file-change | controlled-tool | validation | response-finalization | none` 这些安全类别;它是粗粒度活动标识,不是工具日志。 -- `accumulatedText`:截至当前序号的完整助手可见正文,前端原位替换临时回复,不将其追加为多条消息。 -- `updatedAt`:事件产生时间,只用于展示和诊断,不参与顺序判定。 - -`activity` 及其对应的展示文案不得泄漏模型 reasoning、工具原始参数、内部路径、Provider、认证信息或未脱敏错误。`accumulatedText` 只能来自助手面向用户的正文增量,不得混入 reasoning、tool call/item、raw arguments、stderr 或内部诊断。 - -app-server 的 `turn/plan/updated`、reasoning summary、MCP progress、文件 patch/output、命令 output 和验证类通知只能按通知方法名映射为上述固定 `activity`,不得把通知 params 传入 observer。连续同类高频活动应在进入 turn channel 前有界合并;该合并不得影响 `AgentMessageDelta` 正文和 terminal 终态。 - -### 15.3 生命周期与前端门禁 - -1. 每次 direct 提交必须先建立 `projectPath + turnId` 的临时回复,生命周期按 `accepted -> running -> streaming -> finalizing -> completed` 前进;没有正文增量时可跳过 `streaming`,任一非终态都可进入 `failed`,终态后不再接受该回合事件。 -2. 前端只处理 `projectPath` 等于当前项目且 `turnId` 等于当前活动回合的事件。对同一 `projectPath + turnId`,只接受 `sequence` 大于已接收最大值的事件;时间戳更新不能绕过该单调门禁。 -3. 组件存活期内可保留一个全局 Tauri 事件监听。切换项目、切换活动 `turnId` 或 command 完成、失败时,必须清理对应的临时回复、活动文案和最大 `sequence` 等回合关联状态;组件卸载时再清理该全局监听。迟到事件不得污染新项目或新回合。 -4. `failed` 必须结束流式态并清理未完成正文,失败展示继续经现有安全错误映射,不把增量文本伪装成已完成回复。 -5. WorkspaceLauncher 实际项目工作台必须在消息列表内渲染持续可见的同回合过程卡:没有正文时展示当前安全活动,正文 delta 到达后在同一卡内展开累计正文。过程卡不能退化为输入框下方的小号 workspace 状态;用户位于列表底部时活动和正文更新应自动跟随,用户主动上滚后不得强制拉回。 - -### 15.4 权威与持久化边界 - -`game-creator-direct-turn-update` 是 Tauri 进程内的易失通知,只用于提升当前页面的过程可见性;不将事件本身写入项目对话、manifest 或其它 durable 状态,不用它推导跨进程回合已完成。 - -Tauri command 成功返回的 final `String` 是本次回合唯一的终态助手正文和持久化权威。前端收到 command 结果后,用该 `String` 原位收口同一 `turnId` 的临时回复,并且只持久化一条最终 assistant 消息。`completed.accumulatedText` 仍只是临时展示,不得先行或重复持久化,也不得覆盖 command 的 final `String`。 - -本合同是 direct 链路的独立交互投影,不复用 legacy `AgentRuntimeResult`,不恢复 Supervisor 的任务、receipt 或消息真相。本次只保证当前 Tauri command 存活期内的流式展示与最终持久化,不宣称已实现 durable reconnect、跨客户端恢复增量或重连后继续同一未完回合。 - -### 15.5 验收合同 - -- terminal command 返回前,用户消息下方必须持续渲染同回合过程卡;纯工具阶段显示安全活动,真实正文 delta 到达时在同一卡内原位更新临时回复。 -- 对同一 `projectPath + turnId` 注入重复、倒序和迟到的 `sequence`,页面必须拒绝小于或等于已接收最大值的事件,不得发生正文或状态回退。 -- command 成功后只展示并持久化一条以 final `String` 为正文的 assistant 消息;临时回复、`completed` 事件和 command result 不得形成多条最终消息。 -- command 失败、`failed`、项目切换和回合切换均必须清理临时回复、活动状态和序号门禁;组件卸载时必须清理全局监听;旧事件不得出现在新上下文。 -- 单测、AppSurface 回归与真实客户端验收均要覆盖 WorkspaceLauncher 实际工作台、长工具通知 replay、自动跟随和手动上滚保护;事件和 UI 文案不得出现 reasoning、raw arguments、tool item、stderr、内部路径、Provider、凭据或未脱敏错误。 - -## 16. DirectProject 原生 Codex 工具解锁与薄 Runtime(2026-08-24) - -本节 supersede 早期“DirectProject 关闭 shell / unified exec / 任意原生工具、预注入源码快照”的实现描述。它只适用于 `CodexAppServerWorkspaceMode::DirectProject`;ToolHost 与 DirectHome 继续使用被动、只读、无 MCP 的旧合同。 - -- DirectProject 的系统提示词只保留身份、真实 `game/` cwd、可写边界、审核 Skill 索引和副作用归属,总上限收紧为 16 KiB;不再把项目提示词、AGENTS/README/CONTEXT 或 `index.html`、`style.css`、`game.js` 快照批量塞入上下文。Codex 按需读取真实文件,避免重复上下文和过时快照。 -- DirectProject 恢复 Codex 原生文件/搜索/命令、图片查看、Skill 能力,并保留客户端审核的 `agc_tools` 本地 stdio MCP。`taonier_prepare_game_art`、资源登记、去背景、浏览器试玩和受控搜索仍走 `agc_tools`,由客户端负责权限、锁、账本、幂等、下载校验、回滚/对账和投影。 -- `approvalPolicy=never` 与 `workspaceWrite(writableRoots=[真实 game/])` 让原生工具循环不再等待 AGC 泛化审批;原生命令网络保持关闭,联网资料继续走受控 `agc_web_search`。Codex 子 Agent、插件、Apps、图片生成、Goals、Workspace Dependencies、Tool Suggestion 仍显式关闭,因为这些能力尚未接入 AGC 的 durable lock、ledger、取消与 reconciliation。原生浏览器/电脑控制继续不作为未审计副作用入口;真实试玩以 `agc_browser_playtest` 为准。 -- app-server 进程继续使用隔离 `CODEX_HOME`,只注入 `agc_tools`;不会继承用户配置的任意外部 MCP,且显式关闭 hooks。配置了 AGC LLM Key 或可解析的 `OPENAI_API_KEY` 登录态时,AGC 本地 provider proxy 持有真实凭据;前者仍走已配置上游,后者只走 OpenAI 官方 API,Codex 只拿连接级随机代理令牌。无法安全代理的 OAuth `auth.json` 继续关闭 native shell/unified exec。原生 shell 使用 Codex `shell_environment_policy` 的 core 继承与 glob 形式 secret/proxy/bridge 环境排除,provider API key、loopback bridge URL、受控搜索开关不能被 shell 子进程继承。`.agent/`、项目根和 `../assets/` 不可写;sandbox 没有 deny-read,提示词/Skill 约束与真实 smoke 共同验证客户端私有状态不被读取。 -- 旧 `platform-agent-harness`、ToolHost 的 Runtime action、AGC durable delegation 与恢复链路不删除、不改作 Codex 的第二执行权威。多 Agent 仍必须使用现有 Runtime delegation;DirectProject 的原生循环只负责其自身工作区内的即时推理和工具执行。 - -验收重点:DirectProject fake app-server 命令包含 `agc_tools`、原生 shell/unified exec 未被 disable、shell 环境策略和 `agents.enabled=false` 均存在;ToolHost/DirectHome 仍清空 MCP 并关闭原生主动工具;direct 系统提示词不含源码快照或项目 Skill 正文;浏览器工具结果只提供结构化事实证据,不强制固定整改循环。原生 shell 是即时项目检查路径,不产生 legacy `command.exec` receipt,不能据此伪造正式 verification gate 或版本完成证明。真实 smoke 还需确认 Codex 子命令无法读取 provider key、bridge URL 或 `.agent` 私有状态。 diff --git a/docs/project-memory/plans/【实施计划】SFX生成优化V2.0任务拆解-2026-08-06.md b/docs/project-memory/plans/【实施计划】SFX生成优化V2.0任务拆解-2026-08-06.md deleted file mode 100644 index c435a35e6..000000000 --- a/docs/project-memory/plans/【实施计划】SFX生成优化V2.0任务拆解-2026-08-06.md +++ /dev/null @@ -1,259 +0,0 @@ -# SFX 生成优化 V2.0 任务拆解 - -日期:`2026-08-06` - -状态:`T1–T6 工程实施已完成;生产配置确认、旧 Vidu 队列 drain、灰度和实际发布仍须按门禁人工执行` - -开发分支:`feat/sound_opt` - -合并基线:`origin/master@281c84b7bf2d` - -权威设计:[`docs/【编辑器】画板音乐生成入口设计-2026-06-18.md`](../../【编辑器】画板音乐生成入口设计-2026-06-18.md) - -决策入口:[`docs/project-memory/shared-memory/decision-log.md`](../shared-memory/decision-log.md) - -> 本文是通过 Git 共享的脱敏实施计划。代码、OpenAPI、测试和运行配置只实现权威设计中冻结的最终口径,不依赖任何未进入仓库的本地资料。 - -## 文档可见性边界 - -- `local-docs/` 只供当前机器本地使用,由本机 Git exclude 排除,不进入仓库;其他开发者通过 Git 无法看到、读取或核验其中任何文件。 -- 除本节用于声明隔离边界外,仓库中的 tracked 文档不得链接、引用、摘录或把 `local-docs/` 中的文件作为来源、证据或前置阅读材料;代码、OpenAPI、测试、配置和提交信息也不得依赖其内容。 -- 所有参与实现、审查、测试和发布所需的规则与证据,必须自包含地写入 tracked 权威设计、决策日志或本共享计划。团队成员不需要、也不应被要求访问本地资料才能开工或验收。 - -## T0 退出条件 - -T0 只冻结设计、决策、任务归属、迁移 / 回滚门禁和安全记录;不要求当前 Vidu V1 代码、OpenAPI 或实际 API 在 T0 与 SFX V2 设计一致。实现差距在 T1–T5 收敛,T6 验收。 - -| T0 条件 | 状态 | 证据 / 剩余动作 | -| --- | --- | --- | -| 权威 SFX V2 设计已进入 tracked `docs/` | 已完成 | 画板音乐生成入口设计的 SFX V2 章节 | -| T1–T6 计划、基线、测试和迁移门禁已通过 Git 共享 | 已完成 | 本文 | -| External v1 `model` 完整矩阵已冻结 | 已完成 | 本文“请求与幂等口径” | -| 英文化具有 LLM 语义判断和程序 Script 门禁 | 已完成 | 本文“Prompt 与 LLM 口径” | -| 一键优化与翻译的 completion tokens 总预算和 `length` 行为已冻结 | 已完成 | 两类请求均为 `2048 × 4 = 8192`,预算包含 reasoning 与可见输出,见本文“Prompt 与 LLM 口径” | -| 旧 Vidu 队列 drain、发布顺序和回滚门禁已冻结 | 已完成 | 本文“发布与回滚” | -| 凭据安全边界已明确 | 已完成 | 秘密值只允许由服务端私密配置注入,不进入 Git、文档、日志或 fixture;凭据轮换不作为本次 T0 仓库门禁 | -| T0 放行状态已确认 | 已完成 | `2026-08-06` 项目负责人明确确认 T0 通过,可以进入 T1 | - -T0 已通过,T1–T5 可以按本文依赖顺序进入实现;T0 通过不表示功能已上线。 - -## 安全边界与 T0 放行记录 - -该记录只保存日期、责任人 / 工单标识和布尔结论,禁止写入账号、密码、Key、Token、Cookie 或任何可恢复凭据的值。 - -| 记录 | 日期 | 责任人 / 工单 | 结论 | -| --- | --- | --- | --- | -| 凭据安全边界 | `2026-08-06` | 项目负责人确认 | 不在仓库记录秘密值;凭据轮换不作为本次 T0 仓库门禁 | -| 本地资料隔离 | `2026-08-06` | 本机 Git exclude | 已确认仅本机可见、未被 Git 跟踪且不作为团队证据源 | -| T0 放行 | `2026-08-06` | 项目负责人确认 | 已通过,可以进入 T1 | - -## 目标和非目标 - -### 目标 - -- 在 `/editor/canvas` 现有 `audio-sound-effect` 分支把新 SFX 任务从 Vidu `audio1.0` 切换为 ElevenLabs `eleven_text_to_sound_v2`。 -- 复用共享音频 composer、现有生成队列、计费、OSS、资源、素材库和画布完成态。 -- 增加 52 个预设、一键优化、单层交换撤销、Worker 内统一英文化、自动 / 手动时长和 Loop。 -- 稳定保存 `prompt = userPrompt`、`actual_prompt = actualPrompt`、实际时长、Loop、模型、provider 和平台 Task ID。 -- 同批演进站内 DTO、External v1 OpenAPI、幂等语义、定价配置、部署配置和测试。 - -### 非目标 - -- 不修改 BGM Suno、BGM Prompt 助手、BGM 预设、提交锁或定价行为。 -- 不新建 SFX 独立页面、平行 composer 或第二套音频业务真相。 -- 不新建平行编辑器音频 DTO、正式生成 handler、BFF 或 `/api/editor/audios/*/generations` 路由;原地演进 `server-rs/crates/shared-contracts/src/assets.rs` 与 `server-rs/crates/api-server/src/vector_engine_audio_generation/generation.rs` 的现有正式链路。 -- 不开放 Prompt Influence UI;服务端固定 `0.3`。 -- 不为新 SFX 任务提供 Vidu fallback,不删除其它未迁移调用方仍使用的 Vidu 通用能力。 -- 不新增 SpacetimeDB 表或列,不向 External v1 暴露 Prompt 优化或翻译助手。 -- 不执行未授权的真实付费生成。 - -## 当前 V1 差距与任务归属 - -| 领域 | 基线状态 | 收敛任务 | -| --- | --- | --- | -| SFX Prompt | `trim()`、空值回退“游戏音效”、1500 上限 | T1 实现 Unicode canonicalization、2048 上限和无默认回退 | -| SFX UI | textarea、Vidu 胶囊、2–10 整数时长 | T4 增加 52 预设、优化 / 撤销、自动 / 手动时长和 Loop | -| SFX DTO | `prompt + model + duration: u8` | T1 / T5 演进固定模型、nullable 小数时长、Loop 和响应字段 | -| Prompt 语义 | `prompt == actual_prompt` | T2 / T5 分离 userPrompt 和 actualPrompt | -| provider | Vidu submit + poll + URL download | T3 增加 ElevenLabs 同步二进制 adapter,T5 接线 | -| 实际时长 | 请求时长同时作为结果时长 | T3 探测 MP3,T5 写回实际值 | -| Loop | 不存在 | T1 契约、T4 UI、T5 持久化与详情 | -| External v1 | nullable model 默认旧 `audio1.0`,duration 为 2–10 integer | T1 类型基础,T5 同批修改 Rust / OpenAPI / 幂等与结果 | -| 定价 | 旧模型键 5 泥点 | T5 增加新模型键并保持 5 泥点 / 次 | -| 详情 | 通用 Prompt / Model / 时长 / Task | T5 增加中英 Prompt、Loop 和历史 Vidu 分支 | - -## 冻结产品与技术口径 - -### Prompt 与 LLM 口径 - -- `userPrompt` 和 `actualPrompt` 上限均为 2048 Unicode code points。 -- 只按 ECMAScript `String.trim()` 删除首尾空白和行终止符,包含 `U+FEFF`、保留首尾 `U+0085`;不做 NFC、内部空白折叠、换行转换、标点替换或静默截断。 -- 一键优化固定 `gpt-5.6-luna`、`reasoning_effort = medium`;Worker 翻译固定同模型、`reasoning_effort = low`。两类请求分别按各自 2048 Unicode code point 候选上限的 4 倍,固定 completion tokens 总预算 `8192`;该预算由隐藏 reasoning tokens 与可见 JSON 输出 tokens 共享,不包含输入 Prompt tokens,不是可见正文保证,也不按实际输入长度缩小。当前 VectorEngine OpenAI Chat wire 固定发送 `max_completion_tokens = 8192`;内部历史字段名 `max_output_tokens` 不是业务语义。两者均不发送 temperature 或 function tools。 -- 翻译 envelope 固定 `prompt / isEnglish / isFaithfulTranslation / isDirectGenerationFormat / hasAddedOrRemovedRequirement`,只接受完整 `response.text` 中的唯一 JSON object。 -- `isEnglish = true` 作为 LLM 语义判断,程序侧另外要求:候选至少含一个 Script=Latin 的 alphabetic code point,且所有 alphabetic code point 的 Script 均为 Latin;Common / Inherited 数字、标点、空白和符号允许。 -- 日文假名、韩文、西里尔、希腊、阿拉伯等非 Latin alphabetic Script 候选失败。测试必须覆盖中文、英文、中英混合输入,以及 actualPrompt 2048 / 2049 边界。 -- 首轮成功响应但候选不合格或 `finish_reason = length` 时,使用同一 userPrompt 唯一重试;首轮 `content_filter` 和 transport 最终失败不开启第二业务语义轮。 - -### 请求与幂等口径 - -- 自动时长默认开启,并预置最近手动值 `5s`;手动范围 `0.5-30s`、UI 步进 `0.1s`。自动模式发送 null 并保留最近手动值。 -- Loop 默认 false,是独立 API 参数;系统不根据 Prompt 推断、同步或校验 Loop。 -- provider body 固定 `text / model_id / duration_seconds / loop / prompt_influence=0.3`,query 固定 `output_format=mp3_44100_128`。 -- provider POST 不 retry,浏览器正式 POST 不 unsafe retry,队列 `max_attempts = 1`,一个平台 job 最多一次 ElevenLabs POST。 - -External v1 `model` 先删除首尾 Unicode `White_Space`,再按大小写敏感矩阵 canonicalize: - -| 输入 | 结果 | canonical queue payload | -| --- | --- | --- | -| omitted / `null` / 空串 / 纯空白 | 接受 | `eleven_text_to_sound_v2` | -| 首尾空白包围的新模型 | 接受 | `eleven_text_to_sound_v2` | -| `eleven_text_to_sound_v2` | 接受 | `eleven_text_to_sound_v2` | -| `audio1.0` | `400 BAD_REQUEST` | 不入队 | -| 其它未知非空值 | `400 BAD_REQUEST` | 不入队 | - -所有接受形态在定价、预扣和 enqueue 前收敛为同一个 model 字段,不得产生不同幂等 payload。拒绝形态必须证明零入队、零预扣、零 LLM 和零 provider。 - -### 结果、计费与数据 - -- 服务端重建 SFX V2 `generation_inputs_json`,不信任客户端的 actualPrompt、实际时长、model 或 Loop。 -- 成功响应的 MP3 必须按现有 `MAX_GENERATED_AUDIO_BYTES = 40 MiB` 有界读取并验证,探测实际时长且只以独立技术异常上限 `600s` 拒绝过长结果;不把请求最大 `30s` 当作响应上限。平台 taskId 使用 operation / queue job ID,不伪造 provider task ID。 -- 新模型按次保持 5 泥点,以后端入队时冻结价格为真相。 -- 不修改 SpacetimeDB schema,复用 `prompt / actual_prompt / generation_inputs_json` 和画布 layout。 - -## 任务包 - -### T0:权威设计、共享计划、安全记录与迁移口径 - -- 仅修改 tracked 文档,不实现功能代码。 -- 完成权威设计、本共享计划、决策日志、对 V1 差距的 T1–T5 归属、drain / 发布 / 回滚门禁。 -- T0 放行记录必须真实且脱敏,不得为凭据轮换、责任人或工单虚构证据。 - -### T1:Prompt 规则、52 预设、共享契约与 metadata 基础 - -- 实现前后端 ECMAScript `String.trim()` 等值 canonicalization、code point 计数、2048 边界和无默认 Prompt 回退。 -- 增加 40 + 12 预设纯模型,锁定数量、ID、分类和可见文案。 -- 原地演进现有 TypeScript / Rust 音频 DTO:fixed model、nullable 小数 duration、Loop、实际时长和 V2 metadata;不得新增同义 DTO 或平行正式生成契约。 -- 实现 External `model` canonicalizer 的纯函数与矩阵测试;实际 OpenAPI / handler 接线属于 T5。 - -实施记录(`2026-08-06`):T1 已完成。前后端共享 canonicalization fixture 已锁定 Unicode 边界与 `2048 / 2049` 行为;52 个预设、最小优化 DTO、固定模型、nullable duration、Loop 默认值、响应结果字段和强类型 V2 metadata 已落地。duration 纯校验接受自动 `null` 与手动 `0.5–30s`,拒绝非有限值和越界值。External `model` 当前只落地纯 canonicalizer 与输入矩阵测试,正式定价、预扣、enqueue、OpenAPI 和副作用测试仍严格归属 T5;在 T5 完成前不得发布当前中间态。 - -补充验收(`2026-08-06`):音频 compact 结果保留完整 DTO 必填的 `provider`,SFX / BGM 均通过真实 compact → Agent reconcile 回归;正式 SFX 提交流程不再执行原生 `trim()` 或默认 Prompt 回退。Rust V2 metadata 只能经校验构造并拒绝错误版本、模型、时长组合与实际时长;共享 fixture 直接锁定 `1 / 2048 / 2049`,52 个预设 ID 和非 `0.1s` 步进小数时长均有固定断言。 - -规则修订(`2026-08-07`):SFX Prompt 边界 canonicalization 改为 ECMAScript `String.trim()`;本条覆盖上段“不得执行原生 `trim()`”的旧口径。TypeScript 直接调用 `String.trim()`,Rust 以等值边界字符集合实现;首尾 `U+FEFF` 删除、首尾 `U+0085` 保留,BGM Prompt 与 External `model` 的 Unicode `White_Space` 规则不变。 - -### T2:一键优化 BFF 和 Worker 翻译 service - -- 增加登录态 SFX Prompt 优化 BFF,固定 Luna + Medium + completion tokens 总预算 `8192`,32 KiB body limit,严格唯一 JSON envelope,不调用音频 provider 或正式计费。 -- 增加仅 Worker 可调用的 Luna + Low 翻译 service,每次业务尝试固定 completion tokens 总预算 `8192`,严格 `isEnglish` + Unicode Script 门禁、保真判断和最多一次业务重试。 -- 测试覆盖中文 / 英文 / 中英混合输入,日文 / 韩文 / 西里尔等非 Latin 字母候选,actualPrompt 2048 / 2049,请求体精确 token 上限,以及优化直接拒绝 `length`、翻译首轮 `length` 重试一次 / 第二轮 `length` 最终失败和 `content_filter / transport` 行为。 - -实施记录(`2026-08-06`,`2026-08-07` 同步 master token 契约):T2 已完成。登录态 `POST /api/editor/audios/sound-effects/prompts/optimizations` 已按 `32 KiB` body limit、Luna + Medium + OpenAI Chat + completion tokens 总预算 `8192` 接入,并注册 User-scope tracking;当前 VectorEngine Chat wire 只发送 `max_completion_tokens=8192`,不发送 `max_tokens` 或 `max_output_tokens`。优化候选只接受完整唯一五字段 JSON object,拒绝 tool call、未完成响应、非 Han、生成参数内容、代码块、解释、额外 / 重复字段和超限结果,错误响应不暴露候选或内部 envelope。现有音频生成模块内已增加不注册 HTTP 路由的 Worker 翻译 service,固定 Luna + Low + completion tokens 总预算 `8192`,使用同一 Chat wire 字段,严格执行保真 / 直接生成格式 / Latin Script 门禁,首轮内容不合格或 `length` 只以原始 `userPrompt` 重试一次,`content_filter` 和 transport 最终失败不进入第二业务语义轮;typed failure 只暴露 `translation_invalid / translation_upstream_failed` 安全分类。T2 只交付可供 T5 调用的内部 service,尚未改变当前 Vidu 正式生成、队列、计费、持久化、External v1 或 OpenAPI,不是可发布切点。 - -### T3:ElevenLabs adapter、配置、二进制与时长探测 - -- 在 `platform-audio` 增加独立 ElevenLabs settings、endpoint normalizer、request builder 和 direct binary client,不伪装 Vidu / Suno poll task。 -- 固定 model、influence、format、header 与 query;按 `40 MiB` 做 Content-Length 预检和 `limit + 1` 流式读取,执行 MIME / MP3 验证和纯 Rust duration probe,并以 `600s` 作为独立技术异常时长上限。 -- 配置增加 `ELEVENLABS_BASE_URL / ELEVENLABS_API_KEY / ELEVENLABS_REQUEST_TIMEOUT_MS`,Key 只在服务端。 -- 测试断言 429 / 5xx / timeout / 读取失败都只有一次 provider POST,不执行真实付费请求。 - -实施记录(`2026-08-07`):T3 已完成。`platform-audio` 已增加独立 ElevenLabs 直接二进制 adapter,固定 endpoint、header、query、model、influence、nullable 小数时长和 Loop;专用 HTTP client 禁止重定向且没有 retry。成功响应先做 `40 MiB` Content-Length 预检,再以 `limit + 1` 有界读取,严格执行 MIME / 真实 MP3 门禁,并以纯 Rust MP3 probe 取得有限正实际时长和独立 `600s` 上限;请求格式 `mp3_44100_128` 不扩展为返回码率硬校验。配置、环境模板和 fail-closed settings guard 已落地,持久化准备已把 provider / file stem 从轮询任务枚举中最小解耦;正式 handler、Worker、计费、OSS 写回、External v1 和 OpenAPI 均未接线,继续归属 T5。 - -### T4:SFX 前端 controller、预设与参数 UI - -- 新增 SFX Prompt 纯模型、预设纯模型和 dialog-scoped controller;抽取音频预设跑马灯内核,BGM / SFX 保留各自 wrapper。 -- 在共享 composer 的 SFX 分支增加计数、52 预设、一键优化、单层交换撤销、自动 / 手动时长、Loop 和 ElevenLabs 胶囊。 -- 在第一个 await 前取得 AI / 提交 operation,只锁当前 SFX dialog;迟到响应和 scope 切换不写新面板。 -- T4 不切换 provider,不是可发布切点;与 T5 同一发布列车。 - -实施记录(`2026-08-07`):T4 已完成。前端增加独立于 BGM 的 dialog-scoped SFX Prompt 状态模型与 controller,优化和提交都在第一个 `await` 前同步取得 operation;账号、项目、dialog、mode 和 `AbortController` 共同隔离迟到响应。优化成功形成一层 canonical Prompt 交换快照,失败清除本次临时快照且不恢复更早快照,预设写入清快照。现有 BGM 跑马灯已抽出无业务语义的音频内核,BGM / SFX 各保留 wrapper;SFX wrapper 展示 T1 冻结的 `40 + 12` 预设。 - -共享音频 composer 的 SFX 分支现已展示 `0 / 2048` 计数、一键优化、单层撤销、自动 / 手动时长、`0.5-30s` 且 `0.1s` 步进的 slider、Loop、固定 `ElevenLabs` 胶囊和新模型前端 `5` 泥点兜底。dialog layout 保存并恢复 `soundDurationMode / soundDurationSeconds / soundLoop`;历史 Vidu dialog 和改造入口统一打开 SFX V2 模型面板。同步提交 claim 冻结 canonical Prompt、时长模式、最近手动值和 Loop,只锁当前 dialog,并在 scope 失效后拒绝旧 UI 写回。 - -T4 没有修改 Worker、provider 调用、正式请求的 nullable duration / Loop 映射、服务端动态定价、计费、OSS、持久化详情、External v1、OpenAPI 或 SpacetimeDB schema;这些继续严格归属 T5。T4 单独合入仍不是可发布切点,也未执行真实 LLM、ElevenLabs 或付费生成。 - -### T5:正式提交、Worker、计费、持久化、详情和 External v1 - -- 前端提交冻结 canonical Prompt、duration 和 Loop,正式 POST 不 unsafe retry。 -- 原地演进 `server-rs/crates/api-server/src/vector_engine_audio_generation/generation.rs` 的现有 handler,在定价 / 预扣 / enqueue 前 canonicalize External model,入队 payload 不含提前翻译的 actualPrompt;保留现有路由注册、queue / inline 分流和计费边界。 -- Worker 执行翻译、单次 ElevenLabs、MP3 时长探测、OSS 和权威 metadata / 画布写回;任一阶段失败进入现有退款链路。 -- 实现新模型定价键、历史 Vidu 只读 / 重绘兼容、中英 Prompt + Loop 详情和真实时长。 -- 同批更新 External v1 Rust DTO / handler / OpenAPI / Idempotency-Key 重放 / compact result;任一字段不一致时 T5 不完成。 - -实施记录(`2026-08-07`):T5 已完成。站内与 External SFX 请求在定价、预扣和 enqueue 前统一 canonicalize 为固定模型、canonical userPrompt、nullable 小数时长与 Loop;正式浏览器 POST 不再配置 unsafe retry,queue payload 不包含提前翻译的 actualPrompt。Worker 在既有冻结计费上下文内执行 Luna 英文化、单次 ElevenLabs POST、MP3 校验与实际时长探测、OSS、项目资源 / 账号素材 / 画布完成态写回,并使用 queue job ID 或 inline 预生成的平台 ID 作为 Task ID。服务端重建 `generation_inputs_json`,客户端自报的实际英文 Prompt、实际时长、模型与 Loop 不进入权威 metadata。 - -新定价键 `eleven_text_to_sound_v2` 已加入默认 JSON、api-server 与 SpacetimeDB 值校验,旧 `audio1.0` 键继续保留;历史 SpacetimeDB 定价快照仅缺新键时由受控本地定价补齐读取,下一次后台保存写回完整矩阵,不修改 schema。详情展示中英 Prompt、实际时长、Loop、生成模型与完整平台 Task ID;SFX V2 重绘恢复 userPrompt、duration mode / requested duration 和 Loop,自动时长不会把实际输出时长误作下一次手动值。 - -External v1 Rust handler、共享 DTO、OpenAPI、compact result 与 Agent Skill 已同步 nullable `0.5-30` 时长、Loop、固定模型和实际 `durationSeconds`;接受的 model 形态生成同一 canonical queue payload,旧 / 未知模型在 enqueue 前返回 `400`。External compact 继续隐藏 provider 与 Prompt,只保留稳定资源引用、实际时长和 Loop。T5 定向 Rust、TypeScript、External/OpenAPI、Agent、定价与 SpacetimeDB WASM build 已通过,未执行真实 LLM、ElevenLabs 或其它付费请求;完整失败矩阵、端到端与发布 smoke 继续归属 T6。 - -### T6:测试、文档、灰度和发布门禁 - -- 汇总 T1–T5 分层测试,增加 mock LLM + mock ElevenLabs + mock OSS 失败矩阵、端到端等值、刷新 / 重绘、计费退款、无重试、External 幂等和 BGM 回归。 -- 更新后端架构、前端专题、开发运维和共享项目记忆。 -- 执行定向 TypeScript / Rust / OpenAPI、`npm run typecheck`、`npm run check:encoding`、`git diff --check`、`npm run check:spacetime-schema`、`npm run dev:api-server` + `/healthz`。 -- 不将 mock 测试写成真实 provider 验收,不执行未授权付费生成。 - -实施记录(`2026-08-07`):T6 已完成工程侧测试缝、组合失败矩阵、跨入口补齐、稳定失败分类和发布 runbook。正式 SFX Worker 现由同一编排函数串联计费、翻译、ElevenLabs、OSS、asset object / bind 候选和原子资源 / 素材 / 画布 / job 提交;生产 adapter 继续调用原实现,测试 adapter 覆盖自动 / 手动时长 × Loop、余额不足零外部副作用、翻译 / provider / MP3 / OSS / asset candidate / 原子项目资源 / 账号素材 / 画布写回失败、一次退款和单 job 最多一次 provider POST。ElevenLabs HTTP / 无效音频 / 时长探测分别稳定归类为 `elevenlabs_http_failed / invalid_audio / duration_probe_failed`,OSS 与后续写回归类为 `oss_failed / writeback_failed`;普通用户继续只看到稳定短文案。 - -T6 盘点发现并修复画布 Agent 遗留的 Vidu 参数边界:`generate-sound-effect` 现与站内和 External v1 共用 canonical Prompt、固定模型、`duration = null | 0.5-30` 和 `loop`,显式 `duration: null` 不再被通用 null-default 兼容层错误恢复为手动 `5s`。完整验证和生产门禁记录见 [`docs/【实施记录】SFX生成优化V2.0T6测试与发布门禁-2026-08-07.md`](../../【实施记录】SFX生成优化V2.0T6测试与发布门禁-2026-08-07.md)。本阶段没有调用真实 LLM / ElevenLabs、没有执行付费生成、没有连接生产 SpacetimeDB,也没有执行发布;因此“工程 T6 完成”不等于“生产门禁已放行”。 - -## 依赖和发布列车 - -```text -T0 -> T1 -T1 -> T2 + T3 + T4 -T2 + T3 + T4 -> T5 -T5 -> T6 -``` - -- T2 / T3 可在 T1 契约稳定后并行;T4 可与两者后半程并行。 -- T4 与 T5 之间不存在可发布切点。 -- 不修改 SpacetimeDB schema;如实际实现发现必须修改,立即停止并按 schema 迁移规则重新评审,不得带入本计划默认实施。 - -## 测试门禁 - -| 层级 | 必要覆盖 | -| --- | --- | -| canonical | 空 / 全 ECMAScript trim 字符(含 U+FEFF)、首尾 U+0085 保留、U+200B、内部 U+FEFF、换行、组合字符、ZWJ emoji、2048 / 2049 | -| 预设 | 40 + 12、ID / label 唯一、文案等值、逗号追加、重复、清快照、超限保文 | -| 优化 | Luna + Medium + completion tokens 总预算 `8192`,Chat wire 只含 `max_completion_tokens=8192`,唯一 JSON、布尔门禁、length 直接失败、content_filter、无 tool call、无候选泄漏、dialog / scope 迟到响应 | -| 翻译 | 每轮 Luna + Low + completion tokens 总预算 `8192`,Chat wire 只含 `max_completion_tokens=8192`,中文 / 英文 / 中英混合输入,日文 / 韩文 / 西里尔候选,isEnglish + Script 门禁,2048 / 2049,首轮 length 唯一重试、第二轮 length 最终失败且 provider 0 次 | -| 跨入口 / External model | 登录态、External v1、画布 Agent 共用 canonical SFX queue payload;omitted / null / 空串 / 纯空白 / 包围空白新模型 / 显式新模型共用幂等 payload;`audio1.0` / 未知值为 400 + 零副作用 | -| ElevenLabs | auto / manual × Loop false / true,固定 model / influence / format,Key 不泄漏,网络 / HTTP / body 失败均只有一次 POST | -| 二进制与时长 | `40 MiB` 接受 / `40 MiB + 1 byte` 拒绝,Content-Length / chunked 超限、空 / HTML / JSON / 损坏 MP3、允许与 fallback MIME;有限正时长、30.5 / 60 / 600s 接受,>600s / NaN / 无穷拒绝 | -| 持久化 | prompt / actual_prompt / model / provider / task / actual duration / Loop 权威等值,客户端伪造值失效 | -| 计费 | 余额不足零 LLM / provider;翻译 / provider / MP3 / OSS / DB 失败一次退款 | -| 回归 | BGM Suno、助手、预设、锁和定价不变;其它 Vidu 调用方仍可编译和测试 | - -## 发布与回滚 - -### 发布前 - -- 不打印值地确认生产 `ELEVENLABS_BASE_URL / ELEVENLABS_API_KEY / ELEVENLABS_REQUEST_TIMEOUT_MS` 均已配置。 -- 确认定价 override 包含 `eleven_text_to_sound_v2` 且价格已批准。 -- 只读查询 `external_generation_job` 中 `job_kind = 'editor_sound_effect_generation'` 且 `status IN ('pending', 'running')` 的旧 Vidu payload。非零时先 drain,不得让新 Worker 按 V2 nullable duration / Loop payload 解析旧任务;命令必须显式指定 `--server` / `--server-url`。 -- 先部署 api-server / worker,再部署 web;两者之间使用维护窗或暂时关闭 SFX 提交入口。 -- External v1 变更提前通知调用方并完成 contract smoke。 - -### 观测 - -- 区分 `translation_invalid / translation_upstream_failed / elevenlabs_http_failed / invalid_audio / duration_probe_failed / oss_failed / writeback_failed`。 -- 只记录 operation ID、阶段、HTTP status、耗时、响应字节数和实际时长;不记录 Key 或完整 provider 错误正文。 -- 对账 job 完成数、退款数、ElevenLabs 调用数和完成资源数,识别重复调用和孤儿资源。 - -### 回滚 - -- 回滚时不自动切回 Vidu;先停止新 SFX 入队。 -- 等待或人工收口 V2 queued / running job,避免旧 Worker 无法解析 V2 payload。 -- 协同回滚 web、api-server、worker 和 External v1 文档,禁止只回滚一层。 -- 新生成的 ElevenLabs 素材继续按通用 audio / model / generation inputs 只读展示,不做数据迁移回滚。 -- 没有 SpacetimeDB schema 变更,回滚不执行表迁移或字段删除。 - -## 完成定义 - -- T0 已通过,T1–T5 按依赖顺序实现并分别完成测试门禁。 -- T1–T5 完成各自分层测试,T6 完成全部发布门禁。 -- 新编辑器 SFX 不调用 Vidu,历史 Vidu 数据仍可读和按新模型重绘。 -- 翻译最终失败时 ElevenLabs 调用为 0;成功 job 最多一次 provider POST。 -- MP3 经过有界读取、验证和实际时长探测,权威 metadata 跨队列、OSS、素材、画布、响应和刷新一致。 -- External v1 Rust、OpenAPI、幂等 payload、副作用和最终响应逐字段一致。 -- 配置、日志、fixture、差异和提交不包含真实账号、Key、Token、Cookie 或其它凭据值。 diff --git a/docs/project-memory/plans/【计划】AGC开发态单窗口启动收口-2026-08-17.md b/docs/project-memory/plans/【计划】AGC开发态单窗口启动收口-2026-08-17.md deleted file mode 100644 index 042892441..000000000 --- a/docs/project-memory/plans/【计划】AGC开发态单窗口启动收口-2026-08-17.md +++ /dev/null @@ -1,19 +0,0 @@ -# AGC 开发态单窗口启动收口计划 - -日期:`2026-08-17` - -## 目标 - -`npm run agc` 启动时只打开标题为“陶泥儿”的正式客户端窗口,不再自动额外打开 Agent 聊天开发窗口。 - -## 范围与边界 - -- 删除 Tauri setup 中仅 debug 生效的自动 developer 窗口调用,以及已无调用方的 developer 窗口构造代码与专属路由测试。 -- 不删除前端 `?agent-chat` 调试页面;它不再是 `npm run agc` 的自动入口。 -- 同步原生壳静态门禁、技术方案和长期决策记录,防止自动双窗口回归。 - -## 验收 - -1. Tauri 定向 Rust 测试和前端类型检查通过。 -2. 配置门禁、编码检查和差异检查通过。 -3. 实际运行 `npm run agc` 后,仅存在标题为“陶泥儿”的客户端窗口,不存在 Agent 聊天开发窗口。 diff --git a/docs/project-memory/plans/【计划】AgentSwarm纯聊天验证入口-2026-07-14.md b/docs/project-memory/plans/【计划】AgentSwarm纯聊天验证入口-2026-07-14.md deleted file mode 100644 index 5a5270a2b..000000000 --- a/docs/project-memory/plans/【计划】AgentSwarm纯聊天验证入口-2026-07-14.md +++ /dev/null @@ -1,48 +0,0 @@ -# Agent Swarm 纯聊天验证入口计划 - -更新时间:`2026-07-14` - -## 目标 - -提供一版不依赖正常客户端 GUI 的终端聊天入口,让开发者选择一个父 Agent,通过真实 Agent Runtime 验证静态委派、动态隔离子 Agent、并行执行、确认动作、回执汇总和多轮持久化。 - -## 范围 - -- 新增 `--swarm-chat [--init] <本地项目绝对路径> [parentAgentId]`,省略时默认进入 `project-supervisor`。 -- 新增总控短命令 `npm run agc:chat -- --config-dir <项目外 AppData 绝对路径> [--init] `;保留 `agc:swarm` 显式父 Agent 调试入口。 -- 普通输入进入父 Agent background Runtime;不使用一次性 `--agent-chat`。 -- 复用 External Runner、active Session、现有 conversation、Agent 私有记忆、项目黑板、`agent.delegate`、`agent.spawn_isolated`、terminal receipt 和 all-join。 -- 展示全部 Agent 的状态、事件、父子身份和委派关系,并支持在终端批准或拒绝待确认动作。 -- 提供 `/help`、`/agents`、`/status`、`/history`、`/quit`。 - -## 非目标 - -- 不新增 Tauri 窗口、浏览器页面或本地 HTTP / SSE bridge。 -- 不新增 Provider 调用路径、Agent 数据库或 conversation 格式。 -- 不伪造 token streaming;首版展示 Runtime 状态 / 事件流和最终回复。 -- 不在终端退出时取消 Runner、run 或 Runner-owned process session。 - -## 实现步骤 - -1. 扩展 CLI command、参数解析和项目外 `--config-dir` 门禁。 -2. 新增独立终端 REPL 模块,复用项目初始化、Runtime resume、任务投递和 conversation 读取。 -3. 轮询全 Agent Runtime,按身份去重输出状态和事件;待确认时走现有 confirm / reject。 -4. 用“全 Runtime 非活跃 + 全队列为空 + 稳定观察窗口”判断一轮收束,再读取父 Agent 当前 Session 的新增 assistant 消息。 -5. 增加 npm 短命令、确定性测试、真实启动 smoke 和文档同步。 - -## 验收清单 - -- CLI parse、绝对路径、项目初始化、`--config-dir`、空输入、EOF 和 slash command。 -- 同一父 Agent 连续两轮使用同一 Session,退出重进后历史可见。 -- 两个静态 Agent 并行委派,多个动态 child 并行并形成唯一 all-join。 -- approve / reject 均能在终端完成,拒绝后父 Agent 能继续修正计划。 -- 父 Agent 暂时 idle、child 仍运行或 receipt 尚未认领时不提前结束。 -- Runner 或终端重启后恢复同一 run / session,不重放副作用。 -- 真实 Provider transcript 与 task / event / Agent DB / receipt / conversation 一致,最终父回复唯一且无密钥泄漏。 - -## 当前进度 - -- 已完成终端入口、短命令、Runtime 状态 / 事件输出、approve / reject、active Session 历史、same-run steer、活跃 `/quit`、启动 / 收束恢复扫描和 Runner 失联阻断。 -- 已用真实 `gpt-5.5` 观察到两个静态 Agent 并行、两条 child result、receipt 排队与重启恢复;终端确认、拒绝和活跃退出均生效。同一父 Session 连续 4 轮固定回复及 8 条消息历史恢复通过,最终双安静窗口收束返回 `FOURTH_OK`。 -- 未通过父 Agent 最终汇总:全量 `agent.run_status` 输出截断导致第一轮预算耗尽;第二轮 receipt continuation 未恢复原始只读目标并请求文件写入,已拒绝。 -- 待办:修复定向状态查询或 receipt continuation 目标恢复,复验唯一最终父回复;再补动态 isolated child 并行、唯一 all-join 和 Runner 强杀恢复。 diff --git a/docs/project-memory/plans/架构优化计划书.md b/docs/project-memory/plans/架构优化计划书.md deleted file mode 100644 index 604dc11b7..000000000 --- a/docs/project-memory/plans/架构优化计划书.md +++ /dev/null @@ -1,399 +0,0 @@ -# Genarrative(陶泥儿)项目架构优化计划书 - -**文档版本**:v1.0 -**编制日期**:2026-05-26 -**项目名称**:Genarrative(陶泥儿) -**文档密级**:内部 - ---- - -## 一、项目概况 - -| 维度 | 详情 | -|---|---| -| **项目名** | Genarrative(陶泥儿) | -| **项目定位** | AI Native 互动视觉 RPG 平台——支持多种玩法模板的 AI 创作、运行与分享("玩法类型平台") | -| **核心玩法** | 拼图、视觉小说、Match3D、Bark Battle、Big Fish、Jump-Hop、Square Hole、木鱼、教娱等 10+ 种玩法模板 | -| **代码规模** | 前端 ~823 个 TS/TSX 文件,后端 ~1532 个 Rust 文件,属于大型项目 | - -### 1.1 计划目的 - -本计划书基于对 Genarrative 项目当前架构的全面分析,识别架构层面的关键问题,并提出分阶段、可落地的优化方案。旨在: - -- 统一前端架构模式,降低团队认知成本和新人上手门槛 -- 提升模块内聚性,减少不必要的耦合与依赖 -- 建立自动化契约保障机制,降低跨语言同步出错风险 -- 优化工程基础设施,提高开发效率和运维可观测性 - ---- - -## 二、技术栈总览 - -| 层级 | 技术选型 | 版本 | -|---|---|---| -| **前端框架** | React + TypeScript + Vite | React 19 / TS 5.8 / Vite 6 | -| **样式** | TailwindCSS | v4 | -| **3D / 动画** | Three.js、Motion、cannon-es | - | -| **后端 HTTP** | Rust + Axum(BFF 门面) | Axum 0.8 | -| **游戏状态 DB** | SpacetimeDB(实时反应式数据库) | v2.2 | -| **AI / LLM** | LangChain-Rust + LLM Proxy | - | -| **小程序** | 微信小程序(含微信支付) | - | -| **容器化** | Docker Compose(Nginx + API Server + OTel Collector) | - | -| **运维** | systemd、Nginx、Jenkins CI/CD、k6 压测 | - | -| **可观测性** | OpenTelemetry(OTLP → Grafana) | - | - ---- - -## 三、当前架构分层图 - -``` -┌──────────────────────────────────────────────────────────────┐ -│ 入口层 │ -│ index.html → main.tsx → resolveAppRoute() → RouteComponent │ -│ (多入口路由:平台主页 / 拼图 / BigFish / Match3D / ...) │ -└──────────────────────────────────────────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────────────────────────┐ -│ 前端应用层 (src/) │ -│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────────┐│ -│ │ components/ │ │ services/ │ │ games/ ││ -│ │ *-creation │ │ *-creation │ │ bark-battle/ ││ -│ │ *-result │ │ *-runtime │ │ domain/ ││ -│ │ *-runtime │ │ *-works │ │ application/ ││ -│ │ common/ │ │ storyEngine │ │ infrastructure/ ││ -│ │ auth/ │ │ payment │ │ ui/ ││ -│ └─────────────┘ └──────────────┘ └──────────────────────┘│ -│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────────┐│ -│ │ hooks/ │ │ data/ │ │ routing/ ││ -│ │ persistence/│ │ functionCat. │ │ config/ editor/ ││ -│ └─────────────┘ └──────────────┘ └──────────────────────┘│ -└──────────────────────────────────────────────────────────────┘ - │ Vite Proxy (/api/*) - ▼ -┌──────────────────────────────────────────────────────────────┐ -│ Rust 后端 (server-rs/) │ -│ ┌──────────────────────────────────────────────────────┐ │ -│ │ api-server (Axum HTTP / SSE / BFF 门面) │ │ -│ └──────────────────────────────────────────────────────┘ │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ ┌──────────┐ ┌──────────────────┐ ┌──────────────┐ │ -│ │ platform │ │ module-* │ │ shared │ │ -│ │ -auth │ │ -puzzle │ │ -contracts │ │ -│ │ -llm │ │ -visual-novel │ │ -kernel │ │ -│ │ -image │ │ -match3d │ │ -logging │ │ -│ │ -oss │ │ -bark-battle │ └──────────────┘ │ -│ │ -speech │ │ -big-fish ... │ │ -│ │ -agent │ │ -runtime │ │ -│ └──────────┘ │ -combat/npc │ │ -│ └──────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────────────────────────────────────────┐ │ -│ │ spacetime-module + spacetime-client → SpacetimeDB │ │ -│ └──────────────────────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────┘ - -┌──────────────────────────────────────────────────────────────┐ -│ 辅助子系统 │ -│ apps/admin-web (React 后台管理) │ -│ miniprogram/ (微信小程序) │ -│ packages/shared (前后端共享契约/LLM工具) │ -│ deploy/ (Docker/Nginx/systemd/OTel) │ -│ scripts/ (40+ 构建/部署/检查脚本) │ -│ jenkins/ (CI/CD Pipeline) │ -└──────────────────────────────────────────────────────────────┘ -``` - ---- - -## 四、架构亮点 - -1. **清晰的"玩法模板"平台模式** - 每种玩法遵循统一的 `creation → result → runtime` 三段式生命周期,前端 `components/` 和 `services/` 均按此模式组织。新增玩法可快速套用模板,极大降低了横向扩展成本。 - -2. **后端严格的分层约束** - `api-server`(门面)→ `module-*`(领域)→ `spacetime-module`(持久化),`module-*` 不直接依赖 Axum、HTTP、SpacetimeDB table、LLM、文件系统,保证了领域纯净性和可测试性。 - -3. **SpacetimeDB 作为游戏状态核心** - 采用反应式实时数据库替代传统 Redis + PostgreSQL 组合,天然适合多人实时游戏状态同步,减少了中间层复杂度和延迟。 - -4. **前端 DDD 探索** - `src/games/bark-battle/` 采用 `domain / application / infrastructure / ui` 四层 DDD 结构,为复杂玩法的前端架构提供了良好范本。 - -5. **完善的多入口路由体系** - 通过 `resolveAppRoute()` 按 URL path 分发到不同的 lazy-loaded 组件,实现了按需加载和良好的首屏性能。 - -6. **运维体系完备** - Docker Compose + systemd + Nginx + OpenTelemetry + k6 压测 + Jenkins CI/CD,覆盖了构建、部署、监控、压测全链路。 - ---- - -## 五、问题诊断与改进方案 - -### 问题 1:前端 services/ 与 components/ 的耦合不统一 - -**现状** -大部分玩法遵循 `services/` + `components/` 分离模式,但部分玩法运行时直接放在 `components/` 下,services 层职责模糊——有的承担了业务逻辑编排,有的仅作简单 API 调用。 - -**影响** -- 新人阅读代码时无法预判某个逻辑应位于哪个目录 -- 单元测试困难:services 与组件耦合的业务逻辑无法独立测试 -- 跨玩法复用时需要额外的迁移成本 - -**改进方案** -1. 制定规范:`services/` 仅负责纯 API 调用和数据转换,不包含业务判断逻辑 -2. 业务逻辑统一归到 `hooks/` 或 `games//application/` -3. 以 puzzle 玩法为样板,先行重构并形成迁移指南,再推广至其余玩法 -4. 在 CI 中增加 ESLint 规则,禁止 `components/` 直接 import `services/` 之外的外部模块 - -**预期收益** -- 职责边界清晰,降低认知成本约 30% -- services 层可独立单测覆盖率达到 80%+ -- 新玩法开发上手时间从 2 天缩短至 0.5 天 - ---- - -### 问题 2:前端 DDD 与模板模式并存,架构不统一 - -**现状** -`bark-battle` 采用 DDD 四层结构(`domain/application/infrastructure/ui`),其余玩法散落在 `components/` + `services/` 下,存在两种截然不同的组织范式。 - -**影响** -- 团队内部对"正确"的代码组织方式缺乏共识 -- 代码审查时需要切换判断标准 -- DDD 玩法的优势无法在全局范围内发挥 - -**改进方案** -1. 所有玩法统一迁移到 `src/games//` 下,采用 `domain / application / ui` 三层结构(infrastructure 按需保留) -2. 以 puzzle 为样板完成首例迁移,产出迁移 Checklist 和模板生成脚本 -3. 新增玩法脚手架直接生成 DDD 结构目录 -4. 旧玩法分批次迁移,每批次 2-3 个玩法,在 4 个迭代内完成 - -**预期收益** -- 架构一致性提升至 100% -- 跨玩法逻辑复用变得可能(domain 层可共享) -- 为后续 monorepo 改造打下基础 - ---- - -### 问题 3:后端 module-* 粒度偏细,存在潜在循环依赖风险 - -**现状** -后端共 35 个 crate。`module-runtime` 被拆分为 3 个独立 crate,`module-combat / npc / inventory` 各自独立。部分紧密协作的模块之间可能存在隐式耦合。 - -**影响** -- 编译时间增长(35 个 crate 独立编译) -- 跨 crate 重构时需要同时修改多处 -- 循环依赖风险增加,可能在特定组合下触发编译失败 - -**改进方案** -1. 评估合并方案: - - `module-runtime-*` 系列合并为单 crate `module-runtime`,内部用 `mod` 做逻辑隔离 - - `module-combat / npc / inventory` 评估合并为 `module-combat`,npc 和 inventory 作为子模块 -2. 保留 trait/interface 抽象层,确保 module 之间不直接依赖具体实现 -3. 在 CI 中引入 `cargo-deny` 或自定义脚本,自动检测 module 间的依赖方向是否违反分层约束 -4. 目标:将 35 个 crate 精简至 25 个以内 - -**预期收益** -- 全量编译时间预计缩短 15%-20% -- 循环依赖风险归零 -- module 内部重构成本降低 - ---- - -### 问题 4:根目录 env 文件过多且混乱 - -**现状** -根目录存在 4 个 env 文件(`.env`、`.env.example`、`.env.production` 等),且 `deploy/` 下另有多个 env 文件。配置分散在多处,部分文件之间字段不一致。 - -**影响** -- 排查配置问题时需要翻阅多个文件 -- 新人无法快速确定本地开发需要哪些环境变量 -- 部署时可能遗漏或错误覆盖某项配置 - -**改进方案** -1. 收敛为三层配置体系: - - `.env.example`:包含所有可配置项的说明和默认值(唯一提交到仓库的 env 文件) - - `.env.local`:本地开发覆盖(加入 .gitignore) - - `deploy/env/.env`:各部署环境专用配置 -2. 引入 config crate,支持层次覆盖(default → local → env-specific),启动时自动校验必填字段 -3. 在 CI 中加入 env 校验步骤:对比 `.env.example` 与部署环境的 env 文件,标记缺失或多余字段 - -**预期收益** -- 配置查找时间从分钟级降至秒级 -- 部署配置遗漏导致的线上事故减少 90%+ -- 新成员本地环境搭建时间从 30 分钟缩短至 10 分钟 - ---- - -### 问题 5:scripts/ 目录膨胀为"万能工具箱" - -**现状** -`scripts/` 目录共 42 个文件,涵盖构建、部署、检查、迁移、生成、压测等,全部平铺在同一层级,缺乏分类。 - -**影响** -- 难以快速定位所需脚本 -- 同类脚本缺乏命名规范 -- 新增脚本时不知道放在何处 - -**改进方案** -1. 按功能域分类重组: - -``` -scripts/ -├── build/ # 构建相关(vite、cargo、wasm 等) -├── deploy/ # 部署相关(docker、systemd、rsync) -├── check/ # 检查/校验(lint、format、type-check) -├── spacetime/ # SpacetimeDB 相关(migration、seed) -├── generate/ # 代码生成(scaffold、proto、types) -└── loadtest/ # 压测脚本(k6 配置及辅助) -``` - -2. 为每个子目录添加 README.md,说明各脚本用途和调用方式 -3. 将重复逻辑抽取为共享函数库 - -**预期收益** -- 脚本查找效率提升 60%+ -- 降低脚本重复概率 -- 便于 CI Pipeline 直接引用标准化路径 - ---- - -### 问题 6:前端路由系统缺乏统一的"玩法注册"机制 - -**现状** -`appRoutes.tsx` 中硬编码 `switch-case` 逻辑,每新增一种玩法需手动修改路由文件、入口组件、资源加载等多个位置。 - -**影响** -- 新增玩法的接入点分散,容易遗漏 -- 路由文件随玩法增多持续膨胀 -- 无法实现"按需注册"——即使某环境不包含某玩法,路由代码仍然存在 - -**改进方案** -1. 建立 `PlayTypeRegistry` 模式:每个玩法导出一个注册项对象,包含 `path`、`lazyComponent`、`preload` 等字段 -2. `resolveAppRoute()` 改为动态聚合所有注册项,替代硬编码 switch-case -3. 支持环境级玩法开关:通过配置控制某环境启用哪些玩法,路由系统自动忽略未启用的 - -**预期收益** -- 新增玩法零侵入路由系统,只需在玩法目录内添加注册文件 -- 路由文件体积与玩法数量解耦 -- 灰度发布和 A/B 测试变得可能 - ---- - -### 问题 7:前端缺少统一的状态管理层 - -**现状** -前端状态管理依赖 React hooks + props drilling + services 层手动管理。未使用任何状态管理库(如 Zustand、Jotai、Redux)。 - -**影响** -- 全局状态(用户认证、会话、通知)通过多层 props 传递,组件耦合度高 -- 跨页面状态无法优雅共享 -- 状态变更难以追踪和调试 - -**改进方案** -1. 引入 Zustand(轻量、无 boilerplate、TS 友好)管理全局状态: - - `useAuthStore`:认证状态 - - `useSessionStore`:当前会话/游戏状态 - - `useNotificationStore`:全局通知 -2. 玩法内状态继续使用 React hooks + `useReducer`,保持局部自治 -3. 全局 store 与玩法内 state 通过事件总线松耦合通信 - -**预期收益** -- props drilling 层级从 5+ 层降至 1-2 层 -- 全局状态可追溯,支持 Redux DevTools 调试 -- 跨玩法状态共享(如用户余额、道具)变得自然 - ---- - -### 问题 8:shared-contracts 的实际复用程度待验证 - -**现状** -前后端通过 `packages/shared` 共享 DTO 类型定义,但依赖手动同步 TypeScript 类型。可能存在前后端契约不一致但编译期无法检出的情况。 - -**影响** -- 后端修改 DTO 字段后,前端可能遗漏更新导致运行时错误 -- 手动同步耗时且易出错 -- Code Review 时难以判断契约一致性 - -**改进方案** -1. 引入 `ts-rs`:从 Rust 结构体自动生成 TypeScript 类型定义 -2. 将生成步骤集成到 CI Pipeline: - - 每次 Rust PR 触发 `ts-rs` 重新生成 TS 类型 - - 对比生成的类型与仓库中的类型是否一致,不一致则 CI 失败 -3. 长期考虑引入 Protobuf / OpenAPI 作为跨语言契约的单一事实来源 - -**预期收益** -- 前后端契约不一致导致的线上 bug 减少 95%+ -- 手动同步工作量归零 -- PR Review 时契约一致性问题自动拦截 - ---- - -## 六、改进优先级路线图 - -| 优先级 | 改进项 | 涉及层 | 建议时间 | 预期收益 | -|---|---|---|---|---| -| **P0** | 统一前端 services/hooks/components 职责边界 | 前端 | 第 1-2 周 | 降低认知成本,提升可测试性 | -| **P1** | 建立 PlayType 注册机制 | 前端 | 第 2-3 周 | 新增玩法零侵入路由 | -| **P1** | 评估 module-* 合并方案并执行 | 后端 | 第 3-4 周 | 减少编译时间 15%-20% | -| **P1** | 引入 Zustand 全局状态管理 | 前端 | 第 4-5 周 | 改善状态追踪与跨组件共享 | -| **P2** | 清理 scripts/ 目录结构 | 工程 | 第 5-6 周 | 提高可发现性 | -| **P2** | 前端玩法统一迁移至 DDD 结构 | 前端 | 第 5-8 周 | 架构一致性 100% | -| **P2** | env 配置收敛 | 工程 | 第 6-8 周 | 减少部署配置事故 | -| **P3** | 前后端共享 DTO 自动化(ts-rs) | 全栈 | 第 6-8 周 | 消除契约不一致风险 | -| **P3** | CI 分层约束检查(cargo-deny) | 后端 | 第 8-10 周 | 循环依赖归零 | - -> **说明**:P0 为阻塞项,必须最先完成。P1 项可部分并行推进(PlayType 注册与 module 合并互不依赖)。P2/P3 为优化项,可在日常迭代中穿插推进。 - ---- - -## 七、架构健康度评分卡 - -| 维度 | 评分 | 当前状态 | 目标状态 | -|---|---|---|---| -| **分层清晰度** | ★★★★☆ | 后端分层严格,前端分层存在不一致 | ★★★★★ 前后端均严格分层 | -| **模块化程度** | ★★★★☆ | 后端 35 crate 粒度偏细,前端结构化较好 | ★★★★☆ 后端精简至 25 crate | -| **可扩展性** | ★★★★★ | 玩法模板模式使新增玩法成本低 | ★★★★★ 维持 | -| **代码复用** | ★★★☆☆ | shared 层作用有限,services 层有重复 | ★★★★☆ DDD 统一后 domain 可复用 | -| **DevOps 成熟度** | ★★★★★ | Docker + k6 + OTel + Jenkins 覆盖完整 | ★★★★★ 维持 | -| **文档完备性** | ★★★★★ | docs/ 分类清晰,基线文档齐全 | ★★★★★ 维持 | -| **技术债务管控** | ★★★★☆ | 有明确的"历史残留"标记和废弃策略 | ★★★★★ 增加自动化检测 | - -**综合评级:A-(优秀,存在可优化空间)** - ---- - -## 八、附录:代码规模统计 - -| 维度 | 数量 | -|---|---| -| **前端 TypeScript/TSX 文件** | ~823 个 | -| **后端 Rust 源文件** | ~1532 个 | -| **后端 Crate 数量** | 35 个 | -| **核心玩法类型** | 10+ 种 | -| **scripts/ 脚本数量** | 42 个 | -| **根目录 env 文件** | 4 个 + deploy 下多个 | - -### 模块规模明细(后端) - -| Crate | 职责 | 建议 | -|---|---|---| -| `api-server` | Axum HTTP 门面,路由聚合 | 保持 | -| `platform-*` (auth/llm/image/oss/speech/agent) | 平台级跨玩法能力 | 保持 | -| `module-puzzle` | 拼图玩法 | 作为 DDD 迁移样板 | -| `module-visual-novel` | 视觉小说 | 后续迁移 | -| `module-match3d` | Match3D 三消 | 后续迁移 | -| `module-bark-battle` | 犬吠对战 | 已对接前端 DDD | -| `module-big-fish` | Big Fish | 后续迁移 | -| `module-runtime*` (3 crates) | 通用运行时 | **建议合并为单 crate** | -| `module-combat / npc / inventory` | 战斗系统 | **建议合并** | -| `spacetime-module` + `spacetime-client` | SpacetimeDB 接入 | 保持 | -| `shared-contracts / kernel / logging` | 共享基础设施 | 保持 | - ---- - -> **文档结束** -> 本计划书由 Genarrative 架构分析报告衍生,所有改进项均基于对当前项目代码库的实际分析。执行过程中如遇阻力或新发现,应及时更新本计划书并同步相关方。 \ No newline at end of file diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index 134f60bc4..4ffd04577 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -1,4 +1,20 @@ # 决策记录 +> 用途:记录已经确认、会影响后续开发的长期技术/产品/协作决策。短期讨论不要写在这里。 +> 当前口径:历史条目的旧路径、旧版本和已退役对象只用于追溯,不构成现行实现依据;如与当前代码或 `docs/README.md` 冲突,以当前代码和最新专题文档为准。 + +## 记录格式 + +```md +## YYYY-MM-DD 决策标题 + +- 背景:为什么需要这个决策 +- 决策:最终决定是什么 +- 影响范围:涉及哪些模块/文档/流程 +- 验证方式:如何确认决策仍有效 +- 关联文档:相关 PRD、技术文档、提交或 Issue +``` + +--- ## 2026-08-24 AGC Direct 媒体能力只通过客户端语义工具开放 @@ -688,7015 +704,6 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在 - 边界:不修改 `game-creator-resource-layout.v1`、布局 Rust 持久层、manifest、api-server 或 SpacetimeDB;type 模式不等待资源图且继续保留全部已有坐标。图失败只降级初始化一次,项目或 mode 切换后旧图结果必须丢弃。 - 验证:延迟图 Promise 证明终态前零布局读取/写入,手动位置保持且自动位置按最终深度协调;4096 张真实卡片连续拖动证明非拖动卡片零重渲染、静态 SVG 不重建、Observer 单实例,并以 Chromium p95 `<16.7ms` 和零 `>50ms` long task 验收。 -> 用途:记录已经确认、会影响后续开发的长期技术/产品/协作决策。短期讨论不要写在这里。 - -## 记录格式 - -```md -## YYYY-MM-DD 决策标题 - -- 背景:为什么需要这个决策 -- 决策:最终决定是什么 -- 影响范围:涉及哪些模块/文档/流程 -- 验证方式:如何确认决策仍有效 -- 关联文档:相关 PRD、技术文档、提交或 Issue -``` - ---- - - - -- 背景:用户要求把已有美术接入当前俄罗斯方块时,Runtime 在 Supervisor 首次 Provider turn 之前按关键词重置 Graph、选择是否复用美术并自动调度 child;Supervisor 没有固定快车道计划时又直接 `fixed-task-graph-stalled`。结果是模型没有理解和决策机会,`art-asset-plan` 在已有资产与 baseline 门互相冲突时重复空规划直至耗尽预算。 -- 验证方式:覆盖决策前零 child、用户原句只产生 hint、持久 intent 后只启动主 Agent、主 Agent `asset.list` 前零美术委派、完整复用零生成、精确缺口单 child、回执恢复同一主 Run、child 写入范围与当前 revision 的接入/静态 smoke/双视口试玩完成门,以及旧 root/错误 binding/fingerprint/缺口/重复 route 失败关闭。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`、`docs/project-memory/shared-memory/pitfalls.md`。 - ---- - -## 2026-08-06 AGC 根长任务启动与终态失败采用 Runtime 公开消息硬门 - -- 背景:AGC 已有模型 final-reply、Runtime `eventId/publicText` 和进度卡,但根任务“已入队”没有后端持久公开回执;失败消息又散落在 main loop 多个 `let _ = append conversation` 分支。Provider 或 Runtime 在首条公开事件前失败时可能零消息,同一次失败也可能被 `turn.failed` 和 conversation 重复播报。 -- 恢复补充(以本条为准):`preparing` 只要同 run 的用户消息或 accepted 任一已完整持久即属可恢复;preflight 不改写业务文件,resume 才在 Agent 锁内补写 accepted 并入队。用户消息或 accepted conversation 已存在而审计补写失败不得把任务改判为启动失败。根终态首次公开写入遇到瞬时失败时,完成终态投影后必须用同 message ID 再幂等写一次。带 parent 的 Supervisor receipt / isolated-join 续跑只保留一份 Runtime 公开终态,不再追加 Session 重复消息;`runtime-task-*` 与 `runtime-public-status-*` 共享同 run 的不透明关联摘要,多个同秒任务在 UI 中按实际 run 关联的 `user -> accepted -> terminal` 交错排序。 -- 验证方式:覆盖 `preparing -> accepted -> pending` 顺序与崩溃恢复、启动确认幂等、启动确认无法持久化时任务零执行、公开状态不进入实际 Agent prompt、状态文件写入本身失败时仍先产生公开失败、根终态事件不重复进聊天、专业 Agent 启动事件仍可见、普通项目消息不被误标 Runtime-owned,并运行 Runtime 定向 Rust、AppSurface、模型测试、typecheck、编码和 diff 门禁。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`、`docs/project-memory/shared-memory/pitfalls.md`。 - ---- - - - -- 背景:ready scheduler 已为当前根 Run 持久化并启动 `code-prototype`,但并发 hydration 持有的旧 manifest 快照随后把该节点从 running 覆盖回 pending。父 Run 只读取 manifest 时会在 child 仍运行的情况下误判固定 Graph 已停滞并先行失败;child 完成门又因 pending 连续拒绝真实交付,最终耗尽 loop。 -- 失败关闭:GUI/CLI、旧父 Run child、终态 child、错误/伪造绑定、非确定性 runId、WaitingForConfirmation、WaitingForUserInput 和 needs-reconciliation 都不得借用该容忍;创建更新的根 Run 后,旧 child 立即失去父 DAG 活性与 pending 完成资格。 -- 玩法连续性:普通美术措辞不再触发历史玩法类型回溯;只有正式 failed continuation 继承原完成合同,纯“继续”沿用现有 continuation 识别边界。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/pitfalls.md`。 - ---- - -## 2026-08-05 增量接入既有美术时复用已验收 Graph 节点 - - -- 禁止替代方案:不得增加 loop 次数掩盖冲突,不得递增虚构的产物版本号,不得覆盖 art manifest 扩展字段,也不得重放历史图片生成 action。 -- 验证方式:回归必须证明明确复用时两项美术节点保持 completed、父完成门不再报告 art manifest baseline 未变化、俄罗斯方块场景保持 `tetris-v1`;删除任一切片后豁免立即失效。另以普通新目标和“全新美术”请求证明旧美术不能被认领。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/pitfalls.md`。 - ---- - -## 2026-08-05 专业 Agent ready-task 必须先确认 durable start 再异步执行 - -- 背景:AI 游戏创作首波 `design-director / art-director / code-director` 已全部写入 queued 与 scheduled,但 scheduler 把 per-Agent 执行锁直接移交 fire-and-forget Tokio future 后就返回成功;其中一个 child 未首次 poll 时会永久停在 `pending / queued`,而 recovery 又因执行锁仍被该 future 持有而无法接管。Runner heartbeat 与进程均正常,单靠“进程存活 / 锁已移交 / scheduled 已写”不能证明任务开始。 -- 决策:在实际持有执行权的 Runner/进程内,ready scheduler 必须先释放项目写锁,再同步完成 child 的 `pending -> running`、`turn.started` 和 started journal,随后才把已经启动的 state 与执行锁交给已确认开始轮询的独立 execution worker。同步启动或 worker 接管失败时,必须在仍持有 per-Agent 执行锁期间依次把 child 落为 failed、把 manifest Graph 节点投影为 failed,再释放锁并向 parent 返回调度错误;`autonomous_ready_task.scheduled` 仅是诊断审计,写入失败不得阻断 durable child 启动。只负责投递的 external client 继续释放本地锁并 wake External Runner,不在客户端冒充执行。 -- 可观测性:用户界面的“疑似停滞”只是 Runtime 活跃度投影,不改写正式业务状态。`startedAt` 由新 Run 的 durable queued/start 时间写入,旧 Run 从完整 task journal 的同一 `sessionId + runId` 最早记录恢复;从最新 task record 构造的 fallback state 必须保持 `startedAt=0`,不能把最近进度或终态时间冒充开始时间。运行态超过 5 分钟没有父 Run 或当前关联专业 Agent 的新事件时提示静默时长;等待用户、等待确认、Provider retry、视觉资产、进程会话、pausing 和 paused 均排除。父 Run terminal 后持续时间只冻结在父 Run 自身最后活动,关联 child 的晚到收口事件不能继续增加父 Run 时长。 -- 对账取消续跑:ready-task 的未知工具结果仍禁止自动重放;人工核对并取消旧 child 后保留 cancel tombstone,旧 child 与旧父 Run 都按真实 cancelled/failed 终态收口。后续同 Session、同 source、同有效任务语义的 Supervisor continuation 建立新完成合同时,只把 manifest 中能由历史 `needs-reconciliation -> cancelled` child 与 tombstone 共同证明的对应 failed 节点恢复为 pending,并生成全新 child Run;manifest 读取、failed 节点筛选、每任务一次的 child journal 索引、证据重验和最终写回必须位于同一项目写锁域。较新的无 child 父 Run 只有在 durable root journal 明确记录为“固定 Graph 在调度前已无法推进”时才能跨过;普通失败、scheduler 持久化前失败、无 tombstone、无 reconciliation 历史或不同任务语义均不得借用更老凭证隐式重试,也不得把旧 action、observation 或 child 伪装为 completed。 -- 完成门性能边界:Canvas 视觉验收在源码同时没有 `import` 与 `export` 关键字时不运行模块依赖分析,必须保留纯 `export ... from` / `export * from` 重导出依赖;当前脚本既不含目标资产文件名、也不含任一已绑定 DOM 图片元素 ID,且对 JavaScript `\\xNN`、`\\uNNNN`、`\\u{...}` 等转义做候选解码后仍不含二者时,不运行完整 Canvas 数据流与函数可达性分析。转义解码不确定时必须保守进入 parser,以保留 computed `src` 和转义 DOM 方法名;词法预检不能把命中当作通过,存在候选时仍执行原 parser、semantic binding、解码后的属性/StringLiteral 路径、可达性与目标 Canvas 检查。 -- 影响范围:AI 游戏创作 `runtime_driver/task_start.rs`、`task_queue.rs`、自主构建 continuation 合同、Supervisor 进度卡与相应 Rust/AppSurface 回归;不改变 manifest DAG、Agent catalog、Provider 路由或项目产物合同。 -- 验证方式:不预占 child locks,真实一次调度三项首波任务,并在有界时间内证明每个逻辑 Run 至少写入 running/`turn.started`;重复调度不得新增逻辑 Run。前端固定时钟覆盖正常运行、子 Agent 新活动、疑似停滞、各类合法等待与 terminal 冻结。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/pitfalls.md`。 - -## 2026-07-31 图集切片按需编码并批量确认持久化 - -- 背景:`2026-07-29 图集切片必须受前置容量和有界 CPU 保护` 收口了连通域数量与 CPU 并发,但切片仍在一次循环里全部裁剪并编码,最多 64 份 PNG 字节连同整张 RGBA 同时驻留内存;持久化又按切片逐个调用 procedure,N 片至少 2N 次写入外加一次 cohort 完成,任一片失败都会留下已确认的部分记录。手动拆分入口另有一处重复鉴权:`get_editor_project` 已经取回并定位了来源资源,随后仍走 `parse_editor_reference_image` 按注册 ID 再解析一次,触发全账号项目与素材库扫描。 -- 编码与内存决策:`platform-image` 把切片拆成 `prepare` 与 `encode` 两步,`prepare` 只计算带 padding 的裁剪边界并持有 `Arc`,`encode(index)` 被调用时才裁剪并编码单片。裁剪阶段累计 padding 后像素,超过调用方传入的上限即在任何编码前返回 `TotalCropPixelLimitExceeded`;api-server 传 `EDITOR_ICON_SPRITESHEET_MAX_TOTAL_CROP_PIXELS = EDITOR_ICON_SPRITESHEET_MAX_PIXELS * 4`(`16777216` 像素),映射为 `422` 与 `crop-pixel-limit-exceeded`。编码与上传由 `buffer_unordered(EDITOR_ICON_SPRITESHEET_UPLOAD_MAX_CONCURRENCY)`(`2`)串起,同时最多两片 PNG 在内存中。 -- 准入决策:新增独立于既有 CPU 信号量的 `EDITOR_ICON_SPRITESHEET_MEMORY_LIMITER`(`EDITOR_ICON_SPRITESHEET_MEMORY_MAX_CONCURRENCY = 2`)。手动拆分在创建下载客户端和发起下载**之前**取得该许可,许可覆盖「下载 → prepare → 逐片编码 → 逐片上传」整段,在进入 SpacetimeDB 批量调用前显式释放,避免数据库慢调用继续占用整张 RGBA。门限不可用返回 `503`、等待超预算返回 `504`,两者共用既有 `slice-processing-timeout` code。自动生成路径复用同一许可,但其源图此前已在内存中,该许可只保护解码与连通域阶段,不覆盖下载。 -- 持久化决策:新增 procedure `persist_editor_spritesheet_slice_batch_and_return`,在单个事务内依次确认每片的 asset object、可选项目资源、可选账号素材,并在存在 `group_task_id` 时一并完成 cohort;每次拆分请求只调用一次。批次上限 `EDITOR_SPRITESHEET_SLICE_BATCH_MAX_ITEMS = 64`,写入前校验数量与 `expected_asset_count` 一致、批内 `assetObjectId / objectKey / resourceId / assetId` 不重复、`source_resource_id` 指向的既有资源存在且同 owner 同 project;需要完成 cohort 的批次必须每项都创建素材。切片记录 ID 由 `(ownerUserId, taskId, 切片序号)` 经 SHA-256 确定性派生,重放得到相同 ID,且只有既有记录与新输入逐字段一致时才幂等复用,否则报幂等键冲突。 -- 鉴权决策:手动拆分不再调用 `parse_editor_reference_image`,直接用已随 owner-scoped 项目读取取得的 `source_resource` 取 objectKey,典型路径的 SpacetimeDB 调用从 3 次降为 1 次。作为替代,新增显式三重断言——项目属于当前 owner、资源属于当前 owner、资源属于当前 project——任一不符返回 `403`。结构断言禁止该区间再出现 `parse_editor_reference_image` 或 `list_editor_projects`。 -- 传输边界:新增 `build_editor_spritesheet_http_client(connect, request)`,下载与上传共用同一组常量 `EDITOR_ICON_SPRITESHEET_UPLOAD_CONNECT_TIMEOUT = 10s`、`EDITOR_ICON_SPRITESHEET_UPLOAD_REQUEST_TIMEOUT = 60s`。 -- 影响范围:`server-rs/crates/platform-image/src/generated_asset_sheets/`、`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/spacetime-module/src/editor_project_storage.rs`、`server-rs/crates/spacetime-client/src/editor_project.rs` 及生成的 module bindings;图标图集手动拆分与自动拆分链路。新增 SpacetimeDB procedure 与输入输出类型,需要重新生成绑定。 -- 验证方式:`platform-image` 覆盖 prepare 不编码且 `Send + Sync`、并发编码多个 index 结果不变、累计裁剪像素在编码前拒绝;`api-server` 覆盖切片记录 ID 稳定且按 owner / index 分区、自动路径保留处理超时告警码、上传超时释放内存许可;`spacetime-module` 覆盖批次校验的完整 cohort、重复 objectKey、来源资源同 owner 同 project、部分 cohort 拒绝与重放只在内容一致时复用。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、本文件 `2026-07-29 图集切片必须受前置容量和有界 CPU 保护`。 -- 补记说明:本条为事后补写,记录提交 `cf1a02312` 已落地的行为,不改变其任何决策。 - -## 2026-07-31 AI 游戏创作资源依赖图采用 Rust 只读拓扑与前端派生 SVG - -> 状态:其中资源卡 Pointer Move 拖动预览与局部更新验收已由 2026-08-03 mentor 最新决定暂缓;只读拓扑、SVG 派生展示、搜索与选择高亮合同继续生效。 - -- 背景:资源画布已有 dependency / type 双模式坐标与本地 CAS sidecar,但 dependency 模式尚未把当前 manifest 中可证明的资源引用和任务流转可视化;关系图不能反向污染布局持久化或建立第二套资源真相。 -- 决策:dependency 模式由 Tauri Rust 只读命令从当前 manifest、资源卡身份和有界 `.agent/agent.db` 审计构建稳定 `ProjectResourceGraph` read model,前端只归一化 DTO、测量卡片坐标并用原生 SVG 渲染。资产 `source.referenceResourceIds` 只在唯一匹配另一资产 `source.resourceId` 后形成橙色实线;任务依赖按任务对聚合,禁止资源笛卡尔积。本条最初把聚合任务流绘制为灰色虚线主线与分支,该显示口径已由 2026-08-10 最新决定替代为只参与布局、不进入 SVG。Rust 以迭代式强连通分量分析识别资源环和完整任务 DAG 环,并返回资源局部连接索引。 -- 任务身份:External Editor 响应中的 `source.taskId` 是平台生成任务 ID,不等于本地 manifest task ID,禁止据此分配 producer。画布资产只接受 `agent.runtime.canvas.asset_generate` 审计中经当前 manifest task 校验的 `assetId -> agentId`;证据缺失、冲突或已超出有界读取窗口时不生成对应 task flow。任务产物与 Agent 回执继续使用自身已有的 manifest task 身份。 -- 生命周期与边界:Pointer Move 先用 `requestAnimationFrame` 合帧;基础 positions 与拖动预览分离,SVG 静态拓扑保持复用,每帧只按局部索引更新拖动资源关联的 reference edge 和 task flow。`ResizeObserver` 在单个图层生命周期只创建一次。type 模式不挂载图层;切换 mode、项目或卸载工作台时销毁 SVG、Observer 和窗口监听。SVG 统一 `pointer-events: none`;path、marker、图结构和 section 原点从不持久化。 -- 数据边界:本切片只新增 Tauri Rust 只读 read model,不修改 layout sidecar、`resourceCanvasLayoutModel.ts`、manifest、api-server、SpacetimeDB schema 或生成绑定,也不引入第三方图表库。dependency section 只在显示层额外预留 `64px` 右侧视觉 gutter,卡片坐标和持久化布局不变。 -- 影响范围:`apps/ai-game-creator-shell` 的 Tauri project read model/command、项目开发资源投影、依赖图 DTO、SVG overlay、样式与前后端测试,以及工作台 PRD 和客户端实施计划。 -- 验证方式:Rust 定向测试覆盖真实 producer 映射、拒绝复用外部 `taskId`、证据缺失、去重、无效 ID、完整任务环、4096 任务链与聚合复杂度;前端模型和 SVG 测试覆盖 DTO 防御过滤、局部上下游、可见资源自引用闭环、搜索、高亮、单帧局部 path 更新和稳定 Observer;AppSurface 覆盖生产数据形状、两种边、type 模式卸载和项目切换销毁,并运行 shell typecheck、编码检查与 `git diff --check`。 -- 关联文档:`docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - ---- - -## 2026-08-04 画布生成输入 V2 原地收紧并统一回落当前默认值 - -- 背景:画布 `generationInputs.version=2` 从持久化 JSON 恢复时只校验通用结构,未知、非法、已下线或与当前模型能力不兼容的模型、比例、尺寸、清晰度、声音、时长及角色动作档位仍可通过 TypeScript 断言进入 UI 和再次提交。前端已隐藏但后端仍兼容的历史 Veo 也不再属于当前可选模型。 -- 决策:不新增 V3,不迁移数据库,不保留旧值再次执行;V2 在读取时原地按 `action` 解码。所有已存在但未知、非法、已下线或与当前模型不兼容的参数统一回落到该 action 的当前默认值,历史 Veo 同样回落到当前默认视频模型。图片比例 / 尺寸按回落后的模型联动校验,视频参数按当前模型能力校验,角色动作 `frameCount / durationSeconds` 按完整档位成对校验。发生回落时必须向用户显示“部分原生成参数已使用当前默认值”告警;再次提交只使用规范结果并保存为仍是 `version: 2` 的新快照。缺失字段继续由当前 action 默认值补齐,不为此单独升级版本。 -- 实现边界:单一 action 级 runtime decoder 是持久化 V2 的读取真相,恢复 UI、改造入口和再次提交链不得各自解释原始 JSON;canonical 选项从当前编辑器模型 / 参数注册表派生,不新增平行旧模型清单。通用结构不合法时整份配方不支持改造;必需 `source` 缺失时仍按 action capability 保留改造按钮,点击后在恢复路径拒绝改造,不用默认值伪造引用;运行期来源变化时同样必须复检并拒绝。该策略只改变画布配方的运行时恢复和后续重存,不修改 SpacetimeDB schema、BFF DTO 或已有资产原始 JSON。 -- 影响范围:`ImageCanvasGenerationModel` 的 V2 decoder、`ImageCanvasGenerationDialogModel` 的恢复入口、`useImageCanvasGenerationWorkflow` 的回落告警、生成输入回归测试和编辑器 Lovart 统一方案。 -- 验证方式:fixture 覆盖当前合法 V2、历史 Veo、未知模型、模型不兼容尺寸、非法视频参数、非法音效参数、角色动作错配档位和缺失必需来源;断言 UI、价格与提交使用规范值,回落显示告警,再次生成仍保存 V2。运行图片画布定向 Vitest、`npm run typecheck`、定向 ESLint、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`、`review.txt`。 - ---- - -## 2026-07-30 抠图实际后端作为 generationInputs 顶层内部元数据保存 - -- 背景:角色、图标图集和 UI 图集抠图派生资产需要保留最终实际执行的处理后端,供后台诊断 BgFilter、阿里云通用抠图和本地键色的降级结果;把抠图模型写成 `generationInputs.fields` 的“处理模型”会进入图片信息,与用户可见输入快照语义冲突,而覆盖正式资产 `model` 又会丢失源生图模型。 -- 决策:继续使用现有 `generation_inputs_json` JSON 包络,不修改 SpacetimeDB schema。`fields` / `references` 只保存用户可见生成输入;仿照顶层 `screenColorHex`,抠图派生资产在顶层写入 `mattingProvider` / `mattingModel`。BgFilter 记录本次实际 `seg_model`;阿里云记录 `Aliyun Matting / segment-common-image`;本地键色记录 `Genarrative Local / screen-color-keying`。三条链路的正式资产 `model` 继续继承源生图模型,图片信息不读取顶层内部字段。`screenColorHex`、`mattingProvider`、`mattingModel` 和素材顶层 `provider` 属于内部执行信息:普通用户(包括素材 owner)、精选提交 / 点赞响应与匿名公开读取统一省略,只有后台管理和服务端 raw 审计读取原始值;历史数据不迁移,在 User/Public mapper 边界清理。角色动作逐帧可能混用多个 fallback,本次不把单帧结果提升为整组动画模型。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs` 的抠图结果和角色 / 图标 / UI 派生资产持久化、图片信息兼容测试、后端数据契约与图片画布 MVP 文档;不修改前端生产展示逻辑、请求 DTO、SpacetimeDB 表、迁移或生成绑定。 -- 验证方式:后端单测覆盖三种实际结果映射、顶层元数据不改写 `fields`,结构断言覆盖三条派生资产持久化链路仍保留源生图模型;User/Public mapper 测试同时证明素材 owner、精选提交 / 点赞与匿名响应均省略 `provider` 和三个内部键,Admin raw payload 保留原始值;前端测试覆盖顶层字段不在图片信息或搜索索引出现。运行 `cargo test -p api-server editor_project::tests --manifest-path server-rs/Cargo.toml`、图片信息定向前端测试、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run typecheck`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - ---- - -## 2026-07-31 修正抠图内部元数据的普通用户读取边界 - -- 背景:2026-07-30 的记录误把素材 owner 与后台审计并列为原始抠图执行信息的读取方。owner 是普通用户,前端不展示字段不能阻止其从项目资源、素材库、精选提交 / 点赞回包、画布布局或任务完成响应的网络 payload 读取 BgFilter、阿里云、本地键色、具体分割模型或背景色。 -- 决策:本条取代 2026-07-30 决策中“素材 owner、精选提交响应仍可读取原始值”的表述。普通用户(包括素材 owner)读取时必须过滤素材顶层 `provider`、内部处理 `model`,以及 `generationInputs` 顶层 `screenColorHex`、`mattingProvider`、`mattingModel`;正常用户可见生成 `model` 和其他合法功能性顶层字段(例如 `characterAnimation`)保持不变。匿名公开素材 payload 不包含整个 `generationInputs`。User/Owner mapper 完成普通用户清理,public mapper 在其基础上移除该 owner-only 配方字段;后台管理与服务端审计继续使用 raw mapper 和持久化原值。历史数据不迁移,统一在读取边界清理。 -- 入站与持久化:客户端提交的 `generationInputs` 不得伪造上述内部键,服务端在实际处理完成后才写入可信值。手动去背景的正式素材 `model` 必须继承经服务端验证的正常源生图模型;若来源或祖先链不存在正常模型则为 `null`,不得写入 `BgFilter complex` 等内部处理模型。内部抠图 provider / model 可继续持久化供后台审计,普通用户完成响应和用户可见错误文本均不得暴露它们;手动去背景与角色动作透明化失败在 Owner HTTP / 任务状态边界统一替换为稳定业务文案,原始错误只留在任务记录、tracing 和后台审计。 -- 影响范围:项目资源、素材库、精选提交 / 点赞、图片 / 图标 / 视频 / 音频 / 角色动画生成完成、Agent 紧凑结果和识别出的画布资源 / 图层快照的 User/Public mapper;手动去背景持久化和完成响应;External Editor API 创建素材 / 资源时的保留键入站清理;相应响应 / OpenAPI 契约、前端搜索 / 详情 / ZIP 过滤测试与后台 raw 审计测试。同源画布 BFF 的角色、图标和 UI 请求继续由前端自动提交默认 `segModel=birefnet`,后端继续校验并在缺失时回落默认值;该请求控制字段不进入 `generationInputs`、普通用户响应、搜索、详情、导出或错误详情。角色动作的 `seg_model` 继续由后端固定。不修改 SpacetimeDB schema、迁移或 bindings。 -- 验证方式:Owner 响应覆盖无 `provider`、无内部 `model`、无三个内部 `generationInputs` 键,同时保留正常 `model` 与 `characterAnimation`;匿名公开素材响应完全不含 `generationInputs`;Admin raw payload 保持完整。覆盖历史 `BgFilter complex`、三类入站伪造键、手动去背景源模型回溯和用户错误文本过滤;运行 api-server 定向测试、前端定向测试、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run typecheck`、`npm run check:encoding` 与 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - ---- - -## 2026-07-31 接受外部 OpenAPI v1 的未版本化 breaking change - -- 背景:2026-07-31「修正抠图内部元数据的普通用户读取边界」把 OpenAPI 更新列为影响范围内的机械同步,但实际动作是从已发布的 `/api/external/v1` 契约中删除四个生成响应里原本 `required` 的 `provider`,另从 `EditorProjectResource` / `EditorAsset` 删除可选 `provider`,而 `info.version` 仍为 `1.0.0`、路径前缀未变。严格反序列化或由 OpenAPI 生成的调用方会在服务端上线瞬间直接失败,且不需要调用方做任何动作。脱敏目标本身成立,但契约处理方式当时没有单独定性。 -- 决策:确认这是 breaking change 而非文档同步,并接受本次不升版本、不提供兼容字段、不设弃用期。唯一依据是截至 2026-07-31 `external_api_key` 无属于外部第三方的存量调用方。该豁免不具一般性:API Key 由用户在个人中心自助发放,`/api/external/v1/openapi.json` 又是该批路由中唯一免鉴权端点,因此「无外部调用方」不是受控状态,出现非内部账号活跃密钥、对外公布契约或与外部团队联调后立即失效。今后删除响应字段、把字段移出 `required`、收窄类型或取值、改变字段语义、新增请求必填字段均视为 breaking,存量调用方出现后必须按兼容值、弃用期或 `/api/external/v2` 三选一处理,只更新 JSON 不构成合规变更流程。本次不追加代码改动。 -- 影响范围:`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md` 新增「版本与兼容策略」一节;`docs/openapi/genarrative-external-v1.openapi.json` 的 `info.description` 补充面向集成方的兼容性说明;`pitfalls.md` 记录「无调用方」不可当长期前提。不修改响应结构、请求 DTO、路由或 `external_editor_api.rs` 断言。 -- 验证方式:`info.version` 保持 `1.0.0` 且 JSON 仍可被 `serde_json` / `json.load` 解析;`external_editor_api.rs` 既有 openapi 断言继续通过。该断言只校验 schema 形状、不校验兼容性,因此通过不等于契约安全,判定仍以上述 breaking 清单为准。正式对外发放第一个外部密钥前需复核本条是否仍成立。 -- 关联文档:`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md`、`docs/openapi/genarrative-external-v1.openapi.json`、`docs/project-memory/shared-memory/pitfalls.md`。 - ---- - -## 2026-07-31 历史素材的内部处理模型不做回溯清理 - -- 背景:用户可见性过滤 `isEditorUserVisibleGenerationInputField` 的实现是标题精确匹配 `处理模型`,既不识别语义也不探测取值;服务端 User/Public mapper 只清理 `generationInputs` 顶层的 `screenColorHex` / `mattingProvider` / `mattingModel`,不遍历 `fields` 数组。历史资产中存在标题为「抠图模型」、取值形如 `动漫风格 anime-seg` 的字段,两侧都拦不住,因此仍会出现在图片信息弹窗和画布 ZIP 导出元数据中。MVP 接入方案原文「前端同时过滤历史项目中已持久化的处理模型字段」读起来是全覆盖保证,与实际实现和历史数据存在显式冲突。 -- 决策:维持产品决策——历史素材不迁移、不回溯清理,本次不扩大过滤范围,不修改 `isEditorUserVisibleGenerationInputField`。改为收敛文档口径:明确过滤是标题精确匹配而非语义识别,明确「抠图模型」为已知例外且属于接受状态,不得据此判定为缺陷。约束只对新写入生效,新产生的 `generationInputs.fields` 不得再写入任何内部处理模型字段,无论标题为何。若将来决定扩大过滤范围,必须先对生产 `generation_inputs_json` 做标题去重查询枚举真实存在的历史标题,不得仅凭测试夹具推断清单。 -- 影响范围:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md` 收敛该句表述并补充已知例外;`pitfalls.md` 记录过滤口径与排查方式。不修改前端过滤实现、服务端 mapper、素材数据或导出结构。 -- 验证方式:图片信息弹窗与画布 ZIP 共用同一过滤口径,任何一侧改动必须同时覆盖另一侧;既有 `ImageCanvasMetadataModalView` 与 `ImageCanvasExportModel` 测试保持通过,不新增针对历史「抠图模型」的过滤断言,以免与本决策冲突。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/project-memory/shared-memory/pitfalls.md`。 - ---- - -## 2026-07-30 图片画布搜索不得索引内部模型和 Provider - -- 背景:素材和图层详情虽已把内部处理模型显示为 `-`,搜索仍索引原始 `model` 与 `provider`,导致 `BgFilter complex`、`segment-common-image`、`BgFilter` 或 `Aliyun Matting` 等隐藏信息可被查询命中,并出现“命中但无可见匹配字段”的异常体验。 -- 决策:素材与图层搜索只索引用户可见生成模型;统一复用 `isEditorInternalProcessingModel(...)` 排除内部处理模型,并完全排除 `provider`。该规则只约束前端临时搜索值,不删除或改写素材、图层及后端保存的原始审计字段;`gpt-image-2`、`audio1.0` 等正常模型继续支持搜索。 -- 影响范围:`ImageCanvasAssetLibraryModel.ts` 的素材与图层搜索值、图片画布素材 / 图层侧栏搜索和对应前端架构文档;不改变持久化、详情展示、删除、移动或画布保存行为。 -- 验证方式:模型单测覆盖内部模型和 Provider 不命中、正常模型继续命中且原对象元数据不变;侧栏交互测试覆盖素材与图层两类入口。运行对应 Vitest、`npm run typecheck`、`npm run lint:eslint`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - ---- - -## 2026-07-31 每日免费泥点基础额度纳入后台钱包配置 - -- 背景:每日免费泥点已是独立余额桶,但基础发放量仍在运行时固定为 `20`,后台“账号配置”只能维护注册初始泥点,运营调整需要改代码。 -- 决策:在 `profile_wallet_config` 尾部追加带默认值 `20` 的 `daily_free_points_per_day`,与 `initial_mud_points` 共用 `/admin/api/profile/wallet-config` 和后台账号配置页一次读写。尚未初始化当日额度的用户立即使用最新值;已初始化用户的当日余额不追补、不回收,下一北京时间业务日首次触达时按最新配置重置。跨日退款可继续使当日 `granted_points` 高于基础额度,因此充值中心 `dailyFreeResetPoints` 必须显式投影配置值,不用当日已发放总额反推。 -- 迁移与边界:旧 SpacetimeDB 表行和旧迁移 JSON 均缺少新字段,自动迁移与 `migration.rs` 导入归一统一补 `20`;新字段只允许正整数。每日任务奖励、扣费桶顺序、退款归因和北京时间日切边界不变。 -- 影响范围:`module-runtime`、`spacetime-module`、`spacetime-client`、`shared-contracts`、`api-server`、`apps/admin-web`、SpacetimeDB 迁移与生成绑定。 -- 验证方式:后台页面与 API 定向测试、每日免费日切与迁移定向 Rust 测试、`npm run spacetime:generate -- --rust-only`、`npm run check:spacetime-schema`、`npm run admin-web:typecheck`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - ---- - -## 2026-07-31 发布前延期冷备份由独立 systemd 上传并补偿扫描 - -- 背景:Jenkins Stdb Publish 的 async 备份先生成 `uploadStatus=deferred` 的本地 tar.gz,再从 EXIT trap 用 `nohup` 启动上传。后台进程仍继承 Jenkins Cookie,作业结束时可被清理;旧 deferred manifest 也没有后续补偿扫描,导致 dev 的本地冷备份持续占满根盘。 -- 决策:`production-stdb-publish.sh` 只能用具名、`Type=exec`、`--collect` 的 `systemd-run` transient service 启动异步上传,禁止回退 `nohup`。独立服务执行 `database-backup-to-oss.mjs --upload-deferred-dir `,在同一备份锁内按文件名串行补传同库 `deferred/pending` 归档;目录外路径或 manifest/归档不匹配时失败关闭,缺失归档的历史 manifest 只报告不删除。 -- 清理边界:只有 archive 上传与 HEAD 验真、manifest sidecar 上传验真、baseline state 写入全部成功后,才按 `GENARRATIVE_DATABASE_BACKUP_KEEP_LOCAL` 删除精确的 archive 与 manifest。transient unit 未启动或上传失败时保留归档,由后续 publish 继续补偿;`files-history` timer 仍不负责清理这些 tar.gz。 -- 影响范围:`scripts/deploy/production-stdb-publish.sh`、`scripts/database-backup-to-oss.mjs`、生产运维门禁和本文档。 -- 验证方式:`npm run check:database-backup`、`npm run check:production-ops`、`npm run check:encoding`、`git diff --check`;dev 现场还必须确认 transient unit 不在 Jenkins session scope,旧 deferred 归档逐份变为 OSS 已验真对象后被删除,备份锁清空,核心服务与公开接口健康。 -- 关联文档:`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - ---- - -## 2026-07-31 画布 Agent 图片结果单击直接定位 - -- 背景:生成图片在对话中是静态缩略图,用户需要用更直接的方式回到对应画布图层;视频和音频仍有播放、拖动和音量等原生点击交互,不能共用该行为。 -- 决策:携带有效 `resourceId` 的 Agent 生成图片在普通单击时直接调用实例级 `ImageCanvasActionsContext.focusResource(resourceId)`;无 `resourceId` 的旧图片保持无动作。视频和音频的普通点击仍只操作播放器,三类媒体均保留右键菜单的“在画布中定位”。图片卡片本次不新增按钮语义或键盘 Tab 停靠,Enter / Space 不触发定位。 -- 影响范围:`ToolCallView`、消息气泡交互测试和画布 Agent 前端专题文档;不修改共享 DTO、后端 API、SpacetimeDB 或 viewport 动画语义。 -- 验证方式:覆盖有效图片单击、旧图片无动作、视频 / 音频单击无定位及三类媒体右键定位;运行前端定向测试、`npm run typecheck`、`npm run lint:eslint`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【编辑器】画布Agent对话面板-2026-07-03.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - ---- - -## 2026-07-30 画布 Agent 结果通过实例级 Action Context 刷新并从右键菜单定位资源 - -- 背景:画布 Agent 图片、视频和音频结果需要提供画布定位和结果完成后的工程刷新;若继续从舞台向面板、消息和工具结果逐层传 callback,会扩大现有 prop drilling,而把 callback 或瞬时命令放入全局 Zustand 又会引入多实例和卸载残留问题。直接把点击和定位语义附到生成媒体上还会让视频 / 音频的播放、暂停、拖动与音量操作误触发画布聚焦,并给原生媒体控件附加错误的定位标签。 -- 决策:`ImageCanvasEditorView` 提供实例级 `ImageCanvasActionsContext`,暴露 `focusResource(resourceId)` 与 `refreshCanvas()`;Agent 工具结果刷新、生成结果右键菜单和任务侧栏直接消费对应动作,不新增中间 props,也不扩展现有只保存 `projectId` 的 Zustand store。`refreshCanvas()` 统一重新读取当前工程快照并刷新素材库,任务列表入队后的立即失效继续保持独立。带有效 `resourceId` 的图片、视频和音频生成结果只在素材右键菜单显示“在画布中定位”,普通媒体卡片不声明按钮语义或 `tabIndex`,点击、Enter 和 Space 均不触发定位;视频和音频原生播放器只使用描述媒体自身的标签,不承载定位标签或点击处理。`focusResource(resourceId)` 命中当前图层后只按完整画布 viewport 播放固定 `420ms` ease-out fit 动画,不改变图层选择、工具、侧栏或 Agent 面板;普通 viewport 写入和用户交互可取消动画,reduced-motion 直接完成,缺失 ID 或图层时无动作。 -- 影响范围:图片画布 Action Context、viewport controls、Agent 结果媒体交互、前端测试和编辑器专题文档;不修改共享 DTO、后端 API 或 SpacetimeDB。 -- 验证方式:覆盖 Context 作用域、三类媒体普通点击无动作与右键菜单分发、原生媒体控件无定位标签、动画中间帧与终态、手动取消、reduced-motion,以及编辑器集成中选择态和面板保持不变;运行前端定向测试、`npm run typecheck`、`npm run lint:eslint`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【编辑器】画布Agent对话面板-2026-07-03.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/technical/【前端架构】图片画布编辑器前端拆分计划-2026-06-17.md`。 - ---- - -## 2026-07-29 图集切片必须受前置容量和有界 CPU 保护 - -- 背景:图标与 UI 图集的 alpha 连通域识别会在 async handler 上同步执行;原始连通域合并采用全量两两比较,`64` 个输出限制又晚于排序、裁剪和 PNG 编码。碎块或噪点图会放大 CPU 与内存成本,手动拆分、图标自动拆分和 UI 提取都受影响。另一方面,图标与 UI 的 Alpha 尺寸恢复、provider 原图回读或透明图解码失败此前只记日志,仍会把不可信透明图持久化并拆分。 -- 决策:`platform-image` 在每次 flood-fill 后累计所有原始连通域(包括随后过滤的噪点)并以 `4096` 为硬上限;合并只通过 `64px` 空间网格查询 `48px` 最大邻域内且满足辅助部件尺寸条件的候选,单网格最多登记 `256` 个组件、单 source 最多保留 `512` 个候选,拥挤时明确返回资源限制错误;调用方把固定 `maxOutputSlices=64` 传入 platform slicer,并在排序、裁剪和 PNG 编码前拒绝超限。三条入口统一走 2 路 semaphore、30 秒本地上界与请求绝对 deadline 共同保护的 `spawn_blocking`,permit 必须由 blocking 闭包持有。自动图标 / UI 超限以空切片和稳定 `sliceWarning` 完成,手动拆分返回 `422`,两者都不得产生任何切片 PUT、资源或画布切片;自动路径已成功的整张图集仍按既有契约保留。 -- source-only 收口:角色、图标和 UI 共用同一个 provider 原图收口 helper。BgFilter 最终失败、Alpha 比例漂移超过 `5%`、provider 原图修复性回读失败、Alpha 回贴失败或透明图完整解码失败时,只用已保存 provider 原图完成占位,返回 `completed + warning`;图标 / UI 固定 `iconImageSrcs=[]`、`sliceWarning=null`,不写透明图、不拆分。provider 原图本身无法解码时在首次持久化前失败,不再伪造 `512×512` 元数据。 -- 影响范围:`server-rs/crates/platform-image/src/generated_asset_sheets/`、`server-rs/crates/api-server/src/editor_project.rs`、图片画布图标与 UI 素材生成 / 手动拆分链路;不修改请求 DTO、扣费退款、SpacetimeDB schema 或成功路径多产物布局。 -- 验证方式:platform-image 覆盖大量独立 `4×4` 块、单像素噪点和 65 个有效输出;api-server 覆盖比例漂移、原图回读失败、截断透明 PNG、共享 source-only helper 无持久化副作用,以及三入口统一 bounded slicer。运行 `cargo test -p platform-image generated_asset_sheets --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server editor_project::tests --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【编辑器】画板图标素材生成入口设计-2026-06-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - ---- - -## 2026-07-29 像素规整降级必须复用交付尺寸守卫 - -- 背景:像素模式接入「角色带背景原图与透明图统一交付尺寸」后,删除了原先像素路径末尾的后置尺寸恢复。但像素规整的 best-effort 降级分支(预算耗尽、回读 provider 原图失败或超时、CPU permit 获取失败、worker 内 deadline、join 异常、worker 超时)都直接返回 BgFilter 原始输出并把尺寸错误置为 `None`,跳过了非像素路径已有的尺寸比对与 alpha 回贴。BgFilter 回图尺寸漂移是已知现象,叠加并发上限 2 导致的 permit 超时后,角色会绕过「改用已保存的同尺寸原图完成画布」的安全降级,角色和图标都可能持久化尺寸漂移的低分辨率透明图。 -- 决策:像素路径的每一条降级都必须经 `degrade_editor_pixel_art_to_postprocessed_with_dimension_guard` 收口,该守卫复用非像素路径的 `apply_editor_postprocessed_alpha_from_persisted_provider_source_or_original`:先做纯内存尺寸比对,与交付尺寸一致就原样返回且不产生额外 OSS GET;漂移才回读原图重贴 alpha;修复失败如实返回尺寸错误,由调用方按各自既有语义处理。由 provider 原图逐像素合成的 `rgba_source` fallback 尺寸天然正确,不再经守卫。像素路径函数因此需要显式接收交付宽高。 -- 生效范围(由同日后续决策补齐):像素路径继续保证不把 BgFilter 原始输出连同 `None` 尺寸错误交回调用方;角色、图标和 UI 拿到尺寸 / Alpha 错误后现已统一走 provider 原图 source-only 收口,不再持久化或拆分尺寸异常、比例异常或不可解码的透明图。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs` 的角色与图标像素规整降级路径;不改变成功路径、OSS PUT 次数、资源类型、画布项或前端契约,OSS GET 仍只在尺寸漂移时发生。 -- 验证方式:`pixel_art_degrade_paths_guard_postprocessed_delivery_dimensions` 结构断言固定"降级分支不得返回 `(postprocessed, None, …)`"与守卫的委托实现;运行 `cargo test -p api-server editor_project --manifest-path server-rs/Cargo.toml`、`npm run check:rustfmt`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:本文件「2026-07-29 角色带背景原图与透明图统一交付尺寸」与「2026-07-28 图片生成风格使用可扩展字段并以纯内存像素规整首发」。 -- 补充(同日):守卫的回读必须分两类处理。已取得 provider 原图的四条降级分支(permit 获取失败、worker 内 deadline、join 异常、worker 超时)改走纯内存守卫 `degrade_editor_pixel_art_with_provider_source`,零额外 GET;尚未取得原图的三条分支(进函数即预算耗尽、第一次回读失败、第一次回读超时)才走会回读的守卫。计数断言固定「回读守卫 3 处、内存守卫 4 处」,防止后续新增分支时误用回读版本。 -- OSS 回读口径(修正此前「最多增加一次 OSS GET」的措辞):约束是**不重复读取已经成功取得的对象**,而不是"整个请求至多一次 GET"。仅在尺寸漂移且尚未持有原图时才发起最多一次修复性回读,失败后不再重试;因此第一次回读失败或被像素预算掐断时,允许存在第二次、也是最后一次尝试——第一次超时往往并非 OSS 异常,而是被 30 秒像素预算切断,此时对象通常可正常读取,放弃修复反而会让角色更频繁地退化为原图单产物。 -- 回读上界:修复性回读必须始终有绝对 deadline。优先取外层 `request_deadline`,但它只在队列 worker 路径上有值——inline HTTP 请求的 `RequestContext` 默认 `external_call_deadline = None`,此时守卫自行以 `Instant::now() + EDITOR_PIXEL_ART_MAX_PROCESSING_DURATION` 重新计时派生上界,不得退化为无界 `download.await`。`apply_editor_postprocessed_alpha_from_persisted_provider_source_or_original` 的可选 `download_deadline` 只对像素守卫传值,非像素路径继续传 `None` 保持既有语义不变。结构断言固定守卫内必须同时出现 `request_deadline.unwrap_or_else(` 与 `EDITOR_PIXEL_ART_MAX_PROCESSING_DURATION`,防止兜底上界被移除后静默退回无界。 - ---- - -## 2026-07-29 角色带背景原图与透明图统一交付尺寸 - -- 背景:图片画布已将模型原生回图归一到统一业务像素矩阵,但角色分支为了保留 provider 原生分辨率,先持久化带背景原图,只在扣背后归一透明主图。因此同一个 1K 角色任务会同时给出模型原生大图和长边 `1024` 的透明图。 -- 决策:角色分支必须在持久化带纯色背景原图和调用 BgFilter 之前,先按统一业务像素矩阵执行一次尺寸归一;该原图和透明派生图始终使用同一实际像素尺寸,1K 的长边为 `1024`。若 provider 回图任意一边小于业务目标或比例偏差过大,仍禁止放大或大幅裁切;此时两张图一同保留 provider 实际尺寸并返回通用 `warning`,不允许只改透明图。BgFilter 回图尺寸漂移时只允许在宽高比偏差不超过 `5%` 时重采样 alpha 蒙版并回贴到该原图;蒙版比例超限、回贴失败或尺寸验证失败时必须改用原图单产物降级,不持久化尺寸或比例不一致的透明图。若尺寸降级和后处理降级同时发生,同一条 `warning.reason` 必须同时保留两个原因。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs` 的角色生成、原图持久化、BgFilter 输入、项目资源尺寸与画布图层 Resolution;不改变前端请求 DTO、扣费、素材类型或多产物布局。 -- 验证方式:后端定向测试覆盖角色全尺寸矩阵:`nanobanana2` 的 `0.5K / 1K / 2K` 和 `gpt-image-2` 的 `1K / 2K`,每档均覆盖 `1:1 / 4:3 / 3:2 / 2:3 / 9:16 / 16:9`,30 个组合全部构造大于目标尺寸的真实 PNG provider 回图并执行像素恢复,不只校验字符串映射;另覆盖欠尺寸禁止放大、比例超限、BgFilter 错比例 alpha 蒙版拒绝和组合告警。同时从函数调用顺序上固定“尺寸归一 → 持久化带背景原图 → BgFilter”。运行 `cargo test -p api-server editor_project --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - ---- - -## 2026-07-29 图标图集 BgFilter 开启 cross-check - -- 背景:图标 spritesheet 的透明化需要提高主体内部孔洞、轮廓和相邻小图标边缘的交叉校验质量。 -- 决策:生成图标素材的 BgFilter `background_mode=flat` 请求固定显式传 `cross_check=on`,与角色形象和角色动作逐帧去背一致;UI 设计图素材提取及手动 complex 去背景继续传 `off`。该参数仍属于后端内部供应商策略,不进入前端 DTO 或外部 OpenAPI。 -- 边界:不修改 BgFilter fallback、Alpha 回贴、默认关闭 despill、图标切片、OSS / 资源 / 画布持久化和任务告警语义。 -- 验证方式:运行 `cargo test -p api-server editor_canvas_screen_background_generation_uses_bgfilter_postprocess --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:rustfmt`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【编辑器】画板图标素材生成入口设计-2026-06-15.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - ---- - -## 2026-07-23 画布 Agent 工具生命周期统一经 object-safe trait 分派 - -- 背景:画布 Agent 八类工具的参数规范化、确认展示、计价与 worker payload、完成结果格式化和媒体投影分别在 `tool_args.rs`、`display_args.rs`、`api.rs`、`reconcile.rs` 重复按工具名分派;新增或调整工具时容易漏改其中一处。 -- 决策:api-server 以 object-safe `EditorAgentTool: ToolDyn` 取代仅承载计价的 `EditorAgentPricedTool`。trait 的所有动态方法统一接收 `serde_json::Value`;每个具体工具实现自行反序列化为真实 Args / 结果,`validate_args` 与 `format_execute_message` 显式转发到 `platform-editor-agent` 已有强类型实现,再把规范 Args、展示投影、job payload、完成文本或媒体引用擦除回公共类型。`editor_agent_tool(toolName, context)` 绑定当前 `EditorToolContext` 并作为唯一八分支工具名分派;规划、确认和回填不得再维护平行 switch。LLM builder 的工具注册列表保持独立显式维护。 -- 边界:不改变工具名、LLM schema、OSS 消息文档、`displayArgs`、模型定价、job kind / payload、dedupe key、worker、计费、完成消息或图片 / 视频 / 音频引用契约,不涉及前端、SpacetimeDB schema 或迁移。 -- 影响范围:`server-rs/crates/api-server/src/editor_agent` 的工具 trait、参数规范化、确认入队与终态回填,以及画布 Agent 专题文档。 -- 验证方式:覆盖八类 factory 与 dyn validation / pricing / display / job / formatter / media projection 的 api-server 定向测试,运行 `cargo test -p api-server --manifest-path server-rs/Cargo.toml editor_agent`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:rustfmt`、`npm run check:encoding` 和 `git diff --check`。 - ---- - -## 2026-07-28 AI 游戏创作资源画布布局使用本地双模式 CAS sidecar - -- 背景:项目开发工作台当前只在 React 会话内保存同分类资源的一维拖拽顺序,项目切换或客户端重启后重建默认排列;工作台 PRD 虽已给出二维位置字段,但缺少落盘路径、坐标系、Tauri API、CAS、异常与安全边界,仍不足以直接编码。 -- 决策:dependency 与 type 两套布局分别保存为项目内 `.agent/workbench/resource-layouts/dependency.json` 和 `type.json`,统一使用 `game-creator-resource-layout.v1`。`x / y` 是 section 内容 CSS 像素,revision 从缺文件时的 `0` 单调递增;新资源首次默认放置,任何已有坐标不因排序、筛选、模式切换或 resize 被自动覆盖。type 默认布局固定按 `subtype -> mediaType -> label -> id` 排序,manifest 资产使用 `asset.kind`,任务产物、附件与 Agent 文本成果使用稳定 fallback,subtype 同时进入资源协调签名。 -- 并发与失败:Tauri 用 `read_local_project_resource_canvas_layout` 和 `update_local_project_resource_canvas_layout` 暴露读写,以 `projectId + mode + expectedRevision` 在专用跨窗口布局锁内做 CAS。更新额外携带只读结果中的 `expectedProjectId` 身份栅栏,路径被重建为新项目时旧窗口在锁副作用前失败;Rust 内部 revision 保留 `u64`,但共享 serde、Tauri 输入和前端 IPC 统一限制为 `0..=Number.MAX_SAFE_INTEGER`,达到上限时保持原文件。锁入口文件持久存在,Unix 以 `flock` 文件描述符、Windows 以不共享句柄持有互斥;应用不按 mtime / PID 猜测 stale、不删除锁文件,进程退出由操作系统释放。更新在创建锁目录前只读验证 manifest,锁内复核 projectId;无效根保持零 workbench 副作用。2026-08-05 阶段四把完整资源输入签名加入 `projectPath + projectId + mode` scope identity:资源投影或可信依赖深度变化立即建立新 epoch,旧读写继续由后端 CAS 收束,但不占用新 scope 的前端单写者槽且迟到响应被丢弃;同一签名 scope 内的资源协调仍使用 FIFO 和前一笔权威 revision。冲突返回最新完整布局且零写入,资源协调最多追加两次冲突重试,普通失败恢复最近可信布局。写入复用项目安全路径、链接校验、容量上限、恢复副本与原子替换,损坏或身份冲突不能被空布局覆盖。 -- 业务边界:布局是本地工作台 UI sidecar,不进入 manifest,不推进游戏项目 mutation revision,不使 Runtime verification 失效,不触发 Agent 权限,也不属于资产、Agent 产物、Git 或云端事实。本切片不包含关系线、资源替换、浮层位置、缩放 / 平移、搜索 / 筛选条件和当前 mode。 -- 影响范围:`packages/shared` 与 Rust `shared-contracts` 的跨边界 DTO、AI 游戏创作 Tauri 项目持久层与命令、项目开发资源画布、定向 Rust / React 测试、工作台 PRD 和客户端实施计划。 -- 验证方式:序列化与字段上限测试、缺文件 / 损坏 / 原子恢复 / 链接安全测试、同 revision 双写最多一个成功、两种 mode 跨重启独立恢复、新增资源不移动旧坐标、`1280×800` 横屏无页面级溢出,以及 `npm run agc:typecheck`、定向测试、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-31 generic-v1 使用稳定观察与当前场景指纹关闭试玩假阳性 - -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。 - - -- 背景:External Runner 和 Tauri 客户端各自拥有进程内 `PreviewRegistry`。Runner 完成 `preview.validate` 后,其 server 与 running 状态不会出现在 Tauri registry,导致已有可玩版本时用户预览不自动出现;后续 revision 即使验证成功,既有 iframe 也可能继续显示 WebView 缓存中的旧资源。顶部只写“未启动”还会让用户无法判断是 Runner、Runtime 还是预览未启动。 -- 验证方式:以当前 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 等待与耗尽状态使用严格字段派生的安全摘要 - -- 决策:重试资格继续按稳定错误类别判断,durable retry record 额外保留精确且不含正文的 `upstream-`;等待态从 record 派生 HTTP 状态、真实 attempt 上限和退避剩余秒数。耗尽态只在 `kind/httpStatus/fingerprint/chars/retryAttempt/maxRetries/retryState` 全部严格匹配时派生安全中文摘要;Runtime 私有机器字段可供确定性投影,但状态卡和持久 conversation 不显示 fingerprint、字符数、绝对路径、脱敏占位符或 Provider 正文。所有写入“后台任务失败”conversation 的生产分支统一经过同一安全 formatter,其它错误只显示固定失败文案。 -- 验证方式:Rust mock 503 覆盖等待、恢复与耗尽,断言 exact HTTP status、attempt、sidecar 清理和正文零泄漏;前端模型覆盖状态卡优先级、严格字段解析、字段不一致与尾随正文失败关闭;conversation 测试覆盖 Provider URL/query、API Key、绝对路径、fingerprint、chars 和 redaction marker 均不可见。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。 - - -- 背景:独立包原先在 Tauri 最终退出时仅调用一次 `runner.shutdown_if_idle`;若 Runner 正忙便返回 busy 且没有稍后关闭闩锁,Runner 和后台命令会永久残留。`command.exec / project.verify` 只有进程组 flag,STDIO MCP、Git 和清理命令也缺少 `CREATE_NO_WINDOW`,因此 Windows release 会连续弹出多个控制台窗口。 -- 验证方式:定向测试覆盖专用 RPC 的 draining / shutdown 与普通 idle 语义不变;正式安装包在活跃任务期间确认无后台控制台窗口,关闭主窗口后核对 Runner、MCP、command、ConPTY 和孙进程全部退出,再启动确认 durable 状态正确 reconciliation。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。 - -## 2026-07-30 Windows Runner 新建私有控制文件在原子安装前初始化 TokenUser owner - -- 决策:既有 durable 文件的读取继续严格拒绝 foreign owner。只有本进程以 `create_new` 创建且仍持有 Windows `share_mode(0)` 独占句柄、并通过普通文件 / 非 reparse / 单链接检查的临时文件,才在写入和原子安装前初始化 `TokenUser` owner 与 protected 私有 DACL,失败时关闭句柄并清理刚创建的文件;安装后继续严格复核。固定 `agent-runner.lock` 的 stale 恢复还要求父目录是已验证的私有 AppData;活锁不可接管或截断,只有 sharing / lock violation `32/33` 表示占用。父进程观察到 Runner 子进程退出后立即返回真实错误,不再空等启动 deadline。Tauri `.setup()` 内的致命失败在记录日志后直接显示诊断路径。 -- 验证方式:Windows 定向测试覆盖 endpoint 原子写入与 TokenUser 复核、new/stale lock owner 修复、活锁不截断、hardlink / reparse 不触碰目标、project-owner 诊断 TokenUser 复核、错误码精确分类,以及子进程退出在 2 秒内返回;正式包在现场 TokenOwner 为 Administrators 的机器上必须依次出现 `startup.runner.start.complete`,创建项目任务时 execution-owner 诊断也必须成功。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。 - - -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。 - - -- 背景:Windows 安装包首次创建 AppData 时若沿用继承 owner,目录 owner 可能是 Administrators 而非当前登录用户;后续严格 owner 校验会让客户端在 `.setup()` 阶段退出,且无控制台 release 缺少可见诊断。直接修改 foreign-owner 旧目录的 ACL 还可能覆盖其它主体持有的数据或跟随 reparse 路径。 -- 决策:新建客户端 AppData 时以进程 `TokenUser` SID 显式设置 owner 和当前用户私有 DACL,不使用 `TokenOwner` 代表用户。历史 foreign-owner 真实目录先原子重命名为同级唯一 `.owner-mismatch-backup-*`,再重建并回读验证安全目录;任何 reparse / junction / symlink、备份冲突或迁移失败都失败关闭,不在旧目录上放宽权限。独立 release 的 `startup.log` 和记录 Runner stdout / stderr 摘要的 `agent-runner.log` 均采用 256 KiB 上限、仅一份 previous 和脱敏写入;AppData 日志不可写时 `startup.log` 回退系统 TEMP,Tauri URL、AppData、Runner、`.setup()` 或 `.build()` 初始化失败时在 Windows 显示包含诊断日志位置的错误对话框。 -- 验证方式:Windows 定向测试覆盖 TokenUser owner、私有 DACL、foreign-owner 同级备份不覆盖和 reparse 拒绝;诊断测试覆盖 256 KiB 单 previous 轮转、凭据与绝对路径脱敏、AppData 不可写时 TEMP 回退和初始化失败对话框。安装包 smoke 后保留旧备份证据并确认新 AppData 可写、Runner 可启动。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`docs/project-memory/shared-memory/development-workflow.md`。 - - -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-28 AI 游戏临时页面启动消息采用 URL 消费加页面闩锁 - -- 决策:首屏只读取一次 `initialMessage`,随即使用同源 history 替换从 URL 删除该参数;App 同时以启动项目绑定页面级闩锁。StrictMode、组件重挂载、HMR、整页重载、Runtime 终态和项目切换均不得重投,旧消息也不得投给另一个项目。 -- 验证方式:AppSurface 覆盖 StrictMode、组件重挂载、终态变化、项目切换和 URL 二次消费;真实长运行中再次触发前端热更新后,Supervisor 队列不得新增相同任务。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-28 AI 游戏创作视觉产物使用规范图 DAG 和玩法无关 UI 合同 - -- 背景:游戏图集曾被普通生图代替,且 UI 生成与视觉验收硬编码单位卡槽、波次和敌人入口,导致贪吃蛇等非塔防项目即使调用正确接口也生成错误内容。 -- 决策:复用现有 16 任务图,固定 `art-director -> design-foundation -> art-asset-plan` 三 owner DAG。规范图走 images generations `kind=spec`;UI 精确引用当前规范图 resourceId,走同一路由 `kind=ui-design`;透明图集使用同一 resourceId 和具体 `iconDescriptions`,只走 icon-spritesheets generations。UI extraction 仅用于已有带标注 UI 图,不参与该 DAG。 -- 内容与验收:UI prompt、art spec、图集分类和 `ui-prototype.v2` 必须从当前任务与 `game/game_design.md` 提取真实玩法,不得预设塔防或补入不存在的单位、卡牌、波次、敌人入口。v2 检查信息 HUD、可玩区域、关键实体、主要操作、失败/重开、移动布局意图、实现清晰度和原创主题;`ui-prototype.v1` 只供历史审计安全读取,不能放行新建或恢复 run。 -- 替换与透明度:旧正式图只能由 Supervisor 认领原合同后签发的唯一 repair 原位替换,禁止先删图。`postprocess-failed-source-preserved` 源图不得登记为透明交付物;正式图集必须有真实 `alpha < 255`。 -- 影响范围:AI 游戏创作 Runtime 生图路由、策划/美术 Agent prompt、manifest 溯源、UI 视觉审计、External Editor API skill 和技术方案;不新增后端接口或平台玩法入口。 -- 验证方式:定向 Rust 测试锁定专用路由、精确规范图引用、告警分类、真实 alpha、玩法无关 prompt 和 v1/v2 审计边界;完整生成后用当前 revision 的桌面/移动真实试玩和 PNG 证据验收。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`.codex/skills/genarrative-external-editor-api/SKILL.md`。 - -## 2026-07-21 AI 游戏创作客户端采用薄入口与领域模块 - -- 背景:`apps/ai-game-creator-shell` 的前端入口、Tauri 项目能力、Rust 测试、界面测试和真实 Runtime E2E 随能力增长形成超大文件,单文件所有权已经影响并行开发、审查和定向验证。 -- 决策:入口文件只负责依赖组合、模块注册和稳定导出;生产实现按认证、配置、Agent Runtime、项目摘要、项目持久化等功能域拆分,测试与 E2E 按 suite / 场景域拆分并保留稳定注册顺序。不同 Agent 并行重构时必须使用互斥写入目录,由主线程统一审查和执行完整门禁。 -- 拆分边界:重构不得改变 Tauri command、前端公开导出、测试名称、测试数量、E2E CLI 参数或持久化格式;不得用 `include!`、运行时读取源码、整文件字符串拼接或把原文件整体搬到另一个超大文件来规避体量问题。共享 helper 只在确有多模块复用时上提。 -- 影响范围:`apps/ai-game-creator-shell/src`、`src-tauri/src/project`、`src-tauri/src/tests`、`tests/appSurface`、`scripts/agent-runtime-real-e2e` 和客户端实施计划。 -- 验证方式:对比拆分前后测试名集合,运行 shell ESLint / Prettier / typecheck、完整界面测试、Tauri Rust 测试、真实 E2E self-test、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-18 AI 游戏创作正式项目页升级为 GameAgent 工作台 - -- 背景:新的《陶泥儿GameAgent-V1.0 项目开发界面需求》要求正式项目开发页同时承载资源管理、运行表现层、陶泥儿对话和子 Agent 状态,旧的“正式用户页只有主聊天与只读专业 Agent 列表”已不足以支撑目标交互。 -- 决策:在现有 `apps/ai-game-creator-shell` 项目开发入口内扩展单一工作台,不新建平行客户端。首版从当前 manifest、导入附件和 Agent 状态派生界面,提供资源 / 运行切换、资源排列与聚焦、审批弹层和底部状态栏;真实游戏通过现有 localhost 预览 server 直接载入客户端内受限运行容器,不再调用系统外部浏览器。未具备正式写回契约的拖拽布局、版本资源替换、数值微调、泥点累计、Agent.md 和 Skill 管理不得在前端伪造成功。 -- 横屏窗口:当前独立 App 只交付横屏桌面工作台,`client` 默认窗口固定为 `1280×800`,最小窗口固定为 `1280×720`。工作台按壳内剩余视口排布并收紧四周留白;消息区与 Runtime 区各自承担内部滚动,专业状态增长不得把输入区或底部 Agent 栏推到视口外。窄屏纵向布局不作为当前客户端验收目标。 -- 影响范围:`apps/ai-game-creator-shell` 正式项目开发页、项目工作台前端测试、AI 游戏创作智能体 App 实施计划和原生壳预览门禁。 -- 验证方式:运行 AI game creator shell 定向测试与 typecheck、`npm run ai-game-creator-shell:check`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-17 AI 游戏创作 V1.31 使用同一父 run 收束静态与隔离协作 - -- 背景:V1.30 已证明 Supervisor 能在无编排配方的真实终端任务中自主选择多个 static 专业 Agent,但尚未证明同一父 run 同时存在 static delivery/claim 与 isolated all-join 时,等待、唤醒、恢复和唯一 finalization 可以组合。两类协议分别通过不能替代组合证据。 -- 决策:继续复用 `project-supervisor`、`--swarm-chat`、External Runner 和既有 durable 事实源,不新建第二套调度器或结果协议。用户任务只描述业务范围;仓库规则可声明验证要求和安全禁用边界,但不写 Agent 编排工具、调用顺序或 Runner 配方。Supervisor 在同一目标同时包含长期专业交付与临时隔离检查时,首个协作批次不得遗漏任一类。 -- 完成边界:static delivery/claim 与 isolated group/result/join delivery 保持各自状态机,但全部绑定同一个 parent Agent/Session/run;waiting phase 只投影当前首个 blocker,Runner 恢复和 finalization 必须在项目锁内重新枚举两类事实源。两类结果都已认领且其它 blocker 清零后,原 Supervisor run 才能写唯一用户 assistant。 -- 验证:确定性基线统一运行 `project_supervisor_mixed_`,真实行为运行 `npm run agc:mixed-swarm-e2e -- --config-dir `。失败尝试不得和后续轮次拼接;详细拓扑、一次性计数与当前 PASS 报告只维护在 Runtime V1.31 技术方案,不复制进长期共享决策。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-17 AI 游戏创作 V1.30 使用自主 Supervisor 终端门禁和语义消息收敛 - -- 背景:V1.28 已证明预置双专业方向下的合同委派、repair、Runner 恢复和唯一回复,V1.29 已证明受控瞬态重试;但二者都没有证明 Supervisor 在用户不提供 Agent ID、数量、并行或 repair 配方时会自主编排,也没有把重复 `agent.message` 的持久幂等与后台 loop 有界收敛串成完整证据。 -- 自主编排:保留 `project-supervisor` 作为正式用户唯一对话与最终回复 Agent。`supervisor-swarm-autonomous-chat` 必须通过真实发布二进制的 `--swarm-chat` 接收纯业务任务,由 Supervisor 在同一 native planning 批次自主选择至少两个不同规范专业 Agent;真实 child Provider 生命周期必须重叠。弱交付只能由 Supervisor 按 acceptance criteria 做语义裁决,并在同一父 Session/run 创建唯一、完整继承原合同的单层 repair。终局以 durable delivery/claim/receipt/finalization、唯一 Supervisor assistant 和单行脱敏 `turn.report` 为事实源。 -- 消息收敛:`agent.message` 的语义身份固定为来源 Agent/run、目标 Agent/已解析 Session 与清洗截断后正文 SHA-256。相同语义重放必须复用唯一 conversation message 与 `agent.runtime.agent.message` 审计,冲突失败关闭;不同来源、run、目标、Session 或正文仍是新消息。重复调用返回 `messageAppended=false`,不算上下文窗口的新进展,也不能替代专业 Agent 自身最终回执。持续重复时最多在当前 6 轮停滞窗口结束后进入 `failed / budget-exhausted / loop-budget-exhausted`,原 `in_progress` 计划保持原样,不能写 completed 或成功回复;每次 Runtime action/observation/receipt 仍完整留痕且公共 receipt 不保存正文。 -- E2E 隔离:自主 suite 的 sentinel AppData 必须创建在正式 AppData 同级,不能嵌套在源目录;正式目录只读,配置副本、source-dir guard、endpoint 身份、CLI 调用计数和自动清理均进入硬门禁。父 Supervisor 在 repair 前执行的 `project.verify` 属于合法宿主验证,harness 只能拒绝其它意外父 pending action,不能把父验证和专业 Agent 修改确认一刀切。 -- 验证:最终正式 `openai_chat / gpt-5.5` 诊断轮为 PASS:无编排配方任务下完成双专业 Provider 真重叠、2 个初始 delivery、1 个 repair、2 个 Observed claim、pidfd Runner 强杀/boot 恢复、同一父 Session/run、严格宿主验证、唯一正式 assistant 和 3 条内部专业 assistant。51 个 Provider request identity 全部 `started -> completed`,28/28 成功计划和 19/19 格式修复全为 `native_runtime_tools`;重复、残留 sidecar、Provider payload、私有正文、API Key、诱饵、项目/配置路径和报告泄漏均为 0。确定性完整 loop 回归另证明 6 次重复消息 action 全部落账、目标消息/两类消息审计各 1 条、第 6 轮预算失败且第 7 次 Provider 请求、compaction 和 completed 均为 0。 -- 范围:V1.30 证明自主 static 专业编排与真实终端聊天可组合;同一父 run 的 static delivery + isolated all-join 真实组合,以及 Tauri/WebView 宿主级 Supervisor E2E 仍是独立后续门禁。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-17 AI 游戏创作 Swarm 显式重试必须使用受控真实故障门禁 - -- 背景:V1.28 `supervisor-swarm` 正式报告的 46 个 Provider request 全部 completed;确定性测试和条件式 E2E validator 虽覆盖 retry 契约,但 `failed=0 / retry=0` 仍可 PASS,不能证明真实 Provider Swarm 进入过显式重试链。 -- 决策:保留正常 `supervisor-swarm` 作为合同委派/repair/恢复协议门禁,另设 `supervisor-swarm-transient-retry`。新 suite 用 sentinel 管理的隔离 AppData 只覆盖一个专业 Agent 的 `baseUrl / maxRetries / retryBackoffMs`;本地 loopback 代理在首个 POST 转发正文前断线,后继请求先暂停。暂停期间必须证明唯一 `started -> failed`、唯一 retry audit、不同 request identity、稳定 `-transient-1` slot和相同逻辑身份,同时 action、receipt、目标 Agent 子委派、claim、assistant、pending、project revision、目标产物和 upstream forwarding 全为 0,之后才允许真实 Provider 请求继续。 -- 安全:代理不记录或返回 upstream URL、headers、Authorization、请求/响应正文或凭据,只公开计数与布尔状态;只接受 loopback origin-form POST 和原 base path,redirect 原样返回而不跟随。E2E 启动 CLI/Runner 时必须合并并同时覆盖 `NO_PROXY / no_proxy`,显式加入 `127.0.0.1 / localhost / ::1`,避免继承的系统 HTTP 代理先接触发往故障代理的凭据和正文。端口 0 耗尽时使用有界 loopback fallback,stop 必须幂等关闭全部上下游连接。隔离 AppData 创建在正式目录同级,source-dir guard 禁止本 suite 前缀进入源目录或留下残留项;源配置私有副本逐字校验,正式 Runner endpoint 身份保持不变,临时合并配置与 overlay 为 `0600` 并由 sentinel 删除。并发正式 Runner 的 heartbeat 可改变目录 mtime/ctime,不得据此把外部写入误归因给 suite。完整链后续失败时,partial report 仍必须回填已经取得的 retry checkpoint 和零副作用证据。 -- 验证:最终加强版正式 `openai_chat / gpt-5.5` 报告为 46 个 request identity、46 started/terminal、45 completed、1 failed、1 retry;受控重试前所有副作用计数为 0。代理观察到的 10 个目标 Agent 请求与该 Agent lifecycle 数量一致,其中 1 个注入失败、1 个暂停、9 个转发。放行后双专业 Agent 真重叠、2 初始 + 1 repair delivery、2 个 Observed claim、targeted contract read、pidfd Runner 强杀恢复、唯一 Supervisor assistant 和 3 条内部专业 assistant 全部成立;27/27 成功计划与 14/14 repair 全为原生工具协议,源 AppData 未被写入,重复、残留和敏感泄漏均为 0,代理、隔离 Runner/AppData/项目全部清理。 -- 范围:该门禁证明“显式重试可与既有 Swarm 完整链组合”,不证明 Supervisor 已在无 Agent ID、同轮或 repair 次数提示时自主选择编排。自主 suite、真实 `--swarm-chat`、static+isolated all-join 组合和 Tauri 宿主 E2E 保留为后续完成项。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-16 AI 游戏创作 Agent Runtime V1.28 Supervisor 合同委派与单回复收束 - -- 背景:V1.16 已建立 Supervisor 的 durable static delivery/claim 和同一父 run 唯一回复,但旧 `agent.delegate` 只描述目标与任务,Runtime 只能确认子任务终态,不能持久证明预期产物、验证证据或返工关系;实施计划中也仍有普通用户进入单 Agent 对话的旧表述。 -- 决策:`project-supervisor` 固定为正式用户唯一默认对话与最终回复 Agent。专业 Agent 和 isolated child 只向父 run 提交内部回执、摘要与证据;开发窗口单 Agent 直调和 `agc:swarm` 调试不获得正式用户回复所有权。 -- 正式 GUI:登录后的单窗口客户端从首页创建项目或从项目组打开已有项目后,项目开发页只挂载 Supervisor 用户面。首条需求直接投递 active `project-supervisor` Session;全新项目还没有该 Session 时先通过既有 Session 命令创建并设为 active;已有非终态 run 的后续输入使用 same-run steer。普通用户只看到 Supervisor 对话、紧凑 Runtime 状态、确认/Needs input 和专业 Agent 协作只读状态;专业 Agent picker、Session 管理、完整计划和工具台继续只属于开发入口。 -- 对话与配置边界:legacy `.agent/conversations/project.jsonl` 只作有界兼容读取,正式 Runtime user/流式草稿/final assistant 不再由 React 双写到 legacy 项目对话,规范消息只归属 Supervisor Session。正式项目页缺少 LLM/AppData 配置时只显示 Runtime 错误,由单窗口壳全局“配置”入口处理,不自动弹开发配置框。 -- 合同:新 native `agent.delegate` 的 strict schema 固定携带 `agentId / task / acceptanceCriteria / expectedArtifacts / repairOfDelegationId / runId`,六个字段均必填,后两者可为 `null`。`acceptanceCriteria` 为 1-8 项;`expectedArtifacts` 为 0-16 个精确项目内非私有相对文件,不接受 glob。旧持久 action 缺字段按空合同恢复,不迁移已有 pending/delivery/claim sidecar。 -- 交付与门禁:durable delivery、ready receipt 和 claim 快照原样保存合同及 `structuredResult`;结构化结果包含 `contractStatus=evidence-ready|needs-repair`、artifact path/SHA-256、`missingExpectedArtifacts`、`verificationRequired`、`verifiedRevision`、安全 `evidence/error`。Runtime 只在 child completed、预期产物齐全、必要 verification passed 时判 evidence-ready;语义是否满足仍由 Supervisor 按 acceptance criteria、摘要和证据裁决。 -- 返工:Supervisor 只有在同一父 run 已认领原 delivery 后,才能为 needs-repair 或语义未通过发出 `repairOfDelegationId=<原 delegationId>` 的新委派。repair 必须完整继承原合同并交回原专业 Agent,深度固定为 1,同一原 delivery 同时最多一个非 suppressed repair;相同 durable action 重放幂等复用,不同重复或并发竞争拒绝。`suppressed` repair 不算完成,同一 action 可在无终态字段时原地恢复;若该 action 已持久失败,新 action 只可在所有既有 repair 均 suppressed 时重做基础设施投递。repair 继续在原父 Session/run 收束,不产生第二条用户回复。首次 repair 被合同继承门禁拒绝时,失败 observation 返回同一 durable delivery 的完整权威合同,Supervisor 可据此直接逐项修正;字段缺失或身份不确定时再按 `delegationId` 定向重读。 -- Prompt 与完成:专业 Agent task prompt 必须携带完整合同并明确只交内部回执;Supervisor prompt 明确不得把 evidence-ready 自动当作语义通过,也不得忽略 needs-repair。无法自行裁决的问题统一通过既有 `user.input_request` 汇总询问用户。所有必要 delivery/claim/repair、结构化计划、verification、确认、用户输入及其它既有 blocker 清零后,才允许原 Supervisor finalization 写唯一 assistant。 -- 计划推进:单独 `update_agent_plan` 只用于步骤或状态真实变化;当前 `in_progress` 步骤已具备事实、权限和合同后必须在同一响应附带具体 action,格式修复不能把可执行动作退化为 explanation-only checkpoint。未完成计划 blocker 和 prompt 必须明确该规则,避免 Supervisor 理解了下一步却持续空转。 -- 多 action 原批次:Provider 同轮返回 2-3 个 action 时,Runtime 先持久化绑定完整 planning 身份与稳定 actionId 的私有批次,再对整批完成策略/MCP preflight。任一拒绝保证零工具执行;所有确认收齐后才从 action 0 按原顺序 dispatch。cursor 只在 observation、投影、receipt、Agent DB 与 context 全部落盘后推进;Runner 重启按原 cursor 补投影,steer、仓库漂移或非 ok observation 会持久作废剩余后缀。批次 sidecar 清理前,空 action 收束与 finalization 都必须阻断。 -- Provider 瞬态失败显式重试:`agentLlm..maxRetries / retryBackoffMs` 由 Runtime 解释为独立物理尝试及其有界指数退避,不得在单 lifecycle 内恢复 `LlmClient` 隐式 HTTP 重放。每次尝试都重建禁用自动重试的 client,并形成自己唯一的单次 lifecycle;首次 request slot 不变,第 `N` 次重试稳定使用 `-transient-N` 后缀。只有 `timeout / connectivity / transport` 可进入重试;工具协议无效继续使用独立 `repair-N` 格式修复,其它错误与重试耗尽按原失败路径收束。退避后必须重新检查 Goal、steer、cancel、task/run 和 orphan lifecycle,控制请求可阻止下一次尝试;Runner 强杀后无可信终态的 `started` 仍进入 reconciliation,不能自动补发。重试发生在解析与副作用之前,不创建 action、pending、receipt、delivery、assistant 或 revision;既有控制、Runner、orphan、finalization 和隐私边界不放宽,公共审计不得保存 Provider 正文、arguments、凭据或绝对路径。 -- 影响范围:AI 游戏创作 Agent Runtime 的 native tool schema、静态委派 delivery/claim/receipt、恢复与 finalization、Supervisor/专业 Agent prompt、正式用户对话入口、确定性测试和真实 Provider E2E;编码级细节以 Runtime V1.28 章节为准。 -- 验证方式:确定性回归覆盖 strict schema、旧 action 空合同恢复且 sidecar 不迁移、合同跨 Runner 重启、artifact/verification 客观门禁、语义验收边界、单层唯一 repair、并发幂等和 final barrier。真实 `gpt-5.5` swarm 必须证明同一 Supervisor run 下两个专业 Agent 真并行、一份弱交付恰好触发一次 repair、唯一 Supervisor assistant、重复 action/receipt/message 为 0、敏感信息泄漏为 0。 -- 当前状态:PASS。2026-07-17 正式 `openai_chat / gpt-5.5` `supervisor-swarm` 已证明同一 native 批次双专业委派、真实 Provider 重叠、2 份初始 delivery、1 次 targeted contract read、唯一 repair、pidfd Runner 强杀/boot 恢复、同一父 Session/run、唯一 Supervisor assistant 和专业回复仅内部可见。报告为 46/46 Provider lifecycle 闭合且 completed,成功计划 24/24、格式修复 20/20 全为原生工具协议;重复、残留 sidecar、正文/凭据/绝对路径/报告泄漏均为 0。真实门禁同时发现并修复 `agent.message` 公共审计保存绝对 conversation path 的缺陷,现统一保存 `.agent/conversations/...` 项目相对路径并有定向回归。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-16 AI 游戏创作 Agent Runtime 只并行持久只读批次 - -- 背景:V1.26 已允许 Provider 一轮返回最多三个原生工具 action,但同一 Agent 仍逐个执行;直接把 action future `join` 会因同步文件 I/O、单 pending sidecar 和项目一致性锁而形成假并行,并破坏 steer、崩溃恢复与 exactly-once。 -- 决策:同一 Agent 只把连续 2-3 个自动批准的严格只读工具组成 durable parallel-read batch。首版白名单为 `memory.read`、`conversation.read`、`asset.list`、`project.search`、`project.diff`、`git.inspect`、`file.list`、`file.read`、`task.list`;所有写入、命令/进程、确认、Provider/MCP、生成、Git commit、委派和回执认领工具继续串行。批次在项目一致性锁内完成 preflight、executing、线程并行读取和 observed 落盘,控制请求只在批次边界前或后线性化;终态观察仍按 Provider 顺序投影。 -- 恢复与安全:批次成员使用稳定 actionId/指纹。Runner 在 `executing` 中退出只允许同身份重放严格只读物理读取,`observed` 只补齐幂等投影;不能新建 Provider lifecycle、action 或 receipt。公共审计只记录身份、工具名、计时与重叠结论,不记录参数、观察正文、绝对路径或凭据。任何分类、策略、Goal、steer、repository context 或持久身份不确定都失败关闭或退回既有串行路径。 -- 影响范围:AI 游戏创作客户端 Rust Agent Runtime、Runner 恢复、定向测试、真实 Provider E2E 和 Runtime 技术文档。 -- 验证方式:`parallel_read_batch_` 的 8 项确定性用例覆盖真实重叠、稳定顺序、串行屏障、控制竞态、取消/Goal/repository drift、`executing` 重放和 `observed`/部分投影恢复去重;正式 `openai_chat / gpt-5.5` 独立 suite 必须证明模型自主发出至少两个同轮读取、时间区间真实重叠、同 run 唯一回复、原生协议、零重放/重复/泄漏和隔离清理。 -- 真实结论:2026-07-16 隔离 `parallel-read` suite PASS。真实模型同轮提交 2 个独立 `project.search`,单一持久批次重叠 `10,969,247ns` 且按 Provider 顺序投影;4/4 个成功工具计划与 2/2 个 repair 全为 `native_runtime_tools`,6 个 tool-plan 与 1 个 final-reply lifecycle 唯一闭合。最终 assistant/completed 各 1,重复 action/receipt/Provider lifecycle、遗留 finalization/批次 sidecar、私有正文、API Key、诱饵、项目/配置路径和报告泄漏均为 0,隔离 Runner/AppData/项目完整清理。V1.27 当前门禁为 PASS。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`。 - -## 2026-07-16 AI 游戏创作 Goal 真实验收强制原生工具协议 - -- 背景:V1.18 的 `goal-runtime` 已证明 edit/pause/Runner 强杀/resume/finalization,但该 PASS 早于 V1.26 原生工具目录;旧验收只接受协议兼容集合,无法证明长任务没有静默退回 wrapper/text JSON。阶段等待在 Runtime 已因外部 transport 失败时还可能继续等 30 分钟。 -- 决策:Goal PASS 必须要求同一主 run 的全部成功 tool-plan 和 repair audit 都是 `native_runtime_tools`,wrapper/text fallback 为 0,function call 数量、call id、函数名数组完整且协议审计不含 arguments/response/toolArguments。PASS、部分失败与空报告统一输出协议计数。旧动作 blocked、revision 2 失败验证和写动作 settle 等长等待必须同步读取 task/runtime,failed、cancelled、budget-exhausted 或 needs-reconciliation 立即结构化失败。 -- 影响范围:`apps/ai-game-creator-shell/scripts/agent-runtime-real-e2e.mjs`、AI 游戏创作 Runtime 与 App 实施计划;生产 Goal/Runner 状态机不改变。 -- 验证方式:正式 `openai_chat / gpt-5.5` 加强版 `goal-runtime` 最终成功计划 21/21、repair 17/17 全原生,fallback/协议 payload 为 0;Goal revision 1 -> 2、真实失败后 patchset 修复、pause、pidfd Runner 强杀、paused 零推进、显式同 run resume、verification、四阶段 finalization、唯一 assistant、零重复/重放/泄漏全部 PASS。独立 transport failure 报告的成功 6/6、repair 5/5 仍全原生,并促成 terminal fail-fast。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-16 AI 游戏创作 Agent Runtime 使用 Provider 原生工具目录 - -> 后续更正:本条把 Anthropic 与「历史 fixture 和旧响应」并列为 wrapper/text JSON 兼容对象的描述,已由 2026-07-27「Anthropic 与流式统一使用 Provider 原生工具」取代;Anthropic 现在与 Chat / Responses 一样发送原生工具目录,text JSON 只剩历史响应与 fixture 兼容。下文保留作历史记录。 - -- 背景:OpenAI-compatible planning 虽已使用 function calling,但只向 Provider 提供 `submit_agent_tool_plan` 包装函数,真实工具藏在 `actions[].tool + input` 中,具体工具名和参数主要依赖长提示词,Provider 不能按工具 schema 约束选择与输入。 -- 决策:OpenAI Chat / Responses 直接获得稳定的 `update_agent_plan`、`respond_to_user`、每个内置 Runtime action 和动态 MCP function。内置名称从规范 tool id 映射,MCP 名称从 server/tool 身份派生;真实 MCP binding 与 fingerprint 由 Runtime 注入。每个 action 携带非空 reason 与独立 input schema,一轮最多 1 次计划更新和 3 个动作,或计划更新加最终回复;动作与回复不得共存。plan-only 是合法持久 checkpoint,应用后继续同一 run planning,未完成计划和项目验证门禁继续阻止最终化。 -- 兼容与安全:新请求和 repair 不广告旧 wrapper;parser 只为 Anthropic、历史 fixture 和旧响应保留 wrapper/text JSON 兼容。未知函数、重复 call id、重复计划/回复、四个动作、正文与 function calls 共存、MCP binding 冲突和非法参数均在副作用前失败。公共审计只保存协议、call 数量、函数名和 call id,不保存 arguments、正文或 MCP 参数。 -- 影响范围:`agent_native_tools.rs`、后台 planning 请求/解析/repair、Runtime 协议审计、真实 E2E harness、AI 游戏创作 Runtime 与 App 实施计划。 -- 验证方式:确定性目录/parser/Runtime 回归覆盖 plan-only、计划加多动作、计划加回复、顺序与负向边界;正式 `openai_chat / gpt-5.5` 的 `project-skill` suite 最终 9/9 个成功计划和 6/6 个 repair 全为 `native_runtime_tools`,wrapper/text fallback 为 0,只读 Skill、单文件修改、Agent/宿主验证、唯一 lifecycle/assistant/completed、零泄漏和隔离清理全部通过。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-16 AI 游戏创作 Agent Runtime 使用项目 Skill 渐进加载 - -- 背景:单 Agent 已能按目录 scope 应用 `AGENTS.md`,但领域工作流如果全部预加载进每轮 prompt,会长期占用上下文并让无关说明干扰规划;只保存文件哈希又无法证明模型真正读取并遵循了匹配工作流。 -- 决策:项目 Skill 只从 `.codex/skills//SKILL.md` 和兼容的 `.agents/skills//SKILL.md` 直接入口发现,同名时 `.codex` 优先。`repository-startup-context-v3` 首轮只向 Provider 提供清洗后的名称、描述、入口路径与正文哈希;Agent 判断任务命中后必须通过现有 `file.read` 渐进读取正文和必要引用。Skill 不新增工具或权限,不替用户确认,不放宽沙箱、隐私、验证、finalization、仓库 scope 或副作用重放门禁;适用路径的 `AGENTS.md` 始终优先。active Skill 内容或 metadata 变化必须推进 repository fingerprint,使旧 pending 动作先 blocked 后同 run 重规划。 -- 影响范围:`apps/ai-game-creator-shell/src-tauri/src/repository_context.rs`、Agent planning prompt、pending repository-context drift 门禁、真实 Runtime E2E harness 和 AI 游戏创作 Runtime 文档。 -- 验证方式:确定性测试覆盖发现根、优先级、YAML/路径/符号链接/预算、metadata 清洗、正文按需可见和 fingerprint 漂移;正式 `openai_chat / gpt-5.5` 的 `project-skill` suite 必须证明 hash-only fixture 先失败、匹配 Skill 在首个变更前读取、无关 Skill 不读取、唯一目标文件修改、Agent 与宿主验证通过,以及 Provider lifecycle、唯一回复、配置隔离和零泄漏全部闭合。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-23 BgFilter 失败审计使用硬上限与独立 tracking outbox - -- 背景:BgFilter worker 每个已发出的失败 provider attempt 都会启动 detached 审计任务;专用 worker 又关闭了 tracking outbox,使任务逐条等待 SpacetimeDB。`Q` 只约束内部 HTTP 请求生命周期,响应结束后无法限制仍在等待数据库的审计任务,部分失败、预算截短 timeout、重试恢复和熔断重置场景下可能持续堆积。 -- 决策:BgFilter worker 的失败审计在 `tokio::spawn` 前统一获取进程级 `1024` 个硬上限 permit,满载时直接丢弃并记录低基数指标,不创建等待任务。获准任务优先写入 worker 独立 tracking outbox,目录固定派生为共享 `GENARRATIVE_TRACKING_OUTBOX_DIR` 下的 `bgfilter-worker/` 子目录;worker 启动 outbox flush worker,退出时先排空已获准审计 enqueue,再封存并尽力 flush。BgFilter 专用策略在 outbox 缺失、容量拒绝或写盘失败时丢弃并观测,不回退同步直写 SpacetimeDB;其它外部 API 审计保持原有 fallback 语义。 -- 影响范围:`api-server` BgFilter worker、外部 API 失败审计策略、tracking outbox 进程接线、指标与测试、BgFilter 架构和开发运维文档;不修改 SpacetimeDB schema、procedure、bindings、前端或公开 DTO。 -- 验证方式:覆盖 spawn 前容量拒绝、flat / complex 共享总上限、permit 生命周期、独立 outbox 目录、outbox 满载 / 写盘失败不直写、SpacetimeDB 不可用时任务与磁盘保持有界,以及退出时 tracker drain 后再 flush;运行 api-server 定向测试、BgFilter fault smoke、Rust check、编码和 diff 检查。 -- 关联文档:`docs/technical/【后端架构】BgFilter受限资源调度方案-2026-07-21.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - ---- - -## 2026-07-22 BgFilter flat 与 complex 使用独立熔断状态 - -- 背景:complex 请求在 provider 持续快速失败时仍会不断发起真实 provider attempt,并为每次已发出的失败生成异步审计;现有 flat 熔断不能约束 complex,且五分钟冷却会让短暂故障恢复后的等待过长。 -- 决策:把现有 flat 熔断行为按原语义复用到 complex。flat / complex 共享 `GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_FAILURE_THRESHOLD=3` 与 `GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_COOLDOWN_SECONDS=120`,但在唯一 `bgfilter-worker` 内分别维护独立的连续失败数和打开截止时间;真实 provider attempt 的失败或成功只更新当前模式。两种模式都在排队前及取得 provider permit 后、第一次真实 HTTP 前检查自身熔断;已经通过第二次检查的逻辑调用仍可完成自己的第二次顺序 attempt。complex 熔断仍直接使父流程失败,不获得 flat 的阿里云 / 本地 fallback;本次不修改失败审计的异步处理流程。 -- 部署边界:deploy / Provision 将 worker env 中历史模板默认 cooldown `300` 定向迁移到 `120`,其它显式自定义值保持不变;`bgfilter_circuit_state` 分别上报 `mode=flat` 与 `mode=complex`。 -- 影响范围:`api-server` BgFilter worker、熔断指标与测试、worker 环境模板、生产部署迁移门禁、BgFilter 架构和运维文档;不修改 SpacetimeDB schema、父业务 fallback、计费或失败审计流程。 -- 验证方式:覆盖两种模式状态隔离、阈值、成功重置、cooldown 到期、permit 前二次检查和部署默认值迁移;运行 api-server BgFilter 定向测试、生产部署脚本门禁、编码检查与 diff 检查。 -- 关联文档:`docs/technical/【后端架构】BgFilter受限资源调度方案-2026-07-21.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - -## 2026-07-21 BgFilter 首版采用单实例同步内部 HTTP 与父流程原地等待 - -- 背景:角色动画在单个 `external_generation_job` 内通过 `buffer_unordered(frame_count)` 可并发发射最多 `48` 次 BgFilter 请求;限制父 worker 并发不能限制单个父 job 内的实际 BgFilter 并发。父 job checkpoint / continuation 和 SpacetimeDB 持久子任务都会扩大父状态机、attempt、计费、恢复和清理改动,而当前 BgFilter 成功结果本来就是 HTTP 图片二进制。 -- 决策:父 future 保持原调用栈、lease 和 attempt,等待期间继续占用通用 worker 槽并由现有 heartbeat 续租;所有调用统一同步请求唯一 `bgfilter-worker` 的内部 loopback HTTP。输入只传 OSS object key、参数、`maxQueueWaitMs / callBudgetMs` 和有界审计关联,成功直接返回经过校验的图片二进制。子 worker 使用有界 admission `Q` 和进程内 `Semaphore(N)`,负责最多两次顺序 provider attempt、flat 进程级熔断和失败审计;父流程继续负责 flat 降级、complex 失败、Alpha / 尺寸恢复、动画 finalizer、最终 OSS、业务写回、计费和父终态。 -- 超时边界:父 job 总预算仍为普通 `900s` / 长任务 `1800s`,并保留现有 `60s` 终态写回窗口。内部协议拆成互不挪用的 `maxQueueWaitMs` 与 `callBudgetMs`:前者由父剩余绝对预算扣除调用预算和父侧预留后派生,只限制等待 provider permit;flat 的 `39s` 父侧预留由 `37s` fallback(阿里云 `30s` + 本地 `7s`)与 `2s` 传输窗组成,complex 只留 `2s` 传输窗。后者从取得 permit 后起算,覆盖签名、最多两次 attempt、结果校验和响应构造。provider attempt 上限按 `N × est × 2` 派生,调用预算按 `2 × attempt + 1s` 派生;额外 `1s` 吸收 attempt 间开销,只要剩余时间仍能容纳完整 attempt 就不得先扣响应预留。父内部 client timeout 精确取 `maxQueueWaitMs + callBudgetMs + 2s`,不在发送阶段重新裁剪两笔相对预算。冻结 `N=16`、`est=5000ms` 时 attempt / callBudget 分别为 `160s / 321s`。动画删除旧的按帧数 timeout 增量,父侧不得在内部 timeout / 断连后重试整次 RPC。 -- 故障边界:首版不新增 `bgfilter_task_group`、`bgfilter_request_task`、raw OSS、checkpoint、continuation、数据库 capacity slot、共享熔断或 QPS token bucket。父或子进程崩溃、RPC 丢失时不查询、不恢复结果;父 job 沿用现有 lease / `max_attempts=1` 失败退款语义。动画首版保持所有已提交帧 collect / drain,不增加跨帧取消组。 -- 部署边界:专用进程首版仍复用完整 `AppState`,因此 systemd unit 先加载共享 `/etc/genarrative/api-server.env`,再加载 `/etc/genarrative/bgfilter-worker.env` 覆盖 worker 独占参数;父子共同依赖的 `N=16` 与 `est=5000ms` 必须来自共享基础环境,worker 专属环境只管理 flat 熔断参数和默认 `Q=2048` 保险丝。发布切换前校验父子使用同一个非空、非符号链接、`root:genarrative 0440` 的内部 Token 文件,并拒绝父子内部 URL、Token、连接参数、`N / est`、OSS bucket 或 endpoint 漂移(同 bucket 的独立 AK 允许)。worker 停机时立即拒绝仍在排队的请求,只排空已取得 provider permit 的调用;unit 使用 `TimeoutStopSec=900` 覆盖默认 `321s` 调用预算及响应收口。运行期巡检同时检查唯一 worker unit active 与 loopback readiness;本地 `npm run dev` 同样启动独立子进程并解析第五个 dev 端口,`ProcessRole::All` 不内嵌 listener。 -- 影响范围:已实施范围包括 `api-server` 内部 HTTP client、专用 `bgfilter-worker` listener / process role、并发与超时配置、部署和运维观测;未修改 SpacetimeDB schema、父 job schema、用户任务 DTO、任务列表或收费归属,当前待生产压测后启用。 -- 验证方式:`48` 帧并发进入父 future 时,健康唯一子 worker 进程持有的 BgFilter HTTP future 峰值不得超过生产显式配置的 `N`,且 `queued + running + egress` 不超过 `Q`(admission permit 持有到 response body 发送完成或 drop);覆盖 flat / complex 降级矩阵、内部 deadline、断连后已启动请求排空、动画全帧 drain、External v1 / inline 旁路扫描、二进制大小 / MIME / 尺寸门禁、单实例部署、DDD、编码和 diff 门禁。 -- 关联文档:`docs/technical/【后端架构】BgFilter受限资源调度方案-2026-07-21.md`、`docs/technical/【后端架构】外部生成Worker化方案-2026-06-03.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - ---- - -## 2026-07-20 角色动作抠图前禁止透明 padding - -- 背景:图片画布角色动作此前在 BgFilter 前复用最终帧 finalizer,把 FFmpeg 抽帧先转成目标尺寸 RGBA 画布并用透明黑像素补边;透明区域进入 BgFilter、阿里云和本地键色共同读取的 OSS 源帧后,会干扰主体边缘判断并降低抠图质量。 -- 决策:仅图片画布角色动作链路在抠图前把 FFmpeg 帧转为 RGB8,按最终帧宽高的 contain 比例使用 `Triangle` 缩放到内容尺寸,不创建最终目标画布、不引入 Alpha、不插入 padding;该 RGB8 PNG owned 上传 OSS 后由三段抠图链共享。抠图返回后继续复用原最终帧 finalizer,转为 RGBA8、居中放入最终目标尺寸,并以 `RGBA(0,0,0,0)` 补边。`560×752 → 323×480` 的固定验收结果为 `323×434 RGB8` 抠图输入和上下各 `23px` 透明补边的 `323×480 RGBA8` 最终帧。 -- 补充(2026-07-21 实现收口):转 RGB8 时若解码帧携带 Alpha 通道(共享 FFmpeg 抽帧命令不固定 `-pix_fmt`,源视频为 alpha 格式时 PNG 可能是 RGBA),必须先把像素按白底合成为不透明再转 RGB8(`flatten_alpha_onto_white_rgb`),禁止直接丢弃 Alpha——全透明像素下未定义的 RGB 值会以杂色进入抠图输入,重新引入本决策要消除的杂色边缘。该白底合成职责只属于图片画布角色动作的 BgFilter 输入准备阶段,不得为此在共享抽帧命令里固定像素格式。 -- 边界:不改变最终帧的 RGBA/padding 语义与透明帧格式、BgFilter 请求、OSS 上传与签名、抽帧数量和采样时间,也不改变旧 `/api/assets/character-animation/*` 动作发布链路;因为降级链复用同一个 object key,阿里云和本地键色同样读取新的无补边 RGB8 源帧。 -- 影响范围:`server-rs/crates/api-server/src/character_animation_assets.rs`、后端融合架构、角色动作专题和图片画布当前接入方案;不涉及 DTO、前端接口、SpacetimeDB schema 或运维配置。 -- 验证方式:像素测试断言 `560×752 RGB8 → 323×434 RGB8` 且无 Alpha/补边,并断言抠图结果最终成为上下各 `23px` 透明补边的 `323×480 RGBA8`;运行 `cargo test -p api-server character_animation --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - ---- - -## 2026-07-20 角色动画帧 OSS 请求使用专用连接池、并发保护与结构化重试 - -- 背景:角色动作逐帧流水线会同时发起源帧 PUT、透明帧 PUT 和最终帧 HEAD;原路径每次请求新建 `reqwest::Client`,且 OSS 请求错误丢失 HTTP 状态和 timeout/connect/transport 分类,多个动画任务叠加时无法在进程级限制 OSS 在途请求,也无法安全区分 PUT 与 HEAD 的失败。 -- 决策:`AppState` 仅为角色动画帧初始化一次 OSS HTTP Client 和 8 路 `Semaphore`。全帧 Future 仍保持 `buffer_unordered(frame_count.max(1))`,BgFilter、阿里云抠图和本地处理不占 OSS permit;每次 PUT/HEAD 网络 attempt 单独获取 permit,退避期间释放。`platform-oss` 保留 `OssErrorKind::Request`,但在 `OssError::Request` 中保留 operation、status、timeout、connect、transport、OSS code、OSS request-id 和原脱敏 message,并为动画帧提供 3 次 attempt、250ms/500ms 退避的 PUT/HEAD 独立重试。仅无响应传输错误、timeout、OSS PutObject 的 `400 + RequestTimeout`、PUT 400 错误体读取失败(未解析出 `Code`,按 timeout/transport 归类)、408、429 和 5xx 可重试;动作帧 PUT 对 400 错误体最多读取 16 KiB,只提取 `Code` 和响应头优先的 `x-oss-request-id`,不记录完整 XML;错误体读取超时/断流时保留已读字节,已解析出的 `Code` 优先生效。除 `RequestTimeout` 与该错误体读取失败情形外的确定性 4xx、配置、签名、URL、空请求体、抠图和素材登记错误不重试。重试体在 platform-oss 内一次转为可复用 `Bytes`,每次重新签名和构造 Request,不复制整帧字节。 -- 失败语义:最终帧 PUT 成功后才执行 HEAD;HEAD 失败只重试 HEAD,不重复 PUT。任一帧最终失败仍排空已启动的 Future、整段动作退款并禁止发布缺帧动画,帧结果继续按原始序号排序。 -- 影响范围:`state.rs`、`platform-oss/lib.rs`、`character_animation_assets.rs`、对应 Cargo 依赖和架构 / 运维文档;不改变其他 OSS 调用方、BgFilter/阿里云降级、worker、计费退款、SpacetimeDB schema/DTO 或前端接口。 -- 验证方式:`cargo test -p platform-oss --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server character_animation --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding`、`git diff --check`。 - ---- - -## 2026-07-19 角色动作视频使用单进程批量抽帧 - -- 背景:角色动作生成在拿到预览视频后,原实现会为 `32 / 40 / 48` 个采样点分别启动一次 FFmpeg、重复解码同一视频。release 的 2 vCPU 主机在一次 32 帧任务中因此出现约 10 秒的 CPU 尖刺,且进程启动和重复解码都不是业务必需开销。 -- 决策:角色动作抽帧必须先沿用 `compute_sample_time_seconds()` 计算全部采样点,再通过一个 FFmpeg filter graph 对输入统一 `setpts`、`split`,各分支按精确 `select=gte(t\,)` 输出一帧。不得改用会漂移现有采样时刻的粗粒度 `fps` 抽帧。单次命令完成后逐一确认全部目标文件存在,任一缺帧继续使用原有用户错误文案,并在 details 中保留首个缺帧的 `targetSeconds / outputPath`、整批 `missingFrames` 和 stdout/stderr。视频封面等单帧调用保留兼容 helper,但内部复用同一批量实现。 -- 影响范围:`server-rs/crates/api-server/src/character_animation_assets.rs` 的角色动作视频本地抽帧和单帧视频封面抽取;不改变尾帧安全步长、BgFilter 并发、OSS 路径、帧编号、透明化后处理或前后端结果契约。 -- 验证方式:运行 `cargo test -p api-server editor_character_animation --manifest-path server-rs/Cargo.toml`,真实短视频回归必须由一次 FFmpeg 命令产出整批帧,并继续断言 `32帧·4秒` 最后一帧为 `3.875s`;追加 `cargo check -p api-server --manifest-path server-rs/Cargo.toml`、Rust 格式、编码和 diff 门禁。 -- 关联文档:`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`、`docs/project-memory/shared-memory/pitfalls.md`。 - ---- - -## 2026-07-18 图片生成 K 档由 provider 直接生成 - -- 背景:旧 gpt-image-2 尺寸表会把 2K 竖版回落到 `1024x1536`,图标入口又使用固定 `360x360 / 512x512` 占位;角色去背景结果变小时还会直接放大整张透明成品,导致 UI 显示的 2K 与模型实际生成清晰度不一致。 -- 决策:用户选择的模型、比例和 K 档先映射为 provider 可直接接受的真实像素,前端占位、api-server 请求和 VectorEngine request body 保持一致。带显式尺寸选项的用户生成不再用回图后缩放恢复 K 档;宣发素材固定交付尺寸与旧无尺寸请求保留原有兼容恢复。角色、图标和 UI 去背景降采样时只重采样 alpha 蒙版并应用回 provider 原始 RGB,不放大低分辨率后处理 RGB。 -- 影响范围:普通图片、角色形象、图标图集、UI 设计图的占位与生成请求,gpt-image-2 尺寸矩阵,以及角色透明后处理。 -- 验证方式:前端尺寸矩阵和入口占位测试、api-server 生成参数与 alpha 合成测试、platform-image 最终 request body 测试、类型检查、Rust check、编码和 diff 门禁。 -- 关联文档:`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`、`docs/【编辑器】画板图标素材生成入口设计-2026-06-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-18 阿里云 URL 抠图链路按外部调用阶段审计 - -- 背景:阿里云 URL 抠图先从源 OSS GET,再解码、校验尺寸、归一化并上传临时 OSS;此前解码和尺寸失败仍使用普通 `InvalidRequest`,被错误标记为 `externalCallAttempted=false`,无法满足阿里云失败统一审计约定。 -- 决策:真正开始外部调用前的本地预检不写 `external_api_call_failure`;源 OSS GET 成功后发生的解码、尺寸、归一化、临时上传、阿里云请求和结果处理失败均进入审计。`platform-matting` 使用结构化 `LocalProcessing` 分类和 `failureStage`,由 api-server 映射为 `source_decode`、`source_validate`、`source_normalize`、`temp_upload`、`result_decode` 等阶段,不再把这些错误统称为“发请求前本地预检”。 -- 影响范围:`server-rs/crates/platform-matting/src/lib.rs`、`server-rs/crates/api-server/src/aliyun_matting.rs`、`server-rs/crates/api-server/src/external_api_audit.rs`、`server-rs/crates/api-server/src/editor_project.rs`、后端架构文档。 -- 验证方式:运行 `cargo test -p platform-matting --manifest-path server-rs/Cargo.toml`、阿里云抠图与外部审计定向测试、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 - -## 2026-07-18 手动去背景稳定媒体引用校验收口 - -- 背景:当前分支与 `master` 分别增加手动去背景专用 Data URL 校验和编辑器通用稳定媒体引用校验,直接叠加会让 API 与 worker 重复执行语义相同的 helper,并造成 `data:` / `blob:` 覆盖范围和错误文案漂移。 -- 决策:删除手动去背景专用校验。HTTP API 在入队前统一调用 `ensure_editor_reference_image_source_is_stable`,立即拒绝 `data:` / `blob:`;worker 不重复调用该入口校验,只通过 `resolve_editor_reference_object_key_for_owner` 完成稳定引用解析和 owner 归属校验。底层 `resolve_editor_reference_object_key` 在尝试 object key、项目资源 ID 或素材 ID 解析前统一拒绝内联媒体,作为历史任务和内部直接调用的最终边界。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、图片画布手动去背景测试和图片画布技术方案;不改变队列 DTO、BgFilter `image_url` 协议或 SpacetimeDB 的编辑器任务 payload 门禁。 -- 验证方式:覆盖 API 入队前拒绝 `data:` / `blob:`、解析器拒绝内联媒体、worker 只调用稳定引用解析与归属校验;运行 api-server 编辑器定向测试、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-17 画布 Agent 普通消息不提供客户端停止 - -- 背景:普通消息进入 LLM 前,后端已经把用户消息写入 OSS;前端中断 fetch 只能停止本地等待,不能保证后端停止规划,且会保留无法与后端消息对齐的 optimistic message。 -- 决策:移除画布 Agent 普通消息的“停止”按钮和 `stopCurrentTurn`,发送期间保持按钮禁用并等待后端响应。待确认工具调用的“取消”仍保留,不受本决策影响。 -- 影响范围:画布 Agent 对话 hook、发送区交互、前端测试和专题文档。 -- 验证方式:运行画布 Agent hook / 面板定向测试、`npm run typecheck`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【编辑器】画布Agent对话面板-2026-07-03.md`。 - -## 2026-07-10 画布 Agent 工具确认分离执行参数与展示投影 - -- 背景:画布 Agent 已在实际生成前进入 `pending_confirmation`,但 `EditorAgentToolCall.args` 只保存工具私有的规范参数 JSON,其中图片参数是保护真实 data key 的 SHA-256 opaque ID。前端直接解析 `args` 只能显示内部哈希或图片数量,无法向用户准确展示即将使用的目标图、参考图和完整参数;若直接把图片 URL 或对象塞回 `args`,又会破坏确认执行反序列化和 LLM 不可见真实 data key 的安全边界。 -- 决策:LLM 返回的原始工具参数只作为 api-server 本次处理的瞬时输入;后端按已注册 ToolArgs 反序列化、补齐默认值、删除未知 / 退役字段、完成工具参数校验并重新序列化后,才把结果写入 `EditorAgentToolCall.args`。校验失败的调用不得持久化为待确认消息。该规范 `args` 是确认执行唯一真相,不允许前端改写或回传替代参数;新增必填 `displayArgs` 只读展示投影,内含 `stringArgs`、`imageArgs` 和 `extras.priceMudPoints`。`stringArgs` 承载提示词与规格等用户可见字段,`imageArgs.refs` 承载规范 `args` 中的 `imageId` 及后端解析出的 `objectKey`、`imageSrc`、可选缩略图、标签和尺寸;`extras.priceMudPoints` 由 api-server 在创建待确认消息时使用后端运行时模型定价快照计算,前端只显示“预计消耗 N泥点”,不自行计算或回传价格。api-server 必须按已注册 tool 白名单,从规范 `args` 与 OSS 会话文档的附件 / 历史生成结果构建该投影;前端只渲染投影,以 `ResolvedAssetImage` 换签显示图片,不解析 tool 私有 schema、不展示 SHA-256 ID。展示价格不参与确认执行或实际扣费,确认后仍由既有生成 BFF 按后端运行时定价预扣费。删除只重复 `args` 且没有稳定语义的 `EditorAgentToolCall.summary`。模块尚未上线,不保留缺少 `displayArgs` 时读取 `args` 的旧消息降级路径。 -- 影响范围:`shared-contracts` / `packages/shared` 的 `editorAgent` DTO、`api-server/src/editor_agent/api.rs` 的待确认消息构建、画布 Agent 待确认卡、OSS 会话消息文档与相关测试。 -- 验证方式:`cargo test -p shared-contracts --manifest-path server-rs/Cargo.toml editor_agent`、`cargo test -p api-server --manifest-path server-rs/Cargo.toml editor_agent`、`npm run test -- src/components/image-editor/EditorAgentConversation/EditorAgentConversationPanelView.test.tsx src/components/image-editor/EditorAgentConversation/useEditorAgentConversation.test.tsx src/services/image-editor/editorAgentClient.test.ts`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【编辑器】画布Agent对话面板-2026-07-03.md`、`docs/adr/【ADR】画布Agent会话消息存OSS-2026-07-03.md`。 - -## 2026-07-18 图片多产物任务的原图进入正常完成画布 - -- 背景:角色形象、图标 spritesheet 和 UI 素材提取会同时持久化带纯色背景的 provider 原图与透明后处理结果;这些原图都需要在画布中可直接查看和复用。任务与扣费实际仍只有一次。 -- 决策:provider 原图继续写入 OSS、`asset_object`、项目资源和账号素材库。三类任务透明处理正常成功时,透明结果作为主图并保持生成器 `generatedLayerId` 锚点,provider 原图作为第二个图层放在透明主结果右侧;图标和 UI 的业务拆分素材从原图右侧继续排列。只有透明背景处理最终失败时,才把 provider 原图作为唯一主图完成占位并返回 warning。 -- 影响范围:角色形象、图标 spritesheet、UI 素材提取的画布完成快照,以及多产物持久化与画布展示边界。 -- 验证方式:后端定向测试断言三类任务正常成功都落透明主图与右侧 provider 原图、`generatedLayerId` 仍指向透明主图,图标 / UI 拆分素材继续排列在原图右侧,同时保留 source-only 失败降级测试;并运行 `cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【后端架构】外部生成Worker化方案-2026-06-03.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-17 生成后抠图原图以 OSS 作为内存生命周期边界 - -- 背景:角色形象、图标图集、UI 素材图集和角色动作抽取帧的带背景原图虽然已先落私有 OSS,但 api-server 仍可能把原图字节保留到 BgFilter / 阿里云 / 本地 fallback 结束,造成并发任务下的内存峰值叠加。 -- 决策:目标链路的带背景原图上传 OSS 时消费 `DownloadedImage` 或动作帧字节所有权,不为上传克隆整张字节缓冲;上传完成后不再跨 BgFilter 调用常驻。手动去背景直接复用已有 OSS object key,不下载原图。BgFilter 只读取 600 秒签名 URL;进入阿里云 fallback 时由 `platform-matting` 新 URL 接口下载原图、上传 `AuthorizeFileUpload` 临时对象,并在开始阿里云推理前结束下载缓冲作用域;阿里云继续失败时,api-server 再从私有 OSS 独立下载原图供本地键色,产出后释放本次原图下载缓冲。 -- 边界:不改变接口 DTO、资源记录、画布原图展示、图集切分行为和降级顺序;“释放”指 Rust 所有权和 `Vec` 析构,RSS 不保证同步下降。 -- 验证方式:`platform-matting` 测试覆盖 URL 下载缓冲在临时上传后结束、降尺寸 Alpha 回贴;`api-server` 结构测试覆盖带背景原图 owned 上传、URL 阿里云 fallback、本地重新下载与原图释放;随后运行两个 crate 的测试与编译检查。 - -## 2026-07-17 图片改造保持源图与所选清晰度 - -- 背景:图片画布从已生成的 2K 角色图重新打开生成器时,面板恢复逻辑会优先采用新建面板的 1K 默认值;即使用户重新选择 2K,角色透明化链路也可能接受 BgFilter / 阿里云返回的 1K 后处理图,并因 `nanobanana2` 使用标量清晰度档位而跳过几何尺寸恢复,最终把 2K provider 原图降为 1K 透明图。 -- 决策:从既有图片重新打开普通图片、角色、UI 或宣发生成器时,在没有仍存活的生成对话框快照时按当前图层真实 `originalWidth / originalHeight` 恢复比例与清晰度,并按目标模型支持范围归一;恢复或切换比例 / 清晰度后,普通图片、角色、图标图集和 UI 设计图的待生成及生成中占位框必须同步使用目标像素尺寸,不能保留新建 draft 的默认 1K 框。UI 素材提取的占位按框选数量对应的 1K / 2K 计划生成,旧图片修改入口按源图真实尺寸占位。角色形象去背景完成后必须保持去背景前 provider 原图的像素尺寸;若去背景供应商返回较小结果,只把 alpha 蒙版重采样回原图并保留原始 RGB,不放大低分辨率透明成品。 -- 影响范围:图片画布生成对话框恢复、生成中占位尺寸、UI 素材提取与旧图片修改的 `canvasCompletion`、角色形象 BgFilter / 阿里云 / 本地去背后处理、项目资源与账号素材尺寸元数据。 -- 验证方式:覆盖“持久化 2K 角色图重开仍为 2K”“普通图片 / 角色 / 图标 / UI 改造的 2K 占位与目标一致”“普通生图、规范图和角色图生成中占位不回退 1K”“UI 提取和旧修改入口的完成占位使用业务目标尺寸”以及“较小去背结果只提供 alpha、最终 RGB 仍来自 2K provider 原图”的前后端定向测试,并运行前端类型检查、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`。 - -## 2026-07-15 BgFilter 输入改用私有 OSS 短期签名 URL - -> 后续更正(2026-07-21):复用 object key、通过 `image_url` 提交且不传 `file` 的协议语义保留,但 600 秒 OSS GET URL 的签发和 BgFilter provider multipart 调用已迁入唯一 `bgfilter-worker`。父流程只向内部 worker 发送一次 object key、参数和剩余预算,不签发 BgFilter URL,也不重试已被 worker 接收的内部 RPC(2026-07-23 起:连接从未建立的失败按调度方案 §5.1 有界重连,见当日决策条目)。下文保留作历史记录。 - -- 背景:角色形象、图标图集、UI 素材图集、角色动作抽取帧和手动去背景在调用 BgFilter 前都已有私有 OSS object key;继续由 api-server 下载或保留图片并作为 multipart `file` 再上传,会重复传输图片字节并占用 API 进程网络与内存。 -- 决策:上述抠图链路统一复用 object key,签发 600 秒 OSS GET URL,并通过 BgFilter multipart 的 `image_url` 字段提交;请求中不再携带 `file`。签名 URL 只交给 BgFilter,不写日志或持久化。2026-07-17 起,生成原图和动作帧上传后不再保留图片字节;进入“阿里云通用抠图 → 本地键色”兜底链时按阶段从私有 OSS 重新下载。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/api-server/src/character_animation_assets.rs`、相关测试与文档;不改变 BgFilter endpoint、鉴权、`screen_color`、`seg_model`、输出校验、熔断规则、阿里云上传协议或降级顺序。 -- 验证方式:定向测试必须断言 BgFilter 请求函数包含 `image_url` 与 600 秒 OSS 换签,不包含 multipart `file` 或源图字节读取;随后运行 `cargo check -p api-server --manifest-path server-rs/Cargo.toml`。 - -## 2026-07-15 阿里云通用抠图上传切换到 AuthorizeFileUpload 正式链路 - -- 背景:`platform-matting` 原先通过 `viapiutils/GetOssStsToken` 获取临时 AK/SK,再向固定 `viapi-customer-temp` 共享桶执行 OSS V1 PUT。阿里云官方文档将该显式生成 URL 的共享临时桶通道标记为不保证 SLA、仅便于调试且不推荐生产使用;动作视频逐帧抠图会把这条风险放大到每任务 32 至 48 次。 -- 决策:非上海地域图片字节统一按新版官方 SDK `AdvanceRequest` 的实际协议处理:调用 `openplatform.aliyuncs.com` 的 `AuthorizeFileUpload` 获取单对象 `Bucket`、`Endpoint`、`AccessKeyId`、`EncodedPolicy`、`Signature` 与 `ObjectKey`;再以 multipart Policy POST 上传到动态返回的上海临时 OSS,表单字段为 `OSSAccessKeyId`(= AccessKeyId)、`policy`(= EncodedPolicy)、`Signature`、`key`(= ObjectKey)、`success_action_status=201` 与 `file`,最后把临时对象 URL 交给 `SegmentCommonImage`。移除 `GetOssStsToken`、固定 `viapi-customer-temp`、AccessKeySecret/SecurityToken 临时凭证组合和 OSS V1 SHA-1 签名;Policy POST 仍需要授权响应中的 `AccessKeyId`,不再下发可独立签名的完整临时密钥。图片归一化、结果下载、原尺寸 Alpha 回贴和上层降级顺序保持不变。该链路仍会让图片字节经过执行任务的 api-server / worker 并上传临时 OSS,不把它描述成阿里云服务端直接抓取任意公网 URL。 -- 影响范围:`server-rs/crates/platform-matting`、阿里云抠图冒烟示例、后端架构与开发运维文档;不改变 api-server DTO、动作拆帧、BgFilter 或业务降级契约。 -- 验证方式:`cargo test -p platform-matting --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`,并用真实图片运行 `segment_smoke`,确认授权上传 host 来自动态上海 OSS 且 `SegmentCommonImage` 成功返回。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`、阿里云“通用图像分割”与“文件 URL 处理”官方文档。 - -## 2026-07-15 角色动作 BgFilter 请求超时按帧数扩展 - -> 后续更正(2026-07-21):本条按帧数增加 timeout 的决策已被 2026-07-21「BgFilter 首版采用单实例同步内部 HTTP 与父流程原地等待」的公式化双预算取代。当前每帧分别携带 `maxQueueWaitMs` 与 `callBudgetMs`:排队预算只约束等待 provider permit,取得 permit 后才启动调用预算;provider attempt 按 `N × est × 2`、调用预算按 `2 × attempt + 1s` 运行时派生,冻结 `N=16`、`est=5000ms` 时为 `160s / 321s`,不再按 `32 / 40 / 48` 帧扩展。下文保留作历史记录。 - -- 背景:角色动作全部序列帧会并发进入 BgFilter,而服务端可能在自身进程内排队;固定 `180000ms` 会把排队时间和单帧推理共用同一预算,靠后的请求可能在服务仍正常处理时被 api-server 提前取消。 -- 决策:保留 `GENARRATIVE_EDITOR_BGFILTER_REQUEST_TIMEOUT_MS` 作为统一基准值。只有角色动作逐帧 BgFilter 在共享 Client 的 RequestBuilder 上把每一次 HTTP attempt 覆盖为“基准值 + `2000ms × 本次实际帧数`”,默认 `32 / 40 / 48` 帧为 `244000 / 260000 / 276000ms`;角色形象单图、图标、UI 和手动去背景不增加帧预算。该 timeout 覆盖请求发起到响应体读取完成;首次失败后的重试重新获得同样的 request deadline,整批并发策略、失败排空语义和 worker long-job 总预算不变。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/api-server/src/character_animation_assets.rs`、后端架构、开发运维和图片画布专题文档。 -- 验证方式:运行角色动作超时公式、BgFilter request override 与逐帧流水线定向测试,执行 `cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-15 手动复杂去背景复用 BgFilter 单次重试 - -> 后续更正(2026-07-21):首次失败后再尝试一次、即同一次 complex 逻辑调用最多两次顺序 provider attempt 的语义保留,但重试所有权已迁入唯一 `bgfilter-worker`。父 `external-generation-worker` 至多让 worker 接收一次内部 HTTP RPC,不重试已被接收的 RPC(2026-07-23 起:连接从未建立的失败按调度方案 §5.1 有界重连,见当日决策条目);两次 provider attempt 都失败时,子 worker 把最终类型化错误返回父流程,complex 仍不接入 flat 的阿里云 / 本地 fallback。下文所称“worker 重试”按此边界理解。 - -- 背景:图片画布手动去背景已经改用 BgFilter `background_mode=complex`,但 worker 仍只发送一次上游请求,短暂网络抖动会直接让任务失败。 -- 决策:手动去背景的 complex 请求复用现有 `EDITOR_BGFILTER_RETRY_COUNT=1`,首次请求失败后立即重试一次,两次都失败仍返回最终错误;本次不把手动 complex 接入标准纯色背景链路的阿里云 / 本地兜底,也不改变 flat 路径的熔断状态。 -- 影响范围:图片画布手动去背景 worker、BgFilter complex 请求日志和 api-server 定向测试。 -- 验证方式:运行 `cargo test -p api-server editor_manual_background_removal_retries_once --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/project-memory/shared-memory/decision-log.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-14 手动去背景迁移到 BgFilter complex 模式 - -> 后续更正:本条关于 multipart 图片文件输入的描述已由 2026-07-15「BgFilter 输入改用私有 OSS 短期签名 URL」和 2026-07-17「生成后抠图原图以 OSS 作为内存生命周期边界」取代;当前手动路径不下载原图,只提交 `image_url`。下文保留作历史记录。 - -- 背景:图片画布手动“去除背景”此前单独代理 BiRefNet 服务;BgFilter 已增加 `background_mode=complex`,可直接处理非纯色背景,继续保留独立服务会形成重复的上游、配置和错误处理链路。 -- 决策:`POST /api/editor/images/background-removals` 保持前端与 BFF 契约不变,worker 改用现有 BgFilter 地址、token、超时和共享 HTTP client。multipart 提交图片文件、`background_mode=complex`、`seg_model=birefnet` 与 `cross_check=off`,不提交 `screen_color`。标准纯色背景的角色形象、图标 spritesheet、UI 素材提取和角色动作逐帧抠图继续使用 `background_mode=flat`。删除独立 BiRefNet base URL / timeout 配置;旧 `GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_TOKEN` 仅作为 `GENARRATIVE_EDITOR_BGFILTER_TOKEN` 的兼容回退别名。 -- 影响范围:图片画布手动去背景 worker、BgFilter HTTP 协议、api-server 配置、资源元数据、前端 provider 展示和相关文档。 -- 验证方式:运行 api-server BGFilter / 手动去背景定向测试、前端 editorProjectClient / 画布 workflow 定向测试、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - -## 2026-07-13 外部生成任务持久化真实执行阶段 - -- 背景:图片画布任务列表此前把所有 `running` 任务固定映射为“正在生成”,角色生图、图标/UI spritesheet、角色动作和手动去背景进入抠图后仍无法展示“正在处理”;前端按耗时推断阶段会产生新的非正式业务真相。 -- 决策:不新增 DB 表,在既有 `external_generation_job` 与 `external_generation_job_summary` 末尾追加带默认值的可选 `phase`。worker claim 时写 `generating`;角色生图、图标 spritesheet、UI 素材提取在调用 BgFilter 前,角色动作在视频生成返回并开始抽帧/逐帧抠图前,手动去背景在执行开始时,通过 `job_id + worker_id + lease_token` 保护的 procedure 写 `processing`。phase procedure 用结构化结果区分 `LeaseFencingRejected` 与 `OtherRejected`;api-server 对 `LeaseFencingRejected` 立即终止,对 `OtherRejected` 以及 SDK 的 `Procedure` / `Runtime` 错误不重试,仅对 `Build` / `ConnectDropped` / `Timeout` 在同一 job attempt 内重试 `1` 次。编辑器 job 固定 `max_attempts=1`,第二次传输失败后进入 `failed`,不回 `pending`、不重新调用 provider,也不按错误文案猜测拒绝类型。BFF 将 `running + processing` 映射为“正在处理”,其它 `running`(含旧数据 `phase=None`)映射为“正在生成”;前端只展示后端投影。 -- 影响范围:`external_generation_job`、`external_generation_job_summary`、SpacetimeDB procedure / typed client / bindings、图片画布生成 worker、任务列表 BFF 与相关文档。 -- 验证方式:运行 `npm run spacetime:generate`、`npm run check:spacetime-schema`、外部生成 module/client/api-server 定向测试、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【后端架构】外部生成Worker化方案-2026-06-03.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-13 角色动作逐帧开启 BgFilter cross-check - -- 背景:角色动作逐帧抠图此前为减少额外推理开销固定传 `cross_check=off`,但动作帧同样需要保留发丝、镂空和运动边缘质量。 -- 决策:角色动作逐帧 BgFilter 请求固定显式传 `cross_check=on`,与角色形象保持一致;图标 spritesheet 和 UI 设计图素材提取继续固定传 `off`。该策略仍属于后端内部供应商参数,不进入前端或外部 OpenAPI。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/api-server/src/character_animation_assets.rs`、后端架构文档和图片画布技术文档。 -- 验证方式:运行 `cargo test -p api-server editor_bgfilter_cross_check --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server editor_character_animation_frames_use_three_stage_matting_fallback --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-13 角色动作 BgFilter 全帧流水线与单次重试 - -> 后续更正(2026-07-23):本条「每次 BgFilter 调用失败后立即重试 1 次」与「不新增供应商进程锁或全局 Semaphore」已被 2026-07-21 起的唯一 `bgfilter-worker` 架构取代。重试所有权迁入子 worker:对一次逻辑调用最多两次顺序 provider attempt,provider 并发由 worker 进程内 `Semaphore(N)`(生产 `N=16`)约束;父侧不重试已被 worker 接收的内部 RPC,仅 TCP 连接从未建立的失败按调度方案 §5.1 有界重连(见 2026-07-23「BgFilter 父侧连接失败有界重连与冷启动宽限」条目)。全帧独立流水化、失败排空与整任务失败退款的语义保留。下文保留作历史记录。 - -- 背景:角色动作抽帧后原先固定 `buffered(3)`,并在整批绿幕源帧串行落 OSS 后才开始抠图;每帧还单独创建 HTTP Client。公网 BgFilter 的网络等待会让服务端推理队列出现空档,且首个最终错误会通过 `try_collect` 提前取消 api-server 中其余已发 Future。 -- 决策:BgFilter HTTP Client 在 `AppState` 中统一创建并复用 keep-alive 连接池;每次 BgFilter 调用失败后立即重试 `1` 次,两次都失败才进入既有“阿里云通用抠图 → 本地键色”降级链,每次已发失败调用都保留审计。角色动作全部 `32 / 40 / 48` 帧按“单帧绿幕源图落 OSS → BgFilter/降级 → 透明帧落 OSS”独立流水化,使用覆盖本次全部帧的 `buffer_unordered` 连续发射并携带原始帧序,完成后排序;不在 api-server 新增供应商进程锁或全局 Semaphore。任一帧最终失败时先排空全部已启动 Future,再让整个动作任务失败退款,不发布缺帧动画。 -- 影响范围:`server-rs/crates/api-server/src/state.rs`、`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/api-server/src/character_animation_assets.rs`、后端架构文档和图片画布技术文档。 -- 验证方式:运行 `cargo test -p api-server editor_bgfilter_retries_once_before_fallback --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server editor_character_animation_frames_use_three_stage_matting_fallback --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server editor_canvas_screen_background_generation_uses_bgfilter_postprocess --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-16 SpacetimeDB 备份采用逐文件基线、CAS 增量与安全历史清理 - -- 背景:SpacetimeDB standalone 2.6.0 不自动删除已被 snapshot 覆盖的历史 commitlog 与旧 snapshot;反复压缩整个 `/stdb` 会重复占用磁盘、停机和 OSS 带宽。上游 issue #5542 的 contributor 明确说明,不触碰最新 snapshot 与重启所需 commitlog suffix 时,可在运行中移动或删除这些历史文件。 -- 决策:统一脚本新增 `--storage-format files`,完整基线递归保留目录、文件和 data-dir 内部相对符号链接,普通文件按 SHA-256 上传为不可变 CAS 对象,catalog 记录目录、路径、长度、SHA、对象 key 与相对链接目标;绝对或越界链接拒绝备份。相同内容不重复 PUT,后续 full 扫描只上传新增或变化内容,不再生成 tar.gz。旧 `archive` 路径保留兼容。full 必须从停库目录或已验证的冻结副本生成,不能把在线跨文件扫描称为一致时点备份。 -- history 继续按 replica 计算安全边界:只接受完整、未锁定且含同 offset `.snapshot_bsatn` 的 snapshot,保留跨越最新 snapshot 的边界 segment 及全部后缀。旧 segment 对和旧 snapshot 被递归映射为单文件 CAS 对象;对象、history catalog、full baseline catalog、候选 fingerprint 与当前边界全部验真后才删除源文件。同库执行用 work-dir PID lock 互斥。 -- OSS 固定恢复入口为 `//latest.json`。CAS 文件和 full/history catalog 保持不可变;latest pointer 只保存最新 full catalog 与已发布 history catalog 的 object key、长度和 SHA,不包含主机绝对路径或文件内容。每次 state 变化先验真全部引用 catalog,再覆盖上传并 HEAD 验真 latest pointer,成功后才落本地 state;history 还必须在 pointer 成功后才允许删除源文件。全新机器可仅凭 bucket、database、prefix 与 OSS 凭据自动下载 pointer 和 full catalog。 -- dev 带宽不足时,允许把已冻结的 dev 基线经 `10.2.0.10 -> 10.2.4.16` 内网 rsync 到 release 独立 staging,再用 release 出口上传 dev bucket;staging 不得指向 release `/stdb`,不得停止或修改 release 服务,传输凭据必须临时创建并在演练后移除。catalog 不记录 staging 绝对路径,files state 可回传 dev 继续 history。 -- 恢复边界:恢复时默认从 OSS `latest.json` 自动定位 full catalog,创建目录并按相对路径下载每个对象、逐文件校验长度与 SHA;本地 state 只用于备份续跑,不再是异机恢复前置条件。远程 dev 已完成真实 OSS、清理、重启和异机隔离恢复演练;release timer 与 publish 前备份继续保持原行为。 -- systemd 接线:主 service 保持 `archive-full`。Server-Provision 新增默认值为 `archive-full` 的 `DATABASE_BACKUP_PROFILE`;dev 或 release 显式选择 `files-history` 时,必须为各自主机指定独立 work-dir,并先用 current release 脚本执行 history dry-run,确认已有 full state 后才安装仓库托管 drop-in,并删除现场手写旧 drop-in。切回默认 profile 必须删除所有 history 覆盖。 -- 影响范围:`scripts/database-backup-to-oss.mjs`、备份门禁、生产 env 示例、systemd 模板、Server-Provision、SpacetimeDB 运维与恢复流程;release timer 可在独立 baseline 验证后显式选择 profile,publish 前备份是否切换仍需单独决策。 -- 验证方式:`npm run check:database-backup`、`npm run check:production-ops`、`npm run check:encoding`、`git diff --check`;dev 现场必须完成逐文件 full catalog、重复 full 零 PUT、history dry-run、上传后清理、STDB 重启和按 catalog 隔离恢复 roundtrip。 -- 关联:。 - -## 2026-07-27 逐文件备份本地元数据采用去重 state 与 gzip 保留 - -- 背景:files v1 本地 state 同时在 `baselineCatalog`、`latestCatalog` 和每个 `historyCatalogs[]` 中嵌入完整文件清单,且每次成功 history 的本地 catalog 与 `--result-file` 再复制同一清单;release 独立 work-dir 已由此累积约 840 MiB JSON,但 OSS-only 恢复实际只依赖 `latest.json`、catalog 引用和 CAS 对象。 -- 决策:OSS catalog/latest schema、对象 key、序列化字节与恢复链保持不变。本地 state 升级为 gzip v2,只保存去重后的 catalog 引用;旧 v1 JSON 可读,并且只在非 dry-run 成功发布、验真 latest、原子写入 v2 后删除。full 增量复用从本地 latest full catalog gzip 缓存读取,缓存缺失时退化为逐对象 OSS HEAD,不影响正确性;缓存长度或 SHA 与 state 不一致时失败关闭。 -- 清理边界:成功运行后只压缩保留 latest full catalog;已验真的本地 history catalog、旧 full catalog和严格文件名匹配的失败/dry-run 遗留 catalog 清理。`--result-file` 只写紧凑引用和计数。任一 state 压缩或本地 metadata 清理失败都发生在 `/stdb` history 源文件删除之前;OSS catalog、latest 和 CAS 对象永不由本地 metadata 清理删除。 -- 兼容与验证:`--restore-files-state` 同时接受 v1 JSON 与 v2 gzip,`--restore-files-latest` 不受本地格式影响。门禁覆盖 v1 迁移、gzip/state/catalog 损坏拒绝、full 增量复用、history catalog 本地清理、紧凑 result、pointer 失败不清源和 OSS-only 恢复。 -- 关联:`scripts/database-backup-to-oss.mjs`、`scripts/check-database-backup-to-oss.mjs`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - -## 2026-07-14 后台账号采用 owner 引导账号与一级 Tab 实时授权 - -- 背景:后台此前只支持一组环境变量管理员,所有 `/admin/api/*` 共用统一 admin 门禁,无法给运营、审核等人员分配独立账号和页面范围。 -- 决策:现有 `GENARRATIVE_ADMIN_USERNAME/PASSWORD` 账号固定作为不可编辑 owner;新增 member 独立保存到私有 `admin_account` 表,密码使用 Argon2id 摘要。登录凭据快照与普通账号快照在类型层分离,普通列表、按 ID 查询和写入响应不包含 `password_hash`。Argon2id 在 blocking 任务中运行并由 api-server 有界限流;未知、停用和 owner 错密账号使用 dummy hash 抹平耗时。member 常规权限粒度固定为后台 15 个一级 Tab,“账号管理”只允许 owner 且不可授予 member;2026-07-24 起,历史花费手动对账作为独立高风险操作权限 `profile-wallet-consumption-reconcile`,不随任意 Tab 自动授予。member 每次请求重新读取当前账号并校验启停、`token_version`、Tab 权限和独立操作权限;任一权限、密码或启停变化递增版本并立即淘汰旧 JWT。账号不存在返回 `401`,SpacetimeDB 故障保留 `502/503` 而不清理有效 token。前端导航和操作按钮过滤只负责体验,正式授权由 api-server 路由权限矩阵执行,未登记的新后台路由对 member 默认拒绝。后台面向运营展示管理员身份时统一使用 `displayName`;持久审计仍保存稳定 subject,由 api-server 解析显示名称,前端不得暴露账号 ID 或用登录用户名代替。写接口必须在主事务前加载显示名目录,或在主事务后降级解析,不能把已提交写入伪装为失败。 -- 影响范围:`admin_account`、SpacetimeDB typed procedures / client facade、后台 JWT 与 session DTO、`/admin/api/accounts*`、后台路由权限中间件、admin-web 导航和账号管理页。 -- 验证方式:SpacetimeDB schema / client / API 定向测试、`npm run check:admin-account-procedures` 隔离 procedure smoke、完整路由矩阵测试、admin-web 权限路由与账号 API 测试、owner/member 浏览器 smoke、`npm run check:spacetime-schema`、编码与 diff 门禁。 -- 关联文档:`docs/technical/【后台管理】多账号与Tab访问权限方案-2026-07-14.md`。 - -## 2026-07-13 图片画布生成资源统一命名 - -- 背景:图片画布的普通图片、规范、角色、图标图集、UI 设计、宣发素材、视频和音频默认使用“类型 + 数字”命名,用户只能在生成后单独重命名素材,画布图层、项目资源和素材库名称容易不一致。 -- 决策:主生成状态继续使用可选 `assetLabel`,名称最多 80 个字符并在提交时去除首尾空格;当前生成面板不展示“资源名称”标签和输入框,默认沿用现有自动编号名称,历史状态或内部调用若携带非空名称,仍必须让同一个名称贯穿 `assetLabel`、`canvasCompletion.title`、本地结果图层标题、项目资源和账号素材库,不允许各链路自行生成不同名称。移除名称输入后,角色、图标图集、UI 设计和角色动作等提示词输入恢复统一可见边框。 -- 派生产物:图标和角色动作后端契约补齐 `assetLabel`。带背景原图、角色动作绿幕预览等具有独立复用价值的中间产物基于主名称追加“(原图)”等后缀;普通图片和图片修改的纯尺寸变换在内存完成后只上传一次,不生成“原始输出”副本。2026-07-29 起,图标切片不再按用户提示词命名,统一按全连通域视觉顺序命名为 `素材 N`。 -- 影响范围:图片画布生成状态与面板、提交模型、图标和角色动作请求契约、项目资源 / 素材库持久化和相关编辑器文档。 -- 验证方式:覆盖生成面板不渲染资源名称输入、提示词边框、空白回退、内部自定义名与长度限制,以及图片 / 图标 / 视频 / 音频 / 角色动作的请求名称、完成快照标题和素材名称一致性;运行前端定向测试、Rust 契约与 API 定向测试、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 - -## 2026-07-13 图片画布多产物生成任务必须保存全部可恢复产物 - -- 背景:角色形象、图标 spritesheet 和 UI 素材提取会先得到带纯色背景的原图,再执行抠图或拆分;图片修改会先得到模型对齐尺寸的原始输出,角色动作会先得到绿幕预览视频,再抽帧和抠图。此前部分原始产物只登记到 OSS,或者要等后处理成功后才进入项目资源,用户无法在失败后找回已经生成成功的内容。 -- 决策:凡一次资产生成任务产生多个具有独立复用价值的产物,后端必须把上游已返回的中间产物写入 OSS、`asset_object`、项目资源和账号素材库,再执行抠图、抽帧或拆分;未指定素材文件夹时进入默认“项目”文件夹。角色形象、图标 spritesheet 和 UI 素材提取在透明背景处理正常成功时同时保留纯色背景原图与透明后处理结果;透明背景处理最终失败时只保留已经持久化的 provider 原图,并按下一条降级规则收口。普通图片和图片修改的纯尺寸变换不属于独立产物:provider 回图保留在内存,变换成功只上传变换结果,变换失败只上传 provider 原图,整个流程只写一次 OSS 并只创建一个素材,不能制造重复“原始输出”。`nanobanana2` 使用标量清晰度档位和独立比例,保留 provider 输出尺寸,不按 `WIDTHxHEIGHT` 解析。角色动作把绿幕预览视频作为一个可复用素材保存,逐帧源图继续留在同一任务 OSS 路径,不把 32 至 48 帧逐张灌入素材库。去背景、音频等没有独立上游中间产物的任务不制造重复副本。 -- 画布、成本与降级:有项目上下文的图片多产物继续由同一次 `canvasCompletion` 写入权威画布快照,正常成功时生成器 `generatedLayerId` 锚定主后处理结果,角色形象、图标 spritesheet 和 UI 素材提取都把 provider 原图作为第二个图层放在透明主结果右侧;图标和 UI 的业务拆分素材从原图右侧继续排列。三类任务已经保存 provider 原图、但透明背景处理最终失败时,任务以 `completed + warning` 收口,原图作为唯一主图完成画布占位;不写入不存在的透明处理图,图标和 UI 也不继续拆分。透明处理成功后的图标和 UI 图集自动拆分仍是 best-effort;识别或切片持久化失败继续完成整张透明图集,并在 inline、队列轮询和刷新后任务列表中提示非阻断 warning,不得借用失败错误字段。provider 原图或角色动作预览视频承载该任务的模型生成成本,抠图、逐帧处理、透明图集和切片等后处理派生产物的 `generation_cost_mud_points = 0`,避免把生图成本误显示成抠图成本;所有中间产物沿用所属任务的真实 `asset_kind`,角色原图仍为 `character`、图标和 UI 图集原图仍为 `icon-spritesheet`、角色动作预览仍为 `character-animation`,不得再写新的“原图类型”。后台素材查询按任务分页,最终产物作为父行并显示任务总成本,每个中间产物作为可展开的独立子行显示阶段生成器和阶段成本。扣费确认边界保持为 provider 成功,OSS、尺寸恢复和画布回填不延长退款保护。 -- 2026-07-16 告警契约补充:inline / external v1 继续返回结构化原始诊断;queue 有意把通用 `warning` 或 `sliceWarning` 归一为展示就绪字符串,通用 `warning.reason` 原样保留,`sliceWarning.reason` 由 worker 添加“图集已生成,但自动拆分未完成:”前缀,摘要与 BFF 原样投影,Web 直接展示。历史值保留写入时快照,不按新格式回填或推断;该内部字符串契约通过 API/worker 与 Web 同一维护窗口、同版本发布收口,不增加混部兼容层。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、`character_animation_assets.rs`、外部生成任务摘要、图片画布完成快照、账号素材库和前端生成提示。 -- 验证方式:覆盖中间产物登记先于后处理、默认素材文件夹、图集拆分降级、inline / queue warning 和主结果锚定的定向测试,并运行 `cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:spacetime-schema`、前端定向测试、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-12 泥点充值收敛为四档并统一资产入口 - -- 背景:主站与图片画板的泥点余额入口、余额明细和充值弹窗存在不同实现,旧充值口径仍展示六档泥点、首充双倍和会员购买 / 升级入口,容易让展示、商品资格与后端余额真相发生漂移。 -- 决策:主站与图片画板统一复用公共泥点资产入口,收起态展示总额与充值,展开态只展示不限时泥点、每日免费泥点和使用详情;充值中心 BFF 继续统一下发总额、三桶余额、限时到期时间、每日免费基础重置额及下次重置时间,前端不得自行相减推算,但会员周期限时泥点仅用于存量兼容和后端结算,当前版本不在前台展示。钱包明细每次展开都重新读取充值中心 BFF,打开期间实时总额变化时继续补读;图片画板的生成扣费或退款完成后同时刷新总额与充值中心拆分。充值中心读请求必须使用 revision 门禁,支付创建、到账确认等权威响应写入时使旧读失效,避免旧响应覆盖新的每日免费 / 不限时明细。默认泥点商品收敛为 `60 / ¥6`、`180 + 90 / ¥18`、`300 + 150 / ¥30`、`680 + 340 / ¥68` 四档,`60` 档无赠送,后三档按现有 `user_id + product_id` 独立资格规则首次购买加赠 `50%`。当前版本关闭会员购买页签、会员商品和购买 / 升级入口。 -- 2026-07-17 追加:主站、图片画板与 AI 游戏创作独立 App 的泥点账单统一复用 `packages/shared/src/components/PlatformProfileWalletLedgerModal`。共享组件只依赖 `ProfileWalletLedgerResponse`,承接来源 label、金额正负号、UTC 日期、余额兜底和 loading / empty / error 展示;`/api/profile/wallet-ledger` 请求、鉴权、打开状态与重试生命周期继续由各宿主持有,不把账户事实或后端副作用下沉到共享 UI。 -- 影响范围:`profile_recharge_product_config` 默认商品、充值中心 read model、共享前后端契约、主站与图片画板泥点资产入口、充值弹窗、后台充值商品默认值。 -- 验证方式:充值与统一入口定向前端测试、`npm run typecheck`、充值商品定向 Rust 测试、`cargo check -p spacetime-module -p spacetime-client -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【项目基线】当前产品与工程约束-2026-05-15.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-12 每日免费泥点独立于任务并按北京时间日切 - -- 背景:现有“每日免费泥点”实际只是每日登录任务领取奖励,领取后进入普通永久余额,既不是独立余额桶,也不会在次日失效;同时主站仍展示每日任务卡片和任务中心入口,与新的产品口径不一致。 -- 决策:新增 `profile_daily_free_points` 作为每日免费泥点事实源,基础额度固定为 `20`,以北京时间 `day_key` 为业务日;跨日后的首次余额读取或扣费原子清除昨日剩余及退款叠加量,并把当日额度重置为 `20`,对外语义始终视为北京时间 `00:00` 已重置。扣费按“每日免费 -> 会员周期限时 -> 永久”顺序;资产退款在同一业务日恢复原每日免费额度,跨业务日时把原每日免费消费部分叠加到退款当日每日免费桶,当日允许超过 `20`,下一业务日仍统一重置为 `20`。每日任务系统和 `daily_task_reward` 保留为普通永久奖励,但主站隐藏每日任务卡片及任务中心入口。 -- 影响范围:`profile_daily_free_points`、`profile_wallet_ledger`、个人资金 read model、钱包扣费和退款 metadata、主站“我的”页、SpacetimeDB 迁移与生成绑定。 -- 验证方式:`npm run spacetime:generate`、`npm run check:spacetime-schema`、钱包定向 Rust 测试、个人中心定向前端测试、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【项目基线】当前产品与工程约束-2026-05-15.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-11 BgFilter 交叉模型否决用于角色形象与角色动作 - -- 背景:新版 BgFilter 的 `cross_check` 默认开启,会额外运行 HR-matting 第二意见模型;角色形象与角色动作序列帧需要保留发丝、镂空和运动边缘质量;图标 spritesheet 和 UI 素材提取不需要承担这部分额外推理开销。 -- 决策:api-server 调用 BgFilter 时必须显式发送 multipart 字段 `cross_check`,不依赖服务端默认值。角色形象生成和角色动作逐帧去背固定传 `on`;图标 spritesheet 生成和 UI 设计图素材提取固定传 `off`。角色动作逐帧去背与三条静态生图路线复用同一条 `BgFilter → 阿里云通用抠图 → 本地键色` 降级链和同一 BgFilter 熔断器。该字段是后端内部供应商策略,不进入前端请求或外部 OpenAPI。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/api-server/src/character_animation_assets.rs`、图片画布 BgFilter 调用文档。 -- 验证方式:运行 `cargo test -p api-server editor_bgfilter_cross_check --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server editor_canvas_screen_background_generation_uses_bgfilter_postprocess --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server editor_character_animation_frames_use_three_stage_matting_fallback --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-11 SpacetimeDB 工具链统一升级到 2.6.0 - -- 背景:生产数据副本验证已使用 2.6.0 standalone,而仓库 Rust crate、本地 CLI、生成 bindings、容器与 server provision 仍锁定 2.5.0 或更早版本,继续混用会增加 BSATN / procedure 返回值与发布产物错配风险。 -- 决策:`server-rs/Cargo.toml` 的 `spacetimedb`、`spacetimedb-sdk`、`spacetimedb-lib` 精确锁定 2.6.0;本地 CLI / standalone、Rust bindings、worker smoke、容器压测镜像和生产 provision 下载根同步对齐 2.6.0。其它 crate 恰好出现的 2.4.1 / 2.5.0 不随本决策机械替换。 -- 影响范围:Rust workspace lockfile、SpacetimeDB bindings、本地 dev 版本门禁、容器 smoke / loadtest、server provision Jenkins 与项目 SpacetimeDB skills / 文档。 -- 验证方式:核对 `spacetime --version`,运行 `npm run spacetime:generate`、`npm run check:spacetime-schema`、`cargo check` / 定向测试、`npm run test -- scripts/dev.test.ts`、server provision 工具测试、production ops / encoding / diff 门禁。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - -## 2026-07-17 SpacetimeDB 工具链统一升级到 2.6.1 - -- 背景:SpacetimeDB 2.6.1 修复 procedure context 中调用者 `Identity` / `ConnectionId` 丢失问题,并修正 TypeScript 生成代码中 `Option` 字段的可选键语义;继续运行 2.6.0 会保留已知 procedure 身份回归。 -- 决策:`server-rs/Cargo.toml` 的 `spacetimedb`、`spacetimedb-sdk`、`spacetimedb-lib` 精确锁定 2.6.1;本地 CLI / standalone、Rust bindings、worker smoke、容器压测镜像和生产 provision 下载根同步对齐 2.6.1。 -- 影响范围:Rust workspace lockfile、SpacetimeDB bindings、本地 dev 版本门禁、容器 smoke / loadtest、server provision Jenkins 与项目 SpacetimeDB skills / 文档。 -- 验证方式:核对 `spacetime --version`,运行 `npm run spacetime:generate`、`npm run check:spacetime-schema`、`cargo check` / 定向测试、server provision 工具测试、encoding / diff 门禁。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - -## 2026-07-23 SpacetimeDB 工具链统一升级到 2.7.0 - -- 背景:SpacetimeDB 2.7.0 增加满足数据约束时的 unique / primary-key 非破坏迁移、Rust SDK capability traits、standalone MCP endpoint、SQL JSON 输出和更多连接/视图/内存指标,并修复旧 procedural-view backing table 的自动迁移。官方当前发行资产位于 `v2.7.0-hotfix3` 标签,二进制和 Rust crates 版本仍为 2.7.0。 -- 决策:`server-rs/Cargo.toml` 的 `spacetimedb`、`spacetimedb-sdk`、`spacetimedb-lib` 精确锁定 2.7.0;本地 CLI / standalone 与 Rust bindings 使用官方 2.7.0 hotfix3 构建,worker smoke 本地镜像按运行版本标记 2.7.0,官方容器和生产 provision 下载根固定到 `v2.7.0-hotfix3`。provision 从 hotfix 资产标签解析运行版本时必须得到 2.7.0,并同时核对 CLI commit 为 `d220349a...`;裸 tag `a08663c7...` 不得因版本号相同而被复用,下载 / 安装结果也必须通过同一 commit 门禁。 -- 影响范围:Rust workspace lockfile、SpacetimeDB bindings、本地 dev 版本门禁、容器 smoke / loadtest、server provision Jenkins 与项目 SpacetimeDB skills / 文档;现役 module 没有 procedural view,本次不修改 schema 或 migration。 -- 验证方式:核对 CLI 版本和 commit,重新生成 Rust bindings,运行 `npm run check:spacetime-schema`、相关 Cargo check、server provision 工具测试、容器配置、Rust 1.93 兼容检查、standalone `/v1/ping`、encoding 和 diff 门禁。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - -## 2026-07-10 外部生成任务只持久化轻量媒体引用并独立维护摘要投影 - -- 背景:编辑器 worker 化后直接把同步接口 payload 序列化进 `external_generation_job.request_payload_json`;前端又把已有 OSS `objectKey` 下载成 Data URL 再提交,导致单个任务 JSON 膨胀到数 MB,正式任务列表读取 20 条任务时同时搬运约 65 MB payload,并放大为 SpacetimeDB 与 api-server 的瞬时内存峰值。此前“禁止 Data URL 持久化”只覆盖工程、素材、图层和元数据,遗漏了正式生成任务表。 -- 决策:`external_generation_job.request_payload_json` / `result_payload_json` 同样属于正式持久化边界。对于本次事故涉及的 `source_module = editor-canvas` 任务,只允许普通业务参数和 `objectKey` / `resourceId` / `assetId` 等已登记轻量引用;任意层级 `data:` / `blob:` 与超限 JSON 必须由 api-server 和 SpacetimeDB 双重拒绝。编辑器已有媒体直接传正式引用,本地红框标记图先上传 OSS 后再入队,上传目录与文件名使用同一个强唯一 ID。其它玩法现存 Data URL 请求契约不在本次事故修复中被静默禁用,后续必须先完成各自资源化再扩大 DB 门禁。用户任务列表、单任务状态和 acknowledge 只读取不含 request/result payload 的 `external_generation_job_summary` 投影;acknowledge 只更新摘要小表并保留审计事件,不为确认通知加载 / 重写主任务 payload。提示词在入队时提前提取;错误摘要统一去除内联媒体并限制为 2048 字符;列表在单次 owner 扫描中只保留固定大小 top-N,不再收集全量历史后截断。历史终态 payload 仅允许迁移操作员通过默认 dry-run、`editor-canvas + job_id` B-tree cursor 显式分批压缩,pending / running 永不压缩;cursor 选择最多读取 `limit + 1` 行,apply 再逐条主键读取。首次发布默认 fail-closed 暂停在 Stdb 与 API 之间,保持维护模式并停止旧 API/controller/worker,完成压缩和摘要回填后才由指定审批人放行 API。 -- 影响范围:编辑器生成提交 workflow、`external_generation_job`、`external_generation_job_summary`、外部生成 procedure / typed client / BFF、SpacetimeDB bindings、历史数据维护流程和图片画布文档。 -- 验证方式:覆盖编辑器嵌套内联媒体与 payload 上限拒绝、非编辑器既有任务不被本轮门禁误伤、正式任务接口类型不含 payload、终态分批压缩不修改活动任务、已有 objectKey 不转 Data URL、本地标记图先上传再提交;运行外部生成定向 Rust / Vitest、`npm run spacetime:generate`、`npm run check:spacetime-schema`、`npm run typecheck`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/project-memory/shared-memory/pitfalls.md`。 - -## 2026-07-10 BgFilter segModel 保留内部字段,不进入外部 OpenAPI - -- 背景:`api-server` 的图片生成、图标 spritesheet 与 UI 素材提取请求仍可反序列化 `segModel`,并识别 `birefnet` / `anime-seg`,以兼容内部调用和既有任务;但 BgFilter 当前受服务进程内存与并发容量约束,不同分割模型的内存占用并非可由外部调用方自由选择的稳定契约。 -- 决策:`segModel` 是有效的**内部**字段,不是用户可配置字段。产品 UI 不提供抠图模型选择,应用内调用固定使用 `birefnet`;外部编辑器 OpenAPI 刻意不声明 `segModel`,并通过请求 schema 的 `additionalProperties: false` 拒绝该字段。外部调用方应省略它并使用服务端默认值;只有维护 BgFilter 容量与模型策略的后端代码可在经过内存 / 并发验证后调整内部固定值或兼容策略。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、`src/services/image-editor/editorProjectClient.ts`、图片画布提交模型、`docs/openapi/genarrative-external-v1.openapi.json`。 -- 验证方式:确认外部 OpenAPI 三个生成请求 schema 均未公开 `segModel` 且保持 `additionalProperties: false`;运行 `npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/project-memory/shared-memory/pitfalls.md`(BgFilter 模型字段的对外暴露边界)。 - -## 2026-07-10 背景色决策统一走 gpt-5-mini 并挪到预扣泥点之后 - -- 背景:背景色决策此前无源图路径继承 `state.llm_client()`(Ark/豆包,选色能力弱、线上从未真正调用 VectorEngine);且四条生成链路(角色生图 / 角色动作生视频 / 图标 spritesheet / UI 设计图提取)都在 `execute_billable_asset_operation_with_cost` 预扣泥点之前发起决策,导致用户余额不足或生成注定失败时仍白发一次 gpt-5-mini 决策、平台白付 token,也与定价文档「预扣失败不得继续调用上游」的原则相悖。 -- 决策:(1)无源图决策改走独立常量 `EDITOR_SCREEN_BACKGROUND_TEXT_LLM_MODEL = gpt-5-mini`(VectorEngine,Responses 协议 + `reasoning_effort=low`),与有源图视觉档 `EDITOR_SCREEN_BACKGROUND_VISION_LLM_MODEL` 分离、便于各自调参;gpt5 客户端未配置时才降级回默认文本客户端。(2)**所有用到背景色决策的生成链路,决策必须在余额校验 + 预扣泥点之后发起**:预扣前只做颜色无关的算价 / 校验 / settings(动画用默认色占位算价,与队列路径一致),决策及颜色相关的 prompt / 合成 / `generationInputs` 搬进 billable 闭包,闭包把决策结果带出供后续抠图与落库使用。语义:余额不足则决策不跑(平台零成本);决策失败则闭包返 `Err` 走失败退款(用户不损失泥点)。后续新增任何用背景色的生成链路都必须遵循此顺序。 -- 影响范围:`server-rs/crates/api-server/src/llm_model_routing.rs`、`editor_screen_background_decision.rs`、`editor_project.rs`(生图 / 图标 / UI 提取三条 `_for_owner`)、`character_animation_assets.rs`(动画 `_for_owner`);四条链路的 worker / inline / agent / external-API 入口同时覆盖。 -- 验证方式:`cargo test -p api-server editor_project --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server character_animation --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`;`editor_screen_background_decision::tests::live_*`(`-- --ignored`,需真实 `VECTOR_ENGINE_*`)验证有图 / 无图两条路径真实调用 VectorEngine。 -- 关联文档:`docs/【编辑器】模型定价配置管理方案-2026-06-22.md`(预扣泥点原则)、`docs/project-memory/shared-memory/pitfalls.md`(gpt-5-mini 图片输入上限实测)。 - -## 2026-07-10 图片画布模型定价以 SpacetimeDB 为运行时事实源 - -- 背景:后台模型定价原先保存到运行时 override JSON 文件,生产部署需要额外保证目录可写,且不符合当前 `server-rs + SpacetimeDB` 的配置事实源边界。 -- 决策:模型定价默认 JSON 继续保留在 `server-rs/crates/api-server/config/editor-generation-pricing.default.json` 作为空表和数据库不可达时的兜底;运行时事实源改为 SpacetimeDB `editor_generation_pricing_config` 全局表,固定 `config_id = global`,以强类型 `models` 保存模型、单位和档位,不在 procedure / client 边界传递不透明 JSON。首次初始化通过 `initialize_editor_generation_pricing_config_if_missing_and_return` 在单事务内仅缺失时写入,并把 `ctx.sender()` 记为 `writer_identity`;表存在后 bootstrap secret 不得接管 writer,迁移操作员修复价格也必须保留 writer。runtime queue / 钱包 guard 只接受精确 writer,identity 轮换只能由迁移操作员调用独立 procedure,并写入 `editor_generation_runtime_identity_rotation` 审计表;migration operator 与 runtime writer 必须身份互斥,任何 operator 不能成为 writer,当前 writer 也不能授权为 operator,已有任一 operator 后 bootstrap secret 不得新增或接管 operator;生产统一由 `scripts/deploy/production-runtime-writer-identity-rotate.mjs` 双录新 identity 后执行并核对审计。后台 `/admin/api/editor-generation-pricing` 保存时必须入库,不再写 override 文件;主站 `/api/editor/generation-pricing` 和后端扣费入口优先读取 SpacetimeDB。旧 override 文件只作为启动本地缓存和首次空表种子的兼容来源。外部生成队列必须保存入队时价格,worker 的扣费、退款、响应和资产成本统一使用该冻结价格,配置更新不得改变已入队任务金额。队列 attempt 结算通过 `asset_operation_wallet_settlement` 持久化 consume/refund 配对或取消 intent;退款先到时,后续迟到 consume 必须失败,重复 ledger 只有用户、金额和来源一致才算幂等。lease 过期仅在 `attempt < max_attempts` 时允许重领;最终 attempt 耗尽后由 claim transaction 直接收口为 failed 并结算当前 attempt,不能再次进入 provider executor。运行时服务首次授权必须使用固定 64 位十六进制原始 bootstrap secret,WASM 只嵌入其 SHA-256,发布 artifact 不保存原文:本地 dev 把专用 API token 与按 server/database 作用域的 secret 分别持久化为 gitignored `0600` 文件,只注入 api-server;人工 production release 自动生成的原文只写 `server-rs/.spacetimedb/build-secrets/.txt`,目录 `0700`、文件 `0600`。生产 Jenkins 构建和发布阶段分别挂载同一个受保护 Secret File,Build / Publish 的 credential ID 必须相同;构建阶段只计算并注入 SHA-256,Stdb release manifest 以 `migration_bootstrap_secret_sha256` 记录摘要,发布阶段使用同一 Secret File 重算摘要并与 manifest 强制匹配后,才交给 `production-stdb-publish.sh` 安装为 root 持有、`genarrative` 组只读的固定运行时文件,归档和 `copyArtifacts` 都不含原文。Full Build 先发 Stdb、后发 API,所以 Stdb publish 必须同步补齐旧 API / worker env 的 FILE 配置并重启 active API / controller / worker,日志和前端子进程不得接触明文。重启前的 systemd 状态查询、active worker 枚举、重启后 active 复核以及原 active API 的本机 `/healthz` readiness 都是退出维护模式前的硬门禁,任一步查询或验证失败都必须保留维护模式。 -- 追加约束(2026-07-10):`writer_identity` 只保留在 private 表和轮换审计内,不进入定价 procedure 返回快照;只有 HTTP 角色负责空表 seed,worker / controller 启动改用受 writer 鉴权的 queue-stats procedure 做只读预检并继续 fail-fast。后台保存携带 `AppConfig` 已读取的受保护 bootstrap secret,只在配置行意外缺失时用于原子首写,已有配置仍按 writer / operator 鉴权且不能隐式轮换身份。 -- 影响范围:`editor_generation_pricing_config`、`editor_generation_runtime_identity_rotation`、`asset_operation_wallet_settlement`、`editor_generation_config`、`spacetime-client` editor project facade、后台模型定价页、编辑器生成扣费链路、Stdb Build / Publish、Server-Provision、API deploy、生产 env 示例和模型定价文档。 -- 验证方式:运行 `npm run spacetime:generate`、`npm run check:spacetime-schema`、`cargo check -p spacetime-module -p spacetime-client -p api-server --manifest-path server-rs/Cargo.toml`、模型定价路由定向测试、部署脚本 `bash -n`、`node --check scripts/dev.mjs scripts/check-production-ops-guardrails.mjs`、`npm run check:production-ops`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【编辑器】模型定价配置管理方案-2026-06-22.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-10 资产签名读取按入口和对象事实授权 - -- 背景:后台资源预览需要跨账号读取图片、视频和音频,但主站或 External API 若只按 generated 前缀签名任意 `objectKey`,知道私有对象键的调用方即可越权读取;`read-bytes` 若不复用换签授权也会形成旁路。 -- 决策:主站 `/api/assets/read-url` 与 `/api/assets/read-bytes` 共用同一授权函数,并优先按配置 bucket / 精确 key 查询 `asset_object`。一旦存在 metadata,即使 key 命中 legacy 前缀,也必须按 `PublicRead` 或 owner ACL;只有同 bucket / key 未登记 metadata 的历史对象,才允许显式 `legacyPublicPath` 命中 `platform_oss::LEGACY_PUBLIC_PREFIXES` curated 白名单后匿名兼容。任意 `objectKey` 必须命中已登记 metadata。External `/api/external/v1/assets/read-url` 还必须有 `editor:asset` scope,并以 API Key 绑定 owner 执行同一检查;主站和 External 的 object confirm owner 均来自认证主体,不能信任请求体 owner,同 bucket / key 已登记后不得改变 owner。后台跨 owner 换签仅用于管理员资源预览,不放宽主站和 External 边界;成功换签后以 `admin_asset_read_url` 写入 `tracking_event`,持久化管理员 subject、请求对象和有效期,不保存 signed URL。未登记、跨 owner 和匿名私有对象统一按不存在处理。 -- 影响范围:`api-server` assets / external assets / admin 路由、后台资源查询图片放大和音视频预览、OSS 读取契约与安全测试。 -- 验证方式:定向测试覆盖 curated `legacyPublicPath` 可匿名签名、任意未登记 `objectKey` 拒绝、`PublicRead` 可读、owner 私有对象仅本人可读、External 跨 owner 拒绝、Admin endpoint 仅管理员可用,以及 `read-bytes` 与 `read-url` 同授权。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-09 角色动作视频生成背景色统一为多色自动决策 + 阿里云抠帧 - -- 背景:角色动作视频抽帧过去固定 legacy `#00FF00` 绿幕 + 本地 `editor_green_screen`,与生图链路的多色自动决策不一致;实测出现背景色与前景 / 皮肤撞色(蓝撞蓝、桃 / 黄撞肤色)以及图生视频背景变白的问题。 -- 决策:角色动作视频背景色与生图统一。`screenColor=auto` 时由视觉 LLM(`gpt-5-mini`,Responses 协议、`reasoning_effort=low`,`max_output_tokens=1024`)读源角色图自动决策,并经硬过滤器(Lab 危险质量 + 皮肤专属三判据:ΔE 距离 / 色调投影 / RGB 分离)剔除与前景及皮肤撞色的候选,手动 hex 仍尊重用户选择;透明源角色图在提交 Ark 图生视频前先合成到选定背景色实色,使视频背景确定性等于抠图键色。抽帧后逐帧优先走 BgFilter(固定 `seg_model=birefnet`、`cross_check=on`),失败依次降级阿里云通用抠图和本地 `editor_green_screen` 键色兜底(按生成时选定的背景色,而非固定 `#00FF00`)。BgFilter 与阿里云抠图失败均写入 `external_api_call_failure` 失败审计。调色板新增中明度低饱和「灰竹绿 `#A0BBA0`」补齐冷区绿色段。 -- 影响范围:`server-rs/crates/api-server/src/character_animation_assets.rs`、`editor_screen_background_decision.rs`、`editor_screen_background_filter.rs`(新增硬过滤模块)、`editor_green_screen.rs`(调色板)、`external_api_audit.rs`、`llm_model_routing.rs`、图片画布 MVP 与后端数据契约文档。 -- 验证方式:`cargo test -p api-server editor_screen_background character_animation --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、真机对源角色图跑视觉决策与候选危险度表、抽帧后采样序列帧背景色确认落在冷区安全集。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-07-09 充值订单过期改为 SpacetimeDB scheduled 表触发 - -- 背景:旧充值过期处理使用 api-server 后台轮询 worker claim 普通 schedule 表,非 HTTP 的 external-generation-worker / controller 进程也可能启动同一过期任务;扩外部生成 worker 会意外放大微信查单 / 关单流量,并且本地过期后若微信仍可支付,容易出现“微信扣款但本地拒绝入账”的风险。 -- 决策:新建原生 scheduled 表 `profile_recharge_order_expiration_timer`,创建真实微信 pending 充值订单时写入 5 分钟 timer;scheduled reducer 到点只把仍为 `pending` 的订单改为 `expired` 并写 `expired_at`。HTTP `api-server` 只订阅活跃 timer 表的删除事件,按 `order_id` 重新读取订单并仅对 `expired` 执行微信查单补偿;支付或主动关闭导致的 timer 删除会被状态判断忽略,断线窗口由未检查过期订单 catch-up 补齐,不订阅完整 `profile_recharge_order` 历史表。`SUCCESS` 允许 `Expired -> Paid` 入账,未支付或远端已终态只记录检查结果,本地保持 `expired`。`external-generation-worker` 和 controller 不处理充值过期。 -- 影响范围:`profile_recharge_order`、`profile_recharge_order_expiration_timer`、充值订单状态契约、`spacetime-client` bindings/facade、`api-server` 充值过期监听器、微信支付查单 / 关单、个人中心充值前端、后台表查询和运维文档。 -- 验证方式:`npm run spacetime:generate`、`npm run check:spacetime-schema`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、充值过期 listener / 微信支付 / shared contracts / 前端充值定向测试、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 - -## 2026-07-09 会员有效期与周期泥点重置分离 - -- 背景:账户会员制度新增 Starter / Basic / Pro / Ultimate 四档后,会员有效期、周期限时泥点和普通永久泥点容易被混成同一条时间线;升级场景尤其容易误把“补差额”实现成延长会员或重算 reset time。 -- 决策:`profile_membership.expires_at` 只表示会员是否生效,`cycle_resets_at/cycle_period_days` 只表示会员周期限时泥点重置时间。同级会员购买只延长 `expires_at`,不发当前周期额外泥点,不移动 reset time;升级只补齐当前周期应发泥点差额并更新档位,不延长 `expires_at`,不移动 reset time,但后续周期天数切换为新商品配置。旧月 / 季 / 年卡购买同等级新会员档位时按同级迁移购买处理,延长有效期并切到 Starter / Basic / Pro,避免存量会员无法迁移;购买更高等级新档位仍按升级处理。周期刷新由后端在个人中心、充值中心、任务中心、账单读取和钱包扣费入口执行,先清上周期剩余限时泥点,再发当前档位周期额度;资产操作退款按原消费流水恢复同一周期限时泥点,避免把限时泥点退成永久泥点。 -- 影响范围:`profile_membership`、`profile_recharge_product_config`、`profile_wallet_ledger`、充值中心、后台充值商品配置、个人资金 ViewModel、钱包扣费入口。 -- 验证方式:`npm run spacetime:generate`、`cargo check -p spacetime-client --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server --manifest-path server-rs/Cargo.toml wechat_virtual_pay_params`、`npm run typecheck`、充值弹窗和资金 ViewModel 定向测试。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-09 AI 游戏创作 App Runtime V1 增加单 Agent 后台任务 - -- 2026-07-12 安全边界:`project.verify` 的 script 最多 160 个字符,固定使用系统 script shell,并在解析和执行前拒绝项目级 `.npmrc`。Runtime context bundle 必须绑定 `projectId / agentId / taskId / sessionId / runId / source / task`,结尾换行计入 64 KiB 上限;恢复时还要校验 `nextLoopIndex`、context window、当前窗口已完成轮数、观察指纹、计划和 observation 数量。bundle 写入必须拒绝父目录符号链接,读取必须基于同一文件句柄限制到 64 KiB,并清洗项目路径及常见平台凭据;已观察动作只有在 observation 写入 context checkpoint 后才能删除 ledger,下一轮 planning 和跨重启恢复不得再被旧 ledger 抢占。 -- 背景:开发用单 Agent 聊天已经能真实调用各 Agent 的 LLM 路由并持久化对话,但 Agent 仍主要表现为同步问答,用户无法明确投递一个任务让某个 Agent 独立运行,也无法同时启动多个 Agent 的工作。 -- 决策:在现有 `.agent/runtime` 和 `.agent/conversations` 基础上新增单 Agent 后台任务入口。Tauri 命令 `start_game_creator_agent_runtime_task` 立即写入该 Agent 的 runtime state/event/task history,追加用户任务到 `.agent/conversations/agents/.jsonl`,随后在 App 进程内启动 tokio task 执行最小 Agent loop:Agent 按轮输出 `thinkingSummary / plan / actions / response`,Runtime 按白名单和项目权限策略执行工具并记录 `action / observation` 事件,再把已有 observation 放回下一轮 prompt,让 Agent 修正计划、继续行动或用空 actions + response 收束;单 Agent Runtime 每 6 轮形成一个上下文压缩窗口,窗口有新的独立 observation 时压缩上下文并在同一 run 继续,最近 6 轮没有独立进展或相邻窗口重复时以 `failed / budget-exhausted` 和 `loop-budget-exhausted` 终止,不生成总结伪装完成。完成或失败后把 assistant 回复或错误追加回对话,并写入 `.agent/agent.db` 审计记录。工具箱包含只读工具 `memory.read`、`conversation.read`、`asset.list`、`project.index`、`project.diff`、`file.list`、`file.read`、`agent.run_status`,以及受策略保护的写/运行工具 `memory.write`、`file.write`、`command.run_limited`、`blackboard.write`、`agent.message` 和 `agent.delegate`;`memory.write` 可追加或覆盖本 Agent 私有记忆、项目长期/短期记忆或黑板,`file.write` 只能写项目内相对路径,`command.run_limited` 只接受 `game.static_smoke` 并复用本地静态自检安全边界,`blackboard.write` 追加共享黑板,`agent.message` 写目标 Agent 对话,`agent.delegate` 把任务投递到目标 Agent 的独立后台队列;策略拒绝时不执行工具并把 `blocked` observation 回给 Agent;策略要求确认时不执行工具,而是持久化精确待确认动作并暂停该 Agent 队列,待开发者确认或拒绝后在同一 run 续跑。每个 Agent 的任务历史落在 `.agent/runtime/tasks/.jsonl`,读 runtime 时按 `runId` 去重返回最近任务,任务视角状态使用 `pending / running / completed / failed`,Runtime state 增加 `nextStep`,UI 在 Runtime 面板和主 Agent 状态卡展示当前任务、动作、下一步与最近任务。不同 Agent 使用独立 `.agent/runtime/locks/.lock`,允许并行运行;同一 Agent 已有运行任务时,新任务会先进入该 Agent 的 pending 队列,当前 drain 持锁完成后串行继续下一条 pending。该能力仍不是独立 OS 进程或跨重启离线常驻 worker。 -- 2026-07-10 补充:后台 Runtime 每次追加 `.agent/runtime/events/.jsonl` 后会通过 Tauri `game-creator-agent-runtime-update` 事件广播当前 `AgentRuntimeResult`;开发单 Agent 聊天页、项目内 Agent 对话弹窗和主窗口 Agent 状态列表都只把该事件作为实时 UI 通知并复用前端 runtime 归一化合并,事实源仍是 `.agent/runtime/agents`、`events` 和 `tasks` 文件。 -- 2026-07-11 补充:开发单 Agent 聊天页保留整页纵向滚动,聊天消息区固定响应式高度并在内部滚动;Runtime 恢复确认区使用独立布局行,避免与 Runtime 详情或聊天内容重叠。Runtime 面板详情可折叠且折叠时不渲染详情 DOM,但状态标题与任务控制按钮继续保留;等待 LLM 时在消息区持续显示动态状态和进行中提示,连续流式 delta 合并到动画帧更新并跳过重复 Runtime state。OpenAI Chat SSE 会跳过空 `choices` 心跳 / 元数据事件,收集 usage-only 尾包、保留 finish reason 与上游 error message,收到 `[DONE]` 后立即结束;正文与 finish reason 已接收后出现尾包异常时保存已完成正文,不把整轮改写成失败。持久事件订阅失败时显示非致命错误,聊天事件监听不可用或首个文本片段前流式失败时降级普通回复并继续落盘。 -- 2026-07-11 补充:为缩小单 Agent 与 Codex CLI 在代码任务上的差距,Runtime 工具箱新增 `project.search` 和 `file.patch`,并扩展 `file.read` 的按行分页。`project.search` 在项目内执行有界字面量检索,默认忽略大小写,返回相对路径、行号和匹配行,跳过 `.agent`、敏感配置、依赖和构建目录;权限继承 `file.read`。`file.read` 接受 `startLine / maxLines`,返回带行号的最多 240 行、8,000 字符上下文,允许 Agent 继续分页而不是只看到文件开头约 900 字符。`file.patch` 只做 `oldText -> newText` 精确替换,必须声明预期匹配数,匹配数不符时不写入;它继承 `file.write` 权限,复用项目写锁和 Runtime 动作账本,并追加不含代码正文的 `agent.runtime.file.patch` 审计记录。三者组成“搜索定位 -> 分段读取 -> 局部修改 -> 再次读取验证”的最小代码工作闭环,不开放任意 shell。 -- 2026-07-12 补充:单 Agent Runtime 工具箱新增受策略保护的 `file.delete`,补齐项目文件的完整生命周期。该工具只接受项目内相对 `path`,使用独立且默认 `confirm` 的 `file.delete` 权限,不继承 `file.write`;绝对路径、`..`、反斜杠、有效或悬空符号链接、目录和整个 `.agent/**` 控制面都失败关闭。Runtime 在项目写锁内、删除前先推进 project revision 并锁存当前 run 的 verification gate,成功后写 `agent.runtime.file.delete` 审计而不记录文件正文;目标已不存在时返回幂等 observation,但不撤销保守推进的 revision。自动与确认删除都经过 durable action ledger;pending action v3 额外绑定创建时的全局 project revision,等待确认期间任一 Agent 推进 revision 后旧动作必须进入 `needs-reconciliation`,不得删除漂移后的目标。崩溃停在 `executing` 时同样进入 `needs-reconciliation`,不得自动重放。删除后必须通过当前 revision 的 `project.verify` 或 `game.static_smoke` 才能收束;普通用户聊天和正式用户窗口不新增删除入口,也不因此开放任意 shell。 -- 2026-07-12 加固:`file.delete` 取得项目写锁后必须重新读取当前项目和 Agent 权限策略;锁竞争期间从 allow 改为 deny 时立即阻断,从 allow 改为 confirm 时自动动作退回待确认,只有已确认动作可继续。Agent 私有记忆以及客户端开发面板的文件、记忆、资产、草案、导出和 checkpoint 恢复写入都在同一项目锁内保守推进全局 revision,确保等待中的旧删除动作不会作用于客户端刚改写的内容。manifest 持久化使用同目录临时文件;平台不能覆盖既有文件时先移动到 `.manifest.json.previous` 恢复副本,主文件缺失时从副本读取,安装新文件失败时恢复旧文件。 -- 2026-07-11 补充,2026-07-12 更新:单 Agent 代码闭环新增开发专用 `project.verify`,用于在修改后执行项目根 `package.json` 已定义的固定脚本 `check / typecheck / test / lint / build`,或以 `check: / test: / lint: / typecheck: / build: / verify: / validate:` 开头、后缀由安全非空段组成的命名脚本;当前只支持 npm,不接受自由命令、参数或工作目录。Agent 必须先读取普通文件 `package.json`,再把真实存在的脚本名、完整原始脚本文本 `expectedCommand` 和 1-300 秒超时一起提交;Runtime 在真正执行前重新解析 JSON,要求脚本仍存在且正文精确一致,脚本漂移时拒绝执行。非 npm `packageManager` 或 pnpm / yarn / bun 锁文件必须失败关闭;`pre* / post*` 生命周期脚本名不在允许范围,npm 执行再附加 `--ignore-scripts`,阻止所选脚本关联的 pre/post lifecycle。该工具使用独立、默认 `confirm` 的 `project.verify` 权限,不再与 `command.run_limited` / `game.static_smoke` 共用授权;确认指纹覆盖脚本正文和超时。执行时不经过 App 自行拼接的 `bash -c`;继承环境被清理到 PATH 与必要平台变量,HOME/TMP/npm cache 隔离,stdin 关闭,输出保留有界头尾。Unix 下验证根进程正常结束或超时都会清理同进程组残留后代;项目写锁会按持有 PID 回收崩溃遗留锁,并拒绝 `.agent` 符号链接逃逸。进入进程执行后的成功、非零退出、启动失败和超时会写 `.agent/logs/command.log`、manifest command run 与 `agent.runtime.project.verify` 审计;输入预检拒绝则只进入 Runtime observation / error 事件。输出先过滤敏感内容再进入 observation。只要最新 `project.verify` 未通过,或通过后又发生 `file.write / file.patch / file.delete / project.restore`,Runtime 就拒绝模型用空 actions 假完成,继续要求修复和重新验证;多窗口重复无进展而以 `loop-budget-exhausted` 终止时,仍未形成新通过结果则保持失败。该能力会执行用户项目自身脚本,环境隔离不等同于 OS 沙箱,不能把不可信项目脚本视为安全代码;它不是自由 shell 代理,也不进入普通用户命令入口。 -- 2026-07-11 补充:开发侧新增 headless 单 Agent Runtime 入口 `npm run ai-game-creator-shell:agent-task -- [--init] `。该入口不实现第二套 Agent,只复用 Tauri App 的持久任务队列、per-agent 锁、LLM 路由、权限策略、工具 action / observation loop、对话和审计文件,并轮询到 `completed / failed / waiting-for-confirmation` 后用稳定键值行退出;`--init` 只在显式传入且 manifest 不存在时初始化项目。遇到待确认动作时 CLI 返回非零并打印 actionId、tool 和脱敏摘要,后续仍由开发窗口完成确认,不提供静默 `--yes` 绕过。 -- 2026-07-15 收口:废止后台 Agent 工具规划和最终回复对 `EmptyResponse / Timeout / Connectivity / Transport / 408 / 429 / 5xx` 的原样自动重试。每个 Provider request lifecycle 只允许一次物理请求,专用客户端强制 `max_retries=0`,不继承全局或 per-Agent 的 `maxRetries`;可观察错误写唯一 `failed` 终态,`started` 后没有可信终态则进入 `needs-reconciliation` orphan barrier。只有显式 steer、Goal resume 或人工 reconciliation 后的新 request slot 才能建立新 lifecycle;工具协议格式修复使用新的 repair slot/lifecycle,不属于传输重试。 -- 2026-07-11 调整,2026-07-12 更新:后台单 Agent 的 planning loop 每 6 轮形成一个上下文压缩窗口,每轮工具动作上限仍为 3;6 轮不再是整个 run 的固定上限。`loopIteration` 在同一 run 内连续递增,`maxLoopIterations` 指向当前窗口结束轮次,跨重启待确认动作按 context bundle 的 `nextLoopIndex` 继续。每个窗口结束时压缩已有 observation;窗口产生新的独立观察时继续同一 run,最近 6 轮没有独立进展或相邻窗口指纹重复时才进入 `failed / budget-exhausted`,并记录 `loop-budget-exhausted`,不会伪装完成。该调整只作用于后台单 Agent Runtime,不改变游戏草案 Generator/Evaluator 的 3 轮上限;旧实施摘要中“后台 3 轮后整理最终回复”或“整个 run 最多 6 轮”的描述由本条取代。 -- 2026-07-12 补充:后台 Agent 每个 run 的可恢复 planning 上下文使用 `.agent/runtime/context-bundles//.json`。Runtime 通过临时文件替换原子写入,绑定 Agent、Task、Session、Run 和任务正文,保存 `nextLoopIndex`、当前窗口、计划、fallback response、压缩后的 observation 与上一窗口指纹;单文件最多 64 KiB、最多 12 条 observation。写入前统一截断并过滤敏感内容和项目绝对路径,安全校验失败时拒绝落盘;读取时要求普通文件,并校验 schema、Agent、Session、Run、任务正文和 observation 数量,身份不一致时拒绝续跑。该路径属于 Runtime 私有控制面,与根级 `.agent/context.bundle.json` 的旧 run-control 辅助文件不是同一契约,通用文件工具不得暴露。 -- 2026-07-11 调整,2026-07-15 收口:开发者投递的后台任务从队列记录、Runtime `currentTask/currentGoal` 到待确认动作私有账本统一保留最多 4,000 字符,不再在入队时截成 180 字符。必要的 180 字符可见摘要只用于私有执行界面;公共 event、Agent DB、receipt、activity、output 和报告不再保存任务预览或正文,只保存 `taskSha256 / taskChars` 等身份、哈希和计数。LLM planning、显式恢复、确认续跑和重启恢复继续使用私有完整任务字段,避免丢失长需求末尾的验收条件、禁止项或输出格式。 -- 2026-07-11 调整,2026-07-15 收口,2026-08-06 修正 token 契约:后台结构化 planning 使用独立的 4,000 生成 token 预算,最终回复使用 2,400;两者显式请求 low reasoning effort 和 low text verbosity。生成预算包含可见输出与隐藏 reasoning token,不是可见输出余量,也不是输入加输出总量。`platform-llm` 会把 reasoning effort 同时映射到 OpenAI Responses 的 `reasoning.effort` 与 Chat Completions 的 `reasoning_effort`,未设置时不新增字段;协议中立预算按 endpoint 能力映射为 Chat `max_completion_tokens` 或 legacy `max_tokens`、Responses `max_output_tokens`、Anthropic `max_tokens`。AGC 配置、Provider 请求序列化和重试 / handoff 指纹中的既有 `maxOutputTokens` 键冻结不变,避免升级后进入 reconciliation。低推理强度和较大的生成预算只用于降低空响应概率;`EmptyResponse` 仍按单次 lifecycle 的歧义失败处理,不再自动原样重放。 -- 2026-07-11 补充:后台单 Agent 的工具计划响应只接受可反序列化为计划 schema 的 JSON object。解析器提取模型输出中的首个完整对象并允许对象后带普通说明;未找到完整 JSON 对象,或提取对象无法反序列化为工具计划时,Runtime 最多追加 2 次自动格式修复请求。每次修复只携带限长、脱敏后的上一次无效输出,并写入 `agent.runtime.tool_plan.repair` 审计。两次修复后仍无有效对象则按工具规划失败处理;工具规划阶段的普通文本不得转换为默认的空 actions + response,也不得据此把任务标记为完成。 -- 2026-07-11 调整:工具计划顶层 `thinkingSummary / plan / actions / response` 四个字段必须同时存在,未知顶层字段、空 thinkingSummary 和空 tool 均属于协议错误并进入同一格式修复预算,`{}` 或前置无关 JSON 对象不能再触发空计划收束。空 actions 表示 planning 收束;response 非空时直接采用,response 为空时进入独立的最终回复生成。`agent.runtime.project.verify` 审计同时保存 `runId / actionId / actionFingerprint`,使并行 Agent 的失败与通过记录能够精确归属到发起动作。 -- 2026-07-12 补充,2026-07-27 更正:OpenAI Chat / Responses 的后台 Agent 工具 planning 改用唯一 `submit_agent_tool_plan` 原生 function tool,字符串 `tool_choice=required` 和 strict schema;只接受恰好一次同名调用,arguments 继续经过本地计划 schema、工具白名单和权限策略校验,错误函数、多调用或非法 arguments 进入原有两次格式修复预算且不产生副作用。本条原写「Anthropic 保留文本 JSON 回退;planning 非流式」,已由 2026-07-27「Anthropic 与流式统一使用 Provider 原生工具」取代——Anthropic 同样发送原生工具目录,planning 不再因协议强制非流式。每轮成功协议写 `agent.runtime.tool_plan.protocol`,修复审计记录 protocol、callId 和 functionName。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `preview.start`,让 Agent 在完成写盘或静态自检后能按策略自行启动当前项目的 `127.0.0.1` 本地 HTTP 预览。该工具复用 `preview.start` 权限策略、项目写锁、共享 `PreviewRegistry`、manifest 预览状态、`.agent/logs/preview.log` 和 run trace 追加逻辑;写入 `.agent/agent.db` 的审计类型为 `agent.runtime.preview.start`。发给 LLM 的 observation 只包含 localhost URL 和端口,不包含用户项目绝对路径。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `canvas.asset_generate`,让美术类 Agent 可在 loop 中自行请求生成首版美术素材。该工具读取 AppData / Tauri 配置中的 `editorApi`,复用 `canvas.asset_generate` 权限策略、项目写锁、External Editor API 生成和下载链路、manifest 资产登记以及 `canvas.asset_generate` 本地索引记录;另写 `agent.runtime.canvas.asset_generate` 记录到 `.agent/agent.db`,标明触发的 agent 与本地素材路径。API Key 不进入 prompt observation、manifest、agent.db 或日志;策略要求确认或拒绝时不会调用外部 API。 -- 补充:规范 Agent ID 统一使用 manifest taskId,例如 `art-asset-plan` 和 `code-prototype`;历史前端曾使用的 `group-role` 别名只在 Tauri command 层兼容并映射到规范 taskId。主窗口 Agent 状态列表通过 `read_game_creator_agent_runtimes` 批量读取 `.agent/runtime/agents/.json` 和最近任务,把每个 Agent 的 Runtime 状态、当前动作和最近 task 直接显示在状态卡片和 `/agents` 汇总里。 -- 2026-07-10 补充:单 Agent 聊天和后台 planning prompt 统一注入本 Agent 的 Runtime 连续上下文,包括最近状态、runId、当前任务、计划、观察、最近回复、最近工具动作、最近事件、最近任务和工具策略摘要;上下文只按规范 taskId 读取本 Agent runtime,进入 prompt 前过滤密钥和本机绝对路径。新后台 run 启动时继承同 Agent 上次 `recentToolCalls` 和 `lastResponse`,让下一轮任务能基于前一轮真实行动证据继续推理,同时不串入其他 Agent 的 runtime。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `file.list`,让 Agent 可先列出项目文件摘要或某个相对目录下的条目,再决定是否读取具体文件或继续行动。该工具复用 `file.list` 项目权限策略,策略要求确认或拒绝时不会枚举项目文件;observation 只包含项目相对路径、类型和大小,不读取文件内容、不返回项目绝对路径。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `project.diff`,让 Agent 可基于已存在 checkpoint 观察本地项目新增、修改和删除摘要。该工具复用 `project.diff` 项目权限策略,策略要求确认或拒绝时不会执行 diff;observation 只包含 checkpoint id、三类计数和项目相对路径,不返回本机绝对路径或文件正文。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `agent.run_status`,让 Agent 可在 loop 中读取自己、目标 Agent 或一组 Agent 的 Runtime 状态摘要,用于判断同伴是否正在运行、最近任务和最近工具动作。该工具复用 `agent.run_status` 项目权限策略,策略要求确认或拒绝时不会读取状态;observation 只包含 agentId、status、phase、runId、当前任务、当前动作、下一步、计划摘要、最近任务、最近工具和错误摘要,不返回 `.agent/runtime/*` 文件绝对路径。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `agent.delegate`,让 Agent 可把明确子任务投递到另一个 Agent 的独立后台队列。该工具复用目标 Agent 既有锁和 pending drain 语义,不创建平行 runtime;同一目标 Agent 串行,不同 Agent 可并行。该工具使用独立 `agent.delegate` 权限策略,策略要求确认或拒绝时不会写目标对话、不会启动目标后台任务,也不会写 `agent.runtime.agent.delegate` 审计记录。 -- 2026-07-10 补充:主窗口 Agent 状态栏在开发模式新增“调度 Ready”控制,用来显式调用 `schedule_game_creator_agent_ready_tasks`。该控制先读取项目策略,命中 `agent.schedule_ready` confirm 时走现有确认弹窗,确认后才把 manifest ready task 投递到对应 Agent Runtime;普通用户窗口不展示这个开发控制。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `agent.schedule_ready`,让 Agent 在完成或更新 manifest task 后可按项目权限策略自行调度新 ready task。该工具复用同一个 scheduler:扫描依赖已完成且仍为 pending 的 manifest task,先标为 running,再按 taskId 投递到对应 Agent 的既有后台队列;策略要求确认时当前 Agent 停在 `waiting-for-confirmation`,不会静默启动下游 Agent。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `project.checkpoint`,让 Agent 在 `file.write`、`task.update` 或批量修改前自行创建本地 checkpoint。该工具复用 `project.checkpoint` 策略和项目写锁,observation 只返回 checkpoint id、文件数和总字节数,不返回本机绝对路径;策略要求确认时不创建 checkpoint。 -- 2026-07-10 补充:后台 Agent Runtime 的白名单工具继续扩到 `project.restore`,让 Agent 在 diff 或自检发现走偏后可请求恢复到指定 checkpoint。该工具复用 `project.restore` 确认策略和项目写锁,observation 只返回 checkpoint id、恢复文件数和删除文件数;默认确认策略下不会静默回滚用户项目。 -- 影响范围:`apps/ai-game-creator-shell` 的 Tauri command、Agent Runtime state/event、开发窗口单 Agent 聊天、项目内 Agent 对话弹窗、`appSurface.test.ts` 和 AI 游戏创作 App 实施计划。 -- 验证方式:运行 Tauri Rust 后台 Agent 并行测试、壳前端 appSurface 测试、壳 typecheck、编码检查和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-08 AI 游戏创作 App v1 使用单窗口首页作为普通用户入口 - -- 背景:GameAgent V1 首页需求把登录后的入口定义为单窗口客户端首页,旧“先选项目再打开主窗口”的启动器概念会让普通用户流程割裂,也不符合首页先输入需求再选择目录创建项目的交互。 -- 决策:普通用户启动 App 后先检查平台登录态,未登录只展示登录页,登录后进入同一个客户端壳。客户端左侧栏和顶部栏常驻,中部在首页、项目组、指南 / 反馈和项目开发占位之间切换;旧 Tauri 窗口 command 只保留兼容,不进入用户主流程。首页支持 `做游戏` / `做素材` / `做方案` 三种模式,发送需求时弹原生目录选择,非空目录必须二次确认;确认后只初始化本地项目、导入附件、追加首条用户需求和接收回执、写最近项目,并切到项目开发占位,不启动真实生成、不调用平台美术生成或 LLM 聊天。 -- 补充:项目组页在同一窗口管理最近项目、打开项目、新建项目和显示目录。打开项目只进入已初始化且 `.agent/manifest.json` 可读的本地项目并切到项目开发占位;无效项目禁用,不自动重建历史路径。首页最近项目最多展示 3 个,空时隐藏。 -- 补充:项目开发占位展示项目名、路径、创建模式、首条需求、附件导入结果、最近 run 状态和后续“项目开发画布”占位;“项目开发画布”是 GameAgent 项目的工作区概念,不等同于 `/editor` 图片画布工程。 -- 补充:首页账户 / 泥点 / 精选素材只读取平台真实接口 `/api/profile/dashboard`、`/api/profile/wallet-ledger` 和 `/api/editor/showcase/resources`;失败时显示轻量空态,不伪造后端未下发字段。 -- 补充:2026-07-18 修复首页“开启创作”打开目录选择器时的客户端冻结。目录和文件 picker 统一使用非阻塞 callback,并绑定到当前 `client` 窗口;不得把 `blocking_pick_folder` / `blocking_pick_file` 放回同步 Tauri command。首页直接创建项目仍是普通用户主路径,不要求先进入项目组。 -- 影响范围:`apps/ai-game-creator-shell` 登录后渲染入口、首页 / 项目组 / 项目开发占位 UI、本地项目初始化与附件导入流程、AI 游戏创作 App 实施计划和 `CONTEXT.md`。 -- 验证方式:运行 `npm run test -- apps/ai-game-creator-shell/tests/appSurface.test.ts`、`npm --prefix apps/ai-game-creator-shell run typecheck`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`、`CONTEXT.md`。 - -## 2026-07-03 AI 游戏创作 App 本地试玩包导出只打包运行白名单 - -- 背景:AI 游戏创作 App 需要给普通用户提供首版本地试玩包,但不能把项目记忆、trace、日志、运行时配置或密钥类文件混入可分发 ZIP。 -- 决策:v1 新增 `/export` 聊天入口和 `project.export_package` 确认命令。导出前重新校验 `game/index.html` 是可试玩自包含 HTML;ZIP 只包含 `game/**`、`assets/**` 和 `exports/README.md`,输出到 `exports/playtest-package-*.zip`;导出拒绝符号链接和不安全条目路径,并写入 manifest `commandRuns`、`.agent/logs/command.log` 和 `.agent/agent.db`。 -- 补充:新增 `/exports` 只读聊天入口和 `project.export_list` 自动命令,用于列出当前项目 `exports/playtest-package-*.zip` 历史试玩包;该入口只读、不删除旧包、不做系统分享,给用户继续 `/export` 或显示目录的草稿。 -- 影响范围:`apps/ai-game-creator-shell` 的聊天命令、Tauri 本地项目能力、共享命令契约和 AI 游戏创作 App 实施计划。 -- 验证方式:运行 AI 游戏创作壳主窗口 smoke、Tauri `export` 定向测试、共享契约测试、类型检查、编码检查和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-01 AI 游戏创作 App v1 使用本地 JSONL 对话和派生 Agent 状态 - -- 背景:AI 游戏创作 App 已有 Godcoder 式本地工程护栏、项目黑板、角色私有记忆、manifest 和 run trace;新增结构化对话记录、agent 状态列表和单 agent 对话入口时,需要避免引入平行状态源或提前承诺后台 runner 能力。 -- 决策:v1 结构化对话记录统一使用本地 `.agent/conversations/` append-only JSONL。普通聊天写 `.agent/conversations/project.jsonl`;从 agent 状态列表进入单个 agent 后,用户消息、agent 回复、工具建议和错误只写对应 `.agent/conversations/agents/.jsonl`。Agent 状态列表从 `.agent/manifest.json` 的任务 / 角色清单和 `.agent/run.latest.json` / `.agent/runs/.json` 的 step、taskGraph、passPlans、lifecycleStatus 派生,并把 `taskGraph.tasks` 的任务状态与 active / carry-over / ready 编排标记显示在主窗口和单 agent 对话入口中;单 agent 最近证据里的安全相对输入 / 输出路径只填入 `/read ` 草稿,仍由用户发送并走既有 `file.read` / `agent.trace_read` 权限流。不新增独立状态数据库。项目黑板和角色私有记忆继续只保存稳定摘要,不承载原始对话流水。 -- 补充:2026-07-08 起普通用户入口改为单窗口客户端首页;旧独立启动器 / 主窗口切换口径废止。首页发送需求或项目组新建项目时,先选择目录并在非空目录时二次确认,初始化成功后写最近项目并切到项目开发占位;取消或初始化失败则不切换视图、不写最近项目。最近工作区只保存在本机 WebView storage,可单项移除或清空,不进入项目文件或共享记忆;已初始化项目优先显示 manifest 项目名并保留路径副信息,`.agent/run.latest.json` 可读时显示最近 run 状态。最近项目路径缺失、不是目录、缺少可读 `.agent/manifest.json` 或检查失败时禁用打开,刷新只重新执行只读检查;“显示”只用系统文件管理器打开已确认存在的本地目录,未初始化但存在的目录也可显示,避免把历史路径误当新项目重建。 -- 补充:项目开发占位“显示目录”复用同一只读目录打开能力,只打开当前本地项目目录,不初始化项目、不写项目文件、不切换工作区;顶部只读显示 manifest 项目名、项目路径、最近 `.agent/run.latest.json` 的 run 状态摘要和当前预览状态,并通过“刷新状态”重新读取同一 trace,不新增状态数据库。最近项目资产入口只读展示 localPath、kind、mediaType 和 source.kind,点击仍走原 `file.read` 权限流;旁边的“读取命令”只填入 `/read ` 草稿,不直接读取文件或绕过权限。项目开发占位里的项目黑板和 Agent 状态快捷入口仍只填入聊天草稿,不直接读取 run 辅助文件、不写 `.agent/policy.json`、不调用 LLM。 -- 补充:首页、项目组和项目开发占位共用同一个运行时配置弹窗,配置只读写 Tauri 应用配置目录中的 `game-creator.config.json`,不写入项目文件或对话历史。 -- 补充:项目组“打开”只进入已初始化且 `.agent/manifest.json` 可读的 AI 游戏项目;路径不存在、不是文件夹或只是普通文件夹时不切换到项目开发占位、不创建目录,用户需要创建或初始化时走“新建项目”。 -- 影响范围:`apps/ai-game-creator-shell` 的主窗口 agent 状态列表、单 agent 对话入口、本地项目文件结构、共享契约和 AI 游戏创作 App 实施计划。 -- 验证方式:文档更新先运行 `npm run check:encoding` 和 `git diff --check`;后续工程落地时补充壳 typecheck、Tauri Rust 测试和对话 JSONL / 状态派生的定向测试。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-06-30 AI 游戏创作 App 使用客户端配置文件 - -- 背景:`apps/ai-game-creator-shell` 是客户端 App,不应通过 `.env` 或进程环境变量承载 LLM / 画板同步配置;旧口径会让本地 secrets、CLI wrapper 和桌面 App 启动逻辑混在一起。 -- 决策:仓库内 `apps/ai-game-creator-shell/game-creator.config.json` 只作为默认模板;发布 App 启动时在 Tauri 应用配置目录写入默认 `game-creator.config.json`,真实密钥和本机覆盖项都保存在该运行时配置文件中。主窗口提供“配置”面板读写该运行时 JSON;开发 CLI 无 AppHandle 时才回退读取仓库旁边的模板和 gitignored 本机覆盖文件。`llm.apiKey/baseUrl/model/apiKind/stream/requestTimeoutMs/maxRetries/retryBackoffMs` 驱动全局 LLM 路径,`agentLlm.` 可为 Planner、Generator 和角色 agent 单独覆盖 API Key、base URL、模型、API 类型和流式请求,空项继承全局配置;`editorApi.baseUrl/apiKey` 驱动画板项目同步;`/llm-status` 只展示全局和各 agent resolved 后的 baseUrl、model、apiKind、stream 和 API Key 是否存在,不显示密钥;`/llm-routes` 复用同一只读检查结果,按 agent 展示 resolved provider 路由、单独路由数量和缺口数量,不请求上游、不显示密钥、不写项目。生成游戏或平台美术遇到 LLM / editorApi 缺配置错误时,主窗口自动打开运行时配置弹窗,但错误消息仍只显示缺失项,不回显密钥值。 -- 影响范围:AI 游戏创作 App 的 Tauri Rust 配置加载、主窗口配置面板、CLI wrapper、agent-run smoke、`check-config` 门禁、`.gitignore` 和实施计划文档。 -- 验证方式:运行 `npm run ai-game-creator-shell:typecheck`、`cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-07-02 图片画布生成抠图背景色使用 screenColor 传递 - -- 背景:画布角色、图标和 UI 素材生成过去固定要求 `#00FF00` 绿幕,后续 BGfilter 服务需要按生成时背景色做去背景,不能继续把背景色写死在 prompt 或后处理里。 -- 决策:角色形象、图标 spritesheet 和 UI 设计图素材提取不再向用户提供手动抠图背景色选择;前端用户路径统一提交 `screenColor=auto`,但用户可见生成输入快照不再写入 `抠图背景色` 或 `抠图模型`。api-server 在 12 个候选色中自动决策具体 hex,失败后兜底 `#CFEFFF`;最终 prompt 和 BgFilter 去背景只接收解析后的具体 hex 作为 `screen_color`。后端仍保留手动 hex 解析能力供内部兼容。角色动作背景色和抠帧口径已由 2026-07-09 决策取代。 -- 影响范围:`/editor/canvas` 角色形象生成、图标素材生成、UI 设计图素材提取、BgFilter 服务入参、图片画布 MVP 和角色形象生成设计文档。 -- 验证方式:运行画布生成模型 / workflow / API client 定向前端测试、`cargo test -p api-server editor_green_screen --manifest-path server-rs/Cargo.toml`、`cargo test -p platform-image generated_asset_sheet_light_blue_key_color_removes_selected_background --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`。 - -## 2026-07-05 图片画布抠图背景色自动决策 - -- 背景:手动背景色选择对用户负担较高,且不同角色、图标和 UI 素材主题需要避开不同主体色;但 BgFilter 和生成 prompt 仍必须拿到明确的纯色 hex。 -- 决策:前端用户路径直接固定通过 `screenColor=auto` 提交,不再展示背景色选项;api-server 新增 `editor_screen_background_decision` 模块,在角色形象、图标 spritesheet 和 UI 设计图素材提取组装 prompt 前解析 `screenColor`。手动 hex 直接校验并使用;`auto` 通过服务端 LLM 在 12 个候选色中选择具体 hex,最多重试 3 次,LLM 未配置、请求失败或返回非法颜色时 fallback 到 `浅雾蓝 #CFEFFF`。自动解析结果不写入用户可见生成输入快照;最终生图 prompt 和 BgFilter `screen_color` 永远只接收具体 hex,不透传 `auto`。 -- 影响范围:`/editor/canvas` 角色形象生成、图标素材生成、UI 设计图素材提取、api-server LLM 调用、BgFilter 参数、图片画布文档。 -- 验证方式:运行背景决策模块单测、画布生成模型 / workflow / API client 定向前端测试、`cargo test -p api-server editor_screen_background_decision editor_green_screen --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`、`docs/【编辑器】画板UI设计图生成入口设计-2026-06-17.md`、`docs/【编辑器】画板图标素材生成入口设计-2026-06-15.md`。 - -## 2026-07-05 BgFilter 失败时本地纯色去背兜底 - -> 后续更正:本条关于手动去背景仍使用独立 BiRefNet BFF 的描述已由 2026-07-14「手动去背景迁移到 BgFilter complex 模式」、2026-07-15 OSS 签名 URL 决策和 2026-07-17 内存生命周期决策取代。下文保留作历史记录。 - -- 背景:曾用一次性 BgFilter live probe 稳定复现 BgFilter 对 2K 输入返回 `HTTP 500 {"detail":"inference failed"}`,浏览器生成链路会因此收到“BgFilter 服务返回非成功状态”。 -- 决策:角色形象生成、图标 spritesheet 生成和 UI 设计图素材提取仍优先调用独立 BgFilter;若 BgFilter 请求失败、返回非成功状态、返回空图片或非法图片,api-server 记录 warning 后使用本地 `editor_green_screen` 按解析后的纯色背景执行确定性去背兜底,不中断生成。手动任意图片去背景仍只走独立 BiRefNet BFF,不使用该兜底。 -- 更正(截至 2026-07-10 实现):BgFilter 失败/熔断后不再直接本地兜底,而是先走阿里云通用抠图,仅阿里云也失败才本地 `editor_green_screen` 键色兜底;口径统一见 2026-07-09「角色动作视频…阿里云抠帧」决策,并已扩展到本条的角色形象/图标/UI 三条静态生图链路。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、BgFilter 运维排障、图片画布生成后处理。 -- 验证方式:运行 `cargo test -p api-server editor_canvas_screen_background_generation_uses_bgfilter_postprocess editor_green_screen --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`、`docs/【编辑器】画板UI设计图生成入口设计-2026-06-17.md`、`docs/【编辑器】画板图标素材生成入口设计-2026-06-15.md`。 - -## 2026-07-03 图片画布生成纯色背景资产接入 BgFilter - -> 后续更正:本条关于 multipart `file`、手动去背景独立 BiRefNet 配置以及 BgFilter 失败后直接本地兜底的描述,已分别由 2026-07-14、2026-07-15 OSS 签名 URL 决策和 2026-07-17 内存生命周期决策取代;其中固定 provider timeout 配置也已被 2026-07-21 的公式化双预算取代,当前请求分别携带 `maxQueueWaitMs / callBudgetMs`,attempt 按 `N × est × 2` 派生,冻结 `N=16 / est=5000ms` 时为 `160s`,调用预算为 `321s`。下文保留作历史记录。 - -- 背景:独立 BgFilter 服务已部署在 image host,并提供 `POST /bgfilter/remove-background`,支持显式 `screen_color` 和 `seg_model`。手动去背景已有独立 BiRefNet BFF,不能把两个服务的配置或语义混在一起。 -- 决策:角色形象生成、图标 spritesheet 生成和 UI 设计图素材提取在保存带纯色背景源图后,统一调用 BgFilter 生成透明 PNG;请求 multipart 字段为 `file`、`screen_color=` 和内部固定的 `seg_model=birefnet`。`segModel` 虽是后端可识别的内部兼容字段(另保留 `anime-seg`),但不向用户或外部 OpenAPI 暴露:当前 BgFilter 的内存与并发容量不适合由调用方自由切换模型。BgFilter 使用独立配置 `GENARRATIVE_EDITOR_BGFILTER_BASE_URL`、`GENARRATIVE_EDITOR_BGFILTER_TOKEN`、`GENARRATIVE_EDITOR_BGFILTER_REQUEST_TIMEOUT_MS`,默认 base URL 为 `http://58.87.105.82/bgfilter`,默认请求超时 `180000ms`,token 未配置时复用 `GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_TOKEN`。手动 `POST /api/editor/images/background-removals` 继续使用独立 BiRefNet 配置 `GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_BASE_URL`,不受 BgFilter 影响。BgFilter 参数里的 `seg_model=birefnet` 只表示 BgFilter 内部分割后端,不等于手动去背景的独立 BiRefNet 服务。若 BgFilter 失败,api-server 对这些标准纯色背景生成图使用本地 `editor_green_screen` 兜底;连续失败达到 `GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_FAILURE_THRESHOLD`(默认 `3`)后,`GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_COOLDOWN_SECONDS`(默认 `300`)内直接本地兜底。角色动作背景色和抠帧口径已由 2026-07-09 决策取代:角色动作同样使用多色自动决策,抽帧后优先阿里云通用抠图,失败再按选定背景色本地兜底。更正(截至 2026-07-10 实现):BgFilter 失败与熔断期本条描述的「直接本地兜底」已过时——角色形象/图标/UI 三条静态生图链路同样先走阿里云通用抠图,仅阿里云也失败才本地 `editor_green_screen` 兜底。 -- 影响范围:`server-rs/crates/api-server/src/config.rs`、`server-rs/crates/api-server/src/editor_project.rs`、图片画布 MVP 文档和角色形象生成设计文档。 -- 验证方式:运行 `cargo test -p api-server config::tests::from_env_reads_editor_bgfilter_settings_and_reuses_background_token editor_project::tests::editor_canvas_screen_background_generation_uses_bgfilter_postprocess --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`。 - -## 2026-07-03 作品公开默认关闭 - -- 背景:作品发布完成不应默认进入公开广场 / 公开详情 / 公开互动消费路径,需要先由后台可见性开关明确开启。 -- 决策:各玩法源表的 `visible` 新作品默认值改为 `false`;从草稿首次发布时仍保持 `false`,只有已发布作品再次发布 / 更新时才保留既有 `visible`。公开列表、详情、点赞、Remix 和正式公开 runtime 继续按 `Published + visible=true` 判断。旧迁移数据缺少 `visible` 时仍补 `true`,避免历史已公开作品被批量隐藏。 -- 影响范围:`spacetime-module` 各玩法作品表、发布 / 编译 / Remix 写入路径、统一公开作品 read model、后台作品可见性管理。 -- 验证方式:运行 `cargo fmt --manifest-path server-rs/Cargo.toml --all`、`cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`、`npm run check:spacetime-schema`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`docs/technical/【后端架构】统一公开作品ReadModel设计-2026-05-26.md`。 - -## 2026-07-04 陶泥儿精选改为素材提交审核后公开 - -- 背景:`/creation` 的 `陶泥儿精选` 过去依赖 `editor_project_resource.public_showcase_enabled`,生成画布资源默认可公开,和“作品公开默认关闭、由用户主动投稿精选”的运营要求冲突,也无法在后台审核、返还泥点和配置固定活动卡。 -- 决策:`陶泥儿精选` 的公开事实改为独立 `editor_showcase_asset` 审核表。生成素材默认不公开;用户在账号级素材库对 `sourceType="generated"` 且有媒体内容的素材提交审核,后端快照素材信息并写入 `pending`。后台审核通过后写入 `approved`,但默认 `display_enabled=false` 且 `showcase_category=null`,运营可按前台具体 Tab 手动设置分类并开启展示;未设置分类的素材展示开启后进入前台“全部”,但不进入角色 / UI / 音乐 / 美宣具体分类。审核通过时按 `generation_cost_mud_points` 返还 50% 泥点;拒绝后写入 `rejected`。公开接口 `GET /api/editor/showcase/resources` 返回已通过、展示开启且媒体非空的快照,按通过时间和 `showcaseId` 倒序分页,并可携带后台配置的固定活动卡。旧 `editor_project_resource.public_showcase_enabled` 和旧 PATCH 接口只保留兼容,不再驱动精选公开。 -- 影响范围:`server-rs/crates/spacetime-module/src/editor_project_storage.rs`、`spacetime-client` 绑定与 mapper、`api-server` 编辑器和后台路由、admin-web 精选审核页、素材库右键菜单、`/creation` 精选瀑布流、图片画布文档和后端表目录。 -- 验证方式:运行 `npm run spacetime:generate`、`npm run check:spacetime-schema`、`cargo check --manifest-path server-rs/Cargo.toml -p spacetime-module -p spacetime-client -p api-server`、前端 / 后台 typecheck 与精选相关组件测试,确认默认不公开、提交后 pending、审核通过后展示和返还、展示开关与点赞生效。 -- 后续修正:精选批准、确定性返还流水和返还完成标记必须由同一个 SpacetimeDB procedure 在单事务内落地,失败时不得先留下 `approved`;已公开精选私有对象通过同 owner 的精确 `assetObjectId` / `objectKey` 派生匿名读取授权,不把 `generated-*` 前缀整体公开。 -- 关联文档:`docs/【玩法创作】创作主页与项目入口改版计划-2026-06-18.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-03 外部编辑器 API 生成默认写入画布与素材库 - -- 背景:外部 API 面向美术 Agent 使用时,需要从自然语言自动选路,并保证生成结果不会只停留在接口回包里;同时后续素材生成需要复用已抽象出的美术规范,避免每次重新追问风格要求。 -- 决策:外部编辑器 API skill 在新对话首个生成前先确认画布名称,并创建 / 复用同名画布项目和素材库文件夹。所有外部生成请求默认携带 `projectId`、`assetFolderId`、素材展示名和 `canvasCompletion`,使结果进入画布和素材库;角色动画端点当前不直接返回 `asset`,由 helper 在动画成功后用首帧补建素材库记录。skill 先把用户需求抽象为可复用美术规范,缺少目标素材必需信息时再追问;已有规范且用户未提出新规范时自动复用。 -- 影响范围:`.codex/skills/genarrative-external-editor-api`、外部 OpenAPI 使用说明、外部画布生成集成方。 -- 验证方式:运行 skill 校验、helper 自测、Python 编译检查、编码检查和 `git diff --check`;真实线上生成 smoke 需要本机 `~/.config/genarrative/external-editor-api.json` 中有有效 API Key。 -- 关联文档:`docs/openapi/genarrative-external-v1.openapi.json`、`.codex/skills/genarrative-external-editor-api/SKILL.md`。 - -## 2026-07-03 新建项目与 AI 任务 ID 使用短前缀 - -- 背景:新建外部画布项目和 AI 任务 ID 需要统一以 `proj`、`task` 开头,同时保留旧 ID 兼容读取和路由。 -- 决策:新建 editor project ID 前缀改为 `proj-`,新建 AI task / 生成任务 / 草稿任务 ID 前缀改为 `task-`。路由和读写仍按字符串处理,不新增拒绝 `editor-project-*`、`aitask_*` 或 `extgen-*` 的校验,历史数据继续兼容。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/module-ai/src/domain/ids.rs`、`server-rs/crates/api-server/src/editor_generation_queue.rs`、玩法外部生成入队路径、外部编辑器 API 新建项目返回值、AI 任务创建链路。 -- 验证方式:运行 `cargo test -p module-ai --manifest-path server-rs/Cargo.toml`、定向 api-server editor project 测试、编码检查和 `git diff --check`。 -- 关联文档:`docs/openapi/genarrative-external-v1.openapi.json`。 - -## 2026-07-03 画布Agent会话元数据入 SpacetimeDB、消息正文存 OSS - -- 背景:图片画布工程需要对话式编辑历史,但消息正文随对话和工具结果增长,不适合放入表行或画布布局快照;同时画布 Agent 只属于编辑器画布域,不能复用拼图 `creative-agent` 内存会话。 -- 决策:`module-editor-agent` 只承载可供 SpacetimeDB WASM 使用的纯领域规则;Agent runner、工具实现和资产 DTO 迁入原生 `platform-editor-agent`,仅由 `api-server` 依赖。`editor_agent_conversation` 只保存会话元数据,完整消息以 `editor-agent/{conversationId}.json` 会话粒度存 OSS;`api-server` 负责编排 LLM、普通 JSON 消息、OSS 读写和既有生成工具调用。用户消息以独立 `clientMessageId` 在会话锁内幂等,数字 `message.id` 只作后端定位;旧 OSS 消息允许缺失幂等键,早期用户消息字符串 `id` 在读取时迁入 `clientMessageId`。画布 Agent 只与任务侧栏互斥,不与左侧素材 / 图层栏互斥。 -- 影响范围:图片画布右侧 Agent 面板、`shared-contracts` / `packages/shared` 的 `editorAgent` 契约、`spacetime-module` / `spacetime-client`、`platform-oss` 内部读签名边界、画布生成落板规则。 -- 验证方式:`npm run spacetime:generate`、`npm run check:spacetime-schema`、`cargo test -p module-editor-agent --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server --manifest-path server-rs/Cargo.toml editor_agent`、前端 Agent 面板与 JSON client 定向测试、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【编辑器】画布Agent对话面板-2026-07-03.md`、`docs/adr/【ADR】画布Agent会话消息存OSS-2026-07-03.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-07-01 认证工作集只经 typed projection 同步正式表 - -- 背景:同手机号重复账号、兑换码白名单错配和微信资料不回写暴露出 `module-auth` 内存工作集、`auth_store_snapshot` 和正式认证表之间仍有历史互刷路径;旧 JSON 快照会把过期手机号索引或用户资料重新带回运行态。 -- 决策:删除 `auth_store_snapshot` 表和旧 `import_auth_store_snapshot_json` / `export_auth_store_snapshot_from_tables` procedure;`module-auth` 只保留内存工作集和 typed `AuthStoreProjectionView` 导入 / 导出。运行中认证写操作通过 `sync_auth_store_projection` 同步 `user_account` / `auth_identity` / `refresh_session`,启动恢复通过 `export_auth_store_projection_from_tables` 从正式表恢复内存。账号资料真相只在 `user_account`,`auth_identity` 只保存登录入口身份键。 -- 影响范围:`module-auth` projection API、`spacetime-module` auth schema/procedure、`spacetime-client` bindings/facade、`api-server` 启动恢复和认证同步、后端架构文档与认证排障记忆。 -- 验证方式:`npm run spacetime:generate`、`SPACETIME_SCHEMA_GUARD_ALLOW_BREAKING=1 npm run check:spacetime-schema`、`cargo test -p module-auth --manifest-path server-rs/Cargo.toml -- --nocapture`、`cargo check -p spacetime-client --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-06-29 图片画布手动抠图走远端 BiRefNet BFF - -> 后续更正:本条独立 BiRefNet 服务、专用 base URL 以及 api-server 下载并解析原图的实现,已由 2026-07-14「手动去背景迁移到 BgFilter complex 模式」、2026-07-15 OSS 签名 URL 决策和 2026-07-17 内存生命周期决策取代。下文保留作历史记录。 - -- 背景:用户手动“去除背景”面对任意图片,前端 `chromaKey` 和标准绿幕后处理不适合复杂人物、自然背景或非纯色背景;远端 image host 已部署 BiRefNet 服务,需要让手动抠图走高质量模型,同时避免把服务令牌暴露到浏览器。 -- 决策:画布手动“去除背景”默认调用登录态同源 BFF `POST /api/editor/images/background-removals`。api-server 解析当前图片后代理到 `GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_BASE_URL/remove-background`,默认指向 `http://58.87.105.82/remove-background`,可选 `GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_TOKEN` 只在服务端注入。api-server 对上游结果做字节和尺寸上限保护,并先落 OSS / asset object 再返回给前端。编辑器自己生成的标准绿幕资产不属于该决策,见 2026-06-30 绿幕契约收口。 -- 影响范围:api-server 编辑器图片接口、图片画布手动去背景、画布右上角任务侧栏、图片画布 MVP 技术文档。 -- 验证方式:运行 `cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server config::tests::from_env_reads_editor_background_removal_settings --manifest-path server-rs/Cargo.toml`、`npm run typecheck`、定向画布 workflow 测试、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-06-26 React 组件测试按用户行为与稳定契约收敛 - -- 背景:部分 React 测试把组件内部状态、测试专用 DOM 探针、图标 class、完整按钮顺序或精确长文案当成契约,正常 UI 重构时容易误报,增加维护成本。 -- 决策:新增和重写 React 测试时,默认分成用户流程测试、稳定契约测试、hook / model 逻辑测试三层。用户流程测试优先断言 role / label / URL / 弹窗 / callback 等可感知结果;演化中的 DTO 和 callback payload 使用关键字段或 `expect.objectContaining(...)`;hook 测试使用 `renderHook` 验证公开返回契约,不再为读取内部状态制造 `data-testid` 仪表盘。 -- 影响范围:前端 React 组件测试、图片画布测试、平台入口测试、后续共享组件和 hook 测试新增 / 重写方式。 -- 验证方式:运行定向 React 测试、`npm run typecheck`、`npm run check:encoding` 和 `git diff --check`;出现正常重构引发测试破碎时,优先把测试改到用户行为或稳定契约层。 -- 关联文档:`docs/technical/【前端测试】React组件测试准则-2026-06-26.md`、`src/components/image-editor/useCanvasGenerationDialogs.test.tsx`、`src/components/image-editor/ImageCanvasBottomToolbarView.test.tsx`。 - -## 2026-06-26 AI 游戏创作 App 生成过程必须在聊天可见 - -- 背景:普通用户窗口只保留聊天入口,但如果生成确认后只显示“已生成草案”和本地产物路径,真实 LLM / Agent loop 会被误解成固定模板落盘。 -- 决策:`game.generate_draft` 保持正式用户窗口不展示开发面板,但必须通过聊天实时显示 Planner LLM、Orchestrator、6 组角色 brief、Generator LLM、Evaluator、ArtifactWriter 和自检进度;生成完成后普通聊天消息直接展示 `.agent/run.latest.json` 的 Run、LLM 对话、loop 轮次、active / carry-over 任务、编排轮次、最近步骤、建议命令和本地产物快照;没有同步建议命令时,首个安全产物只提供 `/read` 草稿,`/trace` 继续读取同一份完整证据。 -- 影响范围:`apps/ai-game-creator-shell/src/App.tsx`、`apps/ai-game-creator-shell/src-tauri/src/main.rs`、AI 游戏创作 App 聊天体验和实施计划文档。 -- 验证方式:运行 `npm run ai-game-creator-shell:check`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-06-26 AI 游戏创作 App 增加显式质量评审 Gate - -- 背景:AI 游戏创作 App 已有 Evaluator loop 和静态 smoke,但任务图、能力清单和 trace 中没有单独的质检 / 评审任务,用户无法从 `/tasks`、`/trace` 或 `/audit` 看出质量评审是明确环节。 -- 决策:保持策划、美术、程序、数值、音乐、运营 6 个专业组不变,在程序组内新增 `quality-review` / `Review` 角色任务;Evaluator 的评审 step 绑定到该任务,依赖顺序为 `code-prototype -> quality-review -> preview-readiness -> preview-playtest -> publish-strategy -> publish-package`。`game.static_smoke` 只完成 `preview-readiness`,不代替质量评审。 -- 影响范围:AI 游戏创作 App 任务图、共享契约、Tauri trace / manifest 状态推导、聊天 `/capabilities` `/tasks` `/trace` `/audit` 摘要和实施计划文档。 -- 验证方式:运行 `npm run ai-game-creator-shell:check`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-06-25 AI 游戏创作 App 真实 LLM 联调用流式请求 - -- 背景:AI 游戏创作 App 的真实 OpenAI-compatible provider 验收中,小请求可返回,但 Planner 等稍长非流式请求会在上游响应前被网关空闲连接切断,表现为 TLS record 解密失败;本地无密钥 provider smoke 不能覆盖该真实网关行为。 -- 决策:`platform-llm` 文本 client 使用系统 TLS backend,并保留底层错误链用于排障;AI 游戏创作 App 通过客户端配置项 `llm.stream=true` 开关打开流式请求,打开后 Planner、组内角色和 Generator 走流式请求。 -- 影响范围:`server-rs/crates/platform-llm`、`apps/ai-game-creator-shell/src-tauri/src/main.rs` 和 AI 游戏创作智能体 App 实施计划。 -- 验证方式:运行 `cargo test -p platform-llm --manifest-path server-rs/Cargo.toml request_text_parses_non_stream_response`,并用真实 OpenAI-compatible 本机配置执行 `npm run ai-game-creator-shell:agent-run -- --no-wait /tmp/genarrative-ai-game-real-loop-test-6 "做一个像素风反弹弹幕厨房小游戏..."`,确认 36 个 trace step、36 次 tool call、`game.static_smoke`、`preview.start` 和 `preview.stop` 完成。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -2026-06-27 追加,2026-06-30 更新:`platform-llm` 旧 `LlmTextRequest` / `LlmTextResponse` 已直接替换为 provider-neutral 的 `LlmRunRequest` / `LlmRunResponse`,API kind 先固定为 `openai_chat`、`openai_responses`、`anthropic` 三类。AI 游戏创作 App 改用客户端运行时配置(Tauri 应用配置目录的 `game-creator.config.json`),LLM 维度由 `llm.apiKind` 控制,默认 `openai_responses`,可设为 `openai_chat` 接旧 Chat Completions 兼容网关,或 `anthropic` 接 Anthropic Messages。当前 run 响应只保留通用文本、finish reason、response id 和 usage,高级能力后续按 capability 扩展,不把业务层绑死到 Responses 字段。 - -## 2026-06-24 AI 游戏创作 App 生成编排使用文件驱动 loop - -- 背景:AI 游戏创作 App 的 `game.generate_draft` 已接入 LLM,但单次请求仍不能体现 Planner / Generator / Evaluator 的协作闭环,也无法把评估反馈作为下一轮生成输入。 -- 决策:v1 使用最小文件驱动 loop,不引入 LangChain、AutoGen、Microsoft Agent Framework 或 OpenAI Agents SDK sidecar。Planner 写 `.agent/spec.md`;每轮先调用策划、数值、美术、音乐、程序、运营 6 组下的 15 个角色 agent,角色 brief 写到 `.agent/passes/pass-N/groups//*.md`,再由 `GroupCoordinator` 汇总到 `.agent/passes/pass-N/groups/*.md`;Generator 读取 spec、`.agent/findings.md` 和 6 组汇总 brief 生成结构化游戏草案。LLM JSON 必须带 `handoffs` 数组并覆盖 `design`、`balance`、`art`、`audio`、`code`、`publishing` 6 个专业组;每轮再把这些结构化交接快照写到 `.agent/passes/pass-N/`。Evaluator 做本地静态验收并写 `.agent/findings.md`,最多 3 轮;返工轮必须把 findings 转成结构化 `repairRoutes`,记录每条问题命中的 taskIds 和 reason,再据此选择 activeTaskIds。每次运行另写 `.agent/run.latest.json` 和 `.agent/runs/.json`,记录 step、角色级 `toolCalls`、组汇总、专业组交接、输入输出路径、artifact 字节数与 `fnv1a64:` checksum;每个 step 带 phase、taskId、group 和 role,trace 顶层 `taskGraph` 记录 goal、readyTaskIds、activeTaskIds、carriedTaskIds、repairFocus、repairRoutes 和当前任务状态,`passPlans` 逐轮记录 mode、summary、activeTaskIds、carriedTaskIds、dependencyWaves、repairFocus 和 repairRoutes;latest 是当前指针,runs 目录保留历史 trace,作为开发窗口和后续工具调用 trace 的事实源,schema 由共享 TS/Rust 契约 `game-creator-agent-run.v1` 固定。最终产物写盘时追加 `ArtifactWriter / file.write.local_artifacts` step,随后自动跑白名单 `game.static_smoke`,检查 `game/index.html` 具备 canvas、canvas 渲染上下文、绘制调用、主循环、输入监听、明确目标、失败或胜利状态和重开路径,且不使用远程资源、`eval`、`new Function`、`localStorage`、`fetch`、`WebSocket` 或 `ServiceWorker`,再把 Playtest 工具调用写回 trace;通过后把 runId、状态、轮次、下一步、active / carry-over 任务和最终本地产物摘要追加到 `memory/session.md` 与 `memory/project.md`,让下一次 Planner / 角色 agent / Generator 从记忆输入直接看到上一轮稳定原型;后续 `preview.start` 会在已有 trace 上追加 Preview 工具调用和本地预览 URL。 -- 决策补充:普通用户聊天 `/trace` 读取同一份 `.agent/run.latest.json`,但摘要必须把 activeTaskIds、carriedTaskIds、repairRoutes 和 dependencyWaves 从内部 taskId 映射成专业组 / 角色 / 任务名,确保不打开开发窗口也能看出 6 组 agent、组内角色、返工路线和 carry-over 真实发生。 -- 影响范围:`apps/ai-game-creator-shell/src-tauri/src/main.rs`、`packages/shared/src/contracts/gameCreationApp.ts`、`server-rs/crates/shared-contracts/src/game_creation_app.rs` 和 AI 游戏创作智能体 App 实施计划。 -- 验证方式:运行 AI 游戏创作壳 Rust 测试、共享契约 TS/Rust 测试、壳 typecheck、编码检查和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-06-24 AI 游戏创作 App 编排 v1 使用 ready-task 选择器 - -- 背景:AI 游戏创作 App 已有专业组任务拆分和依赖字段,但如果没有当前可执行任务选择器,“任务编排”只停留在静态清单,普通用户在聊天里也看不到下一步由哪组 agent 接手。 -- 决策:v1 编排先使用最小 ready-task 规则:只选择 `pending` 且所有依赖任务均为 `completed` 的任务;共享 TS/Rust 契约和 `platform-agent` 都提供同一语义的选择器,聊天 `/tasks` 只展示下一步可执行专业组,不新增独立编排面板或外部 agent 框架。 -- 影响范围:`packages/shared/src/contracts/gameCreationApp.ts`、`server-rs/crates/shared-contracts/src/game_creation_app.rs`、`server-rs/crates/platform-agent/src/game_creation.rs`、`apps/ai-game-creator-shell/src/App.tsx` 和 AI 游戏创作智能体 App 实施计划。 -- 验证方式:运行共享契约测试、`platform-agent` 与 `shared-contracts` 的 Rust 测试、AI 游戏创作壳 typecheck、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`。 - -## 2026-06-24 外部生成队列升级为正式生成任务列表 - -- 背景:外部生成队列已经承载画板和玩法的付费生成,但前端只展示排队概览,缺少可追溯任务列表、后端确认状态、完成提示补弹和退款记录到任务的追踪关系。 -- 决策:`external_generation_job` 同时作为正式生成任务列表事实源,保存 `price_mud_points`、`refund_ledger_id` 和 `notification_acknowledged_at`;新增 `external_generation_job_event` 追加状态转换审计。BFF 新增当前账号任务列表和 acknowledge 接口;前端只展示后端任务状态,完成 / 失败提示关闭时由后端写确认时间,未确认终态任务在下次登录后按列表集中弹出。任务触发的钱包扣费 / 退款流水 metadata 必须写 `externalGenerationJobId`,本机退款 outbox 重放也保留该任务 ID。 -- 2026-06-25 追加:平台壳的当前账号任务列表只在登录、网络恢复、页面回到前台或已有 queued/running/未确认终态任务时刷新;空队列刷新一次后不保持 4 秒轮询,避免 `/api/runtime/external-generation/jobs` 在无任务时持续请求。 -- 影响范围:`spacetime-module` 外部生成 schema / procedure、`spacetime-client` bindings/facade、`api-server` 外部生成 BFF、worker 失败回写和资产计费退款链路、平台入口“我的”页任务卡和完成提示弹窗。 -- 验证方式:运行 `npm run spacetime:generate`、`npm run check:spacetime-schema`、`cargo test -p spacetime-module external_generation --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server wallet_refund_outbox --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/technical/【后端架构】外部生成Worker化方案-2026-06-03.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-06-23 编辑器宣发素材固定 gpt-image-2 - -- 背景:画板宣发素材的游戏首图、详情五图和运营海报只应使用稳定的宣发图生成链路,不能被图片模型上次选择或旧请求切到 `nanobanana2`。 -- 决策:三个宣发素材工作流前端面板只显示禁用态 `gpt-image-2` 模型胶囊,生成提交固定携带 `gpt-image-2` 且不写入图片模型记忆;后端 `/api/editor/images/generations` 对 `kind = "publication-material"` 强制归一为 `gpt-image-2` 后再生成和按运行时模型定价扣费。`生成角色形象` 的默认图片模型继续使用 `nanobanana2`。 -- 影响范围:图片画布宣发素材面板、图片生成提交模型、编辑器图片 BFF、宣发素材设计文档和 Lovart 生成面板方案。 -- 验证方式:运行宣发素材提交模型 / 面板测试、`api-server` 宣发素材模型锁定测试、前端类型检查、编码检查和 `git diff --check`。 -- 关联文档:`docs/【编辑器】宣发素材工具演示入口设计-2026-06-17.md`、`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-06-23 陶泥儿产品 IP 形象统一为陶罐探出橙色耳朵形象 - -- 背景:平台左上角“陶泥儿”品牌旁产品形象曾分散使用创作主页旧小陶偶、运行态 logo 或局部欢迎图,后续提到产品 IP / 产品形象容易产生歧义。 -- 决策:产品 IP / 产品形象统一定义为 `public/branding/taonier-product-ip.png`,即陶罐中探出的橙色耳朵形象。公共品牌组件 `RpgEntryBrandLogo` 默认展示该图;后续左上角品牌区和产品形象说明默认引用该资产,专题玩法若有独立运行态素材需在对应文档单独说明。 -- 影响范围:平台左上角品牌区、绑定手机号页品牌块、创作主页工作台 chrome、公共品牌资产常量和产品基线文档。 -- 验证方式:运行品牌标识、绑定手机号页和平台首页相关前端测试,确认品牌图 `src` 为 `/branding/taonier-product-ip.png`;执行 `npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【项目基线】当前产品与工程约束-2026-05-15.md`、`docs/【玩法创作】创作主页与项目入口改版计划-2026-06-18.md`。 - -## 2026-06-22 创作主页精选展示全站公开画布生成资源 - -- 背景:`/creation` 的 `陶泥儿精选` 曾从账号级素材库读取,并在素材为空时用公开作品图片补充,导致新创作页出现不属于任何当前图片画布项目的素材。 -- 决策:该历史决策已被 2026-07-04 的“素材提交审核后公开”取代。历史背景仍有效:公开作品图片和假数据不应回填精选;但精选事实源不再是 `editor_project_resource.public_showcase_enabled`,而是 `editor_showcase_asset` 审核快照。 -- 影响范围:`/creation` 创作主页、`creationShowcaseModel`、公开精选 BFF、图片画布素材列表右键菜单、账号素材库快照、创作主页改版计划和精选素材相关测试。 -- 验证方式:运行 `src/components/creation-home/creationShowcaseModel.test.ts`、`CreationLandingView.test.tsx`、`ImageCanvasAssetRowView.test.tsx`、`useImageCanvasAssetLibrary.test.tsx` 与 `src/services/image-editor/editorProjectClient.test.ts`,确认公开生成资源展示、上传素材过滤、公开开关隐藏资源、删除入口在右键菜单中、公开作品不再 fallback。 -- 关联文档:`docs/【玩法创作】创作主页与项目入口改版计划-2026-06-18.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-06-22 编辑器生成模型默认定价调整 - -- 背景:图片画布生成按钮、后端模型定价扣费和后台定价页需要统一使用新的模型默认泥点。 -- 决策:`audio1.0` 默认按次 `5` 泥点,`chirp-v5` 默认按次 `12` 泥点,`gpt-image-2` 默认 `1K=3`、`2K=5` 泥点;运行态仍允许后台 override 覆盖,前端兜底必须与后端默认 JSON 保持一致。 -- 影响范围:`editor-generation-pricing.default.json`、`ImageCanvasGenerationModel.ts`、后台定价页 fixture、后端价格计算和编辑器定价文档。 -- 验证方式:运行 `editor_generation_config`、公开定价路由、图标素材价格校验、图片画布定价模型和后台定价页相关测试。 -- 关联文档:`docs/【编辑器】模型定价配置管理方案-2026-06-22.md`、`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`。 - -## 2026-06-22 编辑器生成扣费与新用户赠送收口 - -- 背景:画板多个生成按钮已经展示泥点消耗,但部分图片、图标、UI 提取、视频、角色动作或音频链路只校验 / 展示价格,没有统一进入钱包预扣;新用户注册送泥点也需要与当前生成价格匹配。 -- 决策:编辑器所有外部生成入口不再从前端请求接收 `priceMudPoints`,后端按运行时模型定价配置计算价格后统一进入 `execute_billable_asset_operation_with_cost` 或等价音频发布扣费链路;角色动作和视频使用真实登录用户作为扣费 owner。新用户注册赠送固定为 `100` 泥点。 -- 影响范围:编辑器图片 / 图片修改 / 图标 spritesheet / UI 提取 / 视频 / 角色动作 / 音频生成 BFF,前端画板生成提交模型,外部 OpenAPI,`module-runtime` 钱包注册奖励。 -- 验证方式:运行编辑器图片、图标、UI 提取、视频、角色动作、音频扣费结构性测试,前端生成提交和 API client 测试,`module-runtime` 注册奖励测试。 -- 关联文档:`docs/【编辑器】模型定价配置管理方案-2026-06-22.md`、`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-06-22 AGENTS.md 收敛为入口导航 - -- 背景:`AGENTS.md` 同时承载项目记忆、RAG、Issue、UI、Git、后端、SpacetimeDB 和文档图谱等细则,入口过重,复杂任务启动成本高。 -- 决策:`AGENTS.md` 只保留最高优先级规则、任务路由、后端红线、验证提交要求和文档图谱;新增 `docs/【协作规范】Agent工作入口与执行准则-2026-06-22.md` 承接完整执行细则。复杂任务阅读顺序固定为 `AGENTS.md` -> Agent 执行准则 -> `docs/project-memory/` -> `docs/README.md` 和专题文档。 -- 影响范围:`AGENTS.md`、`docs/【协作规范】Agent工作入口与执行准则-2026-06-22.md`、`docs/README.md`、`docs/project-memory/README.md` 和共享记忆索引。 -- 验证方式:执行 `npm run check:encoding`、`git diff --check`,并检查入口文档不再重复承载专题细则。 -- 关联文档:`AGENTS.md`、`docs/【协作规范】Agent工作入口与执行准则-2026-06-22.md`。 - -## 2026-06-22 图片画布角色动作主媒体改为透明序列帧 - -- 背景:角色动作生成后端已经在视频生成后抽取透明 PNG 帧并完成绿幕去背;画板继续把 `previewVideoPath` 当主媒体会让用户看到未扣绿幕视频,下载也拿不到可直接用于游戏素材的帧序列。 -- 决策:`/api/editor/character-animations/generations` 的上游预览视频继续保留为来源信息,但画板落层主类型固定为 `mediaType="image-sequence"`、`assetKind="character-animation"`;图层 `src` / `thumbnailSrc` 使用首帧,完整 `frames` 保存到 `imageSequenceFrames`,画布展示使用序列帧播放器循环播放。单图层下载生成序列帧 ZIP,画布素材 ZIP 中角色动作写入 `sequences/<编号-标题>/frames/`,不再把预览视频作为角色动作下载产物。 -- 影响范围:图片画布角色动作生成、画布图层快照、序列帧播放器、素材导出、角色动作设计文档和排障记忆。 -- 验证方式:运行角色动作图层工厂、画布展示、画布持久化、生成提交和素材导出相关前端测试,执行 `npm run typecheck`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`。 - -## 2026-06-24 图片画布项目封面使用静态快照资源 - -- 背景:项目页和创作主页最近项目曾在卡片中根据项目 `layers + viewport + resources` 临时重建一份迷你画布,视觉上像封面,但它不是持久快照,也会把列表页变成画布布局解释器。 -- 决策:项目封面图改为画布当前视口栅格化后的静态资源。前端在项目加载后和防抖保存 layout 时生成 320x240 WebP,走私有 OSS / asset object 上传,再创建 `editor_project_resource`,其中 `assetKind="project-cover-snapshot"`、`sourceType="uploaded"`;项目列表和创作主页最近项目只读取最新封面快照资源渲染,没有快照时显示项目占位,不再回退为实时画布组合。 -- 2026-07-24 补充:封面取景以当前画布工作区的实际尺寸和渲染态 viewport 为准,先绘制工作区背景色,再从视口中心等比放大并裁成 4:3;持久化显示倍率不得直接用于封面渲染。 -- 2026-07-29 补充:常规编辑仍沿用防抖保存;用户从画布返回项目页时必须取消待执行 timer,以最新权威 revision 立即保存 layout,并等待同一视口封面写入本地缓存和正式项目资源后再导航。当前视口存在图层但全部位于取景外时仍生成纯背景封面,不沿用旧缩略图。 -- 影响范围:`src/components/image-editor/useImageCanvasProjectPersistence.ts`、`src/components/image-editor/ImageCanvasProjectCoverSnapshotModel.ts`、`src/components/project/ProjectCanvasCover.tsx`、`src/components/project/ProjectGalleryView.tsx`、`src/components/creation-home/CreationLandingView.tsx` 和图片画布数据契约文档。 -- 验证方式:运行项目页、封面快照模型、图片画布项目持久化和媒体上传相关前端测试,执行 `npm run typecheck`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-06-21 图片画布生成完成态由后端写入画布布局 - -- 背景:图片画布角色形象等长耗时生成在服务端完成后,如果浏览器已刷新或原 HTTP 回调丢失,前端无法再把生成结果图层和 `generation-dialog` 完成态写回 `editor_canvas.layers_json`,用户会继续看到“生成中”卡片。 -- 决策:图片生成请求在有项目上下文时携带 `canvasCompletion`(生成器 `dialogId`、结果标题和占位框);`api-server` 在生成成功并创建 `editor_project_resource` / `editor_asset` 后,直接读取当前项目布局,只有当前布局仍存在对应生成器时才插入轻量结果图层,把生成器标记为 `idle` 并写入 `generatedLayerId`,沿用后端当前 viewport 保存 layout 后返回最新项目快照。前端只应用后端快照刷新显示,不再把生成完成态作为正式业务真相,也不在项目加载时根据资源行推断完成态。 -- 影响范围:`server-rs/crates/api-server/src/editor_project.rs`、图片画布生成提交工作流、项目快照 hydrate / persistence、图片画布技术方案和排障记录。 -- 验证方式:`cargo test -p api-server editor_canvas_generation_completion --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run test -- src/components/image-editor/ImageCanvasEditorModel.test.ts src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/services/image-editor/editorProjectClient.test.ts src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx -- --runInBand`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-06-21 图片画布参考图元数据只保存项目内行引用 - -- 背景:参考图如果把 Data URL、signed URL 或 `objectKey` 写入 `generationInputs` 或生成器布局快照,会撑大资源 / 素材 / 画布 JSON,也无法稳定索引到项目内用户可见行数据。 -- 决策:`generationInputs.references` 只保存稳定行指针,不保存媒体本身。2026-08-03 起 V2 新写入结构为 `{ id, title, label?, refType, refId }`;`refType="project-resource"` 和 `refType="asset"` 只用于匹配当前画布中已 hydrate 图层的 `resourceId/sourceAssetId`,媒体类型取匹配图层的运行时数据,不新增 owner-only 工程资源 / 素材库 resolver。生成器 `itemType="generation-dialog"` 布局快照中的参考图也只保存 `resourceId/sourceAssetId` 和展示 label,不保存图片 Data URL、signed URL 或 `objectKey`;提交生成请求前的内存态可以临时持有 `src/objectKey`。面板直接上传引用不是画布图层,不承诺刷新或复用恢复;已移出画布的引用同样不恢复。不兼容旧 `src` 型参考图元数据。 -- 影响范围:图片画布生成输入快照、生成器布局保存 / 恢复、参考图上传工作流、元数据弹窗和图片画布技术文档。 -- 验证方式:运行图片画布生成模型、生成提交、上传工作流、项目持久化、元数据弹窗相关前端测试,执行 `npm run typecheck`、`npm run check:encoding` 和 `git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。 - -## 2026-06-19 外部 OpenAPI 与 API Key 管理走 server-rs 正式链路 - -- 背景:外部调用方需要稳定调用图片画布项目创建、画布布局保存和编辑器美术生图能力,同时需要可撤销的开发者凭据,不能依赖前端临时状态或人工分发密钥。 -- 决策:外部 API 固定放在 `/api/external/v1` 命名空间,v1 暴露素材直传凭证 / asset object 确认 / 签名读取、项目列表 / 最近 / 创建 / 读取 / 重命名 / 删除、默认画布保存、账号级素材库、项目资源记录、编辑器图片 / 视频 / 音频生成和 `/api/external/v1/openapi.json`。API Key 管理走登录态 `/api/profile/api-keys`,外部调用使用 `Authorization: Bearer tnr_sk_xxx`;后端只保存 `key_hash` 和 `key_prefix`,明文只在创建响应返回一次。外部 API 鉴权、项目 / 画布 / 素材写回全部经 `api-server -> spacetime-client -> spacetime-module`,生成素材成功后按请求写入账号级 `editor_asset`,带 `projectId` 时写入 `editor_project_resource`;外部确认 asset object 时 owner 固定为 API Key 所属账号。API Key 管理接口不进入外部 OpenAPI JSON。 -- 影响范围:`server-rs/crates/api-server/src/external_*`、`server-rs/crates/api-server/src/modules/external_api.rs`、`server-rs/crates/spacetime-module/src/external_api_key_storage.rs`、`server-rs/crates/spacetime-client/src/external_api_key.rs`、`docs/openapi/genarrative-external-v1.openapi.json` 和后端数据契约文档。 -- 验证方式:`cargo test -p api-server external_api --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server external_editor_api --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:spacetime-schema`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【后端架构】外部OpenAPI与APIKey接入方案-2026-06-19.md`。 - -## 2026-06-19 图片画布素材生成元数据上移到资源和素材 - -- 背景:角色、图标、UI 设计图、视频和音频等生成结果会在图片信息页展示用户可见输入快照;此前这些 `assetKind/generationInputs` 主要保存在画布 layer JSON 中,素材进入账号级素材库后跨项目复用和刷新恢复都依赖画布布局,不符合素材库作为账号级事实源的边界。 -- 决策:普通图层的新保存不再把 `assetKind/generationInputs` 写入 `editor_canvas.layers_json`。`editor_project_resource` 保存项目画布资源快照的 `asset_kind/generation_inputs_json`,`editor_asset` 保存账号级素材的同名元数据和可选封面 `thumbnail_src`;图片 / 图标 / UI 提取等生成 BFF 在请求携带 `projectId` / `assetFolderId` 时由后端创建新 resource / asset 并把快照回传前端,前端只用回包更新画布图层和素材栏,不再把同一生成结果二次调用保存接口。生成视频由后端单独抽取首帧封面写入 `editor_asset.thumbnail_src` 和画布图层 `thumbnailSrc`,刷新素材库或从素材库拖回画布时继续作为视频 poster 使用。前端加载时优先从 resource / asset 恢复素材类别和生成输入快照,旧 layout 中的同名字段只作为历史兼容兜底。生成器对象本身仍作为 `itemType="generation-dialog"` 保存在画布布局中。 -- 影响范围:`server-rs/crates/spacetime-module/src/editor_project_storage.rs`、`server-rs/crates/spacetime-client/src/mapper/editor_project.rs`、`server-rs/crates/api-server/src/editor_project.rs`、`src/services/image-editor/editorProjectClient.ts`、图片画布 hydrate / serialize / project persistence / asset library 代码和后端数据契约文档。 -- 验证方式:运行 `npm run spacetime:generate`、`npm run check:spacetime-schema`、`npm run test -- src/components/image-editor/ImageCanvasEditorModel.test.ts src/components/image-editor/useImageCanvasProjectPersistence.test.tsx src/services/image-editor/editorProjectClient.test.ts`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`,并按需补充 `cargo check -p spacetime-client -p api-server --manifest-path server-rs/Cargo.toml`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。 - -## 2026-06-19 图片画布生成按钮价格统一绑定模型定价配置 - -- 背景:图片画布的生成图片、生成视频、生成规范、生成角色、生成素材、生成 UI、宣发素材、快速编辑、重绘和音频生成入口都在按钮内显示泥点;如果按钮文案、前端请求和后端扣费各自写固定数值,后续调整模型价格会出现展示价和扣费价不一致。 -- 决策:所有画板生成按钮展示价格必须从 `src/components/image-editor/ImageCanvasGenerationModel.ts` 的模型定价配置函数计算,但生成请求不提交 `priceMudPoints`;后端默认配置独立放在 `server-rs/crates/api-server/config/editor-generation-pricing.default.json`,运行时事实源为 SpacetimeDB `editor_generation_pricing_config` 全局表;后台“模型定价”通过 `/admin/api/editor-generation-pricing` 读取和保存完整 `models` 配置,主站通过 `/api/editor/generation-pricing` 动态下发。后端扣费以 `AppState` 当前运行时配置为准,前端内置定价只作为接口失败兜底展示。模型定价不再按图片 / 规范、视频 / 动作用途拆分,只按模型区分:图片模型按尺寸单次计价,`gemini-3.1-flash-image-preview` 必须配置 `0.5K / 1K / 2K`,`gpt-image-2` 必须配置 `1K / 2K`,规范固定读取 `gpt-image-2` 的 `2K`;视频和角色动作共用视频模型分辨率每秒价格,角色动作仍固定 `seedance2.0-fast`。后台管理页必须显示定价单位“按次 / 按秒”。画板 UI 统一显示 `nanobanana2`,历史输入或旧布局中的 `nano-banana` 必须归一到真实模型 ID 后再提交和计费。 -- 影响范围:图片画布生成类面板、生成提交模型、编辑器图片 / 视频 / 音频 BFF、`editor_generation_config`、后台管理端和 Lovart 生成类面板文档。 -- 验证方式:运行 `cargo test -p api-server --manifest-path server-rs/Cargo.toml editor_generation_config::tests editor_generation_pricing_route -- --nocapture`、`npx vitest run src/components/image-editor/ImageCanvasGenerationModel.test.ts src/services/image-editor/editorProjectClient.test.ts apps/admin-web/src/pages/AdminEditorGenerationPricingPage.test.tsx apps/admin-web/src/app/adminRoutes.test.ts --reporter verbose`、`npm run admin-web:typecheck`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`、`docs/【编辑器】模型定价配置管理方案-2026-06-22.md`。 - -## 2026-06-18 图片画布 UI 设计图提取素材保留图集 - -- 背景:UI 设计图需要从成图中继续抽取可复用独立素材;原图标素材生成只把拆分后的图标放入画布,spritesheet 原图没有保留,后续追溯和二次切图不方便。 -- 决策:`assetKind="ui-design"` 图层浮动工具栏新增 `提取素材`,点击后先进入红框素材框选编辑态,默认矩形框选,并支持椭圆框选和画笔自由框选。至少存在一个框选区域后才能提交;前端把红色轮廓绘入原 UI 设计图并将合成图作为 `/api/editor/ui-designs/assets/extractions` 的参考图。后端固定 `gpt-image-2` 和纯色背景素材提取提示词,返回结构复用图标 spritesheet 响应。透明背景处理正常成功时,UI 提取把透明 spritesheet 图集作为 `assetKind="icon-spritesheet"` 图层放到画布,再放 provider 原图和拆分成功的 `assetKind="icon"` 素材。2026-07-03 起,UI 提取的纯色背景由 `screenColor` 选择并经 BgFilter 透明化。2026-07-13 起,图标素材生成在透明背景处理正常成功时把带背景原图和透明 spritesheet 同时写入项目资源、账号素材库和画布,未指定文件夹时落默认“项目”文件夹,再 best-effort 按 alpha 连通域拆分独立图标;拆分素材从 provider 原图右侧继续排列。拆分失败不改变生成成功状态,响应以空 `iconImageSrcs` 和结构化 `sliceWarning` 返回原因,用户可从图集工具栏手动重试。2026-07-16 起,透明背景处理最终失败时只把已经持久化的 provider 原图作为唯一主图放入画布,以 `completed + warning` 收口,不创建透明图集,也不继续拆分。2026-07-29 起,图标生成的自动拆分与手动拆分共同识别全图集有效连通域,限制单边 `4096`、总像素 `2048×2048`、最多 `64` 个切片,不再以提示词条目数决定切片数量;手动拆分仍保留且不计费。所有切片用 `sourceResourceId` 指向透明图集。`icon-spritesheet` 图集继续显示并允许快速编辑,只有拆分后的 `assetKind="icon"` 单图标隐藏并拒绝快速编辑;工具栏、右键菜单、打开流程和提交兜底必须共用同一判定。本条新决策取代“图标素材生成只保留图集”的旧口径。 -- 影响范围:图片画布浮动工具栏、编辑器图片生成 BFF、`platform-image` 图集连通域拆分、画布图层类型和编辑器文档。 -- 验证方式:运行图片画布工具栏 / 图集落层 / 生成提交相关前端测试,`cargo test -p platform-image generated_asset_sheets --manifest-path server-rs/Cargo.toml`,以及 `cargo test -p api-server editor_ui_design_asset_extraction_prompt_is_fixed --manifest-path server-rs/Cargo.toml`。 -- 关联文档:`docs/【编辑器】画板UI设计图生成入口设计-2026-06-17.md`、`docs/【编辑器】画板图标素材生成入口设计-2026-06-15.md`。 - -## 2026-06-30 图片画布标准绿幕契约收口 - -> 后续更正:本条关于生成资产只使用本地透明化、手动路径继续使用独立 BiRefNet 的描述,已由 2026-07-14、2026-07-15 OSS 签名 URL 决策和 2026-07-17 内存生命周期决策取代;当前 flat 链路为 `BgFilter → 阿里云 → 本地键色`。下文保留作历史记录。 - -- 背景:角色形象、图标 spritesheet、UI 提取 spritesheet 和角色动作帧都要求模型生成标准绿幕,但提示词片段和后处理入口分散在多个模块中,容易把标准绿幕资产误接到远端 BiRefNet。 -- 决策:编辑器标准绿幕提示词和本地确定性绿幕透明化统一收口到 `server-rs/crates/api-server/src/editor_green_screen.rs`。手动 `POST /api/editor/images/background-removals` 继续面向用户任意图片并走 BiRefNet;编辑器自己生成的标准绿幕资产统一复用 `platform-image::generated_asset_sheets` 的本地透明化能力,不再依赖 BiRefNet。角色图、图标 spritesheet、UI 提取 spritesheet 和角色动作抽帧源图必须在绿幕透明化前先保存一份带绿幕原图到 OSS,便于追溯和重处理。 -- 影响范围:`editor_project.rs` 的角色图 / 图标图集 / UI 提取图集、`character_animation_assets.rs` 的编辑器角色动作帧、编辑器绿幕相关文档。 -- 验证方式:运行 `cargo test -p api-server --manifest-path server-rs/Cargo.toml prompt`,并单独按需过滤 `editor_canvas_green_screen_generation_uses_local_postprocess`、`editor_character_animation_frames_use_local_green_screen_postprocess`;同时运行 `npm run check:encoding` 和 `git diff --check`。 - -## 2026-06-18 `/creation` 独立为陶泥儿创作工具主页 - -- 背景:图片画布项目已经成为独立项目资产,旧“创作”站内 Tab 和一级“草稿”入口不能清晰表达桌面端创作工具主页与项目管理入口。 -- 决策:桌面端新增独立 `/creation` 创作工具主页,桌面端直接打开站点首页 `/` 时也默认展示新版创作主页;顶级“创作”入口跳转 `/creation`,原“草稿”入口替换为“项目”并跳转 `/project`。移动端首页 `/` 继续保持原推荐首页,移动端隐藏“创作”和“项目”入口;移动端直达 `/creation` 时不加载创作主页,显示桌面端打开引导,`/creation/` 玩法工作台直达仍按原链路进入。页面文案统一使用“陶泥儿”,外部品牌只作为设计参考,不进入用户可见 UI、测试名、产品文案或验收口径。`陶泥儿精选` 是用户素材瀑布流,不展示玩法入口列表;创作入口事实源继续来自 `/api/creation-entry/config`,项目入口通过 `createEditorProject` 和 `/editor/canvas?projectid=xxx` 链路进入画布。 -- 影响范围:平台入口导航、`SelectionStage` 路由、`/creation` 首页、`/project` 项目入口、`/editor/canvas` 项目打开链路、“我的”页快捷入口和创作入口相关测试。 -- 验证方式:桌面 `/` 初始阶段和 `/creation` 解析为创作主页,移动端 `/` 仍是推荐首页,`/creation/` 仍进入对应玩法工作台;桌面导航显示“创作 / 项目”且不显示“草稿”;移动端底部不显示“创作 / 项目”;页面不出现外站品牌或 `Discord` 字样;新建项目进入 `/editor/canvas?projectid=xxx`。 -- 关联文档:`docs/【玩法创作】创作主页与项目入口改版计划-2026-06-18.md`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。 - -## 2026-06-18 图片画布 Seedance 2.0 参考媒体提交边界 - -- 背景:`/editor/canvas` 生成视频需要严格对齐火山 Seedance 2.0 多模态参考输入;参考视频若继续走 Base64 / `data:video` 会超过请求体并被上游拒绝,参考音频单独输入和非 Seedance 模型携带参考字段也会违反文档契约。 -- 决策:仅 `seedance2.0-fast` / `seedance2.0` 可提交参考图片、参考视频、参考音频;图片 `0~9`、视频 `0~3`、音频 `0~3`,音频必须搭配图片或视频。参考视频只能提交公网 URL、`asset://` 或画板资源 `objectKey`,禁止 `data:video/*`;视频 / 音频上传先走 OSS 直传和 asset*object confirm,前端保存 signed URL 预览但提交优先 `objectKey`,后端统一重新签名给 Ark。Ark body 按 `image_url` / `video_url` / `audio_url` + `reference*\*`role 构造,并显式发送`generate_audio:false`。 -- 影响范围:图片画布生成视频面板、参考媒体上传工作流、`editorReferenceUploadClient`、`ImageCanvasGenerationSubmissionModel`、`shared-contracts`、`api-server` 编辑器视频 BFF、Lovart 生成类面板文档。 -- 验证方式:运行 `npx vitest run src/components/image-editor/useImageCanvasUploadWorkflow.test.tsx src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/services/image-editor/editorReferenceUploadClient.test.ts --reporter verbose`、`cargo test -p api-server editor_video --manifest-path server-rs/Cargo.toml`、`cargo test -p shared-contracts editor_video_request_supports_seedance_multimodal_references --manifest-path server-rs/Cargo.toml`,并执行 `npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`、火山 Seedance 2.0 任务创建文档。 - -## 2026-06-21 图片画布生成视频参数扩展 - -- 背景:编辑器画布生成视频需要开放更多 Lovart 式参数,同时保留模型能力边界;`seedance2.0-fast` 不支持 `1080p`,联网搜索暂没有可确认的 Ark 视频生成 body 字段。 -- 决策:生成视频参数面板支持比例 `16:9 / 9:16 / 1:1 / 4:3 / 3:4 / 21:9`,时长为 4 到 15 秒整数 slider,清晰度支持 `480p / 720p / 1080p`;`seedance2.0-fast` 不展示可用 `1080p`,从其它模型的 `1080p` 切回 Fast 时自动降到 `720p`,后端也拒绝 `seedance2.0-fast + 1080p`。静音只作为一个 toggle 展示,默认有声并映射 `sound=on` / Ark `generate_audio=true`;关闭静音时传 `sound=off` / `generate_audio=false`。`webSearchEnabled` 默认随请求提交为 `true`,但前端不展示联网搜索开关,后端当前只接收契约字段,不向 Ark 透传未知参数。 -- 影响范围:图片画布生成视频面板、生成提交模型、画布项目快照恢复、`editorProjectClient`、`shared-contracts`、`api-server` 编辑器视频 BFF、编辑器技术文档。 -- 验证方式:运行 `npm run test -- src/components/image-editor/ImageCanvasGenerationModel.test.ts src/components/image-editor/ImageCanvasGenerationSubmissionModel.test.ts src/components/image-editor/ImageCanvasGenerationComposerView.test.tsx src/services/image-editor/editorProjectClient.test.ts src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts`、`cargo test -p shared-contracts editor_video --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server editor_video --manifest-path server-rs/Cargo.toml`,并执行 `npm run typecheck`、`npm run check:encoding`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`。 - -## 2026-06-18 图片画布生成音乐入口作为音频图层接入 - -- 背景:图片画布底部生成工具需要补齐游戏音效和游戏背景音乐生成,既要复用现有 Lovart 式画布生成器快照、占位避让和持久化,又不能把音频能力并入图片素材库或视觉小说专用音频开关。 -- 决策:`/editor/canvas` 新增底部 `生成音乐` 入口,点击后先弹出“生成游戏音效 / 生成游戏背景音乐”选项框,再分别创建 `audio-sound-effect` 或 `audio-background-music` 生成器;生成结果作为 `mediaType="audio"` 的画布音频卡保存,`assetKind` 分别为 `sound-effect` / `background-music`。音效请求字段固定映射 Vidu `prompt/model/duration`,模型固定 `audio1.0`、时长严格 `2-10` 秒;背景音乐请求字段固定映射 `gpt_description_prompt` 且 `make_instrumental=true`。 -- 影响范围:图片画布生成工作流、前端 editorProjectClient、`shared-contracts`、`platform-audio`、`api-server` 编辑器音频 BFF、图片画布技术方案和音乐生成入口设计文档。 -- 验证方式:运行编辑器生成入口 / 提交 / 音频图层相关前端测试,`platform-audio` 请求体测试,`shared-contracts` editor audio 序列化测试,`api-server` editor audio 归一化测试,并执行 `npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/【编辑器】画板音乐生成入口设计-2026-06-18.md`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`。 - -## 2026-06-17 图片画布生成占位统一避让落点 - -- 背景:图片画布的普通图片、规范、角色、图标、视频和 UI 设计图生成入口都会先在画布中新建“即将生成”的占位图;若各入口直接使用当前视口中心,容易压住已有图片或已有生成占位,Lovart 式连续创作体验不稳定。 -- 决策:所有会新建画布生成占位的入口统一经过 `ImageCanvasGenerationPlacementModel` 计算落点。模型以当前视口世界中心为目标,避让所有未隐藏画布图层和 active / inactive generation dialog placeholder,按 32px 画布世界坐标间距外扩阻挡矩形,选择距离当前屏幕中心对应画板位置最近且不重叠的位置。选定后立即调用 `centerViewportOnPlacement(...)`,保持当前缩放比例不变,只平移画布 viewport,让屏幕中心移动到新占位中心。 -- 影响范围:`/editor/canvas` 图片画布生成入口、`useImageCanvasGenerationWorkflow`、`ImageCanvasGenerationPlacementModel`、图片画布技术方案和 Lovart 生成类面板文档。 -- 验证方式:运行 `npm run test -- src/components/image-editor/ImageCanvasGenerationPlacementModel.test.ts src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx`,并执行 `npm run typecheck`、`npm run check:encoding`、`git diff --check`。 -- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`。 - -## 2026-06-13 Pingora 低端口直连只通过显式 systemd drop-in 启用 - -- 背景:`genarrative-pingora-gateway.service` 默认以 `genarrative` 非 root 用户运行,shadow 阶段只监听本机高端口;如果正式评估让 Pingora 直接绑定公网 `80/443`,需要低端口绑定能力,但不能让 Server-Provision 或默认 service 自动改变接流边界。 -- 决策:主 systemd service 保持 shadow 口径,不携带 `CAP_NET_BIND_SERVICE`。仓库提供 `deploy/systemd/genarrative-pingora-gateway-direct-entry.conf` 作为人工启用 drop-in 模板,Server-Provision 只安装到 `/etc/genarrative/pingora/genarrative-pingora-gateway-direct-entry.conf` 备查和手动覆盖;正式切换窗口从 `/opt/genarrative/current/scripts/deploy/pingora-direct-enable.sh` 执行时默认读取 current release 随包的 `/opt/genarrative/current/deploy/systemd/genarrative-pingora-gateway-direct-entry.conf`,不依赖 `/etc` 参考模板、Jenkins 工作区或源码 checkout。直连切换前先用 `npm run plan:pingora-direct-cutover -- --require-direct ...` 生成 JSON runbook,逐条审阅 Host 与回退巡检入口确认、current release preflight、启用前基础门禁、direct enable dry-run、direct enable apply(通过命令证据脚本归档 stdout / stderr / 退出码)、切换后 health patrol 切到 `pingora-direct`、启用后 health patrol env 直连复核、启用后 `--require-direct` 复核、rollback dry-run、rollback apply(通过命令证据脚本归档 stdout / stderr / 退出码)、回退后 health patrol 切回 `nginx` 并恢复切换前 public base URL / Host、回退后 health patrol env Nginx 模式复核;启用前基础门禁不带 `--require-direct`,因为 systemd drop-in 尚未生效,启用后复核必须带 `--require-direct`。正式切换 runbook 中 `--direct-redirect-host`、`--rollback-nginx-smoke-host` 和 `--direct-host` 必须使用同一 hostname,只允许端口不同,避免 redirect 和回退 smoke 分别验证到不同入口;还必须显式传 `--rollback-health-patrol-public-base-url <切换前Nginx巡检入口>`,切换前 Nginx 巡检需要 Host 覆盖时再传 `--rollback-health-patrol-public-host <切换前Host>`,确认步骤会展示回退后要恢复的 public base URL / Host,避免回退 runbook 覆盖现场原有巡检入口。若需把回退后 Pingora shadow 探针复核纳入 runbook,追加 `--rollback-pingora-shadow-probe-url` / `--rollback-pingora-shadow-probe-token`,JSON 输出会隐藏 token 原文并把参数传给 rollback dry-run / apply。只有切换窗口通过 `pingora-direct-enable.sh --apply --preflight-env-file /etc/genarrative/pingora-gateway.env --preflight-check-cert-readable --preflight-check-service-env-file --preflight-check-service-user-cert-readable --preflight-check-service-binary-executable --preflight-check-ports-free --direct-https-base-url https://127.0.0.1 --direct-http-base-url http://127.0.0.1 --direct-host <域名> --direct-redirect-host <域名或host:port> --direct-spacetime-database <库名>` 先跑 current release 自审,确认发布包自包含、`pingora-gateway` 可执行且 systemd `ExecStart` 指向随包网关,失败时不安装 drop-in;随后跑 direct preflight,确认当前执行用户和 `genarrative-pingora-gateway.service` 的 `User=` 服务用户都可读取证书链 / 私钥,确认 service 模板与 `systemctl cat` 最终配置读取的 `EnvironmentFile=` 都包含本次 `/etc/genarrative/pingora-gateway.env`,并确认 service `ExecStart=` 指向的 current release `pingora-gateway` 存在且可执行,再安装到 `/etc/systemd/system/genarrative-pingora-gateway.service.d/direct-entry.conf`、执行 `systemctl daemon-reload`、重启 Pingora,并用 `systemctl cat` 核验 `AmbientCapabilities=CAP_NET_BIND_SERVICE`、`CapabilityBoundingSet=CAP_NET_BIND_SERVICE` 和 `EnvironmentFile=/etc/genarrative/pingora-gateway.env` 已生效、用 `systemctl is-active` 确认服务 active、用 direct live smoke 验证 HTTPS / HTTP redirect / ACME / WSS 101 后,才视为授予低端口能力成功。启用前还必须显式配置 TLS / redirect env 和真实证书,并确认 current release 已落盘可执行 `pingora-gateway`、Nginx 或其它进程已释放 `80/443`;启用后仍必须跑 release readiness 门禁;验证失败时统一执行 `pingora-direct-rollback.sh --apply --reload-nginx --nginx-smoke-url https://<域名>/ --nginx-smoke-expect-body ''` 回到 shadow / Nginx 入口,回退脚本会先运行 `nginx -t`,通过后移除 direct-entry drop-in、重启 Pingora,再用 `systemctl cat` 确认两条低端口 capability 均已从最终 unit 配置中移除,用 `systemctl show ... ExecStart` 确认最终 service 仍指向随包主 service 模板中的 current release `pingora-gateway`,并 reload Nginx、确认 Nginx service 仍为 `active`,最后用 curl smoke URL 证明 Nginx 入口真实可访问;回退 smoke URL/body 必须来自切换前真实 Nginx 入口,不要继续用固定 `http://127.0.0.1/healthz` 与 `"ok":true`。回退脚本 `--apply` 必须同时带 `--reload-nginx` 和 `--nginx-smoke-url`,避免只撤掉 Pingora 低端口能力却没有证明 Nginx 已重新接流;本机打 `127.0.0.1`、`localhost` 或 `::1` 时,`--apply` 必须带 `--nginx-smoke-host <域名>`,且该值只能是 host 或 `host:port`,避免命中默认 vhost。回退后必须复核 health patrol env 已切回 `nginx` 且 public base URL / Host 恢复为切换前记录值;如果 env 已预先修正,rollback 脚本可追加 `--health-patrol-env-file /etc/genarrative/health-patrol.env --health-patrol-expected-public-base-url <切换前Nginx巡检入口> --health-patrol-require-empty-public-host` 自动执行这项复核,切换前 Nginx 巡检需要 Host 覆盖时把最后一项换成 `--health-patrol-expected-public-host <切换前Host>`。若需证明 Pingora 仍以 shadow 高端口存活,可追加 `--pingora-shadow-probe-url http://127.0.0.1:18081/__genarrative_pingora/healthz --pingora-shadow-probe-token `,脚本会隐藏 token 并要求响应包含 `gateway=pingora-shadow`。 -- 决策补充:health patrol env 的直连/回退切换不再靠人工编辑三行变量;正式 runbook 使用 current release 随包 `node -- /opt/genarrative/current/scripts/deploy/pingora-health-patrol-env-switch.mjs --apply`,只更新 `GENARRATIVE_HEALTH_PATROL_GATEWAY_MODE`、`GENARRATIVE_HEALTH_PATROL_PUBLIC_BASE_URL`、`GENARRATIVE_HEALTH_PATROL_PUBLIC_HOST` 并立即调用随包 `check-production-health-patrol-env.mjs` 复核。Pingora direct 使用本机 public base URL 时脚本必须带 `--public-host <域名>`;回退到 Nginx 时根据切换前记录传 `--clear-public-host` 或 `--public-host <切换前Host>`。生产巡检、health patrol env 复核和 env 切换脚本读取的布尔 env 必须严格解析,非法值直接失败,不得静默按 false 继续;env 复核脚本的 `--env-file` 与 env 切换脚本的 `--env-file` / `--check-script` 必须是绝对路径且不能是文件系统根目录,也不能包含换行或 NUL;env 切换脚本写入的 public base URL / Host 同样不能包含换行或 NUL。Node 22 已内置 `--env-file` 启动参数,凡是用 Node 启动项目脚本且要把业务 `--env-file` 传给脚本时,必须写成 `node --