rein-aharness/tests/test_claim_loop.py
tegwick 8200a672ea Implement REIN-A-0002 ops_run claim loop and approach registry.
Add activity-core ops_run client, approach selection (FI/Binky/mail/agent),
claim-loop worker with lease heartbeat, CLI run --from-ops-run and claim-loop,
install units, and docs demoting issue-core to legacy external tickets.
T05 timer cutover remains operator after five clean cycles.
2026-08-03 20:04:25 +02:00

97 lines
3 KiB
Python

"""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