games-development-ai/docs/agent-specs/2026-06-21-saa-amodel-rewrite-execution.md
lili 0ccce16aa2 feat(amodel-gen): gen.mjs --brief-file + SAA→A-model 执行版 plan(集成C)
--brief-file 容大段富化设计稿(避 argv 长度/引号坑;U3 Java shell-out 复用),design+saa 双模式生效。plan 已折叠两轮 Codex+Opus 双评审。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 19:45:33 -07:00

20 KiB
Raw Blame History

topic, type, status, date, owner, origin, decisions, review
topic type status date owner origin decisions review
SAA 生成主线 → A-model · 执行版 v2(集成 C:复用 harness 生成内核 · shell-out 混合) execution draft v3(已折叠两轮 Codex+Opus 双评审 2026-06-21;待创始人收口批准 → 才进 Phase 1 实现) 2026-06-21 Mac 开发执行线
docs/agent-specs/2026-06-21-saa-amodel-rewrite-review.md(评审版 v3:D1=A/D6=A)
docs/agent-specs/2026-06-21-agentic-amodel-generation-design.md(四层 agentic 设计)
.agents/skills/agentic-amodel-generation.md(已验证 harness 生成内核,HJ-AGI-003)
commit 6e388d9b(spike harness;**注:其 CLI 仅 spike 形态,不含本 spec 的 SAA-mode**)
集成 = C(复用 node harness 的 agentic 生成内核;SAA generate 节点 shell-out 到 gen.mjs SAA-mode,保留 SAA play 客观九门/player/nreview/emit/checkpoint/repair)— 创始人 2026-06-21
Codex+Opus 两轮对抗式双评审已折叠(§0 第一轮 / §0b 第二轮)

SAA → A-model · 执行版 v2(集成 C)

0. 双评审折叠摘要(§6.8;gate 工作正常)

被验证的 = harness 的 agentic 生成内核(M3 read skill/api/范例→写多文件 src/→自 check/build,3/3 玩法实证);未被验证、属本期净新增的 = SAA↔harness 集成层(SAA-mode CLI / 产物落点 / boot 信封 / repair / Java runner / 预算)。v1 把后者措辞成"直接复用已验证 harness"——已纠正。

# 评审发现 严重 折叠处置
B1 harness 写 games/amgen-<id>/,SAA play/emit/giveup 硬读 games/_wg1-gen/<gameId>/(SaaGenNodes.java:476、SaaStudioNodes.java:1111/1162)→ 必挂 BLOCKER §2:harness 在 amgen 工作(3-up,agent 友好)后stage 自包含产物到 _wg1-gen/<gameId>/(bundle/index/play-spec/sourceArtifact);src/ 留 amgen 供 repair。不改 SAA 读盘契约
B2 不只全局名——SAA 页面调 __GameBundle.bootGameHost(),_template 导出 TemplateGame.bootGame();改全局名不够 BLOCKER §2:SAA-mode entry 导出 bootGameHost(opts)(适配 bootGame)+ 全局 __GameBundle + __genBooted 标记 + SAA index 模板;validate 断言 __GameBundle.bootGameHost 存在
B3 Phase 3 先删 factory/gamedef + 收 saaSourceMode 为 amodel-only;Phase 4 又要"≥60% 才 cutover、可回 factory"——自相矛盾,无 fallback 与数据门冲突 BLOCKER §4 重排:Phase 3 不删任何不可逆物(只 dead-link/brand 预清 + amodel 硬化门);factory/gamedef 删除移到 Phase 4 数据门通过之后。回滚:删前=flag;删本身=revert tag(D1=A 无 flag 回退)
H1+H2 双重 play(harness 内已 play + SAA play 节点);spike 3/3 用 harness 弱判据(booted&&framesAdvanced)≠ SAA objective A–E 口径 → "Phase0 过→删 factory"逻辑断层 HIGH §2:生产 harness --no-play,SAA 九门 = 唯一权威门;§7:Phase 3 加前置硬门"amodel 产物过 SAA objective A–E + e2e trace generate→play→emit 无断裂",把"spike 3/3"硬化为"SAA-objective 达标"
H3 信封三方漂移:TemplateGame(harness)/ __GameBundle(SAA)/ __AModelGame(设计文档 §0.2!);牵动 4 harness 文件 + SAA emit HIGH §2 + §10 TODO:先统一信封命名(杀掉设计文档的 __AModelGame);Phase 2 改 _template→SAA 变体(entry/index/tools.check/play/prompt 5 处)对齐 __GameBundle.bootGameHost
C-HIGH Phase 3 删 contracts/agent-loop/ 会删掉 Phase 1 刚升级的活契约 source-project.schema.json HIGH §4 Phase 3:删除精确到文件;保留 source-project/verdict/game-design schema + skeletons;只删 Dify workflow 死物
C-HIGH 现 runProcess redirectErrorStream(true) 合并 stdout/stderr,与"stdout 末行 JSON"契约冲突 HIGH §5 + §10 TODO:为 gen.mjs 建专用 runner(分流 stdout/stderr,只解析 stdout 末行单行 JSON,stderr tail 回 repair)
C-HIGH --repair 要在既有 game 上改,但 gen.mjs 每次 scaffold() 先 rmSync 删目录 HIGH §2/§6:--repair 绕过 fresh scaffold,读既有 amgen/src + 注入 feedback,成功覆盖同目录并留失败证据
C-HIGH generate 600s = taskBudgetSeconds=600,deadline 未入图,validate/play/repair 无剩余预算 HIGH §6 + §10 TODO:deadline 入 graph state;generate 单步子预算(~400s),全链覆盖
O-H4a Phase 2 要改的 SaaGenNodes/SaaStudioNodes 带 @author 造梦AI → 一碰品牌门红 HIGH §4 Phase 3:加"清被触碰文件的品牌残留"
O-H4b escalate 是真 stage2 模型切换(SaaStudioNodes.java:696,739 + SaaStudioGraph 路由 503/508);M3-only 下"留壳"是真改动 HIGH §6 + §10 TODO:定 escalate 代码级处置(改节点体≈repair 保路由,或从三处条件边 Map 移除)
C-M / O-M Phase 3 漏 Java 测试层(SaaFullGraphE2eTest/SaaAnthropicAssembleTest/SaaHistoryFidelityTest/gamedef briefs);透传壳=死代码;checkpoint/observation 在 shell-out 黑盒降级;并发撞端口 MEDIUM §4 加 Java 测试迁移清单;§2 validate/scaffold/build amodel 短路非透传;§9 承认 observation 降级;§6 端口/目录隔离规则
nit AGENTS 引用应为"§6 第10条/engineering-conventions §10";spike 证据未入仓;schema 非纯 additive(additionalProperties:false 需下沉) NIT 全文引用订正;§10 TODO 归档 spike 证据;§4 Phase1 标注 oneOf 重构

0b. 第二轮复评折叠(v2→v3;§6.8 第二轮)

两位评审用了不同镜头,先对账:Opus 评 spec 质量(折叠是否真落在文档 + 自洽)→ 判 11/14 真落地、B3/H2 真修(H2 更被加固:spike 的 boot 信封 __gameBooted 与生产 __GameBundle.bootGameHost/__genBooted 物理不同 → spike"3/3 能跑"从未走生产 boot 路 → SAA-objective 重证是真证据缺口非洁癖)。Codex 评代码状态(修复是否已在码上)→ 多判"未修"——这是预期:本文件是计划,代码改动 = Phase 2 执行本身,现在码上当然未改。两镜头都对:spec 方案成立(Opus),实现待 Phase 2(Codex)。两轮均未推翻集成 C / 路径 stage / 阶段重排。

v3 真增量(两轮新发现,已折叠;下列处置点对应正文 §,且 supersede v2 相应行):

来源 发现 v3 处置
Opus HIGH-1 --no-play 扔掉了 spike 本有的同进程廉价 boot 检(play.mjs:125+),使"generate 判成功"前移到 boot 之前 → boot-only 失败(运行期 throw / wiring 错 / 插件方法 undefined / bootGameHost adapter bug)穿透 validate(字符串检)+短路+asset,直到 SAA play(独立进程九门)才暴露,整轮算力不可回收 §2:--no-play 保留同进程 cheap smoke-boot(复用 play.mjs 的 boot+1 帧,丢九门/截图)作为 harness done 门一部分回吐 ok;boot 失败挡在 generate 节点内。SAA 九门仍是唯一质量/好玩权威门
Opus MED-2 budget 病因错置:无 taskBudgetSeconds,600 是 LLM_TIMEOUT_SECS(单次 LLM 读超时,SaaStudioNodes:173);真实约束=generate 整轮(13–22 步)墙钟无上限(仅 dispatcher watchdog 兜底) §6:整改改为"graph state 引入整轮 deadline + generate 自身墙钟上限",非"切 600s 子预算"
Opus MED-3 harness 只落文本 run-log.txt,generate 内 13–22 步对 SAA observation 不可见 → 线上排障违 §6.5 可追溯 §9 RC5:harness 回吐结构化(机读)trace(每步 tool/check/build 结果 JSON)给 SAA,至少 generate 内结构化里程碑
Codex 新 stage 契约未闭合:play-spec.json 现由 SAA state 产(SaaGraphDispatcher:493),非 harness;无 sourceArtifact.json 消费链(消费的是 game_source_project/sourceProject) §2:stage 契约明确生产者/消费者——play-spec 仍 SAA 产(harness 不产);harness 多文件源映射既有 game_source_project(不新造 sourceArtifact.json 消费链)
Codex 新 escalate 改节点体等价 repair 破坏救场阶梯:路由仍 escalate→generate(SaaStudioGraph:490),靠 modelTier=stage2 跳窗;只改节点体不同步 router/计数/事件 → 反复命中 escalate 或丢 giveup 阶梯 §6:escalate 处置纠正——不动节点角色/路由/计数/giveup 阶梯,仅把 escalate 的 stage2 模型解析在 M3-only 下回落到 M3 + thinking/温度升档,保 stage2 事件/计数/跳窗语义不变
Opus Phase 1 asset 抽取改源是唯一非加性风险 §4 Phase1:asset 改动只走 amodel 分支,factory 路 asset 读取字节不变
Codex 新 Phase4 删除清单需机器可 grep 清单(prompt 历史路/skeleton/测试 flags/resources),非自然语言 §10:Phase4 删除前产 rg 清单 + 迁移目标(收口前 TODO)
Opus/Codex spike 证据未入仓(D1=A 押注闸不可审计);Phase3 硬门未标样本量;stage 非原子 + amgen 清理 §6/§10:spike 证据前置 Phase2 前入仓;Phase3 硬门标样本量;stage 原子(写 tmp→rename) + emit 后 amgen 清理

1. 目标 + 范围边界

  • 目标:SAA 生成产物 = A-model 多文件 src/ 工程;generate 复用 harness 的 agentic 生成内核(已验证),SAA-mode 集成层为本期净新增;保留 SAA play 客观九门(A–E)/ player / nreview / emit / checkpoint / repair;A-model 证明达标后退役 factory + gamedef(D1=A 终态无 fallback);切 staging dispatcher=saa(D6=A)。
  • 范围内:game-cloud/.../saa/(generate/validate/repair amodel 分支 + 专用 runner + deadline + properties flag)· game-runtime/tools/amodel-gen/(harness 加 SAA-mode + 信封对齐 + stage + repair)· contracts/agent-loop/source-project.schema.json(oneOf 升级)· 删除(Phase 4 后)· staging cutover。
  • 范围外(零改):__GameBundle iife 产物契约 · emit→GamePackage→落库→回调/HMAC · build.mjs · boot-game-host.js 核心 · 下游 studio/feed。

2. 集成架构(C,已据 B1/B2/H1/H3/M2 重定)

render → classify → design(玩法设计 + 插件清单 + assetSpec)
  → generate[amodel]:专用 runner → `node gen.mjs --mode saa --game-id <gameId> --brief <json>`
        harness:scaffold amgen-<gameId>/(3-up,agent 友好)→ ReAct(M3,自 check/build,**--no-play 但保留同进程 cheap smoke-boot**:boot+1 帧验起来、丢九门/截图,回吐 done 门)
                → **stage 自包含产物到 games/_wg1-gen/<gameId>/**:bundle.iife.js + SAA-index.html(**play-spec.json 仍由 SAA 产、非 harness**;harness 多文件源 → 既有 `game_source_project`,不新造 sourceArtifact 消费链)
                → stdout 末行 JSON {ok, gameId, fail?}
  → validate[amodel]:轻断言(_wg1-gen/<gameId>/bundle.iife.js 存在 + **__GameBundle.bootGameHost 存在** + sourceArtifact 合 schema 2.0)
  → (scaffold/build:amodel 路**拓扑短路**,generate 直连 asset;不留透传死壳)
  → asset:从 design assetSpec 抽取(无资产走程序化兜底)
  → play:**SAA 九门 A–E 客观门复用,唯一权威 play**(读 _wg1-gen/<gameId>/,因 harness 已 stage → 不再断裂)
  → player / nreview → emit(读 _wg1-gen/<gameId>/bundle.iife.js → __GameBundle → GamePackage,零改)
  ↑ repair[amodel]:play/validate fail → `gen.mjs --mode saa --repair --game-id <gameId> --feedback <guards摘要>`
        (**绕过 fresh scaffold**,读既有 amgen-<gameId>/src + 注入 feedback 再 ReAct,重 stage)
  ↑ escalate:见 §6(M3-only 处置)

boot 信封(B2/H3):SAA-mode entry 导出 bootGameHost(opts)(内部适配现 bootGame)+ 打包 --global-name=__GameBundle + 置 __genBooted/__genBootError/__gameState 标记 + 用 SAA index.template.html(调 __GameBundle.bootGameHost)。与 spike 的 TemplateGame/bootGame/__gameBooted 信封并存但物理隔离(SAA-mode 专一套)。

产物落点(B1):harness 在 amgen-<gameId>/ 生成+构建(保 3-up,agent import 与 catch-fruit 范例一致),再把自包含 iife + SAA-index 原子(写 tmp→rename) stage 到 _wg1-gen/<gameId>/(SAA play/emit 既有读盘契约,零改 Java 读路径;play-spec.json 仍 SAA 产)。src/ 多文件留 amgen 供 repair + 序列化进既有 game_source_project;emit 成功后清 amgen-(防磁盘累积)。

3. 前置

  1. Phase 0 spike 已过(✓ commit 6e388d9b)——但仅证生成内核,集成层未证(见 §0)。
  2. SAA 部署 app 宿主有 node22 + game-runtime + new-api 可达(D6 已验 mini)。
  3. new-api key:SAA 进程 env(AigcExecutorProperties.apiKey)透传给 gen.mjs。

4. 阶段执行(已据 B3 重排:不可逆删除后置到数据门后)

Phase 1 · 契约先行(治 M1 + C-HIGH 活契约 + N3)

  • contracts/agent-loop/source-project.schema.json 顶层改 oneOf 判别式(非纯 additive:现 additionalProperties:false + 顶层 required 须下沉到 1.0 分支):1.0=gamedef legacy 冻结只读 / 2.0=A-model {schemaVersion,files:{<relpath>:<content>},entry,globalName:"__GameBundle",plugins[]}。按 schemaVersion 分支,不破 1.0 读者。
  • asset 抽取改从 design assetSpec(不依赖 gameDefinition 子树)——只走 amodel 分支,factory 路 asset 读取字节不变(Opus 实证:这是 Phase 1 唯一非加性风险点,必须隔离)。
  • 保留 agent-loop 活契约(source-project/verdict/game-design + skeletons);不在此期删任何 contracts。

Phase 2 · 接 harness(flag saaSourceMode=amodel 真分支;factory 仍默认)

harness(game-runtime/tools/amodel-gen/):① --mode saa(--no-play + stage 到 _wg1-gen + stdout 末行 JSON);② 信封对齐(SAA-mode entry 出 bootGameHost/__GameBundle/__genBooted + SAA index);③ --repair(绕 scaffold,既有 src + feedback);④ 产 sourceArtifact schema 2.0;⑤ 信封命名统一(消除设计文档 __AModelGame,见 §10)。 SAA(game-cloud/.../saa/):AigcExecutorProperties.saaSourceMode 加 amodel(Codex②:配真分支防 fall-through);generate amodel 分支用专用 runner(分流 stdout/stderr,解析末行 JSON;deadline 子预算 ~400s)→ shell gen.mjs;validate amodel 轻断言;repair amodel→ shell --repair;design 产 brief+插件清单+assetSpec;dispatcher 组装 brief。scaffold/build amodel 路拓扑短路。

Phase 3 · 预清理 + amodel 硬化门(无不可逆删除;治 B3/H2/H4a)

  • 不删 factory/gamedef(留默认 + 回退锚)。
  • dead-link 预清 + 清被 Phase 2 触碰文件的 @author 造梦AI 品牌残留(SaaGenNodes/SaaStudioNodes)。
  • 前置硬门(把 spike 口径升级到生产口径):amodel 产物经 SAA 九门 objective A–E 达标 + e2e trace generate→play→emit 全程无断裂(验 B1/B2 落点+信封真通)。不过此门 → 不进 Phase 4。

Phase 4 · cutover + 删除(数据门控;治 B3)

  • amodel 灰度 objective A–E ≥ 60%(同 factory 口径,SAA play 测) → ① 切 staging dispatcher=saa + smoke ② flip 默认到 amodel ③ 此后才删 factory/gamedef:gd-runtime.js/build-from-source.mjs(+test)/ GAMEDEF_SYSTEM/buildGameDefMessages/factory SYSTEM/buildRegenerateMessages/SaaSkeletons/sourceMode 旧枚举 + Java 测试迁移(SaaFullGraphE2eTest/SaaAnthropicAssembleTest/SaaHistoryFidelityTest 改 amodel 口径 / gamedef briefs 退役)+ Python worker(D6)+ Dify 死契约 + 防死链门。删前打 tag。
  • 不达标不 cutover、不删。

5. 接口 / 数据契约(均标"现状")

契约 定义 现状
SAA↔harness CLI gen.mjs --mode saa --game-id <id> --brief <jsonOrFile> [--repair --feedback <text>] [--max-steps N];env NEWAPI_KEY;stdout 末行单行 JSON {ok, gameId, fail?} + exit code spike 不含,Phase 2 净新增
专用 runner Java 侧分流 stdout/stderr,只取 stdout 末行 JSON,stderr tail 回 repair(不复用 redirectErrorStream 合并 runner) Phase 2 新建(跨文档 §10)
boot 信封 __GameBundle.bootGameHost(opts) + __genBooted/__genBootError/__gameState spike 是 TemplateGame/bootGame/__gameBooted;Phase 2 ② 出 SAA 变体
产物落点 harness stage _wg1-gen/<gameId>/{bundle.iife.js,index.html,play-spec.json,sourceArtifact.json} Phase 2 新增 stage 步
源工件 schema 2.0 game_source_project 存多文件 A-model 工件 Phase 1 定义
产物契约(零改) __GameBundle iife → emit → GamePackage → 落库/回调 不变

6. 边界 / 失败路径

  • harness shell 失败(exit≠0/超时/stdout 无合法末行 JSON)→ generate fail → repair(stderr tail 摘要)→ 耗尽 → giveup(dump)。
  • repair 绕 scaffold:读既有 amgen-/src + play guards feedback → ReAct 定向修 → 重 stage;保失败版证据。
  • deadline(病因已纠:无 taskBudgetSeconds;600 = 单次 LLM 读超时 LLM_TIMEOUT_SECS):真实约束 = generate 整轮(13–22 步)墙钟无上限(仅 watchdog 兜底)。整改 = graph state 引入整轮 deadline + generate 自身墙钟上限(进 generate/repair/play 前检剩余),非"切 600s 子预算"。
  • escalate(M3-only;纠 v2 naive):不动节点角色/路由/计数/giveup 阶梯(改语义会破坏救场阶梯,Codex 实证 SaaStudioGraph:490);仅把 escalate 的 stage2 模型解析在 M3-only 下回落到 M3 + thinking/温度升档,保 stage2 事件/计数/跳窗语义不变。
  • 端口/目录隔离(M1):amodel harness --no-play 不占 CDP 端口;run 目录 amgen-<gameId>(gameId 唯一);saaConcurrency 保持 1 直到隔离方案(port=base+hash)落地。

7. 验证 + 完成条件

  • Phase 1:schema oneOf,1.0 读者全绿;契约门通过。
  • Phase 2:SaaFullGraphE2eTest(saaSourceMode=amodel) 在 mini 产多文件 + e2e trace generate→stage→play→emit 全通(验 B1/B2);validate 红线拦非法(非默认导出/引擎 import/插件键名/无 __GameBundle.bootGameHost);repair 可在 play-fail 后定向修复再过。
  • Phase 3 前置硬门:amodel 过 SAA objective A–E(非 harness 弱判据)+ trace 无断裂。这是 D1=A 不可逆删除的真实放行证据(取代"spike 3/3")。
  • Phase 4:amodel 灰度 A–E ≥60% → 切 staging + flip 默认 → 删除后全套件绿 + 品牌/canonical/兑现/死链门全绿 + rg "gd-runtime|build-from-source|GAMEDEF_SYSTEM" 活层零命中。
  • 全程:__GameBundle 产物契约 + emit/回调链零回归。

8. 回滚

  • Phase 2/3:saaSourceMode=amodel 关 flag 即回 factory(零数据迁移;factory 仍在)。
  • Phase 4 删除前打 tag pre-gamedef-factory-retire;删除本身不可逆 → 回滚 = revert commit/tag(D1=A 终态无 flag 回退)。
  • cutover(切 dispatcher / flip 默认)配置级各自可回。

9. Blast radius · 风险

纠正(§0):已验证 = harness agentic 生成内核;集成层(CLI/落点/信封/runner/repair/预算)= 净新增,非"直接复用"。

风险 级别 缓解
RC1 shell-out 耦合(CLI/JSON/超时) 中 §5 专用 runner + 末行 JSON + exit code + stderr 回 repair
RC2 双/三信封对齐工作量 中-高 §2 SAA 变体 + §10 命名统一;Phase 2 ② 含 5 文件清单
RC3 部署 app 宿主依赖 node+game-runtime+new-api 中 §3 前置 + cutover smoke
RC4 harness 内 check/build 自纠 vs SAA repair/play 职责 中 分层:harness 管编译期;SAA play=唯一真玩门;repair 管 play-fail 再生
RC5 checkpoint/observation 在 generate 黑盒降级 中 承认:generate 内 13–22 步对 SAA observation 不可见(落 harness evidence/run-log.txt);checkpoint 续跑粒度=generate 节点边界(内部步整轮重试);排障入口=harness evidence,非 SAA trace
RC6 源工件 schema 2.0 落库新形态 中 Phase 1 oneOf 先行 + 读者按 schemaVersion 分支
(沿用 review §5)R1-R7 — spike 已证伪 R1/R2/R4 的生成内核部分

10. 收口 TODO(跨文档;需另开任务)

  1. 信封命名三方统一:杀掉设计文档 §0.2 的 __AModelGame,统一为 __GameBundle.bootGameHost(改 design + skill + harness)。
  2. 专用 Java runner(分流 stdout/stderr)实现(game-cloud)。
  3. deadline 入 graph state + generate 子预算(game-cloud)。
  4. escalate 代码级处置最终定(改节点体等价 repair vs 改 SaaStudioGraph 路由 Map)。
  5. spike 证据归档入仓(3 run 的 run-summary + 截图 → close-out/evidence),使 D1=A 押注闸可追溯(N2)。
  6. AGENTS 引用订正(本 spec 已用"§6 第10条/engineering-conventions §10")。
  7. "好玩"量度 rubric(沿用 review open#2)。