lili cbfd4d871b
Some checks failed
contract-gates / contract-gates (push) Has been cancelled
docs-gate / docs-gate (push) Has been cancelled
feat(acceptance): 闭合 playtest v3 与 A+ 可信消费链
固化 Match-3 生产者、视觉、音频与双 Judge 证据闭包。

将《山海行纪》r1.1 绑定新的不可变 release,并以生产预检现场核验 bundle、Registry/2 和 25 项 Writer 快照。

同步地图1平衡锁值、跨游戏回归修复、验收契约与 SoT 证据。
2026-07-28 20:16:13 -07:00

123 lines
5.6 KiB
Python
Raw Permalink 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_trace_source.py — M3b U1build_trace_source 9d-trace 源维度富化单测。
守的不变量:
· 纯函数 build_trace_source(verdict, driver_type, attempts, stage, model) 产 additive 4 键
verdictFull/driverType/models/stage供 result_out 组 payload["trace"]、后端 D11 算分;
· verdictFull 保留完整 verdictguards.H_progress 仍是嵌套对象,含 passplay 没跑 → None
· driverType 透传(没产 play-spec → Nonemodels = {code: model} map
· 不回写既有键 attempts守「不动既有键」repairs 由 result_out 据 summary.attempts 派生);
· _furthest_stage 据收口实际到达步判最远阶段。
不跑真 gen纯函数合成 verdict dict
cheap-worker/.venv/bin/python cheap-worker/tests/test_trace_source.py
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1])) # → cheap-worker/
import cheap_studio as S # noqa: E402
# 合成完整九门 verdict含 guards.H_progress 嵌套对象,对齐真 verdict.json 形态;带 url/ts 噪声供 U2 验去噪)。
_FULL_VERDICT = {
"pass": True,
"url": "http://localhost:4320/?cheap",
"ts": 1700000000,
"guards": {
"A_boot": {"pass": True},
"H_progress": {"pass": True, "checks": ["score+"], "latch": True, "state0": 0, "state1": 3},
},
}
def test_build_trace_source_success_shape():
"""成功路verdictFull 含完整 guardsH_progress 嵌套保 pass、driverType 透传、models map、stage。"""
out = S.build_trace_source(_FULL_VERDICT, "tap-targets", 1, "play", "MiniMax-M3")
assert out["verdictFull"]["pass"] is True
# H_progress 保持嵌套对象(不是裸 bool后端 ReadinessScorer.guardPass 读其 .pass
assert isinstance(out["verdictFull"]["guards"]["H_progress"], dict)
assert out["verdictFull"]["guards"]["H_progress"]["pass"] is True
assert out["driverType"] == "tap-targets"
assert out["models"] == {"code": "MiniMax-M3"}
assert out["stage"] == "play"
def test_build_trace_source_none_verdict():
"""play 没跑verdict=None→ verdictFull=NonedriverType=None不崩"""
out = S.build_trace_source(None, None, 1, "smoke", "MiniMax-M3")
assert out["verdictFull"] is None
assert out["driverType"] is None
assert out["models"] == {"code": "MiniMax-M3"}
assert out["stage"] == "smoke"
def test_build_trace_source_does_not_emit_attempts():
"""不回写既有键 attempts守「不动既有键」repairs 由 result_out 据 summary.attempts 派生)。"""
out = S.build_trace_source(_FULL_VERDICT, "tap-targets", 3, "play", "MiniMax-M3")
assert "attempts" not in out
def test_build_trace_source_non_dict_verdict_to_none():
"""verdict 非 dict异常形态→ verdictFull=None防御"""
out = S.build_trace_source("not-a-dict", None, 1, "code", "MiniMax-M3")
assert out["verdictFull"] is None
def test_furthest_stage_ordering():
"""_furthest_stage 据收口实际到达步取最远play>smoke>stage>code>scaffold。"""
assert S._furthest_stage(finished=True, staged=True, smoke_ran=True, played=True) == "play"
assert S._furthest_stage(finished=True, staged=True, smoke_ran=True, played=False) == "smoke"
assert S._furthest_stage(finished=True, staged=True, smoke_ran=False, played=False) == "stage"
assert S._furthest_stage(finished=True, staged=False, smoke_ran=False, played=False) == "code"
assert S._furthest_stage(finished=False, staged=False, smoke_ran=False, played=False) == "scaffold"
def test_closeout_gates_passes_optional_interaction_profile(monkeypatch, tmp_path):
"""完整 closeout 的 smoke 透传 profileplay 顺序和默认结果形状保持不变。"""
received = []
monkeypatch.setattr(S.cheap_run, "stage", lambda _gid: {"ok": True, "output": ""})
monkeypatch.setattr(
S.cheap_run, "smoke",
lambda _gid, **kwargs: received.append(kwargs.get("interaction_profile_id"))
or {"ok": True, "state": None, "raw": ""},
)
monkeypatch.setattr(S.cheap_run, "play", lambda _gid, **_kwargs: {"verdict": {"pass": True}})
monkeypatch.setattr(S.cheap_run, "wg1_game_dir", lambda _gid: tmp_path)
out = S._closeout_gates(
"match3-closeout", port=4320, cdp_port=9222,
interaction_profile_id="match3.orthogonal-swap-v1",
)
assert received == ["match3.orthogonal-swap-v1"]
assert out["staged"] is True and out["smoke_ok"] is True
def test_closeout_gates_default_profile_is_none(monkeypatch, tmp_path):
"""未传 profile 时显式透传 None兼容既有普通游戏 smoke。"""
received = []
monkeypatch.setattr(S.cheap_run, "stage", lambda _gid: {"ok": True, "output": ""})
monkeypatch.setattr(
S.cheap_run, "smoke",
lambda _gid, **kwargs: received.append(kwargs.get("interaction_profile_id"))
or {"ok": True, "state": None, "raw": ""},
)
monkeypatch.setattr(S.cheap_run, "play", lambda _gid, **_kwargs: {"verdict": {"pass": True}})
monkeypatch.setattr(S.cheap_run, "wg1_game_dir", lambda _gid: tmp_path)
S._closeout_gates("default-closeout", port=4320, cdp_port=9222)
assert received == [None]
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)