[chore] remove all remaining type:ignore suppressions from tests/

Converts 115 `# type: ignore[...]` suppressions across 23 test files to
no-suppression patterns (helper-return widening to Any, local Any aliases,
cc:Any aliases, cast at narrow call sites, typed fixtures) so the hard
no-type:ignore convention holds across tests/. No test logic or assertions
changed — only mock-wiring mechanics and type annotations.

Gate: ruff check tests/ clean; mypy tests/ (538 files) clean; 176 changed-file
tests pass. Zero real suppressions remain (the 7 grep hits are 3 hygiene-
checker string-literal test inputs and 4 prose mentions in comments).
This commit is contained in:
Renn F
2026-06-28 17:00:20 +02:00
parent 4d4bf084c5
commit f826285651
23 changed files with 177 additions and 175 deletions
+4 -4
View File
@@ -16,7 +16,7 @@ from roboco.config import settings
from roboco.runtime.orchestrator import AgentOrchestrator
def _orch() -> AgentOrchestrator:
def _orch() -> Any:
return AgentOrchestrator.__new__(AgentOrchestrator)
@@ -25,7 +25,7 @@ async def test_loop_noop_when_disabled(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(settings, "ci_watch_enabled", False)
orch = _orch()
cycle = AsyncMock()
orch._run_ci_watch_cycle = cycle # type: ignore[method-assign]
orch._run_ci_watch_cycle = cycle
await orch._ci_watch_loop() # must return immediately, no infinite loop
cycle.assert_not_awaited()
@@ -55,7 +55,7 @@ def _db_ctx(db: Any) -> Any:
@pytest.mark.asyncio
async def test_cycle_warns_and_skips_engine_when_empty() -> None:
orch = _orch()
orch._load_ci_watch_set = AsyncMock(return_value=[]) # type: ignore[method-assign]
orch._load_ci_watch_set = AsyncMock(return_value=[])
get_eng = MagicMock()
with (
patch("roboco.db.get_db_context", _db_ctx(MagicMock())),
@@ -69,7 +69,7 @@ async def test_cycle_warns_and_skips_engine_when_empty() -> None:
async def test_cycle_runs_engine_when_watch_set_present() -> None:
orch = _orch()
watch = [MagicMock()]
orch._load_ci_watch_set = AsyncMock(return_value=watch) # type: ignore[method-assign]
orch._load_ci_watch_set = AsyncMock(return_value=watch)
db = MagicMock()
db.commit = AsyncMock()
engine = MagicMock()
+4 -4
View File
@@ -16,7 +16,7 @@ from roboco.config import settings
from roboco.runtime.orchestrator import AgentOrchestrator
def _orch() -> AgentOrchestrator:
def _orch() -> Any:
return AgentOrchestrator.__new__(AgentOrchestrator)
@@ -25,7 +25,7 @@ async def test_loop_noop_when_disabled(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(settings, "dep_update_enabled", False)
orch = _orch()
cycle = AsyncMock()
orch._run_dep_update_cycle = cycle # type: ignore[method-assign]
orch._run_dep_update_cycle = cycle
await orch._dep_update_loop()
cycle.assert_not_awaited()
@@ -55,7 +55,7 @@ def _db_ctx(db: Any) -> Any:
@pytest.mark.asyncio
async def test_cycle_warns_and_skips_engine_when_empty() -> None:
orch = _orch()
orch._load_dep_update_set = AsyncMock(return_value=[]) # type: ignore[method-assign]
orch._load_dep_update_set = AsyncMock(return_value=[])
get_eng = MagicMock()
with (
patch("roboco.db.get_db_context", _db_ctx(MagicMock())),
@@ -69,7 +69,7 @@ async def test_cycle_warns_and_skips_engine_when_empty() -> None:
async def test_cycle_runs_engine_when_eligible_present() -> None:
orch = _orch()
eligible = [MagicMock()]
orch._load_dep_update_set = AsyncMock(return_value=eligible) # type: ignore[method-assign]
orch._load_dep_update_set = AsyncMock(return_value=eligible)
db = MagicMock()
db.commit = AsyncMock()
engine = MagicMock()
+21 -20
View File
@@ -20,6 +20,7 @@ or future is covered, because they all go through `spawn_agent`.
from __future__ import annotations
from typing import Any
from unittest.mock import AsyncMock, MagicMock
import pytest
@@ -28,7 +29,7 @@ from roboco.runtime.orchestrator import AgentOrchestrator, AgentReadinessError
from roboco.seeds.initial_data import AGENT_UUIDS
def _orch() -> AgentOrchestrator:
def _orch() -> Any:
# The human-role guard is the first statement in spawn_agent and only
# consults the pure `role_for_slug` + the module logger — no self state
# — so a bare (un-initialized) orchestrator is sufficient to exercise it.
@@ -75,7 +76,7 @@ async def test_spawn_agent_does_not_refuse_real_agent() -> None:
async def _ready(_aid: str, _tid: str | None) -> str | None:
return "stubbed-not-ready"
orch._readiness_gate = _ready # type: ignore[assignment]
orch._readiness_gate = _ready
with pytest.raises(AgentReadinessError) as exc_info:
await orch.spawn_agent("be-dev-1", task_id="t-1")
@@ -89,15 +90,15 @@ async def test_spawn_agent_does_not_refuse_real_agent() -> None:
# ---------------------------------------------------------------------------
def _a2a_orch(ceo_uuid: str) -> AgentOrchestrator:
def _a2a_orch(ceo_uuid: str) -> Any:
"""A bare orchestrator with the a2a-dispatch collaborators stubbed."""
orch = object.__new__(AgentOrchestrator)
orch: Any = object.__new__(AgentOrchestrator)
# _dispatch_a2a_work consults: _fetch_notifications, _resolve_agent_slug,
# _is_agent_active, spawn_agent. _resolve_agent_slug is pure (module
# UUID_TO_SLUG) so it works unstubbed; stub the rest.
orch.spawn_agent = AsyncMock() # type: ignore[method-assign]
orch._is_agent_active = MagicMock(return_value=False) # type: ignore[method-assign]
orch._fetch_notifications = AsyncMock( # type: ignore[method-assign]
orch.spawn_agent = AsyncMock()
orch._is_agent_active = MagicMock(return_value=False)
orch._fetch_notifications = AsyncMock(
return_value=[
{"id": "n1", "to_agents": [ceo_uuid], "body": "board handoff"},
]
@@ -119,7 +120,7 @@ async def test_dispatch_a2a_skips_ceo_target() -> None:
await orch._dispatch_a2a_work(client)
orch.spawn_agent.assert_not_awaited() # type: ignore[attr-defined]
orch.spawn_agent.assert_not_awaited()
@pytest.mark.asyncio
@@ -128,7 +129,7 @@ async def test_dispatch_a2a_skips_intake_and_secretary_targets() -> None:
for slug in ("intake-1", "secretary-1"):
orch = _a2a_orch(AGENT_UUIDS[slug])
await orch._dispatch_a2a_work(MagicMock())
orch.spawn_agent.assert_not_awaited() # type: ignore[attr-defined]
orch.spawn_agent.assert_not_awaited()
@pytest.mark.asyncio
@@ -141,8 +142,8 @@ async def test_dispatch_a2a_still_spawns_real_agent_target() -> None:
await orch._dispatch_a2a_work(client)
orch.spawn_agent.assert_awaited_once() # type: ignore[attr-defined]
_args, kwargs = orch.spawn_agent.call_args # type: ignore[attr-defined]
orch.spawn_agent.assert_awaited_once()
_args, kwargs = orch.spawn_agent.call_args
assert kwargs.get("agent_id") == "be-dev-1"
@@ -152,10 +153,10 @@ async def test_dispatch_a2a_mixed_targets_skips_only_human() -> None:
real agent once and never the CEO."""
ceo_uuid = AGENT_UUIDS["ceo"]
be_uuid = AGENT_UUIDS["be-dev-1"]
orch = object.__new__(AgentOrchestrator)
orch.spawn_agent = AsyncMock() # type: ignore[method-assign]
orch._is_agent_active = MagicMock(return_value=False) # type: ignore[method-assign]
orch._fetch_notifications = AsyncMock( # type: ignore[method-assign]
orch: Any = object.__new__(AgentOrchestrator)
orch.spawn_agent = AsyncMock()
orch._is_agent_active = MagicMock(return_value=False)
orch._fetch_notifications = AsyncMock(
return_value=[{"id": "n1", "to_agents": [ceo_uuid, be_uuid]}]
)
client = MagicMock()
@@ -177,11 +178,11 @@ async def test_dispatch_pm_review_skips_ceo_assignee() -> None:
"""An awaiting_pm_review task assigned to the CEO must NOT respawn a CEO
container, and must NOT abort the dispatcher's tick (which would stall
other PM-review respawns behind it). The skip leaves it for the human."""
orch = object.__new__(AgentOrchestrator)
orch.spawn_agent = AsyncMock() # type: ignore[method-assign]
orch._is_agent_active = MagicMock(return_value=False) # type: ignore[method-assign]
orch._pm_respawn_should_gate = AsyncMock(return_value=False) # type: ignore[method-assign]
orch._fetch_tasks = AsyncMock( # type: ignore[method-assign]
orch: Any = object.__new__(AgentOrchestrator)
orch.spawn_agent = AsyncMock()
orch._is_agent_active = MagicMock(return_value=False)
orch._pm_respawn_should_gate = AsyncMock(return_value=False)
orch._fetch_tasks = AsyncMock(
return_value=[
{
"id": "t1",
@@ -18,36 +18,36 @@ triggers only its own recovery helper.
from __future__ import annotations
from typing import cast
from typing import Any, cast
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from roboco.runtime.orchestrator import AgentOrchestrator
def _orch() -> AgentOrchestrator:
def _orch() -> Any:
with patch.object(AgentOrchestrator, "__init__", return_value=None):
return AgentOrchestrator.__new__(AgentOrchestrator)
def _ready_orch() -> AgentOrchestrator:
def _ready_orch() -> Any:
"""Orchestrator with every closure gate stubbed so _maybe_spawn_pm_closure
reaches the spawn (descendants terminal, not recently paused, not
already promoted, PM idle)."""
orch = _orch()
orch._is_recently_paused = MagicMock(return_value=False) # type: ignore[method-assign]
orch._fetch_all_descendants = AsyncMock( # type: ignore[method-assign]
orch._is_recently_paused = MagicMock(return_value=False)
orch._fetch_all_descendants = AsyncMock(
return_value=[{"id": "leaf", "status": "completed"}]
)
orch._all_descendants_terminal = MagicMock(return_value=True) # type: ignore[method-assign]
orch._already_promoted_for_closure = MagicMock(return_value=False) # type: ignore[method-assign]
orch._closure_pm_for_team = MagicMock(return_value="be-pm") # type: ignore[method-assign]
orch._is_agent_active = MagicMock(return_value=False) # type: ignore[method-assign]
orch._build_pm_closure_prompt = MagicMock(return_value="PROMPT") # type: ignore[method-assign]
orch._task_git_context = MagicMock(return_value=None) # type: ignore[method-assign]
orch.spawn_agent = AsyncMock() # type: ignore[method-assign]
orch._auto_resume_paused_parent = AsyncMock() # type: ignore[method-assign]
orch._auto_recover_blocked_parent = AsyncMock() # type: ignore[method-assign]
orch._all_descendants_terminal = MagicMock(return_value=True)
orch._already_promoted_for_closure = MagicMock(return_value=False)
orch._closure_pm_for_team = MagicMock(return_value="be-pm")
orch._is_agent_active = MagicMock(return_value=False)
orch._build_pm_closure_prompt = MagicMock(return_value="PROMPT")
orch._task_git_context = MagicMock(return_value=None)
orch.spawn_agent = AsyncMock()
orch._auto_resume_paused_parent = AsyncMock()
orch._auto_recover_blocked_parent = AsyncMock()
return orch
@@ -102,7 +102,7 @@ async def test_non_paused_parent_is_not_resumed() -> None:
async def test_resume_skipped_when_closure_gate_blocks_spawn() -> None:
"""If descendants aren't terminal there is no spawn — and no resume."""
orch = _ready_orch()
orch._all_descendants_terminal = MagicMock(return_value=False) # type: ignore[method-assign]
orch._all_descendants_terminal = MagicMock(return_value=False)
client = AsyncMock()
await orch._maybe_spawn_pm_closure(
@@ -12,6 +12,7 @@ reaper's live-skip and the spawn gate see the live agent immediately.
from __future__ import annotations
from typing import Any
from unittest.mock import AsyncMock, MagicMock
import pytest
@@ -20,7 +21,7 @@ from roboco.runtime.orchestrator import AgentOrchestrator, AgentState
_EXPECTED_READOPTED = 2
def _orch() -> AgentOrchestrator:
def _orch() -> Any:
orch = AgentOrchestrator.__new__(AgentOrchestrator) # bypass __init__
orch._instances = {}
return orch
@@ -35,7 +36,7 @@ async def test_readopts_running_containers_as_active() -> None:
slug = name.removeprefix("roboco-agent-")
return (slug in running, 0)
orch._inspect_container_state = AsyncMock(side_effect=inspect) # type: ignore[method-assign]
orch._inspect_container_state = AsyncMock(side_effect=inspect)
n = await orch._readopt_running_agents()
@@ -51,7 +52,7 @@ async def test_readopt_leaves_already_tracked_instance_untouched() -> None:
orch = _orch()
sentinel = MagicMock()
orch._instances = {"be-dev-1": sentinel}
orch._inspect_container_state = AsyncMock(return_value=(True, 0)) # type: ignore[method-assign]
orch._inspect_container_state = AsyncMock(return_value=(True, 0))
await orch._readopt_running_agents()
@@ -61,7 +62,7 @@ async def test_readopt_leaves_already_tracked_instance_untouched() -> None:
@pytest.mark.asyncio
async def test_readopt_inert_when_nothing_running() -> None:
orch = _orch()
orch._inspect_container_state = AsyncMock(return_value=(False, None)) # type: ignore[method-assign]
orch._inspect_container_state = AsyncMock(return_value=(False, None))
n = await orch._readopt_running_agents()
@@ -72,7 +73,7 @@ async def test_readopt_inert_when_nothing_running() -> None:
@pytest.mark.asyncio
async def test_readopt_swallows_probe_errors() -> None:
orch = _orch()
orch._inspect_container_state = AsyncMock(side_effect=RuntimeError("no docker")) # type: ignore[method-assign]
orch._inspect_container_state = AsyncMock(side_effect=RuntimeError("no docker"))
n = await orch._readopt_running_agents()
@@ -87,8 +88,8 @@ async def test_readopt_records_container_id_so_health_check_can_see_exit() -> No
# is stranded under a phantom ACTIVE instance forever. Re-adopt must capture
# the real container id so the health loop can observe the later exit.
orch = _orch()
orch._inspect_container_state = AsyncMock(return_value=(True, 0)) # type: ignore[method-assign]
orch._resolve_container_id = AsyncMock(return_value="deadbeef1234") # type: ignore[method-assign]
orch._inspect_container_state = AsyncMock(return_value=(True, 0))
orch._resolve_container_id = AsyncMock(return_value="deadbeef1234")
await orch._readopt_running_agents()