{ "$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 可选。【2026-06-15 T1b-β 收口裁决】当前 P2 走 DB-manifest engineBundle 内嵌路、packageUrl 外链未启用→后端 manifest 端点(AppRuntimeController)未设 Cache-Control、本字段零消费=**有意 future 占位(非孤儿,标记以合规 AGENTS §7 无孤儿设计)**;接 OSS/CDN 独立 bundle URL 后再由端点实现强缓存头并点亮本字段,additive 保留不删(删后切 OSS 需重加、破契约稳定性)。", "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" } } } } }