diff --git a/docs/agent-specs/2026-06-21-saa-amodel-rewrite-execution.md b/docs/agent-specs/2026-06-21-saa-amodel-rewrite-execution.md new file mode 100644 index 00000000..827404ad --- /dev/null +++ b/docs/agent-specs/2026-06-21-saa-amodel-rewrite-execution.md @@ -0,0 +1,169 @@ +--- +topic: SAA 生成主线 → A-model · 执行版 v2(集成 C:复用 harness 生成内核 · shell-out 混合) +type: execution +status: draft v3(已折叠两轮 Codex+Opus 双评审 2026-06-21;待创始人收口批准 → 才进 Phase 1 实现) +date: 2026-06-21 +owner: Mac 开发执行线 +origin: + - 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**) +decisions: + - 集成 = C(复用 node harness 的 agentic 生成内核;SAA generate 节点 shell-out 到 gen.mjs SAA-mode,保留 SAA play 客观九门/player/nreview/emit/checkpoint/repair)— 创始人 2026-06-21 +review: 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-/`,SAA play/emit/giveup 硬读 `games/_wg1-gen//`(SaaGenNodes.java:476、SaaStudioNodes.java:1111/1162)→ 必挂 | BLOCKER | §2:harness 在 amgen 工作(3-up,agent 友好)后**stage 自包含产物到 `_wg1-gen//`**(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 --brief ` + harness:scaffold amgen-/(3-up,agent 友好)→ ReAct(M3,自 check/build,**--no-play 但保留同进程 cheap smoke-boot**:boot+1 帧验起来、丢九门/截图,回吐 done 门) + → **stage 自包含产物到 games/_wg1-gen//**: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//bundle.iife.js 存在 + **__GameBundle.bootGameHost 存在** + sourceArtifact 合 schema 2.0) + → (scaffold/build:amodel 路**拓扑短路**,generate 直连 asset;不留透传死壳) + → asset:从 design assetSpec 抽取(无资产走程序化兜底) + → play:**SAA 九门 A–E 客观门复用,唯一权威 play**(读 _wg1-gen//,因 harness 已 stage → 不再断裂) + → player / nreview → emit(读 _wg1-gen//bundle.iife.js → __GameBundle → GamePackage,零改) + ↑ repair[amodel]:play/validate fail → `gen.mjs --mode saa --repair --game-id --feedback ` + (**绕过 fresh scaffold**,读既有 amgen-/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-/` 生成+构建(保 3-up,agent import 与 catch-fruit 范例一致),再把**自包含 iife + SAA-index** **原子(写 tmp→rename)** stage 到 `_wg1-gen//`(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:{:},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 --brief [--repair --feedback ] [--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//{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 唯一);**`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)。 diff --git a/game-runtime/tools/amodel-gen/gen.mjs b/game-runtime/tools/amodel-gen/gen.mjs index 527f9f07..f4877fe5 100644 --- a/game-runtime/tools/amodel-gen/gen.mjs +++ b/game-runtime/tools/amodel-gen/gen.mjs @@ -14,7 +14,7 @@ 'use strict'; -import { writeFileSync, mkdirSync, cpSync, existsSync } from 'node:fs'; +import { writeFileSync, readFileSync, mkdirSync, cpSync, existsSync } from 'node:fs'; import { join } from 'node:path'; import { scaffold, scaffoldSaa, readFileTool, writeFileTool, listDirTool, check, build, buildSaa, stage, gameDir } from './tools.mjs'; import { chat, MODEL } from './m3.mjs'; @@ -26,6 +26,13 @@ function arg(name, def) { return i >= 0 ? process.argv[i + 1] : def; } +/** brief 取值:优先 --brief-file(读文件,容大段富化设计稿,避 argv 长度/引号坑;U3 Java 也用)→ 否则 --brief。 */ +function briefArg(def) { + const f = arg('brief-file'); + if (f) { try { return readFileSync(f, 'utf8'); } catch (e) { console.error('--brief-file 读失败,回退 --brief: ' + e.message); } } + return arg('brief', def); +} + const TOOL_RESULT_CAP = 30000; // 单次工具结果注入上限(够一份 skill/api.d.ts,控 context) /** 历史压缩:折叠旧的大 tool 结果 / write 内容,控 token(主流 context 工程:循环越长越要压)。占位 <400 字符 → 幂等。 */ @@ -121,7 +128,7 @@ async function main() { // design 模式:tool-using 策划 agent,只产玩家视角设计稿+gatespec(供 designNode shell-out 喂 code agent),不 scaffold/build/play。 if (mode === 'design') { const ok = await runDesign({ - brief: arg('brief', '一个简单的经营小游戏'), + brief: briefArg('一个简单的经营小游戏'), maxSteps: Number(arg('max-steps', '25')), maxWallMs: Number(arg('max-wall-ms', '600000')), }); @@ -129,7 +136,7 @@ async function main() { } const isSaa = mode === 'saa'; const id = isSaa ? arg('game-id', arg('id', 'run1')) : arg('id', 'run1'); - const brief = arg('brief', '一个简单的点击得分小游戏'); + const brief = briefArg('一个简单的点击得分小游戏'); const maxSteps = Number(arg('max-steps', '70')); // 默认 70:raw brief 7 步(3层架构 newarch1),但 SAA design 富化 brief(juice/音效/屏震/gatespec)需更多步;留余量 const maxWallMs = Number(arg('max-wall-ms', '1200000')); // 单次 attempt 墙钟上限 20min:design 富化 brief + M3 大上下文 turn 慢,raw 102s 但富化需更久;bound thrash 而不误杀富化正常 run const port = Number(arg('port', '4320'));