From f97653e8ee81b06d51efbbcedbb5d2e69fa24ba0 Mon Sep 17 00:00:00 2001 From: lili Date: Wed, 17 Jun 2026 15:06:35 -0700 Subject: [PATCH] =?UTF-8?q?docs(skills):=20=E8=92=B8=E9=A6=8F=20=C2=A710?= =?UTF-8?q?=E2=80=94=E2=80=94E1=20=E9=80=82=E9=85=8D=E5=99=A8=206=20?= =?UTF-8?q?=E6=97=8F=20+=20=E5=8A=A0=E6=97=8F=E9=85=8D=E6=96=B9=20+=20KTD1?= =?UTF-8?q?=20=E6=97=8F=E8=BE=B9=E7=95=8C=20+=20=E5=85=AD=E7=B1=BB?= =?UTF-8?q?=E8=B5=84=E4=BA=A7=E6=B6=88=E8=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把本会话 E1/E3 增量回写 game-e2e-cdp-harness.md §10(§7 知识沉淀硬约束): - 三族 → 六族(+flappy/seek/avoidance),覆盖休闲机制主要维度;补「加一族复用配方」7 步 - 新 ★ 族边界律:受控面输入能力足够,族边界由 behavior 复杂度定——aim-fire/drag/match-3 归 code-agent __GameBundle,不入声明式适配器(避越界+过拟合) - 新 ★ 六类资产消费:scene 顶层背景、music 经 url 不可消费(受控面无播文件音频=跨线缺口);Image stub 确定性验 url→drawImage 分支不必上浏览器 Co-Authored-By: Claude Opus 4.8 --- .agents/skills/game-e2e-cdp-harness.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.agents/skills/game-e2e-cdp-harness.md b/.agents/skills/game-e2e-cdp-harness.md index 6f244599..c8621454 100644 --- a/.agents/skills/game-e2e-cdp-harness.md +++ b/.agents/skills/game-e2e-cdp-harness.md @@ -121,10 +121,14 @@ ## 10. E1 2D 适配器:声明式 gameDefinition → 可玩件(plan 002 U1/U2 实证,2026-06-17) -固定架构消费侧 = 把 `SourceProject.gameDefinition`(声明式)适配成命中 `game-host.d.ts` GameInstance 的工厂(非 LLM 直写整 factory)。`game-runtime/src/adapter/`:`adaptGameDefinition(source)→GameHostFactory` 解释 entities/components(render)/scenes/rules + 最小 behavior 词汇(`input:hit-nearest-target`);`scaffold-from-source.mjs` 把 sourceProject 落成 `generated-factory.js`(entry-bundle 固定 import 目标)→ build.mjs → bundle(= 后端确定性 modify guard-pending 在等的"从源真构建"件)。**三 archetype 家族经同一适配器均过真九门**:① 静态点击(tap-targets)② realtime 漂移(drift-targets/update 行为)③ **控制类(control-x + fall-and-catch,paddle-intercept driver,点亮仅控制类才有的 I 门控制跟手)**。词汇:input(hit-nearest-target/control-x)· update(drift-targets/fall-and-catch)· rule(win/lose,序前优先)· assets[] 消费(spec-only 几何兜底)。退役"声明式过拟合/做不了真游戏"之虑。 +固定架构消费侧 = 把 `SourceProject.gameDefinition`(声明式)适配成命中 `game-host.d.ts` GameInstance 的工厂(非 LLM 直写整 factory)。`game-runtime/src/adapter/`:`adaptGameDefinition(source)→GameHostFactory` 解释 entities/components(render)/scenes/rules + behavior 词汇;`scaffold-from-source.mjs` 把 sourceProject 落成 `generated-factory.js`(entry-bundle 固定 import 目标)→ build.mjs → bundle(= 后端确定性 modify guard-pending 在等的"从源真构建"件)。**六 archetype 家族经同一适配器均过真九门 A–I + 首局门**,覆盖休闲玩法主要机制维度:① 静态点击(tap-targets)② realtime 漂移(drift-targets)③ **控制类(control-x+fall-and-catch,paddle-intercept,点亮仅控制类有的 I 门跟手)**④ flappy(flap+flappy-gap,重力穿缝,flap-to-gap)⑤ 导航/收集(move-lr+reach-goal,seek-x,方向式 steer+抵达计分)⑥ 辨别/规避(tap-safe+forensics `safe` 标记,tap-targets `safeOnly`,负反馈:点对计分/点错即负)。词汇:input(hit-nearest-target/control-x/flap/move-lr/tap-safe)· update(drift-targets/fall-and-catch/flappy-gap/reach-goal)· rule(win/lose,序前优先)· 六类资产消费。退役"声明式过拟合/做不了真游戏"之虑。**加一族的复用配方**:SUPPORTED_*_OPS 注册 op → onTap/update 加 op 块(操作 `entById` 取的实体)→ 关键事件发 `ctx.getEngine()` 反馈(过 F)→ driver 需读的实体态在 `_forensicsView().state()` additive 暴露 → fixture + 单测 + play-spec(driver/assertAfterPlay/expectLatch)→ `scaffoldFromSource`→build→九门→清场临时探针。 **★ 必踩契约坑(第一版写错):`_forensicsView()` 返 `{ seed?, state: ()=>snapshot }`,不是裸 snapshot。** `boot-game-host.js:283` 的 `host.state()` 调 `gameForensics.state()`——即 `game._forensicsView().state()`(state 是 thunk)。直接返 `{phase,...}` → `host.state()` 调 `.state()` 时 `undefined()` 抛错、九门 H 读不到态。参照 `tictactoe/generated-factory.js:226`。snapshot 给 `targets:[{idx,x,y,occupied}]`(中心逻辑坐标)喂 tap-targets driver、`phase`(booting|playing|gameover)+ 进展字段(score/moves)喂 H 门 latch。 **★ 声明式件过 F 门(真接线)须自带命中反馈**:适配器在命中/关键事件经 `ctx.getEngine()` 调 `particles.spawnEmitter`+`audio.synth.synthSfx`(null 容错),否则 `expectedEngineCallPrefixes:['particles.','audio.synth']` 的 F 门挂(纯声明式渲染无引擎叶调用)= game-feel + 门双赢。 **★ 边界**:适配器只解释声明式部分;复杂 behavior 真逻辑由 code agent 产、编进 bundle(`source-project.schema.json` behavior 仅 `{id,trigger}`,诚实边界)。单 behavior 声明式游戏**确可过 H 门 latch**(rule condition→outcome win/lose→phase=gameover+驻留),驳"声明式最小集过不了九门"之虑。 + +**★ 族边界 = 机制复杂度,非输入能力**:受控面 `InputEventType` 含 pointerdown/move/up + keydown/keyup(`api.d.ts:218`),足以接 aim-fire(键盘)/drag-aiming(拖拽)/match-3 的输入——但其**抛射物理/旋转瞄准/读盘消除是复杂 behavior 逻辑**,按 KTD1 归 code-agent `__GameBundle`,**不入声明式适配器**(强行内联=越界+过拟合,即 match-3 早被识破的"需更强 driver"同一坑)。适配器止于"简单声明式机制族",已覆 6 族 = 拐点。 + +**★ 六类资产消费(E3,对齐冻结 assetSpec `{id,category,ref,url?}`,无内联数据)**:sprite/character/ui/effect 经实体 render 组件 `.asset` 引用(url→`new Image`+drawImage,否则几何兜底);**scene = 顶层背景**(非实体引用,取首个 `category==='scene'`,url→满幅 drawImage / 默认底兜底);**music 经 url 不可消费**——冻结 `getEngine().audio` 仅 zzfx `synthSfx/synthSong`(合成非文件播放),无播 url 音频能力 = 跨线契约缺口(落 README,勿臆造消费路)。验 url→drawImage 分支(node 无 Image)用**最小 `Image` stub**(`globalThis.Image=class{complete=true;naturalWidth=64}`,finally 还原),确定性验"非兜底"路不必上浏览器。