收口 #599 评审:文档补面板补读的门控条件、PR 正文用例数字与真实计数对齐
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m47s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m14s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m17s
Project CI / Frontend tests (pull_request) Successful in 3m16s
Project CI / Backend tests (pull_request) Successful in 7m37s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m7s
Project CI / Repository checks (pull_request) Successful in 6m46s
Project CI / Native shell tests (pull_request) Successful in 9m3s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m47s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m14s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m17s
Project CI / Frontend tests (pull_request) Successful in 3m16s
Project CI / Backend tests (pull_request) Successful in 7m37s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m7s
Project CI / Repository checks (pull_request) Successful in 6m46s
Project CI / Native shell tests (pull_request) Successful in 9m3s
- 文档口径对齐:pitfalls 的「前端读快照的时序」边界与 decision-log 同段补上门控条件——面板打开时**仅当列表里确实存在在途命名行时才补读**(不给没有命名任务的项目多打一次账本 IPC,避免改变「轮询计数」这类外部可观测行为);不再写成「无条件补读」。 - PR #606 正文数字统一为实测值:测试节 asset_generation_task 22 例 → 27 例、conditional_project_rename_tests 6 例 → 7 例(并补上新用例名),验证节全量 1934 → 1964 passed / 17 skipped,合并段补上 76cd1f057(merge f47a8f305)。 - 用例计数命令与输出:cargo test … asset_generation_task → running 27 tests / 27 passed;cargo test … conditional_project_rename_tests → running 7 tests / 7 passed;静态计数(按测试模块内 #[test] 计数)同为 27 / 7;前端 npx vitest run homeProjectNamingAsync projectNamingGenerationTaskRow → 12 + 3 passed,appSurface.test.ts → 209 tests(200 passed / 9 skipped)。 - 本轮同时把分支合并到最新 origin/master tip 76cd1f057(merge f47a8f305,含 #608 Direct 交付合同重构与临时文档清理)——与本文档/hunk 无冲突,合并后 git merge-base --is-ancestor origin/master HEAD 返回 0。 - 未改动项(评审判定非阻塞):useHomeProjectCreation.ts 的改名 revision 回写沿用既有改名路径同形写法,本轮无改动。 - 门禁:cargo 定向 27 + 7、cargo fmt --check、agc:typecheck、lint:eslint(0 problems)、check:encoding、check:spacetime-schema(91 表)、git diff --check 全过;前端命名/面板 15 passed、appSurface 200 passed / 9 skipped。
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
- 背景:首页「开启创作」原先串行执行「Web 预检 → `await suggest_automatic_project_name` → `create_automatic_local_game_project`」。项目名称不是创建工作区、导入附件或发起首轮创作的前置条件,命名请求(`AUTOMATIC_PROJECT_NAME_TIMEOUT_MS = 15s`,正常请求同样占时)却把用户按在「正在创建工作区」上。
|
||||
- 决策(建项与命名解耦):建项固定传 `name: null`,由宿主既有兜底名(`GameAgent 项目 <8 位短 id>` / `策划项目 <8 位短 id>`)落盘并立即进入项目;命名请求在建项前并行打出、结果交给后台任务。后台拿到合法名称后调用新增的 `rename_local_game_project_if_unchanged(projectPath, expectedProjectId, expectedName, name)`:只有「项目 ID 相同」且「当前名称仍是本次创建的兜底名」才改名,返回 `renamed: true/false`(跳过时不写盘、不是错误)。用户已手动改名、项目 ID 不符、名称与现状相同一律跳过;空 `expectedProjectId` / `expectedName`、空名 / 控制字符 / 超长一律失败关闭。
|
||||
- 决策(纳入「生成任务」体系):自动命名做成**项目工作台那条既有「生成任务」列表里的一条后台任务**,而不只是页面里的一个 promise。账本记录加 `taskType`(`asset-generation` / `project-naming`,缺省 `asset-generation`)、`kind` 变可选,schema 升 `agc-asset-generation-task.v2`(读取同时接受 v1/v2,v1 记录按素材任务读回);新增 `enqueue_local_project_naming_task`(排队中)/ `update_local_project_naming_task`(命名中 → 已完成/失败),展示名固定「AI 项目命名」,与素材生成共用同一份账本、同一个变更事件与同一个侧栏。状态流转:排队中 → 命名中 → 已完成(已应用 AI 名称 / 建议名与现状一致 / 用户已手动改名而跳过)或失败(无可用名称 / 自动改名失败,均保留兜底名)。命名任务由命名链路推进、**不进 live 集合就会被中断收口误判**,所以 enqueue 写账本前登记 live、update 终态写盘后摘除(中断残留仍按命名口径收口为失败)。前端按 `taskType` 把命名记录从素材任务分支里剔除,命名行不渲染缩略图/提示词/派发与定位动作,结论只在终态显示。
|
||||
- 边界:改名是簿记写入,与既有 `rename_local_game_project` 同口径**不推进项目 revision**(推 revision 会让运行时验证凭证无故漂移);返回的 `revision` 是当时盘上的值。后台改名结果写「当前项目上下文」与「最近项目行重检」必须等建项主体收尾(`entrySettled`):AI 比进项目更快时直接写上下文会被随后的 `enterProjectDevelopment` 用兜底名覆盖,最近项目行也要等进项目登记过才会被重检;写入前再过壳的生命周期守卫(`mounted` + 代次),关窗/卸载后只保留已落盘的改名,不写 UI 投影。账本是**展示旁路**:`enqueue` / `update` 失败只写诊断日志,绝不影响建项、命名与首轮创作;「做方案」与手动选目录建项不发起自动命名。本次未改共享契约(`packages/shared/**`)、server-rs 与任何 SpacetimeDB schema/HTTP 路由。条件改名的 `expectedProjectId` / `expectedName` 为空时按仓库同类入口口径失败关闭;`update_local_project_naming_task` 与 enqueue 共用 `project.rename` 权限位、校验记录归属,且终态只接受同状态幂等重放。**兼容性写成显式边界:兼容是单向的**——新构建读 v1 账本 OK;旧构建读到含命名记录(`kind: null`)的账本会整份解析失败(面板报读失败、同批在途素材任务被按中断收口)。前端刷新必须先订阅事件再读快照,并在面板打开时补读一次兜底。
|
||||
- 边界:改名是簿记写入,与既有 `rename_local_game_project` 同口径**不推进项目 revision**(推 revision 会让运行时验证凭证无故漂移);返回的 `revision` 是当时盘上的值。后台改名结果写「当前项目上下文」与「最近项目行重检」必须等建项主体收尾(`entrySettled`):AI 比进项目更快时直接写上下文会被随后的 `enterProjectDevelopment` 用兜底名覆盖,最近项目行也要等进项目登记过才会被重检;写入前再过壳的生命周期守卫(`mounted` + 代次),关窗/卸载后只保留已落盘的改名,不写 UI 投影。账本是**展示旁路**:`enqueue` / `update` 失败只写诊断日志,绝不影响建项、命名与首轮创作;「做方案」与手动选目录建项不发起自动命名。本次未改共享契约(`packages/shared/**`)、server-rs 与任何 SpacetimeDB schema/HTTP 路由。条件改名的 `expectedProjectId` / `expectedName` 为空时按仓库同类入口口径失败关闭;`update_local_project_naming_task` 与 enqueue 共用 `project.rename` 权限位、校验记录归属,且终态只接受同状态幂等重放。**兼容性写成显式边界:兼容是单向的**——新构建读 v1 账本 OK;旧构建读到含命名记录(`kind: null`)的账本会整份解析失败(面板报读失败、同批在途素材任务被按中断收口)。前端刷新必须先订阅事件再读快照,并在面板打开时补读一次兜底(**门控**:仅当列表里确实存在在途命名行时才补读,避免给没有命名任务的项目多打一次账本 IPC)。
|
||||
- 影响范围:`apps/ai-game-creator-shell/src-tauri/src/{commands.rs,desktop.rs,asset_generation_tasks.rs,asset_generation_tasks/runtime.rs}`、`apps/ai-game-creator-shell/src/{app/types.ts,features/app-shell/{useHomeProjectCreation.ts,WorkspaceLauncher.tsx},features/resource-canvas/{resourceCanvasAssetGenerationTaskModel.ts,ResourceCanvasAssetGenerationTasksPanelView.tsx},view/project-development/index.tsx}`、`apps/ai-game-creator-shell/tests/{homeProjectNamingAsync.test.tsx,projectNamingGenerationTaskRow.test.tsx,appSurface/home.suite.ts}`。
|
||||
- 验证:`npx vitest run apps/ai-game-creator-shell/tests/homeProjectNamingAsync.test.tsx`(12 passed,含「命名请求永不返回仍进工作区」「AI 结果先于进项目落定仍不被兜底名覆盖」「手动改名不被覆盖且任务按已完成+已跳过收口」「非法/空响应 → 任务 failed 且保留兜底名」「做方案不发起命名」「切到别的工作区不被劫持」「卸载/pagehide 后不写上下文」,并断言入队→命名中→终态的账本推进序列);`projectNamingGenerationTaskRow.test.tsx`(3 passed:固定展示名/不渲染缩略图提示词定位、终态才显示结论、失败徽章与原因 + 在途计数);AGC 全量 `npm run test -- apps/ai-game-creator-shell/tests`(1964 passed / 17 skipped);`cargo test --features=cocos-editor-execute,unity-editor-execute,godot-editor-execute asset_generation_task`(27 passed,含 `naming_task_stays_in_flight_across_ledger_reads_until_terminal`、`naming_task_update_requires_the_project_rename_permission`、`naming_task_update_rejects_a_record_from_another_project`、`naming_task_terminal_state_rejects_a_different_status_but_allows_the_same_one`、`ledger_with_an_unsupported_schema_version_fails_closed`、`ledger_without_a_schema_version_is_accepted_as_v1`)与 `conditional_project_rename_tests`(7 passed,含超长名失败关闭);`npm run agc:typecheck`(含 `check:tests:types`)、`cargo fmt --check`、`npm run check:encoding`、`git diff --check`。
|
||||
## 2026-10-03 AGC 发布版本标签改为由工程内部版本派生,取代「用户可编辑标签」口径
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
- **处理(现行口径)**:账本记录加 `taskType`(`asset-generation` / `project-naming`,缺省 `asset-generation`)、`kind` 变可选;schema 升 `agc-asset-generation-task.v2`,读取同时接受 v1 与 v2(v1 记录按素材任务读回)。`enqueue_local_project_naming_task` 写账本前登记 live(写盘失败只回滚本轮插入的那条),`update_local_project_naming_task` 在非终态时幂等登记、终态写盘成功后摘除。命名没有素材可交叉核对,中断收口一律 failed 且文案与素材口径区分(不含「目标素材」)。
|
||||
- **边界**:命名任务的结论文案(已应用 / 用户已改名跳过 / 失败保留兜底名)由命名链路给出;账本只是展示旁路——`enqueue` / `update` 失败只写诊断日志,绝不影响建项、命名与首轮创作。前端按 `taskType` 把命名记录从素材任务列表里剔除(素材分支会按 `kind` 解析),命名行固定展示名「AI 项目命名」,只在终态显示结论。
|
||||
- **边界(兼容是单向的,必须写清)**:**新构建读旧账本 OK,旧构建读新账本会失败**——命名记录写 `"kind": null`,而旧构建(`AssetGenerationTaskRecord.kind` 必填且 `read_ledger` 不校验 schema)解析含命名记录的账本会**整份失败** → 面板报「生成任务列表读取失败」,且同一次读里在途的素材任务会被按「上次运行中断」收口为失败。触发条件只有「同一项目先被新构建写过命名任务、之后又被旧构建打开(降级或新旧混跑)」。潜在的低成本正向兼容方向(**未实施,需先确认**):命名记录也写一个合法 `kind`(例如 `unknown`)只靠 `taskType` 区分——旧构建会把它渲染成一张名为「AI 项目命名」的素材任务卡,但账本能解析、不会误伤在途素材任务。
|
||||
- **边界(前端读快照的时序)**:命名行的推进发生在本组件之外,刷新只能靠「变更事件 + 一次受控快照读取」。**必须先订阅再读**(与素材队列「先订阅后派发」同口径):先读后订阅时,落在这一次 IPC 往返里的终态事件没有消费者、直接丢掉,行会永久停在「命名中」;订阅失败时退化为「进项目读一次 + 面板打开时补读」。补读兜底是必须的(订阅不可用、窗口刚恢复、用户想确认进度)。
|
||||
- **边界(前端读快照的时序)**:命名行的推进发生在本组件之外,刷新只能靠「变更事件 + 一次受控快照读取」。**必须先订阅再读**(与素材队列「先订阅后派发」同口径):先读后订阅时,落在这一次 IPC 往返里的终态事件没有消费者、直接丢掉,行会永久停在「命名中」;订阅失败时退化为「进项目读一次 + 面板打开时补读」。补读兜底必须有,但**有门控**:仅当列表里确实存在一条在途命名行时才读——没有命名任务的项目不该因为打开面板就多打一次账本 IPC,那会改变「轮询计数」这类外部可观测行为(既有生成任务用例正是按轮询次数推进 mock 的)。
|
||||
- **边界(update 的门禁与终态语义)**:`update_local_project_naming_task` 与 `enqueue` 共用 `project.rename` 权限位,并校验记录 `project_id` 与项目一致;记录一旦终态只接受**同状态幂等重放**,改写成另一种状态(含 `completed → failed`)一律 Err 且不写盘——否则一次迟到的排队/失败事件会覆盖已落定的命名结论。
|
||||
- **判据/取证**:Rust `cargo test … asset_generation_task` 27 条(含 `naming_task_stays_in_flight_across_ledger_reads_until_terminal`、`naming_task_update_requires_the_project_rename_permission`、`naming_task_update_rejects_a_record_from_another_project`、`naming_task_terminal_state_rejects_a_different_status_but_allows_the_same_one`、`ledger_with_an_unsupported_schema_version_fails_closed`、`ledger_without_a_schema_version_is_accepted_as_v1`)与 `conditional_project_rename_tests` 7 条(含超长名失败关闭);前端 `homeProjectNamingAsync.test.tsx`(入队→running→终态的推进序列)、`projectNamingGenerationTaskRow.test.tsx`(行渲染)、appSurface 的「syncs the workbench title and recent project list with the AI name after creation」「recovers the naming row when the terminal event lands before the subscription is ready」「re-reads the naming ledger when the generation tasks panel opens」(后两条已做「改前红」验证:退回「先读后订阅 / 面板打开不补读」两条即红)。
|
||||
- **关联**:`apps/ai-game-creator-shell/src-tauri/src/asset_generation_tasks.rs`、`apps/ai-game-creator-shell/src/features/app-shell/useHomeProjectCreation.ts`、`apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasAssetGenerationTaskModel.ts`、`apps/ai-game-creator-shell/src/view/project-development/index.tsx`。
|
||||
|
||||
Reference in New Issue
Block a user