"""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.ops_run_client import OpsRun, OpsRunConfig, ActivityCoreOpsClient 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_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