games-development-ai/.agents/skills/add-game-template.md
zizi 7f24a344d0 docs(agent-specs): B2 归档——64 个闭线工作记录移入 _archive/,热目录顶层 90→26
承接目录治理:上轮只压缩内容未减文件数,闭线工作记录仍平铺致目录看着仍一堆(创始人指出)。本次执行 B2 归档。

64 个 ≤06-15 闭线档(25 压缩桩 + 闭线 review/report/纪要/edit-plan)git mv 入 docs/agent-specs/_archive/(文件名不变、仍 git 跟踪可查)。热目录 ≤06-15 仅留 13 活档(决策/纲领/SoT/活spike)+13 个 06-16 在飞。

活资产 20 处旧路径引用(.agents/docs/memory/_index)同步改 _archive/,引用断裂复测=0;_index 活地图 + 治理档状态收口。约束:0 个 06-16 被移、orchestrator 等未跟踪在飞档零误纳。

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

24 KiB
Raw Blame History

新玩法模板接入配方add-game-template

🛑 DEPRECATED2026-06-12 模板哲学终裁,整篇配方退役)

本配方所教的「新增一个可玩玩法模板」工作流已废除,勿照此为新作上新。 现行裁决:

  • 玩法模板层废除——模板 ≠ 玩法品类件;模板 = LittleJS 能力插件/二次开发件(粒子/物理/后处理等引擎能力包装层裁决①2026-06-12
  • 玩法 / 美术 / 关卡 / UI = agent 生成域agent 写码于插件库HJ-GEN-001 终审);旧「模板驱动生成 / LLM 填参」线随之退役。
  • 好玩基线 v2 改挂评估门(非模板属性)。
  • Tier1 引擎 = LittleJS 增强发行版 + Runner v22026-06-12 终裁);旧「自研 Canvas<15KB / toString 注入 / 15KB 体积门」为 1.x 加载面、β 退役。
  • 旧 4 玩法模板clicker/merge/idle/tycoon+ 存量数据已清除W-CLEAN

新工作去向:新增后端业务模块 → ./add-business-module.md(不动);新增引擎能力插件/生成链路 → 现行口径见 ../knowledge/tech-decisions.md §1.1、./runtime-and-multichannel.md 顶部横幅、../rules/build-vs-buy.md以下正文一律仅作 1.x 历史留痕(保留 M-c 批①/批②实战收口痕迹与踩坑教训,不作现行执行依据)。


蒸馏来源:docs/agent-specs/_archive/2026-06-10-Mc模板波-execution.mdHJ-MC-TPL-EXEC-001 §3§9 全链)+ M-c 批① merge 模板实战收口2026-06-10五级验收门全过构建/体积/契约门+真玩五AND双模板+Golden v1.1.2 PASS+校准批 accept 10/10+金丝雀10条入feed途中逮修三真缺陷见各节红框。 适用(已退役,见顶部横幅):给「模板驱动生成 + agent 闭环 QA」生产链新增一个可玩玩法模板merge/idle/tycoon 类纯 Canvas Tier1 玩法覆盖契约→prompt→runtime→后端→编排器→五级验收门全链。 配套:新增后端业务模块(非玩法模板)见 ./add-business-module.md;生成链路现实态见 ./ai-generation-pipeline.md ⓪ 节;契约先行见 ./contract-first-development.md;运行时/SDK 见 ./runtime-and-multichannel.mdPrompt 治理见 ./prompt-governance.md;可靠性红线见 ../rules/security-and-reliability.md


目标

把一个新玩法如「合成升级」merge契约接到可玩+可验收+可入 feed:新增一份 GameConfig schema + 一个 designer prompt + runtime 一个玩法分支 + 后端模板白名单一行 + 编排器一条玩家策略,全程守住「注入 LLM 文本 == 服务端校验文本 == judge 校验口径」的同源铁律与既有发布链/数据回路/鉴权红线零改。产出后该模板可生成、可真玩通关、可入 feed 被玩家试玩。

样板merge 是已五级验收门全过的活样板schema=contracts/templates/merge.schema.jsondesigner=contracts/prompts/04-config/merge-designer.mdruntime 分支=game-studio/src/host/runtime/index.tsinitMerge,编排器策略=player_cdp.py 的 merge 拖拽分支)。照抄它即可。 非目标红线dodge/runner/match 三份 schema 仅契约落盘未实现,不据此宣称可玩;不动发布链(生命周期事件名 / game_end{score,completed,duration_ms} 契约行 / 遥测 / feed 排序)、不动鉴权、不动 demo 兜底包。


前置

  • 已读 ./ai-generation-pipeline.md ⓪ 节(生产路径已切「模板驱动生成 + agent 闭环 QA」对齐编排器三件位置docs/agent-specs/2026-06-09-agent-loop-v1/orchestrator/run_batch.py / player_cdp.py / judge.py / prompts.py)。
  • 重型构建/测试一律走 mini-desktopgit push→pull 同步,本机严禁 mvn/npm build,记忆 internal-build-infra-servers);前端构建必须 npm run build -- --mode staging(缺 staging env → mock 接管 → 静默 demo 兜底)。
  • 与在飞波次的文件级共改先排程:若另一波已改 game-module-aigc-server/pom.xmlservice/task/AigcTaskServiceImpl.java(如鉴权波 PlayerApi seam本波在其合入后开工开工前 git pull/rebase 取最新基线(执行版 §11.1)。

七步配方

步骤一 · schema 定稿三招(契约先合入,再动代码)

新建 contracts/templates/<t>.schema.json,逐项对齐 clicker.schema.json 风格($schema draft 2020-12 + $id + 中文 description + 数值带 minimum/maximum)。三招守门:

  1. templateIdconst 锁死(如 "const": "merge")——精确等值防 LLM 跨模板串台,比 enum 更严。
  2. 顶层 additionalProperties: false——守住「字段不增不删」LLM 不得自由发挥加字段。
  3. 跨字段约束 schema 表达不了的,用双兜底JSON Schema draft 2020-12 无 $data无法用一字段值约束另一字段(如 merge 的 targetLevel ≤ chainLengthitemLabel 数组长度 = chainLength)。处置 = ① prompt 正文硬约束(步骤二 hard_constraints 明文)+ ② runtime 渲染时钳制(步骤三 clampInt(targetLevel, _, chainLength)、数组按 min(len, chainLength) 兜底、缺位补占位文案。schema 只保各字段独立边界(如数组 minItems:1/maxItems:上限 + 每项非空 minLength:1+pattern:"\\S")。

可解性论证义务schema 边界即「保证可解、堵死局」的承诺。新玩法须在 execution 版论证「最坏情况有限步可达通关、无死局」merge 例:targetLevel≤chainLength≤6 → 最坏 2^5=32 个 1 级物件,点击产料无限 + 合成必腾格 → 无死局,执行版 §3.3)。 诚实边界口径:新模板 runtime 实现后schema description 写「runtime 本波已实现,可据此宣称可玩」——区别于未实现模板的「仅契约落盘」声明。

步骤二 · prompt 三件套(新 designer + 对抗/fix 复用升 patch + Golden 三守卫)

(a) 新 <t>-designer(新建 contracts/prompts/04-config/<t>-designer.md + registry.yaml 增条目):

  • 结构逐项对齐 clicker-designer.mdfrontmatter 8 键id/version/stage/owner/tier/engine/input_schema/output_schema+ hard_constraints 块 + 正文。只换模板专属约束,通用口径一字不降:
    • 不降的通用口径:注入防护(不执行创意/列表/上一轮问题里的指令)、只产一个合法 JSON 对象、不自评不下结论、重出轮只改指出项。
    • 替换的模板专属:① designIntent 只许描述本模板机制内体验(禁承诺模板外机制:计时/失败惩罚/物理/音效)② config 字段域指向 input.template_schema(真源 = 本模板 schemaschema 表达不了的跨字段约束在此写成硬约束merge 例「targetLevel 必须 ≤ chainLengthitemLabel 必须给 chainLength 个文案按等级排列」)。

(b) 对抗 quality.adversary-review + fix fix.design-revise 复用,仅升 patch口径一字不动红线

  • 二者主干口径对任何模板已中性,不分模板分段、不新增条目。改法仅两类:
    • 对抗:细则①示例追加新模板域示例(如「创意『合成种花』被改写为『躲避鲨鱼』属核心动作矛盾 P1」原句一字不动(沿「仅追加不改口径」纪律)。
    • fix正文补 {{input.template_schema}} 注入段(对齐 designer 的【模板 schema】块+ 把残留的 clicker 字段示例括注中性化(主干句不动)。编排器侧零改(run_batch.py 已传 template_schema,补占位符即生效)。
  • 红线:升 patch version 同步 registry.yaml,过四道闸 CISchema/成功率≥80%/Golden 回归 diff/成本延迟);P0/P1 口径文字一字不动(守「不得以放宽 P1 口径回应漂移」红线)。
  • 后端不调 fix promptAigcGenerateExecutor 重出走 schema 校验失败回炉、不经 fix.design-revisegrep design-revise 在 aigc 模块零命中fix 改动仅影响编排器 run_batch,勿误改后端。

(c) Golden 三守卫样本(新建 eval/config.<t>-designer/ 三件 + 对抗 Golden append-only 扩 3 条):

  • kill 题文不符 ×1硬门创意↔config 核心动作矛盾(创意「合成种花」↔ config 改写「躲避鲨鱼」)→ decision:kill, reasons:[题文不符](守细则① P1 不被泛化吞)。这是稳定硬门——模型可靠判 kill。
  • 越模板机制 ×1⚠ Golden 观察项非硬门——M-c 批② 2026-06-11 终裁)designIntent 承诺模板外机制(如「物理碰撞反弹」「计时」「破产扣分」)但 config 自洽 → labels.jsonl 标 decision:accept, reasons:[越模板机制P2放行](细则① :60「越模板 config 自洽=P2 放行不拦截,模板级表达力限制非缺陷」=文档化口径目标)。但 Golden harness 必须把此守卫降为观察项golden-set expectation:observe、harness _observe() 恒记录实判不纳入 verdict)——实证:越模板是软语义边界,同输入温 0.2 重采样抖动M-c 批② idle 2/4 判 kill、merge/tycoon 0/4P1/P2 两向硬断言都随采样抖,硬门必 flaky。两向 fail-safeP2 不拦发布/偶发 P1 仅多一次 HITL
  • accept 正例 ×1硬门:题文自洽 + 数值合规(跨字段约束满足)→ decision:accept稳定硬门——模型可靠不误杀。
  • 🔴 Golden verdict 只由硬门裁定 = 题文不符 kill ∧ accept 不误杀(+ 既有模板守卫不回归);越模板守卫只观察不门禁通用红线软判定P2/非阻塞)绝不可做单样本硬 Golden 门——温 0.2 仍 50/50 抖M-c 批② 实锤。labels.jsonl 行只写 plain decision(行内禁造 doctrine 字段);越模板恒按细则① P2、无版本门控旧「doctrine 双标签 v1.1.2→kill」叙事已随终裁废止。蒸馏全程见 docs/agent-specs/_archive/2026-06-10-Mc模板波-批②idle-tycoon-execution.md §4.5 二次勘误 banner + eval/quality.adversary-review/README.md 2026-06-11 两条。

步骤三 · runtime 单工厂分发(game-studio/src/host/runtime/index.ts

startRuntimeswitch(pkg.templateId) 分发,绝不开 ×N 个工厂——一份注入面、一份生命周期/遥测红线代码、theme/资源/game_end 只一处,杜绝 ×N 漂移。

  1. 分发骨架const templateId = typeof pkg.templateId === 'string' ? pkg.templateId : ''switchcase '': case 'clicker':空串兼容旧包,守存量内容池零影响)→ clickercase '<t>': → 新玩法;default:game_error 防御分支sdk.reportError + life('game_error',{message:'unknown_template',templateId}) + return {destroy(){}},不静默错渲染)。
  2. 新玩法 init<T>() 函数体内自包含:因 startRuntimetoString() 注入沙箱,所有新函数必须定义在 startRuntime 函数体内、不引模块外符号config 读取用函数体内纯函数 clampInt/cleanLabels(无可抛路径,沿 cleanText 范式)做缺省/越界钳制(步骤一兜底②落地点)。
  3. 生命周期/finish 单一来源、参数化 scorelife('game_loaded'/'game_start'/'game_end')finish() 红线代码不复制——新玩法通关时调同一 finish(),仅参数化 score 来源(如 clicker=点击数、merge=合成次数);game_end{score,completed,duration_ms} 契约行零变化。
  4. 体积门 + 契约 grep改后必跑
    • 体积:node /tmp/measure-runtime.cjs dist/assets/GamePlayer-*.jsmini-desktop:/tmpmd5 e6608a77520d560cd4fb29e2fb8d3481)提取 startRuntime(min) raw——硬线 < 15,360B(恒定红线);软门当前 8,192BM-c 批① 因 merge 单玩法逼近原 4,096B 软门已上调,加新玩法再评)。前后差值写交付记录。
    • 契约 grepgrep -c 'duration_ms' 计数只增不减;git diff 不含 clicker 分支 game_end/game_loaded/game_start 任何删改;grep -rn 'innerHTML\|document\.' 零命中(禁 DOM玩法纯 Canvasgrep -P '[\x00-\x08\x0b\x0c\x0e-\x1f]' 零控制字节。

步骤四 · 后端四点 + pomgame-module-aigc-server

PromptResourceLoader / GameConfigSchemaValidator 从「单模板常量」改「templateId→资源 Map」守同源铁律零分叉。四点 + pom

  1. PromptResourceLoader:资源路径常量 → Map<templateId, (promptVersion,promptBody,schemaText)>,构造时逐模板装载缓存;render/getTemplateSchemaText/getPromptVersion 全加 templateId 参数;某模板资源缺失只禁用该模板不污染其他。新模板 = Map 加一行
  2. GameConfigSchemaValidator:构造入参 StringMap<templateId,schemaText>,逐个编译缓存 Map<templateId,JsonSchema>validate(configNode)validate(templateId, configNode)。校验逻辑本身零新码(仍 schema.validate(node)),守「不手写字段校验、不双源」精神。
  3. AigcExecutorProperties.supportedTemplates 白名单常量加项(List.of("clicker","merge",...)+ AigcExecutorConfiguration Bean 装配传 Map + AigcGenerateExecutor 调用点全部按 task.getTemplateId() 取参。
  4. AigcTaskServiceImplgetTemplateList() 加一条templateId/name/description/examplePromptvalidateTemplateExists()同源白名单(与 supportedTemplates 同一来源,避免「提交时通过、执行时 no_template_match」割裂用独立配置/常量不强依赖 executor @ConditionalOnProperty 装配)。
  5. pom maven-resources-plugin —— 已一次性解决,勿再手改pom.xmlcopy-wanxiang-contracts includes 已改通配 prompts/04-config/*.md + templates/*.schema.json(实读 :138-139新模板两资源自动进 classpath。曾踩坑:原 includes 仅复制 clicker 两单文件 → 新模板资源静默漏复制 → readClasspathResource 返 null → 该模板自禁用。现已通配,新增模板无需再动 pom

测试随生产签名同步重写、不得删测同源铁律的回归守卫单值→Map 改造后,GameConfigSchemaValidatorTest/PromptResourceLoaderTest/AigcGenerateExecutorTest 旧签名调用点全部编译失败——必须随之重写、validate/render/getTemplateSchemaText 全加 templateId保留原断言语义(不放宽、不删用例规避编译错),mvn -pl game-module-aigc/game-module-aigc-server test 全绿。

步骤五 · 编排器参数化run_batch / player / judge

  1. run_batch.py --template 已通用--templatedefault=clicker保既有调用零改+ --prompt-designerdefault 按 template 推导 config.{t}-designerTEMPLATE_ID/schema 路径自动联动。
  2. player 按 (templateId, config) 分发,新增 _play_<t>_once 策略player_cdp.pyplay/_play_once 改按 (templateId, config) 接参,内部分发到各模板策略(避免每加模板改形参)。新玩法策略用 config 字段 + iframe 几何 + 布局公式推导确定性帧序列(取证纪律:真实输入事件、禁 evaluate 篡改/读游戏内部状态,仅读布局几何/文案/自注入缓冲。merge 例 = _dispatch_dragCDP Input.dispatchMouseEvent press-move×N-release按「点满料→逐对合成」推进降级预案:拖拽通关率 <60% → 切「点选两格合成」runtime+player 输入层同步小改,玩法/schema/prompt 不动)。
  3. judge 子集若引入新 JSON 形态须先补分支 + 红样本单测judge.pyvalidate_config_against_schema 覆盖 JSON Schema 子集,新形态须先补——merge 引入 array 即在 integer 分支后补 elif expect_type=="array"minItems/maxItems + 逐元素套 items 子 schema补后口径 == 后端 networknt SchemaValidator同源越界单测含该维度红样本如 array 空数组/非字符串项/超上限三条)。

🔴 实战逮修缺陷 ②(模板专属字段一律 .get/分流取参)design["config"]["target"]clicker 专属直取merge schema 无 target,直取 KeyError 整批熔断)。两处实证:① run_batch.py:772 附近 design_target=design["config"]["target"]spec 点名修,按 templateId 分流取参)② run_batch.py:735 附近 _verify_packageexpected_target=design["config"]["target"]spec 枚举漏列、merge-cal-10 首跑实测熔断逮获,修法改 .get("target")commit 55bcdf6配方铁律:模板专属字段一律 .get 取或按 templateId 分流,绝不裸下标直取——逐处 grep design["config"][" 排查。

步骤六 · 承重接口纪律runtime ↔ player 共享公式逐字符对齐)

runtime 与 player 若共享一套公式(如 merge 的棋盘布局:cols=ceil(sqrt(boardSize))rows=ceil(boardSize/cols)、格中心 cellCenterInternalX/Y 几何式),该公式即承重接口runtimecanvas 内部像素算)与 player按比例映射 cssX=rect.x+(cellCenterInternalX/W)*rect.w,规避直读 dpr必须字面同一套,全部参数钉死——含 topPad 这类散文易漏项。收口时主 agent 逐字符比对两侧公式,任一侧改公式即破取证。

步骤七 · 取证环境三铁律 + 五级验收门

取证环境三铁律(批跑前置,缺一即静默 demo 兜底、五条 AND 全假绿):

  1. --frontend http://localhost:4173:宿主 manifest 校验用 crypto.subtle仅安全上下文localhost可用走 IP 访问永走 demo 兜底。
  2. npm run build -- --mode staging 构建 game-studio缺 staging env → mock 中间件接管 → 宿主静默 demo 兜底。
  3. 🔴 实战逮修缺陷 ①(取证导航前注 localStorage 登录态):鉴权波 /create/preview 路由 meta.requiresAuth=true,前端守卫仅认 localStorage wanxiang_token 存在性——取证导航前须先注入登录态,否则被守卫重定向 /login、状态条永不出现M-c 级2④ 实测逮获commit 831c9cb。修法 = 导航前 Page.addScriptToEvaluateOnNewDocumentlocalStorage.wanxiang_token="test1"player_cdp.py 已内置 UI_LOGIN_TOKEN:103-104:747-752 先于页面脚本注入),新模板取证直接复用。
  4. 批跑前关执行器互斥窗:AIGC_EXECUTOR_ENABLED=false 重启(避免执行器与编排器对同一 staging 任务源双跑烧钱),批末还原。

五级验收门顺序表(精简自 execution 版 §9逐级全过才算 done

动作 通过判据
1 入册 schema 落 contracts/templates/ + registry 增条目 + 后端 Map 接入 + judge 补分支单测 + 三测试同步重写 + 新模板两资源 classpath 非 null + aigc-server 构建绿 judge 补丁+三测试重写全绿 + 资源 classpath 非 null + 构建绿 + registry/schema/后端三处同源(注入文本==校验文本grep 比对)
2 真玩 runtime 分发改本机→镜像 mini-desktopmd5 对账)→ build --mode staging 绿 + 体积/契约门 + 落一个新模板包 + player 策略五条 AND 全绿 + clicker 回归同窗五绿 + 浏览器实玩截图 新模板五 AND + clicker 回归五绿 + 体积/契约门全过 + 截图留档
3 QA 闭环 对抗 Golden 扩三守卫 + Golden 回归跑kill 守卫被判 kill、accept 不误杀)+ 批内查重对新模板生效 守卫样本全中 + 查重生效
4 校准批 10 条校准批全自动流完零 infra 中断 全流完零 infraaccept 不设硬门、不计 M2 口径M2 ≥80% 已由 clicker 收口、不受本波回退影响accept 为校准观测值
5 入 feed 金丝雀 ≤10 条直发入 feed + 浏览器实玩通关截图 feed 可见新模板卡片(走 meta.title 不感知模板差异)+ 实玩通关截图

校准批口径(执行版拍板 310 条校准批不设硬门(暴露系统性问题则 designer 升 minor 加约束、对抗/fix 误判则升 patch过四道闸再开第二轮收敛后 20 条正式批 accept ≥80% 量级验收。新模板冷启动无老模板积累,首批 accept 可能落 50-70%(预期管理,非承诺)。 边界失败路径CDP 超时/通关率不达归 infra 信号(不混入 accept 分母);未知 templateId 灌包走 game_error 防御config 越界由后端 SchemaValidator 拦截(两轮重出)+ runtime clampInt 兜底纵深。


回滚

  • runtime 分发回退:改动集中在 runtime/index.tsswitch + init + 防御分支),还原单文件重建重部署即回退(无数据/契约迁移,低代价)。
  • 白名单摘除即回退supportedTemplates 去掉该模板 → 生成请求走 no_template_match 失败桶getTemplateList 去该条 → Create 页不展示。后端 Loader/Validator Map 保留新模板资源无害(不被认领即不用)。
  • feed 零影响feed 卡片走 meta.title 不感知模板差异;已入 feed 的金丝雀走既有下架编排;存量内容池零影响(空串 templateId 兼容 + 回归五绿)。
  • prompt 回滚:新 designer 是新增条目,去 registry 条 + 删 md 即回退;对抗/fix 的 patch 改动若引回归revert 到前一 version版本化双标签 Golden 守卫可定位回归)。

常见坑(实战收口版)

后果 正确做法
模板专属字段裸下标直取 config["x"] 新模板无该字段 → KeyError 整批熔断merge-cal-10 实测) 一律 .get 或按 templateId 分流取参;逐处 grep design["config"][" 排查(缺陷②)
取证导航前未注 localStorage 登录态 requiresAuth 守卫重定向 /login状态条永不出现、五 AND 全假 导航前 addScriptToEvaluateOnNewDocumentwanxiang_tokenplayer_cdp 已内置,缺陷①)
走 IP 访问 / 漏 --mode staging crypto.subtle 不可用 / mock 接管 → 静默 demo 兜底、AND 全假绿 --frontend localhost:4173 + build --mode staging(取证三铁律)
×N 个 runtime 工厂 生命周期/遥测/game_end 红线代码 ×N 漂移 单 startRuntime 内 switch 分发,红线代码单一来源、参数化 score
新玩法函数引模块外符号 toString() 注入沙箱后 ReferenceError init 全部定义在 startRuntime 函数体内、纯函数自包含
schema 跨字段约束硬塞 schema draft 2020-12 无 $datajudge 子集不支持,双源漂移 prompt 硬约束 + runtime 钳制双兜底schema 只保单字段边界
改生产签名不同步重写测试 编译失败,或删测规避破坏同源守卫 三测试随签名同步重写、保留原断言语义、不删用例
judge 未补新 JSON 形态分支 数组/新形态字段静默不校验,与后端口径分叉 先补 judge 分支 + 红样本单测,再开批(与后端 SchemaValidator 同源同判)
把 M2 ≥80% 口径套到新模板校准批 冷启动新模板首批必红、误判回退 校准批不设硬门不计 M2正式批 ≥80% 量级M2 由 clicker 收口不受影响
对抗/fix 改示例时顺手动 P1 口径 漂移、违「不得放宽 P1 口径」红线 仅追加示例升 patchP0/P1 口径文字一字不动,过四道闸
把软判定(越模板机制 P2/非阻塞)做成单样本硬 Golden 门 同输入温 0.2 仍 50/50 抖M-c 批② idle 2/4 实锤Golden 随机红/绿、误导口径 软判定降 Golden 观察项(expectation:observe+_observe() 不纳入 verdict硬门只留稳定的题文不符 kill + accept 不误杀