"""A reusable adapter must keep each sandbox's result in its own session.""" import json from unittest.mock import MagicMock import pytest from glas_harness.contract import ToolCall from glas_harness.reins.rein_aharness import ReinAharness from glas_harness.reins.rein_openweights import ReinOpenWeights from glas_harness.transport import ExecutionTransport @pytest.mark.parametrize("adapter", [ReinAharness, ReinOpenWeights]) def test_interleaved_sessions_keep_their_own_outcomes_and_usage(adapter): rein = adapter() sessions = [] for index, ok in enumerate([True, False]): transport = MagicMock(spec=ExecutionTransport) transport.resolve_executable.return_value = "/runtime/rein" transport.git_head.return_value = f"head-{index}" transport.run.return_value = MagicMock(returncode=0 if ok else 1, stderr="", stdout=json.dumps({"ok": ok, "tokens_spent": 10 + index, "model": f"model-{index}", "reason": None if ok else "failed"})) sessions.append({"transport": transport, "task_file": f"/workspace-{index}/task", "timeout_seconds": 30, "head_before": "baseline"}) # Finish A only after B has reported its different result. for session in sessions: rein.dispatch_tool(session, ToolCall(name="run_task")) first, second = [rein.end_session(session) for session in sessions] assert first.outcome == "succeeded" assert first.tokens_spent == 10 assert first.resolved_model == "model-0" assert second.outcome == "failed" assert second.tokens_spent == 11 assert second.resolved_model == "model-1"