5路并行侦察(读代码非读规格,PLANNED vs ACTUAL 以代码为准)实证:每个灰度闭环必需项 done/absorbed-by-arc 且有真机证据(A6 6/6 `3e5cab4` / P2真机6门 `5d3f7a8` / 3b-B井字棋入feed `238ec2d` / B1主链9001-9002);剩余全是 audit-debt+gold-plating, 无一在完成线(日历闸门)关键路径。 3处 spec↔代码漂移(有意改判非bug,已回填澄清): - Phase B: packageUrl外链 → engineBundle内嵌(absorbed,契约一致无split-brain) - Phase C: 1.x srcdoc→URL退役被P2 O2(b)supersede(moot,单宿主GamePlayer.vue无双轨) - Phase A: random/time/input改判插件自管(透传破粒子确定性/污染帧钟,血统债) 落档(纯文档additive/低风险): - 母spec 9处banner回填(Phase C supersede / Phase B engineBundle / Phase A drifts / 门3·门5·门12 / §12 immutable裁决) - 新收口报告 docs/agent-specs/2026-06-15-T1b-β收口报告.md(wave-close七步) - 总账(§5 backlog+推迟清单+§6执行记录row+表头日期2026-06-15) - 作战清单(§0+T1b-β item标done)+ .agent(TODO→收口block+推迟清单) - schema immutable孤儿字段标future(消无孤儿设计红线 AGENTS §7) 推迟清单(gold-plating+audit-debt)入backlog,创始人可点名某项转required。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
111 lines
7.5 KiB
JSON
111 lines
7.5 KiB
JSON
{
|
||
"$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" }
|
||
}
|
||
}
|
||
}
|
||
}
|