"""Unit tests for SpectateSession (agent-driven, stepwise, rich disclosure).""" from __future__ import annotations import pytest import proteus.game.scenarios # noqa: F401 from proteus.game.agents.vanilla import VanillaAgent from proteus.game.engine.difficulty import Difficulty from proteus.providers.fake import FakeProvider from proteus.game.runtime._session_core import SessionFinishedError from proteus.game.runtime.spectate import SpectateSession def _agent(n=10): return VanillaAgent(FakeProvider(responses=["ACTION: stay"] * n, model_name="demo")) def _new(play_turns=5): return SpectateSession( "template", agent=_agent(), model_name="fake:demo", difficulty=Difficulty.EASY, seed=42, play_turns=play_turns, use_probe=False, ) def test_initial_state_is_cut_intro_int_grid(): s = _new() st = s.state() assert st["phase"] == "cut_intro" assert st["turn_idx"] == 0 assert isinstance(st["grid"][0][0], int) assert st["turns_so_far"] == [] def test_advance_runs_one_llm_turn_with_rich_disclosure(): s = _new() st = s.advance() assert st["turn_idx"] == 1 last = st["turns_so_far"][-1] # rich: optimal/habit/reward/reasoning ARE exposed live (spectator, not scored). for k in ("action", "motive_action", "habit_action", "reward", "is_diagnostic", "was_congruent", "reasoning"): assert k in last def test_advance_to_budget_then_done_and_finish(): s = _new(play_turns=2) while s.state()["outcome"] is None: s.advance() st = s.state() assert st["phase"] == "done" and st["outcome"] in ("survived", "eliminated") trace = s.finish() assert trace.model == "fake:demo" and trace.scenario == "template" def test_advance_after_done_raises(): s = _new(play_turns=1) s.advance() with pytest.raises(SessionFinishedError): s.advance()