zizi e591e9b705 feat(t1b-beta): A1-A4 引擎能力接线落地——受控面工厂/粒子/音频/手感经 getEngine 薄包装(easing 改判)
承 A0 引擎掌帧地基,按创始人「引擎↔插件边界模型」(引擎有→薄包装·引擎无→自研补层·
同一职不留两条并行路)接线 A1-A4。host.js 注入真 engineFactory,getEngine() 在 host-dev 真活。

A1 受控面+引擎工厂地基+easing 门面:
- host.js makeEngineCaps 一处构造 EngineCapabilities{particles,audio.synth,math};
- 新 host-dev/engine-math.js 包装引擎 lerp/smoothStep + Ease 曲线(11 条等价曲线门面);
- api.d.ts additive 扩 EngineEasing + EngineMath.easing?(不破已冻 lerp/smoothStep)+ 块级降级措辞校准为 null no-op;
- 受控面 random/time 保确定性(引擎粒子用全局 rand 不可种子对齐→random 留插件自管,真缺件)。

A2 particles 薄包装+删 sim:
- EngineEmitterSpec additive 扩 10 可选字段(count/coneAngle/speed/gravityScale/sizeStart-End/colorStart-End/additive);
- spawnEmitter 改走 getEngine().particles 映射引擎 ParticleEmitter,删自研逐粒子积分 sim;null-engine→no-op 句柄;
- juice 全段(hitStop/屏震/闪白)补层保留;测试转向映射纯单测+真渲出现(逐像素确定性随 sim 退役,§1.4 记账)。

A3 audio 包装+删 vendored+补 ×0.3:
- 删 vendor/zzfx.js+zzfxm.js;audio.synth 包装引擎 zzfxG/zzfxM;
- 播放层补 ×0.3 主音量(引擎样本不烤 0.3,gain 层施)+ SAMPLE_RATE=44100 本地常量;
- impl.js 走 getEngine().audio.synth,null-engine→合成 no-op(不回退 vendored)。

A4 gamefeel easing 改判=门面包装(对抗门源码证伪纠偏):
- easing 改走 getEngine().math.easing 门面(quadIn→Ease.POWER(2) 等),内置降名 builtinEasing 作 null-engine fallback(纯数学族特例);
- backInOut/elasticInOut 引擎 IN_OUT 拼接差 6.6%/17%(另一条曲线)→门面刻意不暴,这二者恒走内置=真缺件补层;
- collision/physics-lite/palette-post 加边界裁定注释(真缺件补层,源码精校:引擎仅 isOverlapping/isIntersecting 返 boolean,无 Manifold/任意几何/RayHit)。

对抗门两逮(均前置于实现·零返工):
- A4 easing 误判 fatal:前轮按小写 quadIn grep 假阴性误判「引擎无 easing」;引擎实有 Ease(esm.js:15118)→创始人拍本波包装;
- collision 注释 under-claim:已精校为源码准措辞。新红线 §1.5:引擎能力普查禁按预期名 grep,须读 export 块/.d.ts。

本机门全绿(亲验):
- node --test 168/168 绿;all-plugins+host-bundle 双 esbuild rc=0(35594B/209516B);
- 真接线门①引擎真入产物 littlejsengine 163641B;门③负扫=0 插件直 import+vendor 已删+0 自研 sim+0 假注释;Q4 引擎 import 仅 entry.js+host.js。

A6(mini-desktop real 像素门 + 真接线门② runtime probe call-ID)待主会话驱动。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 11:48:28 +00:00
..

game-runtime —— LittleJS 增强发行版(插件协议地基)

协议版本:core-protocol-v0(见 src/core/plugin.js 导出的 CORE_PROTOCOL_VERSION)。 owner:T1b-α lane-core(Gate0 奠基)。配对 spec:docs/agent-specs/2026-06-12-T1b-α插件库与参考件-execution.md(v1.1)/ …W-T1b-Runner与双层模板-review.md(v2.1)。

平台维护一套「LittleJS 增强发行版」:每个插件 = 一项引擎能力(碰撞/粒子/物理/手感/调色/音频…),即插即用、可组合、版本化。 插件不含玩法、不含美术成品、不含关卡、不含 UI —— 这四者是 agent 造游戏时的生成域。 本仓只提供「能力编排 + 受控引擎句柄」,绝不内置任何玩法假设。


协议版本声明

项 值
当前协议版本 v0(2026-06-12 冻结,含 Gate0.1 受控面补丁)
标识来源 src/core/plugin.js → export const CORE_PROTOCOL_VERSION = 'core-protocol-v0';schema/plugin-manifest.schema.json → $id .../v0
冻结状态 Gate0 评审通过即冻结。Gate0.1 补丁(受控面由 4 扩 6:+getInput/+getAudioContext;random 改 per-plugin 派生流;useContext 守卫)为向后兼容增量,随 v0 一并冻结,不 bump 版本号
升级规则 受控面只增不破坏既有 API;破坏性变更须 bump 版本(v0→v1)并在本表登记

扩展受控面 / 改 manifest 字段 = 改协议,必须走 Gate0 后的扩展申请,不得 lane 私自加。 受控面 v0 最终成员(冻结口径,6 项):getContext2d / onFrame / getInput / getAudioContext / time / random。


目录结构

game-runtime/
├── README.md                      # 本文件:目录 + 证据约定 + 协议版本声明位
├── src/
│   ├── core/                      # 协议核心(core-protocol-v0,已冻结对象)
│   │   ├── plugin.js              #   Plugin 接口 / PluginRegistry 生命周期 / PluginContext 受控面(6 项) + host-dev 桩(含输入桥)
│   │   ├── api.d.ts               #   手写类型门面(lane 读契约的一等入口,与 plugin.js JSDoc 同步)
│   │   └── plugin.test.mjs        #   核心零依赖单测(31 测,node --test)
│   └── plugins/
│       └── _example/              # 空插件样例(五件全,可直接克隆为新插件)
│           ├── impl.js            #   ESM 实现(演示受控面用法,无玩法语义)
│           ├── api.d.ts           #   该插件类型门面
│           ├── manifest.json      #   插件机器契约(过 schema 校验)
│           ├── PLUGIN.md          #   给 agent 读的能力文档(PLUGIN-TEMPLATE 活样板)
│           └── test/example.test.mjs  # 该插件零依赖单测(7 测)
├── schema/
│   └── plugin-manifest.schema.json  # manifest.json 契约(additionalProperties:false)
├── docs/
│   └── PLUGIN-TEMPLATE.md          # PLUGIN.md 规格模板(六节固定骨架)
├── scripts/
│   ├── build.mjs                  # esbuild 锁参打包(bundle+min+iife+es2019)——⚠️ 仅集成段跑
│   ├── size.mjs                   # 增量法字节测量(zlib gz level9)→ SIZES.md ——⚠️ 打包部分仅集成段
│   ├── validate-manifest.mjs      # 零依赖 manifest schema 校验(本机可跑)
│   └── test.sh                    # 遍历 core+全插件 node --test(本机可跑)
└── test/
    └── harness/
        └── browser-evidence.cjs   # 浏览器视觉证据 harness(纯计算口径已实现 + CDP 占位,⚠️ 真跑仅集成段)

下列目录在对应阶段产生,本阶段尚未创建:src/plugins/<P1..P10>/(各 lane 插件)、games/(参考件)、host-dev/(本地挂载页)、dist/(集成段构建产物)、evidence/(集成段/参考件证据)、SIZES.md(集成段 size.mjs 产出)。


源码形态与运行纪律

  • 源码形态:发行版 = ESM JS + JSDoc 类型注释,公开能力面 = 手写 api.d.ts。零工具链——lane 阶段 node --test 本地直跑,本机零 npm 依赖、不跑 git。
  • 本机可跑(lane 阶段):
    • bash scripts/test.sh —— 跑 core + 全插件单测;
    • node scripts/validate-manifest.mjs —— 校验全部 manifest.json 合 schema;
    • node scripts/size.mjs --selftest —— gz 量算口径自检。
  • 仅集成段(mini-desktop)跑(需 esbuild / 真 Chrome):
    • node scripts/build.mjs <in> <out> —— 锁参打包;
    • node scripts/size.mjs —— 增量法实测 → SIZES.md;
    • test/harness/browser-evidence.cjs 的 CDP 真跑(连 Chrome 抓 ImageData/截图)。本机(6c6g)禁启 headless Chrome(OOM 红线)。

证据与目录约定(沿 T1 结构)

阶段 证据落点 内容
每 lane <lane>/REPORT.md 实现说明 + 边界 + 红线声明
每 lane <lane>/test/RESULT.txt node --test 原始输出
每插件 <plugin>/PLUGIN.md 给 agent 读的能力文档(六节,见 docs/PLUGIN-TEMPLATE.md)
集成段 SIZES.md + evidence/integration/ 构建日志 / 浏览器证据哈希 + 截图
参考件 evidence/round-N/ + LOOP-LOG.md + sha256-manifest.txt 四件套(输入轨迹/截图+canvas 哈希/probe JSONL/checklist)+ serve 日志
  • 截图路径约定:evidence/<bucket>/<name>.png(集成段 bucket=integration,参考件 bucket=round-N),由 browser-evidence.cjs 的 screenshotPath() 统一给出。
  • 哈希族:全发行版证据用 FNV-1a 32-bit(ImageData 哈希与 P10 RuntimeProbe 哈希链同口径)。
  • 字节预算:每插件 manifest.json 声 gzBudgetBytes,集成段 size.mjs 增量法实测对照;单件超配额→评审,合计>60K→创始人放行(执行版 §5)。

给 lane 开工者的最短路径

  1. 读 src/core/api.d.ts(协议类型契约,一等入口)+ src/core/plugin.js(实现与受控面注释)。
  2. 复制 src/plugins/_example/ 整目录 → 改名为你的插件 → 按 docs/PLUGIN-TEMPLATE.md 六节改写 PLUGIN.md → 改 manifest.json(node scripts/validate-manifest.mjs 必须过)。
  3. 实现 impl.js:只经 PluginContext 4 项受控面拿引擎能力,绝不直透 littlejsengine 裸对象。
  4. 写 test/*.test.mjs:零依赖 node:test,经 createHostDevContext 拿受控面 + tick 驱动帧(vfx/audio 的渲染/发声证据留集成段 harness)。
  5. bash scripts/test.sh 全绿后,产 REPORT.md + test/RESULT.txt。