"""Claim loop process_one tests (REIN-A-0002-T03).""" from __future__ import annotations from unittest.mock import MagicMock, patch from rein_aharness.approaches import ApproachResult, APPROACH_FI_RESEARCH_BRIEF from rein_aharness.claim_loop import process_one, poll_peek from rein_aharness.glas_execution import GLAS_APPROACH, GlasExecutionError from rein_aharness.ops_run_client import ( ActivityCoreOpsClient, OpsRun, OpsRunConfig, OpsRunError, ) def _claimed_run() -> OpsRun: return OpsRun( id="run-1", activity_definition_id="def", idempotency_key="k", target_repo="freedom-intelligence", title="FI daily", description="d", labels=["automated", "research-brief"], state="claimed", claim_owner="worker-1", attempt=1, ) def test_process_one_empty() -> None: client = MagicMock(spec=ActivityCoreOpsClient) client.config = OpsRunConfig(worker_id="w", lease_seconds=90) client.claim.return_value = [] r = process_one(client) assert r.empty is True assert r.claimed is False def test_process_one_claim_error_requests_full_backoff() -> None: client = MagicMock(spec=ActivityCoreOpsClient) client.config = OpsRunConfig(worker_id="w", lease_seconds=90) client.claim.side_effect = OpsRunError("upstream failed") result = process_one(client) assert result.claimed is False assert result.empty is False assert result.retry_full_interval is True def test_process_one_success_completes() -> None: client = MagicMock(spec=ActivityCoreOpsClient) client.config = OpsRunConfig(worker_id="w", lease_seconds=90) client.claim.return_value = [_claimed_run()] client.complete.return_value = OpsRun( id="run-1", activity_definition_id="def", idempotency_key="k", target_repo="freedom-intelligence", title="FI daily", description="", state="succeeded", labels=["automated", "research-brief"], ) ar = ApproachResult( ok=True, approach=APPROACH_FI_RESEARCH_BRIEF, result={"path": "briefs/x.md"}, reason="ok", ) with patch("rein_aharness.claim_loop.execute_approach", return_value=ar): r = process_one(client) assert r.claimed is True assert r.ok is True assert r.approach == APPROACH_FI_RESEARCH_BRIEF client.complete.assert_called_once() client.fail.assert_not_called() def test_process_one_failure_reopens() -> None: client = MagicMock(spec=ActivityCoreOpsClient) client.config = OpsRunConfig(worker_id="w", lease_seconds=90) client.claim.return_value = [_claimed_run()] client.fail.return_value = OpsRun( id="run-1", activity_definition_id="def", idempotency_key="k", target_repo="freedom-intelligence", title="t", description="", state="open", labels=["automated", "research-brief"], ) ar = ApproachResult( ok=False, approach=APPROACH_FI_RESEARCH_BRIEF, reason="llm timeout", reopen=True, ) with patch("rein_aharness.claim_loop.execute_approach", return_value=ar): r = process_one(client) assert r.ok is False client.fail.assert_called_once() assert client.fail.call_args.kwargs["reopen"] is True def test_poll_peek() -> None: client = MagicMock(spec=ActivityCoreOpsClient) client.list_open.return_value = [_claimed_run()] rows = poll_peek(client) assert len(rows) == 1 assert rows[0]["approach"] == APPROACH_FI_RESEARCH_BRIEF def test_profiled_run_uses_glas_and_completes_with_full_result() -> None: client = MagicMock(spec=ActivityCoreOpsClient) client.config = OpsRunConfig(worker_id="w", lease_seconds=90) run = _claimed_run() run.harness_profile_ref = "harness.agent-dev-local@1.0.0" run.approach_hint = "fi-research-brief" client.claim.return_value = [run] client.complete.return_value = OpsRun( id=run.id, activity_definition_id="def", idempotency_key="k", target_repo=run.target_repo, title=run.title, description="", state="succeeded", ) gateway_result = { "ok": True, "evidence": { "outcome": "succeeded", "profile_ref": run.harness_profile_ref, "sandbox_id": "sbx-1", }, "tool_output": "not copied into ProcessResult.detail", "tool_error": None, } with ( patch("rein_aharness.claim_loop.execute_profiled_run", return_value=gateway_result), patch("rein_aharness.claim_loop.select_approach") as select, patch("rein_aharness.claim_loop.execute_approach") as execute, ): result = process_one(client) assert result.ok is True assert result.approach == GLAS_APPROACH assert result.detail == {"execution_evidence": gateway_result["evidence"]} client.complete.assert_called_once_with(run.id, result=gateway_result) client.fail.assert_not_called() select.assert_not_called() execute.assert_not_called() def test_profile_refusal_fails_terminally_without_legacy_fallback() -> None: client = MagicMock(spec=ActivityCoreOpsClient) client.config = OpsRunConfig(worker_id="w", lease_seconds=90) run = _claimed_run() run.harness_profile_ref = "harness.unknown@9.9.9" run.approach_hint = "fi-research-brief" client.claim.return_value = [run] client.fail.return_value = OpsRun( id=run.id, activity_definition_id="def", idempotency_key="k", target_repo=run.target_repo, title=run.title, description="", state="failed", ) with ( patch( "rein_aharness.claim_loop.execute_profiled_run", side_effect=GlasExecutionError("unknown harness profile"), ), patch("rein_aharness.claim_loop.select_approach") as select, patch("rein_aharness.claim_loop.execute_approach") as execute, ): result = process_one(client) assert result.ok is False assert result.ops_state == "failed" assert client.fail.call_args.kwargs["reopen"] is False select.assert_not_called() execute.assert_not_called() def test_poll_peek_reports_authoritative_profile_route() -> None: client = MagicMock(spec=ActivityCoreOpsClient) run = _claimed_run() run.harness_profile_ref = "harness.agent-dev-local@1.0.0" client.list_open.return_value = [run] with patch("rein_aharness.claim_loop.select_approach") as select: rows = poll_peek(client) assert rows[0]["approach"] == GLAS_APPROACH assert rows[0]["harness_profile_ref"] == run.harness_profile_ref select.assert_not_called()