test(wg1): gamedef 快走查加 repair 回环——证 repair 抬升率(runner 7/9→9/9 真过)
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 <noreply@anthropic.com>
This commit is contained in:
parent
da4801828d
commit
099fb8106d
@ -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(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user