diff --git a/docs/architecture/架构/生成引擎/agentic运行时架构图说.md b/docs/architecture/架构/生成引擎/agentic运行时架构图说.md index 7f0b8401..9488492e 100644 --- a/docs/architecture/架构/生成引擎/agentic运行时架构图说.md +++ b/docs/architecture/架构/生成引擎/agentic运行时架构图说.md @@ -189,7 +189,7 @@ B 类对接上面某几条 A 协议,换引擎 / 换框架 / 换渠道时被换 ## 五、运行时八面(facet) -> 八个 facet 是 §四 两实例的逐面放大,把两条线在每一面的设计讲到可照着实现的颗粒度。tier2 富游戏线的内容偏多——**它的核心已落、0 号 spike 已 accept**(各面"现/建"按 2026-06-24 `tier2/HANDOFF.md` 真相标注:多数已落,留后的是 n≥30 统计跑、阶段 1 Agent Team、控制面/管理面);廉价线在每一面以现行已落的对照锚出现。各面引用的 svg 大图在 `assets/`。 +> 八个 facet 是 §四 两实例的逐面放大,把两条线在每一面的设计讲到可照着实现的颗粒度。tier2 富游戏线的内容偏多——**它的核心已落、0 号 spike 已 accept**(各面"现/建"按 2026-06-24 `tier2/HANDOFF.md` 真相标注:多数已落,留后的是 n≥30 统计跑、阶段 1 Agent Team、控制面/管理面);廉价线在每一面以现行已落的对照锚出现。各面引用的 svg 大图在 `assets/`——**这些图是 0 号 spike 前视角(虚线、以及图内"整图状态 = 建·待 spike"小标都是当时的待建标记),现状真相以各面散文的"现/建"为准,不以图的虚线为准**(svg 重绘待 mini-desktop 出图管线)。 ### 5.1 运行时形态 diff --git a/docs/plans/2026-06-23-接口协议层与可插拔模块-design.md b/docs/plans/2026-06-23-接口协议层与可插拔模块-design.md index 1d6a09f4..e13967d7 100644 --- a/docs/plans/2026-06-23-接口协议层与可插拔模块-design.md +++ b/docs/plans/2026-06-23-接口协议层与可插拔模块-design.md @@ -1,483 +1,15 @@ --- -date: 2026-06-23 -topic: 接口协议层与可插拔模块(生成引擎的固定契约 vs 可换实现) -status: opus 终审通过(无 P0 · 2026-06-23)· 作设计基线合入 dev/2.0.0 · §7 14 项开放问题待创始人定 -mapping: - - doc: docs/architecture/架构/生成引擎/agentic集成架构.md - hash: 1b3e375a - - doc: docs/architecture/架构/生成引擎/tier2实现详设.md - hash: d5efe45f - - doc: docs/architecture/架构/生成引擎/SAA编排.md - hash: 1b3e375a - - doc: docs/architecture/架构/生成引擎/自治富游戏引擎.md - hash: 4858e6cf - - doc: docs/architecture/架构/生成引擎/tier2细节图说-D-三层校验与九门.md - hash: 32adda95 - - doc: docs/architecture/架构/生成引擎/tier2细节图说-F-源项目契约与装载.md - hash: cc71dbba - - doc: docs/plans/2026-06-22-003-feat-tier2-富游戏自治生成线-plan.md - hash: ccb00bb9 - - doc: contracts/agent-loop/verdict.schema.json - hash: 208a36ee - - doc: contracts/agent-loop/source-project.schema.json - hash: 5cadf504 - - doc: contracts/game-package.schema.json - hash: c2cb4d75 - - doc: game-cloud/.../service/executor/GenerationDispatcher.java - hash: 314b421a +status: 已退役(2026-06-25 并入 SoT①) +canonical: false +date: 2026-06-25 --- -# 接口协议层与可插拔模块 +# (已退役)接口协议层与可插拔模块(adapter:A1–A13 固定协议 + B 类可插拔模块) -## 0 这份要解决什么 +本 adapter 设计已并入生成运行时架构单一事实源 [`agentic运行时架构图说.md`](../architecture/架构/生成引擎/agentic运行时架构图说.md): -绘境AI 的游戏生成正在从一条线长成两条:一条是已经在生产里跑的廉价线,便宜模型经 new-api 网关由 SAA(Spring AI Alibaba)裸图编排,产物落在 LittleJS 上,过九门兜底;另一条是 tier2 的富游戏线,一个自治的 ReAct agent(用 AgentScope 这套 Python 框架)去造廉价线做不出的多系统富游戏,产物是真 Phaser 源工程。两条线还会继续分叉——引擎可能从 LittleJS 换到 Phaser、Pixi、乃至 Cocos,编排框架可能从 SAA 换到 AgentScope。 +- **A1–A13 固定接口协议 + B 类可插拔模块** → 该 SoT 的 **§三 adapter 协议层**(经 §6.8 双评审对标修正:多数自研协议对到 A2A / MCP / OTel / SKILL.md 标准,自研收到 checkpoint/续跑 + 验收门两块护城河)。 +- **§7 的 14 项开放问题** → 该 SoT 的 **§二补(§6.8 双评审修正)** 与配套执行 plan `docs/plans/2026-06-22-003-feat-tier2-富游戏自治生成线-plan.md` 附段的 build-vs-buy 待决。 +- **划线五原则 / 机制实证 / 现状耦合接缝** → 该 SoT §三 §3.1–§3.3。 -如果每换一次引擎或框架就要改一遍业务侧调用、改一遍验收门、改一遍落库,那这套东西就废了。所以要先把一条线划清楚:哪些是**系统内固定的接口协议**,任何人换引擎换框架都不许动;哪些是**可插拔的实现模块**,换引擎换框架就是换它们。换引擎 = 接一个新适配器,而不是动契约。这就是这份草案要确立的事。 - -划线的依据来自三处已落地的判断。SAA 编排文档的"不变量五点"里,有一条明确写着"框架可换、契约不变";agentic 集成架构文档把引擎定性成"能力包,不是底座";自治富游戏引擎文档立下铁律——"出题的和被考的绝不能是同一只模型"。这三句话分别管住了三件事:接缝在哪、引擎是什么、验收门归谁判。下面把它们展开成一份可对接的协议清单。 - -这份清单里,真正已经在生产里跑过、被代码兑现的固定协议只有少数几条(装载契约、验收门的判定纪律、廉价线的探针),其余多数是 tier2 待 0 号 spike 验证、尚未落代码的设计意图。哪条是"现"、哪条是"建"、哪条是"待定",每条都如实标注。 - -第二轮往外推一层审了平台面(送审/审核、资产、玩法模板、试玩、通用检查、配置)后,这句话要补一个角度:平台面与生成执行段不同,廉价线在生产里已经把送审/审核(合规 Gate + project 审核状态机)、产物体积门、资产骨架、玩法模板(编译期常量)大多兑现了真实现,问题不在"没造出来",而在它们都硬编码在单条线、单条 publish 链路上、从没抽成两条线加各渠道共用的固定接缝;唯一彻底空白的是配置注册表(代码侧零落地、四类各自为政)。所以平台面的"建"多数指"已有实现待抽成协议",而非"零代码"——这与生成执行段 tier2 的"零代码待 spike"是两种不同的"建",下文逐条区分。 - -## 1 那条划线原则 - -划线靠五条规则,逐条讲清。 - -**契约固定、实现可插拔。** 固定的是"形状"——业务侧与生成执行后端之间认的那个接口签名、那份状态 schema、那份 verdict schema。可插拔的是"形状背后由谁去满足它"——SAA 实现一遍任务协议,AgentScope 再实现一遍;LittleJS 实现一套探针,Phaser 再实现一套。判断一样东西该不该固定,问一句:换框架/换引擎时它变不变?若不变(业务侧调用、状态口径、判定纪律),它进 A 类固定协议;若变(某引擎怎么读帧、某框架怎么存状态),它进 B 类可插拔模块。 - -**契约不做成 skill。** AgentScope 的 skill 本质是"喂给 agent 的指令 + 资源包",自身不执行代码(机制实证见 §4)。把契约写成 skill,等于把硬约束降格成 agent 可读可不读的提示,这正是项目治理条款 10 反复警告的塌陷模式——"规则不编译成机器门 = 等于没有"。所以固定协议必须落在机器可校验的载体上:JSON Schema、`.d.ts` 接口、Java interface、纯代码的 judge 判定。skill 只承载"怎么用某个引擎写游戏"这类 playbook 知识,不承载"完成与否谁说了算"这类纪律。 - -**门探针劈两半。** 验收门这件事必须拆成两层:"门要从引擎读哪几样"(canvas 选择器、帧计数源、boot 就绪信号、输入注入、可观测 state)是引擎无关的抽象,该固定;"怎么从某个具体引擎把这几样读出来"是 per-engine 的实现,该可插拔。判 pass/fail 的逻辑永远待在固定层、由纯代码产出,探针只负责"读"和"驱动",绝不负责"判"。这条劈法在现行代码里已经成立(见 §4 末与 §5)。 - -**多语言走 MCP / shell-out。** 单写 agent 跑在 Python(AgentScope)里,但探针是 node/CDP、构建是 esbuild、未来某个引擎的能力包可能是别的语言。跨语言不靠在 Python 里硬塞,而是走两条标准通道:MCP 协议天生跨进程跨语言(stdio 子进程或 HTTP),把任意语言写的能力暴露成 agent 可调的工具;或者 skill 目录里放任意语言的脚本,SKILL.md 指示 agent 用内置 Bash 工具 shell-out 去跑(机制实证见 §4)。 - -**单一实现时不冻接口。** 一个接口只有一套真实现的时候,把它的形状钉死,必然被那唯一一套实现反向决定,等第二套实现落地才发现抽象抽错了。所以遵 rule-of-three:第一套实现先定 v1 directional(方向性草案 + 留演进位),真正冻结推迟到第二套实现落地。这条直接影响下面 A 类里 A6/A7 的定级——它们现在只有 LittleJS 一套真实现,不该被当成已冻结的固定协议(详见 §2 的纠正与 §6)。 - -## 2 (A)系统内固定接口协议 - -这一节是换框架/换引擎都不许动的接口层。原始输入把它们列成 A1–A7 七条;对抗评审揪出其中有真协议被漏掉、也有"想要的契约"被错标成"已是的契约"。下面逐条给出责任、形状、为何固定、谁来适配、状态,并把漏掉的 gap 补进来、把错标的纠正过来。 - -### A1 生成任务协议(GenerationDispatcher) - -**责任:** 把"提交一次生成 / 回调结果 / 取消 / 查进度"收成业务侧(game-cloud)与生成执行后端之间唯一的稳定接缝。调用方不感知底下是 SAA 裸图、HTTP worker 还是 tier2 的 AgentScope service。 - -**为何固定:** 这正是"框架可换、契约不变"那条边界。换 SAA → AgentScope,只换 dispatcher 实现,调用方一行不改。谁来适配它:每个执行后端各写一个实现。语言 = Java(业务侧接口)。 - -**形状(纠正后):** 原始清单把它写成四方法契约 `submit()->taskId; handleCallback(); cancel(); progress()->status`,并标"现·载体=契约#6"。**这是把"想要的契约"错标成"已是的契约"。** 核对代码(`GenerationDispatcher.java`,hash 314b421a):现行 Java 接口只有单方法 `boolean dispatch(Map job)`,是 fire-and-forget 的投递握手;`handleCallback` 在回调服务上、不在 dispatcher 上;`cancel` 和 `progress` 根本不存在。把不存在的 cancel/progress 当成已固定的接缝,会误导适配方以为有取消/查进度可对接——而 tier2 的 long-running ReAct 恰恰最需要 cancel,它现在是零。 - -正确的写法是分两层标注:**已固定的 v1** = `dispatch(job)->bool` 投递握手 + 回调边(SAA 图 emit → 回调服务)。**待建的扩展(明确标"建")** = `cancel(taskId)` 与 `progress(taskId)->status`,这是 tier2 接入时必须补上的,不能假装已有。GenerationRequest 携 brief / confirmedGoal / assetContext(六类素材引用)/ tier(0/1/2)/ idempotencyKey(= traceId)。 - -**状态:** 现(单方法 dispatch + 回调边,两实现 `SaaGraphDispatcher.java` + `WorkerDispatchClient.java`)+ 建(cancel/progress 扩展,plan003 U10 控制面接入时补 tier2 入口 / 并发 / 补偿)。 - -### A2 生成状态 + checkpoint 协议 - -**责任:** 用平台自己的口径表达"一次生成现在跑到哪、能否续跑",不让任何框架的私有结构外泄成平台状态。承载断点续跑,以及三条 session 加载路径(续接 / 加载已有工程 / 新建)的状态语义。 - -**形状:** `GenerationState { traceId; phase/step; cur_iter; tasks_context; cost 累计; checkpointId }`。续跑语义 = 按 traceId 取最新 checkpoint。这里有一条已踩实的平台级坑:SAA 的 checkpoint 行 `saved_at` 没有 tiebreaker,同毫秒多行无法区分先后,所以续跑**必须显式传 checkpointId**,不能只靠时间戳取"最新"。 - -**为何固定:** 不变量五点里点名"状态模型是平台口径、不是框架私有结构"。若 SAA 的 checkpoint 行或 AgentScope 的 AgentState 直接当平台状态,换框架即推倒重来。谁来适配它:各后端的 dispatcher 实现把自己框架的状态序列化 / 反序列化到平台 GenerationState。语言 = Java(SAA 侧 MysqlSaver)+ Python(tier2 侧 AgentState ↔ Redis)。 - -**务实修正(对抗评审):** 平台至今**没有**一份显式的 GenerationState schema——它隐含在两套框架各自的状态里。在 tier2 未落、只有 SAA 一套真状态的此刻,就要求两侧都映射到一个尚不存在的统一 schema,是为未来的第二实现先建抽象。务实做法是先把 SAA 侧已经在跑的 checkpoint 字段(traceId / phase / cur_iter / checkpointId,加上那条 saved_at 显式传 checkpointId 的坑)固化成 v1 平台 GenerationState,等 tier2 的 AgentState 落地时按它适配,而不是现在凭空设计一个两侧都没验证过的统一态。 - -**状态:** 现(SAA 侧 MysqlSaver checkpoint,唯一 saver / threadId = traceId)+ 建(tier2 侧 AgentState 存取,plan003 U7)。**这条是潜在的反锁死缺口:显式 GenerationState 抽象还不存在,建议随 A8 trace 契约一并立 v1。** - -### A2.5(补) 统一 trace 契约 —— 反锁死链上最该先立、却被当成已存在的一环 - -对抗评审揪出的第一个真 gap,补成独立一条。A1 / A2 / A5,以及 AgentScope 适配器,全都把"trace 公共核心子集 + 扩展段"当成已有的固定协议去适配。核对代码:`find contracts -iname '*trace*'` 零命中,contracts/ 下根本没有 trace 契约。现状只有两样东西,且都不是它:`events.schema.json`(契约 #5)是玩家侧遥测信封,Java 侧的 tracer 是后端调用链追踪。两者都不是"生成 ReAct 三段(推理 / 动作 / 观察)→ 平台 trace"的契约。 - -**责任(应立):** 把单写 agent 每一步的"推理 / 动作 / 观察"三段、模型调用,统一成一份平台 trace 信封,供遥测、调试共用。成本是否并进这份信封(还是单立一条成本契约)留 §7 Q6 定;但无论并不并,**成本权威口径都钉死在 new-api 计费行**(经 traceId 关联),trace 至多携带关联键、绝不让 agent 自报金额成为账——这与 A5"agent 自述一律不作证据"同向。 - -**为何该先立:** 遥测 / 计费这一环的固定接缝实际是缺的。若不立,换框架时这一环各搞各的,trace 口径会漂移,反锁死链断在这里。它该被列为 A 类,且优先级排在前面——A1/A2/A5 都在等它。 - -**状态:** 建(不存在,待立 v1)。**这是清单原始版本最严重的误标:把一个零命中的契约当成"已是"去适配。** - -### A3 源项目契约(tier2 真引擎工程) - -**责任:** 认一个真 Phaser/Pixi 源工程"是什么、怎么构建出来、怎么存回来"的稳定形状。钉七要素四组:身份(类型标记)/ 工程骨架(文件树 manifest、入口文件)/ 构建可复现(构建 profile、依赖锁)/ 落库取回(内容哈希、落库寻址 API)。 - -**形状:** 新立 `contracts/agent-loop/tier2-source-project.schema.json`,独立 schema,不扩在现有同名文件上。字段含 `projectType:'tier2-engine'`(类型标记分流靠它)、fileTree、entry、buildProfile、depLock、contentHash(sha256)、addressing。沿用 GamePackage 那套 sha256 落库取回数据范式。 - -**为何固定:** 装载侧、构建侧、落库侧三方都要认同一形状,缺一样链就断;且"游戏 = 长生命周期项目,两年前的工程今天还得能原样构建"要求 depLock / buildProfile 随款冻结。红线:tier2 绝不复用现有 `source-project.schema.json`——核对代码(hash 5cadf504),那是 Tier0/1 的 ECS-lite 数据壳契约(`schemaVersion 1.0`,profile / gameDefinition),两条线结构完全不同。A3 懂得 fork 是对的。语言 = JSON Schema。 - -**务实修正(对抗评审):** 方向对,但定全风险高。tier2 整轨待 0 号 spike,Phaser 一行未落,连 fork 出的探针都还没真落代码(tier2/ 下目前只有 README / .agent / HANDOFF / ci / requirements.txt,无 harness 代码)。此刻就把七要素 schema 形状定全,spike 一跑很可能发现要素错配——esbuild profile 的真实字段、Phaser scene 树的真 role 枚举都还没见过真实例。建议先定**最小 keystone**:`projectType` 类型标记 + `contentHash` + `fetchById` 这三个装载 / 落库三方立刻就要认的,buildProfile / depLock / fileTree.role 等随 spike 实证再补,避免 spike 前冻死。 - -**状态:** 建(新立 schema,plan003 U9;最小 keystone 先行)。 - -### A3.5(补) 源项目版本寻址协议 —— 长生命周期项目的版本谱系 - -对抗评审揪出的第二个真 gap。A3 里"落库 / 取回"只写了 `addressing:{store→MySQL+OSS, fetchById}` 一句,但全生命周期里"同一 sourceHash 的工程被 feed / 再编辑 / 版本升级反复取回"需要一个稳定的寻址 + 版本协议:改源不改包 → 重建 → 产出新 versionId。这正是"游戏 = 长生命周期软件项目"裁定的核心兑现点,不该塞进 A3 的一个字段。 - -**责任(应立):** 定义源工程的版本谱系与取回 API 签名——sourceHash 寻址、versionId 版本化、改源重建产出新版本时旧版本仍可取回。建议单列,与 A3(单款工程的形状)分开:A3 管"一款长什么样",A3.5 管"一款的历史怎么寻址"。 - -**状态:** 建(不存在,待立)。 - -### A4 装载协议(取产物 → boot → 每帧 update/render → latch 终态轮询) - -**责任:** 定义生成产物怎么进浏览器跑起来:类型标记分流到两条装载分支,boot 上下文怎么注入,每帧回调形状,以及"游戏无 emit 通道 → 终态焊成可轮询的状态锁存(latch)、宿主轮询读"这条铁律。latch 这个词指的是:游戏跑到结束态时不主动发事件,而是把 `phase` 焊成 `'gameover'` 驻留在可读状态里,宿主每帧轮询去读,而非等游戏 emit。 - -**形状:** 现行第 9 类契约 `game-host.d.ts`:`GameHostBootContext{ctx:PluginContext, mainContext, canvas, seed, assets?}`、`GameInstance{init/update(dt)/render(g)/onInput?/destroy}`、`GameHostFactory`。装载分流(口径与代码对齐,纠原稿漂移):**现状**按 `pkg.engineBundle` 是否存在分流——有则走引擎包路(挂 `window.__GameBundle`、`bootGameHost`)、无则旧 `startRuntime` 兜底;**`projectType` 类型标记分流是 tier2 待建语义**(见 A3 字段 / A11 同口径),不是现状。tier2 右支取回须先 esbuild 构建再跑。 - -**为何固定:** 宿主与生成产物之间的稳定接线面;生成 agent 的唯一产出靶就是实现这个形状。两条装载分支解耦并存,但都服从"类型标记分流 + 引擎掌帧 + latch 终态"这套口径。谁来适配它:每条装载分支各写 boot 实现,生成 agent 产出物必须符合 GameInstance / Factory 形状。语言 = TypeScript(.d.ts)。 - -**状态:** 现(ECS-lite 左支,Runner v2 P1/P2 已实证)+ 建(tier2 右支第二装载分支,plan003 U9)。载体 = `game-runtime/src/core/game-host.d.ts`(落 game-runtime/src 而非 contracts/,因消费方只在 game-runtime)。tier2 右支的 boot 序列独立,不改 `boot-game-host.js` 的 `opts.engine` 注入边界。 - -### A4.5(补) 构建产物协议 + feed→play 装载入口 —— 两个被漏掉的固定接缝 - -对抗评审揪出的另两个真 gap,合并成一条讲,因为它们卡在同一个位置:产物造出来之后、进浏览器跑之前。 - -**构建产物 = 可装载 bundle 的固定形状。** 现有 `source-project.schema.json` 里已有一个固定语义:`buildInputHash = sha256(sourceHash + buildProfile)`,是确定性构建缓存命中键(核对代码确认,hash 5cadf504 第 12 行)。这是已存在的 A 类语义,但原始清单把构建相关的东西分散塞进 A3(源项目契约)和 A7(build 工具签名),没把它抬成独立契约。问题是:tier2 右支(esbuild 构建真 Phaser 源工程)和左支(ECS-lite 即取即跑、无构建)的构建语义差异巨大,缺一个统一的"构建产物 = 可装载 bundle"的固定形状,A4 装载协议就得各自猜 bundle 长什么样。建议把"构建输入哈希 + 构建产物形状"提成 A 类。 - -**feed → play 装载入口。** A4 止于浏览器内 boot + 每帧 + latch,但"feed 卡片如何拿到 versionId / engineBundle / projectType 并决定走哪条装载分支"这个接缝没被列为 A 类。核对代码:`game-package.schema.json`(hash c2cb4d75)的 `manifest` / `engineBundle` / `packageUrl` 已是事实载体,`engineBundle` 字段就是引擎 + 包装层 + 游戏代码的可执行 iife bundle 文本。tier2 真 Phaser 包(需先 esbuild 构建)进 feed 的播放路径,与 ECS-lite 即取即跑差异是结构性的。缺这环会让 tier2 产物"造得出却进不了 feed"。建议把 feed→play 的装载入口列为 A 类:现状按 `engineBundle` 存在性分流(事实载体已在 game-package.schema.json),tier2 的 `projectType` 类型标记分流是待建语义、需补 tier2 分支。 - -**状态:** 构建产物语义 = 现(buildInputHash 已在左支 schema)+ 建(tier2 右支构建产物形状);feed→play 入口 = 现(game-package.schema.json 事实载体)+ 建(tier2 分支)。 - -### A5 验收门协议(判定纪律 + verdict schema) - -这条是原始清单里被误分类最严重的一条。 - -**责任(抽象层,固定):** 把"完成与否"钉死成确定性、机器可判、禁 LLM 自评的契约。含三层校验框架(L1 硬约束必解 / L2 设计符合尽量 / L3 效果只评分绝不阻塞)、门定义、verdict 终判结构、accept/fix/kill 三值语义。铁律:verdict 由 judge 纯代码产出(无 LLM),agent 自述一律不作证据。这是防 Goodhart(刷指标)的确定性地板。 - -**误分类纠正(对抗评审):** 原始清单把现行 `verdict.schema.json` 直接当成"引擎无关的确定性地板,换哪个框架 / 引擎都不让步",并声称"tier2 扩:三层 verdict + 富游戏专属门 additive 扩展"。**核对代码后这站不住。** verdict.schema.json(hash 208a36ee)实测死锁在 Tier0/1 模板闭环上:`round: enum[0,1]`(tier2 ReAct 多轮迭代远超 1)、`structureOk` 的语义是"config 通过对应模板 schema(clicker/dodge/runner/match)"、`decision: accept/fix/kill`、且通篇 `additionalProperties:false`。一份带 `additionalProperties:false` 且 round 上限为 1 的 schema,**根本无法 additive 扩展**——tier2 只能 fork 一份,正如 A3 已正确地为源项目契约 fork。这是清单内部不自洽:A3 懂得别复用、另立独立 schema,A5 却幻想同一份 verdict 能跨 tier 扩。 - -**正确的劈法:** verdict 要拆成两层。**稳定的 verdict 元协议**(固定层)= decision 三值语义 + severity 分级 + "机器判 / 禁自评"纪律,这一层确实引擎无关、不让步。**per-tier 的具体 schema**(可按 tier 各立)= Tier0/1 用现行 verdict.schema.json,tier2 fork 一份新 schema 承载三层校验 + 富游戏三门(三系统联动 / 经济 / latch),round 放开、structureOk 换成源工程校验。关键纪律要求:tier2 的新 schema 必须把"机器判 + 禁自评"以同等强度焊进契约层,不能让纪律退化成靠 prose 约束、靠 agent 自觉——那正是治理条款 10 警告的塌陷模式(详见 §6 确定性裂缝)。 - -**为何固定:** "出题的和被考的绝不能是同一只模型"。无论底下换哪个框架 / 引擎,verdict 的判定权与机器判口径都不让步。谁来适配它:各引擎 / 品类的探针(B 类)把读到的原始数据喂进对应 tier 的 verdict schema。语言 = JSON Schema(verdict)+ Java/Node(judge 判定代码)。 - -**状态:** 现(L1 九门 + verdict 元协议已在 LittleJS 廉价线跑,机器判 + 禁自评纪律已落 schema 层)+ 建(tier2 fork 一份新 verdict schema,承载三层校验 + 富游戏三门,plan003 U6)。L3 用 M3 软检、绝不当门。 - -### A6 探针钩子协议(门从引擎读什么的抽象接口) - -**责任:** 把"门要从引擎读哪几样"抽象成稳定接口:canvas 选择器、帧计数源、boot 就绪信号、输入注入、可观测 state 读取。门(A5)只认这个抽象接口的结果,不认某引擎具体怎么读。 - -**形状:** `EngineProbeHooks` 抽象接口 `{ canvasSelector; frameSource()->number; bootReadySignal()->bool; injectInput(tap/key/drag); readState()->GameState }`。门按这五样判 A_boot / C_frame / D_render / E_live / F_wiring / G_input / H_progress / I_control。readState 其实分两层:引擎级可观测量(frame / boot / canvas)是 per-engine 的;富游戏的语义 state(coins / ingredients / orders / targets…)是 **per-品类** 的——同一个 Phaser 引擎,经营档导出 orders、塔防档导出 waves,由生成 agent 按品类 state schema(对接 A10)导出、不绑引擎。组织探针时别把这层语义 state 错当 per-engine。 - -**这条是"劈两半"的范本:** 抽象接口形状(读什么)是 A 类固定——门要稳定地拿到这五样;但"怎么从某引擎读"是 B 类 per-engine 可换实现,会随引擎变。LittleJS 用 `#game-engine` / `__engine.snapshot().frame` / `__gameHostEngineInitFired`,Phaser 全不同。换引擎 = 为新引擎重写这套钩子实现,不是参数化一键切。 - -**定级修正(对抗评审 + rule-of-three):** 抽象接口形状现在只有 LittleJS 一套真实现,Phaser 未落。此时把抽象接口钉死必被唯一实现反向决定。所以 A6 的抽象接口应标为 **v1 directional + 留演进位**,真正冻结推迟到 Phaser 探针落地(第二套实现)。谁来适配它:每个引擎写一份探针实现,做成 per-engine skill 或 sandbox driver。语言 = Node/JS(CDP 驱动);可经 MCP 暴露给跨语言 agent。 - -**状态:** 现(LittleJS 实现硬编码在 `play.cdp.cjs`)+ 建(Phaser 重写四条钩子,plan003 U3/U6;抽象接口待第二实现落地再冻)。底座选型(agentscope-runtime BrowserSandbox vs 回落自建薄沙箱)是 spike 前置阻断项(U3,tier2/harness/SANDBOX-PROBE.md)。 - -### A7 agent 能力面协议(toolkit 工具签名) - -**责任:** 钉死单写 agent 能调哪些工具、各自入参出参形状:写源 / build / 跑快检 / 跑门 / 读 verdict / 截图 / 查资产 / 模板初始化 / finish。这是 agent ↔ 平台之间的工具接口契约,不绑某框架的工具注册机制。 - -**形状(directional):** write_source(files[])、build(profile)->bundle、headless_check()->quickVerdict、run_gates(spec)->Verdict(A5 形状)、read_verdict()->Verdict、screenshot()(取证、绝不进硬门判定)、query_assets(spec)->assetRefs、scaffold_init(template)、finish(sourceProject)。三类角色:核心环 / 取证 / 起手收尾。两条焊死要求:finish 的参数 schema 与 A3 源项目契约**共用同一份定义**(防交付 ↔ 落库漂移);截图只取证、不判定;验收零自评。 - -**定级修正(对抗评审 + rule-of-three):** 原始清单把 A7 列为已固定的 A 类协议。但 contracts/ 下不存在任何 toolkit 签名契约工件(grep `run_gates` / `scaffold_init` 零命中),它现在纯是散文 directional 描述,且只有 LittleJS 一套真实现。把一个尚未契约化、只有一套实现的工具面钉成固定协议,等于在只有一个实现时就冻接口——与清单自己对 Pixi 讲的 rule-of-three 自相矛盾。**A7 应降级为 v1 directional + 留演进位**,真正固化签名推迟到 Phaser 工具落地(第二套实现)。但"工具接口以契约定义、不绑某框架的注册机制"这条原则和"finish 形状 = A3 形状"这条等式,现在就要立住——它们是方向,不是实现细节。 - -**状态:** 建(v1 directional;Phaser 落地后固化)。 - -### A 类一览(含定级修正) - -| 编号 | 协议 | 现/建 | 定级修正 | -|---|---|---|---| -| A1 | 生成任务协议 | 现(dispatch 单方法)+ 建(cancel/progress) | 纠:cancel/progress 是"建"不是"现" | -| A2 | 生成状态 + checkpoint | 现(SAA 侧)+ 建(显式 GenerationState v1) | 务实:先固化 SAA v1,别凭空设统一态 | -| A2.5 | 统一 trace 契约 | 建(不存在) | 补:被当成已有却零命中,优先立 | -| A3 | 源项目契约(tier2) | 建 | 务实:先定最小 keystone,spike 后补 | -| A3.5 | 源项目版本寻址 | 建(不存在) | 补:长生命周期版本谱系,单列 | -| A4 | 装载协议 | 现(左支)+ 建(右支) | — | -| A4.5 | 构建产物 + feed→play 入口 | 现(部分载体)+ 建(tier2 分支) | 补:两个结构性接缝被漏 | -| A5 | 验收门协议 | 现(元协议 + 左支 schema)+ 建(tier2 fork schema) | 纠:verdict 不能跨 tier additive 扩,须劈成元协议 + per-tier schema | -| A6 | 探针钩子抽象接口 | 现(LittleJS)+ 建(Phaser) | 降:v1 directional,第二实现后冻 | -| A7 | agent 工具签名 | 建 | 降:v1 directional,第二实现后冻 | -| A8 | 送审/审核协议 | 现·部分(Tier0/1 单线硬编码)+ 建 | 补:渠道/tier2 共用接缝缺失,两 verdict 口径未统一 | -| A9 | 资产协议 | 现·骨架 + 建 | 补:身份/许可/权属/血缘缺失,护城河在数据模型零兑现 | -| A10 | 玩法模板协议 | 现·部分(编译期常量)+ 建 | 补:模板结构 schema 与两阶段注入口径缺失 | -| A11 | 试玩/HITL 迭代协议 | 现·部分(装载复用 A4)+ 建 | 补:HITL 反馈回路三档未抽象 | -| A12 | 通用检查门协议 | 现·散三处 + 建 | 补:引擎无关检查散三处,未收成一道门、未分时相 | -| A13 | 配置注册表协议 | 建(代码侧零落地) | 补:四类配置各自为政,热改/GitOps 两路无判据 | - -### 平台级固定协议(第二轮:A8–A13) - -第一轮的 A1–A7 划的是"生成执行"这一段——从提交生成、跑 ReAct 循环、过验收门、到装载进浏览器——业务侧与生成后端之间的接缝。第二轮往外推一层,审了送审/审核、资产、玩法模板、试玩迭代、通用检查、配置六个平台面。这六面的共同状况是:廉价线(Tier0/1)在生产里已经把它们大多兑现了真实现,但都硬编码在单条线、单条 publish 链路上,从没抽成"两条生成线 + 各发行渠道共用"的固定接缝。tier2 一旦落地,这六面要么各搭一套、要么硬接进单线代码,前者割裂、后者绑死。所以这一轮的任务不是从零造协议,而是把已经长出来、却埋在单线实现里的接缝形状抬出来固定住,并诚实标出哪几段已兑现、哪几段还是空白。 - -编号续 A1–A7,无重号、无重叠。A13 是第一轮没有的新面——A1–A7 全是生成执行接缝,A13 管的是"配置怎么注册、热改还是 GitOps",与第一轮 A2.5 的 trace(管运行轨迹 + 成本上报)正交;但 A13 必须把第一轮已立住的"prompt = 第 8 契约、走 GitOps 四闸"当成自己的一个已落地实例去引用,而不是另起一套配置口径。 - -#### A8 送审/审核协议(Submission & Review Protocol) - -**责任:** 把"提交送审 → 取 verdict → 状态回调"收成两条生成线(SAA 廉价线 / tier2 富游戏线)加各发行渠道共用的唯一稳定接缝。覆盖三段:生成产物提交送审;合规裁决产出 pass/review/block;审核结果回调(pass 准入 feed / review 转人工复核 / block 驳回)。审核状态机归 project 模块、合规裁决归 compliance 模块,这道接缝边界固定不变。 - -**形状:** `evaluate(ComplianceGateReqDTO{gameId, versionId, title, summary, ageRating, promptHash}) → GateVerdict{verdict:enum[pass,review,block], rating, detail[]}`;审核态权威 = `ReviewRecordDO{decision:1通过/2拒绝/3下架, gateResult:pass/block}`;回调 `communityNotifyApi.notifyReviewResult`。 - -**两段串联,不是一段——这是适配方最容易误解的地方。** 核对代码确认:合规门 verdict(pass/review/block)与人工审核 decision(通过/拒绝/下架)是两段串联、不是同一个 verdict。`ComplianceGateApi` 的文档注释写得很清楚:`block → admitted=false`(不进 REVIEWING),`pass/review → 进 REVIEWING` 后由人工 `reviewProject` 再出 decision 1/2/3。所以合规门 verdict 是人工审核 decision 的**前置闸**,A8 把两者都叫 verdict 会让适配方以为是一段。协议层须显式标:合规门 verdict ≠ 人工审核 decision。此外还有第二处 verdict 口径要对齐——合规裁决的 pass/review/block 与第一轮 A5 生成门的 accept/fix/kill 是两套独立 enum(核对 `ComplianceVerdictEnum` 与 `verdict.schema.json` 确认),协议层要么统一、要么显式定义两者的映射,否则合规裁决与生成裁决拼接处会割裂。 - -**还要补两条已落库却被漏掉的回路。** ReviewRecordDO.decision 已含 3=下架,V22.0.0 已建 policy/appeal 两表(申诉),即"block 后的申诉 → 复核 → 翻案"和"已上架后下架 → 重审"这条回路在代码里已经有载体,但只把它当三段直线("提交→verdict→回调")会漏掉它。tier2 是长生命周期项目,同一 gameId 改源重建会产出多个 versionId、各自送审,这条"多版本各自送审"的口径也要列进协议。 - -**为何固定:** 无论哪条生成线、哪个渠道,送审都是同一形状(提交→裁决→回调),换实现就是写一个 adapter 接到这道接缝;合规是护城河一层,接缝必须稳定可审计。verdict 口径若不统一,合规裁决与生成裁决拼接会割裂。谁来适配它:tier2 产物走同一 evaluate 送审接缝(零改设计);各渠道(微信/抖音/快手/TapTap)提审走 B-CHANNEL-* adapter;合规原子(风格/IP/真内容安全)走 B-COMPLIANCE-ATOM-* adapter。语言 = Java(同进程接缝)。 - -**状态:** 现·部分(Tier0/1 单线硬编码)。载体 = `ComplianceGateApi.evaluate`(单方法 seam,game-module-compliance-api,project.publish 同进程注入)+ `ComplianceGateServiceImpl`(聚合 max,落 game_compliance_gate_result 审计台账 + upsert game_content_rating)+ project `AdminProjectController.reviewProject`(POST /admin/project/review)+ 契约 compliance.yaml(R1 唯一 seam /rpc-api/compliance/evaluate)+ V9.0.0/V22.0.0 SQL。建·不存在的部分:"两条线 + 各渠道共用一份"未抽象(现为 publish 单链路硬编码);tier2 走同一接缝;各渠道提审 B adapter(runtime.yaml:14 明列渠道转换为"扩远期、仅留契约挂点");两 verdict 口径统一;申诉/下架/重审回路未列进协议;风格/IP 原子(StyleComplianceAtom/IpComplianceSeam)现为桩默认 pass。 - -#### A9 资产协议(Asset Protocol) - -**责任:** 定义游戏资产的身份(跨源稳定 ID)、许可(license)、权属(ownership,超出行级 creator 隔离)、寻址(ref → 可解析),以及六类 category 枚举(sprite/character/effect/scene/ui/music)这个事实固定面。生成侧的 query_assets 工具(A7)按此协议查,不感知底下是哪个资产源。护城河的"资产合规"一层必须在数据模型里有兑现点。 - -**形状:** 现状 `assetSpec{id, category, ref, url, provider}`(核对代码确认五字段,`provider` 默认 mmx-cli);须补 `{license, ownership, identity(跨源稳定)}`;`query_assets(category, ...) → assetSpec[]`;`provider` 字段 = 可插拔接缝。 - -**还要补一条 README 已点名却零落地的接缝:资产血缘。** README 把"9f 资产血缘"列为第 9 契约组的成员,但生成产物 ↔ 所用资产的血缘追溯(护城河资产合规真正需要的"这款游戏用了哪些资产、各自来源/许可")既不在 game_material 也不在 assetSpec。A9 不能只停在给 assetSpec 加四个字段,资产血缘要作为独立 gap 补进来——否则"资产合规"在审计侧仍是空话。 - -**为何固定:** 六类 category 枚举四处同引(MaterialCategoryEnum / assetSpec / StudioAssetContextItem / DB),生成侧按统一协议查、不感知 provider;identity/license/ownership 是护城河资产合规层,必须固定可审计。可插拔的是 provider 字段——允许切换底层资产源而不动消费侧。谁来适配它:B-ASSET-mmx(mmx-cli 生成器,现行默认 provider)、B-ASSET-MARKET(平台素材市场,待建)、B-ASSET-3RD(第三方源)。语言 = JSON Schema + Java(DB + service)。 - -**状态:** 现·骨架(身份/许可/权属缺失)。载体 = game_material 表(V24.0.0:creator_user_id 行级隔离 / category 六类冻结 / ref / url / provider 默认 mmx-cli / size_bytes / mime_type)落在 studio 模块(非 trade、非独立 ip;game-module-ip 物理目录不存在)+ StudioMaterialServiceImpl + source-project.schema.json $defs.assetSpec(:90-101)+ StudioAssetContextItem。建·不存在的部分:license/ownership(资产级权属,非行级 creator 隔离)与跨源稳定 identity(数据模型对护城河资产合规零兑现);资产血缘(README 9f 已点名,零载体);资产市场(可交易/他人选用——game_material 是创作者私有库,trade 仅钱包/结算/订阅、无素材交易);统一寻址协议(ref MVP = infra 路径,ref=url 同源);market/3rd 的 B 源(provider 只兑现 mmx-cli 一个值)。 - -#### A10 玩法模板协议(Gameplay-Template Protocol) - -**责任:** 定义玩法模板的"结构"(品类框架:玩法骨架 / 约束 / 示例 prompt / 校验 schema),以及怎么把它喂进阶段 1(设计参考)与阶段 2(生成约束)这两阶段的注入口径,两条线共用。模板是品类框架、引导 agent 生成,不是 pre-built 整局代码——旧"游戏模板 = 填参整局代码"已废。 - -**形状:** templateId(白名单字符串,如 generic/business-sim/narrative/puzzle/trpg/heritage)+ prompt md(品类设计师 prompt)+ bundle 校验 schema(contracts/templates/.schema.json);`getTemplateList() → TemplateRespVO{templateId, name, description, examplePrompt}`;PromptResourceLoader 按 templateId 渲染(`{{input.xxx}}`)喂 LLM。须补:统一的"模板结构"schema + 两阶段注入口径。 - -**这里有一处跨协议依赖必须点出来:模板 schema 与 A5 verdict 的 structureOk 耦合。** contracts/templates/.schema.json 既是 bundle 校验 schema,又被 verdict.schema.json 的 structureOk 语义引用("config 通过对应模板 schema")。模板 schema 改了会牵动 verdict 判定——这是 A10 与 A5 之间的既有耦合,A10 讲模板结构协议时不能漏掉这层接缝。 - -**为何固定:** 模板"怎么喂进两阶段"的注入口径应稳定、两条线共用;templateId 白名单单点同源(AigcTemplateConstants)是事实固定。可插拔的是各品类模板包(prompt + schema + RAG)——可增删替换,品类区分留在 prompt 层。谁来适配它:B-TPL-<品类> 各品类模板包(prompt 模板 md + 品类校验 schema + RAG 语料)。语言 = prompt md + JSON Schema(数据形态,非可执行)。 - -**状态:** 现·部分(模板 = 编译期常量,无结构协议)。载体 = AigcTemplateConstants.SUPPORTED_TEMPLATE_IDS(核对代码确认 generic + 5 品类全在 live 白名单,U7 R-TPL 2026-06-18 加)+ AigcTaskServiceImpl.getTemplateList + AigcTemplateDTO(aigc → studio 镜像)+ contracts/prompts/04-config/{品类}-designer.md + contracts/templates/.schema.json + PromptResourceLoader(构建期 maven 复制进 classpath、按 templateId 缓存渲染)+ 前端 Template.vue。5 品类在白名单内是"现",其 RAG/范例库与"模板结构统一 schema"是"建"。建·不存在的部分:统一"模板结构"schema(现靠 PromptResourceLoader.TEMPLATE_RESOURCES Map 硬编码绑定 prompt md + 校验 schema);两阶段注入口径(现仅 `{{input.xxx}}` 渲染喂单次 LLM,无"tier2 工作室设计 → 单写生成如何消费"的统一口径);RAG/品类范例库(prompt md 是静态文本);模板 DB 表(注释明言"本项目无模板定义 DB 表",模板 = 编译期常量,运营无法配置,增删模板要改 Java 常量)。 - -#### A11 试玩/HITL 迭代协议(Playtest & HITL-Iteration Protocol) - -**责任:** 创作者试玩的装载部分直接复用 A4 装载协议、不是本协议的净增量(创作者预览 scene=preview 与玩家试玩 scene=play 已共用同一装载协议,这点 A4 已成立)。A11 的净增量是创作者反馈回阶段 1 重生成的 HITL 迭代闭环口径——确定性覆写 / 模块重生成 / 整体重设计三档——并把它与 session 的"加载已有工程迭代"路径统一,两条线共用。 - -**形状:** 装载复用 A4(GamePlayer.vue iframe srcdoc 注入 SDK+Runtime+engineBundle,inject.ts 按 pkg.engineBundle 分流到 __GameBundle.bootGameHost;取包 runtime.yaml GET /runtime/package/{versionId}?scene=preview|play)。HITL 净增量:`StudioModify{baseVersionId, mode:enum[deterministic 免LLM | regenerate-module 重生成单 behavior], target{kind:asset/config/level/behavior}, payload}`;session 路径"加载已有工程" = `SourceProjectService.fetchByVersionId`(按产物版本反查源工件取 base 源)。须补:反馈回阶段 1"整体重设计"的第三档 + tier2 迭代统一。 - -**装载分流口径要纠一处与代码不符的漂移。** A11(及第一轮 A4)写"按 projectType 分流",但核 game-studio/src/host/inject.ts:实际是按 `pkg.engineBundle` 是否存在分流(有 → __GameBundle 引擎包路 / 无 → 旧 startRuntime 兜底,注释标"模板体系重构中"),全文无 projectType。projectType 分流是 tier2 待建语义(建),现状载体是 engineBundle 存在性(现)。这是 A4/A11 共有的口径漂移,本轮一并纠正:现 = engineBundle 分流,建 = projectType 分流。 - -**为何固定:** 试玩装载形状复用 A4(创作者预览/玩家试玩同一装载协议);HITL 反馈回路三档口径应稳定、两条线共用。可插拔的是各 tier 的实现:tier0/1 走 studio.yaml 现行 modify(deterministic/regenerate-module),tier2 走 AgentScope session 的"加载已有工程"路径(Workspace.workdir 指向已有工程迭代)。装载层适配 = A4 的 inject.ts engineBundle 分流(可加 tier2 第二装载分支)。语言 = Java(studio modify)+ Python(tier2 session)+ TypeScript(装载分流)。 - -**状态:** 现·部分(装载复用 A4 成立,HITL 反馈回路未抽象)。载体 = StudioSessionDO{creatorUserId, gameId, templateId, prompt, attachments, status} + StudioSessionStatusEnum(0草稿/1生成中/2完成/3失败)+ AppStudioController(createDraft/generate/getTask/regenerate/create/modify/extend)+ studio.yaml StudioModify(mode deterministic|regenerate-module)+ SourceProjectService.fetchByVersionId(加载已有工程,核对代码确认真实存在,modify/extend 按 baseVersionId 反查 base 源)+ 前端 GamePlayer.vue/inject.ts/Play.vue + runtime.yaml scene=preview|play。试玩装载复用 A4 = 已成立(preview/play 共用)。建·不存在的部分:session 三路径中"续接之前会话"无显式入口、状态机 DRAFT→GENERATING→DONE/FAILED 线性、无"迭代中"态;创作者反馈回阶段 1"整体重设计"档(现 modify/extend 只到确定性覆写 / 单 behavior 重生成两档);tier2 反馈 → 工作室重设计与 studio modify 接缝统一。 - -#### A12 通用检查门协议(Engine-Agnostic Check-Gate Protocol) - -**责任:** 引擎无关的平台检查门,对所有引擎一视同仁、不需 per-engine 探针:提交侧 prompt 内容安全、产物体积门、产物逻辑/CSP 静态校验。这一层与 A6 探针钩子(per-engine 读帧/canvas/state)互补——A6 是引擎相关、要为每个引擎重写,A12 是引擎无关、对任何引擎产物都一样跑。 - -**形状:** 现状散在三处,须收成一道引擎无关门:aigc 提交侧 `SafetyCheckClient`(GP9,prompt 内容安全,safe=false 拒入队、fail-closed、8s+1retry)+ runtime 产物体积门(`RUNTIME_BUILD_BUNDLE_SIZE_EXCEED`)+ inject.ts 的 scanLogic + CSP(connect-src none)。收成一道门时须暴露统一的"提交检查 + 产物检查"两段接口,两条生成线共用。 - -**收门时必须区分时相,否则会把两类检查混成一锅。** SafetyCheckClient 是生成前的 prompt 安全(GP9,入队前拦截),体积门和 scanLogic 是产物构建后的校验——两者一前一后、触发时机不同。把它们收成"一道引擎无关门"时若不分时相,会把入队前拦截和产物校验混为一谈。正确做法是协议层显式分两段:提交侧检查(生成前,prompt 安全)与产物侧检查(构建后,体积/逻辑/CSP),各自有触发点,共用同一道引擎无关门的外壳。 - -**为何固定:** 这几样检查与引擎无关,无论 LittleJS 还是 Phaser 产物都一样跑,且都是平台安全/合规底线,应固定在引擎无关层、不下放给 per-engine 探针。可插拔的是各检查的具体实现(内容安全模型可换),但"提交检查 + 产物检查"两段口径与触发时机固定。谁来适配它:内容安全模型走 B-COMPLIANCE-ATOM-* 或独立检查服务(实现可换,接缝不变)。语言 = Java(SafetyCheckClient/体积门)+ TypeScript(inject.ts scanLogic/CSP)。 - -**状态:** 现·散三处(从未收成一道门)。载体 = aigc SafetyCheckClient(确认 GP9 fail-closed)+ runtime ErrorCodeConstants 的 RUNTIME_BUILD_BUNDLE_SIZE_EXCEED(确认)+ game-studio/src/host/inject.ts 的 scanLogic + CSP connect-src none(确认)。三处真散在、从未收成一道"引擎无关通用检查门"协议;时相区分(提交侧 vs 产物侧)未在协议层显式划。 - -#### A13 配置注册表协议(Config-Registry Protocol) - -**责任:** 把 model / prompt / skill / mcp 四类配置统一成一份注册表协议:谁注册、注册成什么形状、哪类走热改(DB 直写)、哪类走 GitOps(registry + CI 四闸)。两条生成线共用,运营与研发各按权限改对应类。 - -**形状:** 配置注册表(prompt·model·skill·tool·mcp 节点)——这是 agentic 集成架构文档里设计的 R 节点。须落地为统一的注册/读取接口,并把"热改 vs GitOps"的分流规则协议化。 - -**最该补的是这条:热改还是 GitOps,本身没有协议化判据。** 现状已自发形成两条路——prompt 走 GitOps(registry.yaml + 四闸 CI),infra_config 走 DB 直写(admin 热改)——但没有"哪类配置该走哪条路"的固定判据。缺这条判据,新配置项落地时两条路会随意选,而这恰恰是 A13 配置注册表统一最该解决的核心,却被漏成空白。建议的固定判据:影响生成质量/安全的配置(prompt、生成门阈值)走 GitOps 四闸、不可热改;运营降级开关/阈值走 DB 热改。A13 还须显式引用第一轮已立的"prompt = 第 8 契约、GitOps 四闸"作为配置协议的一个已落地实例,避免另起一套配置口径。 - -**为何固定:** 配置注册的形状与"热改/GitOps 分流判据"应稳定、两条线共用,否则换框架时配置口径各搞各的。可插拔的是各类配置的具体内容(模型清单、prompt 版本、skill/mcp 实例),它们随业务增删,但注册接口与分流判据固定。谁来适配它:各配置源(prompt registry / model properties / skill/mcp 实例)按统一注册接口接入。语言 = Java(注册接口)+ YAML(registry)。 - -**状态:** 建(代码侧零落地,四类各自为政)。核对代码:`ConfigRegistry`/`config_registry`/配置注册 在 game-cloud Java 侧零命中,只在 agentic 集成架构文档里有"配置注册表 R 节点"的设计。现状四类各自为政:prompt = PromptResourceLoader 构建期 maven 快照(§6.1 方案 A,非热加载),model = 散在 Java properties + wg1/gen-worker/worker/models.yaml 一份 worker 本地,skill/mcp = Java 后端零存在。GitOps(prompt 走 contracts + 四闸)与 DB 直写(infra_config 降级开关)两条路已自发形成,但未被统一为一条配置协议、无分流判据。 - -## 3 (B)skill / mcp / tool 可插拔模块 - -这一节是换引擎 / 换框架时被换掉的实现层。每条对接上面某几条 A 协议;并明确它该做成 AgentScope 的 skill、还是 MCP、还是 tool(机制依据见 §4)。 - -### B-ENG-LittleJS — LittleJS 引擎能力包(超休闲 / Tier1 廉价线,现行) - -**责任:** 给 agent 提供在 LittleJS 上写游戏的全套能力:写法 playbook + 引擎文档/范例语料 + 脚手架工程骨架 + 九门探针的 LittleJS 钩子实现。这是现行廉价线在跑的那套底座的能力包形态。 - -**形态:** 写法 / 脚手架 / RAG 语料做成 **skill**(SKILL.md frontmatter name+description + markdown 指令 + 资源目录),正合"如何做某一类事";探针钩子实现是 node/CDP,做成 skill + Bash shell-out 或 MCP。 - -**对接哪条 A:** A6 探针钩子(实现 canvas / 帧 / boot / state 四钩子)、A7 工具接口(实现九工具的 LittleJS 版)、A4.5 构建 profile、A4 装载(ECS-lite / `__GameBundle`)。 - -**语言:** skill 正文 markdown + node(探针)+ 任意脚手架语言。 - -**状态:** 现 —— 九门 harness + LittleJS 钩子在生产已跑(`play.cdp.cjs` 硬编码 LittleJS)。能力包接口形态本身 = 建(第一版只硬编码、不抽满,见 §6 克制)。 - -### B-ENG-Phaser — Phaser 引擎能力包(tier2 富游戏,首批真实现) - -**责任:** 给 tier2 单写 agent 提供在 Phaser 上写富游戏(肥鹅美食街档:多系统耦合 / 稠密 UI / 大内容量)的全套能力:Phaser 写法 skill + Phaser 文档 / 挂机经营先例语料 + Phaser 多文件 src/ 脚手架 + 九门探针的 Phaser 钩子实现(为 Phaser 整个重写,非参数化切换)。 - -**形态:** skill(写法 / 避坑 markdown)+ RAG 语料(补模型对 Phaser 的密度)+ scaffold(Phaser 多文件 src/ 骨架,平台预建那部分、先天过 boot)+ 探针钩子重写(node CDP)+ 把工具接进 AgentScope Toolkit 的 FunctionTool 薄壳(python)。 - -**对接哪条 A:** A6(四钩子 Phaser 等价重写)、A7(工具接口)、A4.5(esbuild for Phaser)、A4(第二装载分支 boot-phaser-host)、A3(源项目契约七要素)。Phaser 是 A6/A7 的**第二套实现**——它落地才是把这两条抽象接口从 v1 directional 固化成稳定协议的依据。 - -**语言:** skill markdown + node(探针 / harness)+ Phaser/JS(脚手架)+ python(FunctionTool 薄壳)。 - -**状态:** 建 —— tier2 待 0 号 spike;plan U2(roles/prompt/validate/run 按 Phaser 重写,接近 net-new)、U3(探针重写 + 沙箱底座)、U4(mini-肥鹅 Phaser 脚手架)。现有载体 = `tier2/harness/play-phaser.cdp.cjs`(待真 fork)。 - -### B-ENG-Pixi — PixiJS 引擎能力包(首批第二引擎,当前留桩) - -**责任:** 给 agent 提供在 PixiJS(Web 2D 渲染事实标准,纯渲染层)上写游戏的能力包。它的真实价值是充当"第二个引擎实现",逼出引擎能力包的通用接口形状——有两套实现做依据,才抽真正的 skill/tool/mcp/rag/脚手架接口而不会白抽。 - -**形态:** 同 Phaser 能力包的五件套形状,但当前是桩。 - -**对接哪条 A:** A6 / A7 / A4.5 / A4。它落地时正是抽象出 A6/A7 通用接口的第二依据来源。 - -**语言:** 同 Phaser 包(skill markdown + node + python)。 - -**状态:** 缓 / 建 —— 首批选型含 Pixi 但当前留桩。通用能力包接口待 Pixi 这第二实现落地再抽。 - -### B-ENG-Cocos — Cocos 引擎能力包(3D / 渠道导出轴,人在环、非自治循环) - -**责任:** 给 3D / 复杂场景 / 渠道导出场景提供 Cocos 能力,服务的是"人在环、离线作者"那条正交轴,不是无人值守的自治生成循环。 - -**形态:** 与自治轴的能力包不同。Cocos 强制依赖图形编辑器、无成熟无头 CLI,所以它不是给自治 agent 的纯代码 skill / 探针,而是编辑器 + 人在环 +(可选)Cocos MCP 插件那套。落点在 3D / 渠道导出而非 tier2 ReAct 循环。 - -**对接哪条 A:** 适配渠道导出 / 3D 那条人在环轴,**不**直接对接 A6 探针协议(它不在无人值守循环里)。 - -**语言:** Cocos/TypeScript + 其 MCP(若用)经 JSON-RPC 跨语言。 - -**状态:** 缓 / future —— 明确推翻旧"Tier2/3 = Cocos+MCP"的锁定结论,Cocos 退回 3D / 渠道导出 / 人在环,不在 tier2 自治轨。 - -### B-PROBE-Phaser — 验收门探针实现 · Phaser(只实现 A6,不碰 A5 判定) - -**责任:** 把"怎么从 Phaser 读帧 / canvas / state / 注入输入"这件 per-engine 的事实现出来:在真浏览器里 navigate → 截图 → 读帧 → 注入 tap/key → 读 gameState,把原始观测数据交给固定的门判定层。它只负责"读"和"驱动",绝不负责"判 pass/fail"——判定是固定协议层(A5)的事。 - -**形态:** node + CDP(沿用现行 `play.cdp.cjs` 的会话 / 截图 / 像素回读 / FNV hash / checkAssertion / runDriver 骨架),重写四钩子,加经营品类 driver(business-sim:点合成 → 凑单 → 交单 → 看金币涨)。 - -**对接哪条 A:** A6(per-engine 实现面)+ A5 的"原始观测数据输入"那一端;绝不实现 verdict 判定逻辑本身。 - -**语言:** node(现行最顺)/ 可换任意——MCP 协议天生跨语言,探针理论上可任意语言;若沙箱底座选 BrowserSandbox 则经其 page.evaluate。 - -**状态:** 建 —— plan U3;现有载体 = `tier2/harness/play-phaser.cdp.cjs`(待 fork)+ `business-sim.driver.js` + `SANDBOX-PROBE.md` 前置阻断结论。fork 行号锚点钉到 A-model 合并后版本重取。 - -### B-PROBE-LittleJS — 验收门探针实现 · LittleJS(现行,per-engine 探针范例) - -**责任:** LittleJS 引擎的探针钩子实现,即现行九门 harness 的引擎读取面:`#game-engine` 像素回读、`__engine.snapshot().frame` 帧源、`__gameHostEngineInitFired` boot 信号、`__gameState` 状态读取,加九个 driver 家族真玩驱动。 - -**形态:** node + CDP,现行 `play.cdp.cjs`(约 1131 行);含 connect / waitBoot / frameDelta / brightPixels / tap / key / readGameState + runDriver 九分发 + checkAssertion + 九门组装。 - -**对接哪条 A:** A6(LittleJS 实现)、A5 原始数据端。它本身就证明了"探针实现绑引擎、verdict 判定不绑引擎"这条劈两半成立。 - -**语言:** node/CDP。 - -**状态:** 现 —— 生产已跑、判过大量游戏。driven 感知 advisory 分级 = 接(A-model 分支已落、待合并 dev/2.0.0 对账)。 - -### B-FRAMEWORK-AgentScope — agent 框架适配器 · AgentScope(tier2 自治富游戏轨,锁 2.0.2) - -**责任:** 把 AgentScope 2.0.2 这套自治 ReAct 框架接到平台的固定协议上:实现任务协议(经 Agent Service `create_app` 接 A1 GenerationDispatcher)、状态模型(存取 AgentState 而非序列化活对象,映射到 A2)、工具接口(把九工具 + mmx 接进 Toolkit,实现 A7)、验收门禁(在门内迭代、禁 LLM 自评,服从 A5)、遥测(订阅 typed Event System,经 trace 中间件映射到 A2.5)。 - -**形态:** 它是"框架适配器",不是能力包。一边吃平台的五条固定协议,一边用 AgentScope 的机制(Toolkit / AgentState / Event System / Agent Service)去满足它们。换框架(AgentScope → 别的)= 重写这一个适配器,五条 A 协议不动。 - -**对接哪条 A:** A1 / A2 / A2.5 / A5 / A7。**计费修正(对抗评审):** 原始清单把"预算 Middleware 订阅 ModelCallEndEvent 折 ¥"只放在这个适配器里,是框架侧实现,不是固定协议。但成本归集是跨 tier、跨框架的横切——若不立一个"生成成本上报"的 A 类契约(谁、哪个 task、花了多少、命中哪个 new-api 计费行),换框架时计费口径会各搞各的,与 newapi_cost 权威口径漂移。建议把成本上报并进 A2.5 trace 契约(trace 里带 cost 段),AgentScope 适配器只是其一个上报方。 - -**语言:** Python(AgentScope 在 Python)。 - -**状态:** 建 —— tier2 待 0 号 spike,锁 AgentScope 2.0.2(外部源码已 clone 在 /root/oss/agentscope)。 - -### 平台级可插拔模块(第二轮:对接 A8–A13) - -第一轮的 B 模块讲的是"换引擎"那条轴——LittleJS/Phaser/Pixi/Cocos 能力包、探针实现、框架适配器。第二轮补的是"换渠道、换资产源、换品类、换合规原子"这几条轴上的可插拔件,它们各自对接上面新立的 A8–A13。一条贯穿的纪律要先说清:这些 B 件里有几样发生在生成线之外——渠道提审在"已过平台送审之后、发行阶段",根本不在 SAA/tier2 两条生成循环里,它是发行侧 Java/任意语言的下游 adapter,不是给 tier2 Python agent 用的"生成线共用 MCP 工具";合规原子是 compliance 模块内同进程的可替换 Java 实现,而非跨进程 MCP——因为 ComplianceGateApi.evaluate 是 project.publish 同步注入的接缝,把原子标成异步 MCP 会破坏 evaluate 的同步语义。这两点把第二轮 B 件的形态从"默认 MCP"拉回到各自接缝该有的形态。 - -#### B-CHANNEL-wechat / douyin / kuaishou(及 TapTap 等,每渠道一个) - -**责任:** 把平台已通过送审/审核的产物,转换成对应渠道的小游戏包 + 调用该渠道审核 API 提交 + 接收渠道侧 verdict 状态回调,归一化回平台送审状态机。微信、抖音、快手、TapTap 各建一个 adapter,按需新增。 - -**形态:** 发行侧渠道 adapter,接 A8 送审协议的下游。语言任意(渠道审核 API 多为 Java 后端要调的 B 端 HTTP 服务,亦可经官方 SDK/MCP 调用),非 skill。要纠正一处定性偏差:渠道提审不在两条生成线的循环内,不该按"生成线共用的 MCP agent 工具"来框,它是 runtime/发行侧的渠道适配,与生成线的工具是两回事。 - -**对接哪条 A:** A8 送审协议(提交 → verdict → 状态回调)+ 产物侧对接 A4 装载/打包(渠道试玩包转换)。 - -**为何可插拔:** 每个渠道的审核 API、包格式、回调形态各异且随渠道版本漂移,且渠道数量会增长,所以数量与实现都可插拔;平台侧"提交/查 verdict/状态回调"三段形状固定为 A8,各渠道只写各自 adapter 接进来,互不影响,新增渠道 = 加一个 adapter、不动 A8 与生成线。 - -**状态:** 建 —— 现无载体。runtime.yaml:14 明列"渠道转换(微信/抖音/快手/TapTap 试玩包,T-RT-21~24)属扩远期,不进 MVP,仅留契约挂点";提审回调零代码、零目录。 - -#### B-COMPLIANCE-ATOM-style / B-COMPLIANCE-ATOM-ip(合规原子) - -**责任:** 对生成产物的视觉/文本风格做合规判定(style)、对 IP 侵权/版权做检测(ip),各产出单原子 verdict(pass/review/block),供 Gate 聚合取 max。 - -**形态:** compliance 模块内的可替换 Java 实现(同进程聚合 max),或封装远程内容安全/版权模型的 Java client。**不宜标成跨进程 MCP stdio** —— StyleComplianceAtom/IpComplianceSeam 是 compliance 模块内的 Java seam,ComplianceGateApi.evaluate 又是 project.publish 同步、同进程、阻塞等 verdict 的 R1 接缝;真内容安全模型若走异步 MCP,会破坏 evaluate 的同步语义。原子实现可换是对的(B),但换的是"模块内 Java 实现 / 远程模型 client",不是把接缝改成异步 MCP。 - -**对接哪条 A:** A8 送审协议内部的合规原子接缝(ComplianceGateServiceImpl 聚合 verdict = max(各原子))。 - -**为何可插拔:** 内容安全模型/版权检测服务会迭代换供应商、可能多源,所以原子实现可插拔;原子接缝(输入 ComplianceGateReqDTO、输出单 verdict)与聚合口径(max)、落表(game_compliance_gate_result)固定在 compliance 模块内。 - -**状态:** 接 —— 接缝已在(StyleComplianceAtom/IpComplianceSeam),MVP 均为桩默认 pass;真内容安全模型 / 真 IP 侵权检测未接。 - -#### B-ASSET-mmx / B-ASSET-MARKET / B-ASSET-3RD(资产源) - -**责任:** 按生成侧请求提供六类资产并接 A9 资产协议。mmx-cli 是现行默认生成器(MiniMax 平台,生成文/图/视频/音);平台素材市场提供可被他人选用/交易的资产、带许可发放与权属转移;第三方源接入外部图库/音效库。生成侧 query_assets 按 identity/category/license/ownership/addressing 查、不感知底下是哪个源。 - -**形态:** provider 字段 + 各源的取/生成实现。mmx-cli 是 skill 形态的全局工具,后端经 provider 字段路由;market 需新建市场查询/交易/权属转移 service;3rd 是按 provider 字段路由的 adapter(可经 MCP)。 - -**对接哪条 A:** A9 资产协议——尤其 license/ownership/identity 三字段:当前 assetSpec/game_material 缺这三样,护城河"资产合规"在数据模型零兑现,market 落地必须先把 A9 这三字段补齐。 - -**为何可插拔:** 资产生成供应商可换(mmx → 其他生成器)、市场是平台护城河资产、第三方源多家且许可条款各异,所以数量与实现可插拔;统一经 provider 字段与 A9 寻址协议接入,消费侧(生成 query_assets)不变。 - -**状态:** B-ASSET-mmx = 现(assetSpec.provider 默认 mmx-cli,唯一兑现的 provider,StudioAssetContextItem.provider 已留可插拔位);B-ASSET-MARKET = 建(game_material 现为 creator 私有库、行级隔离、非可交易市场,trade 只有钱包/结算/订阅、无素材交易,ip→trade 依赖在文档但 ip 模块物理不存在,市场需新建 service);B-ASSET-3RD = 建(provider 只兑现 mmx-cli 一个值,第三方源未建)。 - -#### B-TPL-<品类>(各品类玩法模板包:generic / business-sim / narrative / puzzle / trpg / heritage) - -**责任:** 每个品类提供该品类的玩法骨架/约束/示例 prompt/校验 schema,喂进阶段 1(设计参考)与阶段 2(生成约束)引导 agent 按品类写代码。模板是品类框架引导生成,不是 pre-built 整局代码。 - -**形态:** 数据形态——prompt 模板 md + 品类校验 schema(现行)+ RAG 语料(待建)。非 skill、非 mcp,是喂给生成 agent 的品类框架数据。 - -**对接哪条 A:** A10 玩法模板协议(模板结构 + 怎么喂进阶段 1 设计/阶段 2 生成,两条线共用)。 - -**为何可插拔:** 品类会增删、每品类语料独立演进,所以数据可插拔;模板的"结构"与"注入口径"固定为 A10。现状债:三者靠 PromptResourceLoader.TEMPLATE_RESOURCES Map 硬编码绑定、无统一模板结构 schema、增删模板要改 Java 常量(运营无法配置),所以模板注册表须从编译期常量迁到 A13 配置注册表。 - -**状态:** business-sim/narrative/puzzle/trpg/heritage = 现(prompt-md 形态,核对代码确认六个 templateId 全在 SUPPORTED_TEMPLATE_IDS live 白名单,每品类配 04-config/-designer.md + templates/.schema.json)/ 建(RAG 语料零落地,模板 = 编译期常量、无 DB 表);generic = 现(STUB 占位,contracts/prompts/04-config/generic-coder.md 存在但标 STUB,generic 在白名单内,prompt 模板 md 待补实)。 - -## 4 AgentScope 机制实证 - -这一节是把"该用 skill 还是 mcp 还是 tool、能不能跨语言"这些定级判断坐实到 AgentScope 2.0.2 源码,而不是凭记忆。以下结论均已核实(源码行号为 2.0.2)。 - -**skill = 指令 + 资源包,自身不执行代码。** 一个 skill 是含 `SKILL.md` 的本地目录,SKILL.md 用 YAML frontmatter 携带 name + description(两者缺一即被跳过),正文是 markdown 指令。数据结构 `Skill` dataclass 字段 = name/description/dir/markdown/updated_at(`skill/_base.py:7-20`)。本地加载器 `LocalSkillLoader` 解析 frontmatter 并校验 name/description 必填(`skill/_local_loader.py`)。 - -注册有两条路:① 高代码直连 `Toolkit(tools=, skills_or_loaders=[...], mcps=, tool_groups=)`(`tool/_toolkit.py:88-97`);② Workspace 注册 `workspace.add_skill(skill_path)`,把目录复制进 `/skills/`、按 SHA-256 去重、维护 `.skills` 索引(`workspace/_local_workspace.py:934`),服务层 `create_app` 每次组装 toolkit 时调 `workspace.list_skills()` 灌入(`app/_service/_toolkit.py:180`)。`Workspace.add_skill` 确实存在。 - -skill 怎么被 agent 用:**它不是 tool、不能直接 call。** 两步暴露——(a)`Toolkit.get_skill_instructions()` 把每个 skill 的 name/description/dir 渲染进系统提示(模板 `DEFAULT_SKILL_INSTRUCTION`,`tool/_toolkit.py:51-63`,明文写 "Skills are NOT tools…you MUST use the `Skill` viewer tool to read the skill's full instructions"),Agent 在 `_get_system_prompt` 拼进去(`agent/_agent.py:1984-1988`);(b)内置 `SkillViewer` 工具(tool name = "Skill",`tool/_builtin/_skill.py`),agent 调它传 skill 名,它 `return ToolChunk(text=target_skill.markdown)`——把 SKILL.md 正文回灌给 agent,agent 再照其指令用真正的工具(Bash/Read/Write)去干活。 - -**这就是 §1 "契约不做成 skill" 的硬依据:** skill 的内容是注入系统提示的指令文本,agent 可读可不读、可照做可不照做,它没有任何强制力。把验收门判定纪律写成 skill,等于把它降格成提示。判定纪律必须落在 verdict schema + judge 纯代码,这才是机器门。 - -**宿主非 Python 逻辑能跑,经 shell-out。** skill 目录可放任意语言的脚本 / 二进制,SKILL.md 指示 agent 用内置 `Bash` 工具运行它;`Bash.call` 真起 shell 子进程 `asyncio.create_subprocess_shell`(`tool/_builtin/_bash.py:692`)。skill 框架本身只读 markdown(纯 Python io),不限制脚本语言。**这就是 B-PROBE 探针(node/CDP)能从 Python agent 里跑起来的依据:skill + Bash shell-out。** - -**MCP 完全语言无关。** 注册两条路与 skill 平行(直连 Toolkit / `workspace.add_mcp`,后者确实存在,`workspace/_local_workspace.py:906`)。传输两种,由 pydantic config 判别:`StdioMCPConfig`(command/args/env/cwd,起子进程经 stdio_client,stdio 强制 stateful)与 `HttpMCPConfig`(url/headers/timeout,按 url 后缀选 SSE 或 streamable-http)。`command` 可以是任何语言写的 MCP server(rust/go/c++/node 二进制都行);HTTP server 实现语言任意。MCP server 暴露的工具被包成 `MCPTool`(ToolBase 子类),经 `MCPClient.list_tools()/get_tool()` 注册成 agent 可直接 call 的工具,模型侧工具名格式 `mcp__{name}__{tool}`。**这就是 §1 "多语言走 MCP" 的依据:跨语言能力(含任意语言探针)走 MCP 暴露给 agent。** - -**tool 必须是进程内 Python(或经适配器跨进程)。纠偏一处:2.0.2 没有 `register_tool_function` 方法。** 全仓 grep 该名零命中(只在 `mcp/_mcp_client.py:372` 的 docstring 提到 `toolkit.register_tool(tool)`,但 Toolkit 上也没有该方法,疑文档滞后)。Toolkit 公开方法只有 get_tool_schemas / call_tool / get_skill_instructions / check_tool_available / get_tool / clear。工具的引入靠**构造器入参** `tools=[ToolBase]` 或 `ToolGroup`,不靠运行时 register 方法。把自定义 Python 函数变工具的适配器 = `FunctionTool(func, ...)`(`tool/_adapters.py:31-88`),它在 call 里直接 `self._func(**kwargs)`(同 / 异步皆可)——这是 1.x `register_tool_function` 的等价物。**这就是 B-FRAMEWORK-AgentScope 里"FunctionTool 薄壳"的依据:九工具的 Python 接线靠 FunctionTool,不靠传说中的 register_tool_function。** - -**机制归并:** tool = agent 能直接 call 的最细粒度执行单元(FunctionTool 进程内 Python / MCPTool 跨进程 / builtin Bash·Read·Write);skill = 注入提示的指令 + 资源包,经 SkillViewer 回灌、自身不执行;mcp = 跨进程跨语言的工具来源。映射到本设计:写法 / 脚手架 / 避坑知识 → skill;九工具的 Python 接线 → FunctionTool;探针(node/CDP)→ skill + Bash shell-out,或经 MCP;跨语言能力 → MCP。 - -## 5 现状耦合接缝与改造工作量 - -把"现在哪些地方把 LittleJS 硬编码进了本该引擎无关的接缝"列出来,顺带标出每处该提成哪条 A 协议、改造成哪类 B 模块。这是从耦合审计来的四处真接缝。 - -**装载契约 · 全局名(host ↔ 游戏工厂装载面)。** 硬编码点:`game-runtime/src/core/game-host.d.ts` + `game-studio/src/host/inject.ts` + `contracts/templates/{narrative,heritage}.schema.json` 用正则 pattern 钉死 `__GameBundle` 字面量 + prompt designer 文档。全局名 `__GameBundle` + `bootGameHost(opts)` + `GameHostFactory` + `render(g)` 的 g = 引擎 mainContext。改造:提为引擎无关的装载协议(对应 A4),全局名与 mainContext 改成协议规定的中性符号,Phaser 重写时只换装载适配器、不改契约 pattern。可插拔为:每引擎一个装载适配器(LittleJS-host-adapter / Phaser-host-adapter);contracts/templates 的 pattern 校验改为校验协议字段而非 `__GameBundle` 字面量。 - -**引擎入口 · import 落点(集成段 host 唯一引擎 import)。** 硬编码点:`game-runtime/src/host/boot-game-host.js`(`const LJS = opts.engine` + 注释钉 littlejsengine)+ `entry-bundle.template.js`(`o.engine || (await import('littlejsengine'))`)。boot-game-host 自身已经"不顶层 import 引擎、经 `opts.engine` 注入"——这是 Q4 铁律、是个真接缝——但默认值与五回调骨架仍硬编码 LittleJS(`engineInit` 五回调驱动 + `setGLEnable(false)` 纯 2D + mainCanvas#game-engine)。改造:把引擎生命周期骨架提为引擎无关的运行时形态协议(对应 A4),`opts.engine` 注入点已是正确接缝,但 `engineInit`/`setGLEnable` 这些 LittleJS 专属调用须收进适配器。可插拔为:引擎运行时适配器 `{prepareCanvas, driveFrames(update,render), getMainContext}`;LittleJS 适配器封 engineInit 五回调 + setGLEnable(false),Phaser 适配器封 Scene.create/update;`await import('littlejsengine')` 改为按 tier/引擎名解析适配器模块。 - -**九门探针 · 掌帧 / 装载标记(确定性验收门探针)。** 硬编码点:`play.cdp.cjs` + `index.template.html` + `test/harness/{gate0-engine-takeover,a6-engine-wiring}.cjs`,全是 LittleJS 专属的 `#game-engine` / `__engine.snapshot().frame` / `__gameHostEngineInitFired` / `__genBooted` / `__engineCalls`。守卫 A 装载 = `__genBooted ∧ __gameHostEngineInitFired`;守卫 C 掌帧 = `snapshot().frame` 增量;守卫 D 真渲 = `#game-engine` canvas 像素回读;守卫 F 真接线 = `__engineCalls` 含引擎 call-ID。改造:把这四类可观测量提为引擎无关的探针协议(对应 A6),运行时自报(就绪事件 / 帧计数 / 渲染面 id / 能力调用 trace),探针读协议量而非 LittleJS 私有全局。可插拔为:tool(探针)+ adapter——`play.cdp.cjs` 保持引擎无关(读 `window.__runtimeProbe.{booted,frame,canvasSelector,engineCalls}`),每引擎一个探针适配器把引擎私有量归一化到协议(LittleJS `snapshot().frame` / Phaser `scene.game.loop.frame`)。 - -**受控能力面 · 引擎能力透传(插件 ↔ 引擎 PluginContext.getEngine)。** 硬编码点:`game-runtime/src/core/api.d.ts`(EngineParticles 封 ParticleEmitter / EngineAudioSynth 封 zzfxG·zzfxM / EngineEasing 封 11 条 LittleJS Ease 曲线 / EngineMath 封 lerp·smoothStep / RandomGenerator)。api.d.ts 设计上已是"引擎可换"的受控面(注释反复钉"绝不暴露 littlejsengine 裸类型",是真接缝),但能力面的具体形状是按 LittleJS 内建能力逐项裁剪的——zzfx 参数包是 ZzFX 专属(Phaser 无对等)、easing 是 11 条 LittleJS Ease 等价曲线、EmitterSpec 字段注释直接引 littlejs.esm.js 行号。改造:把"能力清单"(粒子 / 音频合成 / 缓动 / 数学)定为协议(对应 A7 工具接口 + 引擎能力包),把每能力的归一化签名与 LittleJS 解耦(zzfx 须重新定义中性音频 / 粒子签名)。这是引擎能力包的"引擎有 → 薄包装、引擎无 → 自研补层"边界模型在受控面上的落点。 - -**工作量小结:** 四处接缝里,装载入口(boot-game-host 的 opts.engine)和受控能力面(api.d.ts)在设计上已是正确接缝、改造量小(收 LittleJS 专属调用进适配器);全局名 pattern 和探针掌帧标记是字面量级硬编码、改造量中(契约 pattern 改字段校验、探针四量改协议量)。tier2 的真实增量主要在 net-new:Phaser 探针重写(U3)、Phaser 脚手架(U4)、roles/prompt/validate/run 按 Phaser 重写(U2)。 - -## 6 纪律与边界 - -**rule-of-three:只有一套实现的接口定 v1、留演进位,别冻死。** 这是这份草案对原始清单做的最重要纠正。A6(探针抽象接口)和 A7(工具签名)现在都只有 LittleJS 一套真实现,Phaser 一行未落。此刻把抽象接口形状钉成"已固定的 A 类协议",必被唯一那套实现反向决定——B-ENG-Phaser 自己也承认"接口形状会被它反向决定,等 Pixi 落地有两实现再抽"。所以 A6/A7 标 v1 directional + 留演进位,真正冻结推迟到 Phaser(第二套实现)落地。五引擎能力包阶梯(LittleJS 真 / Phaser 建 / Pixi 桩 / Cocos future)列齐本身无害(占位),真正的过度点是把抽象接口在单实现时冻死,这点已纠。同一把尺子量第二轮平台级协议:A8-A13 凡涉及 tier2 适配的段落(tier2 零真实例、待 0 号 spike),也标 v1 directional + 留演进位——尤其 A11 的"反馈→回阶段 1 整体重设计"那一档,现状只有 tier0/1 的 deterministic / regenerate-module 两档真实现,第三档纯设计意图;别在 tier2 落地前把"两条线共用"的协议形状冻死。送审 / 通用检查这类已有 Tier0/1 真实现的,可现在就把已落地那部分固化、只留 tier2 与各渠道的适配段为演进位。 - -**确定性地板留固定层——但要把"地板的 tier2 实例"补上,别让它悬空。** 探针劈两半的裁定是对的、代码已兑现:`play.cdp.cjs` 里"读帧 / canvas / state / 注入输入"确实是 per-engine 的,判 pass/fail 不在探针里;verdict.schema.json 的 description 明文写"由裁决引擎 judge 按决策表纯代码产出(无 LLM;agent 自述一律不作证据)",机器判 + 禁自评的纪律确实落在固定 schema 层、没被 skill 化。但这条纪律目前**只对 Tier0/1 模板闭环成立**——verdict schema 死锁 `round[0,1]` + 模板 structureOk,tier2 的三层校验和富游戏三门在现有 schema 里无处落。后果是:tier2 一旦上线,要么 break `additionalProperties:false`,要么另写 schema 却没把"机器判 + 禁自评"以同等强度焊进新 schema——纪律会在 tier2 这条新线上退化成"靠 prose 约束、靠 agent 自觉",这正是治理条款 10 警告的塌陷模式。地板的**原则**留在固定层(对),但地板的 **tier2 实例**还悬空。所以"tier2 的新 verdict schema 必须把机器判 + 禁自评以同等强度焊进契约层"这条纪律,是本草案给 tier2 立的硬前置、不再问;至于结构上走"元协议 + per-tier 两层"还是"直接 fork 一份",是待创始人定的选择,见 §7 Q2。 - -**tier2 不回归 tier1 产线。** 红线两条:tier2 的源项目契约(A3)绝不复用现有 `source-project.schema.json`(那是 ECS-lite 数据壳,在产线跑着),tier2 另立独立 schema;tier2 的装载右支独立、不改 boot-game-host.js 的 opts.engine 注入边界、不碰左支即取即跑的 ECS-lite 装载契约。两条线解耦并存,共享的只有固定协议层(装载分流口径、验收判定纪律、trace 口径),不共享实现。 - -## 7 待创始人定的开放问题 - -1. **A2.5 统一 trace 契约要不要现在就立为 contracts/ 的新一类?** 它是反锁死链上最该先立、却被原始清单当成已有的一环(实测零命中)。A1/A2/A5 都在等它。建议:列为 tier2 落地前的硬前置,与 A2 显式 GenerationState v1 一并立。 - -2. **A5 verdict 是劈成"元协议 + per-tier schema"还是 tier2 直接 fork 一份独立 verdict?** 现有 verdict.schema.json 因 `round[0,1]` + `additionalProperties:false` 无法 additive 扩。倾向:fork(与 A3 一致),但元协议层(decision 三值 / severity / 机器判禁自评)要抽出来作为两份 schema 共同遵守的纪律。 - -3. **A1 的 cancel/progress 在 tier2 落地前补到什么程度?** long-running ReAct 最需要 cancel,现在是零。是先补 cancel(止血)还是 cancel + progress 一起补? - -4. **A3 是定全七要素还是先定最小 keystone?** 倾向先定 keystone(projectType + contentHash + fetchById),buildProfile/depLock/fileTree.role 随 0 号 spike 实证再补,避免 spike 前冻死要素。请创始人确认是否接受"分两步定 A3"。 - -5. **A3.5 源项目版本寻址协议单列还是并进 A3?** 长生命周期版本谱系(改源不改包 → 重建 → 新 versionId)是"游戏 = 长生命周期项目"裁定的核心兑现点,塞进 A3 一个字段不够。 - -6. **成本上报并进 A2.5 trace(trace 带 cost 段)还是单立一条成本契约?** 成本归集跨 tier、跨框架,不能只留在 AgentScope 适配器的 Middleware 里,否则与 newapi_cost 权威口径漂移。 - -7. **A6 探针抽象接口与 A7 工具签名的冻结时点:确认推迟到 Phaser 落地(第二实现)?** 这关系到 tier2 spike 阶段是否允许探针 / 工具接口形状随实证调整,不被过早冻死的 v1 绑住。 - -8. **A8 的两 verdict 口径,统一成一套还是显式定义映射?** 合规门 pass/review/block 与生成门 accept/fix/kill 是两套独立 enum;且合规门 verdict 是人工审核 decision(通过/拒绝/下架)的前置闸、两段串联。建议:协议层显式标"合规门 verdict ≠ 人工审核 decision",并定义合规 verdict ↔ 生成 verdict 的映射,而非强行合并成一套。 - -9. **A8 的申诉/下架/重审回路与 tier2 多版本送审,这一轮就并进协议还是留 tier2 落地前补?** policy/appeal 两表已建、decision 已含下架,代码有载体但协议三段直线漏了它;tier2 同一 gameId 多 versionId 各自送审的口径也未列。 - -10. **A9 的 license/ownership/identity 三字段 + 资产血缘(README 9f),是 tier2/资产市场落地前的硬前置吗?** 护城河"资产合规"在数据模型当前零兑现。建议:这四样列为资产市场(B-ASSET-MARKET)落地的前置,先补进 A9 与 game_material/assetSpec,再建市场。 - -11. **A10 模板注册表从编译期常量迁到 A13 配置注册表,这一轮立判据还是随 A13 一起?** 现增删模板要改 Java 常量、运营无法配置;且模板 schema 与 A5 verdict 的 structureOk 有跨协议耦合(改模板 schema 牵动 verdict 判定),迁移时要带上这层耦合一起考虑。 - -12. **A12 通用检查门收门时是否按"提交侧 vs 产物侧"两时相显式划?** SafetyCheckClient 是生成前 prompt 安全、体积门/scanLogic 是构建后产物校验,触发时机不同。建议:协议层显式分两段、共用一道引擎无关门外壳,避免把入队前拦截与产物校验混成一锅。 - -13. **A13 的"热改 vs GitOps"分流判据,采用"影响生成质量/安全→GitOps 四闸不可热改、运营降级开关/阈值→DB 热改"这条吗?** 当前两条路已自发形成但无固定判据,新配置项落地会随意选路。这条判据是 A13 配置注册表统一最该先定的核心。 - -14. **A4.5 的构建产物形状 + feed→play 装载入口,这一轮就提成独立 A 类协议,还是先作为 A3/A4 的字段、待 tier2 spike 后再独立?** 与 A3.5(Q5)同口径:构建缓存键 buildInputHash 已在左支 schema、feed 事实载体已在 game-package.schema.json,但 tier2 右支(esbuild 构建 + 进 feed)的形状未定,这一轮定全有 spike 前冻死风险。 +请以该 SoT 为准(它是同一"adapter 命题"的唯一设计文档);本文件原始 484 行详设见 git 历史。