作品管理与Phaser4客户端发布 #565

Merged
suzmii merged 53 commits from feat/game-works-management into master 2026-10-04 20:03:38 +08:00
Member

这个 PR 做了什么

本章节为本轮整理,目的是让作者日后不必回忆。事实均可在 feat/game-works-management 上复核。

一、定位:作品管理与 Phaser4 客户端发布的第二轮

  • 底座已由 master 提供,本分支不重复造游戏分发的轮子:
    • 328ac3184(09-20)游戏分发实现;
    • cc958f367(09-23)后台游戏管理;
    • b60aea4e7(10-01)游戏评价 #561。
  • 本分支首笔提交在 09-30,在既有底座之上继续开发。
  • 关联 Issue:#470。

二、净差规模

现算口径(git diff origin/master...HEAD --shortstat / --name-status):

口径 数值
变更文件 131
插入 / 删除 +12323 / -1470
新增文件 28
删除 master 文件 0
分支提交数 50(含 merge)

口径随 head 更新:现 head e593236f9,对比基准 origin/master a2f250364。历史锚点:2f6df57ce 时为 127 files / +12028 / -1461 / 新增 27 / 删除 0;aa4d17895 时为 130 files / +12235 / -1470 / 新增 27;本轮再追加 2e7409274(5 files / +27 / -22)与 e593236f9(3 files / +91 / -8),即上表现值。

三、不可替代的能力(master 上没有)

  1. AGC Phaser4 真实打包 / 分片上传 / 原生幂等账本 / 阶段进度:受控构建 → dist 归一化打包 → 8 MiB 分片上传 → 真实进度 → 幂等恢复 → 送审;核心在 apps/ai-game-creator-shell/src-tauri/ 与 server-rs/crates/api-server/src/modules/game_distribution.rs。
  2. versionNumber 语义统一:支持版本回退与重复标签提交,冲突由 CAS 拒绝并返回 VERSION_NUMBER_CONFLICT(GAME_DISTRIBUTION_VERSION_NUMBER_CONFLICT)。
  3. owner 私有作品详情 / 资料编辑 / 版本历史 / 软删除:GET / PATCH / DELETE /api/game-distribution/my-games/{game_id}。
  4. 后台作品筛选 / 游标分页 / 软删除治理:GET /admin/api/game-distribution/games。
  5. 后台待审版本试玩预览:POST /admin/api/game-distribution/versions/{version_id}/preview-session + GET /api/game-distribution/admin-previews/{preview_token}[/{*asset_path}]。
  6. 发行资源归一化 + storage bootstrap 注入:新增 server-rs/crates/api-server/src/modules/game_distribution_release_storage_bootstrap.js。
  7. packages/shared 新增 GameDetailDisplay / GameDetailShowcase 组件:作者侧与后台复用同一套作品详情展示(packages/shared/src/components/GameDetailDisplay/)。

四、路由变化

  • api-server/src/app.rs 未变(0 行改动),新路由全部在模块内挂载。
  • 路由数:master 37 → 本分支 42(净增 5 条,集中在 my-games/{game_id} 与 admin-previews 家族)。

五、SpacetimeDB 变更

  • 无新表。
  • 追加字段:GameDistributionGame.deleted_at、CreateVersionInput.version_number、GameSnapshot.local_project_id、AdminGameSnapshot.deleted_at_micros、AdminGameListResult.next_cursor、ReviewListInput.{keyword, owner_user_id, status, cursor}。
  • 新增 2 个 procedure:update_game_distribution_game_metadata_and_return、delete_game_distribution_game_and_return。

六、本轮质量修复

  1. 「AI 改完一版却没出现新版本卡」根因:新增的内部版本只落在清单里,不经过工具桥,因此没有任何事件;登记成功后必须显式宣告清单失效,否则渲染层的资源投影(「项目版本」卡、发布面板版本标签)在本回合结束后不会重读清单。修复见 apps/ai-game-creator-shell/src-tauri/src/project/manifest.rs:1025(append_agent_game_iteration_version_at 改为返回是否登记成功)与 apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime/mod.rs:4181-4193(登记后 emit_game_creator_manifest_invalidated)。
  2. 版本卡顺序修复:按内部版本序数排序,修正初始版本被排到最后;resourceProjectionModel.ts 的 orderIndex 与 compareResourceOrder。
  3. 发布面板「项目版本」:改为由 AGC 内部版本只读派生,拆除 projectVersion 写链路。
  4. AGC 发布抽屉隐藏滚动条:apps/ai-game-creator-shell/src/styles.css。
  5. 作品详情页非公开态:不再请求评价接口,封面显示「审核中」。
  6. 后台审核页游戏列:显示游戏名 + 作者,不再只显示 gameId(用例 AdminGameDistributionReviewPage.test.tsx:256)。
  7. 后台游戏列表:下架入口收敛为独立面板,状态胶囊不换行。
  8. 与 master 的重复实现已去重:master a1b80ffde + 33552d2ed 已含游戏评价页排布实现,本分支对应改动删除,以 master 为准(提交 aa4d17895,+1/-18)。

七、验证

  • CI run 3329(head 2f6df57ce)= 8/8 全绿;run 3335(head aa4d17895)= 8/8 全绿。
  • run 3342(head e593236f9,本 PR 现 head)截至写入时状态为 queued,结论待 CI(已注册,尚未产出结果)。
  • 关键用例:AdminGameDistributionReviewPage.test.tsx 7 passed、AdminGameReviewsPage.test.tsx 8 passed;前端整体 246 passed / 0 failed(run 3335 口径)。

八、同日追加修复(发布版本文案 / 作者名)

head aa4d17895 → e593236f9 追加两笔:2e7409274 发布版本文案去诱导(5 files / +27 / -22)、e593236f9 公开作品详情页作者名(3 files / +91 / -8)。

8.1 发布版本文案:为什么要去掉「发布标签 v{N}」

事实依据(为何原文案会误导):

  • 发布提交的版本标签只有一个来源:resolveGameCreationAppProjectVersion(manifest) 返回 versions.length(packages/shared/src/contracts/gameCreationApp.ts:993-999);面板把它作为只读派生值取用(apps/ai-game-creator-shell/src/components/game-distribution/GameDistributionPublishPanel.tsx:282),提交时原样写入 versionNumber(同文件 :775)。即:发布固定取最新内部版本,与用户在画布上选中哪张卡无关。
  • 资源画布的「当前版本」只作用于素材卡绑定与运行播放:WorkspaceLauncher.tsx:199 的 activeVersionId → resourceCanvasVersionBindingModel.ts:51-82,其中 isResourceUsedByCurrentVersion 要求 resource.manifestAssetId !== null;而版本卡在投影里 manifestAssetId 恒为 null(resourceProjectionModel.ts 的 project-version 分支)——版本卡根本没有选中态,画布上无法「选中要发布的那一版」。
  • 打包侧同理:export_local_project_package_at(apps/ai-game-creator-shell/src-tauri/src/project/export.rs:25)打的是项目当前构建,与任何版本号无关。

改法:

  • 版本卡角标由「最新 · 发布标签 v{N}」改为中性的「最新」,并换回卡面既有的中性 pill 类 game-resource-card-version-latest-tag(apps/ai-game-creator-shell/src/view/project-development/index.tsx:1301;样式 apps/ai-game-creator-shell/src/styles.css:8176)。
  • 发布面板说明改为直陈口径:「发布将使用最新内部版本 v{N}(标签 = 内部版本条数,暂不能指定其它版本);agent 再改进一次后,下一次是 v{N+1}。线上最近提交 v{M} 是平台侧事实,与本标签互不推导。」(GameDistributionPublishPanel.tsx:292-303)。

8.2 公开作品详情页作者名:为什么后端只会给「创作者」

事实依据:

  • 公开投影的作者名是后端占位词:server-rs/crates/api-server/src/modules/game_distribution.rs:2976 为 game.author_name.as_deref().unwrap_or("创作者")(后台行同族退化为 "未知作者"),而创建接口固定写空(同文件 :1460 为 author_name: None)。因此每款游戏的公开详情页都显示「创作者」,不可能是真实昵称。
  • 补查走既有免登录接口:GET /api/auth/public-users/by-id/{id}(前端封装 src/services/authService.ts:465-471,与陶泥号 by-code 同族,无需登录态)。

改法:

  • 新增 src/components/game-distribution/useGameAuthorName.ts:useGameAuthorDisplayName —— 回包名是占位词(「创作者」/「未知作者」)或空时,按 author.id(= owner_user_id)查询真实 displayName;查询中返回 null(避免先闪占位词),查不到返回空串、不编造名字;回包名本来就是真实昵称时不再发请求(后端补上后此 hook 自然退化为普通渲染)。
  • src/components/game-distribution/GameDetailPage.tsx:300-304:详情页以解析后的名字装配 displayGame(author: { ...game.author, name: authorName ?? '' }),替代直接使用公开投影的 author.name。
  • packages/shared/src/components/GameDetailDisplay/index.tsx:214、:239-243:空名不渲染「由 X 制作」那一行;头像首字改用 Array.from(authorName)[0](避免 emoji 代理对被截断);作者行补 title 悬浮显示完整名字。

8.3 已知待办(未做 / 待决策)

  1. 让「发布跟随当前选中版本」 —— 需三块一起做:(a) 版本卡区增加「设为要发布的版本」入口(当前版本卡没有选中态);(b) 把选择传进发布链路(面板 props + versionNumber + expectedPublicationRevision 的 CAS 语义);(c) 先定义「发布某个版本」到底打什么包(当前打包与版本无关)。未做。
  2. 后端读时解析作者名 —— 照抄 server-rs/crates/spacetime-module/src/game_distribution.rs:3286-3293 既有口径(按 owner_user_id 联 user_account.display_name,空则回退快照),在公开投影侧解析,可免掉前端这一跳;需重发 spacetime 模块 + api-server。未做。
  3. 公开广场卡片同根因 —— src/components/game-distribution/GameGalleryPage.tsx:114 直接渲染 game.author.name,同样只会得到「创作者」;每卡一次查询,需先评估 QPS 再定前端补查或后端解析。未做。

原始描述(保留)

关联 Issue: #470

状态

WIP。先建立持续可见的实现入口,后续按客户端上传、Web 作者管理、后台作品管理和真实栈验收逐步补齐。

当前范围

  • 客户端首版只支持 Phaser 4 npm/Vite 工程:受控构建、dist 归一化打包、8 MiB 分片上传、真实进度、幂等恢复和送审。
  • Web 作者侧:私有作品详情、状态筛选、版本历史、驳回理由、继续上传/撤回/下架/发布新版本、资料编辑和软删除。
  • 后台:作品搜索、作者筛选、状态筛选、分页、版本/审核历史、安全下架与恢复。

不变式

  • 复用现有 game-distribution 上传、审核、发行网关,不建立第二套作品系统。
  • 版本包和冻结资料不可原地修改;公开投影不携带作者私有字段。
  • owner、管理员鉴权、publicationRevision CAS 和 Idempotency-Key 继续由服务端裁决。

验收

真实 Phaser4 工程完成构建→归一化 ZIP→分片上传→送审;中断/重启恢复不重复创建游戏或版本;作者不能越权读取私有作品;后台可筛选分页并执行审核/下架/恢复;补齐定向测试、类型检查、schema、编码、文档索引、diff 和真实本地栈/客户端 smoke。

详细实施计划:docs/project-memory/plans/【实施计划】游戏作品管理与客户端发布收口-2026-09-30.md

合并前状态

  • head:aad8eb2ab;已合并 origin/master 13a15fed5(base 为最新,分支不含落后提交)
  • CI:run 3313 已跑完,8/8 全部通过(sha aad8eb2ab,state=success)。本次在本地跑过的门禁结论:check:nginx-spa-routes 通过(OK, 14 SPA routes, 1 prefix routes, 3 Nginx templates)、check-pingora-route-parity 通过(OK, 25 routes)、check:encoding 通过(5250 files)、check:doc-index 通过(240 份 Markdown)、git diff --check 干净、定向 vitest 通过(2 files / 49 passed)、eslint --max-warnings 0 通过、根 typecheck 通过
  • 已知项①:Frontend tests 的 PlatformEntryActiveFlowShell.test.tsx:748 是时序敏感 flaky —— 同一文件 blob 在绿头上相同、历史 16+ 次全绿、重跑即过,与本次改动无关
  • 已知项②:本机 check:git-hooks 的 EBUSY、以及环境性的 resources/plugins 档位差异,都不影响 CI
  • 本轮修复清单:
    1. 发布版本标签改由 manifest.versions.length 派生且面板只读(真机实测 value=4、readOnly,并并列显示「线上最近提交 v6」)
    2. AGC 发布抽屉隐藏滚动条(实测布局占位 15px → 0,可滚范围 scrollTopMax 不变)
    3. 作品详情页在非公开状态下不再请求评价/评分接口,封面显示「审核中」(真机零请求)
    4. 后台审核页移除非版本级的「安全下架」入口;提交时间格式修复;游戏列表下架改为独立面板
  • 已知未修(不在本 PR 范围,另有交接):后台「支付订单」页 502(master payment_admin.rs 的 ORDER BY)、MCP 工具表多播 2 个经 MCP 调用必 401 的工具
## 这个 PR 做了什么 > 本章节为本轮整理,目的是让作者日后不必回忆。事实均可在 `feat/game-works-management` 上复核。 ### 一、定位:作品管理与 Phaser4 客户端发布的第二轮 - 底座已由 master 提供,本分支**不重复造游戏分发的轮子**: - `328ac3184`(09-20)游戏分发实现; - `cc958f367`(09-23)后台游戏管理; - `b60aea4e7`(10-01)游戏评价 #561。 - 本分支首笔提交在 09-30,**在既有底座之上继续开发**。 - 关联 Issue:#470。 ### 二、净差规模 现算口径(`git diff origin/master...HEAD --shortstat` / `--name-status`): | 口径 | 数值 | | --- | --- | | 变更文件 | 131 | | 插入 / 删除 | +12323 / -1470 | | 新增文件 | 28 | | 删除 master 文件 | 0 | | 分支提交数 | 50(含 merge) | **口径随 head 更新**:现 head `e593236f9`,对比基准 origin/master `a2f250364`。历史锚点:`2f6df57ce` 时为 127 files / +12028 / -1461 / 新增 27 / 删除 0;`aa4d17895` 时为 130 files / +12235 / -1470 / 新增 27;本轮再追加 `2e7409274`(5 files / +27 / -22)与 `e593236f9`(3 files / +91 / -8),即上表现值。 ### 三、不可替代的能力(master 上没有) 1. **AGC Phaser4 真实打包 / 分片上传 / 原生幂等账本 / 阶段进度**:受控构建 → dist 归一化打包 → 8 MiB 分片上传 → 真实进度 → 幂等恢复 → 送审;核心在 `apps/ai-game-creator-shell/src-tauri/` 与 `server-rs/crates/api-server/src/modules/game_distribution.rs`。 2. **versionNumber 语义统一**:支持版本回退与重复标签提交,冲突由 CAS 拒绝并返回 `VERSION_NUMBER_CONFLICT`(`GAME_DISTRIBUTION_VERSION_NUMBER_CONFLICT`)。 3. **owner 私有作品详情 / 资料编辑 / 版本历史 / 软删除**:`GET / PATCH / DELETE /api/game-distribution/my-games/{game_id}`。 4. **后台作品筛选 / 游标分页 / 软删除治理**:`GET /admin/api/game-distribution/games`。 5. **后台待审版本试玩预览**:`POST /admin/api/game-distribution/versions/{version_id}/preview-session` + `GET /api/game-distribution/admin-previews/{preview_token}[/{*asset_path}]`。 6. **发行资源归一化 + storage bootstrap 注入**:新增 `server-rs/crates/api-server/src/modules/game_distribution_release_storage_bootstrap.js`。 7. **`packages/shared` 新增 `GameDetailDisplay` / `GameDetailShowcase` 组件**:作者侧与后台复用同一套作品详情展示(`packages/shared/src/components/GameDetailDisplay/`)。 ### 四、路由变化 - `api-server/src/app.rs` **未变**(0 行改动),新路由全部在模块内挂载。 - 路由数:master **37** → 本分支 **42**(净增 5 条,集中在 `my-games/{game_id}` 与 `admin-previews` 家族)。 ### 五、SpacetimeDB 变更 - **无新表**。 - 追加字段:`GameDistributionGame.deleted_at`、`CreateVersionInput.version_number`、`GameSnapshot.local_project_id`、`AdminGameSnapshot.deleted_at_micros`、`AdminGameListResult.next_cursor`、`ReviewListInput.{keyword, owner_user_id, status, cursor}`。 - **新增 2 个 procedure**:`update_game_distribution_game_metadata_and_return`、`delete_game_distribution_game_and_return`。 ### 六、本轮质量修复 1. **「AI 改完一版却没出现新版本卡」根因**:新增的内部版本只落在清单里,不经过工具桥,因此没有任何事件;登记成功后必须显式宣告清单失效,否则渲染层的资源投影(「项目版本」卡、发布面板版本标签)在本回合结束后不会重读清单。修复见 `apps/ai-game-creator-shell/src-tauri/src/project/manifest.rs:1025`(`append_agent_game_iteration_version_at` 改为返回是否登记成功)与 `apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime/mod.rs:4181-4193`(登记后 `emit_game_creator_manifest_invalidated`)。 2. **版本卡顺序修复**:按内部版本序数排序,修正初始版本被排到最后;`resourceProjectionModel.ts` 的 `orderIndex` 与 `compareResourceOrder`。 3. **发布面板「项目版本」**:改为由 AGC 内部版本**只读派生**,拆除 `projectVersion` 写链路。 4. **AGC 发布抽屉隐藏滚动条**:`apps/ai-game-creator-shell/src/styles.css`。 5. **作品详情页非公开态**:不再请求评价接口,封面显示「审核中」。 6. **后台审核页游戏列**:显示游戏名 + 作者,不再只显示 gameId(用例 `AdminGameDistributionReviewPage.test.tsx:256`)。 7. **后台游戏列表**:下架入口收敛为独立面板,状态胶囊不换行。 8. **与 master 的重复实现已去重**:master `a1b80ffde` + `33552d2ed` 已含游戏评价页排布实现,本分支对应改动删除,**以 master 为准**(提交 `aa4d17895`,`+1/-18`)。 ### 七、验证 - CI **run 3329**(head `2f6df57ce`)= **8/8 全绿**;**run 3335**(head `aa4d17895`)= **8/8 全绿**。 - **run 3342**(head `e593236f9`,本 PR 现 head)截至写入时状态为 `queued`,结论**待 CI**(已注册,尚未产出结果)。 - 关键用例:`AdminGameDistributionReviewPage.test.tsx` 7 passed、`AdminGameReviewsPage.test.tsx` 8 passed;前端整体 246 passed / 0 failed(run 3335 口径)。 ### 八、同日追加修复(发布版本文案 / 作者名) head `aa4d17895` → `e593236f9` 追加两笔:`2e7409274` 发布版本文案去诱导(5 files / +27 / -22)、`e593236f9` 公开作品详情页作者名(3 files / +91 / -8)。 #### 8.1 发布版本文案:为什么要去掉「发布标签 v{N}」 **事实依据(为何原文案会误导):** - 发布提交的版本标签**只有一个来源**:`resolveGameCreationAppProjectVersion(manifest)` 返回 `versions.length`(`packages/shared/src/contracts/gameCreationApp.ts:993-999`);面板把它作为只读派生值取用(`apps/ai-game-creator-shell/src/components/game-distribution/GameDistributionPublishPanel.tsx:282`),提交时原样写入 `versionNumber`(同文件 `:775`)。即:**发布固定取最新内部版本,与用户在画布上选中哪张卡无关**。 - 资源画布的「当前版本」**只作用于素材卡绑定与运行播放**:`WorkspaceLauncher.tsx:199` 的 `activeVersionId` → `resourceCanvasVersionBindingModel.ts:51-82`,其中 `isResourceUsedByCurrentVersion` 要求 `resource.manifestAssetId !== null`;而版本卡在投影里 `manifestAssetId` 恒为 `null`(`resourceProjectionModel.ts` 的 `project-version` 分支)——**版本卡根本没有选中态**,画布上无法「选中要发布的那一版」。 - 打包侧同理:`export_local_project_package_at`(`apps/ai-game-creator-shell/src-tauri/src/project/export.rs:25`)打的是**项目当前构建**,与任何版本号无关。 **改法:** - 版本卡角标由「最新 · 发布标签 v{N}」改为中性的「**最新**」,并换回卡面既有的中性 pill 类 `game-resource-card-version-latest-tag`(`apps/ai-game-creator-shell/src/view/project-development/index.tsx:1301`;样式 `apps/ai-game-creator-shell/src/styles.css:8176`)。 - 发布面板说明改为直陈口径:「发布将使用最新内部版本 v{N}(标签 = 内部版本条数,暂不能指定其它版本);agent 再改进一次后,下一次是 v{N+1}。线上最近提交 v{M} 是平台侧事实,与本标签互不推导。」(`GameDistributionPublishPanel.tsx:292-303`)。 #### 8.2 公开作品详情页作者名:为什么后端只会给「创作者」 **事实依据:** - 公开投影的作者名是**后端占位词**:`server-rs/crates/api-server/src/modules/game_distribution.rs:2976` 为 `game.author_name.as_deref().unwrap_or("创作者")`(后台行同族退化为 `"未知作者"`),而创建接口**固定写空**(同文件 `:1460` 为 `author_name: None`)。因此每款游戏的公开详情页都显示「创作者」,**不可能**是真实昵称。 - 补查走**既有免登录**接口:`GET /api/auth/public-users/by-id/{id}`(前端封装 `src/services/authService.ts:465-471`,与陶泥号 `by-code` 同族,无需登录态)。 **改法:** - 新增 `src/components/game-distribution/useGameAuthorName.ts`:`useGameAuthorDisplayName` —— 回包名是占位词(「创作者」/「未知作者」)或空时,按 `author.id`(= `owner_user_id`)查询真实 `displayName`;查询中返回 `null`(避免先闪占位词),查不到返回空串、**不编造名字**;回包名本来就是真实昵称时不再发请求(后端补上后此 hook 自然退化为普通渲染)。 - `src/components/game-distribution/GameDetailPage.tsx:300-304`:详情页以解析后的名字装配 `displayGame`(`author: { ...game.author, name: authorName ?? '' }`),替代直接使用公开投影的 `author.name`。 - `packages/shared/src/components/GameDetailDisplay/index.tsx:214`、`:239-243`:空名**不渲染**「由 X 制作」那一行;头像首字改用 `Array.from(authorName)[0]`(避免 emoji 代理对被截断);作者行补 `title` 悬浮显示完整名字。 #### 8.3 已知待办(**未做 / 待决策**) 1. **让「发布跟随当前选中版本」** —— 需三块一起做:(a) 版本卡区增加「设为要发布的版本」入口(当前版本卡没有选中态);(b) 把选择传进发布链路(面板 props + `versionNumber` + `expectedPublicationRevision` 的 CAS 语义);(c) 先定义「发布某个版本」到底打什么包(当前打包与版本无关)。**未做。** 2. **后端读时解析作者名** —— 照抄 `server-rs/crates/spacetime-module/src/game_distribution.rs:3286-3293` 既有口径(按 `owner_user_id` 联 `user_account.display_name`,空则回退快照),在公开投影侧解析,可免掉前端这一跳;需**重发 spacetime 模块 + api-server**。**未做。** 3. **公开广场卡片同根因** —— `src/components/game-distribution/GameGalleryPage.tsx:114` 直接渲染 `game.author.name`,同样只会得到「创作者」;每卡一次查询,需先评估 QPS 再定前端补查或后端解析。**未做。** --- ## 原始描述(保留) 关联 Issue: #470 ## 状态 WIP。先建立持续可见的实现入口,后续按客户端上传、Web 作者管理、后台作品管理和真实栈验收逐步补齐。 ## 当前范围 - 客户端首版只支持 Phaser 4 npm/Vite 工程:受控构建、dist 归一化打包、8 MiB 分片上传、真实进度、幂等恢复和送审。 - Web 作者侧:私有作品详情、状态筛选、版本历史、驳回理由、继续上传/撤回/下架/发布新版本、资料编辑和软删除。 - 后台:作品搜索、作者筛选、状态筛选、分页、版本/审核历史、安全下架与恢复。 ## 不变式 - 复用现有 game-distribution 上传、审核、发行网关,不建立第二套作品系统。 - 版本包和冻结资料不可原地修改;公开投影不携带作者私有字段。 - owner、管理员鉴权、publicationRevision CAS 和 Idempotency-Key 继续由服务端裁决。 ## 验收 真实 Phaser4 工程完成构建→归一化 ZIP→分片上传→送审;中断/重启恢复不重复创建游戏或版本;作者不能越权读取私有作品;后台可筛选分页并执行审核/下架/恢复;补齐定向测试、类型检查、schema、编码、文档索引、diff 和真实本地栈/客户端 smoke。 详细实施计划:docs/project-memory/plans/【实施计划】游戏作品管理与客户端发布收口-2026-09-30.md ## 合并前状态 - head:`aad8eb2ab`;已合并 `origin/master 13a15fed5`(base 为最新,分支不含落后提交) - CI:run 3313 已跑完,**8/8 全部通过**(sha `aad8eb2ab`,state=success)。本次在本地跑过的门禁结论:`check:nginx-spa-routes` 通过(OK, 14 SPA routes, 1 prefix routes, 3 Nginx templates)、`check-pingora-route-parity` 通过(OK, 25 routes)、`check:encoding` 通过(5250 files)、`check:doc-index` 通过(240 份 Markdown)、`git diff --check` 干净、定向 `vitest` 通过(2 files / 49 passed)、`eslint --max-warnings 0` 通过、根 `typecheck` 通过 - 已知项①:`Frontend tests` 的 `PlatformEntryActiveFlowShell.test.tsx:748` 是时序敏感 flaky —— 同一文件 blob 在绿头上相同、历史 16+ 次全绿、重跑即过,与本次改动无关 - 已知项②:本机 `check:git-hooks` 的 EBUSY、以及环境性的 `resources/plugins` 档位差异,都不影响 CI - 本轮修复清单: 1. 发布版本标签改由 `manifest.versions.length` 派生且面板只读(真机实测 `value=4`、`readOnly`,并并列显示「线上最近提交 v6」) 2. AGC 发布抽屉隐藏滚动条(实测布局占位 15px → 0,可滚范围 `scrollTopMax` 不变) 3. 作品详情页在非公开状态下不再请求评价/评分接口,封面显示「审核中」(真机零请求) 4. 后台审核页移除非版本级的「安全下架」入口;提交时间格式修复;游戏列表下架改为独立面板 - 已知未修(不在本 PR 范围,另有交接):后台「支付订单」页 502(master `payment_admin.rs` 的 `ORDER BY`)、MCP 工具表多播 2 个经 MCP 调用必 401 的工具
suzmii added 2 commits 2026-10-01 13:59:37 +08:00
- api-server 新增 GET /api/game-distribution/my-games/{gameId},作者可读自己名下审核中/被驳回/已下架/已撤回的作品
- 抽取 owner_game_entry_payload 统一作者条目形状,公开投影继续不携带版本私有状态
- 版本私有状态补 entryUrl 与 packageFileCount,供客户端作品详情展示版本历史与公开链接
- 主规范路由表登记新路由,并修正 /my-games 的错名
- 新增里程碑实施计划【实施计划】游戏作品管理与客户端发布收口-2026-09-30
Merge remote-tracking branch 'origin/master' into feat/game-works-management
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m52s
Project CI / Backend tests (pull_request) Failing after 14s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m19s
Project CI / Frontend tests (pull_request) Successful in 2m10s
Project CI / Repository checks (pull_request) Failing after 13s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m40s
Project CI / Native shell tests (pull_request) Successful in 5m16s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 8m42s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 9m16s
1f055e9902
Author
Member

本轮实现已完成,仍保持 WIP:

  • 客户端:Phaser 4 + Vite 发布前校验;构建/准备/上传/校验/送审阶段与上传百分比;账号 + origin + localProjectId + 包摘要的原生幂等账本。
  • Web 作者侧:owner 私有详情、状态/版本筛选、版本历史、恢复动作、资料编辑、软删除、撤回/下架/继续发布操作。
  • 后台:作品搜索、作者/状态筛选、游标分页、软删除展示与版本历史。
  • 后端:deleted_at 末尾追加、公开/owner/admin 过滤、PATCH/DELETE owner 路由、审计事件、DTO/绑定/schema 同步。

自动验证:主站/后台/AGC typecheck;Web/后台 104 个定向测试;AGC 发布 27 个定向测试;api-server 游戏分发 33 个测试、spacetime-module 262 个过滤测试、shared-contracts 4 个测试;Rust fmt、schema、generated bindings、DTO parity、encoding、doc-index、diff check 均通过。真实 Web 未登录作者入口与后台登录入口已用 Chromium 冒烟;真实 AGC GUI 发布、生产开闸和 OSS 清理策略仍未验证。

本轮实现已完成,仍保持 WIP: - 客户端:Phaser 4 + Vite 发布前校验;构建/准备/上传/校验/送审阶段与上传百分比;账号 + origin + localProjectId + 包摘要的原生幂等账本。 - Web 作者侧:owner 私有详情、状态/版本筛选、版本历史、恢复动作、资料编辑、软删除、撤回/下架/继续发布操作。 - 后台:作品搜索、作者/状态筛选、游标分页、软删除展示与版本历史。 - 后端:deleted_at 末尾追加、公开/owner/admin 过滤、PATCH/DELETE owner 路由、审计事件、DTO/绑定/schema 同步。 自动验证:主站/后台/AGC typecheck;Web/后台 104 个定向测试;AGC 发布 27 个定向测试;api-server 游戏分发 33 个测试、spacetime-module 262 个过滤测试、shared-contracts 4 个测试;Rust fmt、schema、generated bindings、DTO parity、encoding、doc-index、diff check 均通过。真实 Web 未登录作者入口与后台登录入口已用 Chromium 冒烟;真实 AGC GUI 发布、生产开闸和 OSS 清理策略仍未验证。
suzmii added 1 commit 2026-10-01 16:31:27 +08:00
作品管理与Phaser4客户端发布闭环
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m21s
Project CI / Backend tests (pull_request) Failing after 16s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m18s
Project CI / Frontend tests (pull_request) Successful in 2m8s
Project CI / Repository checks (pull_request) Failing after 16s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m56s
Project CI / Native shell tests (pull_request) Successful in 5m47s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
a2b70d92b8
补齐 Phaser4 客户端发布前校验、阶段进度与原生幂等账本

增加 Web 作者私有作品管理、资料编辑、版本历史与软删除

增加后台作品筛选、游标分页与删除治理

同步 SpacetimeDB schema、bindings、DTO、文档与定向测试
suzmii added 1 commit 2026-10-01 16:52:06 +08:00
收紧Phaser4发布边界并整理前端模型
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (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
0e4cf6356f
阻断无npm构建工作区的单文件项目发布,明确客户端首版支持范围

拆分作品资料媒体默认逻辑与版本历史模型,满足前端刷新组件规则

补充对应Rust发布门禁与导出测试
Author
Member

补充修正:客户端发布现已对无 npm build 工作区的单文件项目主动失败,只支持 Phaser 4 + Vite;对应 Rust 门禁与导出测试已通过。
更正测试统计:spacetime-module 本次命令匹配到 0 个测试(262 个被过滤),不是 262 个通过;api-server 游戏分发 33 passed,shared-contracts 4 passed,AGC Phaser 门禁 5 + 4 passed。
真实验证边界不变:Web/后台已验证未登录入口与视觉渲染;作者登录后作品操作、后台登录后管理列表、真实 AGC GUI 发布、生产开闸和 OSS 清理仍待具备 warm token/真实客户端与生产条件后验证。

补充修正:客户端发布现已对无 npm build 工作区的单文件项目主动失败,只支持 Phaser 4 + Vite;对应 Rust 门禁与导出测试已通过。 更正测试统计:spacetime-module 本次命令匹配到 0 个测试(262 个被过滤),不是 262 个通过;api-server 游戏分发 33 passed,shared-contracts 4 passed,AGC Phaser 门禁 5 + 4 passed。 真实验证边界不变:Web/后台已验证未登录入口与视觉渲染;作者登录后作品操作、后台登录后管理列表、真实 AGC GUI 发布、生产开闸和 OSS 清理仍待具备 warm token/真实客户端与生产条件后验证。
suzmii added 1 commit 2026-10-01 17:05:23 +08:00
合并master到作品管理分支
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (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
b3e6950546
保留主线DirectProject与客户端基础设施更新

重新接回Phaser4发布、分片上传进度和幂等账本改动
suzmii added 1 commit 2026-10-01 17:05:52 +08:00
Merge branch 'master' into feat/game-works-management
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (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
929a26d59b
suzmii added 2 commits 2026-10-01 17:32:22 +08:00
将分片上传与校验进度迁入主线runtime模块

移除commands旧层重复发布命令并保留desktop入口

补齐合并后的Rust编译与上传回归
Merge remote-tracking branch 'origin/feat/game-works-management' into feat/game-works-management
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m34s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m18s
Project CI / Backend tests (pull_request) Successful in 4m27s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 10m41s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 9m41s
Project CI / Frontend tests (pull_request) Successful in 2m11s
Project CI / Native shell tests (pull_request) Successful in 6m4s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m8s
Project CI / Repository checks (pull_request) Successful in 2m53s
e471d4505f
Author
Member

已同步最新 master 到功能分支并推送:\n- 合并提交:e471d4505(包含主线 DirectProject/Codex 相关更新);\n- 修复主线将 game_package_upload 拆到 runtime 后的发布进度接线冲突;\n- 合并后 Web/后台 104 个定向测试、AGC 发布 27 个定向测试、主站类型检查、AGC cargo check、Rust fmt、编码/文档/diff 门禁通过。

已同步最新 master 到功能分支并推送:\n- 合并提交:e471d4505(包含主线 DirectProject/Codex 相关更新);\n- 修复主线将 game_package_upload 拆到 runtime 后的发布进度接线冲突;\n- 合并后 Web/后台 104 个定向测试、AGC 发布 27 个定向测试、主站类型检查、AGC cargo check、Rust fmt、编码/文档/diff 门禁通过。
suzmii added 1 commit 2026-10-01 20:11:23 +08:00
移除AGC发布入口前端灰度
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m33s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m3s
Project CI / Backend tests (pull_request) Failing after 18s
Project CI / Frontend tests (pull_request) Successful in 2m18s
Project CI / Repository checks (pull_request) Failing after 16s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m42s
Project CI / Native shell tests (pull_request) Successful in 6m13s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 8m59s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 11m8s
618c69e766
让DirectProject工作台始终展示发布按钮,保留Tauri、项目原型和服务端校验

删除原生发布灰度查询命令及配置白名单

更新发布入口与Rust facade定向测试
Author
Member

已按需求移除 AGC 发布入口的前端灰度阻断。DirectProject 工作台现在直接传递发布回调;仍保留 Tauri 宿主、项目原型完成、封面/资料校验、服务端鉴权与审核校验。
同时删除 read_game_publish_availability 原生命令、配置白名单与对应测试夹具。验证:入口/发布定向测试 29 passed,AGC typecheck、check-config、ESLint、Prettier、Rust fmt 和 encoding/diff 门禁通过。提交:618c69e76。

已按需求移除 AGC 发布入口的前端灰度阻断。DirectProject 工作台现在直接传递发布回调;仍保留 Tauri 宿主、项目原型完成、封面/资料校验、服务端鉴权与审核校验。 同时删除 read_game_publish_availability 原生命令、配置白名单与对应测试夹具。验证:入口/发布定向测试 29 passed,AGC typecheck、check-config、ESLint、Prettier、Rust fmt 和 encoding/diff 门禁通过。提交:618c69e76。
suzmii added 3 commits 2026-10-02 16:04:59 +08:00
修复游戏封面预览并统一发布灰度说明
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m53s
Project CI / Backend tests (pull_request) Failing after 15s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m41s
Project CI / Frontend tests (pull_request) Failing after 1m5s
Project CI / Repository checks (pull_request) Failing after 23s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m48s
Project CI / Native shell tests (pull_request) Successful in 5m43s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 10m6s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 10m9s
772e9f0d42
封面生成结果经鉴权 read-url 转为安全 data URL 预览,失败时不阻断已登记素材发布。

统一后台、前端与后端对 game-distribution:publish 未配置和关闭状态的说明。
suzmii added 5 commits 2026-10-03 13:30:47 +08:00
将运行期存储兼容层保存为独立 JavaScript 文件,通过 include_str 注入发行 HTML。

保持 opaque sandbox 隔离,仅提供当前运行实例的 localStorage 与 sessionStorage 兼容能力。

同步发行沙箱验收脚本和玩法运行契约文档。
构建项目发布时补入 dist 未包含的项目根 assets 文件,并优先保留 dist 同路径产物。

增加 Phaser 发行包素材回归测试并同步发行契约文档。
后台审核详情复用公开游戏详情样式,补齐发布者、冻结资料、素材换签和待审 ZIP 试玩。

AGC 保存已发布作品绑定,支持同一 gameId 更新版本并由用户填写目标版本号。

保留 SpacetimeDB 表结构不变,增加版本号请求校验、幂等边界和本地清单字段。
修复发行资源路径与审核试玩 Cookie
Project CI / Backend tests (pull_request) Failing after 29s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m48s
Project CI / Frontend tests (pull_request) Failing after 1m11s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 3m18s
Project CI / Repository checks (pull_request) Failing after 42s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 4m13s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m15s
Project CI / Native shell tests (pull_request) Successful in 6m37s
2eac0975df
归一化发行包根绝对资源引用并兼容已有发行包,修复正式运行时素材请求跑到本地 Vite 的问题。

审核预览仅拒绝真实平台 refresh Cookie,保留版本绑定 Token 和私有缓存隔离。
suzmii added 1 commit 2026-10-03 14:34:41 +08:00
修复审核版本 revision 冲突
Project CI / Backend tests (pull_request) Failing after 33s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m57s
Project CI / Frontend tests (pull_request) Failing after 1m33s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 3m39s
Project CI / Repository checks (pull_request) Failing after 25s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 4m46s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m54s
Project CI / Native shell tests (pull_request) Successful in 6m1s
454ed320a5
审核队列与版本快照使用所属游戏当前 publication_revision,避免新游戏审核通过时误携带 0。

详情审核动作使用最新详情 revision,并补充后台回归测试。
suzmii added 1 commit 2026-10-03 14:48:29 +08:00
合并最新 master 到作品管理分支
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m48s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 3m13s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 4m21s
Project CI / Frontend tests (pull_request) Failing after 1m39s
Project CI / Repository checks (pull_request) Failing after 1m26s
Project CI / Backend tests (pull_request) Successful in 6m50s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m0s
Project CI / Native shell tests (pull_request) Successful in 6m48s
667d1ad6dc
suzmii added 1 commit 2026-10-03 15:05:02 +08:00
修正发行资源归一化测试
Project CI / Backend tests (pull_request) Failing after 23s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m56s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 3m44s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m41s
Project CI / Repository checks (pull_request) Failing after 29s
Project CI / Frontend tests (pull_request) Failing after 1m38s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m46s
Project CI / Native shell tests (pull_request) Successful in 6m5s
b1e04e8a7b
使用真实 HTML 资源引用验证根绝对路径归一化,修复 CI 中的转义输入误报。
suzmii added 2 commits 2026-10-03 15:46:14 +08:00
统一 AGC 项目与发行版本模型
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m18s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 3m54s
Project CI / Frontend tests (pull_request) Failing after 1m28s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m33s
Project CI / Repository checks (pull_request) Failing after 1m15s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m15s
Project CI / Backend tests (pull_request) Successful in 6m50s
Project CI / Native shell tests (pull_request) Successful in 6m45s
996135379b
将用户版本改为可回退、可重复提交的版本标签,使用不可变 versionId 区分具体提交实例。

明确 publicationRevision 仅负责并发 CAS,不再限制用户版本号递增。
suzmii added 1 commit 2026-10-03 16:42:35 +08:00
实现统一项目发行版本
Project CI / AI game creator shell Rust crates (pull_request) Failing after 56s
Project CI / Backend tests (pull_request) Failing after 23s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 5m7s
Project CI / Repository checks (pull_request) Failing after 21s
Project CI / Frontend tests (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 lane 2/2 (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
3aa3e33ceb
以 projectVersion 作为 AGC 唯一用户版本,支持同版本重复提交和版本回退。

保留 publicationRevision 并发校验与旧客户端自动递增兼容。
suzmii added 1 commit 2026-10-03 16:55:08 +08:00
支持统一版本回退与重复提交
Project CI / Backend tests (pull_request) Failing after 54s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m22s
Project CI / Frontend tests (pull_request) Successful in 2m8s
Project CI / Repository checks (pull_request) Failing after 17s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m23s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 4m27s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m3s
Project CI / Native shell tests (pull_request) Successful in 5m18s
7bf7d6b10e
以 projectVersion 作为唯一用户版本标签,允许同版本重复提交和版本回退。

按 versionId 保持提交实例不可变,取消同版本旧 pending 提交并按最近提交排序。
suzmii added 1 commit 2026-10-03 17:06:11 +08:00
Merge remote-tracking branch 'origin/master' into feat/game-works-management
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m5s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 3m28s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m5s
Project CI / Frontend tests (pull_request) Successful in 2m43s
Project CI / Backend tests (pull_request) Successful in 6m12s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m37s
Project CI / Repository checks (pull_request) Failing after 3m54s
Project CI / Native shell tests (pull_request) Successful in 5m59s
72d6ea2180
suzmii added 1 commit 2026-10-03 17:20:09 +08:00
修复审核与发布页面 import 排序
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 2m34s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 4m30s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m18s
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 / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
3a1ccf312d
按仓库 eslint simple-import-sort 规则整理五个相关文件,保持行为不变。
suzmii added 1 commit 2026-10-03 17:34:31 +08:00
合并最新 master 到作品管理分支
Project CI / Backend tests (pull_request) Failing after 39s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m44s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 3m43s
Project CI / Repository checks (pull_request) Failing after 40s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m52s
Project CI / Frontend tests (pull_request) Successful in 3m17s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m12s
Project CI / Native shell tests (pull_request) Successful in 6m41s
f4ca1aeecc
suzmii added 1 commit 2026-10-03 18:26:46 +08:00
Merge remote-tracking branch 'origin/master' into feat/game-works-management
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m56s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m55s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 6m19s
Project CI / Backend tests (pull_request) Failing after 4m14s
Project CI / Frontend tests (pull_request) Successful in 2m48s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m36s
Project CI / Repository checks (pull_request) Failing after 3m50s
Project CI / Native shell tests (pull_request) Successful in 6m0s
6edda2ae68
suzmii added 7 commits 2026-10-04 00:40:57 +08:00
- shared contracts:resolveGameCreationAppProjectVersion 改为按 manifest.versions 条数派生,删除 isGameCreationAppProjectVersion,projectVersion 注释降级为遗留兼容位
- Rust shared-contracts:删除 resolve_game_creation_app_project_version / is_game_creation_app_project_version / GAME_CREATION_APP_FIRST_PROJECT_VERSION,project_version 注释改遗留位并重写往返测试
- AGC 发布面板:项目版本改为 useMemo 派生只读输入框,删除本地 state、失焦落盘与 onManifestUpdated 回调
- AGC 发布服务:删除 saveGameDistributionProjectVersion,提交版本号缺省改为按 versions 派生
- AGC 原生:发布成功回写与绑定回填不再写 project_version(置空),删除 update_game_distribution_project_version 命令
- AGC 命令注册与白名单:desktop.rs 注销命令、check-config.mjs 移除白名单条目
- AGC 前端装配:App.tsx 移除两处 onManifestUpdated 传递
- AGC 测试:publish/panel 两条测试改为覆盖派生口径,删除四条写回用例
- 注释对齐:game_publish_attempt.rs / project/manifest.rs / styles.css / shared-contracts 的 game_distribution.rs 把版本标签口径改为「由 versions[] 派生」,清掉 projectVersion 遗留位表述
- 文档:decision-log 追加本决策条目,两份 2026-10-02 计划加取代标注,新增 2026-10-03 里程碑与实施计划
- export.rs:npm 导出用例改名并扩断言,覆盖根 assets 补入与 dist 同名优先
- export.rs:新增 5 条发布前工程栈校验用例(Phaser4+Vite 通过、Phaser3 报可操作错误、缺依赖与非 Vite 失败、semver 区间与 lockfile 版本、无 npm build 工作区失败)
- export.rs:新增 1 条端到端归一化 ZIP 用例(剥离 game 前缀、dist 产物优先、node_modules 与源码不入包、入口引用改相对)
- export.rs:新增 1 条已有可玩入口时跳过 npm run build 的用例
- 游戏管理页:下架改为独立面板(原因必填、校验提示、仍走二次确认),操作列与作者列排版调整,gameId 省略号加 title
- 游戏管理页测试:拆成空原因不提交、面板取消不请求、面板确认后仍需二次确认三条
- 审核页:移除行内游戏级安全下架及其状态与二次确认接线,理由弹窗只服务拒绝,gameId 截断加 title
- 审核页测试:删除两条安全下架用例,替换为行内无该动作、microsZ 时间列渲染、窄视口 gameId 截断
- 新增 adminGameDistributionReview.css:审核页专属列宽与动作列 nowrap,含 1366/980 两档断点
- admin-web admin.css:新增游戏管理表格 5 条排版规则
- shared AdminFormat:新增 normalizeAdminTimestamp,兼容后端 seconds.microsZ 时间口径
- shared AdminFormat 测试:新增 5 条覆盖微秒口径、补零、ISO 与 epoch 兼容、非法值回落
- shared admin.css:admin-status 改为 nowrap
- 文档:后台游戏审核详情计划加取代标注,说明审核页只承载版本级动作
- 平台入口与玩法链路:改写版本模型条款为按 versions 派生只读,并同步安全下架入口收敛到游戏管理页
- 平台入口与玩法链路:新增兼容与迁移、非目标两条
- pitfalls:追加随包 plugins feature 档位与 build.rs 假通过排障条目
# Conflicts:
#	apps/ai-game-creator-shell/tests/gameDistributionPublishLive.test.ts
- 改动文件:apps/ai-game-creator-shell/tests/gameDistributionPublishPanel.test.tsx(仅此一个文件)
- 写法替换:把 `Promise.withResolvers<unknown>()` 换成本地手写 deferred(`let settlePending` + `new Promise((resolve) => { settlePending = resolve })`),resolve 仍由外部持有、promise 仍交回测试,与原 onResolve/onReject 语义一致(原 reject 未被使用)
- 为什么不改 tsconfig:`Promise.withResolvers` 需要 lib ES2024,而 apps/ai-game-creator-shell/tsconfig.json 是 target/lib ES2022;为单个测试把 lib 提到 ES2024 会改整个 AGC 客户端的编译目标与运行时假设,影响面远大于此处需求,故只在测试内手写等价 deferred
- 验证:npm run agc:typecheck 五步全 0(check:tests:types → tsc -p tsconfig.json → skill-pack:check → bundled-resources:check → check-config.mjs)
消除 AGC 导出测试对 HOME 环境变量的依赖
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m6s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m3s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 6m9s
Project CI / Backend tests (pull_request) Failing after 3m57s
Project CI / Frontend tests (pull_request) Successful in 3m8s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m1s
Project CI / Repository checks (pull_request) Failing after 4m21s
Project CI / Native shell tests (pull_request) Successful in 7m42s
0bf84e2886
- export.rs:npm_export_tests 的 2 条用例(npm_package_contains_dist_project_root_assets_and_publish_readme、本批新增的 built_project_publish_payload_includes_uploaded_assets_and_prefers_dist_assets)不再用 std::env::var("HOME") 拼临时根,改用仓库既有约定的 crate::tests::canonical_test_tempdir
- 动机:Windows 只设 USERPROFILE、不设 HOME 时,std::env::var("HOME").unwrap() 会以 NotPresent panic;改后与本批另 5 条 publish_export_tests 的临时根口径一致
- 未动断言:两条用例的断言与语义保持不变,只替换临时根来源(canonical_test_tempdir 同样返回 tempfile::TempDir,root.path() 用法不变)
- 验证(同一命令 cargo test --locked --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --bin genarrative-ai-game-creator-shell -- --test-threads=1 project::export::):HOME 未设置(env -u HOME)→ exit 0,test result: ok. 12 passed; 0 failed;HOME=C:/Users/dongy → exit 0,test result: ok. 12 passed; 0 failed
- 顺带核对:project/verification.rs 仍有 1 处同名 HOME 写法,属其它模块范围,本次不动
Author
Member

CI run 3295 结论(head 0bf84e288)

一句话:CI run 3295 = 6 passed / 2 failed;两处失败均为 master 既有缺陷,与本 PR 无因果关系;本 PR 此前唯一的真实门禁红(AGC shell lane 的旧导出断言)已修复并转绿。

本轮失败项与出处

  1. Backend tests(run 3295 / job 19355)
    • 失败步骤:cargo test --locked --workspace --exclude spacetime-module --no-fail-fast --manifest-path server-rs/Cargo.toml
    • 首个错误:crates/api-server/src/external_mcp/semantic/tests.rs:33 → assertion \left == right` failed/left: 32/right: 30`
    • 归属:master 4b529a895「新增支付服务接入与订单收银台」(PR #597) 在 docs/openapi/genarrative-external-v1.openapi.json 追加了 /api/external/v1/payment/orders 与 /api/external/v1/payment/orders/{orderId} 两条外部操作,未标 x-mcp-excluded,因此经 external_mcp.rs 的自动派生进入 MCP 工具表;而 semantic/tests.rs 的期望值未同步(MCP_OPERATIONS.len() == 30)。master 自身 run 3268 / job 19139 逐字相同。 紧随的 names.len() == 45(实际 47)亦已过期,同源。
  2. Repository checks(run 3295 / job 19358)
    • 失败步骤:npm run check:repository-ci
    • 首个错误:[check:nginx-spa-routes] FAILED - deploy/nginx/genarrative.conf 缺少 SPA 路由: /pay, /profile/payment(共 15 条诊断,涉及 deploy/nginx/genarrative.conf、deploy/nginx/genarrative-dev-http.conf、deploy/container/nginx.conf)
    • 归属:同一提交把 /pay、/profile/payment 加进 src/routing/activeAppPageRoutes.ts,但未同步 nginx 模板与 Pingora 网关 SPA 清单。master 自身 run 3268 / job 19142 相同。 check:pingora-route-parity 因 npm 链在该步中断而未执行;同一缺口同样存在于 server-rs/crates/pingora-gateway/src/main.rs 的 MAIN_SPA_PATHS(12 条 vs 应为 14 条)。
    • 边界:本 PR 相对 master 对 deploy/**、src/routing/**、server-rs/crates/api-server/src/external_mcp/** 零差异,可在 master 上独立复现。

本 PR 本轮修掉的门禁红

AI game creator shell Rust lane 2/2(run 3295 / job 19353)→ success。原用例 project::export::npm_export_tests::npm_package_contains_only_dist_and_publish_readme 的期望(仅 3 条目、不含项目根 assets/**)与生产行为冲突;其对应的真实回归用例已随一次 master 合并被删除。现已改名为 npm_package_contains_dist_project_root_assets_and_publish_readme 并按契约文档口径扩断言,另补回 6 条发布前工程栈/导出用例。

本轮主要内容

  • 发布版本标签改为由工程内部版本 manifest.versions 条数派生、面板只读;拆除 projectVersion 写链路与该手改命令。
  • AGC 导出/发布测试回补(含去 HOME 依赖、跳过构建路径)。
  • 后台「游戏管理与审核」排版修复,下架流程收敛:安全下架仅保留在游戏管理页的独立面板,审核页只保留版本级动作。
  • 平台入口主规范与排障记忆同步(含 pitfalls.md 4 条新条目)。

真机核验(非测试替代)

真实 AGC 客户端(WebView2 + CDP)实测发布面板:「项目版本」输入框 value=4、readOnly=true、aria-readonly=true,与 get_local_game_manifest 的 versions.length=4 一致;面板并列显示「线上最近提交 v6 · 审核中」;面板内可编辑版本号输入框数量为 0;磁盘清单中遗留的 projectVersion 键已被抹除。

本机环境项(不经由 CI,避免误读)

Windows 本机 check:git-hooks 因临时目录 EBUSY 失败;AGC rust 分片 runner 会被一个 Windows 阻塞模态用例挂死(Linux CI 不受影响,本地改用等价分块跑)。两者均不经由 CI;本机 cargo 类门禁已在 featureless 档位下实跑通过。

## CI run 3295 结论(head `0bf84e288`) **一句话**:CI run 3295 = **6 passed / 2 failed**;两处失败均为 **master 既有缺陷**,与本 PR 无因果关系;本 PR 此前唯一的真实门禁红(AGC shell lane 的旧导出断言)已修复并转绿。 ### 本轮失败项与出处 1. **`Backend tests`**(run 3295 / job 19355) - 失败步骤:`cargo test --locked --workspace --exclude spacetime-module --no-fail-fast --manifest-path server-rs/Cargo.toml` - 首个错误:`crates/api-server/src/external_mcp/semantic/tests.rs:33` → `assertion \`left == right\` failed` / `left: 32` / `right: 30` - 归属:master `4b529a895`「新增支付服务接入与订单收银台」(PR #597) 在 `docs/openapi/genarrative-external-v1.openapi.json` 追加了 `/api/external/v1/payment/orders` 与 `/api/external/v1/payment/orders/{orderId}` 两条外部操作,未标 `x-mcp-excluded`,因此经 `external_mcp.rs` 的自动派生进入 MCP 工具表;而 `semantic/tests.rs` 的期望值未同步(`MCP_OPERATIONS.len() == 30`)。**master 自身 run 3268 / job 19139 逐字相同。** 紧随的 `names.len() == 45`(实际 47)亦已过期,同源。 2. **`Repository checks`**(run 3295 / job 19358) - 失败步骤:`npm run check:repository-ci` - 首个错误:`[check:nginx-spa-routes] FAILED - deploy/nginx/genarrative.conf 缺少 SPA 路由: /pay, /profile/payment`(共 15 条诊断,涉及 `deploy/nginx/genarrative.conf`、`deploy/nginx/genarrative-dev-http.conf`、`deploy/container/nginx.conf`) - 归属:同一提交把 `/pay`、`/profile/payment` 加进 `src/routing/activeAppPageRoutes.ts`,但未同步 nginx 模板与 Pingora 网关 SPA 清单。**master 自身 run 3268 / job 19142 相同。** `check:pingora-route-parity` 因 npm 链在该步中断而未执行;同一缺口同样存在于 `server-rs/crates/pingora-gateway/src/main.rs` 的 `MAIN_SPA_PATHS`(12 条 vs 应为 14 条)。 - 边界:本 PR 相对 master 对 `deploy/**`、`src/routing/**`、`server-rs/crates/api-server/src/external_mcp/**` 零差异,可在 master 上独立复现。 ### 本 PR 本轮修掉的门禁红 `AI game creator shell Rust lane 2/2`(run 3295 / job 19353)→ **success**。原用例 `project::export::npm_export_tests::npm_package_contains_only_dist_and_publish_readme` 的期望(仅 3 条目、不含项目根 `assets/**`)与生产行为冲突;其对应的真实回归用例已随一次 master 合并被删除。现已改名为 `npm_package_contains_dist_project_root_assets_and_publish_readme` 并按契约文档口径扩断言,另补回 6 条发布前工程栈/导出用例。 ### 本轮主要内容 - 发布版本标签改为由工程内部版本 `manifest.versions` 条数派生、面板只读;拆除 `projectVersion` 写链路与该手改命令。 - AGC 导出/发布测试回补(含去 HOME 依赖、跳过构建路径)。 - 后台「游戏管理与审核」排版修复,下架流程收敛:安全下架仅保留在游戏管理页的独立面板,审核页只保留版本级动作。 - 平台入口主规范与排障记忆同步(含 `pitfalls.md` 4 条新条目)。 ### 真机核验(非测试替代) 真实 AGC 客户端(WebView2 + CDP)实测发布面板:「项目版本」输入框 `value=4`、`readOnly=true`、`aria-readonly=true`,与 `get_local_game_manifest` 的 `versions.length=4` 一致;面板并列显示「线上最近提交 v6 · 审核中」;面板内可编辑版本号输入框数量为 0;磁盘清单中遗留的 `projectVersion` 键已被抹除。 ### 本机环境项(不经由 CI,避免误读) Windows 本机 `check:git-hooks` 因临时目录 `EBUSY` 失败;AGC rust 分片 runner 会被一个 Windows 阻塞模态用例挂死(Linux CI 不受影响,本地改用等价分块跑)。两者均不经由 CI;本机 cargo 类门禁已在 featureless 档位下实跑通过。
suzmii added 1 commit 2026-10-04 01:18:55 +08:00
回补 AGC 客户端发布与导出路径的机器级覆盖
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m11s
Project CI / Backend tests (pull_request) Failing after 4m21s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m6s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 6m3s
Project CI / Frontend tests (pull_request) Successful in 3m10s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m42s
Project CI / Repository checks (pull_request) Failing after 3m43s
Project CI / Native shell tests (pull_request) Successful in 6m13s
c4b3d22042
master 839051f53(PR #568 退役 AGC 自建 Agent Runtime/CLI)整文件删除了
src-tauri/src/tests/project.rs(当时含 128 个用例),本分支合并 783ca014e 采纳了
这次删除,导致其中覆盖「客户端发布/导出」活代码的断言失去全部引用。本次不复活已删
文件,把同域用例按原断言意图重建在 project/export.rs 的现役测试模块。生产代码未改动。

mod publish_export_tests 本次新增:
- publish_build_plan_prefers_game_subproject_and_requires_dependencies:构建计划优先 game 子工程;
  缺 game/node_modules 时 needs_dependency_install=true,补齐后为 false。
- publish_build_plan_falls_back_to_root_npm_build:game 无 build 脚本时回落到项目根 npm 工程
  (cwd_relative="."、command 取根 build 脚本、不需要装依赖)。
- publish_export_runs_project_build_before_packaging:原型完成后发布先跑项目 npm build 产出
  dist/ 再打包,且 .agent/logs/command.log 必须记录一次 project.verify build。
- publish_export_blocks_build_until_runnable_prototype_is_completed:原型未完成时禁止触发用户
  项目构建(无 build 标记文件、无 build 日志、错误含「首个可运行原型尚未完成」)。
- publish_export_reports_actionable_error_without_entry_or_build_script:缺可玩入口且没有 build
  脚本时失败关闭,错误必须同时给出「还没有可玩入口」与「build 脚本」。
- local_project_export_package_publish_payload_contains_bytes_and_file_digests:发行载荷带
  package_size_bytes、64 位十六进制 sha256 与逐文件清单;条目无 game/ 前缀、含 index.html 与
  exports/README.md(体积/契约)。
- local_project_export_package_list_only_returns_recent_playtest_zips:包列表只返回
  exports/playtest-package-*.zip,按修改时间倒序,忽略非 playtest 文件与非 exports 目录。
- local_project_export_package_list_skips_symlink_packages(cfg(unix)):符号链接试玩包不得列出(安全)。
- local_project_export_package_rejects_symlink_assets(cfg(unix)):assets/ 内符号链接素材必须
  整包拒收,且不得留下试玩包(安全)。
- local_project_export_package_rejects_symlink_runtime_dirs_and_readme(cfg(unix)):README 与
  运行时目录被符号链接顶替时必须拒收(安全)。

同批提交中另含上一轮已重建的 7 条(同一文件):
publish_stack_validation_{accepts_scaffolded_phaser4_vite_project,
reports_actionable_error_for_phaser3,requires_phaser_dependency_and_vite,
reads_semver_ranges_and_lockfile_versions,rejects_projects_without_npm_build_workspace}、
publish_export_skips_build_when_phaser_vite_entry_exists、
built_project_publish_payload_includes_uploaded_assets_and_prefers_dist_assets。

不适用 / 已覆盖:
- publish_export_skips_build_when_playable_entry_exists(原始版本)已由
  publish_export_skips_build_when_phaser_vite_entry_exists 以 Phaser 4 + Vite 语境等价覆盖,不重复。
- 其余域(preview / assets / commands / windows / cli 等)缺口不在本 PR 交付面,未处理。

fixture 适配:unique_project_path 在 HEAD 为私有 fn,改用 crate::tests::canonical_test_tempdir;
随文件删除的 init_existing_html_project_at 与 fake_llm_game_draft 用最小内联 fixture 取代
(内联单文件可玩 HTML + 去掉 npm 工作区脚手架的工程)。
Author
Member

补充:CI run 3297(head c4b3d2204)

  • 结论:run 3297 = 6 passed / 2 failed,失败项与 run 3295 完全同源 —— Backend tests ← crates/api-server/src/external_mcp/semantic/tests.rs:33 期望 30 实际 32;Repository checks ← check:nginx-spa-routes 缺 /pay、/profile/payment;本批引入 = 0。check:pingora-route-parity 仍因 npm 链在前一步中断而未执行(无报错原文,推定同类)。
  • 本轮新增提交:c4b3d2204 补回 AGC 客户端发布/导出路径的 10 条机器级用例(project::export:: 本机 19 passed / 0 failed),CI 用例数 1884 → 1894,两个 AGC Rust lane 均 success。
  • 门禁:base is ancestor of head 满足(origin/master = ccd271572,盯梢期间未推进)。
  • PR 仍为 draft,保持 WIP,待按反馈整理后再转正式评审。
### 补充:CI run 3297(head `c4b3d2204`) - **结论**:run 3297 = **6 passed / 2 failed**,失败项与 run 3295 完全同源 —— `Backend tests` ← `crates/api-server/src/external_mcp/semantic/tests.rs:33` 期望 30 实际 32;`Repository checks` ← `check:nginx-spa-routes` 缺 `/pay`、`/profile/payment`;**本批引入 = 0**。`check:pingora-route-parity` 仍因 npm 链在前一步中断而未执行(无报错原文,推定同类)。 - **本轮新增提交**:`c4b3d2204` 补回 AGC 客户端发布/导出路径的 **10 条机器级用例**(`project::export::` 本机 19 passed / 0 failed),CI 用例数 `1884 → 1894`,两个 AGC Rust lane 均 **success**。 - **门禁**:`base is ancestor of head` 满足(`origin/master = ccd271572`,盯梢期间未推进)。 - PR 仍为 draft,保持 WIP,待按反馈整理后再转正式评审。
suzmii added 1 commit 2026-10-04 09:23:47 +08:00
Merge branch 'master' into feat/game-works-management
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m44s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m31s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m2s
Project CI / Frontend tests (pull_request) Successful in 2m21s
Project CI / Backend tests (pull_request) Successful in 6m47s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m51s
Project CI / Native shell tests (pull_request) Successful in 6m18s
Project CI / Repository checks (pull_request) Successful in 5m5s
8abc35158c
suzmii added 1 commit 2026-10-04 11:27:48 +08:00
Merge remote-tracking branch 'origin/master' into feat/game-works-management
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m3s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m33s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m18s
Project CI / Backend tests (pull_request) Successful in 6m35s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m50s
Project CI / Native shell tests (pull_request) Successful in 6m32s
Project CI / Repository checks (pull_request) Successful in 5m9s
Project CI / Frontend tests (pull_request) Successful in 1m53s
0168aa7bc3
# Conflicts:
#	docs/project-memory/shared-memory/decision-log.md
#	docs/project-memory/shared-memory/pitfalls.md
suzmii added 2 commits 2026-10-04 12:33:14 +08:00
- 改动规则:apps/ai-game-creator-shell/src/styles.css 的 `.game-distribution-publish-panel` 追加 `scrollbar-width: none` 与其 `::-webkit-scrollbar { display: none; }`
- 为什么用 scrollbar-width: none:该抽屉自身就是唯一滚动区(用户口径:这条抽屉里的滚动条太丑);实测隐藏后引擎不再为滚动条预留槽位,内容宽度恒定、无宽度跳变
- 另一条 webkit 规则的必要性:`scrollbar-width` 只覆盖标准路径(Firefox / 新引擎),Chromium / WebView2(AGC 真机)仍需 `::-webkit-scrollbar` 才能隐藏,否则真机上滚动条依旧可见
- 真机实测结论(CDP,WebView2):滚动条布局占位 15px → 0,`clientWidth` 503 → 518,`scrollTopMax` 231 不变,滚轮与键盘仍可滚到底
- 验证命令:`npm run check:encoding`、`git diff --check`
Merge remote-tracking branch 'origin/master' into feat/game-works-management
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m5s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / Backend 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 lane 2/2 (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
ddc3832279
suzmii added 1 commit 2026-10-04 12:37:09 +08:00
作品详情页在非公开状态下不再请求评价接口,封面显示审核状态
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m2s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m16s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 4m49s
Project CI / Backend tests (pull_request) Successful in 7m16s
Project CI / Frontend tests (pull_request) Successful in 3m7s
Project CI / Native shell tests (pull_request) Successful in 6m59s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m40s
Project CI / Repository checks (pull_request) Successful in 5m42s
aad8eb2aba
- useGameReviews 新增第 3 参 publiclyVisible:非公开(game.status !== 'published',含审核中 / 审核未通过 / 未公开 / 已下架)时 loadPage / loadMine / submit 直接 return,不置错误态
- GameReviews 两栏在非公开时渲染既有 PlatformEmptyState「暂无评价」,不出现错误块 / 重试 / 评分失败
- 封面占位文案新增 resolveNonPublicCoverLabel(pending_review → 审核中、rejected → 审核未通过,其余退回作品级文案),样式 .game-detail-cover__pending 落在本域 CSS
- hero 评分与分页在非公开时不渲染
- 已公开(published)行为保持不变
- 新增行为测试:非公开时零请求 + 两栏空态 + 封面文案映射;已公开仍照常发请求
suzmii marked the pull request as ready for review 2026-10-04 12:49:15 +08:00
suzmii added 1 commit 2026-10-04 14:54:22 +08:00
项目版本卡按内部版本序数排序,修正初始版本被排到最后
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (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
3cca4fb99c
- 根因:版本投影的显示顺序走依赖视图、同层按 opaque 资源 id 做字符串排序,而 `version:initial-*` 的字符串序大于 `version:agent-*`,于是初始版本被排到最后(4 个版本读作 2/3/4/1,既与卡面「版本 N」序号冲突,也与「最新版本 = 发布标签」冲突;已落盘坐标 agent-22(0,0) agent-42(228,0) agent-46(0,168) initial-13(228,168) 为证)
- 改法:`ProjectResource` / `ResourceCanvasItem` 增加 `orderIndex`(= 内部版本序数,仅项目版本资源携带),新增 `compareResourceOrder`(先比序键、再回落 opaque id)并替换依赖视图 4 处 `compareStableIdentifier`;类型视图在 mediaType 之后插入序键比较(顺带修掉 ≥10 个版本时「版本 10」被字符串序排到「版本 2」之前的错位)
- 兼容性:不带 `orderIndex` 的其它资源排序结果与落盘坐标逐值不变
- 验证:`npx vitest run apps/ai-game-creator-shell/tests` 199 文件 / 1935 passed / 0 failed;`npm run agc:typecheck` exit 0;`npm run check:encoding` passed;`git diff --check` 干净;真机 CDP 用 Vite 现网真实模块 + 真实 manifest 复算落位:修复前 2→3→4→5→1,修复后 1→2→3→4→5
suzmii added 1 commit 2026-10-04 15:01:13 +08:00
Merge remote-tracking branch 'origin/master' into feat/game-works-management
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m32s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m5s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 3m33s
Project CI / Frontend tests (pull_request) Successful in 3m39s
Project CI / Backend tests (pull_request) Successful in 6m49s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m39s
Project CI / Repository checks (pull_request) Successful in 6m43s
Project CI / Native shell tests (pull_request) Successful in 7m39s
2f6df57ce2
# Conflicts:
#	docs/project-memory/shared-memory/decision-log.md
#	docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md
#	server-rs/crates/api-server/src/modules/game_distribution.rs
#	server-rs/crates/spacetime-client/src/active.rs
#	server-rs/crates/spacetime-module/src/game_distribution.rs
#	src/components/game-distribution/GameDistributionPages.test.tsx
suzmii added 5 commits 2026-10-04 16:39:06 +08:00
- 根因:版本追加只写盘、不发「清单已变」事件,而前端被当作「回合结束刷新」的那次调用实际发生在入队时(useDirectProjectChatController.ts:588-592 紧跟 startTurn 的 finally,await 的只是 enqueue_direct_codex_turn),于是 agent 追加版本后无人重读清单,新卡必须先重开项目才出现(旁证:resource-layouts/dependency.json 里 74 分钟缺该版本,直到重开项目才补齐)
- 修复:版本真正追加成功时才 emit_game_creator_manifest_invalidated(root, "direct-codex.version")(与素材工具桥同口径),订阅侧立刻重读清单
- 版本卡显示顺序:orderIndex(内部版本序数)+ compareResourceOrder,修正初始版本被排到最后(4 版读作 2/3/4/1 → 现为 1..N 单调);不带 orderIndex 的资源排序与坐标逐值不变
- 最新版本卡角标:`最新 · 发布标签 v{N}`(只给 versions 最后一条,N = versions.length = 发布面板取的标签)
- 发布面板文案:「本次发布标签 = 最新内部版本 v{N};agent 再改进一次后,下一次发布将是 v{N+1}」,并保留「平台线上号是平台侧事实、与本标签互不推导」
- 验证:vitest apps/ai-game-creator-shell/tests 1935 passed / 0 failed;cargo check(带编辑器 feature)通过;encoding / typecheck 通过;真机未验(环境重新拉起前无法核验,待补)
- AdminGameReviewsPage.tsx:评价列表加 tableClassName="admin-game-reviews-table",操作列单元格加 admin-game-reviews-actions-cell(与游戏管理页操作列同口径)
- styles/admin.css:新增本页专属规则,操作列 width:1% + white-space:nowrap,动作行 flex-wrap:nowrap 并右对齐,避免「删除 / 查看详情 / 隐藏」被挤到第二行
- 选择器全部框在 .admin-game-reviews-table 内,不影响其它后台页面
- AdminGameDistributionReviewPage.tsx:待审列表只回版本字段,新增 resolveGameMeta 用既有后台作品列表接口按 gameId 反查标题/作者,逐游戏去重并按会话缓存;单个游戏取不到只回落显示 gameId,不阻断审核列表
- 同文件:loadReviews 在拿到 entries 后并行补齐本页 distinct gameId 的元数据
- 同文件:游戏列由单个 gameId 文本改为「游戏名(主行)+ 作者名与 user_id(副行,截断显示,完整值放 title)」
- adminGameDistributionReview.css:以 .admin-game-review-game 网格布局替换 .admin-game-review-game-id,保留窄视口截断与 title 出口
- AdminGameDistributionReviewPage.test.tsx:补 listAdminGameDistributionGames 的 mock 与游戏列表 fixture,断言由 gameId 改为游戏名
去掉与 master 重复的游戏评价页排布实现
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m57s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m42s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m50s
Project CI / Frontend tests (pull_request) Successful in 3m30s
Project CI / Backend tests (pull_request) Successful in 7m0s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m47s
Project CI / Native shell tests (pull_request) Successful in 7m59s
Project CI / Repository checks (pull_request) Successful in 6m43s
aa4d178956
- AdminGameReviewsPage.tsx:删除我们新增的重复 tableClassName(master 已在同一组件上有一份,保留 master 那处),保证同名 JSX 属性只剩一处
- AdminGameReviewsPage.tsx:操作列 td 去掉 className="admin-game-reviews-actions-cell"(该 class 的唯一样式来源已随本提交删除,留着就是死代码)
- styles/admin.css:整段删除我们尾部新增的平行实现(.admin-game-reviews-table th:last-child 与 .admin-game-reviews-actions-cell .admin-action-row 的 width/nowrap/flex-end)
- 保留 master 的评价列表排布体系:.admin-game-reviews-table .admin-status、td:last-child .admin-action-row{flex-wrap:nowrap;justify-content:flex-start} 与 >button{flex-shrink:0}
- 自证:tableClassName="admin-game-reviews-table" 命中 1 处;admin-game-reviews-actions-cell 命中 0 处
suzmii added 2 commits 2026-10-04 18:01:00 +08:00
- resourceProjectionModel.ts:publicationTag 注释改为「值是内部版本序数(versions.length),也就是发布时会提交的那个标签」,并注明卡面只渲染中性的「最新」角标,不再写「发布标签 v{N}」
- GameDistributionPublishPanel.tsx:「项目版本」说明注释写明发布提交的标签是 versions.length(最新内部版本序数),不读任何「选中版本」;画布上的选中/「当前版本」只影响当前版本素材与运行播放哪一版
- index.tsx / styles.css:版本卡角标由「最新 · 发布标签 v{N}」改为中性的「最新」,并换用卡面既有的中性 pill 样式
- gameDistributionPublishPanel.test.tsx:同步旧的角标/文案断言
公开作品详情页不再显示占位作者名「创作者」,按作者 ID 补查真实昵称
Project CI / Backend tests (pull_request) Failing after 30s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m27s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m23s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m15s
Project CI / Repository checks (pull_request) Failing after 33s
Project CI / Frontend tests (pull_request) Successful in 3m59s
Project CI / AI game creator shell web tests (pull_request) Successful in 4m10s
Project CI / Native shell tests (pull_request) Successful in 8m37s
e593236f9b
- useGameAuthorName.ts(新增):useGameAuthorDisplayName —— 回包名是占位词(「创作者」/「未知作者」)或空时,按 author.id 调 GET /api/auth/public-users/by-id/{id} 取 displayName;查询中返回 null(避免先闪占位词),查不到返回空串、不编造名字
- GameDetailPage.tsx:详情页用解析后的作者名装配展示对象(displayGame),替代直接用公开投影里的 author.name
- packages/shared/src/components/GameDetailDisplay/index.tsx:作者名为空时不渲染「由 X 制作」那一行;头像首字改用 Array.from(name)[0](避免 emoji 代理对被截断);作者行补 title 悬浮显示完整名字
suzmii added 2 commits 2026-10-04 18:48:08 +08:00
删除发布面板冗余提示文案
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m58s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m52s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m47s
Project CI / Frontend tests (pull_request) Successful in 3m32s
Project CI / Backend tests (pull_request) Successful in 8m33s
Project CI / Repository checks (pull_request) Successful in 7m6s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m42s
Project CI / Native shell tests (pull_request) Successful in 10m57s
5a651f3eae
- GameDistributionPublishPanel.tsx:删除「项目版本」下的说明段(projectVersionHint 派生逻辑与其 useMemo、以及渲染它的 hint span),面板不再写「发布将使用最新内部版本 v{N}…」「线上最近提交 vN 是平台侧事实…」
- GameDistributionPublishPanel.tsx:删除简介/分类的三态提示文案(「正在根据创作内容生成简介和分类…」/「AI 已根据创作内容生成…」/「已根据创作内容预填…」)及支撑它们的 metadataSuggestionPending、metadataSuggestionReady 两个 state 与请求完成后的置位,保留静默预填行为
- apps/ai-game-creator-shell/src/styles.css:删除随上述提示一起作废的样式(-7 行)
- tests/gameDistributionPublishPanel.test.tsx:同步删除对已废弃提示文案的断言(-15 行)
Author
Member

合并意见(阻塞项评审)

结论:可合 —— 未发现阻塞项。

  • 评审范围:git diff origin/master...HEAD
  • PR head:5a651f3ea
  • master:65514328f

一、范围与结论

  1. 数据丢失/不可逆:diff 内 0 个 D、0 个 R;游戏侧删除是软删(deleted_at,spacetime-module/src/game_distribution.rs 的 delete_game_distribution_game_tx / ensure_game_distribution_game_not_deleted),版本行与冻结资料不可变。⚠️ 后台「删除评价」是硬删(moderation 的 tx.db.game_distribution_review().review_id().delete(...)),但经 git grep origin/master 确认该硬删在 master 已存在(module :691、admin 路由 :243),本 PR 的 module diff 对该处零命中 → 存量行为,非本 PR 引入;审计表 game_distribution_review_moderation_log 不含 score/comment,误删不可恢复。
  2. 安全/鉴权:/admin/api/game-distribution/* 全部 require_admin_auth(:277-281、:378-384);admin-previews 的 token 是 Uuid::new_v4(state.rs:771-793)、TTL 600s(:2495)、读时收敛过期、拒绝带 Cookie 的请求(:2562-2570)、仅放行 pending_review/rejected(:2581-2584);公开面只走 get_public_game_distribution_game,serve_release_asset 先查 public 再校验 published;作者写路径用 claims.user_id 并与模块 owner_user_id 逐条比对。
  3. 契约/Schema:新增字段追加在末尾且有默认值(GameDistributionGame.deleted_at 的 #[default(None::<Timestamp>)] 等),migration.rs 同步,module_bindings 已重生成;/api/external/v1 无变更 → OpenAPI 无需同步。
  4. 不打破 master:0 D/R;被删符号(createGameDistributionPublishKey / readGamePublishAvailability / createSuspendIdempotencyKey / GameShowcase(Thumb) / applyVersionMediaDefaults / useGameReviews 参数变化)逐个反查无残留调用;与 master a1b80ffde/33552d2ed 的重复实现已去干净(tableClassName 只在 shared AdminListPanel 定义一次;admin-game-reviews-actions-cell 全库 0 命中)。
  5. 半成品/死代码:全 diff 扫 TODO/FIXME/HACK = 0;loadVersionRecoveryActions 已接线(MyGamesPage:200-211);抽出的 CATEGORIES/ORIENTATIONS/applyVersionMediaDefaults 已落到新文件并被两页共用。
  6. 回归:2e7409274 / 5a651f3ea 仅文案与死样式/死状态;e593236f9 的 useGameAuthorDisplayName 仅 GameDetailPage:300 一处使用(详情页单请求),排除占位词「创作者」「未知作者」,GameDetailDisplay:214/237 空名不渲染作者行;AdminFormat.normalizeAdminTimestamp 只归一 ^\d+\.\d{1,9}Z$。

二、重要但不阻塞(5 条,含证据与最小修法)

  1. spacetime-module/src/game_distribution.rs:936 GameDistributionCreateVersionInput.version_number 插在中间(非末尾)→ 若 module 与 api-server 非严格同批上线,procedure 入参按位 BSATN 解析会错位(显式失败,非静默脏数据);最小修法:挪到末尾并重生成绑定。
  2. api-server/src/modules/game_distribution.rs:1206-1226(load_owner_game_versions,MAX_LIST_LIMIT=48 见 :87)→ 单作者作品 > 48 时 /my-games/{id} 版本列表为空(有降级、无错数据);放量前补按 game_id 精确列版本的 procedure。
  3. src/services/gameDistributionClient.ts(loadVersionRecoveryActions)→ 作者中心首屏最多约 48 个并发版本回读(已收敛为「每作品仅 latestVersion 且需作者动作」);量级变大时加并发上限或批量接口。
  4. server-rs/crates/api-server/src/modules/game_distribution_release_storage_bootstrap.js + game_distribution.rs:107-112 → 发行/试玩 HTML 前无条件用内存实现覆盖 window.localStorage/sessionStorage:opaque sandbox 下是必要修复,但若发行侧存在真实 origin会把原生持久化顶掉(托管游戏本地存档不跨刷新保留);建议探测式安装或在描述里写明「托管游戏不做持久化」。
  5. docs/project-memory/plans/【实施计划】游戏分发阶段A领域合同-2026-09-19.md:116 仍写「未配置 game-distribution:publish 时默认开放」,与 state.rs:1236-1252 及本 PR 注释相反 → 仅文档陈旧,建议同步。

三、遗留待办(非阻塞,已在描述「八、3」标注)

  1. 发布跟随「当前选中版本」(版本卡无选中态 + 打包与版本无关,需重定义链路);
  2. 后端读时解析作者名(现在前端按 owner_user_id 补查 /api/auth/public-users/by-id/{id});
  3. 公开广场卡片 GameGalleryPage.tsx:114 同根因;
  4. 后台评价硬删不可恢复、审计不含正文(存量行为)。

四、评审边界

本次为静态评审(未跑测试/构建);CI 结果另见该 head 的 run。

不确定项:

  1. 未逐行确认本 PR 是否改动 module 评价审核 tx 的 .delete(按存量处理);
  2. 未确认生产上发行是每游戏独立 origin 还是 opaque iframe;
  3. 未确认 module 与 api-server 是否严格同批上线。
## 合并意见(阻塞项评审) **结论:可合** —— 未发现阻塞项。 - 评审范围:`git diff origin/master...HEAD` - PR head:`5a651f3ea` - master:`65514328f` ### 一、范围与结论 1. **数据丢失/不可逆**:diff 内 **0 个 D、0 个 R**;游戏侧删除是软删(`deleted_at`,`spacetime-module/src/game_distribution.rs` 的 `delete_game_distribution_game_tx` / `ensure_game_distribution_game_not_deleted`),版本行与冻结资料不可变。⚠️ 后台「删除评价」是**硬删**(`moderation` 的 `tx.db.game_distribution_review().review_id().delete(...)`),但经 `git grep origin/master` 确认**该硬删在 master 已存在**(module `:691`、admin 路由 `:243`),本 PR 的 module diff 对该处**零命中** → **存量行为,非本 PR 引入**;审计表 `game_distribution_review_moderation_log` 不含 `score`/`comment`,误删不可恢复。 2. **安全/鉴权**:`/admin/api/game-distribution/*` 全部 `require_admin_auth`(`:277-281`、`:378-384`);`admin-previews` 的 token 是 `Uuid::new_v4`(`state.rs:771-793`)、TTL **600s**(`:2495`)、读时收敛过期、**拒绝带 Cookie 的请求**(`:2562-2570`)、仅放行 `pending_review/rejected`(`:2581-2584`);公开面只走 `get_public_game_distribution_game`,`serve_release_asset` 先查 public 再校验 published;作者写路径用 `claims.user_id` 并与模块 `owner_user_id` 逐条比对。 3. **契约/Schema**:新增字段**追加在末尾且有默认值**(`GameDistributionGame.deleted_at` 的 `#[default(None::<Timestamp>)]` 等),`migration.rs` 同步,`module_bindings` 已重生成;`/api/external/v1` 无变更 → OpenAPI 无需同步。 4. **不打破 master**:0 D/R;被删符号(`createGameDistributionPublishKey` / `readGamePublishAvailability` / `createSuspendIdempotencyKey` / `GameShowcase(Thumb)` / `applyVersionMediaDefaults` / `useGameReviews` 参数变化)逐个反查**无残留调用**;与 master `a1b80ffde`/`33552d2ed` 的重复实现**已去干净**(`tableClassName` 只在 shared `AdminListPanel` 定义一次;`admin-game-reviews-actions-cell` 全库 0 命中)。 5. **半成品/死代码**:全 diff 扫 `TODO/FIXME/HACK` = **0**;`loadVersionRecoveryActions` 已接线(`MyGamesPage:200-211`);抽出的 `CATEGORIES/ORIENTATIONS/applyVersionMediaDefaults` 已落到新文件并被两页共用。 6. **回归**:`2e7409274` / `5a651f3ea` 仅文案与死样式/死状态;`e593236f9` 的 `useGameAuthorDisplayName` 仅 `GameDetailPage:300` 一处使用(详情页单请求),排除占位词「创作者」「未知作者」,`GameDetailDisplay:214/237` 空名不渲染作者行;`AdminFormat.normalizeAdminTimestamp` 只归一 `^\d+\.\d{1,9}Z$`。 ### 二、重要但不阻塞(5 条,含证据与最小修法) 1. `spacetime-module/src/game_distribution.rs:936` `GameDistributionCreateVersionInput.version_number` 插在**中间**(非末尾)→ 若 module 与 api-server 非严格同批上线,procedure 入参按位 BSATN 解析会错位(显式失败,非静默脏数据);最小修法:挪到末尾并重生成绑定。 2. `api-server/src/modules/game_distribution.rs:1206-1226`(`load_owner_game_versions`,`MAX_LIST_LIMIT=48` 见 `:87`)→ 单作者作品 > 48 时 `/my-games/{id}` 版本列表为空(有降级、无错数据);放量前补按 `game_id` 精确列版本的 procedure。 3. `src/services/gameDistributionClient.ts`(`loadVersionRecoveryActions`)→ 作者中心首屏最多约 48 个并发版本回读(已收敛为「每作品仅 latestVersion 且需作者动作」);量级变大时加并发上限或批量接口。 4. `server-rs/crates/api-server/src/modules/game_distribution_release_storage_bootstrap.js` + `game_distribution.rs:107-112` → 发行/试玩 HTML 前无条件用内存实现**覆盖 `window.localStorage`/`sessionStorage`**:opaque sandbox 下是必要修复,但若发行侧存在**真实 origin**会把原生持久化顶掉(托管游戏本地存档不跨刷新保留);建议探测式安装或在描述里写明「托管游戏不做持久化」。 5. `docs/project-memory/plans/【实施计划】游戏分发阶段A领域合同-2026-09-19.md:116` 仍写「未配置 `game-distribution:publish` 时默认开放」,与 `state.rs:1236-1252` 及本 PR 注释相反 → 仅文档陈旧,建议同步。 ### 三、遗留待办(非阻塞,已在描述「八、3」标注) 1. 发布跟随「当前选中版本」(版本卡无选中态 + 打包与版本无关,需重定义链路); 2. 后端读时解析作者名(现在前端按 `owner_user_id` 补查 `/api/auth/public-users/by-id/{id}`); 3. 公开广场卡片 `GameGalleryPage.tsx:114` 同根因; 4. 后台评价**硬删不可恢复**、审计不含正文(存量行为)。 ### 四、评审边界 > 本次为**静态评审**(未跑测试/构建);CI 结果另见该 head 的 run。 不确定项: 1. 未逐行确认本 PR 是否改动 module 评价审核 tx 的 `.delete`(按存量处理); 2. 未确认生产上发行是每游戏独立 origin 还是 opaque iframe; 3. 未确认 module 与 api-server 是否严格同批上线。
suzmii added 1 commit 2026-10-04 19:44:13 +08:00
同步发布面板测试:删除已废弃的「按首版」提示断言
Project CI / AI game creator shell Rust crates (pull_request) Successful in 6m9s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 7m26s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 8m16s
Project CI / Backend tests (pull_request) Successful in 8m52s
Project CI / Frontend tests (pull_request) Successful in 2m58s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m59s
Project CI / Native shell tests (pull_request) Successful in 7m10s
Project CI / Repository checks (pull_request) Successful in 5m26s
42364befb1
- tests/gameDistributionPublishPanel.test.tsx:删除「已有绑定时进入更新模式,回填线上资料并按派生项目版本提交原 gameId」用例中对 /本次发布按首版 v1。/ 的断言(该文案随 5a651f3ea 删除 projectVersionHint 一并下线,属遗漏同步)
- 版本派生本身仍由同用例的「项目版本」只读值 1、提交参数 versionNumber=1 覆盖,断言能力未削弱
suzmii merged commit 29f7d157cd into master 2026-10-04 20:03:38 +08:00
suzmii deleted branch feat/game-works-management 2026-10-04 20:03:38 +08:00
Sign in to join this conversation.