W-G1 生成核心:brief→便宜模型写 GameHostFactory→esbuild __GameBundle iife→P1 bootGameHost
装载→本机 Chrome+CDP 七门真玩取证;失败回喂错因重试。只消费冻结契约,零改 P1/P2。
实测(deepseek-v4-flash 最便宜档):Pong/Simon/打地鼠 三款【七门全过真玩】,
单款 ¥0.01–0.03(远低于 ¥0.15 L1 闸门)。最优模型:flash 打底 + 难档升 deepseek-v4-pro(Simon 0 重试 ¥0.06)。
关键:实证「能生成代码 ≠ 能玩」——一处 prompt 输入坐标契约写错(误称 x/y∈[0,1],实为逻辑像素)
让生成游戏能编译/渲染/动但点击全失灵;Pong 因自走动画假绿混过、Simon 被正确判否。
为此加装 G 门(确定性 A/B 对照,隔离自走动画假绿)+ 修 prompt 后三款真过。
- harness:games/_wg1-gen/_shared/{entry-bundle 模板,index 模板,play.cdp.cjs 七门,serve-and-play.sh}(复用 ref buildRefHostConfig + browser-evidence.cjs)
- worker:wg1/gen-worker/worker/{_client(代理旁路),prompt(生成上下文包),validate(静态门+node --check),cost(¥折算),run(§3 编排+重试门)}
- golden-path 自检:ref 工厂 5/6(F=0 菜单态正确)+ probe 工厂 7/7 → harness 无假绿
- game-runtime/package.json:加 ws(CDP 驱动 devDep)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
12 KiB
W-G1 生成核心 · 交付报告(结论先行)
lane:
wg1/gen-worker(从spike/agentscope-wg1HEAD = dev/2.0.0 + 已落地 P1/P2/spike 切出)| 日期:2026-06-13 验证假设 HJ-GEN-001:便宜模型(new-api: DeepSeek-V4 / MiniMax)能在【插件库 + 装载契约】上写出可真玩的轻游戏;质量由 harness 门保证,非模型自觉。
0. 结论速览
结论:成立。便宜模型能可靠产出可真玩的轻游戏。 用最便宜档 deepseek-v4-flash 生成 3 款冒烟游戏,全部经 CDP 真机 Chrome 七门真玩通过,单款 ¥0.01–0.03(远低于 ¥0.15 L1 闸门,5–15× 余量)。
| 游戏 | 模型 | 真玩七门 | 重试 | ¥(上界) vs ¥0.15 |
|---|---|---|---|---|
| Pong 弹球 | deepseek-v4-flash | ✅ 7/7 | 0 | ¥0.0098 ✅ |
| 打地鼠 Whack | deepseek-v4-flash | ✅ 7/7 | 0 | ¥0.0136 ✅ |
| Simon 记忆 | deepseek-v4-flash | ✅ 7/7 | 2 | ¥0.0298 ✅ |
最关键的一条(必须如实传达):「能生成代码」≠「能玩」。本 lane 实证了这一点——一处由我方 prompt 写错的输入坐标契约(声称 x/y∈[0,1],实为逻辑像素)让所有生成游戏"能编译、能渲染、能动",但玩家点击全部失灵;Pong 因小球自走动画假绿混过初版门,Simon 因无自走动画被门正确判否。正是真玩门(而非"代码编译过")逮住了它。 修复 prompt + 加装「输入有效性确定性对照门」后,三款全部真过。
1. 产物靶与全链路(只消费冻结契约,零改 P1/P2)
brief → 便宜模型 → factory.js(纯 GameHostFactory 模块:默认导出,零引擎 import,能力经 boot.ctx)
↓ 通用壳(复用 ref buildRefHostConfig:标准 7 插件 wiring,仅 override factory)
entry-bundle.js → esbuild --global-name=__GameBundle → bundle.iife.js(引擎内联 265KB)
↓ index.html: window.__GameBundle.bootGameHost({canvas, recHook, onReady})
static-serve + 本机 Chrome(headless) + CDP → 七门真玩取证
- 冻结契约零修改:
game-host.d.ts/boot-game-host.js/ 6 受控面 /__GameBundle/bootGameHost全程只消费。 - 生成游戏落
game-runtime/games/_wg1-gen/(新建隔离子目录,零碰既有文件)——因生成游戏本质是 game-runtime 游戏(动态 importlittlejsengine、import../../../src/plugins/*、复用ref-host-config.js),esbuild 默认解析要求入口在 node_modules 可达处。worker(Python) 与报告留wg1/gen-worker/。详见games/_wg1-gen/.agent。 - 唯一对既有树的非生成改动:
game-runtime/package.json加ws(devDep,CDP 驱动用,ref harness 亦需)。
2. 真玩取证 harness:七道假绿守卫(false-green guard)
每款游戏经下列七门,全过才判 PASS(驱动 = games/_wg1-gen/_shared/play.cdp.cjs,复用 test/harness/browser-evidence.cjs):
| 门 | 判据 | 防的假绿 |
|---|---|---|
| A 装载 | __genBooted ∧ __gameHostEngineInitFired ∧ 无 bootError |
白屏 / 装载失败 |
| B 未捕获 | __genInternals.uncaught == [] ∧ 无 __gameHostBootError |
运行期报错 |
| C 掌帧 | __engine.frame 500ms 增量 ∈ [20,45](@60fps≈30) |
冻屏 / 失控 / 单步假推进 |
| D 真渲染 | #game-engine readback 有色像素(maxCh>80)>50 |
白屏 / 全黑 |
| E 活性 | 真玩全程 ≥2 个不同整帧哈希态 | 冻屏(多采样捕捉瞬时态) |
| F 真接线 | __engineCalls 经 recHook 含期望 call-ID(粒子/音效/数学) |
自绘伪装、没真用插件库/引擎 |
| G 输入有效 | 同 seed 再开无输入对照实例、推进到同一帧、整帧哈希 ≠ 有输入实例 | 靠自走动画蒙混过 E 的假绿 |
G 门是本 lane 关键发明:Pong/打地鼠有自走动画(球/地鼠),E 门会被自走动画满足、掩盖「输入失灵」。G 门用确定性 A/B 对照(new-api 生成 bundle seed 固定→自走部分逐帧确定)隔离出「输入到底改没改变游戏走向」——挡板位置 / Simon 轮次 / 打地鼠分数都会持续到对照帧,有输入≠无输入即证真可玩。
golden-path 自检(证 harness 可信):先用 ref 工厂(已知好)跑通整条链——5/6 门过、F=0(菜单态不调引擎,正确);再用最小 probe 工厂(确定性调 getEngine)→ 7/7 全过。harness 在真可玩上判过、在没真调引擎/没真响应输入时判否,无假绿。
3. 逐款四件套(真玩证据)
证据落
game-runtime/games/_wg1-gen/<game>/evidence/{first-paint.png, after-play.png, verdict.json}。
Pong 弹球(deepseek-v4-flash · 0 重试 · ¥0.0098)
- ①截图:竖屏弹球——白球在场、青色玩家挡板(已移到末次点击 x)、虚线中线、
Player:0 CPU:1(真打了一回合)、撞击红粒子。 - ②掌帧:Δframe=31(C✅)。③渲染:maxCh=255、有色像素满屏(D✅)。④真接线:
__engineCalls含particles.spawnEmitter/audio.synth.synthSfx(撞击反馈,F✅)。 - 输入有效(G✅):有输入态
0d7715dc≠ 无输入对照855a1c03@frame444 → 挡板真响应点击。228 行源码,export default createPongGame,ctx.random/ctx.getInput/ctx.time全受控。
打地鼠 Whack(deepseek-v4-flash · 0 重试 · ¥0.0136)
- ①截图:
得分:0、3×3 深色洞口、两只地鼠(棕圆+眼睛+腮红)正冒出。 - ②③④:C✅ / D✅(maxCh255) / F✅(命中粒子 + 冒出音效)。
- 输入有效(G✅):
a9de479b ≠ b0584efe@frame446 → 点击真改变游戏(命中/分数)。命中判定为自写"点到圆距"(不依赖网格/CCD)。
Simon 记忆(deepseek-v4-flash · 2 重试 · ¥0.0298)
- ①截图:
Round:1、Your turn!、红/绿/蓝/黄 2×2 大按钮。 - ②③④:C✅(Δ31) / D✅(maxCh255,bright272006) / F✅(序列音效
audio.synth.synthSfx+ 缓动math.easing.quadOut)。 - 输入有效(G✅):
a5100b7a ≠ f7530fdd@frame400 → 点击真推进序列/轮次。状态机(INIT→SHOWING→WAIT→PAUSE/FAIL)完整。 - 重试原因:附录 A——首版坐标错(修 prompt 前)/ 逻辑边界,靠错误回喂 3 轮内收敛。
4. 成本表 + 模型对比 → 最优模型
口径:quota=(prompt+completion×completion_ratio)×model_ratio×group_ratio(1.0);¥=quota/500000×7.3(/api/status 实拉)。¥为上界(不计 prompt 缓存折扣;精确 logs.quota 需网关 access token,sk- key 无管理权——留给创始人核)。reasoning_tokens 已计入 completion。
| 游戏(难度) | 模型 | 重试 | prompt/completion tok | ¥上界 | vs ¥0.15 |
|---|---|---|---|---|---|
| Pong(易) | deepseek-v4-flash | 0 | 2861 / 4775 | 0.0098 | ✅ 15× 余量 |
| 打地鼠(易+) | deepseek-v4-flash | 0 | 2899 / 7223 | 0.0136 | ✅ 11× |
| Simon(中) | deepseek-v4-flash | 2 | 9120 / 14220 | 0.0298 | ✅ 5× |
| Simon | deepseek-v4-pro | 0 | 2889 / 9445 | 0.0625 | ✅ |
| Simon | MiniMax-M2.7 | 1 | 5582 / 11912 | 0.1166 | ✅(贴闸门) |
最优模型结论:
- 默认 =
deepseek-v4-flash:最便宜(model_ratio 0.06 / completion_ratio 1.75),易档 0 重试 ¥0.01;难档(Simon)靠重试门兜(2 重试仍 ¥0.03)。 - 难档升级 =
deepseek-v4-pro:Simon 0 重试、¥0.06(2× flash 但仍极廉),可靠性最高。建议策略:flash 打底 + 耗尽重试自动升 pro。 - MiniMax 不优先:M2.7 completion_ratio=4 拉高成本(¥0.117 贴近闸门),可靠性不及 pro。
5. 五大坑(给主 agent / 创始人少踩半天)
- 【实测·最坑】受控输入 x/y 是逻辑像素不是 [0,1]:
boot-game-host.js:295x=(clientX-rect.left)/rect.width*VIEW_W(390)。ref 直接hitZone(e.x,e.y)用像素。若 prompt 误导模型"乘视口"→命中全爆掉、点击失灵,但代码照编译照渲染照动——只有真玩门逮得住。生成 prompt 的能力契约必须逐字对齐 boot-game-host 实际口径。 - 【实测】自走动画会制造假绿:有自走物(球/地鼠)的游戏,"画面变了"(E)≠"输入有效"。**必须加 G 门(确定性 A/B 对照)**才能证真可玩。
- 【实测】reasoning 模型吃 max_tokens:deepseek-v4-flash/MiniMax 是 reasoning 模型,reasoning_tokens 计入 completion 且可烧空可见 content(
finish_reason:length时 content 空)。max_tokens 须给足(本 worker 16000),否则截断→校验门拒→空转重试。 - 【实测】CDP 触摸要镜像 ref 范式:
Input.dispatchTouchEvent裸{x,y}点、touchStart→touchEnd 背靠背、坐标经c.width/dpr映射(非硬编码 390);加radius/force或长按反而不稳。 - 【实测·复用 spike】本机代理吃网关:
NO_PROXY须并100.64.0.8(_client.py 已内置),否则 SDK→502(curl 假通)。
6. 哪些游戏类型超出当前插件库能力(来自 20 基准交叉比对)
便宜模型受插件库门面缺口限制,非模型能力限制。当前 4 短板(详见 docs/agent-specs/2026-06-13-WG1-20经典轻游戏基准-review.md):
- ① 文本/分数 HUD🟡:无文本渲染门面,每款自
fillText(本冒烟可兜,但风格各异)。最高频缺口,建议 W-G1 后第一优先补门面。 - ② 网格/棋盘 grid🟡:无 tilemap 门面 → 2048/Tetris/Match-3/贪吃蛇/井字棋 网格态每款重写易出 bug。
- ③ 连续碰撞 CCD❌(真缺口):collision 仅离散 MTV,无 swept/toi → 高速小球(Breakout 高速/Asteroids 子弹/多球)穿透。冒烟刻意避开。
- ④ 手势 swipe/drag🟡:getInput 仅 5 类原始事件,无手势合成 → 愤怒小鸟拖拽蓄力/2048 滑动每款自缓存方向。
→ 本冒烟选 Pong/Simon/打地鼠 正是"零/最轻短板 + canvas 简单"的最干净子集(避开 Snake/2048/Cookie Clicker——它们撞①②)。
7. worker ↔ pipeline 接缝(留给创始人集成,§3 契约形状)
worker 已暴露「job in → result out」(worker/run.py:run_job):
- in:
{game_id, brief(题面), play_spec(CDP 输入+期望 call-ID), model, max_retries} - out(
results/<game>.json):{pass, retries, attempts[{stage,errors,usage}], factory_path, bundle_path, verdict(七门), tokens, request_ids} - 闭环:generate → validate(静态契约+
node --check) → bundle(esbuild) → play(CDP 七门) → 失败回喂错因重试 ≤N。 - 字段对齐你 spike VERDICT §3 的 REST/队列形状;待你拉取后冻结。
8. 蒸馏建议(留我 lane,待你拉进 .agents/,避免与你并行 P3 撞车)
skills/增补:把「§2 七门真玩 harness(尤其 G 门 A/B 对照)+ §5 五坑」蒸馏进game-e2e-cdp-harness.md(W-G1 复用并扩展了它)。rules/红线:「生成 prompt 能力契约必须逐字对齐 boot-game-host 实际口径(输入坐标=逻辑像素)」「能生成≠能玩:必须过真玩门+G 门」。knowledge/:HJ-GEN-001 验证结论(便宜模型可产可玩轻游戏 / 最优模型 flash 打底+pro 升级 / ¥0.01–0.06)。
附录 A · 复现
# 0) 前置:wg1/gen-worker/.env 写 NEWAPI_KEY(gitignored);game-runtime 先 npm i(含 ws)
# 1) 装 worker venv
uv venv wg1/gen-worker/.venv --python 3.12
uv pip install -p wg1/gen-worker/.venv/bin/python -r wg1/gen-worker/requirements.txt
# 2) 生成+真玩一款(generate→validate→bundle→CDP 七门)
wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/run.py pong --model deepseek-v4-flash --max-retries 2
# 3) 成本表
wg1/gen-worker/.venv/bin/python wg1/gen-worker/worker/cost.py
# 仅重放某款(不重新生成):
( cd game-runtime && bash games/_wg1-gen/_shared/serve-and-play.sh pong )