合并 master:音频后台化与 Mac 构建管线进分支,冲突按新口径解
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
- index.tsx 的 audio/video 提交:取 master 侧(#437 已把它改成后台任务队列 + 项目内账本), 卡片浮层那套本地提交记录在这条链路上不再需要——队列本身就是它的可见性与幂等来源 - PRD 更新时间两边的两条事实合成一行;decision-log 保留 master 的音频章节与我们的 派生任务/提交即关章节,并把「appSurface 16 条既有失败」更正为 cwd 假红的口径 - 样式守卫里撤掉「生图面板」这条探针:它走 AGC 自有类名,本就不吃 `image-canvas-editor__*` 那一族(守卫自身加的空集断言把这条假探针暴露了出来) - 合并后从仓库根验证:appSurface 538 通过 / 17 跳过 / 0 失败;AGC 定向 84 条、typecheck、 check:encoding、git diff --check 全通过
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# AI 游戏创作项目开发工作台 PRD
|
||||
|
||||
更新时间:`2026-09-20`(派生/修改类任务并入同一「生成任务」侧栏,见 §3.10;2026-09-14 同步功能画布图片类生成后台化的当前事实:入口 IPC 改为 `start_local_project_asset_generation` + 项目内任务账本 + 本地排队 + 非模态「生成任务」面板,见 §3.10 / §7.9;2026-09-13 新增的功能画布底部工具栏入口矩阵 §3.10 / §7.9,以及右侧 Supervisor 对话气泡、可访问对比度与过程卡布局收口,资源卡预览、分区布局、非破坏性资源编辑、资源替换与 Godot 双根合同保持不变)
|
||||
更新时间:`2026-09-21`(2026-09-20 音频生成并入图片类那份后台任务账本、派生/修改类任务并入同一「生成任务」侧栏,2026-09-21 卡片浮层改为「提交即关」,见 §3.10 / §7.9;2026-09-14 图片类生成后台化:入口 IPC 为 `start_local_project_asset_generation` + 项目内任务账本 + 本地排队 + 非模态「生成任务」面板;2026-09-13 新增的功能画布底部工具栏入口矩阵 §3.10 / §7.9,以及右侧 Supervisor 对话气泡、可访问对比度与过程卡布局收口,资源卡预览、分区布局、非破坏性资源编辑、资源替换与 Godot 双根合同保持不变)
|
||||
|
||||
## 1. 产品定位
|
||||
|
||||
@@ -151,19 +151,19 @@
|
||||
|
||||
### 3.10 功能画布底部工具栏(入口矩阵)
|
||||
|
||||
实现状态(2026-09-13;2026-09-14 图片类生成后台化:提交即返回 + 项目内任务账本 + 本地排队 + 非模态「生成任务」面板):功能画布 = 资源栏目页(`resourceBookState.view === 'child'`)。栏目页左下角的底部工具栏按 manifest 资产的**功能分类** `category` 分流,矩阵由用户 2026-09-13 拍板,工具项顺序即下表顺序(最右一项为「上传」)。
|
||||
实现状态(2026-09-13;2026-09-14 图片类生成后台化:提交即返回 + 项目内任务账本 + 本地排队 + 非模态「生成任务」面板;2026-09-20 音频生成并入同一条后台任务账本):功能画布 = 资源栏目页(`resourceBookState.view === 'child'`)。栏目页左下角的底部工具栏按 manifest 资产的**功能分类** `category` 分流,矩阵由用户 2026-09-13 拍板,工具项顺序即下表顺序(最右一项为「上传」)。
|
||||
|
||||
| 栏目 | 工具栏里的生成入口 |
|
||||
| --- | --- |
|
||||
| UI 与交互 `ui-interaction` | 生成图片 | 生成规范(二级:图标规范 / 自定义规范)| 生成图标素材 | 生成 UI 设计图 | 上传 |
|
||||
| 角色与对象 `character` | 生成图片 | 生成规范(二级:角色规范 / 自定义规范)| 生成角色形象 | 上传 |
|
||||
| 场景与环境 `scene` | 生成图片 | 生成规范(二级:自定义规范)| 上传 |
|
||||
| 音频 `audio` | 生成背景音乐 | 生成音效 | 上传 |
|
||||
| 文档 `document`、待归类 `unclassified`、项目版本 `version`、「所有资源」展开态、资源总览 | **不渲染工具栏** |
|
||||
| 栏目 | 工具栏里的生成入口 |
|
||||
| ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| UI 与交互 `ui-interaction` | 生成图片 | 生成规范(二级:图标规范 / 自定义规范)| 生成图标素材 | 生成 UI 设计图 | 上传 |
|
||||
| 角色与对象 `character` | 生成图片 | 生成规范(二级:角色规范 / 自定义规范)| 生成角色形象 | 上传 |
|
||||
| 场景与环境 `scene` | 生成图片 | 生成规范(二级:自定义规范)| 上传 |
|
||||
| 音频 `audio` | 生成背景音乐 | 生成音效 | 上传 |
|
||||
| 文档 `document`、待归类 `unclassified`、项目版本 `version`、「所有资源」展开态、资源总览 | **不渲染工具栏** |
|
||||
|
||||
- 位置与层级:画布左下角(`left: 14px; bottom: 14px; z-index: 40`)。右下角是既有的缩放 / 撤销 Dock(`right: 14px; bottom: 14px`),左下角是画布上唯一两者都不占的稳定空位。工具栏是管理区 `.game-resource-book-manager` 的**直接子节点**、与画本场景并列,不进带 `scale()` 的场景层;二级菜单与「入口不可用原因」都贴着工具栏上沿弹出,不做内嵌内容。
|
||||
- 外壳用共享 chrome(`packages/image-canvas-react` 的 `CanvasToolbar / CanvasToolbarGroup / CanvasChromeButton`),样式落在 AGC 的 `resourceCanvasChrome.css`;共享包只承接通用表现,不含业务规则。
|
||||
- 接线:图片类入口走本地 IPC `start_local_project_asset_generation`(`kind` ∈ `image / character / spec / icon-spec / ui-prototype / art-spritesheet`;**提交即返回任务记录**,生成由 Rust 后台任务跑完写回项目,进度用 `list_local_project_asset_generations` 读回项目内账本 `.agent/runtime/asset-generation-tasks/tasks.json`);音频入口复用既有的无源生成链路 `derive_local_project_resource`(`generationMode: 'create'`、`editKind` = `sound-effect` / `background-music`);「上传」复用 `upload_local_asset`。生成 / 上传成功后一律用「配对读 `(revision, manifest)`」交给 `onManifestChange`,走既有 manifest 刷新与资源投影链路,不重算依赖图、不另写布局。
|
||||
- 接线:图片类入口走本地 IPC `start_local_project_asset_generation`(`kind` ∈ `image / character / spec / icon-spec / ui-prototype / art-spritesheet`;**提交即返回任务记录**,生成由 Rust 后台任务跑完写回项目,进度用 `list_local_project_asset_generations` 读回项目内账本 `.agent/runtime/asset-generation-tasks/tasks.json`);音频入口也走 `start_local_project_asset_generation`(同一份项目内任务账本;`kind` = `sound-effect` / `background-music`,并额外携带该次生成的请求身份 `idempotencyKey`,任务 id 即该次生成的 operation id;生成仍复用既有音频无源生成链路,`generationMode: 'create'`、`editKind` = `sound-effect` / `background-music`,不新增平台路由与请求体口径);「上传」复用 `upload_local_asset`。生成 / 上传成功后一律用「配对读 `(revision, manifest)`」交给 `onManifestChange`,走既有 manifest 刷新与资源投影链路,不重算依赖图、不另写布局。
|
||||
- 本地排队与进度可见:AGC 本地 durable 输出槽已按**精确动作指纹**分槽(不同 prompt / 素材名各自独立成槽,具备并行能力),但本批前端仍按「同一时刻只派发一条」排队——真并行派发需要并发收口设计(配对读 + manifest CAS + 聚焦意图互不覆盖),留待下一批;所以第一条未终态时第二条提交停在**前端本地队列**里(不调用提交 IPC,显示本地排队的「排队中。」),前一条终态后自动补发;任务状态与阶段文案(后端 `phaseDetail`)由任务账本提供,前端不拼阶段、不做百分比。进度面是**画布上常驻的可折叠任务侧栏**(形态对齐网页端美术画布的任务侧栏):展开是两个分栏「排队/生成中」与「已完成」(各带条数,「已完成」封顶 20 条 + 列表滚动 + 高度有界),关闭入口只保留头部那一枚 ×(底部重复的关闭按钮与其分割线已删除)、折叠即整块让出画布且不留贴边把手,开合只走工具条上常驻的「生成任务 · N」按钮(两个页签下都在);每项显示状态徽标 / 阶段文案 / 已耗时 / 素材名,可「定位到素材」。侧栏非模态(不铺全屏遮罩、不做焦点陷阱、不参与模态遮挡判据),位置在画布左侧标题栏之下、**覆盖式**(不 reflow 挤窄画布视口),提交受理后自动展开。定位动作**每次点击都终局化**:能定位就定位并选中;素材在别的栏目先切栏目;不在投影里给「素材已不在项目里 / 已登记但尚未同步」的结论;3 秒内有界兜底,不允许提示条永久停在「正在定位生成的素材…」。
|
||||
- 面板形态:独立浮层(`ThemedModal`),**不在当前面板下面追加内容**;面板内不写功能说明或规则解释文案。**点「生成」即同步关闭面板**(不等 IPC、不等排队、不等生成),面板里**不出现**「排队中。」「正在生成。」「提交中…」这类阶段文案——阶段文案的唯一去处是任务侧栏与工具栏提示条。**只有「点击瞬间就失败」**(校验不过、权限拒绝、start IPC 立即报错)才自动重开面板并带回草稿与原因;**受理之后才失败**只在侧栏把该任务收口为失败 + 原因,不重开面板。关闭 ≠ 取消请求(请求挂在任务与账本上,不挂在面板生命周期上)。
|
||||
- 参数口径:比例 / 尺寸选项来自网页端美术画布的纯模型(`src/components/image-editor/ImageCanvasGenerationModel.ts`),并按本地 IPC 白名单收窄(本地通道明确拒绝 `4:3`);默认档 `1:1 · 1K`,生成 UI 设计图沿用网页端 UI 设计面板的默认 `16:9 · 1K`。本地 IPC 没有 `model` 入参,因此面板**不渲染模型选择器**(渲染一个改不了请求的控件就是假控件)。
|
||||
@@ -366,7 +366,7 @@ type UpdateProjectResourceCanvasLayoutResult =
|
||||
1. **查找素材**:关键词,就是画布搜索本身,与筛选条件共用同一份状态,只有一个入口读写它,不得各存一份;判据沿用搜索既有的名称、路径、媒体类型、任务名四字段与大小写不敏感口径。
|
||||
2. **所在区域**:取值为「全部区域」加上现行分区栏目(`PROJECT_RESOURCE_CANVAS_SECTIONS` 的 6 类资产分类与末尾独立的「项目版本」栏),显示名沿用 `@` 面板资源筛选那份唯一中文口径,不另建译名表。
|
||||
3. **自定义标签**:从 manifest `assets[].tags` 派生的标签库,多选且为 AND 语义(已选标签必须全部命中,空选择不过滤),复用共享判据 `assetTagsMatchSelection`。
|
||||
不提供「状态」字段:manifest 资产与资源投影都没有状态事实源,候选的任务状态与附件导入状态在资源投影里已被上游过滤,任何取值都恒为同一结果,因此不渲染该字段,也不保留占位下拉。
|
||||
不提供「状态」字段:manifest 资产与资源投影都没有状态事实源,候选的任务状态与附件导入状态在资源投影里已被上游过滤,任何取值都恒为同一结果,因此不渲染该字段,也不保留占位下拉。
|
||||
- 「所在区域」**既是筛选维度也是画布当前栏目**,两者必须是同一份状态:区域取值由画布栏目状态派生,切换区域走与栏目切换完全相同的那一条路径,因此用户用滚轮、总览卡片或下一页切换栏目时区域显示随之变化,不需要双向同步逻辑,也不会出现两处状态互相漂移。
|
||||
- 区域取值与其它维度叠加时,筛选只作用于当前区域内的资源;「全部区域」作用于全部资源。两种语义共用同一份过滤实现,不为「只筛当前区域」另写一套裁集合逻辑。
|
||||
- 筛选浮层是画布唯一的搜索与筛选入口:Dock 上的放大镜按钮与 `Ctrl/Cmd+F` 叫出的是同一个浮层,不存在第二个浮层,因此也不存在「两个浮层互斥」这一说。
|
||||
@@ -667,9 +667,10 @@ type ProjectAgentMudPointAttribution = {
|
||||
3. 每个图片类入口一次提交**一条** `start_local_project_asset_generation`,载荷字段逐字为 `{ projectPath, projectId, taskId, kind, prompt, aspectRatio, imageSize, assetName, outputPath }`——**原同步命令的生成载荷字段名与取值口径逐字不变**(`kind / prompt / aspectRatio / imageSize / assetName / outputPath` 全部原样搬过来),只多了任务身份 `projectId` 与前端每次提交新铸的本地 `taskId`;`kind` 映射:生成图片 `image`、生成角色形象 `character`、图标规范 `icon-spec`、角色规范 / 自定义规范 `spec`、生成图标素材 `art-spritesheet`、生成 UI 设计图 `ui-prototype`。命令**提交即返回**一条任务记录,生成在 Rust 后台任务里跑,状态与阶段由 `list_local_project_asset_generations` 从项目内账本读回。
|
||||
4. 比例 / 尺寸选项**不含**本地通道拒绝的 `4:3`;比例与尺寸的切换都进入载荷;固定档规范入口只读展示当前规格(如 `1:1·1K`),不渲染可点比例控件。
|
||||
5. 缺权威规范图时「生成图标素材 / 生成 UI 设计图」保持可点击、给出含 `assets/art-spec.png` 的原因说明,且**不发出任何生成请求**;「图标规范」此时把 `outputPath` 指向 `assets/art-spec.png`;项目已有权威规范图时 `outputPath` 为 `null`(两种状态各一条用例)。
|
||||
6. 生成 / 上传成功后走既有刷新路径:`get_local_game_project_revision` + `get_local_game_manifest` 的配对读发生在**该任务收口之后**(提交命令不再等待生成,配对读由任务终态驱动,顺序仍在写入之后),结果交给 `onManifestChange`;音频入口提交的是 `derive_local_project_resource`(`editKind` = `sound-effect` / `background-music`、`generationMode: 'create'`、`sourceMediaType: 'audio/mpeg'`)。
|
||||
6. 生成 / 上传成功后走既有刷新路径:`get_local_game_project_revision` + `get_local_game_manifest` 的配对读发生在**该任务收口之后**(提交命令不再等待生成,配对读由任务终态驱动,顺序仍在写入之后),结果交给 `onManifestChange`;音频入口提交同一条命令的音频载荷(`kind` = `sound-effect` / `background-music`、`idempotencyKey` = 该次生成的幂等键、任务 id 即该次生成的 operation id);原生命令内部仍复用既有音频无源生成链路(`editKind` = `sound-effect` / `background-music`、`generationMode: 'create'`、源快照媒体类型由 `editKind` 推为 `audio/mpeg`),不新增平台路由、请求体或计费口径。
|
||||
7. 既有「生成素材」浮层入口只呈现视频:面板不再渲染音效 / 背景音乐类型选择器(单类型入口没有类型选择器),音频入口只出现在音频栏目工具栏。
|
||||
8. 生成期间可退出与本地排队(2026-09-14):提交后点 × / 遮罩 / Esc /「后台运行并关闭」任一都能关面板,画布立即恢复可交互,关闭不取消请求;面板关闭后任务仍在「生成任务」面板(非模态浮层,无 `aria-modal`)里显示后端 `phaseDetail`;第一条未终态时提交第二条 → 第二条显示「排队中。」且生成提交 IPC 次数仍为 1,第一条终态后自动补发(次数为 2);两条各自完成后各走一次「配对读 + 落卡」,manifest revision 单调、不被后到者覆盖。
|
||||
8. 提交即关闭与本地排队(2026-09-14 图片类后台化,2026-09-20 音频并入同一条通道):点「生成」就把这次输入交给后台任务账本并**同步关闭**面板(不等 IPC、不等排队、不等生成),画布立即恢复可交互,关闭不等于取消;面板里因此不出现「排队中。」「正在生成。」「提交中…」与「后台运行并关闭」这类阶段文案与在途按钮,未提交时点 × / 遮罩 / Esc 收起面板只是收起草稿、不发请求;面板关闭后任务仍在「生成任务」面板(非模态浮层,无 `aria-modal`)里显示后端 `phaseDetail`;第一条未终态时提交第二条 → 第二条显示「排队中。」且生成提交 IPC 次数仍为 1,第一条终态后自动补发(次数为 2);两条各自完成后各走一次「配对读 + 落卡」,manifest revision 单调、不被后到者覆盖。
|
||||
9. 音频生成进入后台任务账本(2026-09-20):音频栏目的「生成背景音乐 / 生成音效」提交后**立即**返回一条任务记录并同步关闭面板(不等 IPC、不等排队、不等生成);任务与图片类任务在同一条本地队列里按「同一时刻只派发一条」排队,面板关闭后仍在「生成任务」侧栏显示后端 `phaseDetail`;成功走既有的「配对读 `(revision, manifest)` + 落占位最新位置」;只有「点击瞬间就失败」(未受理)才自动重开面板并带回原草稿与原请求身份,受理之后才失败只在侧栏收口为失败。同一份失败原请求的重试复用同一 operation 与幂等键,不产生第二次付费生成;重开项目后音频任务从账本恢复显示,上次运行中断的任务按中断口径收口。
|
||||
|
||||
## 8. 非目标
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 【实施计划】AGC 音频生成进入后台任务账本
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Milestone | `docs/project-memory/plans/【里程碑】AGC音频生成进入后台任务账本-2026-09-20.md` |
|
||||
| Status | implemented-awaiting-runtime-acceptance |
|
||||
| Owner | 主 Agent(自审;本运行没有独立评审人) |
|
||||
|
||||
## 修改边界
|
||||
|
||||
- 允许修改:
|
||||
- 主规范:`docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md`(§3.10 / §7.9)、`docs/technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md`。
|
||||
- AGC 原生:`apps/ai-game-creator-shell/src-tauri/src/asset_generation_tasks.rs`、`commands.rs`、`project.rs`、`project/resource_editor.rs`(仅新增收口入口,不改既有派生语义)。
|
||||
- AGC 前端:`apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasAssetGenerationTaskModel.ts`、`resourceCanvasAssetGenerationQueue.ts`、`view/project-development/index.tsx`。
|
||||
- 定向测试:`apps/ai-game-creator-shell/tests/resourceCanvasGenerationHostLifecycle.test.tsx`、`resourceCanvasAssetGenerationQueue.test.ts`、`appSurface/project-development.suite.ts`(仅音频相关断言)。
|
||||
- 明确不修改:`/api/editor/audios/*/generations` 与 `/api/external/v1` 路由、请求体、OpenAPI、共享 DTO、SpacetimeDB schema、权限命令词汇、`derive_local_project_resource` 的同步语义与其既有无源生成入参校验。
|
||||
|
||||
## 实现顺序
|
||||
|
||||
1. 主规范:把音频入口的接线口径从「同步无源生成」改写为「与图片类同一条后台任务账本」,并补上音频提交载荷、失败重开与幂等条款(PRD §3.10 / §7.9,AGC 工具栏入口矩阵文档)。
|
||||
2. 原生:在资源编辑模块新增音频入参收口与「后台跑一次音频派生」的入口(复用既有派生实现,不复制生成逻辑);在 `asset_generation_tasks` 里按 `kind` 分流,音频任务复用同一份账本、同一套阶段文案与中断收口;`start_local_project_asset_generation` 增加可选幂等键入参,音频 kind 走新分支且不改图片类载荷口径。
|
||||
3. 原生测试:音频任务入参收口(kind / 提示词上限 / 幂等键 / 未知 kind 拒绝)、账本记录 kind 为音频、图像载荷口径不回归。
|
||||
4. 前端模型与队列:任务模型支持音频任务(kind、请求身份、无比例 / 尺寸 / 参考字段),音频 kind 的入口文案从工具栏模型派生;队列按 kind 分流派发同一命令的音频载荷,其余排队与轮询语义不变。
|
||||
5. 前端宿主:音频提交改为「入队即返回」,占位绑定任务 id、自动展开侧栏、给出提示条;收口复用既有「配对读 + 落卡」链路,未受理失败按原请求身份重开音频面板。
|
||||
6. 前端测试:宿主生命周期(提交即关闭、侧栏可见、落卡、未受理失败重开并复用身份)、队列音频分支(载荷与轮询、第二条本地排队不发 IPC)、appSurface 音频载荷。
|
||||
7. 验证与证据矩阵:跑定向测试、类型检查、编码 / 文档索引 / `git diff --check`,按里程碑逐条填写证据。
|
||||
|
||||
## 验证命令
|
||||
|
||||
1. `npx vitest run apps/ai-game-creator-shell/tests/resourceCanvasGenerationHostLifecycle.test.tsx apps/ai-game-creator-shell/tests/resourceCanvasAssetGenerationQueue.test.ts apps/ai-game-creator-shell/tests/resourceCanvasAssetGenerationTasksPanel.test.tsx`
|
||||
2. `npx vitest run apps/ai-game-creator-shell/tests/appSurface.test.ts`
|
||||
3. `cargo test -p genarrative-ai-game-creator-shell asset_generation_task`
|
||||
4. `npm run agc:typecheck`(或 `npm run typecheck --workspace @genarrative/ai-game-creator-shell`)
|
||||
5. `npm run check:encoding && npm run check:doc-index && git diff --check`
|
||||
|
||||
## 执行结果
|
||||
|
||||
1. 主规范:PRD(§3.10 / §7.9 / §7.9 第 8~9 条)与 AGC 工具栏入口矩阵文档改为「音频与图片类同一条后台任务账本」,同步 `【测试用例】AGC资源工作台V3端到端验收` 的 S11a 判据。
|
||||
2. 原生:`prepare_local_project_audio_generation`(提交期收口)+ `run_local_project_audio_generation_at`(派发时刻读 revision,复用派生实现),`start_local_project_asset_generation` 新增可选 `idempotencyKey` 并在音频 kind 分支落同一份账本、由 `run_local_project_audio_generation_task` 写 running → completed / failed;图片类分支逐字未改。
|
||||
3. 前端:任务模型新增音频任务与 `idempotencyKey`(恢复出来的历史任务不带它,也不承接重试);队列按 kind 分流派发载荷;面板提交改为同步返回并立即关闭;宿主改为同步入队 + 失败重开。
|
||||
4. 测试:面板(点击即关闭、无阶段文案与在途按钮)、队列(音频载荷逐字)、宿主生命周期(提交关闭 / 侧栏 / 落卡 / 未受理重开 / 受理后不重开 / 重试身份复用 / 失败态按占位隔离)、appSurface 音频载荷。
|
||||
5. 验证命令与结果:9 个定向 vitest 文件 73 项通过;`appSurface.test.ts` 552 项通过(17 项跳过);`cargo test asset_generation_task` 14 项通过;`npm run agc:typecheck`、`npm run check:encoding`、`npm run check:doc-index`、`git diff --check` 通过。
|
||||
6. 与预期不一致处:音频任务不再携带 `targetCategory`(原生音频通道不消费它,前端也没有读它的地方);`restored` 任务无幂等键,只用于展示与定位,不承接重试。
|
||||
7. 已知与本任务无关的既有失败:`clientAuthStorage` / `clientApi` / `clientHttp` / `chatPromptPolish` / `projectCreationDirectory` 五个文件在本机 Node v26 + vitest 0.34 的 jsdom 下 `localStorage` 为 undefined(在干净工作区同样失败);`cargo test resource_edit` 整组过滤下有 5 项既有并行干扰失败(单跑通过)。
|
||||
|
||||
## 风险与回滚点
|
||||
|
||||
- 音频任务与图片类任务共用队列:若音频任务未终态会挡住后续派发(本地排队是既有语义,接受)。回滚点是前端提交分支与原生 `kind` 分流,各自可独立回退。
|
||||
- 音频自带的 operation 幂等账本与任务账本是两层身份:任务 id 取 operation id,重试复用同一对 operation / 幂等键;不得为「省事」在重试时换新的请求身份(那是一次新的付费生成)。
|
||||
- 账本 `kind` 为音频时,`restore` 的入口文案若查不到工具栏模型会退化成素材名:入口文案必须由工具栏模型派生,避免恢复后文案漂移。
|
||||
- 后台跑生成会让「项目 revision CAS」窗口从提交前移到派发时刻:冲突时按失败收口(不静默重试),避免把生成写到非预期基线。
|
||||
@@ -0,0 +1,14 @@
|
||||
# Mac 本机构建节点接入实施计划
|
||||
|
||||
- Version: 1
|
||||
- Status: preparing-network-required
|
||||
- Date: 2026-09-18
|
||||
- Parent Spec: `【里程碑】Mac本机构建节点接入-2026-09-18.md`
|
||||
|
||||
1. 本地准备 universal 依赖预备、CI 打包脚本和 Jenkinsfile,运行离线单测、配置门禁及编码检查。
|
||||
2. 恢复内网后只读核对 Jenkins 版本、既有节点/Job、Git 凭据标识与插件;已存在对象优先核对,不重复创建。
|
||||
3. 从同一控制器取得 agent.jar,以当前已有 Java 21 运行专用 inbound Agent;secret 保存在用户私有目录,LaunchAgent 参数只引用 secret 文件,不保存控制器 API Token。
|
||||
4. 建立单 executor、EXCLUSIVE 的专用 Mac 节点与手动 archive-only Job。源码必须是可追溯 Git 提交,未推送改动需另行确认源码交付方式,不能默认推送。
|
||||
5. 初次构建核对独立工作目录、空间、目标与依赖;在 Jenkins 实际 SUCCESS 后确认 DMG、SHA-256 和两架构 smoke 证据。
|
||||
|
||||
失败边界:网络不可达不启动重试服务;节点/Job 修改前保留原配置;不更改其它节点、Job 或调度。禁止把 CLI 日志、认证文件和私有路径提交 Git。未获得真实 SUCCESS 前保留活动计划。
|
||||
@@ -0,0 +1,16 @@
|
||||
# Mac 通用安装包实施计划
|
||||
|
||||
- Version: 1
|
||||
- Status: awaiting-user-acceptance
|
||||
- Date: 2026-09-18
|
||||
- Parent Spec: `【里程碑】Mac通用安装包与构建管线-2026-09-18.md`
|
||||
|
||||
1. 等待当前 Intel 编译结束,避免共用 staging 并发写。
|
||||
2. macOS build.rs 按白名单分别 stage 两套原生资源;共享 Layout 使用架构子目录,运行时原有 hash/版本校验不变。
|
||||
3. Tauri macOS 映射双目录,发布入口接受 universal 并生成两个清单键;更新配置门禁与定向测试。
|
||||
4. 安装包 smoke 支持显式选择主程序切片,验证 universal 主程序与该切片对应原生依赖。
|
||||
5. 用 Tauri universal 构建 app,分别做 arm64/Rosetta smoke,hdiutil 生成新 universal DMG,校验并交付。
|
||||
|
||||
不发布、不使用私钥;依赖仅从锁定 npm tarball 下载并对照 lockfile integrity。磁盘不足停止,不擅自删除其它 target/cache。保留单架构 DMG。Jenkins 配置作为后续门禁,不混入本地包构建。
|
||||
|
||||
本地构建与双架构隔离验证完成,证据见对应里程碑。更新 master 时先停止旧构建,保护并恢复改动后重建;未进行 Jenkins 写操作,待确认 Mac Agent 再制定管线实施计划。
|
||||
@@ -3,7 +3,7 @@
|
||||
| 字段 | 值 |
|
||||
| ----------- | ------------------------------------------------------------------ |
|
||||
| Version | 1.0 |
|
||||
| Status | deferred |
|
||||
| Status | in-progress |
|
||||
| Date | 2026-09-17 |
|
||||
| Parent Spec | `docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md` |
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
- macOS 签名证书与公证凭据可用;若不满足,本里程碑只能交付构建与清单能力,并明确标注未验证项。
|
||||
- macOS 通用包所需的双架构工具链(两个 darwin 目标)在构建机上可用。
|
||||
|
||||
本里程碑暂缓执行:macOS 构建机与签名 / 公证凭据尚未就绪,改由后续独立变更承接;暂缓期间 dev-mac 渠道不发布。
|
||||
构建与发布能力已落地:专用 macOS Jenkins 节点(label `genarrative-agc-macos`)+ `Jenkinsfile.ai-game-creator-shell-macos-build` + `scripts/build-macos-ci.mjs` 负责 universal 构建、双架构隔离 smoke、universal DMG、渠道清单 `latest.json`、更新包验签门禁与 OSS 上传(`AGC_RELEASE_DRY_RUN` 默认开启)。
|
||||
|
||||
仍未就绪:Apple 代码签名与公证凭据(产物保持未签名 + 未公证,构建清单显式记录 `appleSigned=false` / `notarized=false`,首装需手动放行 Gatekeeper);「安装 → 重启接管新版本」的实机更新闭环、Intel 真机 smoke(当前 x86_64 侧为 Rosetta)尚未验收。
|
||||
|
||||
## 验收标准
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 【里程碑】AGC 音频生成进入后台任务账本
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Version | 1.0 |
|
||||
| Status | implemented-awaiting-runtime-acceptance |
|
||||
| Date | 2026-09-20 |
|
||||
| Parent Spec | `docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md`(§3.10 / §7.9)、`docs/technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md` |
|
||||
|
||||
## 目标
|
||||
|
||||
AGC 功能画布音频栏目的「生成背景音乐 / 生成音效」与图片类生成走**同一条后台生成任务账本**:提交即返回任务记录、生成在客户端后台跑、状态与阶段文案由账本提供,任务出现在画布「生成任务」侧栏里,重开项目后仍能看到并按中断口径收口。
|
||||
|
||||
## 范围
|
||||
|
||||
- 音频无源生成(`create`)的提交、排队、状态读回、成功落卡、失败收口与重试幂等。
|
||||
- 音频任务与图片类任务共用同一份项目内任务账本、同一个前端本地排队与同一个「生成任务」侧栏。
|
||||
- 音频任务的阶段文案、状态与耗时来源与图片类一致(后端账本拥有阶段文案)。
|
||||
|
||||
## 不在范围内
|
||||
|
||||
- 平台侧(api-server / external v1 / OpenAPI)路由、请求体、计费、队列与 worker 语义:本轮不改,音频仍提交既有 `/api/editor/audios/*/generations` 通道。
|
||||
- 音频波形级编辑、多轨、时长 / 循环等音频参数入口:仍按现状不做。
|
||||
- 视频入口、上传入口、图片类生成的参数与前置判据:行为不变。
|
||||
- 真并行派发(并发收口设计):本轮仍保留「同一时刻只派发一条」的本地排队。
|
||||
|
||||
## 依赖与前置条件
|
||||
|
||||
- 现有图片类后台任务的账本、轮询、落点与聚焦链路可复用;音频生成通道(资源编辑派生)已具备 operation 幂等账本。
|
||||
- 音频提交需要携带请求身份(operation 与幂等键),否则重试会变成一次新的付费生成。
|
||||
|
||||
## 验收标准与证据
|
||||
|
||||
| 验收标准 | 结论 | 证据 |
|
||||
| --- | --- | --- |
|
||||
| 音频栏目的「生成背景音乐 / 生成音效」提交后**立即**返回一条任务记录;面板同步关闭,不等 IPC、不等排队、不等生成结束 | 自动化通过 | `resourceCanvasAssetGenerationBackgroundClose.test.tsx`(点「生成音效」同步提交 + 关闭,面板 DOM 里没有阶段文案与「后台运行并关闭」)、`resourceCanvasGenerationEntry.test.tsx`、`resourceCanvasGenerationHostLifecycle.test.tsx`(音频载荷逐字为 `projectPath / projectId / taskId / kind / prompt / assetName / idempotencyKey`) |
|
||||
| 提交受理后任务出现在「生成任务」侧栏,状态与阶段文案来自后端账本,前端不拼阶段、不做百分比 | 自动化通过 | `resourceCanvasAssetGenerationQueue.test.ts`(音频收口复用同一份账本记录)、`resourceCanvasAssetGenerationTasksPanel.test.tsx`、`resourceCanvasGenerationHostLifecycle.test.tsx`(提交后自动展开侧栏) |
|
||||
| 音频任务与图片类任务在同一条本地队列里按「同一时刻只派发一条」排队;第二条在本地排队期间不发提交 IPC | 自动化通过 | `resourceCanvasAssetGenerationQueue.test.ts`(音频载荷逐字断言 + 既有本地排队用例) |
|
||||
| 成功:走既有的「配对读 `(revision, manifest)`」交给 `onManifestChange`,结果落到该占位的最新位置并定位新卡 | 自动化通过 | `resourceCanvasGenerationHostLifecycle.test.tsx`(账本收口为 completed 后新卡落在占位坐标、占位被撤掉) |
|
||||
| 失败:只有「点击瞬间就失败」(未受理)才自动重开面板并带回原草稿与原请求身份;受理之后才失败只在侧栏收口为失败并给出原因,不重开面板 | 自动化通过 | `resourceCanvasGenerationHostLifecycle.test.tsx`「未受理的即时失败」(重开 + 草稿还原;同一用例里受理后不再重开)与「失败后用同一份请求重试」 |
|
||||
| 幂等:同一份失败原请求的重试复用同一 operation 与幂等键,不产生第二次付费生成 | 自动化通过 | `resourceCanvasGenerationHostLifecycle.test.tsx`(重试的 `taskId` = operation id 与 `idempotencyKey` 与首次逐字相同)、`resourceCanvasGenerationLanding.test.tsx` |
|
||||
| 重开项目:音频任务从账本恢复显示;上次运行中断的任务按中断口径收口,不假装还在跑 | 自动化通过(恢复路径) | 音频 kind 的入口文案由工具栏模型派生(`resourceCanvasAssetGenerationTaskModel` + `resourceCanvasAssetGenerationQueue.test.ts`);中断收口沿用既有账本口径 |
|
||||
| 音频提交失败(校验 / 权限 / 通道拒绝)时 manifest、revision 与任务账本都不出现半途写入 | 自动化通过 | Rust `asset_generation_tasks` 的 `audio_submission_rejects_invalid_identity_and_prompt_without_touching_the_ledger`(提交期拒绝零写入)、`audio_submission_lands_in_the_shared_ledger_with_its_audio_kind` |
|
||||
|
||||
运行时验收(未做):没有跑真实付费音频生成,也没有在真实客户端里做手感验收;全链以模拟原生接口的宿主用例覆盖。
|
||||
|
||||
## 证据要求
|
||||
|
||||
- 自动化:AGC 前端定向 vitest(音频入口宿主生命周期、生成任务队列与侧栏、appSurface 载荷)+ Rust 定向 `cargo test`(账本与音频任务入参收口)+ 类型检查 + 编码 / 文档索引 / `git diff --check`。
|
||||
- 运行时:无真实付费生成;以模拟原生接口的宿主用例覆盖提交 → 排队 → 收口 → 落卡全链。
|
||||
- 边界:未受理失败的即时重开与身份复用、账本读不到 / 记录缺失的收口、跨项目切换不串任务。
|
||||
@@ -0,0 +1,50 @@
|
||||
# Mac 本机构建节点接入
|
||||
|
||||
- Version: 1
|
||||
- Status: accepted-with-open-items
|
||||
- Date: 2026-09-18
|
||||
- Parent Spec: `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`
|
||||
|
||||
## 交付与边界
|
||||
|
||||
用户已确认使用当前 Mac,允许配置本机后台 Agent、创建 Jenkins 节点与构建 Job,并触发一次验证构建。复用已有 universal 产物合同与 Windows 管线的仓库访问凭据,仅手动构建和归档,无 OSS 上传、更新签名、Apple 签名/公证或定时调度。远程 Git 推送不在本次确认内。
|
||||
|
||||
节点仅运行明确匹配 `genarrative-agc-macos` 的可信构建,单 executor;Job 禁止并发。Agent 根、workspace、原生 staging 与 target 均独立于开发 checkout,禁止在开发目录执行 npm ci、git clean/reset 或 Cargo 构建。登录用户 Agent 不等于安全沙箱,Jenkins 管理员与获准运行此 Job 的人必须受信任。登出、休眠或脱离内网将影响节点可用性。
|
||||
|
||||
## 验收
|
||||
|
||||
1. 从 Jenkins 当前控制器下载匹配的 agent.jar,Java 21 兼容检查通过,凭据留在仓库外、权限受限,不输出 secret。
|
||||
2. 节点实际 online,专用标签、EXCLUSIVE、单 executor;本地 LaunchAgent 可重启、可卸载。
|
||||
3. SCM 构建固定源码 commit,依赖从 lockfile 安装,两种原生 Codex 包 integrity 校验通过。
|
||||
4. universal Release、两架构 smoke、DMG verify 通过;归档只有安装包、摘要和非敏感来源信息。
|
||||
5. 真实 Jenkins build 为 SUCCESS 且归档存在。不以 XML 创建或本地单测冒充远端运行成功。
|
||||
|
||||
## 初始检查与风险
|
||||
|
||||
2026-09-18 当前机器具备 Java 21、两种 Rust Apple target 与 Rosetta;剩余磁盘约 11 GiB,独立 checkout 构建前须检查空间,不清理用户缓存。控制器地址连续连接超时,属于网络阶段,尚未使用认证凭据或创建后台服务。必须先恢复内网可达性;不修改本机网络路由或代理规避此限制。
|
||||
|
||||
## 编码前评审
|
||||
|
||||
只扩展现有 Jenkinsfile/应用打包脚本,不新增发布系统。用专用工作区且保持不发布,是当前明确授权内的最小闭环。代码未推送前不可把远端 master 当作已具备 universal 双资源实现;首跑源码来源必须明确记录,不能暗用开发工作树。
|
||||
|
||||
## 当前证据与阻塞
|
||||
|
||||
Jenkinsfile、锁定双架构依赖预备脚本与 archive-only CI 打包入口已在本地准备。定向 Node 测试 37 项通过,类型/配置、编码、文档索引、定向 ESLint 与 diff 检查通过;未执行完整 Jenkins 构建或在线 Groovy 校验。
|
||||
|
||||
控制器直连多次超时,经当前代理请求返回 502;Java 21 已存在,无需安装新 JDK。尚未注册节点、创建 Job、保存 Agent secret、安装 LaunchAgent 或触发远端构建。需先恢复内网连接,再按本规范验收真实节点及构建状态;不把本地代码准备描述为已经接入成功。
|
||||
|
||||
## 验收结果(2026-09-20)
|
||||
|
||||
| 验收项 | 结果 |
|
||||
| --- | --- |
|
||||
| 控制器匹配的 agent.jar + 已有 Java 21 | 通过(未安装新 JDK) |
|
||||
| 节点实际 online、专用标签、EXCLUSIVE 单 executor | 通过(`genarrative-agc-macos-01`) |
|
||||
| LaunchAgent 可重启/卸载、凭据在仓库外且权限受限 | 通过 |
|
||||
| 固定 commit、锁文件装依赖、两种 macOS 原生包 integrity | 通过 |
|
||||
| universal Release + 双架构 smoke + DMG verify | 通过(arm64 原生、x86_64 走 Rosetta) |
|
||||
| 归档仅含安装包/摘要/非敏感来源信息 | 通过 |
|
||||
| 真实 Jenkins build SUCCESS 且归档存在 | 通过(build #3,43 分钟) |
|
||||
|
||||
同期修复:Mac 入口误传 `--no-sign` 导致更新包无签名;复用 workspace 的残留产物导致 DMG 重建失败、旧签名可能让验签误通过;并行度由写死 4 改为 Job 参数(默认 6)。
|
||||
|
||||
仍未验收:Apple 代码签名与公证(当前 `adhoc`,首装需 Gatekeeper 手动放行)、macOS 安装后重启接管新版本的实机闭环、Intel 真机 smoke、真实(非 dry-run)发布与渠道清单上线。
|
||||
@@ -0,0 +1,36 @@
|
||||
# Mac 通用安装包与构建管线
|
||||
|
||||
- Version: 1
|
||||
- Status: awaiting-user-acceptance
|
||||
- Date: 2026-09-18
|
||||
- Parent Spec: `docs/technical/【技术方案】AGC客户端更新检查与下载-2026-08-31.md`
|
||||
|
||||
## 当前交付门禁
|
||||
|
||||
当前仅交付 AGC 0.1.67 universal 本地 DMG,版本、Codex 0.147.0 与 macOS 15.0 下限不变。不生成私钥、不签名公证、不发布、不推送。
|
||||
|
||||
主程序含 arm64/x86_64 两个切片;macOS 资源分 `darwin-arm64` 与 `darwin-x64`,两套原生依赖保持上游相对路径和独立清单。运行切片只读取对应目录。构建必须校验两套锁定包身份、目标、版本与完整性;Windows 路径和资源不变。不合并原生 Codex 二进制,不改写其上游元数据。
|
||||
|
||||
## 验收
|
||||
|
||||
- 发布上下文接受 universal,dev-mac 的两个平台键同 URL/签名。
|
||||
- 主程序 lipo 两切片,资源检查两套原生架构、摘要和可执行位。
|
||||
- Apple Silicon 与 Rosetta 各做隔离 HOME/PATH 的真实 app-server 握手、正式程序查找与缺组件拒绝;Rosetta 不代替 Intel 真机。
|
||||
- 生成独立 universal DMG,不覆盖已有单架构 DMG;镜像校验、类型/配置/定向测试与编码检查通过。
|
||||
|
||||
## 后续管线边界
|
||||
|
||||
用户要求安装包完成后接入 Jenkins。先只读检查节点与现有 Job;创建/修改 Job、凭据或触发构建前额外确认。只有当前安装包门禁完成后再形成管线实现计划;不把凭据保存进源码、日志、计划或打包资源。
|
||||
|
||||
## 编码前评审
|
||||
|
||||
采用分架构资源而非 lipo Codex,避免破坏原生包元数据及 code-mode host、zsh 的资源寻址。macOS 共用配置明确列举两套文件,必须失败关闭,单架构诊断包也携带完整资源。现有 single-arch 选择逻辑改为同架构子目录,不涉及持久化数据迁移。
|
||||
|
||||
## 验收证据
|
||||
|
||||
- 同步至 master `9a21690fe`,本地 universal 修改无冲突恢复;未推送。
|
||||
- Tauri universal Release 构建通过,主程序 lipo 显示 arm64/x86_64,Info.plist 版本 0.1.67、最低 macOS 15.0。
|
||||
- `check-macos-bundle.mjs <app> arm64 --universal` 与 `x86_64 --universal` 均通过:每架构资源摘要、原生身份、执行权限、正式 Codex 选择、隔离 app-server 握手、缺 code-mode host 时拒绝。x86_64 在 Rosetta 执行,尚非 Intel 真机。
|
||||
- 发布/feature/上传定向 Node 测试 33 项通过,共享 Codex 布局模块在隔离 Cargo harness 的 2 项测试通过;类型/配置、定向 ESLint、编码/文档和 diff 检查通过。
|
||||
- universal `.app` 约 672 MiB,DMG 约 290 MiB;hdiutil 完整性校验通过。未做 GUI、账号/Provider、Intel 真机或签名公证验收。
|
||||
- Jenkins 只读检查确认现有节点为 Linux 与 Windows,尚无 macOS Agent;创建管线前需用户指定并授权接入 Mac 节点。本地凭据不进入源码或验证产物。
|
||||
@@ -35,7 +35,6 @@ Godot 编辑器操控复用既有 AGC 插件宿主、EditorAdapter、Runner 和
|
||||
- 决策(无写副作用):只在生成本轮 prompt 时展开该上下文;历史 item 回读走 `direct_codex_user_item_to_response_item` 的纯投影,不得触发 UI 代码导出或任何项目写入。
|
||||
- 验证:`agent::direct_codex_user_item` 定向 16 条通过,覆盖成功注入、生成失败保留引用摘要、非 UI 文档不触发与历史回读不产生 `ui/generated-*.js`。
|
||||
|
||||
|
||||
## 2026-09-19 AGC Direct 删除每回合四项媒体资源请求上限
|
||||
|
||||
- 背景:2026-08-24 引入的单回合四项上限以「整个 agent run(一条用户消息到回合结束)」为窗口,计数只增不减、请求完成不释放额度;autonomous 游戏构建要求 agent 不停下跑完整局,额度耗尽后的报错实际是终态,与技能的三次重试纪律冲突,现场表现为长时间无效重试。2026-09-18 先将不计费的抠图豁免,但付费 create/derive 仍受同一窗口问题影响。
|
||||
@@ -80,6 +79,7 @@ Godot 编辑器操控复用既有 AGC 插件宿主、EditorAdapter、Runner 和
|
||||
- 背景:AGC 已通过本地项目 ID 建立并持久化本地项目到主站远端画布项目的绑定,但 `agc_remove_background` 提交请求仍把本地 `manifest.project_id` 放入 `projectId`;`assetFolderId` 已使用远端素材目录 ID。主站因此按项目不存在或不属于当前账号返回 404,主站抠图和 BgFilter 本身均正常。
|
||||
- 决策:抠图请求及工具回执统一使用 `prepare_external_canvas_generation_context` 返回的远端 `context.project_id`;本地 manifest 项目 ID 只用于绑定键和本地状态,不得作为主站业务请求的 `projectId`。
|
||||
- 验证:客户端定向 Rust 测试、格式、编码和 diff 检查通过;未修改主站路由或 BgFilter。
|
||||
|
||||
## 2026-09-17 图集切分模式改为显式声明
|
||||
|
||||
## 2026-09-17 DirectProject 首屏历史锚点只认订阅回执的 lastCompletedItemId
|
||||
@@ -101,6 +101,7 @@ Godot 编辑器操控复用既有 AGC 插件宿主、EditorAdapter、Runner 和
|
||||
- 标准美术包:客户端显式声明 `sliceMode=connected-components` + `sliceCount=4`,本地按用途位置写四张 canonical 切片前再次校验数量正好为四,数量不符时失败关闭,禁止截断或补位。
|
||||
- 测试环境:在提权 shell 的 Windows 主机上,`%TEMP%` 下新建目录的默认所有者是 `BUILTIN\Administrators` 而不是当前 TokenUser,AGC 的所有者校验会拒绝测试自己创建的项目根;测试构建对该情形(仅限 `%TEMP%` 内、且失败原因为所有者不匹配)先按“本调用创建的对象”初始化所有者后重试,临时目录之外的越权所有者继续失败关闭。
|
||||
- 权威合同:[画板图标素材生成入口设计](../../【编辑器】画板图标素材生成入口设计-2026-06-15.md)。
|
||||
|
||||
## 2026-09-17 `agc_tools` 媒体资源提示词上限收敛为单一口径,并按 kind 暴露给模型
|
||||
|
||||
- 背景:有人反馈「客户端没法由 agent 调用图片快速编辑功能以及背景音乐生成功能」。核查后工具本身都在(`agc_edit_image` / `agc_create_or_derive_resource`),图片快速编辑在 2026-09-14 的真实项目日志里也有成功记录;但存在三类真实缺陷:① `agc_create_or_derive_resource` 的 `prompt` 在 schema 里只声明 4000,真实上限却是按 kind 分的(背景音乐 140、音效 1900、视频/角色动画 4000、图片 32000),MCP 层还额外写死了一条 140 判断,模型从 schema 与 skill 都看不出 140/1900,写一句正常长度的背景音乐描述就当场被拒;② 客户端 UI 用同一口径但会截断并提示,agent 侧却只有硬拒,形成「UI 能做、agent 调不动」的观感;③ `sourceLocalAssetId` 不是已登记资源时只报「不属于当前项目已登记资源」,模型会原地重试而不会先登记。
|
||||
@@ -219,6 +220,7 @@ Godot 编辑器操控复用既有 AGC 插件宿主、EditorAdapter、Runner 和
|
||||
- 决策:图片类生成接线改为 `start_local_project_asset_generation` + `list_local_project_asset_generations` 后,同步命令 `generate_local_project_asset` **已无生产调用方**,只剩 `src-tauri/src/tests/project.rs` 的三条集成用例与 `commands.rs` 的自身单测在调它;因此登记进 `scripts/check-config.mjs` 的 native-only 白名单(该门禁有「App invoke 与白名单互斥」断言,谁重新给它接调用方就必须同时删掉这条白名单项)。
|
||||
- 待办:它是**注册中的可调用 IPC**,一旦被将来代码调用就是一条绕过任务账本、单次阻塞最长 35 分钟的并行生成路径。下一批次应删除它,或改为转调 `start_local_project_asset_generation`(连带迁移那三条集成用例)。
|
||||
- 关联文档:[栏目画布底部工具栏入口矩阵](../../technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md)。
|
||||
|
||||
## 2026-09-14 AGC 壳 Rust 套件按「一片一 job」拆分,客户端 Rust 关键路径压到 7 分钟以内
|
||||
|
||||
- 背景:`AI game creator shell Rust tests` 是客户端 CI 的关键路径(run 2097 实测 15 分 27 秒)。拆开来看:前置 5 分 30 秒(checkout 10s + `npm ci` 2m45s + Cargo fetch 2m35s)、编译 1m39s、**AGC 壳 bin target 的 2466 条单测串行 507s**、`agent-run` smoke 51s。这 2466 条全在 `apps/ai-game-creator-shell/src-tauri` 的 bin target 里,一条 `cargo test … -- --test-threads=1` 跑完。
|
||||
@@ -231,6 +233,7 @@ Godot 编辑器操控复用既有 AGC 插件宿主、EditorAdapter、Runner 和
|
||||
- 影响范围:`.gitea/workflows/project-ci.yml`(十一个 job)、`scripts/check-native-shells.mjs`(分组由五个到十个:新增 `agc-rust-crates`、`agc-rust-shard-1..4`、`agc-rust-smoke`,移除 `agc-rust` 与随后的 `agc-rust-shell`)、根 `package.json`、`scripts/project-ci-workflow.test.ts`(新增纯 cargo job 免 `npm ci`、分片运行器覆盖校验、crate 级 job 预热顺序断言)、开发运维文档与共享记忆。本仓库不把 Project CI 的 context 配成 `master` 分支保护的合并必需检查(2026-09-14 复核),合并前由人工确认结果,因此 job 拆分/改名不需要同步分支保护设置。
|
||||
- 验证方式:`npx vitest run scripts/project-ci-workflow.test.ts`;分片运行器本地以 `agent-runtime-core`(7 条 → 2/2/2/1)与 `platform-llm`(146 条 → 49/49/48)验证分片、`--exact` 与片 TMPDIR 隔离,负例 `--shard-index=5` 立即失败;`node scripts/check-native-shells.mjs --groups=contract` 回归。预期每个分片 job 收敛到 5 分钟以内(前置约 1 分 30 秒 + 编译约 1 分 39 秒 + 约 617 条用例)。
|
||||
- 关联文档:[开发运维](../../【开发运维】本地开发验证与生产运维-2026-05-15.md)、[踩坑记录](pitfalls.md)。
|
||||
|
||||
## 2026-09-14 AGC 资源画布改为「手动整理」:新素材不再自动重排,整张重排只由「整理画布」发起
|
||||
|
||||
- 背景:生成一张新素材会让整张资源画布重排。两个 layout hook 都把 `rederiveAutomaticPositions` 打开(type 侧无条件 `true`,dependency 侧长期等于 `resourceGraphReady`),而该开关的语义是「每次资源协调签名变化就丢掉全部 `manuallyPlaced=false` 坐标、按当前资源与拓扑整体重算」;新增一张素材必然改签名,于是既有自动卡全部跟着挪位,用户刚记住的位置就没了。画布上也没有任何显式整理入口(`复位资源视图` 只复位视口)。
|
||||
@@ -8918,7 +8921,6 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 影响范围:新增 `apps/ai-game-creator-shell/src-tauri/src/asset_generation_tasks.rs`(+ `main.rs` 注册)、`src/features/resource-canvas/{resourceCanvasAssetGenerationTaskModel.ts,resourceCanvasAssetGenerationQueue.ts,ResourceCanvasAssetGenerationTasksPanelView.tsx}`;改动 `ResourceCanvasAssetGenerationPanelView.tsx` / `ResourceCanvasGenerationPanelView.tsx` / `src/view/project-development/index.tsx`;测试改动 `tests/{resourceCanvasAssetGenerationBackgroundClose.test.tsx,resourceCanvasAssetGenerationQueue.test.ts,resourceCanvasAssetGenerationTasksPanel.test.tsx}`(新增)与 `tests/appSurface/project-development.suite.ts`(把「每个入口一次 `generate_local_project_asset`」改成 `start_local_project_asset_generation` + `list_...` 轮询桩,载荷断言逐字不变)。**未动**:external v1 / OpenAPI、`packages/`、SpacetimeDB、音频入口的 pending-edit 账本语义、生成参数与 IPC 载荷字段名。
|
||||
- 关联文档:`docs/technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md`(§4 / §4a / §8)、`docs/technical/【测试用例】AGC资源工作台V3端到端验收-2026-09-11.md`(S11a / §7.3)。
|
||||
|
||||
|
||||
## 2026-09-15 非 Suno 的 VectorEngine 能力切换到 Tiantoken
|
||||
|
||||
- 决策:新增本地私密环境变量 `TIANTOKEN_BASE_URL` / `TIANTOKEN_API_KEY`(图片 timeout 可独立配置),承载原 VectorEngine 的文本和图片;`VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY` 仅保留给 Suno 背景音乐与 Suno 音效。编辑器 SFX V2 继续走 ElevenLabs。
|
||||
@@ -8943,6 +8945,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 决策:平台会话拆成身份(`userId + api origin + identity generation`)与凭据(当前 access token)。identity generation 只在登录、切号、登出或新的 GUI authority epoch 推进;同账号续期只更新凭据并推进只用于拒绝迟到写入的 revision。冻结会话校验、MCP 会话身份与 Runner attach 统一按身份判定,换号 / 退出仍然失败关闭。刷新失败只在服务端明确 401/403 且一次收敛重试后仍失败时清会话;`/api/auth/refresh` 的轮换失败不再下发清空 refresh cookie 的响应。
|
||||
- 关联规范:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md` 的“2026-09-16 平台会话身份与凭据分离”;开发期计划见 `docs/project-memory/plans/【里程碑】平台会话身份与凭据分离-2026-09-16.md` 与对应实施计划。
|
||||
- 验证:AGC `platform_session::tests`、`runner::tests`、`assets::tests` 定向通过;AGC `appSurface` 前端套件 468 项通过;网站 `src/services/apiClient.test.ts` 33 项通过;`cargo test -p api-server refresh_session` 通过。项目夹具类 Rust 用例受本机临时目录属主为 `BUILTIN\Administrators` 的环境限制,未计入本次证据。
|
||||
|
||||
## 2026-09-15 Direct 回合跨页面继续运行与活动项目面板
|
||||
|
||||
- 决策:采用后台继续运行语义。Direct 回合由进程内项目身份锁持有,页面离开不取消;重进项目通过活动回合只读快照与 Thread Manager bootstrap/consume 恢复忙碌态和进度。左上角面板复用同一快照列出正在运行的 Direct 项目并支持进入。
|
||||
@@ -9034,6 +9037,17 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 发号收口到 Jenkins Job `Genarrative-Agc-Global-Version-Issue`(`disableConcurrentBuilds()`;集群无 `lockable-resources`,以写后回读不一致即失败关闭兜底并发)。
|
||||
- 原渠道高水位逻辑降级为断言:请求号低于本渠道清单版本即失败关闭;`AGC_RELEASE_DRY_RUN` 只预览不烧号。
|
||||
|
||||
## 2026-09-20 AGC 音频生成并入图片类那份后台任务账本
|
||||
|
||||
- 背景:音频栏目的「生成背景音乐 / 生成音效」原先走同步派生通道(`derive_local_project_resource`),提交后前端一直等到生成结束(最长 35 分钟),所以它不出现在画布「生成任务」侧栏里,也没有本地排队;图片类早已改成「提交即返回 + 项目内任务账本」。
|
||||
- 决策:音频改走**同一条命令** `start_local_project_asset_generation`(新增可选入参 `idempotencyKey`,音频 kind 必带);原生在 `kind` 上分叉一次(`is_audio_asset_generation_kind` 只放行 `sound-effect` / `background-music`),音频分支落**同一份**项目内账本 `.agent/runtime/asset-generation-tasks/tasks.json`,生成由 `run_local_project_audio_generation_task` 在后台跑并写 running → completed / failed。图片类载荷与分支逐字未改。
|
||||
- 决策:音频的**任务 id 就是这次生成的 operation id**,请求身份 = 面板铸造的 `operationId` + 幂等键。重试(含失败后点占位重开)必须复用同一对,否则会同一次生成变成第二次付费请求。账本不存幂等键,所以重开项目恢复出来的音频任务只用于展示与定位,不承接重试。
|
||||
- 决策(UI 口径):音频面板与图片类一致——点「生成」**同步关闭**,面板里不存在「排队中。」「正在生成。」「提交中…」与「后台运行并关闭」这类阶段文案与在途按钮,阶段文案的唯一来源是后端账本、唯一去处是「生成任务」侧栏。只有「点击瞬间就失败」(校验 / 权限 / 提交 IPC 立即报错,即后端从未受理)才由宿主把面板连原草稿与原请求身份带回来;受理之后才失败只在侧栏收口为失败。
|
||||
- 决策(时机):项目 revision 的 CAS 由「提交前读」改为「派发时刻读」(`run_local_project_audio_generation_at`);冲突按失败收口,不静默重试,避免把生成写到用户没预期的基线上。
|
||||
- 不变口径:平台侧 `/api/editor/audios/*/generations` 路由、请求体、计费与 `/api/external/v1`、OpenAPI、共享 DTO、SpacetimeDB schema 一律未动;音频仍复用既有资源编辑派生实现,不复制生成逻辑。
|
||||
- 关联规范:`docs/prd/【AI游戏创作】项目开发工作台PRD-2026-07-20.md`(§3.10 / §7.9)、`docs/technical/【AGC】栏目画布底部工具栏入口矩阵-2026-09-13.md`、`docs/project-memory/plans/【里程碑】AGC音频生成进入后台任务账本-2026-09-20.md`。
|
||||
- 验证:9 个定向 vitest 文件 73 项、`appSurface.test.ts` 552 项(17 跳过)、`cargo test asset_generation_task` 14 项、`npm run agc:typecheck`、`npm run check:encoding`、`npm run check:doc-index`、`git diff --check` 全部通过;未跑真实付费生成。
|
||||
|
||||
## 2026-09-20 派生/修改类任务并入「生成任务」侧栏(AGC-039 / AGC-040)
|
||||
|
||||
- 背景:客户端验收现场,快速编辑提交后画布右上角「生成任务」全程是「还没有生成任务」,同一条草稿又还挂在「管理未完成编辑」里,用户据此判断「点了没生成」;随后同一次修改被重复提交,同一张源图派生了两份一模一样的「-编辑版」。
|
||||
@@ -9041,8 +9055,8 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 决策(草稿口径):提交进行中的那一笔不再列进「管理未完成编辑」;失败回落自动把它还回未完成列表,提示词与 `@` 引用不丢。
|
||||
- 决策(重复提交):同一张素材存在在途提交时,重新打开面板再提交会被拦下(可见原因),不重铸 operation 身份。**未做**「同提示词成功后再提交」的去重——那是用户显式重复的付费动作,本批只消除误触来源。
|
||||
- 理由:用户对「生成」的心智是「交出去就得能看见它在跑」,而不是必须区分两条账本;而防重复必须在**身份重铸之前**拦,等到原生账本判重时已经派生过一次。
|
||||
- 验证:新增模型用例 9 条、快速编辑两组宿主用例(提交当帧进侧栏并收口 / 在途重复提交被拦),两处新判据做过变异验证;定向 7 个文件 97 条全绿;`tests/appSurface.test.ts` 与改动前基线逐条一致(16 失败均为本分支既有)。
|
||||
- 待办:远程 CI 与真实客户端验收未跑;`resourceCanvasGenerationTasksSidebarDismiss` 等样式结构用例在本分支既有失败,与本批无关,另行跟踪。
|
||||
- 验证:新增模型用例 9 条、快速编辑两组宿主用例(提交当帧进侧栏并收口 / 在途重复提交被拦),两处新判据做过变异验证;定向 7 个文件 97 条全绿。
|
||||
- 口径更正(2026-09-21):当时记的「`appSurface` 16 条既有失败」是**从 `apps/ai-game-creator-shell` 目录跑**造成的 cwd 假红(`resolve(process.cwd(), 'apps/…')` 路径翻倍 → ENOENT),不是用例本身红。规范跑法是仓库根 `npm test`;现已用 `tests/repoPath.ts`(按 `import.meta.url` 反推仓库根)修掉 19 个文件的同类写法,从仓库根跑 `appSurface` 为 0 失败。远程 CI 与真实客户端验收仍未跑。
|
||||
|
||||
## 2026-09-21 卡片浮层改为「提交即关」:快速编辑 / 生成动画只负责交任务
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ SpacetimeDB 任务统一先读取 `.codex/skills/genarrative-spacetimedb/SKILL.m
|
||||
|
||||
## Jenkins 定时版本调度
|
||||
|
||||
定时与版本比较只保留在 `Genarrative-Scheduled-Revision-Trigger` 一处:每小时用 `git ls-remote` 解析 `SOURCE_BRANCH` 远端 HEAD,与上一次触发过的 revision 比较,变化时才把同一个 `COMMIT_HASH` 同时传给 `Genarrative-Full-Build-And-Deploy` 与 `Genarrative-Agc-Windows-Build`,保证两条管线构建同一个版本。`Genarrative-Full-Build-And-Deploy` 与 `Genarrative-Agc-Windows-Build` 不得自带 `triggers` / `cron`,也不得在管线内再做一套版本去重;`npm run check:production-ops` 会拦住这两类回退。调度状态与生效步骤见 `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
定时与版本比较只保留在 `Genarrative-Scheduled-Revision-Trigger` 一处:每小时用 `git ls-remote` 解析 `SOURCE_BRANCH` 远端 HEAD,与上一次触发过的 revision 比较,变化时才把同一个 `COMMIT_HASH` 传给 `Genarrative-Full-Build-And-Deploy`,并先经 `Genarrative-Agc-Global-Version-Issue` 发号、再把同一个总版本号透传给 `Genarrative-Agc-Windows-Build` 与 `Genarrative-Agc-MacOS-Build`,保证两个客户端的平台分区发布同一个版本。这三个下游 Job 都不得自带 `triggers` / `cron`,也不得在管线内再做一套版本去重;`npm run check:production-ops` 会拦住这两类回退。macOS 节点是日常办公机,调度触发它时置 `SKIP_IF_SUPERSEDED=true`:节点离线期间排队的旧构建在恢复后会自行让位,不发布过期版本。调度状态与生效步骤见 `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
|
||||
## Gitea CI 依赖闭合
|
||||
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# 踩坑与排障记录
|
||||
|
||||
## Tauri `--no-sign` 会连带跳过 updater 签名
|
||||
|
||||
AGC macOS 发布入口一度传入 `--no-sign`(目的是绕过没有 Apple 证书的代码签名),结果 Tauri 打印 `Warn Updater signing is skipped due to --no-sign flag.`,产物只有 `*.app.tar.gz` 而没有 `.sig`,发布入口按设计在「缺少更新包签名」处失败关闭(2026-09-20 首次 Jenkins 实跑命中)。正确做法是不传 `--no-sign`,改为剥离 `APPLE_*` 凭据让 Tauri 跳过 Apple 签名——minisign 更新包签名与 Apple 代码签名这两个开关在 Tauri 里并不独立。Apple 签名状态要按 `codesign -dv` 实测记录,不能硬编码。
|
||||
|
||||
## 复用 workspace 的构建必须显式清理本次要写的产物
|
||||
|
||||
Jenkins workspace 跨构建保留:上一轮失败留下的同名 `陶泥儿_<version>_universal.dmg` 会让 `hdiutil create` 以「文件已经存在」失败,而上一轮遗留的 `*.app.tar.gz.sig` 更危险——本轮即使没签出签名,验签门禁也会读到旧签名而误判通过。构建入口必须在构建前删除本次将写出的确切路径(更新包、签名、同版本 DMG 及其校验文件、`latest.json`、`release-notes.txt`),`hdiutil create` 同时用 `-ov`,让「归档里的产物来自本次构建」成为结构性事实而非假设。
|
||||
|
||||
## AGC macOS 单次构建耗时集中在主 crate 重复编译
|
||||
|
||||
AGC 主 crate(`genarrative_ai_game_creator_shell`)单架构 codegen 约 15–20 分钟,而每次 Tauri 构建都会重新生成前端 `dist`,`build.rs` 对 `dist` 目录的 `rerun-if-changed` 因此每次都判定变化,导致两个架构各重编一次主 crate。实测:`CARGO_BUILD_JOBS=4` 时首次 Jenkins 构建 78 分钟,提到 6 后为 41–43 分钟且成功;依赖 crate 走 sccache 与 target 缓存,首轮 0 命中属预期。剩余优化空间在「不必要地重建 dist」这一层,需单独设计(例如按内容摘要决定是否重跑前端构建),不要在发布入口里用假缓存换取速度。
|
||||
|
||||
## Godot C++ 扩展构建与对象生命周期
|
||||
|
||||
- 原生引导通过官方 `godot-cpp` 管理 Variant、String 和 Ref,不自行维护 ABI 存储。Godot 类型必须在扩展终止回调内释放,不能依赖 DLL 静态对象析构;桥节点可能已经退出,应按实例 ID 核验存活再回调。
|
||||
@@ -28,6 +40,11 @@
|
||||
- **现象**:`GameCreationAppAssetKind` 的 ts-rs `export_to` 从 `apps/ai-game-creator-shell/src/contracts/generated/` 换到 `packages/shared/src/contracts/generated/` 后,任何 `cargo build` / `cargo test` 都会重写生成文件;若新目录没进 `.prettierignore` 与 `.eslintrc.cjs` 的 `ignorePatterns`,lint-staged / prettier 会把生成物重新格式化,于是每次提交都出现「生成物被改」,`cargo test export_bindings` 也不再幂等(跑完 `git diff` 不为空)。
|
||||
- **处理(现行口径)**:生成目录一律成对登记 `.prettierignore` + eslint `ignorePatterns`;改 `export_to` 时同步改这两处,并用 `cargo test --locked -p shared-contracts --features ts-bindings export_bindings --manifest-path server-rs/Cargo.toml` 后 `git diff` 为空来验证幂等。
|
||||
- **易错点**:旧的 `apps/ai-game-creator-shell/src/contracts/generated/` 目录下的同名文件不会自动删除,换目录后必须显式删除旧文件,否则会出现「两个同名 union,改动只落在一个目录」的假绿。
|
||||
|
||||
## universal 主程序必须配套双架构原生依赖
|
||||
|
||||
AGC macOS 主程序可合并为 universal,但 Codex 原生包的 `codex-package.json`、code-mode host 和 zsh 仍有架构身份。两套包应各自保留上游布局与摘要,放入 `coding-agent/mac-native/darwin-arm64/`、`darwin-x64/`,由正在运行的主程序切片选择;不能只把主程序用 lipo 合并后复用最后一次构建的单架构资源。Tauri universal 两次 Cargo 构建共用 staging,每次都必须 stage 完整的两套资源。发布清单两个平台键同 URL/签名,只在 universal 产物上成立;Rosetta 隔离 smoke 不代替 Intel 真机验收。
|
||||
|
||||
## 生成草稿与异步展示边界必须按身份隔离
|
||||
|
||||
非模态生成浮层切换占位时按 draftId 分实例,卸载保留未提交/失败草稿,成功提交不再复活草稿;旧项目占位不存在时丢弃其保存回调。失败重试保留原请求输入和引用身份,引用失效不能静默过滤;修改已绑定输入须明确另起请求,不伪装成原请求重试。
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
## 1. 一句话
|
||||
|
||||
功能画布 = 资源栏目页;栏目页左下角渲染一条由栏目 `category` 决定的工具栏,图片类入口走本地 `start_local_project_asset_generation`(提交即返回、后台生成),音频入口复用既有无源生成链路,上传复用 `upload_local_asset`;生成 / 上传成功后一律走既有 manifest 刷新与资源定位。
|
||||
功能画布 = 资源栏目页;栏目页左下角渲染一条由栏目 `category` 决定的工具栏,图片类与音频入口都走本地 `start_local_project_asset_generation`(提交即返回、后台生成,见 2026-09-20 音频并入后台任务账本),上传复用 `upload_local_asset`;生成 / 上传成功后一律走既有 manifest 刷新与资源定位。
|
||||
|
||||
## 2. 入口矩阵(事实源)
|
||||
|
||||
@@ -40,13 +40,13 @@
|
||||
| 生成规范 → 自定义规范 | 同上 | `kind: 'icon-spec'`,固定 `1:1 · 1K` |
|
||||
| 生成图标素材 | 同上 | `kind: 'icon-spritesheet'`,默认 `1:1 · 1K`;前置:已登记 `assets/art-spec.png` |
|
||||
| 生成 UI 设计图 | 同上 | `kind: 'ui-design'`,默认 `16:9 · 1K`;前置同上 |
|
||||
| 生成背景音乐 | `derive_local_project_resource` | `editKind: 'background-music'`、`generationMode: 'create'`、`sourceMediaType: 'audio/mpeg'` |
|
||||
| 生成音效 | `derive_local_project_resource` | `editKind: 'sound-effect'`、其余同上 |
|
||||
| 生成背景音乐 | `start_local_project_asset_generation` | `kind: 'background-music'`、`idempotencyKey`;任务 id 即该次生成的 operation id |
|
||||
| 生成音效 | `start_local_project_asset_generation` | `kind: 'sound-effect'`、其余同上 |
|
||||
| 上传 | `upload_local_asset` | `{ projectPath, fileName, mediaType, bytes }` |
|
||||
|
||||
`start_local_project_asset_generation` 的完整参数是 `{ projectPath, projectId, taskId, kind, prompt, aspectRatio, imageSize, assetName, outputPath }`(Rust `src-tauri/src/asset_generation_tasks.rs`),**提交即返回**一条任务记录(`taskId / status / phaseDetail / assetId / error` 等);生成在 `tauri::async_runtime::spawn` 出来的后台任务里跑,账本落在项目内 `.agent/runtime/asset-generation-tasks/tasks.json`,进度由 `list_local_project_asset_generations` 读回。截图面板不再「等生成结束」,所以**点「生成」即同步关闭面板**(不等 IPC),面板内不出现阶段文案;只有「点击瞬间就失败」才带草稿重开(关闭 ≠ 取消)。
|
||||
`start_local_project_asset_generation` 的完整参数是 `{ projectPath, projectId, taskId, kind, prompt, aspectRatio, imageSize, assetName, outputPath, idempotencyKey }`(Rust `src-tauri/src/asset_generation_tasks.rs`);图片类入口沿用 `{ projectPath, projectId, taskId, kind, prompt, aspectRatio, imageSize, assetName, outputPath }` 逐字不变,音频入口只带 `{ projectPath, projectId, taskId, kind, prompt, assetName, idempotencyKey }`(`idempotencyKey` = 该次生成的幂等键,任务 id 即 operation id;原生命令内部仍复用既有音频无源生成链路,不新增平台路由与请求体口径),**提交即返回**一条任务记录(`taskId / status / phaseDetail / assetId / error` 等);生成在 `tauri::async_runtime::spawn` 出来的后台任务里跑,账本落在项目内 `.agent/runtime/asset-generation-tasks/tasks.json`,进度由 `list_local_project_asset_generations` 读回。截图面板不再「等生成结束」,所以**点「生成」即同步关闭面板**(不等 IPC),面板内不出现阶段文案;只有「点击瞬间就失败」才带草稿重开(关闭 ≠ 取消)。
|
||||
|
||||
入参 `kind` 一律是共享 `GameCreationAppAssetKind` 的 canonical 成员(`image` / `character` / `icon-spec` / `icon-spritesheet` / `ui-design` / `publication-material`);`spec` / `art-spritesheet` / `ui-prototype` 这类平台请求词汇只由 Rust 侧派生到 `source.generationKind`,不再出现在 IPC 载荷或 manifest kind 里。
|
||||
入参 `kind` 一律是共享 `GameCreationAppAssetKind` 的 canonical 成员(图片类 `image` / `character` / `icon-spec` / `icon-spritesheet` / `ui-design` / `publication-material`,音频 `sound-effect` / `background-music`);`spec` / `art-spritesheet` / `ui-prototype` 这类平台请求词汇只由 Rust 侧派生到 `source.generationKind`,不再出现在 IPC 载荷或 manifest kind 里。
|
||||
|
||||
## 4a. 本地排队与「生成任务」侧栏
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
|
||||
- 音频画布的「生成背景音乐 / 生成音效」由工具栏承载:`ResourceCanvasGenerationPanelView` 新增 `kinds` prop,工具栏各自只放行自己那一种,单类型入口不再渲染类型选择器,面板标题与提交文案跟该类走。
|
||||
- 既有「生成素材」浮层入口传 `kinds={['video']}`,只保留视频;视频能力不删,只是不出现在工具栏里。
|
||||
- 音频入口与图片类入口共用同一份后台任务账本(2026-09-20):提交即返回任务记录、面板同步关闭、状态与阶段文案只由后端账本提供、任务出现在「生成任务」侧栏并在重开项目后恢复。音频任务的**请求身份**(operation id 与幂等键)随任务一起走:任务 id 即 operation id,重试复用同一对身份,不会变成第二次付费生成;音频面板与图片类面板一致,只有「点击瞬间就失败」(未受理)才带原草稿与原请求身份重开。
|
||||
- 音频生成在客户端后台跑时仍复用既有音频无源生成链路(`generationMode: 'create'`、`editKind` = `sound-effect` / `background-music`、源快照媒体类型由 `editKind` 推为 `audio/mpeg`——Create 模式不读 `sourceMediaType` 入参、平台路由与请求体口径不变);音频生成没有可播报的中间进度,因此阶段文案仍是账本的「排队中。」/「正在生成。」/「生成已完成。」/失败原因四档,不新增假阶段。
|
||||
|
||||
## 8. 验证
|
||||
|
||||
@@ -93,6 +95,7 @@ cargo test -p genarrative-ai-game-creator-shell asset_generation_task
|
||||
|
||||
- 模型层:四个栏目的工具集与顺序、未命中栏目返回空、「所有资源」与 `null` 返回空、二级菜单分流、比例 / 尺寸白名单收窄、前置判据、不可用原因、`outputPath` 策略。
|
||||
- 组件层:工具栏渲染与二级菜单开合、不可用入口可点击 + 原因可关闭、上传回调。
|
||||
- 生成任务层:`resourceCanvasAssetGenerationTaskModel`(状态机 / 在途判据 / 恢复 / 耗时文案)、`resourceCanvasAssetGenerationQueue`(第二条不发提交 IPC、前一条终态后自动补发、失败与账本丢失都能收口)、`ResourceCanvasAssetGenerationTasksPanelView`(非模态、阶段文案来自后端记录、按 `assetId` 定位)、两块生成浮层在提交期间可关闭、「后台运行并关闭」文案。
|
||||
- 生成任务层:`resourceCanvasAssetGenerationTaskModel`(状态机 / 在途判据 / 恢复 / 耗时文案、音频任务载荷分流)、`resourceCanvasAssetGenerationQueue`(第二条不发提交 IPC、前一条终态后自动补发、失败与账本丢失都能收口、音频只发任务身份 + 幂等键)、`ResourceCanvasAssetGenerationTasksPanelView`(非模态、阶段文案来自后端记录、按 `assetId` 定位)、两块生成浮层点「生成」即同步关闭(面板 DOM 里没有阶段文案与「后台运行并关闭」这类在途按钮)。
|
||||
- Rust 层:`asset_generation_tasks` 的账本落项目内、排队阶段文案由后端拥有、进程重启把无人推进的记录收口为中断失败、账本上限与 task id 边界。
|
||||
- AppSurface 层:进入栏目出现工具栏 / 回总览与展开态消失、每个图片类入口的 `start_local_project_asset_generation` 载荷、前置缺失可点击说明且零请求、音频入口走 `derive_local_project_resource`、上传走 `upload_local_asset` + 配对读清单、生成面板关闭后任务仍在「生成任务」面板且第二条按本地排队补发、工具栏与右下 Dock 的几何契约。
|
||||
- 音频后台化:音频 kind 的提交返回任务记录且账本 `kind` 为音频、提示词上限与幂等键在提交时收口(未知 kind / 非法身份在提交即拒绝)、第二条提交在本地排队期间不发 IPC、未受理失败重开面板并复用同一 operation 与幂等键、受理后失败的收口与落卡复用图片类同一链路。
|
||||
- AppSurface 层:进入栏目出现工具栏 / 回总览与展开态消失、每个图片类入口的 `start_local_project_asset_generation` 载荷、前置缺失可点击说明且零请求、音频入口走同一条命令的音频载荷(`idempotencyKey` + 任务 id 即 operation id)、上传走 `upload_local_asset` + 配对读清单、生成面板关闭后任务仍在「生成任务」面板且第二条按本地排队补发、工具栏与右下 Dock 的几何契约。
|
||||
|
||||
@@ -98,11 +98,11 @@
|
||||
| 系统 | 构建目标 | 清单平台键 | 更新包 | 清单地址 |
|
||||
| --------- | ------------------------ | ---------------------------------------------- | ------------------------ | ------------------------------------ |
|
||||
| Windows | `x86_64-pc-windows-msvc` | `windows-x86_64` | NSIS `.exe` + `.exe.sig` | `<OSS base>/agc/<channel>-win/latest.json` |
|
||||
| macOS | `aarch64-apple-darwin` 或 `x86_64-apple-darwin` | 对应 `darwin-aarch64` 或 `darwin-x86_64` | `*.app.tar.gz` + `.sig` | `<OSS base>/agc/<channel>-mac/latest.json` |
|
||||
| macOS | `universal-apple-darwin` | `darwin-aarch64` + `darwin-x86_64`(同一对象) | `*.app.tar.gz` + `.sig` | `<OSS base>/agc/<channel>-mac/latest.json` |
|
||||
|
||||
- 对象布局:清单固定写成 `agc/<channel>-win|mac/latest.json`;安装包与签名写成同一分区的 `<version>/<file>` 与 `<file>.sig`。
|
||||
- macOS 当前采用单架构包:Apple Silicon 使用 `aarch64-apple-darwin`,Intel 使用 `x86_64-apple-darwin`;每次生成的清单只登记本次实际构建的架构,不把单架构原生 Codex 资源挂到另一架构。`universal-apple-darwin` 在版本读取/写入、构建和清单生成之前拒绝。
|
||||
- 渠道清单以实际运行架构为键。两种单架构构建不可轮流覆盖同一个 `latest.json` 并宣称双架构均可更新;当前不实现跨构建合并,Intel 发布需先完成其构建验证与多架构清单发布方案。
|
||||
- macOS 正式交付使用 universal 主程序:两个平台键指向同一个 `.app.tar.gz` 与签名,一份产物同时服务 Apple Silicon 与 Intel。单架构目标(`aarch64-apple-darwin` / `x86_64-apple-darwin`)只用于本机诊断,不登记正式分区清单——单架构构建不可轮流覆盖同一个 `latest.json` 并宣称双架构均可更新。
|
||||
- universal 主程序同时携带分目录的 arm64/x64 原生 Codex 组件:每个组件保持上游单架构布局与独立 SHA-256 清单,运行中的主程序切片只选择同架构目录,不得把两套原生包的元数据或辅助程序混装。
|
||||
- 构建期要求:打开 `bundle.createUpdaterArtifacts` 以生成 `.sig`;构建环境提供签名私钥与密码(私钥内容不得入库);公钥写入客户端配置。公钥在首个带更新能力的版本发布后不可更换,更换等于放弃自动更新(只能手动重装)。
|
||||
- 版本递增按渠道及系统分区独立进行:发布脚本读取该分区远端 `latest.json` 的 `version`,与本地版本取较高者递增 patch;不同分区的远端版本互不影响。
|
||||
- 版本高水位:仅 dev 的 Windows 分区在迁移窗口内取「分区清单版本」与「旧协议迁移指针版本」较大值再递增,避免已发布旧客户端版本倒退。迁移窗口结束(旧指针 404)后只读分区清单;release、自定义渠道与所有 Mac 分区均不参与旧指针比较。
|
||||
@@ -146,7 +146,7 @@
|
||||
| 条款 | 验收方式 | 证据 |
|
||||
| ---------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| 渠道与端点映射、渠道校验 | `node --test apps/ai-game-creator-shell/scripts/build-release.test.mjs` | 通过(默认渠道、错配失败关闭、未知渠道失败关闭) |
|
||||
| macOS 单架构清单与 universal 拒绝 | 定向发布脚本测试 | 单架构各用对应平台键;拒绝未闭合的 universal 发布 |
|
||||
| macOS universal 清单与双架构依赖 | 定向发布脚本与安装包验证 | 两个平台键同 URL/签名;两套资源独立校验,真机验收另记 |
|
||||
| 缺签名时失败关闭 | 同上 | 通过 |
|
||||
| 开发态不检查更新 | `vitest run apps/ai-game-creator-shell/tests/appUpdate.test.ts` | 通过(开关关闭时不请求清单) |
|
||||
| 旧自研链路整条删除 | 代码检索无残留命令、事件与白名单条目 | 通过(`download_agc_update` / 下载事件 / 清单常量均无残留) |
|
||||
@@ -168,11 +168,14 @@
|
||||
|
||||
已决策:
|
||||
|
||||
- macOS 采用单架构包,只登记实际构建架构;Intel 真机构建与跨架构清单合并未验收,不公开宣称双架构分发就绪。
|
||||
- macOS 采用 universal 包,两个平台键对应同一更新产物;主程序用 lipo 检查两种架构,Codex 资源分别做原生身份/摘要与启动验证。Rosetta 结果不代替 Intel 真机验收。
|
||||
- 旧客户端迁移桥:保留一个版本周期。渠道清单上线后,发布管线同时把旧的 `agc/latest.json`(sha256 格式)指向 `dev-win` 最新安装包,让已发布客户端自动升级到新协议;下个周期整条删除。
|
||||
- 签名密钥:由本仓库维护者生成并保管,私钥保存在仓库外(`%USERPROFILE%\.tauri\genarrative-agc-updater.key`),只有公钥进入客户端配置;Jenkins 用受保护凭据 `AgcUpdaterSigningKey` 与 `AgcUpdaterSigningKeyPassword` 注入为 Tauri 打包器读取的 `TAURI_SIGNING_PRIVATE_KEY` 与 `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`,本机可用 `TAURI_SIGNING_PRIVATE_KEY_PATH` 指向同一私钥。当前密钥不带密码;首次发布前仍可重新生成,首次发布后不可更换。
|
||||
- macOS 发布方式:对应渠道的 Mac 产物在本机 mac 上执行发布入口上传,Jenkins 暂不新增 macOS 节点;macOS 代码签名与公证凭据未确认前,相关闭环记为未验证项,不静默通过。
|
||||
- macOS 发布方式:已接入专用 macOS Jenkins 节点(label `genarrative-agc-macos`,EXCLUSIVE 单 executor),由 `Jenkinsfile.ai-game-creator-shell-macos-build` 执行 `scripts/build-macos-ci.mjs` 完成 universal 构建、双架构隔离 smoke、universal DMG、分区清单生成、更新包验签与 OSS 上传。`AGC_RELEASE_DRY_RUN` 默认为关(与 Windows 渠道对称,即直接发布),只有勾选后才退化为「只打印上传计划、不写 OSS」的演练。
|
||||
- macOS 代码签名与公证暂缺:产物为未签名 + 未公证,构建入口剥离 `APPLE_*` 凭据跳过 Apple 签名,不传 `--no-sign`(它还会跳过 updater 的 minisign 签名,产物将没有 `.sig`);构建清单实测记录 `appleSigned` 与签名类型,`latest.json` 侧固定记录 `notarized=false`,首装需用户在 Gatekeeper 中手动放行。该限制作为已知未验证项记录,不静默通过;「安装 → 重启接管新版本」的自动更新闭环仍需实机验收。
|
||||
- 更新包验签门禁:构建完成、上传 OSS 之前,用产物内烘焙的 `plugins.updater.pubkey` 复核 `<更新包>.sig`(Tauri 使用 minisign 的 `ED` 预哈希模式)。keyId 不一致或校验失败立即失败关闭,禁止上传——客户端校验失败会直接拒绝安装,且公钥发布后不可更换。
|
||||
|
||||
待办:
|
||||
|
||||
- macOS 实际发布(macOS 构建机、签名与公证、安装后重启验证、是否接入 Jenkins macOS 节点)仍需独立验证;代码中的渠道与分区支持不等于已有 Mac 安装包发布。
|
||||
- macOS 分区(`<channel>-mac`)已落地构建与发布能力:Mac Jenkins 节点、release 入口(更新包 + 签名 + 首装包 + 分区清单)、验签门禁与调度接入均已就绪,默认直接发布。
|
||||
- 剩余待办:Apple 代码签名与公证凭据(未就绪期间以未验证项记录)、macOS 安装后重启接管新版本的实机验证、Intel 真机 smoke(当前 x86_64 侧为 Rosetta)。
|
||||
|
||||
@@ -455,11 +455,11 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创
|
||||
- 调度边界:正式 DAG、manifest、Agent task/session/run 身份、队列、锁、委派、all-join、完成门、Provider lifecycle、持久 retry/handoff 与 `needs-reconciliation` 继续由现有 AGC Runtime 掌控。每个被调度节点在 `codex_cli` 模式下直接启动一次非交互 `codex exec` 充当该节点的推理 Agent;Codex 返回当前 Runtime 广告函数的结构化调用,Runtime 仍是唯一 ToolHost,不允许 CLI 自己写项目、执行命令、调用 MCP 或形成第二套 revision / verification 真相。
|
||||
- 安装包侧车:Windows x64 release 固定随 Tauri resource 打包 `@openai/codex@0.147.0` 的原生 `codex.exe`;Rust build script 从 AGC 子包锁定依赖 stage 到 resource,并写入版本与 SHA-256 清单。Windows 侧车映射只写入 `tauri.windows.conf.json`,通用 `tauri.conf.json` 不得让 Linux / macOS 构建依赖未生成的 Windows 二进制。运行时只在文件摘要和 `codex-cli` 版本同时匹配清单时优先选内置侧车;缺失、损坏或版本漂移时跳过它,按既有 npm 安装、PATH 顺序回退。安装包同时携带 Apache-2.0 第三方声明;API Key、`auth.json`、Cookie、Token、用户 `CODEX_HOME`、用户配置和项目数据绝不打包。
|
||||
- Windows x64 release 安装包只生成 NSIS,不生成 MSI:`tauri.windows.conf.json` 的 `bundle.targets` 固定为 `["nsis"]`,通用配置继续保留其它平台的默认打包目标。安装后的产品名、开始菜单 / 桌面快捷方式和 EXE 产品描述统一由 `tauri.conf.json` 的 `productName: "陶泥儿"` 生成;应用 identifier 与内部可执行文件名保持稳定。内置 Codex 资源安装到顶层 `coding-agent/win-x64/`,运行时从同一路径查找 `bin/codex.exe` 与 `manifest.json`;仓库 staging 仍使用 `resources/codex/win-x64/`,包内子目录、组件名、版本和完整性校验保持原合同。
|
||||
- macOS 单架构安装包同样必须携带锁定版本的原生 Codex、`codex-code-mode-host`、`rg`、上游 zsh、`codex-package.json` 和第三方声明,保留上游相对布局;构建时按 Cargo 目标选择 npm 原生依赖,缺文件、版本或目标不匹配立即失败,不借用开发机 PATH 里的 Codex。资源只在 `tauri.macos.conf.json` 映射到 `Contents/Resources/coding-agent/mac-native/`。构建与运行共享平台文件白名单,运行时由当前 `.app/Contents/MacOS` 定位相邻 `Resources`,完整性与版本验证通过后优先使用内置组件;失败沿既有外部安装回退,不能运行未校验的内置文件。单架构资源不能冒充 universal 包。
|
||||
- macOS 安装包必须携带锁定版本的原生 Codex、`codex-code-mode-host`、`rg`、上游 zsh、`codex-package.json` 和第三方声明,保留上游相对布局;构建时按 Cargo 目标选择 npm 原生依赖,缺文件、版本或目标不匹配立即失败,不借用开发机 PATH 里的 Codex。资源只在 `tauri.macos.conf.json` 映射到 `Contents/Resources/coding-agent/mac-native/darwin-arm64/` 与 `darwin-x64/`。构建与运行共享平台文件白名单,运行时由当前 `.app/Contents/MacOS` 定位相邻 `Resources`,完整性与版本验证通过后优先使用内置组件;失败沿既有外部安装回退,不能运行未校验的内置文件。universal 主程序同时携带两套独立原生资源,运行切片按 Cargo 目标只选择对应目录;macOS 构建必须预备两套锁定原生依赖,不读取全局 Codex。
|
||||
- 内置插件的清单、运行入口与面板同时在 Windows/macOS 随包分发,继续由既有 PluginHost 的应用资源目录扫描入口发现;不携带开发依赖、缓存、测试或私有配置。插件文件随包不等于原生适配器跨平台:Cocos 进程桥接仍受现有 Windows 实现和 feature 门禁约束,macOS 原生桥接另行设计与验收,不复制 Windows DLL 冒充支持。系统 Node、用户 Cocos Creator、账号登录、网络和生成工程的 npm 工具链仍是现有外部前提,不在此次 Codex 侧车补齐中隐式变更。
|
||||
- macOS 安装包验收必须包括:脱离仓库位置的 `.app` 资源与架构检查、受限 PATH/隔离 HOME 下内置 Codex 启动和 app-server 握手、必需文件缺失/篡改/平台错误的拒绝测试,以及 DMG 完整性检查。真实登录、Provider 对话、GUI 和 Cocos 操作必须独立列出证据,不能用压缩包生成或 `--version` 成功替代。未配置正式签名、公证的本地测试包不得作为公开发行包。
|
||||
- macOS 安装包的系统下限取主程序和全部原生组件中的最高要求;锁定 Codex 0.147.0 原生依赖所携带的 zsh 要求 macOS 15.0,因此 `bundle.macOS.minimumSystemVersion` 明确为 `15.0`。更新原生依赖时重新检查 Mach-O 的系统下限,不能只按 AGC 主程序宣称兼容版本。
|
||||
- 发布链路的目标解析和单架构清单以《AGC客户端更新检查与下载》为准:CLI 目标优先,版本、构建、端点、bundle 与更新清单共用单一发布上下文。插件能力以《AGC通用插件宿主与编辑器适配》为准:无已注册 Cocos 原生适配器时隐藏且拒绝启动,前端自动启动只消费后端可用性投影。
|
||||
- 发布链路的目标解析和 universal 清单以《AGC客户端更新检查与下载》为准:CLI 目标优先,版本、构建、端点、bundle 与更新清单共用单一发布上下文。插件能力以《AGC通用插件宿主与编辑器适配》为准:无已注册 Cocos 原生适配器时隐藏且拒绝启动,前端自动启动只消费后端可用性投影。
|
||||
- CLI 安全边界:CLI 固定使用 argv 启动,禁止 shell 拼接;工作目录使用本次请求专用的空临时目录,不把游戏项目绝对路径写入 prompt、stdout、stderr 或持久记录。调用固定使用 ephemeral、忽略用户配置和 exec rules、read-only sandbox、never approval,并关闭 Codex shell tool;只继承 CLI 运行和认证所需的最小环境,显式移除宿主 `CODEX_API_KEY`。用户级 Codex 登录态继续由本机 Codex 自己读取,API Key、auth 文件、Cookie、Token、`CODEX_HOME` 私有内容不得复制到项目配置、Runtime sidecar、Agent DB、conversation 或日志;stdout / stderr 无换行时也受硬上限约束,stderr 诊断只记录固定分类、字节数和 SHA-256。
|
||||
- 协议边界:Runtime 把既有 `LlmRunRequest` 的消息和当前函数目录编码为有界 prompt,并从同一函数 JSON Schema 生成 Codex structured-output schema。CLI 输出转换为现有 `LlmRunResponse / LlmToolCall` 后,继续经过 native tool / MCP 参数校验、动作上限、权限、pending、receipt、验证与格式修复链;最终回复仍走唯一提交路径,不新增平行响应协议。
|
||||
- 取消与恢复:Codex 子进程绑定当前 Provider request lifecycle,取消、暂停、Runner draining 或 GUI owner 丢失时终止并回收当前进程;started 后没有可信终态仍沿现有 Provider reconciliation 处理。`agentMode`、CLI 可执行身份和影响输出的 Codex 参数进入 `providerConfigFingerprint`,模式切换不得消费另一模式遗留的 retry/handoff。
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
| **S15** 删除 | 工具条 / 标签面板「删除」→ 确认弹窗 | 三分支:① 无引用→直接删;② 被引用未勾选→只删素材、版本保留**悬空绑定**、界面不合成幽灵资源卡;③ 勾选→素材与该批版本在**同一次 manifest 写入**内一起删 | L413(版本只追加的唯一例外)、L532–533;#309 C5 | 弹窗 `ariaLabel="确认删除资源"`;被引用时出现 `被 N 个游戏版本使用` + 版本列表 + checkbox `把相关游戏版本一并删除`;无引用时该 body 整块不渲染 | **只摘登记、不删磁盘文件**;读引用命令精确名是 `read_local_project_asset_references` |
|
||||
| **S15a** 替换素材(含点选替换) | 选中被**当前版本**绑定的素材 → 工具条「替换素材」→ 候选弹窗(弹窗内可筛可选);再点 footer「点选替换」→ 弹窗关闭、进入画布点选态 → 在画布上直接点目标素材 | 弹窗确认与点选是**同一条**写入链路(`replace_local_project_version_resource`,载荷逐字一致):改该版本绑定、不建新版本;点选态下合法目标直接提交并自动退出点选态,非法目标零写入、**留在**点选态并在提示条上说明原因 | PRD §5.3 / §7.8 第 8 条;#309「直接替换」口径 | 点选态判据:候选弹窗 `role="dialog"` 已卸载;画布出现 `.game-resource-canvas-pick-hint`,文案含「在画布上点选要替换成的素材」与「点击空白处不会退出」,并有「取消」按钮;非法目标后提示条仍在且出现 `role="alert"`(「替换素材不兼容:分类不同」/「替换素材与源素材相同」/「替换素材未登记或已被删除」);点选期间卡片 `aria-pressed` 不变(单击只用于点选)、源素材选中与工具条不因点空白或点非法目标而丢;Esc 退出点选(画布全局 Esc 的清选中不随之触发);点选态下滚轮平移与缩放照常可用 | 点选只能点**当前画布上可见**的卡:目标在别的栏目时先切栏目(点选会话跨栏目存活,不因「收起资源」或切栏目结束);空白点击不退出、也不清画布选中 |
|
||||
|
||||
| **S11a** 栏目画布底部工具栏 | 进「UI 交互 / 角色与对象 / 场景与环境 / 音频」任一栏目 → 点左下角工具栏里的入口生成 → 「收起资源」回总览看工具栏消失 | 工具栏只在矩阵四个栏目(功能画布)渲染;图片类入口走 `start_local_project_asset_generation`(提交即返回、生成在后台跑),音频入口复用既有无源生成链路,上传复用 `upload_local_asset`;生成 / 上传成功后走既有 manifest 刷新与资源定位 | PRD §3.10、§7.9 | DOM 判据 `[data-resource-bottom-toolbar="<category>"]`(资源总览、「所有资源」展开态、文档、待归类、项目版本都**没有**这个节点);工具栏是 `.game-resource-book-manager` 的直接子节点(`closest('.game-resource-book-scene')` 为 `null`);每个入口一次 `start_local_project_asset_generation`,载荷逐字为 `{ projectPath, projectId, taskId, kind, prompt, aspectRatio, imageSize, assetName, outputPath }`(`kind` 映射见 PRD §7.9 第 3 条;`taskId` 是前端每次提交新铸的本地任务 id);该命令提交即返回,之后有 `list_local_project_asset_generations` 轮询与 `get_local_game_project_revision` + `get_local_game_manifest` 的配对读;提交期间点 × / 遮罩 / Esc /「后台运行并关闭」任一都能关面板且请求继续(画布立即恢复可交互),关闭后任务仍出现在「生成任务」面板(入口按钮 `aria-label="生成任务"`,非模态浮层、无 `aria-modal`)并显示后端 `phaseDetail`;第一条未终态时提交第二条 → 第二条显示「排队中。」且生成提交 IPC 次数仍为 1,第一条终态后自动补发(次数变 2);缺 `assets/art-spec.png` 时「生成图标素材 / 生成 UI 设计图」仍可点击(`aria-disabled="true"` 但**不是**原生 disabled)并给出含该路径的 `role="alert"` 原因、零生成请求;音频入口面板标题即「生成背景音乐」/「生成音效」且没有类型选择器 | ① 本地通道没有 `model` / `specType` / `replaceExisting` 入参:面板不渲染模型选择器,角色规范与自定义规范共用 `spec` 通道(靠 `assetName` 与提示词区分),「图标规范」在项目已有权威规范图时不再指向 `assets/art-spec.png`(否则会被 Rust 的防覆盖校验硬拒);② 本轮不做生成视频 / 宣发素材 / 生成游戏场景 / 选择工具 / 抓手工具;③ 既有「生成素材」浮层入口只保留生成视频,音频入口只在音频栏目工具栏出现 |
|
||||
| **S11a** 栏目画布底部工具栏 | 进「UI 交互 / 角色与对象 / 场景与环境 / 音频」任一栏目 → 点左下角工具栏里的入口生成 → 「收起资源」回总览看工具栏消失 | 工具栏只在矩阵四个栏目(功能画布)渲染;图片类入口走 `start_local_project_asset_generation`(提交即返回、生成在后台跑),音频入口走同一条命令的音频载荷,上传复用 `upload_local_asset`;生成 / 上传成功后走既有 manifest 刷新与资源定位 | PRD §3.10、§7.9 | DOM 判据 `[data-resource-bottom-toolbar="<category>"]`(资源总览、「所有资源」展开态、文档、待归类、项目版本都**没有**这个节点);工具栏是 `.game-resource-book-manager` 的直接子节点(`closest('.game-resource-book-scene')` 为 `null`);每个入口一次 `start_local_project_asset_generation`:图片类载荷逐字为 `{ projectPath, projectId, taskId, kind, prompt, aspectRatio, imageSize, assetName, outputPath }`(`kind` 映射见 PRD §7.9 第 3 条;`taskId` 是前端每次提交新铸的本地任务 id),音频类载荷为 `{ projectPath, projectId, taskId, kind, prompt, assetName, idempotencyKey }`(`taskId` 即该次生成的 operation id,不发图片类那套比例 / 尺寸 / 参考 / 落点参数);该命令提交即返回,之后有 `list_local_project_asset_generations` 轮询与 `get_local_game_project_revision` + `get_local_game_manifest` 的配对读;点「生成」即把这次输入交给后台账本并**同步关闭**面板(不等 IPC、不等排队、不等生成,画布立即恢复可交互;面板 DOM 里没有阶段文案与「后台运行并关闭」这类在途按钮),关闭不等于取消,关闭后任务仍出现在「生成任务」面板(入口按钮 `aria-label="生成任务"`,非模态浮层、无 `aria-modal`)并显示后端 `phaseDetail`;第一条未终态时提交第二条 → 第二条显示「排队中。」且生成提交 IPC 次数仍为 1,第一条终态后自动补发(次数变 2);缺 `assets/art-spec.png` 时「生成图标素材 / 生成 UI 设计图」仍可点击(`aria-disabled="true"` 但**不是**原生 disabled)并给出含该路径的 `role="alert"` 原因、零生成请求;音频入口面板标题即「生成背景音乐」/「生成音效」且没有类型选择器 | ① 本地通道没有 `model` / `specType` / `replaceExisting` 入参:面板不渲染模型选择器,角色规范与自定义规范共用 `spec` 通道(靠 `assetName` 与提示词区分),「图标规范」在项目已有权威规范图时不再指向 `assets/art-spec.png`(否则会被 Rust 的防覆盖校验硬拒);② 本轮不做生成视频 / 宣发素材 / 生成游戏场景 / 选择工具 / 抓手工具;③ 既有「生成素材」浮层入口只保留生成视频,音频入口只在音频栏目工具栏出现 |
|
||||
|
||||
### D 阶段 · 版本与运行
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user