from datetime import UTC, datetime from unittest.mock import MagicMock, patch from sandboxer.models import Reachability, SandboxState, SandboxStatus from glas_harness.contract import ( ExecutionRequest, ExecutionSummary, Rein, SandboxHandle, ToolCall, ToolResult, ) from glas_harness.gateway import run_execution, run_task_through_rein PROFILE = "harness.agent-dev-local@1.0.0" class _FakeRein(Rein): def __init__(self) -> None: self.calls: list[str] = [] def start_session(self, profile, inputs, sandbox: SandboxHandle): self.calls.append("start_session") assert str(profile.ref) == PROFILE assert sandbox.sandbox_id == "sbx1" assert sandbox.reachability.get("workspace_dir") == "/tmp/ws" assert "target_repo" not in inputs return {"session": "s1"} def dispatch_tool(self, session, tool_call: ToolCall) -> ToolResult: self.calls.append("dispatch_tool") assert tool_call.name == "run_task" return ToolResult( ok=True, output="sensitive direct output", events=[{"type": "tool_use"}], events_completeness="complete", tokens_spent=123, resolved_model="claude-sonnet-4-6", ) def end_session(self, session): self.calls.append("end_session") return ExecutionSummary( committed=True, commit_sha="deadbeef", outcome="succeeded", tokens_spent=123, resolved_model="claude-sonnet-4-6", ) def cleanup_session(self, session): self.calls.append("cleanup_session") def _fake_status(sandbox_id: str = "sbx1") -> SandboxStatus: now = datetime.now(UTC) return SandboxStatus( sandbox_id=sandbox_id, profile_id="profile.bwrap-local", extension_id="ext.bwrap", state=SandboxState.READY, consumer={"actor": "agt", "project": "glas-harness"}, host="localhost", reachability=Reachability(host="localhost", pid="123", workspace_dir="/tmp/ws"), created_at=now, updated_at=now, ) def _request(*, profile: str = PROFILE, report_to_hub: bool = False) -> ExecutionRequest: return ExecutionRequest( harness_profile_ref=profile, repo="/tmp/repo", title="t", description="d", request_id="req-1", correlation_id="corr-1", assignment_ref="assignment:42", report_to_hub=report_to_hub, ) def test_run_execution_creates_and_destroys_sandbox() -> None: manager = MagicMock() manager.create.return_value = _fake_status() rein = _FakeRein() result = run_execution(_request(), rein=rein, manager=manager) assert rein.calls == [ "start_session", "dispatch_tool", "end_session", "cleanup_session", ] manager.create.assert_called_once() manager.destroy.assert_called_once_with("sbx1") assert result.ok is True assert result.evidence.profile_ref == PROFILE assert result.evidence.rein_id == "rein-aharness" assert result.evidence.commit_sha == "deadbeef" assert result.evidence.tokens_spent == 123 assert result.evidence.refs["assignment_ref"] == "assignment:42" assert result.tool_output == "sensitive direct output" def test_run_execution_normalizes_execution_failure_and_tears_down() -> None: manager = MagicMock() manager.create.return_value = _fake_status() class _FailingRein(_FakeRein): def dispatch_tool(self, session, tool_call): raise RuntimeError("boom") rein = _FailingRein() result = run_execution(_request(), rein=rein, manager=manager) assert result.ok is False assert result.evidence.outcome == "failed" assert result.evidence.failure_stage == "execution" assert result.evidence.error == "execution failed; inspect direct caller error" assert result.tool_error == "boom" assert rein.calls == ["start_session", "cleanup_session"] manager.destroy.assert_called_once_with("sbx1") def test_run_execution_refuses_unknown_profile_before_sandbox() -> None: manager = MagicMock() result = run_execution(_request(profile="harness.unknown@1.0.0"), manager=manager) assert result.ok is False assert result.evidence.outcome == "refused" assert result.evidence.failure_stage == "resolution" assert "unknown harness profile" in (result.evidence.error or "") manager.create.assert_not_called() def test_hub_receives_normalized_evidence_without_raw_output() -> None: manager = MagicMock() manager.create.return_value = _fake_status() with patch("glas_harness.gateway.hub.post_progress_event", return_value=True) as post: result = run_execution(_request(report_to_hub=True), rein=_FakeRein(), manager=manager) post.assert_called_once() detail = post.call_args.kwargs["detail"] assert detail["outcome"] == "succeeded" assert detail["profile_ref"] == PROFILE assert "tool_output" not in detail assert "sensitive direct output" not in str(detail) assert result.tool_output == "sensitive direct output" def test_hub_failure_detail_excludes_raw_provider_error() -> None: manager = MagicMock() manager.create.return_value = _fake_status() class _FailingRein(_FakeRein): def dispatch_tool(self, session, tool_call): raise RuntimeError("provider body containing sensitive material") with patch("glas_harness.gateway.hub.post_progress_event", return_value=True) as post: result = run_execution( _request(report_to_hub=True), rein=_FailingRein(), manager=manager ) detail = post.call_args.kwargs["detail"] assert detail["error"] == "execution failed; inspect direct caller error" assert "sensitive material" not in str(detail) assert "sensitive material" in (result.tool_error or "") def test_wrapper_requires_and_reports_harness_profile() -> None: manager = MagicMock() manager.create.return_value = _fake_status() result = run_task_through_rein( harness_profile=PROFILE, repo="/tmp/repo", title="t", description="d", rein=_FakeRein(), manager=manager, report_to_hub=False, ) assert result["ok"] is True assert result["evidence"]["profile_ref"] == PROFILE def test_teardown_failure_is_visible_in_evidence() -> None: manager = MagicMock() manager.create.return_value = _fake_status() manager.destroy.side_effect = RuntimeError("cannot teardown") result = run_execution(_request(), rein=_FakeRein(), manager=manager) assert result.ok is False assert result.evidence.failure_stage == "teardown" assert result.evidence.error == "teardown failed; inspect direct caller error" assert result.tool_error == "cannot teardown"