Commit Graph

3279 Commits

Author SHA1 Message Date
suzmii 8d362d718e fix(游戏共创): 把 read_public_game_cover_preview 登记进 native-only 白名单
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m37s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m38s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m52s
Project CI / Frontend tests (pull_request) Successful in 3m2s
Project CI / Backend tests (pull_request) Successful in 7m55s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m58s
Project CI / Repository checks (pull_request) Successful in 6m1s
Project CI / Native shell tests (pull_request) Successful in 7m42s
CI 6/8 里的两条红(`Native shell tests`、`AI game creator shell web tests`)同一根因:`5798551b2`
新增的 Tauri 命令 `read_public_game_cover_preview` 没登记,`check-config.mjs` 的
「App invoke 或显式 native-only 白名单」校验因此失败:

```
Error: AI game creator shell App invoke or explicit native-only allowlist missing commands:
read_public_game_cover_preview
```

为什么静态扫描采不到:这条命令名由渲染层以常量 `COVER_COMMAND` 传给**注入的** invoke
(`src/features/platform-fork/platformForkCover.ts`,注入是为了让封面解析能单测),扫描只认
字面量调用点。按 `apps/ai-game-creator-shell/scripts/check-config.mjs:141` 起加了条目与注释,
注释写明「为什么采不到」以及同批另外两条命令为什么不需要登记。

同批新增命令复核(都不需要登记,都是字面量调用点):
- `create_local_project_from_platform_game` —— `src/features/platform-fork/usePlatformFork.ts`;
- `list_platform_game_catalog` —— `src/features/platform-fork/platformForkCatalog.ts`;
两条命令若漏登记,`check-config` 的同一断言会以同样的方式报出来;现在门禁绿即证明这两条被扫到。
本轮没有新增路由/权限清单(capabilities 只管插件 JS 命令,`invoke` 类命令不走它)。
2026-10-06 13:21:28 +08:00
suzmii 2a04f293b1 Merge remote-tracking branch 'origin/master' into feat/game-fork
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m25s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m18s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m31s
Project CI / Frontend tests (pull_request) Successful in 2m38s
Project CI / Native shell tests (pull_request) Failing after 2m52s
Project CI / AI game creator shell web tests (pull_request) Failing after 1m29s
Project CI / Backend tests (pull_request) Successful in 7m44s
Project CI / Repository checks (pull_request) Successful in 5m37s
2026-10-06 12:24:10 +08:00
suzmii 5798551b21 feat(游戏共创): 共创列表补上真实封面(有界 data URL,失败回退首字占位)
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
- 新命令 `read_public_game_cover_preview(objectKey)`:复用发布面板封面那套链路
  (`read-url` 换签 → `resolve_canvas_resource_download_with_limit_route_and_fence` 有界下载 →
  `cover_preview_data_url`),返回**有界 data URL**。
  为什么不返回签名地址让渲染层 `<img src>`:AGC 既有约定是「渲染层不自行拼 read-url、不接触对象键
  与 bearer token、也不让 WebView 直连签名地址」(`commands.rs` 里同一口径的注释),因此沿用
  data URL 方案——顺带免掉签名过期与 CSP 白名单两个问题。
  对象键做最小校验(非空、≤512、不含 `..`);失败如实返回 `Err`,由调用方回退占位。
- 渲染层 `platformForkCover.ts`:会话内缓存 + 并发去重。
  · 成功:会话内一直复用(data URL 自身不过期);
  · 失败:缓存 60 秒(沿用网页端失败缓存窗口),避免同一张坏图在每张卡片上反复重试;
  · 提供 `clearCoverPreviewCache()` 供换号时清空(换号后旧封面可能已无权访问)。
- `usePlatformForkCovers` 钩子按当前列表批量解析;卡片上有封面就 `<img>`(`object-cover`),
  没有封面 / 换签失败 / 超限一律**保留原来的首字占位 + `coverColor` 底色**(降级逐条测到)。

测试:新增一条覆盖三种情形——有封面(断言 `src` 是命令返回的 data URL)、换签失败(保留占位、
不出现第二张 `<img>`)、没有 `coverObjectKey`(不发换签请求)。
2026-10-06 11:56:34 +08:00
suzmii 7b8c3153b1 feat(游戏共创): 首页内联 Fork 面板改为侧边栏「共创」页
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
用户看了真机截图判定首页那张内联卡片太丑,撤掉并改成独立一页。

- 删掉首页内联面板:`src/view/home/PlatformGameForkSection.tsx`(整文件)与首页里的渲染块、两个
  专属 props(`onPlatformGameProjectCreated`)及其 import(该 prop 一路从 shell 传下来,一并清掉,
  不留死代码);首页恢复成「最近项目 + 模板库推荐」。旧组件测试文件
  `tests/platformGameFork.test.tsx` 删除,其中仍有价值的解析/分类用例抽成
  `tests/platformGameForkModel.test.ts`(纯模型,不依赖组件)。
- 侧边栏新增「共创」:`LauncherView` 加 `co-creation`,`view/layout.tsx` 的 rail 加一个按钮
  (icon 用仓库既有的 lucide-react,选 `GitFork` 对应「像 git fork」的口径;`aria-label`/`title`
  都是「共创」,与既有 rail 项的悬停提示方式一致)。
- 新页 `src/view/co-creation/index.tsx`:
  · 数据源是平台公开目录(匿名可读):新增原生命令 `list_platform_game_catalog(limit, cursor)`
    (不带 Bearer——带鉴权头会把「匿名可读」变成依赖登录态;仍取会话只为拿 base URL;limit
    与服务端同口径:缺省 20 / 上限 50,用 `url` 拼查询串避免手拼游标)。
  · 只保留支持共创的:`forkAuthorization !== 'forbidden'`(字段缺省按 forbidden)。
  · 排序:只按接口顺序(新 → 旧);推荐算法留 TODO,替换点在 `loadForkableGames`
    (UI 只消费它的返回值)。
  · 翻页:最多 3 页 / 150 条,扫到 12 个可 Fork 作品就提前停;被上限截断时页头如实标注
    「已检查最新 N 个作品(M 页,最多 3 页)」。理由写在常量注释里:目录是新→旧的、可 Fork
    的作品可能稀疏,3 页足够填满一屏,同时把最坏请求数与耗时钉住。
  · 卡片:与首页「最近项目」同一套视觉语言(同尺寸圆角卡、首字占位块用作品的 `coverColor`),
    展示标题 / 作者 / 类型 / 更新时间,卡片内一个「Fork」按钮——**一步可达**,点击即走取件建项。
  · 空态:扫完仍没有可 Fork 作品时给明确文案(而不是空白);加载态 / 失败态(含重试)照既有写法。
- 「填详细内容」随页搬走:原来的「输入作品 ID 或链接」输入框放到列表上方,解析仍用
  `parsePlatformGameId`(与 deep link 完全同一份,没有第二套)。
- 提交路径只留一份实现:新增 `usePlatformFork` 状态机,卡片按钮与粘贴输入共用它
  (取件、失败分类、加载态、进项目与埋点都是同一段代码;`busy` 用 ref 挡同一 tick 的重复提交)。
- deep link:`genarrative://fork?gameId=…` 现在切到「共创」页并预填输入框(仍**不自动下载**),
  不再指向首页内联面板;正停在项目工作区时行为不变(不强行切走,请求留着)。

测试:新增 `tests/coCreation.test.tsx`(12 条:目录模型过滤/提前停/页数上限、列表渲染与过滤、
点卡片 Fork 的参数与「点击前不发请求」、粘贴链接同一解析、非法输入本地拦截、空态、失败态与重试、
深链预填且不自动下载、深链错误原因、取件失败分类);`tests/platformForkDeepLink.test.tsx` 收窄为
事件解析 + 订阅(预填行为改由共创页测试覆盖,不重复断言);`tests/appSurface/home.suite.ts` 增两条
外壳级回归:首页不再出现内联面板(标题与按钮都不在)、侧边栏「共创」可切换并落在共创页;
Rust 增一条 `catalog_limit_clamps_to_server_range`。
2026-10-06 11:47:20 +08:00
suzmii fdf6424e42 递增三个已更新模板的 templateVersion
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 6m37s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m52s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m52s
Project CI / Frontend tests (pull_request) Successful in 3m24s
Project CI / Backend tests (pull_request) Successful in 7m36s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m43s
Project CI / Repository checks (pull_request) Successful in 6m46s
Project CI / Native shell tests (pull_request) Successful in 9m7s
- phaser-2d-starter / threejs-3d-starter / blank-3d-scene 的 meta.json templateVersion 0.1.1 → 0.1.2
- 解除发布脚本对「同 templateVersion 的 ZIP 内容变化」的 fail-closed 守卫,其余字段一个字未动
2026-10-06 11:09:11 +08:00
suzmii 7d342856fa Merge pull request '修复运行页刷新按钮不真正重载' (#640) from fix/run-preview-refresh-reload into master
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 7m7s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 6m4s
Project CI / AI game creator shell Rust crates (push) Successful in 5m19s
Project CI / Frontend tests (push) Successful in 4m25s
Project CI / Backend tests (push) Successful in 9m6s
Project CI / AI game creator shell web tests (push) Successful in 2m42s
Project CI / Repository checks (push) Successful in 6m59s
Project CI / Native shell tests (push) Successful in 11m3s
Reviewed-on: http://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/640
2026-10-06 10:59:23 +08:00
k88936 796cf9843c Merge remote-tracking branch 'origin/master' into feat/pricing-plan
Project CI / AI game creator shell Rust crates (pull_request) Successful in 6m0s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m43s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m42s
Project CI / Frontend tests (pull_request) Failing after 1m16s
Project CI / Backend tests (pull_request) Successful in 8m51s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m34s
Project CI / Repository checks (pull_request) Successful in 5m34s
Project CI / Native shell tests (pull_request) Successful in 7m18s
# Conflicts:
#	docs/project-memory/shared-memory/decision-log.md
2026-10-06 10:14:15 +08:00
k88936 febbdd59d5 Merge branch 'feat/pricing-plan-fix' into feat/pricing-plan 2026-10-06 10:12:41 +08:00
suzmii 562549c982 refactor(后台): 共创主题改用共享契约类型 + 后台成员名单接口
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (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 lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
1) 类型去重:`api/adminGameThemeTypes.ts` 不再本地定义任何载荷,改成对
`packages/shared/src/contracts/gameDistribution` 的**纯透传**(相对路径导入,不走包名——仓库根的
`node_modules/@genarrative/shared` 软链指向主工作树,主题契约只在本分支上,走包名会拿到缺类型的
旧副本,实测 TS2724)。页面与 api 客户端改用契约原名(`GameDistributionAdminTheme` 等),
只保留一个后台独有的查询值别名 `AdminThemeStatusFilter = GameDistributionThemeStatus | 'all'`
(`all` 是接口查询白名单取值,不是主题状态本身,没有进契约)。删除重复定义后只剩一份真相。

2) 成员面板改用 `GET /admin/api/game-distribution/themes/{themeId}/members?limit=&cursor=`:
- 草稿 / 归档主题也能读到成员名单(旧做法借公开投影,对未发布主题 404,看不到名单)——公开投影
  那条路(`getPublicGameDistributionTheme`)整体删掉,不留两套读法。
- 每行展示 rootGameId / 标题(游戏行不存在时为「(游戏行不存在)」)/ 排序 / 挂载时间 +
  可见性徽标:`visible` 与 `visibility` 按服务端事实**分别展示、互不推导**——
  「公开可见」;「已公开,但无公开版本」(`visible=false` + `visibility=published`,刻意要让人
  看出来的异常);「作品未公开」;「作品已下架」;「作品已删除」;「游戏行不存在」。
- 分页:每页 20(上限 50,由 api 客户端按服务端口径夹住),`nextCursor` 驱动「加载更多成员」;
  页脚显示「成员行总数 N;已加载 M 条」(`totalMembers` 不受分页影响,不与 `members.length` 互相推导)。
- 增删成员后**重读第一页**而不是本地删行(游标基于排序,本地删会让后续翻页错位);
  读取失败如实报错(如非法游标 400),不渲染成「还没有成员」。

测试(10 条,含新增/改写 4 条):草稿主题也能读到名单并逐条移除(移除后重读第一页)、
「已公开但无公开版本」与其它不可见原因分别展示、游标加载更多(末页按钮消失)、
读取失败如实报错不显示空名单。
2026-10-06 04:34:29 +08:00
suzmii e401963d3a fix(游戏共创): 非法游标回归稳定码 THEME_INVALID_CURSOR(契约码此前在 HTTP 面不可达)
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (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 lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
端到端实测(54 项里唯一红的那条):`GET /api/game-distribution/themes?cursor=abc` 回 400,但
`error.code = "BAD_REQUEST"`——技术方案 §3.4 与主题 e2e 脚本承诺的稳定码 `THEME_INVALID_CURSOR`
在 HTTP 面上拿不到,客户端只能去匹配中文文案。

根因:`map_spacetime_error` 的 `THEME_` 分支前置条件是「消息含 `THEME_`」,而模块侧游标解析只回
中文串「主题列表游标格式无效」⇒ 落兜底分支成 400 + 通用 `BAD_REQUEST`;契约常量与那条映射分支
因此是死代码。且 api-server 原有单测**明确要求**文案不含 `THEME_`(口径留了两套)。

口径二选一,选**让码可达**(模块产出前缀),删掉「要求不含 `THEME_`」的断言:

- `module-game-distribution/src/errors.rs`:新增 6 个主题码常量
  `GAME_DISTRIBUTION_THEME_{NOT_FOUND,BAD_REQUEST,INVALID_CURSOR,IDEMPOTENCY_CONFLICT,MEMBER_NOT_ROOT,MEMBER_GAME_NOT_FOUND}_CODE`,
  并把 `Display` 从字面量改为**复用同一批常量**(消灭「常量改了、`Display` 没改」这类只有真栈才发现的漂移)。
- `theme.rs`:`parse_game_distribution_theme_cursor` 产出 `THEME_INVALID_CURSOR: 主题列表游标格式无效`;
  文档注释更新为「只保留 `FORK_` 这个排在 `THEME_` 分支之前的子串禁忌」(其余子串已抢不到)。
- `lib.rs`:导出新增的 6 个码常量。
- 测试:
  · `domain.rs::theme_errors_are_prefixed_with_their_machine_code` 改为**枚举全部 6 个主题码**(含唯一
    不走领域变体的游标路径——正是当初漏掉它的原因),并加「任何新增码都必须进这张表」的覆盖完整性断言;
  · `theme.rs::invalid_cursor_message_stays_in_the_bad_request_bucket` 增加「必须以稳定码开头」;
  · api-server 新增 `theme_error_codes_are_reachable_from_module_messages`:用**模块真实产出的消息**
    逐码断言 `(状态码, 稳定码)` 可达,并比对模块常量与 `shared-contracts` 常量是同一组字符串;
  · api-server `theme_list_invalid_cursor_maps_to_bad_request` 改为断言映射出 `THEME_INVALID_CURSOR`,
    只把 `FORK_` 留在禁忌列表里(并写明理由)。

门禁:`cargo test -p module-game-distribution` **100 passed**;`cargo test -p api-server game_distribution`
**86 passed**;`cargo check --all-targets` 0;DTO parity 58 组 / 10 构建器;`check:encoding` 0;
`cargo fmt --all -- --check` 0;`git diff --check` 0。
2026-10-06 03:50:05 +08:00
suzmii c3030eddba chore(游戏共创): 收尾清掉最后一条旧口径注释(成品包只作可玩参考 → 生成脚手架 + 参考副本)
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 Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (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
2026-10-06 01:06:20 +08:00
suzmii f94946ef8e feat(游戏共创): 注册并处理 Fork 深链 genarrative://fork?gameId=…
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
冻结约定:`genarrative://fork?gameId=<gameId>`,同时接受 `genarrative://fork/<gameId>`。

方案(用官方两个插件,不手搓单实例与注册表):
- `tauri-plugin-single-instance`(开 `deep-link` feature)**第一个注册**:Windows/Linux 上深链是
  「带 URL 启动第二个进程」,该插件把第二个实例的 argv 转交给已有实例,并(feature 生效时)
  交给 deep-link 插件发事件——否则用户点第二次链接会再开一个窗口。macOS 上它用 Unix socket
  做同样的收口(系统本身也只会有一个 .app 实例)。
- `tauri-plugin-deep-link`:`tauri.conf.json > plugins.deep-link.desktop.schemes = ["genarrative"]`。
  · macOS:打包器按该配置往 `Info.plist` 注入 `CFBundleURLTypes`(插件 `config.rs` 里那句
    `// Used in tauri-bundler` 是代码级证据),运行时由系统把 URL 交给已运行的 .app。
  · Windows:运行时 `register_all()` 写 `HKCU\Software\Classes\genarrative`(`URL Protocol` 标记 +
    `DefaultIcon` + `shell\open\command`,不需要管理员);安装器侧同样按该配置注册。
  · Linux:运行时写用户级 `applications/<exe>-handler.desktop` 并调 xdg-mime(AGC 未以此平台分发,
  但仍走同一条运行时路径)。
- 冷启动:插件在插件初始化阶段就解析 argv 并暂存,而应用 `setup` 晚于插件,因此
  `initialize_fork_deep_link` **先取 `get_current()`**、再 `on_open_url` 订阅后续链接(漏了前者会
  丢冷启动那一次)。
- 收到 URL 后:聚焦主窗口(unminimize + show + set_focus)→ 发 `game-fork-deep-link` 事件
  `{ gameId | message }` → 渲染层把请求存进 store 并切回首页;**不自动下载**,用户按
  「Fork 到我的项目」才走与手工输入完全相同的提交路径。正停在项目工作区时不强行切走
  (避免把用户从进行中的项目里踢出来),请求留在 store 里等用户回到首页。
- 非法链接:解析出可读原因(空链接 / 非 genarrative 方案 / 非 fork 形式 / 缺 gameId / gameId 不合法)
  一并聚焦窗口并交给渲染层展示,不做静默失败。

测试:`fork_game_id_from_deep_link` 的合法(两种形式、大小写、多余参数、game_id/id 别名)与
非法(空、错方案、错形式、缺 gameId、`../escape`、URL 编码斜杠、非 URL)各一组;`gameId` 形状
判据与取件路径共用(`is_safe_fork_game_id`);TS 侧覆盖载荷解析、订阅映射、深链预填后**不自动
下载**、非法链接展示原因且不请求。
2026-10-06 01:05:04 +08:00
suzmii 4cf00ac07d refactor(游戏共创): Fork 口径收敛为「把整个工程复制到你的项目里继续改造」
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
产品裁定:不再对外解释「可玩参考 + 素材 / 不能一键复刻工程 / 需自建合规工程」那套口径。
统一一句话:**Fork = 把整个工程复制一份到你的项目里继续改造(与 git fork 同理)**,动作名统一
叫 Fork。必要告知只保留一句:开启共创并上传工程时,整个工程(含素材与文档)会对他人可见,
且不可撤销。

- 入口(首页):`从平台作品 Fork` + 角标 `Fork`,说明压成一句「把平台上的作品整个工程复制到
  你的项目里继续改造(像 git fork)。输入要 Fork 的作品 ID 或作品链接即可。」;按钮
  `Fork 到我的项目`、加载态「正在 Fork:下载、校验并创建项目…」;成功态只留
  「已创建项目《X》,Fork 自平台作品 <gameId>(来源已记录在 …fork-source.json)」,
  删掉按取件形态分岔的长句。
- 发布面板:授权区只留一句「授权非「禁止共创」即允许他人 Fork 你的作品;开启共创并上传工程时,
  整个工程(含素材与文档)会对他人可见,且不可撤销。」;确认项压成一句
  「我已确认工程里没有不愿公开的内容,同意随本次发布公开整个工程(含素材与文档);一经发布
  不可撤销。」,其后一行写「默认已勾选,可随时取消;不勾选则本次不上传工程源码。」
- 错误与进度文案:取件失败四态改为 Fork 措辞(`无法 Fork` / `该作品当前不能被 Fork(未公开、
  已下架或没有公开版本)`),读取/下载/响应类错误改为 `读取 Fork 信息失败` / `下载 Fork 内容失败`,
  超限提示改为「Fork 内容超过客户端下载上限,无法完成」;「未上传工程源码」提示改为
  「他人 Fork 时只能拿到平台已发布的成品」;默认项目名前缀 `改编项目` → `Fork 项目`;
  记录标签 `项目改编来源记录` → `项目 Fork 来源记录`。
- 实现事实(成品包形态的脚手架 + `reference/<gameId>/`)保留在 Rust 文档注释里,不再作为对外
  表述;`collect_project_bundle_files` 等实现注释不动。
- 测试:入口用例改为断言一句话口径与「Fork 自平台作品」并断言旧的解释性表述已消失;面板用例
  断言新的简短告知与「默认已勾选,可随时取消;不勾选则本次不上传工程源码」;错误文案断言同步。
2026-10-06 00:55:53 +08:00
suzmii bdcefe91d1 Merge remote-tracking branch 'origin/master' into feat/game-fork
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m31s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m20s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m3s
Project CI / Frontend tests (pull_request) Successful in 2m54s
Project CI / Backend tests (pull_request) Successful in 7m36s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m26s
Project CI / Repository checks (pull_request) Successful in 6m25s
Project CI / Native shell tests (pull_request) Successful in 9m34s
# Conflicts:
#	deploy/container/nginx.conf
#	deploy/nginx/genarrative-dev-http.conf
#	deploy/nginx/genarrative.conf
#	server-rs/crates/api-server/src/modules/game_distribution.rs
#	src/components/game-distribution/GameDetailPage.tsx
#	src/components/game-distribution/GameDistributionPages.test.tsx
#	src/components/platform-entry/PlatformEntryActiveFlowShell.tsx
2026-10-06 00:19:40 +08:00
k88936 d917d2f4d1 修复(AGC模型): 会员到账后主动刷新模型目录
- confirmNativeRechargePayment 确认订单为 paid 且 kind=membership 时调用 notifyLlmConfigChanged
- 保留 applyCatalog 的 revision 门控不变,由配置变更事件重置已应用 revision 并重新读取
- 补「revision 不变但账号档位变化时,显式通知必须重新应用」的回归测试
2026-10-05 20:22:43 +08:00
suzmii 386fe4b64f Merge remote-tracking branch 'origin/master' into fix/run-preview-refresh-reload
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m10s
Project CI / Native shell tests (pull_request) Failing after 1m6s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 5m1s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m21s
Project CI / Frontend tests (pull_request) Successful in 2m21s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m32s
Project CI / Backend tests (pull_request) Successful in 7m35s
Project CI / Repository checks (pull_request) Successful in 5m52s
2026-10-05 19:17:50 +08:00
suzmii 96859666ff Merge pull request 'AGC 运行画面点选:canvas 玩法上识别 Phaser 4 / three.js 的已登记素材(#612)' (#624) from feat/agc-runtime-picking-engines into master
Project CI / AI game creator shell Rust crates (push) Successful in 5m29s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 7m5s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 6m28s
Project CI / Backend tests (push) Successful in 9m14s
Project CI / Frontend tests (push) Successful in 4m4s
Project CI / AI game creator shell web tests (push) Successful in 3m36s
Project CI / Repository checks (push) Successful in 7m37s
Project CI / Native shell tests (push) Successful in 10m32s
Reviewed-on: http://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/624
2026-10-05 19:16:03 +08:00
k88936 8788c47a97 修复(AGC模型): 锁定模型项不再进入 Tab 序列
- 去掉锁定项的 tabIndex,原因改由 aria-label 与 hover 提示暴露,避免键盘停在不可选项
- 移除锁定项失效的 :focus-visible 样式与旧注释
- 更新单测:断言锁定项不可 Tab 聚焦且 aria-label 带原因
2026-10-05 18:59:57 +08:00
k88936 9a00700447 修复(AGC模型): 添加协议字段并确保无可用模型时 unavailableModels 返回空数组
Project CI / Backend tests (pull_request) Failing after 1m3s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m16s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m23s
Project CI / Frontend tests (pull_request) Failing after 1m28s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m35s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m56s
Project CI / Native shell tests (pull_request) Successful in 9m33s
Project CI / Repository checks (pull_request) Successful in 7m9s
2026-10-05 18:51:53 +08:00
suzmii df221f4eb9 收口评审 P2:点选条款限定引擎档、对象名上限入边界、素材 id 格式写入 skill
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m29s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m6s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m50s
Project CI / Frontend tests (pull_request) Successful in 3m26s
Project CI / Backend tests (pull_request) Successful in 7m48s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m3s
Project CI / Repository checks (pull_request) Successful in 7m15s
Project CI / Native shell tests (pull_request) Successful in 9m30s
- 功能说明第 8 条「命中区域裁剪在画布内」限定为引擎档,并说明 DOM 档仍是元素矩形;证据表对应行同步对齐
- 功能说明「边界与非目标」新增一条:引擎档对象名超过 40 字符按取不到处理(有意保留),宿主侧标签上限另为 120
- SKILL.md「运行画面点选契约」第 3 条补一句:素材 id 不含空白与路径分隔符(localAssetId 由客户端生成)
- skill-pack 指纹同步(agc-web-game-development version 2026-08-26.42 与 sha256)
2026-10-05 18:31:59 +08:00
suzmii 364b1aa342 Merge remote-tracking branch 'origin/master' into feat/agc-runtime-picking-engines
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
- 冲突解决(3 处):
  - agc-game-production-workflow/SKILL.md:双方都保留——第 4 条用本分支版本(含「运行画面点选契约」指针),第 5 条用 master 的新构建验证口径
  - agc-skills/manifest.json:先取 master 侧,再用 `agc:skill-pack:sync` 按合并后内容重新生成 version 与指纹(2026-08-26.41),`skill-pack:check` 通过
  - pitfalls.md:两侧新增条目全部保留(按日期倒序:本分支 10-05 / 10-04 条目在前,master 的 10-04 / 10-03 条目紧随,未改动任一方内容)
- 无冲突但人工核对:`agc-web-game-development/SKILL.md`(本分支「运行画面点选契约」小节 + master 内容都在)、
  `index.tsx`(我们的 `handleRuntimeInspectSelection` 回调体逐字不变,master 新增内容都在)
- 桥脚本 sha256 未变(9513020cfffa79128fb6355d44cdaabe666eefecbd96b7e807b15d2c4601bf76),真机证据对应字节不变
2026-10-05 18:25:49 +08:00
k88936 b8309eb3ae 重构(后台金额): 抽出统一的元金额格式化
- shared AdminFormat 新增 formatAdminCurrencyCents(分 → ¥x.xx)并从 components 导出
- AdminUserDetailDialog / AdminMembershipPlanPage / AdminRechargeOrderPage / AdminRechargeProductPage 删除各自重复的 formatMoney/formatPrice
- 补充 formatAdminCurrencyCents 单测,避免后台各页面金额格式漂移
2026-10-05 18:12:22 +08:00
suzmii d7c4f82d7d 修复自查发现的门禁与体验问题:格式、超时态语义、压缩 CPU 边界
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m48s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m3s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m33s
Project CI / Frontend tests (pull_request) Successful in 3m24s
Project CI / Backend tests (pull_request) Successful in 7m29s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m55s
Project CI / Repository checks (pull_request) Successful in 6m33s
Project CI / Native shell tests (pull_request) Successful in 9m0s
- 新增 Rust 测试补齐 cargo fmt;ESLint 按仓库约定收口:常量与解析函数拆到 platformGameLoadingSurfaceModel.ts,删除 GAME_PLAY_STARTUP_TIMEOUT_MS 常量别名(测试直接用共享常量)
- 共享加载面新增 stalled:宿主判定等待不再推进时停掉进度动画并把 aria-busy 置回 false(去掉与 role=status 重复的 aria-live)
- 后台试玩超时时传入 stalled,避免「一边转圈一边说超时」
- Accept-Encoding 权重参数名改为大小写不敏感(RFC 9110 §12.5.3),GZIP;Q=0 视为拒绝并补用例
- 发行资源压缩分级:≥2 MiB 改用 level 1(zlib 端实测约 1/3 耗时、压缩比差约 3%),小文件仍用 level 6
- 文档:主规范补压缩与条件请求契约(并写明 60 秒窗口与撤销窗口不放宽)、nginx README 修正 Pingora 压缩关闭时的口径、pitfalls 补 CPU 边界与措辞修正
2026-10-05 18:02:48 +08:00
k88936 6738cf1aa9 Merge remote-tracking branch 'origin/master' into feat/pricing-plan
# Conflicts:
#	docs/project-memory/shared-memory/decision-log.md
2026-10-05 18:00:09 +08:00
k88936 8009a70bb1 测试(AGC模型): 目录透传用例去掉过期的映射断言
- loadClientLlmModels 已改为直接透传 Rust typed command 结果
- 用例改名为透传断言,不再期望渲染层补默认 agentMode(该逻辑已下沉到 Rust)
2026-10-05 17:42:46 +08:00
k88936 7dc056651c 修复(后台用户详情): 非会员不展示占位账期
- 账期仅在 membership.status === 'active' 时展示,否则显示 -
- 避免从未订阅用户显示“月付 第 1/1 期”被误读为正在计费
2026-10-05 17:38:01 +08:00
k88936 07cf7443da 重构(后台契约): 会员变更类型复用后端生成 token
- AdminMembershipOrderChangePayload.changeKind 改用 ProfileMembershipChangeKindToken
- 去掉手写的 'purchase' | 'upgrade' 联合,避免与后端 token 漂移
2026-10-05 17:37:12 +08:00
k88936 9707b74002 修复(后台会员档位): 列表加载时按 rank 排序
- refreshPlans 复用 sortPlanEntries,首屏顺序与保存后一致
- 避免加载态与保存态列表顺序不一致,与档位列“按升级基准 rank”的说明对齐
2026-10-05 17:35:18 +08:00
k88936 92a8fa1b66 重构(共享导出): 会员商品 id helper 提升为公共导出
- packages/shared/src/index.ts 导出 resolveMembershipProductId
- useAccountWallet 改从 @genarrative/shared 公共入口引入,去掉对弹层私有文件结构的深路径依赖
2026-10-05 17:34:27 +08:00
suzmii 10d1fcbc5f fix(游戏共创): 工程源包校验器对抗性补强(P0-a/b/c + 执行级交叉证据)
对抗性复核(`local://verify-m2b.md`)确认三个真实缺口,本次按 P0 → P1-b 补齐;两端规则逐条对齐,parity 门禁仍绿。

- **P0-a 凭据/依赖识别**:任意层级目录新增 `.aws` / `.ssh` / `.kube` / `.docker` / `.gnupg` / `.terraform` / `.secrets`(服务端新增独立变体 `CredentialDirectoryNotAllowed`);文件名前缀新增 `credentials` / `id_ecdsa` / `id_dsa` / `terraform.tfstate` / `service-account`;后缀新增 `.jks` / `.keystore` / `.ppk` / `.p8` / `.kdbx` / `.der`;全名新增 `.htpasswd` / `.pgpass`。另外对**小体积文本条目**(≤256 KiB、扩展名在白名单或无扩展名)做内容特征扫描:PEM 私钥块、`AKIA`+16 位、`ghp_`/`github_pat_`/`xox*-`(服务端新增 `SecretContentDetected`);更宽的前缀启发(如 `sk-`)**故意不做**并在注释里写明理由(误报会直接阻断作者发布)
- **P0-b 规模检查不再被声明值骗**:两侧校验器改为**读取层封顶**——`by_index(index)?.take(declared_size + 1)` + 预分配收紧到单文件硬上限 + 多读 1 字节即判溢出、短读同样失败;压缩比分母从整包字节改为**该条目自身的压缩字节**;**同一修法同步到发行包校验器**(`package.rs` 原有同款洞),常量注释改成与实现一致(明确它不是整包炸弹防线)
- **P0-c 嵌套包识别**:扩展名并集 `.zip/.tar/.gz/.tgz/.7z/.rar/.jar/.whl/.nupkg` + **magic bytes 嗅探**(zip/7z/rar/gzip/tar-ustar),改名成 `.dat` 也拦。**一处有证据的偏离**:`by_index_raw` 拿到的是**压缩流**(zip 2.4.2 文档与实测一致),按它嗅探会漏拦,因此改为对**已按声明大小封顶读出的解压内容**判 magic;客户端命中即报错并点名路径与格式
- **P1-b 执行级交叉证据(走 dev-dependency 路,未退化到 fixture)**:客户端 crate 加 `[dev-dependencies] module-game-distribution`,新测试用真实打包器产出字节喂给服务端 `validate_project_bundle_zip` 断言接受(并逐项比对摘要/字节数/条目顺序),再手造含 `.env` 与 `node_modules` 的包断言服务端独立拒绝
- 客户端同时补上**路径形状检查**(`BUNDLE_FORBIDDEN_PATH_CHARS` / `_SUFFIX_CHARS` / `_SEGMENTS` + `bundle_entry_path_shape_error`),修掉「macOS/Linux 上 `src/a?.ts`、`x.` 客户端能打、服务端必 422」的不一致;客户端压缩比预检也改按条目压缩字节
- 测试:`cargo test -p module-game-distribution` **73 passed**(+4);AGC `cargo test -- project_bundle` **24 passed**(含交叉证据那条);**发行包回归**:`cargo test -p api-server game_distribution` **60 passed / 0 failed**(`package.rs` 改动无行为回归,新增「声明说谎 → ReadFailed」用例)
- 门禁:`cargo check --all-targets` 0;两端 `cargo fmt --check` 0;policy parity 0(服务端 51 条全被客户端覆盖);DTO parity 0;schema 0;encoding 0;`git diff --check` 0
2026-10-05 17:30:50 +08:00
suzmii 18d19d5d54 fix(游戏共创): 源码公开确认改回默认勾选(与「允许共创即开放源码」口径一致)
按产品裁定回落默认值:保留主动取消能力与全部知情告知,但确认项**默认已勾选**——
「允许共创本身就意味着源码开放,不设独立开关」,默认不勾选等于第二个开关,与本面板
自己写着的那句「没有单独的源码可见性开关」自相矛盾。

- `projectBundleConfirmed` 初值 true;每次重新选择授权档位都重置为「非禁止档位即已勾选」,
  避免把上一次的取消状态带到新的档位选择上(禁止共创时不显示该确认项,值本身无意义)。
- 告知文案一字不减(整个项目目录原样公开、含文档/截图/设计稿/笔记、只自动排除依赖/版本库/
  构建产物/常见凭据、一经发布不可撤销、无法收回已下载内容)。
- 新增一句提示说明默认值来源:「上面这项默认已勾选(平台按「允许共创即开放源码」的默认帮你
  勾上,不是替你做决定——你可以随时取消)。」——避免作者以为平台偷偷替他决定。
- 未勾选时的后果提示保留,仍写清「不勾选则本次不上传工程源码……」。

测试(面板 23 条):默认「禁止共创」无确认项;切到非禁止档位后确认项出现且**已勾选**,
并逐条断言告知文案 + 「默认已勾选/可随时取消」;默认状态提交不携带 `includeProjectBundle`
(交给原生按授权执行上传);作者主动取消后提交携带 `includeProjectBundle: false`(这是
「作者能退出」的证据);重新选择档位回到已勾选;切回「禁止共创」确认项消失。
2026-10-05 17:30:50 +08:00
suzmii 7972089a5f fix(游戏共创): 工程源码公开改成作者的主动知情确认,文案如实告知外发范围
背景(对抗性复核 D.7):工程源包的拒绝规则是**黑名单**,作者的 `docs/`、`*.pdf`、`notes.txt`、
截图、设计稿、会议记录等不在任何拒绝集内,会被原样外发。也就是说「授权非禁止 + 上传工程源码」
= **整个项目目录(除少数排除项)对任何登录用户公开**。原来那句「同时公开工程源码……取消勾选则
只能被试玩」是免责声明式措辞,不足以构成知情同意。

文案(最终措辞):
- 授权三态说明统一口径:「授权非「禁止共创」即允许他人改编(**没有单独的源码可见性开关**);
  是否随本次发布把工程源码一起交出去,由下面的确认决定。上架后授权只能单向提升,不能撤销。」
- 确认项(仅授权非「禁止共创」且首次发布时出现):
  「我已确认项目里没有不愿公开的内容,同意随本次发布公开**整个项目目录**:源码、素材与其中
  其它文件(含文档、截图、设计稿、笔记等)都会对任何登录用户公开;只会自动排除依赖目录、
  版本库、构建产物与常见凭据文件。一经发布**不可撤销**:即使之后把授权降级,也无法收回别人
  已经下载的内容。」
- 紧随其后写清不勾选的后果:「不勾选则本次不上传工程源码:作品仍可正常发布,但他人只能拿到
  已构建成品试玩与参考,不能直接重新发布。」

交互选择:**默认不勾选 + 不勾选就不上传**(不是禁用发布按钮)。
- 选它的理由:① 它把第 3 点做成了真正的「主动确认动作」;② 发布本身不被阻断——工程包缺失本来
  就不影响发布(服务端与原生链路都按「可选资产」设计),禁用按钮反而会把「禁止共创 / 只想先发
  出去」的作者一起挡住;③ 勾选状态只作用于本次版本上传,不引入平台侧的独立开关,授权语义不变。
- 注意:这一条**取代**了早先「授权非禁止时默认帮作者上传」的默认值——知情同意优先于默认帮忙;
  若要把默认值改回勾选,只需把 `projectPackageConfirmed` 初值改成 true 并翻转对应断言。

测试:改写两条面板用例——授权开放后确认项出现且**默认未勾选**、九处告知文案逐条断言(整个项目
目录 / 含文档截图设计稿笔记 / 只自动排除四类 / 不可撤销 / 无法收回已下载内容 / 不勾选则不上传 /
没有单独的源码可见性开关)、未确认时显式传 `includeProjectBundle: false`(不上传但照常发布)、
确认后不带该字段(由原生按授权执行上传)。
2026-10-05 17:30:49 +08:00
suzmii 843ecbf4a2 chore(游戏共创): 删掉打包器的 dead_code 豁免,并只保留真正被用到的范围分支
上传链路已在 `5dd9d1c5d` 接好,`#![allow(dead_code)]` 的豁免期结束:

- 删掉模块级 `#![allow(dead_code)]`,注释改成写明调用方(发布链路的
  `upload_project_bundle_for_version`,取件侧摘要校验共用 `sha256_hex`)。
- 移除豁免后只剩一条 dead code:`ProjectBundleScope::GameDirectory` 从未被生产代码构造
  (发布链路一律上传整个项目——收到方要能直接打开并重新构建,只带 `game/` 会丢掉根 `assets/`)。
  该变体承载的是独立能力(不同的遍历根 + 剪枝 + 「没有 game/ 目录」失败关闭),且已被两条用例
  覆盖,因此按仓库做法标 `#[cfg(test)]`(连带的 match 分支同步 cfg),并在注释里写清「真有生产
  调用方时去掉 cfg」;没有连带删除其它代码——模块里其余函数与常量都已被生产路径引用。
2026-10-05 17:30:49 +08:00
suzmii 09a11ac215 fix(游戏共创): 取件成功提示按两种取件形态如实措辞
M2b 之后取件有两种形态:工程源包解压即可编辑工程(没有 reference/ 参考副本),成品包才放在
reference/<gameId>/ 作可玩参考。原来的成功提示写死「参考产物在 reference/<gameId>/ 下」,
对工程源包形态是错的。改为两种情形都说明,并同步测试断言(仍保留「改编自 X」这条来源事实)。
2026-10-05 17:30:49 +08:00
suzmii 1a4af39e56 feat(游戏共创): 取件按 source 分支建项,来源记录升到 v2(兼容 v1)
- 来源记录 v2:新增 `source`(`package` / `project`),当前写入 `agc-fork-source.v2`;
  解析同时接受 v1——v1 没有该字段,按「成品包」解释(当时只有这一条取件通道),
  因此老项目仍能正确读出「改编自哪个作品」,发布时照常带上声明。未知版本与非法取值仍按
  「没有来源记录」失败关闭。
- 建项按取件形态分支(`create_project_from_platform_fork_at` 增加 `source` 入参,远程
  `source` 取值在命令层映射):
  · `project`(工程源包):先把包解到**项目根**再走标准初始化。源包自带
    `package.json` / `vite.config.*`,初始化会跳过 npm 脚手架判据,只补 `.agent` 身份、
    目录与 agent.db,得到一份能继续改、能重新构建的工程;不再生成 `reference/` 参考副本。
  · `package`(成品包):维持原形态(合规脚手架 + `reference/<gameId>/` 可玩参考)。
- 解压仍走既有门禁(`extract_template_archive`:条目数/单文件上限、拒符号链接、条目路径
  只允许项目内相对路径;ZIP 根 == 项目根与模板包同一合同)。
- 命令文档同步说明两种形态的差别(工程源包=解压即工程;成品包=可玩参考,不能直接再发布)。

测试:新增「工程源包建项得到可编辑工程」用例(源码逐字节不被脚手架覆盖、`.agent` 身份已补、
无 `reference/`、记录 source=project)与「v1 记录仍可读且按成品包解释」用例;
既有成品包建项用例补断言 source=package。
2026-10-05 17:30:49 +08:00
suzmii 1fc78faff2 feat(游戏共创): 授权非禁止时随版本上传工程源包(M2b 上传链路,失败不阻断发布)
上传链路(复用既有分片续传,不另写一套):
- `PackageUploadAsset` 收拢两条资产的差异(URL 资源段 `package` / `project-bundle`、文案、
  偏移错误码 `PACKAGE_UPLOAD_OFFSET_MISMATCH` / `PROJECT_BUNDLE_UPLOAD_OFFSET_MISMATCH`、
  是否有创建版本时预登记大小),`upload_staged_game_package` 改名
  `upload_staged_version_asset`,发行包与工程源包共用同一段主循环与重试/续传语义。
- 发布流程:建游戏 → 建版本 → 上传发行包 → 〔授权非「禁止共创」且作者没取消时〕打包工程源包
  并上传 → 送审。插入点必须在送审**之前**:服务端只允许 `awaiting_upload` / `upload_failed`
  档位补传工程包,送审后即 409。
- 失败关闭与不阻断:工程源包打包/上传任何失败都只写进结果的 `projectBundleWarning`
  (「未上传工程源码,本作品只能被产物级改编:…」),发布本身照常成功;作者的作品仍可玩可发布。
- 进度复用既有 `game-package-upload-progress` 事件(phase 仍用 upload/verify,文案区分资产),
  渲染层的阶段联合是闭集,不新增阶段名。

面板与渲染层:
- 新增「同时公开工程源码」勾选:仅当授权非「禁止共创」且为首次发布时出现,默认勾选,
  文案写清「允许他人下载并使用你的工程源文件(含素材),且不可撤销」;
  取消勾选才显式传 `includeProjectBundle: false`,其余情况交给原生按「授权非禁止即上传」判断,
  渲染层不重复实现同一套默认值。
- 成功页如实展示 `projectBundleWarning`,避免作者误以为源码已随版本公开。

测试:Rust 新增「两条资产的路由段/偏移错误码/预登记大小差异」用例,并更新既有 `upload_url` 用例;
TS 新增勾选默认值、取消勾选显式 false、未上传提示三条,服务层新增「true/缺省不带字段、
false 才带」用例。
2026-10-05 17:30:49 +08:00
suzmii 524ca890c6 feat(游戏共创): 工程源包规则与服务端对齐,并加机器 parity 门禁
规则对齐(以服务端为权威,`module-game-distribution/src/project_bundle.rs`):
- 凭据/隐私两侧补齐:客户端新增 `.git-credentials`、`id_rsa*`、`id_ed25519*`、`*.map`,
  并把 `.env` 放宽成服务端同形的 `starts_with(".env")`(`.envrc` 之类一并排掉)。
  反向无需补:客户端没有服务端缺的凭据类规则,比对一次后两侧凭据集合完全一致。
- 新增被漏掉的嵌套压缩包规则:服务端对任意层级 `*.zip` 一律拒收(解包阶段不递归校验,
  等于绕过整份清单),客户端原来会把它打进包里 → 现在同样排除。
- `.agent` 由「项目根首层」对齐到**任意层级**(服务端口径;平台保留名两边一致比更宽松重要)。
- 客户端额外项保留并逐项写明理由:`game/dist`、`game/build`(AGC 脚手架构建输出)、
  `.godot`(编辑器缓存,模板包指南同规则)、`exports`/`memory`(AGC 生成物与 Agent 记忆)。
- 规模上限统一到服务端数值:压缩包 ≤ 200 MiB(新增)、展开 ≤ 500 MiB、单文件 ≤ 64 MiB、
  条目 ≤ 10 000、单文件 ≤ 包体 × 100(新增)。客户端先拦,不再出现「传到一半被 422 拒掉」。
- 顺手补上服务端已有的「大小写折叠后重名条目」防线:客户端提前失败关闭。

可机器比对的常量:规则集拆成 `BUNDLE_EXCLUDED_*` 常量、上限拆成 `PROJECT_BUNDLE_MAX_*`,
新增 `scripts/check-project-bundle-policy-parity.mjs` 逐 token/逐数值比对两侧(服务端每条规则
必须在客户端存在,客户端额外项只打印不算失败;抽不到 token 直接报错,避免假绿),并照既有
DTO parity 的形态接到 `package.json` 的 `check:*` 与 `lint` 链。

测试:客户端 17 条(新增 `.git-credentials`/`id_rsa`/`*.map`/`.envrc`/`.zip`/任意层级 `.agent`、
压缩包上限、压缩比上限各自一条;合同常量锚点改为与服务端逐项相等)。
2026-10-05 17:30:48 +08:00
suzmii 63e6c6345e feat(游戏共创): 新增工程源包确定性打包器(M2b 客户端半,暂不接上传)
- 新模块 `src-tauri/src/project_bundle.rs`:`build_project_bundle(root, scope)` 产出
  `(bytes, sha256, file_count, entry_paths)`,口径见 `docs/【技术方案】游戏共创与作品Fork-…` §3.5.2。
- 确定性:条目按路径排序、固定时间戳(ZIP 下限 1980-01-01)、固定权限位 0o644、固定 deflate,
  只写文件条目不写目录条目;同内容必然得到同一 sha256(有测试钉住,含「改一字节即变」)。
- 路径安全:条目名一律项目根相对并过解压侧同一道门禁 `template_library::safe_archive_relative_path`;
  符号链接 / Windows 重解析点、非普通条目一律失败关闭。ZIP 根 == 项目根(与模板包同一合同)。
- 排除规则:依赖与 VCS 任意层级(`node_modules`/`.git`/`.svn`)、项目根首层构建产物与 IDE
  (`dist`/`build`/`library`/`temp`/`local`/`.idea`/`.vscode`/`.godot`)、任意层级凭据
  (`.env`/`.env.*`/`*.pem`/`*.key`/`*.p12`/`*.pfx`/`.npmrc`/`.netrc`)、AGC 自有目录
  (`.agent`/`exports`/`memory`,理由逐条写在模块注释里)。
- 带上限常量:条目 ≤ 4096、单文件 ≤ 256 MiB、展开总量 ≤ 512 MiB;超限失败关闭并点名违规条目,
  不静默截断(测试用小上限跑同一段逻辑,不另写一条检查路径)。
- 复用而非另起一套:`safe_archive_relative_path`(解压侧)、`project::relative_project_path`、
  `image_inspect::metadata_is_windows_reparse_point`、`export.rs` 的排序 + 逐文件写 ZIP 写法;
  摘要实现抽出 `project_bundle::sha256_hex`,`game_fork` 的取件校验改为复用它(少一份副本)。
- 打包范围:`WholeProject`(默认,M2b 用)与 `GameDirectory`(只收集 `game/`,条目命名不变)。
- 未接上传:上行路由族未定,模块整体带 `#![allow(dead_code)]` 并在注释里写明接线时删除。
- 测试 14 条:每类排除规则、确定性(两次/乱序/改字节)、条目路径不变量 + 解压器往返、
  两个打包范围、空包与三类超限失败关闭、合同常量锚点;符号链接用例按平台 `#[cfg(unix)]`。
2026-10-05 17:30:47 +08:00
suzmii d2698cbb1d fix(门禁): 补 /games/lineage 的 Pingora 登记,并修掉被掩盖的 eslint 失败
- `server-rs/crates/pingora-gateway/src/main.rs`(MAIN_SPA_PATHS,:64-79):插入 `"/games/lineage"`(放在 `"/games/detail"` 之后,保持既有字典序)。这是主站 SPA 深链在 Pingora 网关下的登记,漏一条就把该深链打成 404;与上一提交补的三份 nginx 模板属同一条「新 SPA 路由三处同批更新」规则
- 矩阵与文档无需改:`deploy/pingora/nginx-route-parity.matrix.json` 的既有 `games_spa_fallback` 用例仍前缀匹配同一行 `location`(本次只改交替项、未新增 `location`),Pingora 试点文档的取值表同理未受影响
- `src/components/game-distribution/GameLineagePage.tsx:146`:把 `lineage?.nodes ?? []` 用 `useMemo(..., [lineage])` 稳定下来,消掉两条 `react-hooks/exhaustive-deps`。取值仍是同一表达式的结果,identity 只在 `lineage` 变化时改变,因此两个下游 useMemo(代际分组、可见 ID 集合)取值不变、只少做无谓重算;未用 disable 注释压掉告警
- 6 处 `simple-import-sort/imports` 用 `eslint --fix` 机械修(`apps/.../view/home/PlatformGameForkSection.tsx`、`apps/.../view/home/index.tsx`、`src/components/game-distribution/GameDetailPage.tsx`、`MyGamesPage.test.tsx`、`MyGamesPage.tsx`、`src/services/gameDistributionClient.ts`):逐文件比对「剥掉 import 行后的正文」——5 个文件完全一致,`GameDetailPage.tsx` 仅多一个 import 分组空行
- 这批修的是「修 nginx 时被前一道红掩盖的第二、第三个失败」:CI run 3387 卡在 `check:nginx-spa-routes`,`check:pingora-route-parity` 与 `lint:eslint` 从未跑到
- 本地验证:`check:repository-ci` 的 15 个 lint 环节 + `appSurface` vitest + `npm run build` + `git diff --check 6c9566058...HEAD` 全绿,仅两个**本机不可执行**项(`check:git-hooks` 的 Windows EBUSY、`check:generated-bindings` 的 AGC `export_bindings` 本地构建);另跑 `cargo test -p pingora-gateway` 40 passed、`npx vitest run apps/ai-game-creator-shell/tests` 1957 passed / 17 skipped
2026-10-05 17:30:47 +08:00
suzmii d173e7975e style(游戏共创): 按 rustfmt 格式化 AGC tauri 侧取件与发布改动(纯格式,无语义变化)
CI run 3386 的 `Repository checks` 失败于 `cargo fmt --all -- --check`(AGC tauri
workspace),本分支引入;本次只跑 `cargo fmt --all --manifest-path
apps/ai-game-creator-shell/src-tauri/Cargo.toml`,漂移文件与 CI 报告完全一致,共 3 个:

- game_distribution_publish.rs:404 分支的 `StatusCode::NOT_FOUND =>` 改成块、`game_id`
  字符集判据的 `.chars().all(...)` 换行、`if let Some(...) = crate::project::read_project_fork_source(...)`
  换行、下载路径测试里的 `fork_source_download_segments(...)` 调用换行。
- game_fork.rs:测试里两处 `writer.start_file(...).expect(...)` 与一处 `assert!(...)`
  折行、`filter(|entry| ...)` 闭包折行。
- game_fork/desktop.rs:`use crate::game_distribution_publish::{...}` 收成单行。

逐文件核对过 `git diff`:只有折行 / 缩进 / 大括号位置 / 尾随逗号类变化,标识符、字符串
字面量、注释文本、逻辑一律未动。未改 server-rs、src、scripts,也未动 PR 状态。
2026-10-05 17:30:47 +08:00
suzmii f40050afb1 收口 M3 复核遗留:文档如实口径、fork-source 状态说明、forkAuthorization 机器守卫、e2e 引用去行号
- 技术方案 §3.4:删掉「GET /games/{gameId} 追加 forkSourceAvailable」——实现里不存在该字段;改为如实口径:改造入口显隐只依据 forkAuthorization,真实可复刻形态由 /fork-source 的 source 回答,若 M2b 要区分「可源码级改造 / 只能参考」届时再加
- 实施计划(M1)§5:同步去掉 forkSourceAvailable 并注明「未实现、也不需要」,保留其余字段清单不动
- 技术方案 §2.6 时序图:说明字句从「GET …/fork-source 是待实现接口」改为「M2a 已实现(形状见 §3.4 登录用户表)」,并在图内加一行 Note 标注「图中字段名是 M2b 目标形状」;图属目标形态的免责声明保留
- parity 脚本:game_payload 增加 mustEmit ['forkAuthorization']——该字段 TS 侧可选(旧响应可省),但公开与作者响应必须发出,否则详情页授权徽章与改造入口会静默退化成「禁止共创」;public_game_payload 以 game_payload 为 base,因此一并受保护
- e2e 脚本头部:把全部行号引用(含已过期 2–4 行的那些)改为「文件 + 符号」引用(router()/lineage_read_or_not_found()/GameDistributionLineageNode/lineage.rs 常量与函数等),并删除「消费链路在未提交的 M2a WIP 里」这类会过期的措辞,改为「已在 M2a 落地」;只改注释,断言逻辑未动
2026-10-05 17:30:47 +08:00
suzmii d89e21ffd5 feat(游戏共创): 首页新增「从平台作品开始创作」入口(唯一可点的客户端路径)
- 入口位置:首页模板库推荐位之后新增一节「从平台作品开始创作」。与模板库同属「从现成内容
  起步」,但这条拿的是平台作品的已构建成品(可玩参考 + 素材),不是可编辑工程,因此单独成节
  而不是塞进模板库;未登录用户进不到首页,服务端也确实对任何登录用户开放取件,无需额外灰度。
- 交互:输入平台作品 ID 或作品链接 → 解析出作品 ID(裸 ID / `?id=` / `?gameId=` / `/games/<id>`,
  也容忍不带 scheme 的粘贴;解析不出就本地拦截、不发请求)→ 调
  `create_local_project_from_platform_game`(name/planning 走默认,与模板链路一致)→
  成功后复用模板那条「原生已落盘 → 登记最近项目并进入工作区」通道进项目。
- 三类结果:① 未登录/登录过期(`authentication-required:`)→「请重新登录后重试」;
  ② 403 未开放授权(`permission-denied:`)与 409 未公开/已下架(`fork-source-not-available:`)
  按服务端文案分别展示,且都不建项目、按钮可重试;③ 成功展示「改编自平台作品 <gameId>」
  与 `reference/<gameId>/` 参考产物位置,让来源事实可见。
- 为此给取件的 404/409 补了与 401/403 同族的稳定前缀(`fork-source-not-found:` /
  `fork-source-not-available:`):渲染层按前缀精确分类,不做文案子串猜测。
- 加载态:取件期间按钮禁用 + 明确提示「下载、校验、解压需要几分钟」,并用 ref 守卫挡住同一
  tick 的重复提交(只认最后一次请求)。
- 文案严守产品口径:拿到的是「已构建成品」= 可玩参考 + 素材,不能直接再次发布,需在新工程里
  改造后发布;不出现「一键复刻工程」这类说法。
- 门禁登记:命令已接回 App 入口,因此从 `scripts/check-config.mjs` 的 native-only 白名单移除
  (该脚本要求「已接入」与「未接入」两个集合互斥)。
- 测试:新增 `tests/platformGameFork.test.tsx`(纯解析/失败分类 + 组件:空与非法输入不发请求、
  403/409/401 各自提示且不建项目、加载态与重复提交、成功时命令参数与「改编自」展示)。
2026-10-05 17:30:47 +08:00
suzmii e3bae05351 feat(游戏共创): 发布自动带改编声明,上架可选共创授权档位(AGC 面板三态)
- 改编声明:`publish_local_project_game` 在**首次发布**(不带 gameId)时读取项目内
  `.agent/fork-source.json`,把 `fork: { parentGameId, parentVersionId }` 并入创建作品请求;
  带 gameId 的更新发布不重复带声明(服务端对「复用既有作品身份时再声明来源」失败关闭,
  重复带会变成不可恢复的 409)。判据与注入点都在原生链路,渲染层既传不进也伪造不了;
  声明在 `metadata_digest` 之前并入,幂等根键随之变化属预期行为。
- 授权档位:`GameDistributionPublishMetadata` / `normalizeMetadata` / `toCreateGameRequest`
  接通 `forkAuthorization`(缺省 `forbidden`),发布面板新增「授权共创」三态单选,
  文案复用 `packages/shared/src/contracts/gameDistribution.ts` 的标签常量;更新发布时该栏只读
  并提示「共创授权只在首次发布时生效」——档位只在创建作品时生效,上架后只能单向提升。
  附带按 `styles.css` 既有面板变量补齐这组 radio 的样式(不能套用整行输入框那条规则)。
- 门禁登记:新命令本轮只落 native 能力,按 `scripts/check-config.mjs` 的 native-only 清单登记。
- 测试:Rust 钉住「资料摘要同内容稳定、并入声明即变」;TS 钉住请求体形状
  (带/不带档位、声明不由渲染层提交)与面板三态受控行为、更新模式只读。
2026-10-05 17:30:46 +08:00
suzmii c5564e59ed feat(游戏共创): 客户端落地「从平台作品开始创作」取件链路(本地来源记录 + 新命令)
- 新增 `project/fork_source.rs`:项目改编来源记录落在 `.agent/fork-source.json`
  (`{schemaVersion,gameId,versionId,adoptedAtMillis}`,版本 `agc-fork-source.v1`)。
  位置理由:`.agent/**` 随项目快照上云、随用户整目录拷贝,且导出包不带 `.agent`,
  既随行又不干扰游戏产物;不改 `manifest.json`(它是 deny_unknown_fields + 只接受 v1)。
  写入走统一入口 `write_game_creator_private_file`;读取容忍缺失/损坏/异形/非普通文件,
  一律返回 None 而不报错、不 panic。
- 新增 `game_fork.rs` + `game_fork/desktop.rs` 与命令
  `create_local_project_from_platform_game`(在 `desktop.rs` 的 generate_handler 注册):
  取平台会话 → 取件元数据 → 带 Bearer 下载整包 → 校验字节数与 SHA-256(失败关闭、不落盘)
  → `init_local_game_project_at` 生成合规 Phaser4+Vite 脚手架 → 参考副本解压到
  `<project>/reference/<gameId>/`(复用 `safe_archive_relative_path` 与
  `extract_template_archive` 的条目数/单文件/符号链接门禁,按最小改动把后者提到 pub(crate))
  → 写来源记录;任一步失败都删掉半成品项目目录。
  参考副本必须落在子目录:`create_npm_scaffold` 的判据是「没有 manifest 且根/`game` 都没有
  index.html、package.json」,成品包若落在项目根或 `game/` 根,脚手架一个文件都不会生成。
- `game_distribution_publish.rs` 新增受鉴权取件实现:`fetch_platform_game_fork_source`
  (元数据 GET + 带 Bearer 的整包下载 + 404/409/403/401 四态可区分映射 + 下载路径同源校验)。
  不复用模板库的 `fetch_limited_bytes`:它写死 `client.get(url)`,带不了鉴权头,
  复用它会让受保护内容变成匿名下载。
- 埋点:新增 `CreationSource::PlatformGame`(`analytics/contract.rs` 的 values! 登记)并在建项
  成功后上报,来源标识沿用模板链路的 ID 槽位。
- 修既有编译错误:`game_distribution_publish.rs` 的资料摘要测试缺 `fork` 字段
  (上一提交给 `GameDistributionCreateGameRequest` 加了该字段但没同步该测试字面量),
  补 `fork: None` 以恢复测试目标可编译。
2026-10-05 17:30:46 +08:00
suzmii eeb345f2ad feat(游戏共创): 上架时即可指定共创授权档位(创建作品请求增量)
- TS 契约 `GameDistributionCreateGameRequest` 新增可选 `forkAuthorization?: GameDistributionForkAuthorization`,注释写明缺省禁止共创、非法值整请求 400、上架后只能单向提升
- Rust 契约同结构体新增 `#[serde(default)] pub fork_authorization: GameDistributionForkAuthorization`(非 `Option`):省略与显式传 `forbidden` 得到同一个值,**幂等摘要因此相同**——创建请求的摘要取自整个请求体,若写成 `Option` + `skip_serializing_if`,两种写法会变成「同 key 不同请求」而互相冲突;未知取值由反序列化直接拒绝
- api-server `create_game`:载荷改为 `Result<Json<..>, JsonRejection>`,拒绝统一映射成平台信封 400(与 `set_fork_authorization` 同修法),并按 rejection 文本区分文案(含 `forkAuthorization` → 「共创授权档位不合法,只接受 forbidden / nonCommercial / full」,其余 → 「创建作品请求字段不合法」;框架文本只用于选文案,不回传客户端);创建记录入参新增 `fork_authorization: fork_authorization_value(payload.fork_authorization)`
- spacetime-client:`GameDistributionCreateGameRecordInput` 新增 `fork_authorization: String` 并透传给 procedure;重新生成的 `GameDistributionCreateGameInput` 同步带上该字段
- spacetime-module:`GameDistributionCreateGameInput` 新增 `fork_authorization: String`;创建事务里用 `ForkAuthorization::parse` 解析,未知取值失败关闭(`FORK_AUTHORIZATION_UNKNOWN`,**不静默落成 forbidden**),并把原来的硬编码 `FORK_AUTHORIZATION_FORBIDDEN` 换成解析结果
- 资料编辑复用创建校验的转换函数与既有测试夹具按新字段补默认值;AGC 侧测试字面量同步(AGC 发布面板的 UI 接线留到后续,缺省值等价于不传)
- 测试:`create_game_request_defaults_fork_authorization_without_changing_digest`(缺省 → forbidden;显式 forbidden 与原缺省**摘要相同**;`nonCommercial` / `full` 原样保留;`"allowed"` 反序列化失败)与 `create_game_rejects_unknown_fork_authorization_with_envelope_bad_request`(未知档位 → 400 + 平台信封且无框架纯文本;非档位字段问题走通用文案;合法载荷不会被误拒——测试态发布灰度未配置,得到 503 而非 400,即证明载荷路径已通过且未触达创建)
- 文档:技术方案 §2.4(发布入口上架时即选档位)、§3.4(`POST /games` 请求增量补 `forkAuthorization`)、§3.9(补充说明上架指定档位已支持、事后提升仍保留)
2026-10-05 17:30:46 +08:00
k88936 cebffb9dad 测试(AGC模型): 补齐裸目录响应兼容用例
- 新增 legacy_raw_catalog_payload_defaults_optional_fields:覆盖无 ok 信封、缺少 agentMode/protocol/unavailableModels 的旧裸目录响应
- 断言缺省按 Codex + OpenAI Responses + 空不可用桶兜底,锁定既有兼容行为
2026-10-05 17:28:38 +08:00
suzmii 3206f8f49b 修复在线游玩加载体验:加载期黑屏/空白与发行资源传输开销
- packages/shared 新增共享游戏加载面 PlatformGameLoadingSurface:封面/标题 + 动效进度 + 按时长推进的阶段文案(准备/资源/引擎)+ 慢加载提示,附用例
- 网页游玩页用共享加载面替换近黑壳上的一行小字,加载上限改为共享常量 PLATFORM_GAME_LOADING_TIMEOUT_MS
- 后台审核试玩补加载面、20 秒超时与「重新创建试玩会话」入口,新会话重置加载态;补两条用例
- 发行网关(api-server)对文本类发行资源按 Accept-Encoding 下发 gzip,并下发强 ETag、命中 If-None-Match 返回 304;补 5 条 Rust 用例
- E2E 脚本 check-game-distribution-ops-rollback-e2e 补压缩/Vary/ETag/304/不接受 gzip 四条断言
- 同步 pitfalls、开发运维文档、nginx README 与两份里程碑记录
2026-10-05 17:14:32 +08:00
suzmii 14283db943 修复运行页「刷新运行画面」不是真正重载
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
- 刷新时给 iframe 地址加一枚随 reloadNonce 递增的 __agc_reload 参数:同一地址的导航可能命中缓存,只换元素身份不足以保证重新请求
- 重新载入时丢掉上一版量到的内容尺寸,新页面先在容器尺寸上适配,不再被上一版的适配结果渲染
- tests/localGamePreviewFrame.test.ts 补刷新回归:换新节点 + 地址带一次性参数 + 丢弃旧测量
- tests/runPreviewRefresh.test.tsx 断言改为新契约(原地址逐字保留、参数逐次递增、节点每次都是新的)
2026-10-05 17:08:21 +08:00
suzmii 7ad412f0ec 修运行画面点选后预览自己缩放:高亮框不再参与尺寸上报,命中矩形裁剪到画布
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
- 根因:高亮框(body 下 data-genarrative-preview-inspect,position:fixed)被尺寸上报的 measureContentBounds 遍历计入内容尺寸;three 投影盒超出画布时把内容尺寸撑到 3756×2643(视口 900×560),宿主改 iframe 尺寸触发游戏 resize 重算相机,形成自激振荡
- 桥:measureContentBounds 的 TreeWalker 对 data-genarrative-preview-fit / data-genarrative-preview-inspect 返回 FILTER_REJECT(桥自己的节点不参与内容测量)
- 桥:新增 clipInspectRect,引擎档(three 投影盒、Phaser 世界包围盒)命中矩形统一裁剪到画布可见范围;与画布无交集时退化为指针点矩形(不出现 0/负尺寸)
- 测试:新增 localPreviewInspectSizeStability.test.ts(5 例:桥节点不参与测量、同尺寸普通节点仍计入的对照组、进入检查模式与 hover 后尺寸与宿主适配布局不变、投影盒超出画布时载荷被裁剪、与画布无交集时退化为 1×1);runtimeInspectEngines 的字段换算用例改到画布内的等价参数(原矩形落在画布外,裁剪后按新规则退化为指针点矩形)
- 文档:pitfalls 记一条「高亮框被尺寸上报当成页面内容」的根因、口径与回归
2026-10-05 17:08:03 +08:00
suzmii 21c79f54a4 Merge pull request '修复:AGC 窗口标题栏项目标签改认当前项目(#618)' (#621) from fix/agc-titlebar-project-label into master
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 6m47s
Project CI / AI game creator shell Rust crates (push) Successful in 4m38s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 6m6s
Project CI / Frontend tests (push) Successful in 3m41s
Project CI / Backend tests (push) Successful in 8m0s
Project CI / AI game creator shell web tests (push) Successful in 2m48s
Project CI / Repository checks (push) Successful in 7m17s
Project CI / Native shell tests (push) Successful in 9m27s
Reviewed-on: http://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/621
2026-10-05 16:11:16 +08:00