games-development-ai/cheap-worker/tests/test_studio_smoke.py
lili 675a8e688b feat(cheap-worker): 便宜档 Node→Python 重写进 AgentScope spike — 范式可移植坐实
WU-A 迁移面 spike:便宜档生成核心(多轮 ReAct + 五工具沙箱 + done 门)用 Python 在新建 cheap-worker/
重写成 AgentScope agent,import 复用 tier2 框架层(model client/四道熔断/历史压缩/observability),
check/build/九门 shell-out 现有 node/cjs(不重写 esbuild/CDP/形状门)。

- U1 地基:跨包 sys.path import tier2 worker + 代理旁路 + key 从内网文档注入 env + M3 装配
- U2 五工具:read/list/write Python 实现 + check/build shell-out(形状门三态与 Node 一致)
- U3 LittleJS system prompt:prompt.mjs Python 化(两条 footgun 正反例 + 输入契约)
- U4 scaffold/stage/play 薄壳 + ensure_play_spec(据 state 形态产 play-spec 治链路假绿)
- U5 ReAct 主编排:内置 Agent+ReActConfig+外层有界 resume + done 门 + 收口 stage/smoke/九门
- U6 对照 Node:产物形态 + 九门逐门 + 过门率对比

验收:同 brief Python 新路 vs Node 旧路,产物都真 src/ 6 文件、九门都 9/9 全 PASS、过门率 1.0=1.0
→ spikePass=True。端到端单局 attempt 1 一次收敛、148s。落点 cheap-worker/ 对 tier2/amodel-gen
零改动(结构性零回归)。测试 38/38 全绿。

origin: docs/plans/2026-06-26-001-feat-cheap-worker-python-spike-plan.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 02:42:14 -07:00

74 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
test_studio_smoke.py — U5 端到端产物契约验证。
端到端真跑由 cheap_studio CLI 提供(落 evidence/run-summary.json + staged 工程 + 九门 verdict);
本 test 验证最近一次 run 的产物契约(真 src/ 多文件 + staged + 九门 verdict + run-summary 字段)。
真跑回归(~2.5min,真 M3 ReAct):
cheap-worker/.venv/bin/python cheap-worker/cheap_studio.py --id cheap-smoke1 --brief "一个简单的点击得分小游戏:屏幕上随机冒出可点的圆,点中加分"
然后:cheap-worker/.venv/bin/python cheap-worker/tests/test_studio_smoke.py
"""
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1])) # → cheap-worker/
import cheap_run
GID = "cheap-smoke1"
def _require_run() -> dict:
p = cheap_run.game_dir(GID) / "evidence" / "run-summary.json"
if not p.exists():
raise AssertionError(
f"先跑端到端单局:cheap-worker/.venv/bin/python cheap-worker/cheap_studio.py --id {GID} --brief ...(缺 {p})")
return json.loads(p.read_text(encoding="utf-8"))
def test_run_summary_contract():
"""run-summary 含 finished/check/build/staged 字段且收敛。"""
s = _require_run()
assert s["finished"] is True, s
assert s["check"]["ok"] and s["build"]["ok"], s
assert s["staged"] is True, s
def test_real_src_multifile():
"""产真 src/ 多文件工程(非单文件 / JSON blob / new Function blob)——doc↔code 兑现门的便宜档侧。"""
src = cheap_run.game_dir(GID) / "src"
assert (src / "game-logic.js").exists(), "缺 src/game-logic.js"
js = list(src.glob("*.js"))
assert len(js) >= 2, f"应为真 src/ 多文件工程,实际 {len(js)} 个 .js"
def test_staged_artifact_exists():
"""stage 后 _wg1-gen/<id>/ 有自包含 bundle + index + 自动产的 play-spec。"""
dst = cheap_run.wg1_game_dir(GID)
assert (dst / "bundle.iife.js").exists()
assert (dst / "index.html").exists()
assert (dst / "play-spec.json").exists(), "play-spec 缺失 → 九门会 driven=false 假绿"
def test_nine_gates_verdict():
"""九门 verdict.json 存在且含逐门 guards(不假绿)。"""
v = cheap_run.wg1_game_dir(GID) / "evidence" / "verdict.json"
assert v.exists(), "缺九门 verdict.json"
d = json.loads(v.read_text(encoding="utf-8"))
assert isinstance(d.get("guards"), dict), "verdict 应含九门 guards"
if __name__ == "__main__":
_fns = [v for k, v in sorted(globals().items()) if k.startswith("test_") and callable(v)]
_failed = 0
for _fn in _fns:
try:
_fn()
print(f" PASS {_fn.__name__}")
except Exception as e: # noqa: BLE001
_failed += 1
print(f" FAIL {_fn.__name__}: {type(e).__name__}: {e}")
print(f"\n{len(_fns) - _failed}/{len(_fns)} passed")
sys.exit(1 if _failed else 0)