games-development-ai/contracts/game-package.schema.json
zizi 5d3f7a87f0 feat(runner-v2): P2 通用宿主泛化落地——引擎游戏真渲入 feed 真玩(mini-desktop 真机门验)
P2 = 把 P1 装载契约从「装载王蓝莓一款」泛化为「装载任意 GamePackage」,经发布主链入 feed、
真人浏览器真玩。4 决策落实(O2(b)纳入 Phase C / DB-manifest 内嵌 / 灌库桩 / __GameBundle)。

三轨实现
- 后端:GamePackage schema 加 engineBundle additive 可选字段;buildGamePackage 加 engineBundle put
  (P3 生成路用,P2 恒 null→put 跳过→字节零变,单测 packageBytesReproducible 证);灌库桩
  p2_seed_engine_bundle.mjs + 四态脚手架 p2_scaffold_4state.sql(W-CLEAN 后重建已发布游戏)
- 运行时:P1 bootRef 泛化为 bootGameHost(opts)(引擎骨架照搬+参数化工厂来源/插件/视口),
  bootRef 退化薄包装;固化 build:ref-bundle 产 dist/ref-bundle.iife.js(--global-name=__GameBundle)
- studio:inject.ts 引擎包分支(pkg.engineBundle? → 内联 script 暴露 window.__GameBundle →
  bootGameHost 挂引擎真渲;否则旧 startRuntime 路保兼容);掏空壳改引擎分支(Phase C);CSP 不放外域

对抗代码复审逮 2 mustFix(主 agent 亲核亲修 + 6c6g 复验)
- 灌库桩读错产物(ref-bundle.js harness vs .iife.js)→ mini-desktop 灌库返工死循环
- 引擎分支漏发 game_start → 会话/play_count 静默吞、门②检不出 → 补发(DB session 行实证已修复)
+2 shouldFix(兜底可观测信号 / 灌库 SQL @pj 防撞 max_allowed_packet)
+ 真机门逮 2 环境缺陷已修(seed charset=utf8mb4 防双编码断 checksum 链 / 四态脚手架补 W-CLEAN 空库)

mini-desktop 真机门 6 门(逐门实数,主 agent 肉眼复核证据)
①build:ref-bundle 265374B/__GameBundle 真入包 ②Java 编译过+字节复现单测 ③studio staging 重建消 mock
④灌库 status=1∧checksum 64hex∧engineBundle 键齐∧manifest sha256 一致 ⑤真人 feed 点卡→引擎真渲
暖阳小卖部(warm=1246073px)非「重构中」+game_loaded+game_start+防 demo 三锚+console 零错+DB session 行
⑥回滚:无 engineBundle→demo 壳/错误态,向后兼容未破。证据 game-studio/evidence/p2-feed/

诚实 gap:game_end(到结算)未在自动化窗口内达成=ref gameover 需分钟级真玩+srcdoc 坐标盲点的取证局限,
非引擎/渲染能力缺陷(机制已通,留人工真玩到打烊补全)。受控面 6 项+game-host.d.ts 零改。

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

111 lines
7.1 KiB
JSON
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.

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://wanxiang.ai/contracts/game-package.schema.json",
"title": "GamePackage",
"description": "绘境AI 游戏包契约(契约 #4,owner=WS3+WS2)。生成链路(aigc/studio)的产出物,runtime 编译/预览/发布的输入物。贯穿 生成→编译→预览→发布→游戏流→试玩 全链路,是平台最核心的数据契约。",
"type": "object",
"required": ["schemaVersion", "gameId", "versionId", "templateId", "gameConfig", "assets", "manifest", "meta"],
"additionalProperties": false,
"properties": {
"schemaVersion": {
"description": "本契约版本。新增字段不升版本;删除/重命名字段升版本。",
"type": "string",
"const": "1.0"
},
"gameId": {
"description": "游戏全局唯一 ID(project.game_project.id)",
"type": "string",
"minLength": 1
},
"versionId": {
"description": "游戏版本 ID(project.game_version.id)。资源 OSS 路径按 /games/{gameId}/versions/{versionId}/ 版本化。",
"type": "string",
"minLength": 1
},
"templateId": {
"description": "玩法模板 ID(aigc 模板注册表)。MVP 取值范围 = 3-5 个 P0 模板,如 dodge/runner/clicker/puzzle/shooter(最终由产品拍板)。",
"type": "string",
"minLength": 1
},
"gameConfig": {
"description": "可玩游戏配置(模板相关的玩法参数)。结构由各模板的 GameConfig JSON Schema 约束(contracts 后续批 templates/*.schema.json);此处仅约定为对象并要求 templateId 自洽。runtime 编译前做静态 Schema 校验(门禁④)。",
"type": "object"
},
"assets": {
"description": "资源清单。每项资源 hash 命名长期缓存;编译期校验总大小(≤10MB)、首屏(≤2MB)。",
"type": "array",
"items": {
"type": "object",
"required": ["id", "type", "url", "hash", "bytes", "mime"],
"additionalProperties": false,
"properties": {
"id": { "description": "资源在包内的逻辑 ID", "type": "string" },
"type": { "description": "资源类型", "type": "string", "enum": ["image", "audio", "spine", "json", "font", "atlas"] },
"url": { "description": "资源可访问 URL(MVP 本地 MinIO / 生产 OSS+CDN)", "type": "string", "format": "uri" },
"hash": { "description": "资源内容 sha256(hex),用于完整性校验与 CDN 永久缓存命名", "type": "string", "pattern": "^[a-f0-9]{64}$" },
"bytes": { "description": "资源字节大小", "type": "integer", "minimum": 0 },
"mime": { "description": "资源 MIME 类型", "type": "string" }
}
}
},
"manifest": {
"description": "运行清单。runtime 据此加载与做完整性校验。",
"type": "object",
"required": ["runtimeVersion", "entry", "preloadPolicy", "bundleSize", "checksum"],
"additionalProperties": false,
"properties": {
"runtimeVersion": { "description": "目标 WanxiangGameSDK / Canvas Runtime 版本(semver)", "type": "string" },
"entry": { "description": "入口文件相对路径", "type": "string" },
"preloadPolicy": {
"description": "三容器预加载策略:eager=进容器即加载 / lazy=可见时加载",
"type": "string",
"enum": ["eager", "lazy"]
},
"bundleSize": { "description": "包总字节(编译期门禁校验上限)", "type": "integer", "minimum": 0 },
"checksum": { "description": "整包 sha256(hex),Manifest 完整性校验。T1b-β 门4 防 demo 兜底假阳性=Network 捕获本 checksum 比对发布版本", "type": "string", "pattern": "^[a-f0-9]{64}$" },
"packageUrl": {
"description": "运行包可访问 URL(T1b-β Runner v2 交付锚;additive 可选,存量消费者无此字段时回退后端 resolveManifestUrl 原链路)。MVP 默认降级=复用后端 game_version.package_url 走 DB-manifest 端点 /app-api/runtime/package/{versionId}/manifest(天然含 versionId 版本化,不接 OSS、不改写链);切 OSS 后=OSS 版本化路径。= 后端 RuntimePackageDO.packageUrl 的 GamePackage 契约镜像(同源同物,后端写权)。",
"type": "string",
"format": "uri"
},
"immutable": {
"description": "本 URL 是否携带 immutable 强缓存语义(Cache-Control: public,max-age=31536000,immutable)。true=URL 版本化+内容寻址、命中即永久缓存(编译缓存靠 versionId 兜,门4 用 CDP Network timing 验缓存命中 fromCache/304);false/缺省=普通缓存。additive 可选。",
"type": "boolean"
}
}
},
"meta": {
"description": "展示与合规元信息(发布前检查清单门禁⑦校验)。",
"type": "object",
"required": ["title", "summary", "cover", "ageRating"],
"additionalProperties": false,
"properties": {
"title": { "description": "标题", "type": "string", "minLength": 1, "maxLength": 60 },
"summary": { "description": "简介", "type": "string", "maxLength": 500 },
"cover": { "description": "封面图 URL(首屏卡片展示)", "type": "string", "format": "uri" },
"tags": { "description": "标签", "type": "array", "items": { "type": "string" }, "maxItems": 10 },
"ageRating": {
"description": "适龄提示(发布前必填,门禁⑦)。all=全年龄 / 8+ / 12+ / 16+",
"type": "string",
"enum": ["all", "8+", "12+", "16+"]
}
}
},
"engineBundle": {
"description": "引擎+包装层+游戏代码的可执行 iife bundle 文本(T1b-β P2 通用宿主载体;additive 可选,存量消费者无此字段时走 startRuntime 旧路/demo 兜底)。MVP 默认=随 manifest 内嵌经 DB-manifest 端点 /app-api/runtime/package/{versionId}/manifest 下发(落 game_runtime_package.package_json LONGTEXT,sha256 整包 checksum 覆盖其完整性,不接 OSS、不增第二校验面);切 OSS 后改为 packageUrl 外链。iife 顶层全局名固定为 __GameBundle(宿主据此从 window.__GameBundle 取 GameHostFactory,见 game-runtime/src/core/game-host.d.ts)。后端写权=DifyCallbackTxService.buildGamePackage put(P2 阶段 ref 一款经 O-P2-1 灌库桩注入,真产线 P3 接生成主线)。",
"type": "string"
},
"provenance": {
"description": "可追溯来源(质量门禁与缓存命中用)。相同 promptHash 命中缓存可跳过 LLM 生成。",
"type": "object",
"additionalProperties": false,
"properties": {
"promptHash": { "description": "生成所用 Prompt 的 hash(产物缓存键)", "type": "string" },
"model": { "description": "生成所用 LLM 标识(如 deepseek-chat / qwen-max)", "type": "string" },
"traceId": { "description": "贯穿 生成→编译→加载→运行 的 trace_id", "type": "string" },
"generatedAt": { "description": "生成时间(ISO 8601)", "type": "string", "format": "date-time" }
}
}
}
}