AGC 运行画面点选:canvas 玩法上识别 Phaser 4 / three.js 的已登记素材(#612) #624

Merged
suzmii merged 16 commits from feat/agc-runtime-picking-engines into master 2026-10-05 19:16:03 +08:00
Member

标题:AGC 运行画面点选:canvas 玩法上识别 Phaser 4 / three.js 的已登记素材(#612)

关联

#612

背景与问题

运行画面「点选素材」今天的命中路径只有 DOM:读元素上的 data-resource-id /
data-asset-id / data-genarrative-resource-id,再退一步读媒体 src。
canvas 玩法里这些线索一个都没有,于是点中精灵或 Mesh 时 resourceIds / sourcePath
全空 —— 点选“看起来没反应”,引用只能退化成不带素材的区域引用,芯片名落到元素/画面名
(canvas、甚至贴图内部 key)。本 PR 让引擎画面上的点选也能落到 manifest 的素材 id。

落地方案

  1. 桥脚本搬出 Rust 字符串:PREVIEW_FIT_BRIDGE_SCRIPT 落到
    src-tauri/resources/preview/local-preview-fit.js,preview.rs 改 include_str!。
    注入、去重扫描、/__genarrative/local-preview-fit.js 路由与响应逐字不变(行为零变化)。
  2. 共享命中解析:桥内 handleInspectMove / handleInspectClick 共同部分抽成
    resolveInspectTarget(clientX, clientY) → { selection, rect };DOM 分支等价搬运。
  3. canvas 引擎档:只认玩法显式发布的只读句柄 window.__GENARRATIVE_PREVIEW_GAME__
    ({ engine: 'phaser', game } / { engine: 'three', THREE, scene, camera, renderer }),
    不通过扫描全局对象猜引擎。
    • Phaser 4:game.input.activePointer + scene.input.hitTestPointer,按
      pointer.camera.renderList 索引降序取最上层;setInteractive() 未覆盖的对象用
      scene.children.list(含 depth)+ getBounds() 做几何兜底;矩形按
      camera.matrixCombined 换算屏幕矩形。
    • three.js:renderer.domElement → NDC → Raycaster.setFromCamera +
      intersectObjects(scene.children, true) 取最近命中;矩形用 Box3 八角投影取 min/max。
    • 身份来源优先级:玩法显式标注(genarrativeResourceId / genarrativeResourcePath)
      优先,其次才是从贴图地址推断出的文件名。
  4. 宿主四档匹配(新增纯函数 runtimeInspectResourceMatch.ts):显式 resourceIds
    → sourcePath 与 localPath 的精确后缀(按 /、\ 分段,段边界判定)→ 文件名
    (现有口径)→ 序列帧 imageSequenceFrames[].imageSrc 同权参与后两档;结果去重且只保留
    manifest 现有 id(未知值丢弃,宁可少给不可给错)。芯片名在唯一命中时归一化为
    resourceDisplayName(asset),与 @ 候选 / 资源卡「引用」/ 拖拽引用逐字一致。
  5. 脚手架与模板:DEFAULT_GAME_SCRIPT_JS 与三个起步模板(phaser-2d-starter、
    threejs-3d-starter、blank-3d-scene)发布只读引擎句柄;Phaser 侧改用 Image 标签装载
    (loader: { imageLoadType: 'HTMLImageElement' }),让贴图保留原始素材地址。

前后对照

场景 改前 改后(实测值)
点 Phaser 画面里的贴图精灵(无 data-*、无 src) 不带素材的区域引用(resourceIds=[]) resourceIds=["hero"],芯片 @hero
点与上一个重叠的显式标注对象(取最上层) 不带素材的区域引用 resourceIds=["enemy-tag"],芯片 @enemy
点 three.js 贴图 Mesh / userData 标注 Mesh 不带素材的区域引用 ["hero"] / ["enemy-tag"]
点未开交互的精灵 不带素材的区域引用 几何兜底命中:["hero"](显式路径)
点空白 不带素材的区域引用 不变:@canvas + resourceIds=[],零报错
DOM 点选(HUD data-resource-id、媒体 src) 芯片名 = 元素文本/标签,id 来自 data-* 逐字不变(@HUD 区域 / @img)
消息版本号 / 字段净化 / Rust 校验口径 / 资源选中与信息栏 — 不变

说明:上表「改前」列是按改动前的桥只有 DOM 分支推得(未单独跑改动前版本),
「改后」列是真实 Chromium 实测值。

变更清单

  1. AGC 运行画面点选新增 Phaser 4 与 three.js 引擎档:src-tauri/resources/preview/local-preview-fit.js(新增,1074 行)、
    src-tauri/src/preview.rs(改 include_str!,-508/+1)、
    tests/runtimeInspectEngines.test.ts(新增 1277 行)、.prettierignore。
  2. 运行画面点选结果收敛到 manifest 现有素材 id:src/features/project-workspace/runtimeInspectResourceMatch.ts(新增 173 行)、
    src/view/project-development/index.tsx(+17/-14)、
    tests/runtimeInspectResourceMatch.test.ts(新增 278 行)。
  3. AGC 起步工程与新建脚手架发布点选所需引擎句柄:src-tauri/src/main.rs(DEFAULT_GAME_SCRIPT_JS)、
    template-library/v1/{phaser-2d-starter,threejs-3d-starter,blank-3d-scene}。
  4. 补运行画面点选的行为规范、踩坑与实施记录:功能说明、PRD §3.4、shared-memory/pitfalls.md、实施计划、里程碑。
  5. 补运行画面点选验收证据与里程碑勾选:功能说明证据表、里程碑勾选与「验收证据」节、实施计划落盘记录。

验证证据

  • npm run agc:typecheck:EXIT=0(check:tests:types / tsc / skill-pack 指纹 /
    包布局声明 / check-config 全过)。
  • 前端用例 4 文件 = 95 passed:runtimeInspectEngines(27)、
    runtimeInspectResourceMatch(11)、localGamePreviewFrame(14)、
    resourceReferenceInput(43)。
  • tests/appSurface.test.ts:197 passed / 9 skipped。
  • cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --offline -- preview:
    43 passed / 0 failed。
  • 同路径 -- scaffold:4 passed / 1 既有 #[ignore](需 npm 装依赖 + Provider,非失败)。
  • node scripts/check-doc-index.mjs 通过;npm run check:encoding 通过(5237 files);
    git diff --check 输出为空。
  • 真实 Chromium 端到端(真实 Phaser 4.2.1 / three 0.184 + 真实桥脚本
    local-preview-fit.js,被测 sha256 6276ac48…917a):
    • 已登记贴图对象 → resourceIds=["hero"]、芯片 @hero;
    • 显式标注对象(与上一个重叠)→ ["enemy-tag"]、芯片 @enemy(显式优先 + 取最上层);
    • 非交互精灵(setData('genarrativeResourcePath'))→ 几何兜底命中 ["hero"];
    • 点空白 → @canvas + []、零报错;DOM 档芯片名与 id 行为逐字不变。
  • 高亮矩形:与期望逐值相减,Phaser 差 0px、three 最大差 ≈0.0006px;
    DOM 档仍是元素矩形。

真机复验(2026-10-05,客户端从本分支源码编译)

真机:点中四面体 → 信息栏 TetrahedronGeometry、输入区芯片 @TetrahedronGeometry

  • 点中 three 对象 → 芯片 @CylinderGeometry(title CylinderGeometry · 运行区域),不再是 canvas;
  • 点空白天空 → 芯片回落 @canvas(退化档),控制台 0 报错;
  • 命中高亮:对象级矩形,且超出画布时被裁剪到画布内(实测 (84,200,746,458) 右边/下边恰好贴画布 830×658 的边);
  • 点选不改变预览适配(BUG2 回归验证):进入检查模式 / hover / 点中对象 / 点空白四个阶段,iframe 的 src、style、getBoundingClientRect 逐值相同(830×658、scale(1))、尺寸上报全程仅 1 条、预览页内 resize 计数 0;
  • iframe 内句柄实测:engine='three'、three 键为 [Raycaster, Vector2, Vector3, Box3] 且均为 function、scene/camera/renderer 齐;
  • 附注:点中对象后相机仍会缓动一次,是项目自身 pointerup → focusShape 的既有反应(玩法对所有点击都如此),与检查模式无关;桥只监听 click,不吞 pointerdown/pointerup。

真机:点中对象(橙色高亮框贴画布边被裁剪 + 三枚芯片)
真机:点空白回落 canvas

边界与不做项

  • 不做运行期资源使用关系持久化:不记录“某素材在画面上某位置被用过”、不注入玩法代码、
    不写资源侧车、不改 manifest。
  • 不改 runtime-region 引用契约、genarrative.local-preview-inspect.v1 消息版本号、
    LocalGamePreviewFrame 的解析与净化、Rust direct_codex_user_item 的 resourceIds 校验口径。
  • 不支持 Cocos Creator / Godot / Unity(走各自编辑器桥接),也不包含纯 2D canvas 引擎与 Babylon.js。
  • 不通过扫描全局对象猜引擎;只认玩法发布的只读句柄。
  • 旧项目不自动获得能力:不写迁移、不做兼容分支,历史项目需重新生成或人工补句柄/标注。

已知限制 / 未覆盖

  • Phaser 默认 XHR 装载下贴图地址是 blob:,读不回原始素材路径 → 这类项目必须由玩法
    显式标注素材身份,否则按退化路径处理(不带素材的区域引用)。脚手架与 phaser-2d-starter
    已改用 Image 标签装载;历史项目仍是 blob。
  • Tauri 真机链路未跑:预览脚本注入、去重扫描、/__genarrative/local-preview-fit.js
    路由由 cargo test … -- preview 覆盖;本 PR 的浏览器证据用的是同一份桥脚本文件 +
    真实引擎,但不含 Rust 预览服务器那一环。
  • 未覆盖:多场景叠加、非默认相机(scroll/zoom/rotation)、高亮矩形的真机目视、
    GLB 内嵌纹理模型走显式标注路径的真机验证。

评审提示

  • .prettierignore 新增 src-tauri/resources/preview/:桥脚本是随包注入浏览器的资源,
    按字节搬运自 Rust 内联字符串,禁止 prettier 二次改写(会改变注入字节)。
  • 模板 zip 与线上索引未重新发布(template-library 只改本地源);
    生成期契约落位(玩法 skill / Runtime Prompt 强制标注 + 重新发布模板产物)另立里程碑。
  • 芯片名归一化口径:引擎档(elementTag === 'canvas')唯一命中即归一化为 manifest 显示名;
    DOM 档仅在 label 恰为该 sourcePath 的文件名词干时才归一化,其余原样保留。

截图

three.js:贴图 Mesh 自动档 / userData 显式档

three.js 场景:贴图 Mesh 自动档(@hero)、userData 显式档(@enemy)、点空白(@canvas)、DOM HUD(@HUD 区域)。

Phaser + Image 装载

Phaser(loader.imageLoadType='HTMLImageElement'):自动档 @hero、显式档 @enemy、非交互精灵几何兜底 @hero、点空白 @canvas、DOM HUD 不变。

Phaser 默认 XHR 装载

Phaser(默认 XHR):同一个贴图精灵退化为 @heroUpper(resourceIds=[])——已知限制(贴图地址是 blob:)的证据。

标题:AGC 运行画面点选:canvas 玩法上识别 Phaser 4 / three.js 的已登记素材(#612) ## 关联 #612 ## 背景与问题 运行画面「点选素材」今天的命中路径只有 DOM:读元素上的 `data-resource-id` / `data-asset-id` / `data-genarrative-resource-id`,再退一步读媒体 `src`。 canvas 玩法里这些线索一个都没有,于是点中精灵或 Mesh 时 `resourceIds` / `sourcePath` 全空 —— 点选“看起来没反应”,引用只能退化成不带素材的区域引用,芯片名落到元素/画面名 (`canvas`、甚至贴图内部 key)。本 PR 让引擎画面上的点选也能落到 manifest 的素材 id。 ## 落地方案 1. **桥脚本搬出 Rust 字符串**:`PREVIEW_FIT_BRIDGE_SCRIPT` 落到 `src-tauri/resources/preview/local-preview-fit.js`,`preview.rs` 改 `include_str!`。 注入、去重扫描、`/__genarrative/local-preview-fit.js` 路由与响应逐字不变(行为零变化)。 2. **共享命中解析**:桥内 `handleInspectMove` / `handleInspectClick` 共同部分抽成 `resolveInspectTarget(clientX, clientY)` → `{ selection, rect }`;DOM 分支等价搬运。 3. **canvas 引擎档**:只认玩法显式发布的只读句柄 `window.__GENARRATIVE_PREVIEW_GAME__` (`{ engine: 'phaser', game }` / `{ engine: 'three', THREE, scene, camera, renderer }`), 不通过扫描全局对象猜引擎。 - Phaser 4:`game.input.activePointer` + `scene.input.hitTestPointer`,按 `pointer.camera.renderList` 索引降序取最上层;`setInteractive()` 未覆盖的对象用 `scene.children.list`(含 `depth`)+ `getBounds()` 做几何兜底;矩形按 `camera.matrixCombined` 换算屏幕矩形。 - three.js:`renderer.domElement` → NDC → `Raycaster.setFromCamera` + `intersectObjects(scene.children, true)` 取最近命中;矩形用 `Box3` 八角投影取 min/max。 - 身份来源优先级:玩法显式标注(`genarrativeResourceId` / `genarrativeResourcePath`) 优先,其次才是从贴图地址推断出的文件名。 4. **宿主四档匹配**(新增纯函数 `runtimeInspectResourceMatch.ts`):显式 `resourceIds` → `sourcePath` 与 `localPath` 的精确后缀(按 `/`、`\` 分段,段边界判定)→ 文件名 (现有口径)→ 序列帧 `imageSequenceFrames[].imageSrc` 同权参与后两档;结果去重且只保留 manifest 现有 id(未知值丢弃,宁可少给不可给错)。芯片名在唯一命中时归一化为 `resourceDisplayName(asset)`,与 `@` 候选 / 资源卡「引用」/ 拖拽引用逐字一致。 5. **脚手架与模板**:`DEFAULT_GAME_SCRIPT_JS` 与三个起步模板(`phaser-2d-starter`、 `threejs-3d-starter`、`blank-3d-scene`)发布只读引擎句柄;Phaser 侧改用 Image 标签装载 (`loader: { imageLoadType: 'HTMLImageElement' }`),让贴图保留原始素材地址。 ## 前后对照 | 场景 | 改前 | 改后(实测值) | | ---- | ---- | -------------- | | 点 Phaser 画面里的贴图精灵(无 `data-*`、无 `src`) | 不带素材的区域引用(`resourceIds=[]`) | `resourceIds=["hero"]`,芯片 `@hero` | | 点与上一个重叠的显式标注对象(取最上层) | 不带素材的区域引用 | `resourceIds=["enemy-tag"]`,芯片 `@enemy` | | 点 three.js 贴图 Mesh / `userData` 标注 Mesh | 不带素材的区域引用 | `["hero"]` / `["enemy-tag"]` | | 点未开交互的精灵 | 不带素材的区域引用 | 几何兜底命中:`["hero"]`(显式路径) | | 点空白 | 不带素材的区域引用 | 不变:`@canvas` + `resourceIds=[]`,零报错 | | DOM 点选(HUD `data-resource-id`、媒体 `src`) | 芯片名 = 元素文本/标签,id 来自 `data-*` | 逐字不变(`@HUD 区域` / `@img`) | | 消息版本号 / 字段净化 / Rust 校验口径 / 资源选中与信息栏 | — | 不变 | 说明:上表「改前」列是按改动前的桥只有 DOM 分支推得(未单独跑改动前版本), 「改后」列是真实 Chromium 实测值。 ## 变更清单 1. AGC 运行画面点选新增 Phaser 4 与 three.js 引擎档:`src-tauri/resources/preview/local-preview-fit.js`(新增,1074 行)、 `src-tauri/src/preview.rs`(改 `include_str!`,-508/+1)、 `tests/runtimeInspectEngines.test.ts`(新增 1277 行)、`.prettierignore`。 2. 运行画面点选结果收敛到 manifest 现有素材 id:`src/features/project-workspace/runtimeInspectResourceMatch.ts`(新增 173 行)、 `src/view/project-development/index.tsx`(+17/-14)、 `tests/runtimeInspectResourceMatch.test.ts`(新增 278 行)。 3. AGC 起步工程与新建脚手架发布点选所需引擎句柄:`src-tauri/src/main.rs`(`DEFAULT_GAME_SCRIPT_JS`)、 `template-library/v1/{phaser-2d-starter,threejs-3d-starter,blank-3d-scene}`。 4. 补运行画面点选的行为规范、踩坑与实施记录:功能说明、PRD §3.4、`shared-memory/pitfalls.md`、实施计划、里程碑。 5. 补运行画面点选验收证据与里程碑勾选:功能说明证据表、里程碑勾选与「验收证据」节、实施计划落盘记录。 ## 验证证据 - `npm run agc:typecheck`:EXIT=0(`check:tests:types` / `tsc` / skill-pack 指纹 / 包布局声明 / `check-config` 全过)。 - 前端用例 4 文件 = **95 passed**:`runtimeInspectEngines`(27)、 `runtimeInspectResourceMatch`(11)、`localGamePreviewFrame`(14)、 `resourceReferenceInput`(43)。 - `tests/appSurface.test.ts`:**197 passed / 9 skipped**。 - `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --offline -- preview`: 43 passed / 0 failed。 - 同路径 `-- scaffold`:4 passed / 1 既有 `#[ignore]`(需 npm 装依赖 + Provider,非失败)。 - `node scripts/check-doc-index.mjs` 通过;`npm run check:encoding` 通过(5237 files); `git diff --check` 输出为空。 - **真实 Chromium 端到端**(真实 Phaser 4.2.1 / three 0.184 + 真实桥脚本 `local-preview-fit.js`,被测 sha256 `6276ac48…917a`): - 已登记贴图对象 → `resourceIds=["hero"]`、芯片 `@hero`; - 显式标注对象(与上一个重叠)→ `["enemy-tag"]`、芯片 `@enemy`(显式优先 + 取最上层); - 非交互精灵(`setData('genarrativeResourcePath')`)→ 几何兜底命中 `["hero"]`; - 点空白 → `@canvas` + `[]`、零报错;DOM 档芯片名与 id 行为逐字不变。 - 高亮矩形:与期望逐值相减,Phaser 差 **0px**、three 最大差 **≈0.0006px**; DOM 档仍是元素矩形。 ### 真机复验(2026-10-05,客户端从本分支源码编译) ![真机:点中四面体 → 信息栏 TetrahedronGeometry、输入区芯片 @TetrahedronGeometry](https://git.genarrative.world/git/attachments/ded4888c-befc-4e6c-8871-ee156031f949) - 点中 three 对象 → 芯片 `@CylinderGeometry`(title `CylinderGeometry · 运行区域`),**不再是 `canvas`**; - 点空白天空 → 芯片回落 `@canvas`(退化档),控制台 0 报错; - 命中高亮:对象级矩形,且超出画布时被裁剪到画布内(实测 `(84,200,746,458)` 右边/下边恰好贴画布 830×658 的边); - 点选不改变预览适配(BUG2 回归验证):进入检查模式 / hover / 点中对象 / 点空白四个阶段,iframe 的 `src`、`style`、`getBoundingClientRect` 逐值相同(`830×658`、`scale(1)`)、尺寸上报全程仅 1 条、预览页内 `resize` 计数 **0**; - iframe 内句柄实测:`engine='three'`、`three` 键为 `[Raycaster, Vector2, Vector3, Box3]` 且均为 function、`scene/camera/renderer` 齐; - 附注:点中对象后相机仍会缓动一次,是项目自身 `pointerup → focusShape` 的既有反应(玩法对所有点击都如此),与检查模式无关;桥只监听 `click`,不吞 `pointerdown/pointerup`。 ![真机:点中对象(橙色高亮框贴画布边被裁剪 + 三枚芯片)](https://git.genarrative.world/git/attachments/3a888979-ef69-498e-96bd-eee80e15a15c) ![真机:点空白回落 canvas](https://git.genarrative.world/git/attachments/a3d7a840-f8a8-45ee-a0a3-631fcfc08ea5) ## 边界与不做项 - 不做运行期资源使用关系持久化:不记录“某素材在画面上某位置被用过”、不注入玩法代码、 不写资源侧车、不改 manifest。 - 不改 `runtime-region` 引用契约、`genarrative.local-preview-inspect.v1` 消息版本号、 `LocalGamePreviewFrame` 的解析与净化、Rust `direct_codex_user_item` 的 `resourceIds` 校验口径。 - 不支持 Cocos Creator / Godot / Unity(走各自编辑器桥接),也不包含纯 2D canvas 引擎与 Babylon.js。 - 不通过扫描全局对象猜引擎;只认玩法发布的只读句柄。 - 旧项目不自动获得能力:不写迁移、不做兼容分支,历史项目需重新生成或人工补句柄/标注。 ## 已知限制 / 未覆盖 - **Phaser 默认 XHR 装载下贴图地址是 `blob:`**,读不回原始素材路径 → 这类项目必须由玩法 显式标注素材身份,否则按退化路径处理(不带素材的区域引用)。脚手架与 `phaser-2d-starter` 已改用 Image 标签装载;历史项目仍是 blob。 - **Tauri 真机链路未跑**:预览脚本注入、去重扫描、`/__genarrative/local-preview-fit.js` 路由由 `cargo test … -- preview` 覆盖;本 PR 的浏览器证据用的是同一份桥脚本文件 + 真实引擎,但不含 Rust 预览服务器那一环。 - 未覆盖:多场景叠加、非默认相机(`scroll`/`zoom`/`rotation`)、高亮矩形的真机目视、 GLB 内嵌纹理模型走显式标注路径的真机验证。 ## 评审提示 - `.prettierignore` 新增 `src-tauri/resources/preview/`:桥脚本是随包注入浏览器的资源, 按字节搬运自 Rust 内联字符串,禁止 prettier 二次改写(会改变注入字节)。 - 模板 zip 与线上索引**未重新发布**(`template-library` 只改本地源); 生成期契约落位(玩法 skill / Runtime Prompt 强制标注 + 重新发布模板产物)另立里程碑。 - 芯片名归一化口径:引擎档(`elementTag === 'canvas'`)唯一命中即归一化为 manifest 显示名; DOM 档仅在 label 恰为该 `sourcePath` 的文件名词干时才归一化,其余原样保留。 ## 截图 ![three.js:贴图 Mesh 自动档 / userData 显式档](https://git.genarrative.world/git/attachments/9f2aabd5-b1f4-4b41-a760-e6cafd722bbe) three.js 场景:贴图 Mesh 自动档(`@hero`)、`userData` 显式档(`@enemy`)、点空白(`@canvas`)、DOM HUD(`@HUD 区域`)。 ![Phaser + Image 装载](https://git.genarrative.world/git/attachments/b30f4cb3-284a-434c-8837-8c1d9a76e3ff) Phaser(`loader.imageLoadType='HTMLImageElement'`):自动档 `@hero`、显式档 `@enemy`、非交互精灵几何兜底 `@hero`、点空白 `@canvas`、DOM HUD 不变。 ![Phaser 默认 XHR 装载](https://git.genarrative.world/git/attachments/c6ade083-ad38-4af6-b698-1b810ba90645) Phaser(默认 XHR):同一个贴图精灵退化为 `@heroUpper`(`resourceIds=[]`)——已知限制(贴图地址是 `blob:`)的证据。
suzmii added 6 commits 2026-10-04 23:39:48 +08:00
- 预览桥脚本从 preview.rs 的 Rust 字符串常量搬到 resources/preview/local-preview-fit.js,改由 include_str! 引用,尺寸上报与 DOM 点选行为逐字不变
- 抽出共享命中解析,DOM 档语义保持原样
- 新增 canvas 引擎档:只认玩法发布的只读句柄,实现 Phaser 4 与 three.js 两条适配与几何兜底
- 素材身份显式标注优先于贴图地址推断,取不到时退化为不带素材的区域引用,不伪造 id
- 新增引擎档用例,直接加载随包桥脚本文件断言消息载荷
- 随包桥脚本加入 prettier 排除,保持逐字内容
- 新增匹配纯函数:显式 id、精确路径后缀、文件名、序列帧地址四档,未知值一律丢弃
- 恰好命中一个素材且标签由文件名派生时,芯片名归一化为资源显示名
- 点选处理改为调用该纯函数,派发载荷字段与顺序不变
- 新增匹配与标签归一化的单元用例
- 新建项目默认脚本创建 Phaser 实例后发布只读句柄
- Phaser 与 three.js 两个起步模板及空白三维场景模板同样发布句柄
- Phaser 脚手架与模板改用 Image 标签装载图片,让贴图保留原始素材地址
- 功能说明新增运行画面素材点选的行为合同、退化条款与边界(贴图地址不可得、只认显式句柄)
- PRD 补点选素材条款与更新时间摘要
- 踩坑记录新增 Phaser 命中顺序与默认 XHR 装载两条
- 新增本里程碑与实施计划文档
- 功能说明的验收证据表填入自动化与真实浏览器实测结果
- 里程碑验收标准按证据逐条勾选并补未覆盖项
- 实施计划补四个提交的落盘记录
Merge remote-tracking branch 'origin/master' into feat/agc-runtime-picking-engines
Project CI / AI game creator shell Rust crates (pull_request) Successful in 6m10s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 7m28s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 8m15s
Project CI / Backend tests (pull_request) Successful in 8m43s
Project CI / Frontend tests (pull_request) Successful in 2m47s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m27s
Project CI / Native shell tests (pull_request) Successful in 8m14s
Project CI / Repository checks (pull_request) Successful in 6m38s
b2307a5c5c
# Conflicts:
#	docs/project-memory/shared-memory/pitfalls.md
Author
Member

合并前检查清单

已验证(本轮 merge origin/master 后复跑,全部在合并后的顶端 b2307a5c5 上)

  • npm run agc:typecheck → EXIT=0(check:tests:types / tsc / skill-pack 指纹 / 包布局声明 / check-config 全过)
  • npx vitest run 四文件:runtimeInspectEngines(27)+ runtimeInspectResourceMatch(11)+ localGamePreviewFrame(14)+ resourceReferenceInput(43)→ 4 passed / 95 passed
  • npx vitest run apps/ai-game-creator-shell/tests/appSurface.test.ts → 197 passed / 9 skipped
  • cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --offline -- preview → 44 passed / 0 failed
  • 同路径 -- scaffold → 5 passed / 0 failed / 1 既有 #[ignore](需 npm 装依赖 + Provider)
  • node scripts/check-doc-index.mjs、npm run check:encoding(5272 files)、git diff --check → 全通过
  • git status --porcelain → 空

真实浏览器(Chromium)端到端冒烟

真实 Phaser 4.2.1 / three 0.184 + 真实桥脚本 apps/ai-game-creator-shell/src-tauri/resources/preview/local-preview-fit.js,
被测版本 sha256 6276ac48…917a(合并前后一致)。芯片名与载荷实测值见正文「验证证据」,
截图见正文「截图」:已登记贴图对象 ["hero"]、显式标注对象 ["enemy-tag"]、
非交互精灵经几何兜底命中 ["hero"]、点空白 @canvas + [] 零报错、DOM 档芯片名不被改写、
高亮矩形与期望逐值相减 Phaser 0px / three ≈0.0006px。

未覆盖(评审请勿当成已验)

Tauri 真机链路(预览服务器注入、/__genarrative/local-preview-fit.js 路由、去重扫描由 cargo test … -- preview 覆盖)、
多场景叠加、非默认相机(scroll/zoom/rotation)、高亮矩形的真机目视。

范围

本 PR 对应 #612 阶段一:桥脚本搬迁 + canvas 引擎档识别 + 宿主四档匹配与芯片名归一化 + 脚手架/模板发布句柄与装载方式。
阶段二(生成期契约:AGC 玩法 skill / Runtime Prompt 强制「发布句柄 + 用已登记素材渲染的对象标注素材身份 + 素材以稳定路径进 dist」、
以及模板 template.zip 与线上索引重新发布)在同一 PR 续推,验收判据见正文「评审提示」。

评审提示

请勿合并前保持分支与 master 同步:本分支已 merge 过一次 origin/master(合并提交 b2307a5c5);
若 master 再前进请先同步再合,避免评审看到 tip-to-tip 大 diff。

## 合并前检查清单 **已验证(本轮 merge `origin/master` 后复跑,全部在合并后的顶端 `b2307a5c5` 上)** - `npm run agc:typecheck` → EXIT=0(`check:tests:types` / `tsc` / skill-pack 指纹 / 包布局声明 / `check-config` 全过) - `npx vitest run` 四文件:`runtimeInspectEngines`(27)+ `runtimeInspectResourceMatch`(11)+ `localGamePreviewFrame`(14)+ `resourceReferenceInput`(43)→ 4 passed / **95 passed** - `npx vitest run apps/ai-game-creator-shell/tests/appSurface.test.ts` → **197 passed / 9 skipped** - `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --offline -- preview` → **44 passed / 0 failed** - 同路径 `-- scaffold` → **5 passed / 0 failed / 1 既有 `#[ignore]`**(需 npm 装依赖 + Provider) - `node scripts/check-doc-index.mjs`、`npm run check:encoding`(5272 files)、`git diff --check` → 全通过 - `git status --porcelain` → 空 **真实浏览器(Chromium)端到端冒烟** 真实 Phaser 4.2.1 / three 0.184 + 真实桥脚本 `apps/ai-game-creator-shell/src-tauri/resources/preview/local-preview-fit.js`, 被测版本 sha256 `6276ac48…917a`(合并前后一致)。芯片名与载荷实测值见正文「验证证据」, 截图见正文「截图」:已登记贴图对象 `["hero"]`、显式标注对象 `["enemy-tag"]`、 非交互精灵经几何兜底命中 `["hero"]`、点空白 `@canvas` + `[]` 零报错、DOM 档芯片名不被改写、 高亮矩形与期望逐值相减 Phaser 0px / three ≈0.0006px。 **未覆盖(评审请勿当成已验)** Tauri 真机链路(预览服务器注入、`/__genarrative/local-preview-fit.js` 路由、去重扫描由 `cargo test … -- preview` 覆盖)、 多场景叠加、非默认相机(`scroll`/`zoom`/`rotation`)、高亮矩形的真机目视。 **范围** 本 PR 对应 #612 阶段一:桥脚本搬迁 + canvas 引擎档识别 + 宿主四档匹配与芯片名归一化 + 脚手架/模板发布句柄与装载方式。 阶段二(生成期契约:AGC 玩法 skill / Runtime Prompt 强制「发布句柄 + 用已登记素材渲染的对象标注素材身份 + 素材以稳定路径进 dist」、 以及模板 `template.zip` 与线上索引重新发布)**在同一 PR 续推**,验收判据见正文「评审提示」。 **评审提示** 请勿合并前保持分支与 `master` 同步:本分支已 merge 过一次 `origin/master`(合并提交 `b2307a5c5`); 若 `master` 再前进请先同步再合,避免评审看到 tip-to-tip 大 diff。
suzmii added 1 commit 2026-10-04 23:54:59 +08:00
运行画面点选:生成期契约落进 AGC 玩法 Skill(阶段二)
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
0aed0faa9a
- agc-web-game-development/SKILL.md 新增「运行画面点选契约」:发布只读引擎句柄、Phaser 图片用 Image 标签装载、素材渲染对象标注 manifest 身份、素材进 dist 走与 localPath 对齐的稳定路径
- game-quality-checklist.md 与 agc-game-production-workflow/SKILL.md 只补指针,不在副本里复制契约
- skill-pack:sync 更新 manifest version=2026-08-26.38 与 agc-web-game-development、agc-game-production-workflow 的 sha256(未新增 skill 文件、未改 Rust)
- 文档:功能说明边界补生成期契约来源;里程碑把「生成期契约另立里程碑」改为同一 PR 阶段二;实施计划新增「阶段二进展」
Author
Member

阶段二:生成期契约落位(同一 PR 续推)

阶段一让运行画面能点出素材,但可用性依赖玩法满足三条约定(发布句柄、Phaser 用 Image 装载、对象标注素材身份);阶段二把它们写进生成期契约,新生成的 Phaser 4 / three.js 项目不改代码即可点出素材。提交 0aed0faa9。

落地清单

位置 改动
resources/agc-skills/agc-web-game-development/SKILL.md(主源,唯一写全契约处) 新增「运行画面点选契约(运行态素材身份)」四条:① 发布只读引擎句柄({ engine:'phaser', game } / { engine:'three', THREE, scene, camera, renderer },只服务点选与调试)② Phaser 固定 loader: { imageLoadType: 'HTMLImageElement' }(默认 XHR 装载只剩会话内临时地址)③ 素材渲染对象标注 manifest 身份(Phaser setData('genarrativeResourceId'|'genarrativeResourcePath', …),three.js mesh.userData.…,值只取 agc_list_registered_assets 的 localAssetId / localPath)④ 素材进 dist 走与 localPath 对齐的稳定路径(public/ 原样拷贝,不用 import 的 hash 产物名);并写明不满足时不报错、不伪造 id、退化为不带素材的区域引用(= 验收面)
agc-web-game-development/references/game-quality-checklist.md 只补一条勾选项(指针)
agc-game-production-workflow/SKILL.md 第 4 步(Game implementation)指向该契约(新游戏编排必读),不复制正文
resources/agc-skills/manifest.json skill-pack:sync:version 2026-08-26.37 → 2026-08-26.38,agc-web-game-development 与 agc-game-production-workflow 的 sha256 更新
文档 功能说明「边界与非目标」补生成期契约来源;里程碑把「生成期契约另立里程碑」改为同一 PR 阶段二;实施计划新增「阶段二进展」

skill_pack.rs 逐文件 include_bytes!,因此未新增 skill 文件、未改任何 Rust。

验证(工作树根,提交前最后一次运行)

命令 结果
npm run agc:typecheck exit 0(含 skill-pack 指纹校验、包布局声明、check-config)
npm --prefix apps/ai-game-creator-shell run skill-pack:test 3 passed / 0 failed,exit 0
node scripts/check-doc-index.mjs 通过:244 份 Markdown,current=119,historical=15,review=1
npm run check:encoding Encoding check passed for 5272 file(s).
git diff --check 无输出(clean)
git status --porcelain 提交后为空

边界确认

  • 阶段一内容未变:preview.rs、resources/preview/local-preview-fit.js(sha256 仍为 6276ac48…917a)、宿主匹配 runtimeInspectResourceMatch.ts、index.tsx、脚手架与三个模板源均未改动。
  • 未合并主线(不 merge、不 auto-merge、未动 master);模板 zip 与线上索引未重新发布。
  • 未新增依赖;git push 为普通推送(b2307a5c5..0aed0faa9),未 force。
## 阶段二:生成期契约落位(同一 PR 续推) 阶段一让运行画面能点出素材,但可用性依赖玩法满足三条约定(发布句柄、Phaser 用 Image 装载、对象标注素材身份);阶段二把它们写进**生成期契约**,新生成的 Phaser 4 / three.js 项目不改代码即可点出素材。提交 `0aed0faa9`。 ### 落地清单 | 位置 | 改动 | | --- | --- | | `resources/agc-skills/agc-web-game-development/SKILL.md`(主源,唯一写全契约处) | 新增「运行画面点选契约(运行态素材身份)」四条:① 发布只读引擎句柄(`{ engine:'phaser', game }` / `{ engine:'three', THREE, scene, camera, renderer }`,只服务点选与调试)② Phaser 固定 `loader: { imageLoadType: 'HTMLImageElement' }`(默认 XHR 装载只剩会话内临时地址)③ 素材渲染对象标注 manifest 身份(Phaser `setData('genarrativeResourceId'\|'genarrativeResourcePath', …)`,three.js `mesh.userData.…`,值只取 `agc_list_registered_assets` 的 `localAssetId` / `localPath`)④ 素材进 dist 走与 `localPath` 对齐的稳定路径(`public/` 原样拷贝,不用 `import` 的 hash 产物名);并写明不满足时不报错、不伪造 id、退化为不带素材的区域引用(= 验收面) | | `agc-web-game-development/references/game-quality-checklist.md` | 只补一条勾选项(指针) | | `agc-game-production-workflow/SKILL.md` | 第 4 步(Game implementation)指向该契约(新游戏编排必读),不复制正文 | | `resources/agc-skills/manifest.json` | `skill-pack:sync`:version `2026-08-26.37` → `2026-08-26.38`,`agc-web-game-development` 与 `agc-game-production-workflow` 的 sha256 更新 | | 文档 | 功能说明「边界与非目标」补生成期契约来源;里程碑把「生成期契约另立里程碑」改为同一 PR 阶段二;实施计划新增「阶段二进展」 | `skill_pack.rs` 逐文件 `include_bytes!`,因此**未新增 skill 文件、未改任何 Rust**。 ### 验证(工作树根,提交前最后一次运行) | 命令 | 结果 | | --- | --- | | `npm run agc:typecheck` | exit 0(含 skill-pack 指纹校验、包布局声明、check-config) | | `npm --prefix apps/ai-game-creator-shell run skill-pack:test` | 3 passed / 0 failed,exit 0 | | `node scripts/check-doc-index.mjs` | 通过:244 份 Markdown,current=119,historical=15,review=1 | | `npm run check:encoding` | `Encoding check passed for 5272 file(s).` | | `git diff --check` | 无输出(clean) | | `git status --porcelain` | 提交后为空 | ### 边界确认 - 阶段一内容未变:`preview.rs`、`resources/preview/local-preview-fit.js`(sha256 仍为 `6276ac48…917a`)、宿主匹配 `runtimeInspectResourceMatch.ts`、`index.tsx`、脚手架与三个模板源均未改动。 - **未合并主线**(不 merge、不 auto-merge、未动 master);**模板 zip 与线上索引未重新发布**。 - 未新增依赖;`git push` 为普通推送(`b2307a5c5..0aed0faa9`),未 force。
suzmii added 1 commit 2026-10-05 00:02:12 +08:00
去掉长期文档里的阶段性措辞
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 8m3s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 5m7s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m39s
Project CI / Frontend tests (pull_request) Successful in 2m22s
Project CI / Backend tests (pull_request) Successful in 7m58s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m51s
Project CI / Repository checks (pull_request) Successful in 7m7s
Project CI / Native shell tests (pull_request) Successful in 9m28s
7d205c8da0
- 功能说明「边界与非目标」的生成期契约条目:删掉「本里程碑阶段二,同一 PR 落位」这类开发过程话,保留可长期成立的口径
suzmii added 1 commit 2026-10-05 15:24:35 +08:00
运行画面点选:three 句柄瘦身 + 命中对象 label 兜底
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
19d179bde4
- 桥:three 句柄改读 `handle.three || handle.THREE`(旧整命名空间形态仍兼容),四个构造器缺任一即按未命中退化
- 桥:three label 链补 `object.name` → `geometry.type` → `object.type`,Phaser 补 `name` → `type`(取值超 40 字符丢弃);命中对象但取不到素材身份时芯片不再一律是 `@canvas`
- 契约:agc-web-game-development 的「运行画面点选契约」改用瘦身句柄 `three: { Raycaster, Vector2, Vector3, Box3 }`,并写明整命名空间会破坏 tree-shaking(同一 Vite 构建 517,682 B → 730,831 B,+41%);skill-pack 指纹同步到 2026-08-26.39
- 模板:threejs-3d-starter 与 blank-3d-scene 的句柄源改成瘦身形态
- 测试:runtimeInspectEngines 新增 6 例(瘦身句柄命中、旧命名空间兼容、name / geometry.type / object.type 兜底、缺构造器退化),共 33 例
- 文档:功能说明补 label 兜底与瘦身句柄的验收行和边界;pitfalls 记一条 tree-shaking 口径;实施计划阶段二进展补该轮结论
Author
Member

可见性补强 + three 句柄瘦身(针对实测「点选还是只能选到 canvas」)

提交 19d179bde(普通推送 7d205c8da..19d179bde,无 force)。

1. label 兜底:命中对象但取不到素材身份时不再一律 @canvas

场景 改前 改后(真实 Chromium + 真实 three 0.184 + 真实桥脚本实测)
three object.name = 'Crate'、无材质贴图、无 userData canvas Crate,矩形 143×143(对象区域)
three 无名字的 SphereGeometry canvas SphereGeometry,矩形 227×227
Phaser 无贴图对象 canvas object.name → object.type
  • 链路:three object.name → geometry.type → object.type;Phaser 在 texture.key 之后补 name → type。取值 trim 后超过 40 字符一律丢弃,避免把程序化命名塞进芯片。
  • 有素材身份时不受影响:真实 three 实测 userData.genarrativeResourceId 仍是 resourceIds: ["local-asset:probe"],label 只作为无身份时的兜底。

2. three 句柄瘦身(tree-shaking)

  • 推荐形态:window.__GENARRATIVE_PREVIEW_GAME__ = { engine: 'three', three: { Raycaster, Vector2, Vector3, Box3 }, scene, camera, renderer }。
  • 包体实测对照(同一个 Vite 构建):传整个 THREE 命名空间 730,831 B vs 只传 4 个构造器 517,682 B → +213,149 B ≈ +41%。
  • 桥端 handle.three || handle.THREE 两种形态都读(旧项目不回归);四个构造器缺任一即按未命中退化。
  • 模板 threejs-3d-starter 与 blank-3d-scene 的句柄源改成瘦身形态;契约文本(agc-web-game-development「运行画面点选契约」)写明「不要传整个 three 命名空间」及原因,skill-pack 指纹同步到 2026-08-26.39。

3. 重要:改完必须重启 AGC 客户端

桥脚本是 include_str! 编译期内嵌进客户端的(sha256 6276ac48…917a → 877dbba8…a831)。不重启客户端,预览页拿到的仍是旧桥,label 兜底与瘦身句柄都不会生效。

4. 验证

命令 结果
npx vitest run runtimeInspectEngines / runtimeInspectResourceMatch / localGamePreviewFrame / resourceReferenceInput 4 files passed,101 passed(runtimeInspectEngines 33 例,新增 6 例)
npm run agc:typecheck exit 0(含 skill-pack 指纹 2026-08-26.39、包布局、check-config)
node scripts/check-doc-index.mjs 通过:244 份 Markdown
npm run check:encoding Encoding check passed for 5272 file(s).
git diff --check / git status --porcelain clean / 提交后为空

真实浏览器证据(真实 Chromium + three 0.184 + 真实桥脚本,临时夹具与本地 http 服务已删除):slim 句柄命中、Crate / SphereGeometry / LegacyMesh(旧命名空间句柄)三种芯片名 + 命中对象区域矩形。

5. 边界

  • 未合并主线(不 merge、不 auto-merge);未动用户项目目录;模板 zip 与线上索引未重新发布。
  • 顺带把两份文档里的 runtimeInspectEngines 例数 27 → 33(功能说明与里程碑的证据表;同一 PR 内保持同一口径)。
## 可见性补强 + three 句柄瘦身(针对实测「点选还是只能选到 canvas」) 提交 `19d179bde`(普通推送 `7d205c8da..19d179bde`,无 force)。 ### 1. label 兜底:命中对象但取不到素材身份时不再一律 `@canvas` | 场景 | 改前 | 改后(真实 Chromium + 真实 three 0.184 + 真实桥脚本实测) | | --- | --- | --- | | three `object.name = 'Crate'`、无材质贴图、无 userData | `canvas` | `Crate`,矩形 143×143(对象区域) | | three 无名字的 `SphereGeometry` | `canvas` | `SphereGeometry`,矩形 227×227 | | Phaser 无贴图对象 | `canvas` | `object.name` → `object.type` | - 链路:three `object.name` → `geometry.type` → `object.type`;Phaser 在 `texture.key` 之后补 `name` → `type`。取值 trim 后超过 40 字符一律丢弃,避免把程序化命名塞进芯片。 - 有素材身份时不受影响:真实 three 实测 `userData.genarrativeResourceId` 仍是 `resourceIds: ["local-asset:probe"]`,label 只作为无身份时的兜底。 ### 2. three 句柄瘦身(tree-shaking) - 推荐形态:`window.__GENARRATIVE_PREVIEW_GAME__ = { engine: 'three', three: { Raycaster, Vector2, Vector3, Box3 }, scene, camera, renderer }`。 - 包体实测对照(同一个 Vite 构建):传整个 `THREE` 命名空间 **730,831 B** vs 只传 4 个构造器 **517,682 B** → **+213,149 B ≈ +41%**。 - 桥端 `handle.three || handle.THREE` 两种形态都读(旧项目不回归);四个构造器缺任一即按未命中退化。 - 模板 `threejs-3d-starter` 与 `blank-3d-scene` 的句柄源改成瘦身形态;契约文本(`agc-web-game-development`「运行画面点选契约」)写明「不要传整个 `three` 命名空间」及原因,`skill-pack` 指纹同步到 `2026-08-26.39`。 ### 3. 重要:改完必须重启 AGC 客户端 桥脚本是 `include_str!` **编译期内嵌**进客户端的(sha256 `6276ac48…917a` → `877dbba8…a831`)。不重启客户端,预览页拿到的仍是旧桥,label 兜底与瘦身句柄都不会生效。 ### 4. 验证 | 命令 | 结果 | | --- | --- | | `npx vitest run runtimeInspectEngines / runtimeInspectResourceMatch / localGamePreviewFrame / resourceReferenceInput` | 4 files passed,**101 passed**(`runtimeInspectEngines` 33 例,新增 6 例) | | `npm run agc:typecheck` | exit 0(含 skill-pack 指纹 `2026-08-26.39`、包布局、check-config) | | `node scripts/check-doc-index.mjs` | 通过:244 份 Markdown | | `npm run check:encoding` | `Encoding check passed for 5272 file(s).` | | `git diff --check` / `git status --porcelain` | clean / 提交后为空 | 真实浏览器证据(真实 Chromium + three 0.184 + 真实桥脚本,临时夹具与本地 http 服务已删除):slim 句柄命中、`Crate` / `SphereGeometry` / `LegacyMesh`(旧命名空间句柄)三种芯片名 + 命中对象区域矩形。 ### 5. 边界 - 未合并主线(不 merge、不 auto-merge);未动用户项目目录;模板 zip 与线上索引未重新发布。 - 顺带把两份文档里的 `runtimeInspectEngines` 例数 27 → 33(功能说明与里程碑的证据表;同一 PR 内保持同一口径)。
suzmii added 1 commit 2026-10-05 15:31:52 +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
629369eb0c
- pitfalls:新增「three 档句柄少构造器会整体失效」(Raycaster/Vector2/Vector3/Box3 缺任一即不进引擎档、芯片回落 canvas 且不报错,含四步排查顺序)与「预览桥脚本是编译期内嵌的:改完必须重启 AGC 客户端」
- 实施计划·阶段二进展:补真机复验环境已就绪(客户端自本分支编译启动、exe 内 6 处新代码标记已核实、CDP 可用)与「点选复验待执行」(客户端登录态过期停在登录页)
suzmii added 1 commit 2026-10-05 15:43:50 +08:00
补预览桥注入与去重的覆盖空白说明
Project CI / Backend tests (pull_request) Failing after 17s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 6m37s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m30s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m30s
Project CI / Repository checks (pull_request) Failing after 34s
Project CI / Frontend tests (pull_request) Successful in 3m34s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m30s
Project CI / Native shell tests (pull_request) Successful in 9m39s
8d1980488e
- 踩坑记录新增 2026-10-05 条:preview.rs 的标签注入与去重没有用例覆盖,列出 4 个既有用例并给出人工验证清单
suzmii added 1 commit 2026-10-05 17:08:14 +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
7ad412f0ec
- 根因:高亮框(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 记一条「高亮框被尺寸上报当成页面内容」的根因、口径与回归
Author
Member

BUG 修复:点选 3D 对象后预览画面自己缩放(B2)

提交 7ad412f0e(普通推送 8d1980488..7ad412f0e)。

1. 根因因果链(实证得出,非推测)

  1. 进入检查模式后 hover,桥创建高亮框:resources/preview/local-preview-fit.js:422 inspectOverlay() → :427 document.body.appendChild(overlay),样式 position: fixed,尺寸 = 命中矩形。
  2. 尺寸上报把 body 下所有元素都算进内容尺寸:local-preview-fit.js:336 contentBounds = measureContentBounds(body, …) → :186 document.createTreeWalker(body, NodeFilter.SHOW_ELEMENT),对每个 rect.width>0||height>0 的元素取 rect.right + scrollX / rect.bottom + scrollY 计入上限。
  3. three 档的命中矩形来自 Box3 八角投影(:1048 一带),物体贴近相机时投影盒远超画布:实测高亮框 rect = [-2852, -2078, 6607, 4721]。
  4. 于是上报的内容尺寸从「视口 900×560」跳到 3756×2643。
  5. 宿主按上报尺寸重算适配:LocalGamePreviewFrame.tsx:183 resolveLocalGamePreviewFitLayout → :443 把 iframe 设为 3756×2643 + scale(0.2119)。
  6. iframe 视口变大 → 游戏 resize → 相机 aspect/重新适配距离变化 → 视口又变大 → 自激振荡;点选结束后视口停在放大状态(相机 aspect 停在 1.421112 而不是 1.607143)。

2. 修复(两处,均在桥内,不改点选语义与消息字段)

  • local-preview-fit.js:176 isPreviewBridgeNode + :186 measureContentBounds 的 TreeWalker acceptNode:对 data-genarrative-preview-fit / data-genarrative-preview-inspect 返回 FILTER_REJECT —— 桥自己的节点一律不参与内容尺寸测量。
  • local-preview-fit.js:520 clipInspectRect:引擎档命中矩形统一裁剪到画布可见范围(:867 Phaser、:1048 three);与画布无交集时退化为指针点矩形(width/height 至少 1)。DOM 档语义与消息协议未改。

3. 前后对照(真实 Chromium + 真实 three 0.184 + 真实桥脚本 + 按宿主 resolveLocalGamePreviewFitLayout 逐行复刻的宿主页)

夹具:900×560 容器 / iframe,页面是「全窗口 canvas + resize 里改 aspect 并重新适配」的 three 游戏,贴近相机的大圆柱(投影盒超出画布);动作 = ① 进入检查模式 ② hover 出现高亮框 ③ 点中对象。

指标 修复前 修复后
尺寸消息条数 1459 3(只有加载期)
内容/视口尺寸 3756×2643 @900×560 ×728 与 3756×2643 @3756×2643 ×728(振荡) 仅 300×150 / 300×150@900×560 / 900×560@900×560
iframe 布局变更 1457 次(900x560@1 ↔ 3756x2643@0.2119) 1 次(初始 900x560@1.0000)
游戏 resize 事件 1454 次 1 次(初始)
相机 aspect 1.607143 ↔ 1.421112 振荡,结束停在 1.421112 恒 1.607143;zoom 恒 1、位置不变
视口 / document 滚动尺寸 振荡到 3756×2643 恒 900×560
高亮框 rect [-2852, -2078, 6607, 4721] [0, 0, 904, 564](= 画布 900×560 + overlay 自身 2px 边框)

(夹具与本地 http 服务已删除;三种动作的快照分别记录在夹具里,evidence 为上方数字。)

4. 用例(新增 5 例,回归可抓)

apps/ai-game-creator-shell/tests/localPreviewInspectSizeStability.test.ts:

  1. 尺寸上报把桥自己的节点排除在内容测量之外(同样大小的普通节点仍会被计入)——含对照组(4000×3000 普通节点必须撑大上报),证明用例对「内容尺寸被撑大」敏感;
  2. 进入检查模式与 hover 出现高亮框后:尺寸上报与宿主适配布局都不变——同一用例里断言 resolveLocalGamePreviewFitLayout(真实宿主函数)在点选前后都返回 900×560@1;
  3. three 投影盒超出画布时:载荷矩形被裁剪到画布内,width/height 不为 0;
  4. 投影盒与画布完全无交集时退化为指针点矩形,不产生 0 或负尺寸;
  5. Phaser 世界包围盒超出画布时同样裁剪到画布内。

敏感性验证:把这 5 例跑在修复前的桥(git show HEAD^:...local-preview-fit.js)上 → 5 failed;跑在修复后 → 5 passed。

既有套件:runtimeInspectEngines(33)+ 新增(5)+ localGamePreviewFrame(14)+ resourceReferenceInput(43)= 95 passed;appSurface.test.ts 197 passed / 9 skipped;npm run agc:typecheck exit 0(tsc 0 error);npm run check:encoding 通过(5273 文件);git diff --check clean;提交后 git status --porcelain 为空。

注:runtimeInspectEngines 里「没有 matrixCombined 时按相机字段换算」一例原本断言一个落在画布外的矩形(屏幕 -397..-197),新规则下它应退化为指针点矩形;已把该用例的参数换到画布内的等价取值(scrollX/Y = -400/-300),仍断言「宽 200 高 100 = 世界尺寸的 2 倍」,未放宽任何断言。

5. 边界 / 未覆盖

  • 未合并、未发布;未动「运行页刷新按钮」相关代码;未改用户项目。
  • 真机复验待执行:本轮期间真机客户端进程已退出(非我停止:agc-dev-real 以 exit 0 结束),且此前登录态过期未登录,因此「真机里点选后画面不缩放」尚未实测;已请求重启并登录后补测。
## BUG 修复:点选 3D 对象后预览画面自己缩放(B2) 提交 `7ad412f0e`(普通推送 `8d1980488..7ad412f0e`)。 ### 1. 根因因果链(实证得出,非推测) 1. 进入检查模式后 hover,桥创建高亮框:`resources/preview/local-preview-fit.js:422` `inspectOverlay()` → `:427` `document.body.appendChild(overlay)`,样式 `position: fixed`,尺寸 = 命中矩形。 2. 尺寸上报把 body 下**所有元素**都算进内容尺寸:`local-preview-fit.js:336` `contentBounds = measureContentBounds(body, …)` → `:186` `document.createTreeWalker(body, NodeFilter.SHOW_ELEMENT)`,对每个 `rect.width>0||height>0` 的元素取 `rect.right + scrollX` / `rect.bottom + scrollY` 计入上限。 3. three 档的命中矩形来自 `Box3` 八角投影(`:1048` 一带),物体贴近相机时**投影盒远超画布**:实测高亮框 rect = `[-2852, -2078, 6607, 4721]`。 4. 于是上报的内容尺寸从「视口 900×560」跳到 **3756×2643**。 5. 宿主按上报尺寸重算适配:`LocalGamePreviewFrame.tsx:183 resolveLocalGamePreviewFitLayout` → `:443` 把 iframe 设为 `3756×2643` + `scale(0.2119)`。 6. iframe 视口变大 → 游戏 `resize` → 相机 `aspect`/重新适配距离变化 → 视口又变大 → **自激振荡**;点选结束后视口停在放大状态(相机 aspect 停在 1.421112 而不是 1.607143)。 ### 2. 修复(两处,均在桥内,不改点选语义与消息字段) - `local-preview-fit.js:176 isPreviewBridgeNode` + `:186` `measureContentBounds` 的 TreeWalker `acceptNode`:对 `data-genarrative-preview-fit` / `data-genarrative-preview-inspect` 返回 `FILTER_REJECT` —— 桥自己的节点一律不参与内容尺寸测量。 - `local-preview-fit.js:520 clipInspectRect`:引擎档命中矩形统一**裁剪到画布可见范围**(`:867` Phaser、`:1048` three);与画布无交集时退化为指针点矩形(`width/height` 至少 1)。DOM 档语义与消息协议未改。 ### 3. 前后对照(真实 Chromium + 真实 three 0.184 + 真实桥脚本 + 按宿主 `resolveLocalGamePreviewFitLayout` 逐行复刻的宿主页) 夹具:900×560 容器 / iframe,页面是「全窗口 canvas + resize 里改 aspect 并重新适配」的 three 游戏,贴近相机的大圆柱(投影盒超出画布);动作 = ① 进入检查模式 ② hover 出现高亮框 ③ 点中对象。 | 指标 | 修复前 | 修复后 | | --- | --- | --- | | 尺寸消息条数 | 1459 | **3**(只有加载期) | | 内容/视口尺寸 | `3756×2643 @900×560` ×728 与 `3756×2643 @3756×2643` ×728(振荡) | 仅 `300×150` / `300×150@900×560` / `900×560@900×560` | | iframe 布局变更 | **1457 次**(`900x560@1` ↔ `3756x2643@0.2119`) | **1 次**(初始 `900x560@1.0000`) | | 游戏 `resize` 事件 | 1454 次 | **1 次**(初始) | | 相机 `aspect` | 1.607143 ↔ 1.421112 振荡,结束停在 1.421112 | **恒 1.607143**;`zoom` 恒 1、位置不变 | | 视口 / `document` 滚动尺寸 | 振荡到 3756×2643 | 恒 900×560 | | 高亮框 rect | `[-2852, -2078, 6607, 4721]` | `[0, 0, 904, 564]`(= 画布 900×560 + overlay 自身 2px 边框) | (夹具与本地 http 服务已删除;三种动作的快照分别记录在夹具里,evidence 为上方数字。) ### 4. 用例(新增 5 例,回归可抓) `apps/ai-game-creator-shell/tests/localPreviewInspectSizeStability.test.ts`: 1. `尺寸上报把桥自己的节点排除在内容测量之外(同样大小的普通节点仍会被计入)`——含对照组(4000×3000 普通节点必须撑大上报),证明用例对「内容尺寸被撑大」敏感; 2. `进入检查模式与 hover 出现高亮框后:尺寸上报与宿主适配布局都不变`——同一用例里断言 `resolveLocalGamePreviewFitLayout`(真实宿主函数)在点选前后都返回 `900×560@1`; 3. `three 投影盒超出画布时:载荷矩形被裁剪到画布内,width/height 不为 0`; 4. `投影盒与画布完全无交集时退化为指针点矩形,不产生 0 或负尺寸`; 5. `Phaser 世界包围盒超出画布时同样裁剪到画布内`。 **敏感性验证**:把这 5 例跑在修复前的桥(`git show HEAD^:...local-preview-fit.js`)上 → **5 failed**;跑在修复后 → **5 passed**。 既有套件:`runtimeInspectEngines`(33)+ 新增(5)+ `localGamePreviewFrame`(14)+ `resourceReferenceInput`(43)= **95 passed**;`appSurface.test.ts` **197 passed / 9 skipped**;`npm run agc:typecheck` exit 0(tsc 0 error);`npm run check:encoding` 通过(5273 文件);`git diff --check` clean;提交后 `git status --porcelain` 为空。 > 注:`runtimeInspectEngines` 里「没有 matrixCombined 时按相机字段换算」一例原本断言一个**落在画布外**的矩形(屏幕 -397..-197),新规则下它应退化为指针点矩形;已把该用例的参数换到画布内的等价取值(scrollX/Y = -400/-300),仍断言「宽 200 高 100 = 世界尺寸的 2 倍」,未放宽任何断言。 ### 5. 边界 / 未覆盖 - 未合并、未发布;未动「运行页刷新按钮」相关代码;未改用户项目。 - **真机复验待执行**:本轮期间真机客户端进程已退出(非我停止:`agc-dev-real` 以 exit 0 结束),且此前登录态过期未登录,因此「真机里点选后画面不缩放」尚未实测;已请求重启并登录后补测。
suzmii added 1 commit 2026-10-05 17:11:53 +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
582fabdfbb
- 功能说明「必须成立的行为」新增第 7、8 条:点选不改变预览适配、命中区域裁剪在画布内
- 功能说明「验收标准与证据」补两行:尺寸稳定性用例(5 例)与真实 Chromium 对照值、命中区域裁剪与退化证据
- PRD §3.4「点选素材」条款末尾补一句:点选不得改变预览的内容尺寸与适配缩放,命中区域只取画布内可见部分
suzmii added 1 commit 2026-10-05 17:13:09 +08:00
去掉长期文档里过期的桥脚本哈希
Project CI / Backend tests (pull_request) Failing after 15s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 6m29s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m8s
Project CI / Repository checks (pull_request) Failing after 17s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m26s
Project CI / Frontend tests (pull_request) Successful in 3m15s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m35s
Project CI / Native shell tests (pull_request) Successful in 8m53s
985b8f9fa6
- 功能说明「验收标准与证据」条款 2、3 行:删掉「被测桥脚本 sha256 `6276ac48…917a`」这句(实现产物哈希会随桥改动过期,取证时点与版本由 PR 评论承载),其余行为证据与 Tauri 链路结论原样保留
Author
Member

真机复验完成(三张图已附在正文的「### 真机复验」小节)

  • 客户端:本分支源码编译(exe 内含 BUG2 新标识 isPreviewBridgeNode / clipInspectRect),CDP Edg/154.0.4258.53。
  • 结果:点中 three 对象 → 芯片 @CylinderGeometry(title CylinderGeometry · 运行区域,非 canvas);点空白天空 → @canvas 退化、控制台 0 报错;命中高亮为对象级矩形且超出画布时被裁剪到画布内(实测 (84,200,746,458))。
  • 点选不改变预览适配(BUG2 回归验证):进入检查模式 / hover / 点中对象 / 点空白四阶段,iframe 的 src、style、getBoundingClientRect 逐值相同(830×658、scale(1))、尺寸上报全程仅 1 条、预览页内 resize 计数 0。
  • 附图:用户提供的四面体点选截图(信息栏 TetrahedronGeometry + 芯片 @TetrahedronGeometry)+ 本轮「点中对象」「点空白」两张。
  • 附注:点中对象后相机仍会缓动一次,是项目自身 pointerup → focusShape 的既有反应(玩法对所有点击都如此),与检查模式无关;桥只监听 click,不吞 pointerdown/pointerup。

待用户决定合并(本 PR 未合并)。

## 真机复验完成(三张图已附在正文的「### 真机复验」小节) - 客户端:本分支源码编译(exe 内含 BUG2 新标识 `isPreviewBridgeNode` / `clipInspectRect`),CDP `Edg/154.0.4258.53`。 - 结果:点中 three 对象 → 芯片 `@CylinderGeometry`(title `CylinderGeometry · 运行区域`,**非 `canvas`**);点空白天空 → `@canvas` 退化、控制台 0 报错;命中高亮为对象级矩形且超出画布时被裁剪到画布内(实测 `(84,200,746,458)`)。 - **点选不改变预览适配**(BUG2 回归验证):进入检查模式 / hover / 点中对象 / 点空白四阶段,iframe 的 `src`、`style`、`getBoundingClientRect` 逐值相同(`830×658`、`scale(1)`)、尺寸上报全程仅 1 条、预览页内 `resize` 计数 **0**。 - 附图:用户提供的四面体点选截图(信息栏 TetrahedronGeometry + 芯片 `@TetrahedronGeometry`)+ 本轮「点中对象」「点空白」两张。 - 附注:点中对象后相机仍会缓动一次,是项目自身 `pointerup → focusShape` 的既有反应(玩法对所有点击都如此),与检查模式无关;桥只监听 `click`,不吞 `pointerdown/pointerup`。 **待用户决定合并**(本 PR 未合并)。
suzmii added 1 commit 2026-10-05 18:26:19 +08:00
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
364b1aa342
- 冲突解决(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),真机证据对应字节不变
Author
Member

合并前同步:已并入 origin/master 并解决全部冲突(未合并 PR)

  • 同步前 origin/master:21c79f54a;本分支 985b8f9fa(behind 25 / ahead 14)。
  • merge 提交:364b1aa34(两父:本分支 + origin/master,使用 merge 而非 rebase,评审过的提交链未变)。
  • 推送:普通推送(非 force)985b8f9fa..364b1aa34。

3 处冲突的解决

文件 解决方式
agc-game-production-workflow/SKILL.md 双方都保留:第 4 条用本分支版本(含「运行画面点选契约在 agc-web-game-development」指针),第 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 紧随),未改动任一方内容

另 2 个自动合并但已人工核对:

  • agc-web-game-development/SKILL.md:本分支「运行画面点选契约」小节(18 行)与 master 内容都在(git diff origin/master 仅这 18 行新增)。
  • index.tsx:handleRuntimeInspectSelection 回调体与合并前逐字一致,master 新增的命名任务相关代码都在。

关键不变量

  • 桥脚本 sha256 未变:9513020cfffa79128fb6355d44cdaabe666eefecbd96b7e807b15d2c4601bf76 → 真机截图与点选证据对应字节仍然成立。
  • git diff origin/master HEAD 只含本 PR 的改动集合(21 文件,3930 insertions / 532 deletions;大头是 preview.rs 的 raw string −508 行 ↔ 新增 local-preview-fit.js)。

门禁(合并后复跑)

  • npm run agc:typecheck:EXIT=0(tsc 0 error;[skill-pack] OK(version=2026-08-26.41))
  • picking 相关 5 文件:106 passed(runtimeInspectEngines 33 / localPreviewInspectSizeStability 5 / runtimeInspectResourceMatch 11 / localGamePreviewFrame 14 / resourceReferenceInput 43)
  • appSurface.test.ts:200 passed / 9 skipped(master 新增 3 例)
  • cargo test … -- preview:44 passed / 0 failed;-- scaffold:6 passed / 1 ignored(均为 --bin 形式;因客户端在跑占用 exe,且当前随包 plugins 是带编辑器 feature 的档位,故按仓库口径带 --features=cocos-editor-execute,unity-editor-execute,godot-editor-execute)
  • node scripts/check-doc-index.mjs 通过(244 份);npm run check:encoding 通过(5275 files);git diff --check 空;git status --porcelain 空

当前状态

  • PR #624:state=open、merged=false、mergeable=true、head 364b1aa34。
  • CI:pending(Project CI 8 个检查 "Waiting to run",含 Backend tests / Repository checks / Rust lanes),未等待结果。
  • 未合并(合并动作留给用户决定)。
## 合并前同步:已并入 `origin/master` 并解决全部冲突(**未合并 PR**) - 同步前 `origin/master`:`21c79f54a`;本分支 `985b8f9fa`(behind 25 / ahead 14)。 - **merge 提交**:`364b1aa34`(两父:本分支 + origin/master,使用 merge 而非 rebase,评审过的提交链未变)。 - 推送:普通推送(非 force)`985b8f9fa..364b1aa34`。 ### 3 处冲突的解决 | 文件 | 解决方式 | | --- | --- | | `agc-game-production-workflow/SKILL.md` | 双方都保留:第 4 条用本分支版本(含「运行画面点选契约在 `agc-web-game-development`」指针),第 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 紧随),未改动任一方内容 | 另 2 个自动合并但已人工核对: - `agc-web-game-development/SKILL.md`:本分支「运行画面点选契约」小节(18 行)与 master 内容都在(`git diff origin/master` 仅这 18 行新增)。 - `index.tsx`:`handleRuntimeInspectSelection` 回调体与合并前**逐字一致**,master 新增的命名任务相关代码都在。 ### 关键不变量 - 桥脚本 sha256 **未变**:`9513020cfffa79128fb6355d44cdaabe666eefecbd96b7e807b15d2c4601bf76` → 真机截图与点选证据对应字节仍然成立。 - `git diff origin/master HEAD` 只含本 PR 的改动集合(21 文件,3930 insertions / 532 deletions;大头是 `preview.rs` 的 raw string −508 行 ↔ 新增 `local-preview-fit.js`)。 ### 门禁(合并后复跑) - `npm run agc:typecheck`:EXIT=0(tsc 0 error;`[skill-pack] OK(version=2026-08-26.41)`) - picking 相关 5 文件:**106 passed**(`runtimeInspectEngines` 33 / `localPreviewInspectSizeStability` 5 / `runtimeInspectResourceMatch` 11 / `localGamePreviewFrame` 14 / `resourceReferenceInput` 43) - `appSurface.test.ts`:**200 passed / 9 skipped**(master 新增 3 例) - `cargo test … -- preview`:**44 passed / 0 failed**;`-- scaffold`:**6 passed / 1 ignored**(均为 `--bin` 形式;因客户端在跑占用 exe,且当前随包 `plugins` 是带编辑器 feature 的档位,故按仓库口径带 `--features=cocos-editor-execute,unity-editor-execute,godot-editor-execute`) - `node scripts/check-doc-index.mjs` 通过(244 份);`npm run check:encoding` 通过(5275 files);`git diff --check` 空;`git status --porcelain` 空 ### 当前状态 - PR #624:`state=open`、`merged=false`、**`mergeable=true`**、head `364b1aa34`。 - CI:`pending`(Project CI 8 个检查 "Waiting to run",含 Backend tests / Repository checks / Rust lanes),**未等待结果**。 - **未合并**(合并动作留给用户决定)。
suzmii added 1 commit 2026-10-05 18:32:06 +08:00
收口评审 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
df221f4eb9
- 功能说明第 8 条「命中区域裁剪在画布内」限定为引擎档,并说明 DOM 档仍是元素矩形;证据表对应行同步对齐
- 功能说明「边界与非目标」新增一条:引擎档对象名超过 40 字符按取不到处理(有意保留),宿主侧标签上限另为 120
- SKILL.md「运行画面点选契约」第 3 条补一句:素材 id 不含空白与路径分隔符(localAssetId 由客户端生成)
- skill-pack 指纹同步(agc-web-game-development version 2026-08-26.42 与 sha256)
suzmii merged commit 96859666ff into master 2026-10-05 19:16:03 +08:00
suzmii deleted branch feat/agc-runtime-picking-engines 2026-10-05 19:16:03 +08:00
Author
Member

✅ 已合并(merge 完成)

  • merge 提交:96859666ff631b73460a8643aa6a9b10f2d44a2d(short 96859666f),merged_at=2026-10-05T19:16:03+08:00,merged_by=suzmii(由用户执行;我未调用 merge 接口)。
  • 合并形式:普通 merge(父:fa42cdb13(master) + df221f4eb(本分支)),未 squash/rebase、分支未删。
  • origin/master 顶端:96859666f;git merge-base --is-ancestor df221f4eb origin/master 退出码 0(本分支内容已在 master)。

CI(head df221f4eb,8/8 success)

check 结论
AI game creator shell Rust crates success(4m29s)
AI game creator shell Rust lane 1/2 success(7m6s)
AI game creator shell Rust lane 2/2 success(5m50s)
Frontend tests success(3m26s)
Backend tests success(7m48s)
AI game creator shell web tests success(3m3s)
Repository checks success(7m15s)
Native shell tests success(9m30s)

合并后最小门禁

  • npx vitest run runtimeInspectEngines + localPreviewInspectSizeStability:在 origin/master 的临时 worktree 上跑 → 38 passed(33 + 5)。
  • cargo test … --bin … -- preview:44 passed / 0 failed(EXIT=0)。等价性依据:git diff df221f4eb 96859666f -- apps/ai-game-creator-shell/src-tauri 为空、master 额外改动未触及 shared-contracts,AGC Rust 侧逐字节一致。

真机证据

见本 PR 正文「### 真机复验(2026-10-05,客户端从本分支源码编译)」小节与三张附件(用户四面体点选 / 点中对象高亮+芯片 / 点空白回落 canvas)。

仍未做(后续里程碑/工位)

  1. 模板产物重新发布(阶段二第 3 条:template.zip 与线上索引);
  2. GLB 显式标注路径的真机确认;
  3. 多场景叠加、非默认相机(scroll/zoom/rotation)的真机目视。
## ✅ 已合并(merge 完成) - **merge 提交**:`96859666ff631b73460a8643aa6a9b10f2d44a2d`(short `96859666f`),`merged_at=2026-10-05T19:16:03+08:00`,`merged_by=suzmii`(由用户执行;我未调用 merge 接口)。 - 合并形式:普通 merge(父:`fa42cdb13`(master) + `df221f4eb`(本分支)),**未 squash/rebase、分支未删**。 - `origin/master` 顶端:`96859666f`;`git merge-base --is-ancestor df221f4eb origin/master` 退出码 **0**(本分支内容已在 master)。 ### CI(head `df221f4eb`,8/8 success) | check | 结论 | | --- | --- | | AI game creator shell Rust crates | success(4m29s) | | AI game creator shell Rust lane 1/2 | success(7m6s) | | AI game creator shell Rust lane 2/2 | success(5m50s) | | Frontend tests | success(3m26s) | | Backend tests | success(7m48s) | | AI game creator shell web tests | success(3m3s) | | Repository checks | success(7m15s) | | Native shell tests | success(9m30s) | ### 合并后最小门禁 - `npx vitest run runtimeInspectEngines + localPreviewInspectSizeStability`:在 **origin/master 的临时 worktree** 上跑 → **38 passed**(33 + 5)。 - `cargo test … --bin … -- preview`:**44 passed / 0 failed**(EXIT=0)。等价性依据:`git diff df221f4eb 96859666f -- apps/ai-game-creator-shell/src-tauri` 为空、master 额外改动未触及 `shared-contracts`,AGC Rust 侧逐字节一致。 ### 真机证据 见本 PR 正文「### 真机复验(2026-10-05,客户端从本分支源码编译)」小节与三张附件(用户四面体点选 / 点中对象高亮+芯片 / 点空白回落 canvas)。 ### 仍未做(后续里程碑/工位) 1. 模板产物重新发布(阶段二第 3 条:`template.zip` 与线上索引); 2. GLB 显式标注路径的真机确认; 3. 多场景叠加、非默认相机(scroll/zoom/rotation)的真机目视。
Sign in to join this conversation.