lili 046454d95e feat(adapter): E1 build→九门端到端验证——_adapter-probe 真九门全过(score 0→3 latch✓)
U1 前置另一半(plan 002):声明式 gameDefinition → 适配器 → entry-bundle → build.mjs → 真九门绿。
- _adapter-probe/:generated-factory(adaptGameDefinition+内联 source)+ entry-bundle(拷模板)+ index(拷模板)
  + play-spec(tap-targets driver, assert score increased, expectLatch) + bundle.iife.js(211KB, LittleJS 真入包)。
- 真九门(本机快走查):A装载/B未捕获0/C掌帧Δ30/D真渲染/E活性5/5/F真接线(particles+audio)/
  G输入有效/H 机制+latch(score 0→3 + 终态驻留)/I(无 controlCheck);首局门 可玩51ms/首反馈/60s闭环7s 全过。
- 适配器跟进:① _forensicsView 改契约形态 { seed, state:()=>snapshot }(对齐 boot-game-host:283 + tictactoe);
  ② 命中加引擎粒子+音效反馈(game-feel + 满足 F 门),经 ctx.getEngine 容错。单测仍 6/6 绿。

证成:E1(repo 标"真空白"最高风险件)声明式路端到端可行;build-from-sourceProject 管线(E2)可行;
回答 adversarial MVP-latch 质疑——单 behavior 声明式游戏确过 H 门 latch。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 13:46:17 -07:00

96 lines
5.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!--
index.template.html —— W-G1 通用 host 页模板(逐字拷进每个生成 game 目录为 index.html
ownerW-G1 lane 用法:
· 同目录 esbuild 产物 bundle.iife.jsglobalName=__GameBundle由本页 <script src> 加载;
· serve game-runtime 根CDP 导航到 /games/_wg1-gen/<game>/index.html
· 就绪标记 __genBootedbootGameHost().then 置real 引擎接管标记 __gameHostEngineInitFiredboot-game-host 内置);
· 假绿守卫钩子window.__engineCallsrecHook 记每次引擎能力调用 call-ID、window.__genInternalsonReady 收 uncaught[])。
布局收编(对齐 ref 教训canvas 顶在 (0,0) 满幅 390×844状态行 absolute overlay + pointer-events:none
绝不下推/截触摸(否则 CDP 真输入坐标整体偏移 + 底部不可点)。引擎自建 mainCanvas#game-engine 叠加渲染。
-->
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<!-- 固定取证视口390×844 移动竖屏基准user-scalable=no 防缩放扰动像素哈希。 -->
<meta name="viewport" content="width=390, height=844, initial-scale=1, user-scalable=no" />
<title>W-G1 generated game</title>
<style>
html, body { margin: 0; padding: 0; background: #111; color: #ccc;
font-family: -apple-system, "PingFang SC", monospace; overflow: hidden; }
#wrap { position: relative; width: 390px; margin: 0 auto; }
#game { width: 390px; height: 844px; background: #000; display: block; touch-action: none; }
/* 状态行默认隐藏boot-game-host 的「engine RAF running…」调试浮层会被截图带进画面、污染 player 视觉判分;
harness 真玩门读 JS 变量(__genBooted/__genBootError/console)判定,不依赖此可视行,故隐藏不影响七门。
仅 BOOT ERROR 时由下方脚本显式显示,便于人工排查。 */
#status { display: none; position: absolute; top: 0; left: 0; right: 0; z-index: 2; pointer-events: none;
font-size: 12px; line-height: 1.4; min-height: 15px; text-align: center; word-break: break-all;
opacity: 0.85; text-shadow: 0 1px 2px rgba(0,0,0,0.8); }
</style>
</head>
<body>
<div id="wrap">
<div id="status">booting…</div>
<!-- 受控画布opts.canvas 占位/输入兜底real 引擎自建 #game-engine 叠加。 -->
<canvas id="game"></canvas>
</div>
<!-- esbuild 产物iife 全局 __GameBundle含 GameHostFactory + bootGameHost-->
<script src="./bundle.iife.js"></script>
<script>
// 引导:取 __GameBundle.bootGameHost 启动;注入取证钩子;失败留痕 + 重抛(假绿守卫要看 console 零未捕获)。
(function () {
'use strict';
var statusEl = document.getElementById('status');
var canvas = document.getElementById('game');
// 假绿守卫C·真接线探针每次引擎能力被调recHook 记一条 call-ID 进此数组(证「真调引擎/插件库」非自绘伪装)。
window.__engineCalls = [];
function recHook(id) { try { window.__engineCalls.push(id); } catch (_) {} }
// 就绪/错误标记初值。
window.__genBooted = false;
window.__genBootError = null;
// W-G1 组C·首局门断言①「可玩≤2s」精确计时页面侧 performance.now() 在「可交互首帧」(__genBooted=true) 打点,
// 写 window.__playableAtMs= 自 navigationStart/timeOrigin 起的毫秒。harness 直接读它,
// 规避 ① CDP 轮询 ~300ms 粒度抖动 ② waitBoot 固定 settle floor 对计时的污染——二者都会让 harness 侧计时失真。
window.__playableAtMs = null;
try {
var G = window.__GameBundle;
if (!G || typeof G.bootGameHost !== 'function') {
throw new Error('__GameBundle.bootGameHost 未找到bundle.iife.js 未正确加载或 globalName 不符)');
}
G.bootGameHost({
canvas: canvas,
statusEl: statusEl,
recHook: recHook,
// onReady收集 internalsuncaught[] 等供假绿守卫B 读。
onReady: function (host, internals) {
window.__genHost = host;
window.__genInternals = internals || null;
}
})
.then(function (host) {
window.__genHost = window.__genHost || host;
// 可测性别名守卫H 经此读游戏可观测状态host.state() 透传 game._forensicsView().state游戏未实现则返回 {phase:'booting'})。
// 宿主侧挂载,工厂仍零 window与 ref 在 onReady 挂 __refForensics 同范式。
window.__gameState = function () { try { return host && typeof host.state === 'function' ? host.state() : null; } catch (_) { return null; } };
// 首局门断言①打点可交互首帧达成的墙钟performance.now() 以 navigationStart 为 0 点),供 harness 读取判 ≤2s。
try { window.__playableAtMs = (typeof performance !== 'undefined' && performance.now) ? performance.now() : null; } catch (_) {}
window.__genBooted = true; // CDP 探活标记区分「脚本没加载」与「boot 抛错」)
})
.catch(function (e) {
window.__genBooted = false;
window.__genBootError = String((e && e.message) || e);
if (statusEl) { statusEl.style.display = 'block'; statusEl.textContent = 'BOOT ERROR: ' + window.__genBootError; }
throw e; // 重抛 → 'unhandledrejection' 被假绿守卫逮住
});
} catch (e) {
window.__genBooted = false;
window.__genBootError = String((e && e.message) || e);
if (statusEl) statusEl.textContent = 'BOOT ERROR: ' + window.__genBootError;
throw e;
}
})();
</script>
</body>
</html>