{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://wanxiang.ai/contracts/agent-loop/tier2-source-project.schema.json", "title": "Tier2SourceProject", "description": "tier2 富游戏自治生成线的源项目契约(A3 / F1):认一个『真 Phaser 引擎工程』是什么、怎么构建出来、怎么存回来的稳定形状。【红线】绝不复用 contracts/agent-loop/source-project.schema.json——那份是 Tier0/1 廉价线的 ECS-lite 数据壳(schemaVersion 1.0,profile+gameDefinition,即取即跑无构建);本份是契约组新一类(additive),独立 schema,两条装载路解耦并存。【七要素四组】身份(① projectType 类型标记)/ 工程骨架(② fileTree 文件树 manifest、③ entry 入口文件)/ 构建可复现(④ buildProfile esbuild 配置、⑤ depLock 依赖锁)/ 落库取回(⑥ contentHash 内容哈希、⑦ addressing 落库寻址)。【finish 共用 schema】tier2 单写 agent 的 finish 工具(A7)其参数 schema 与本份共用同一份定义(F3:从源头杜绝交付↔落库漂移),agent ReAct 收敛 → finish 交付的形状 = 落库取回时认的形状。【最小 keystone 先行】对抗评审务实修正(design §A3):tier2 整轨待 0号 spike,Phaser 一行未落,此刻把七要素全冻死有 spike 后要素错配风险。故 required 只焊装载/落库三方立刻要认的最小 keystone(projectType / fileTree / entry / contentHash / addressing);buildProfile / depLock / fileTree.role 枚举等随 spike 实证再收窄(现为 directional,见各字段 description)。状态=建(待 0号 spike;plan003 U9)。详见 docs/architecture/架构/生成引擎/tier2细节图说-F-源项目契约与装载.md。", "type": "object", "required": ["projectType", "fileTree", "entry", "contentHash", "addressing"], "additionalProperties": false, "properties": { "schemaVersion": { "description": "本契约版本(独立于 source-project.schema.json 的 1.0 与 GamePackage 版本)。directional v1;Phaser spike 落地后随第二实现冻结。", "const": "tier2-1.0" }, "projectType": { "description": "要素①身份:源项目类型标记。装载侧(A4 第二装载分支)靠它一眼分清这是 ECS-lite 数据壳还是 tier2 引擎工程、走对应装载分支——两条装载路分流的第一道闸(F2)。tier2 真引擎工程恒为 'tier2-phaser'。注:design §A4 指出现状装载分流事实载体是 engineBundle 存在性,projectType 分流是 tier2 待建语义,本字段即承载该待建语义。", "const": "tier2-phaser" }, "fileTree": { "description": "要素②工程骨架:文件树 manifest,记下工程有哪些源文件、各自什么角色。装载与寻址都按它走;esbuild 多文件构建的输入清单。多文件 src/ 真工程(非单 bundle 文本),允许 import(Phaser / scene 间 import),无单 export default 工厂——与 Tier0/1 validate 规则完全反转(design §C4 net-new 重写)。", "type": "array", "minItems": 1, "items": { "type": "object", "required": ["path", "role"], "additionalProperties": false, "properties": { "path": { "description": "工程内相对路径(POSIX 正斜杠,相对 src 工程根,如 'src/main.js'、'src/scenes/PlayScene.js')。不得含 '..' 或绝对路径(落库取回时按它寻址,越界=安全风险)。", "type": "string", "minLength": 1, "pattern": "^(?!.*\\.\\.)[A-Za-z0-9._/-]+$" }, "role": { "description": "文件角色(directional v1·开放枚举):entry=构建入口 / scene=Phaser 场景 / system=逻辑系统(经营品类的合成/资源/订单等纯逻辑状态机) / ui=界面层 / asset-manifest=资产清单 / config=平衡参数表 / lib=工具库 / other=其余。真实 role 枚举(尤其 Phaser scene 树语义)待 0号 spike 见到真实例再收窄;故此处不锁 enum、留 string + 建议值。", "type": "string", "minLength": 1 } } } }, "entry": { "description": "要素③入口文件:build 从哪个文件起手,整条构建链的源头锚点。必须命中 fileTree 中某个 path(消费方校验:entry ∈ fileTree[].path)。Phaser 工程入口约定 = 'src/main.js'(esbuild 入口),非 Tier0/1 的单 export default 工厂。", "type": "string", "minLength": 1 }, "buildProfile": { "description": "要素④构建可复现:固定这一款用什么 esbuild 配置打包,把构建步骤随款冻结不漂(服务『游戏=长生命周期项目』,两年前的工程今天还得原样构建)。directional v1:字段形状待 spike 跑通真实 esbuild 配置后收窄。非 keystone(spike 前可缺),但 decision=可发布前消费方应要求齐备。", "type": "object", "additionalProperties": true, "properties": { "bundler": { "description": "打包器(tier2 现锁 esbuild;留字段以备 future 换 vite/rollup)。", "type": "string", "default": "esbuild" }, "format": { "description": "产物模块格式。Phaser 多文件工程经 esbuild 打成 iife 可玩 bundle(对照 Tier0/1 单包 iife --global-name=__GameBundle;tier2 入口=main.js)。", "type": "string", "enum": ["iife", "esm", "cjs"], "default": "iife" }, "globalName": { "description": "iife 全局挂载名(A4 装载分流要用,中性符号,默认沿用现行宿主约定 __GameBundle 以复用 boot 探针;tier2 第二装载分支落地后可改协议规定的中性名)。", "type": "string" }, "minify": { "description": "是否压缩。", "type": "boolean", "default": true }, "target": { "description": "构建目标(如 es2020;影响兼容性,随款冻结)。", "type": "string" }, "esbuildOptions": { "description": "其余 esbuild 透传选项(directional·待 spike 实证补全字段)。", "type": "object", "additionalProperties": true } } }, "depLock": { "description": "要素⑤依赖锁:钉死引擎与插件版本,免上游一升级历史游戏就构建不出来(长生命周期项目兑现点)。必含 phaser 版本。directional v1:锁形态(精确版本 vs 锁文件指纹)待 spike 定;非 keystone(spike 前可缺)。", "type": "object", "additionalProperties": true, "required": ["phaser"], "properties": { "phaser": { "description": "Phaser 引擎版本(精确版本号,如 '3.80.1';tier2 首批引擎,随款冻结)。", "type": "string", "minLength": 1 }, "plugins": { "description": "插件/依赖名→精确版本映射(其余依赖锁)。", "type": "object", "additionalProperties": { "type": "string" } }, "lockfileHash": { "description": "锁文件(package-lock.json/pnpm-lock.yaml)规范化后 sha256,做依赖完整性校验(可选,directional)。", "type": "string", "pattern": "^[a-f0-9]{64}$" } } }, "contentHash": { "description": "要素⑥落库取回:整个工程算一个指纹(sha256(fileTree 各文件内容规范化拼接)),既做缓存命中(同指纹直接跳过重建)又做完整性校验。沿用现行 GamePackage 那套 sha256 落库取回数据范式。幂等/可寻址键。", "type": "string", "pattern": "^[a-f0-9]{64}$" }, "buildInputHash": { "description": "确定性构建缓存命中键 = sha256(contentHash + buildProfile 规范化)。口径对齐 Tier0/1 source-project.schema.json 第 12 行 buildInputHash(同语义:同源同构建配置直接命中缓存,跳过 esbuild)。可选(buildProfile 齐备时由消费方计算填入)。", "type": "string", "pattern": "^[a-f0-9]{64}$" }, "addressing": { "description": "要素⑦落库寻址 API:工程怎么存进 MySQL+对象存储(OSS)、怎么按 id 取回来重建。沿用现行 GamePackage 落库取回数据范式(故带『数据』徽标,不另起炉灶)。store=落库后端约定;fetchById=取回签名约定(directional·文字约定,真实 service 签名见 A3.5 版本寻址协议)。", "type": "object", "additionalProperties": false, "required": ["store"], "properties": { "store": { "description": "落库后端约定(directional):'mysql+oss'=manifest 落 MySQL、源文件落对象存储。", "type": "string", "default": "mysql+oss" }, "fetchById": { "description": "取回寻址键约定(directional):按 contentHash(或 A3.5 的 sourceHash/versionId)取回源工程重建。值=寻址键名,真实取回 service 签名留 A3.5『源项目版本寻址协议』定义。", "type": "string", "default": "contentHash" }, "sourceUrl": { "description": "源工程归档地址(OSS 只读镜像,可选;同 GamePackage.packageUrl 范式)。", "type": "string", "format": "uri" } } } } }