From 099fb8106d14e0756b7dc5ae1bdd9e299c6035bc Mon Sep 17 00:00:00 2001 From: lili Date: Thu, 18 Jun 2026 01:18:33 -0700 Subject: [PATCH] =?UTF-8?q?test(wg1):=20gamedef=20=E5=BF=AB=E8=B5=B0?= =?UTF-8?q?=E6=9F=A5=E5=8A=A0=20repair=20=E5=9B=9E=E7=8E=AF=E2=80=94?= =?UTF-8?q?=E2=80=94=E8=AF=81=20repair=20=E6=8A=AC=E5=8D=87=E7=8E=87(runne?= =?UTF-8?q?r=207/9=E2=86=929/9=20=E7=9C=9F=E8=BF=87)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit plan 2026-06-18-001 U3 capstone:快走查加 repair 回环(mirror 真图:验证/真玩失败→verdict 回喂→重生成,≤2 重试), 证 ≥60% cutover 的真机制(repair)在本机可抬首攻失败到过门。 with-repair 早读(design+gamedef 全图镜像,deepseek-v4-flash): - gd-runner ✅ 9/9 真过(att=3)——首攻 7/9,repair 回喂后重生成补齐 → 满九门。**repair 回环端到端证实有效。** - gd-breakout 8/9(att=3)——H_progress(砖 remaining 未降):paddle-intercept 接球清砖精度,3 轮便宜模型 repair 未完全攻克 (R3「九门是机制地板」难类;仍真渲染/构建/玩、挡板接指针)。 - 1/2 小样硬类:与 ≥60%(全图+更大样, authoritative=mini-desktop)目标一致——runner 类过、paddle 精度类待更多 repair/更强档。 总:gamedef 路本机已证 ①端到端可玩(pong/runner 满门)②repair 回环真抬率。≥60% cutover 量化门 authoritative= mini-desktop SaaFullGraphE2eTest -Dsaa.e2e=1(全图+repair+大样)。密钥经 _client 读 .env 不入码;throwaway 已清。 Co-Authored-By: Claude Opus 4.8 --- wg1/gen-worker/gamedef_quickcheck.py | 62 ++++++++++++++++------------ 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/wg1/gen-worker/gamedef_quickcheck.py b/wg1/gen-worker/gamedef_quickcheck.py index f63fa1a2..6007c0e6 100644 --- a/wg1/gen-worker/gamedef_quickcheck.py +++ b/wg1/gen-worker/gamedef_quickcheck.py @@ -27,6 +27,7 @@ SAA_PROMPTS = (REPO_ROOT / "game-cloud/game-module-aigc/game-module-aigc-server/ GAME_RUNTIME = REPO_ROOT / "game-runtime" GEN_DIR = GAME_RUNTIME / "games" / "_wg1-gen" BRIEFS = Path(__file__).resolve().parent / "briefs" +MAX_RETRIES = 2 # repair 回环上限(mirror studio.py max_repairs 默认;总尝试=MAX_RETRIES+1) def extract_block(name): @@ -102,33 +103,39 @@ def run_one(game_id, gamedef_system, design_system, model): out["driver"] = (gs.get("driver") or {}).get("type") except Exception as e: out["err"] = "design 降级:" + str(e)[:80] # design 失败不致命,凭 brief 继续 generate - # ② generate gamedef(用 enriched=brief+设计稿) - user = "请为下面这款游戏产出一份 gameDefinition(只输出一个 JSON 对象,不要 ```代码块、不要解释):\n\n" + enriched - try: - resp = _client.chat(model, gamedef_system, user, max_tokens=16000) - except Exception as e: - out["stage"] = "generate"; out["err"] = str(e)[:200]; return out - out["tokens"] = (resp.get("prompt_tokens"), resp.get("completion_tokens")) - gd = extract_json_obj(resp["content"]) - if gd is None: - out["stage"] = "parse"; out["err"] = "未解析出 gameDefinition JSON"; return out - ok, err = assemble_via_cli(gid, gd) - if not ok: - out["stage"] = "validate/assemble"; out["err"] = err[:400]; return out - # 复用 run.py 的 scaffold 余下(拷模板 + play-spec)+ build + play(factory 已由 CLI 写好)。 + # ② generate→assemble→build→play **repair 回环**(mirror 真图:失败→verdict/错误回喂→重生成,≤max_retries 次)。 + # 这是 ≥60% cutover 门的真机制(单发首攻 ≠ 终率);design 只跑一次,repair 只重 generate。 gdir = GEN_DIR / gid - shutil.copyfile(GEN_DIR / "_shared" / "entry-bundle.template.js", gdir / "entry-bundle.js") - shutil.copyfile(GEN_DIR / "_shared" / "index.template.html", gdir / "index.html") - (gdir / "play-spec.json").write_text(json.dumps(play_spec, ensure_ascii=False, indent=2), encoding="utf-8") - bok, blog = run.build(gid) - if not bok: - out["stage"] = "build"; out["err"] = blog[:400]; return out - rc, _, verdict = run.play(gid) - out["stage"] = "play" - out["guards"] = {k: g.get("pass") for k, g in ((verdict or {}).get("guards") or {}).items()} - out["pass"] = bool(rc == 0 and verdict and verdict.get("pass")) - if not out["pass"]: - out["err"] = run._verdict_feedback(verdict)[:300] + feedback = None + for attempt in range(MAX_RETRIES + 1): + out["attempts"] = attempt + 1 + user = "请为下面这款游戏产出一份 gameDefinition(只输出一个 JSON 对象,不要 ```代码块、不要解释):\n\n" + enriched + if feedback: + user += "\n\n———\n上一次生成【未通过】,原因如下,请针对性修正后重新产出完整 gameDefinition JSON:\n" + feedback + try: + resp = _client.chat(model, gamedef_system, user, max_tokens=16000) + except Exception as e: + out["stage"] = "generate"; feedback = "模型调用失败:" + str(e)[:160]; continue + gd = extract_json_obj(resp["content"]) + if gd is None: + out["stage"] = "parse"; feedback = "未能解析出 gameDefinition JSON。请只输出一个 JSON 对象(顶层 entities/components/behaviors/scenes/rules)。"; continue + ok, err = assemble_via_cli(gid, gd) + if not ok: + out["stage"] = "validate/assemble"; feedback = "校验/装配未过:\n" + err[:500]; continue + shutil.copyfile(GEN_DIR / "_shared" / "entry-bundle.template.js", gdir / "entry-bundle.js") + shutil.copyfile(GEN_DIR / "_shared" / "index.template.html", gdir / "index.html") + (gdir / "play-spec.json").write_text(json.dumps(play_spec, ensure_ascii=False, indent=2), encoding="utf-8") + bok, blog = run.build(gid) + if not bok: + out["stage"] = "build"; feedback = "打包失败(esbuild):\n" + blog[:500]; continue + rc, _, verdict = run.play(gid) + out["stage"] = "play" + out["guards"] = {k: g.get("pass") for k, g in ((verdict or {}).get("guards") or {}).items()} + if rc == 0 and verdict and verdict.get("pass"): + out["pass"] = True + break + feedback = run._verdict_feedback(verdict) + out["err"] = feedback[:300] return out @@ -146,7 +153,8 @@ def main(): gpass = sum(1 for v in r["guards"].values() if v) gtot = len(r["guards"]) drv = r.get("driver") or "-" - print(f" {r['game_id']:14s} {mark:16s} drv={drv:16s} gates={gpass}/{gtot} {('' if r['pass'] else r['err'][:110])}") + att = r.get("attempts", 1) + print(f" {r['game_id']:14s} {mark:16s} drv={drv:14s} att={att} gates={gpass}/{gtot} {('' if r['pass'] else r['err'][:100])}") npass = sum(1 for r in results if r["pass"]) print(f"\n[gamedef-qc] 过门 {npass}/{len(results)} (cutover 门基线=iife 60%; 本为 lili-mac 小样早读, authoritative=mini-desktop)") Path(__file__).resolve().parent.joinpath("results", "gamedef-quickcheck.json").write_text(