"""Typed stub mixins inherit from for static analysis. The role mixins (`board.py`, `doc.py`, `qa.py`, …) call methods like ``self.task.get(...)`` and ``self._emit_rejection(...)`` that live on the legacy ``Choreographer`` class in ``_impl.py``. Without a typed reference, mypy resolves those as ``Any`` (via ``# type: ignore[attr-defined]``) which then bubbles up as ``no-any-return`` errors at every Envelope-returning verb. This module gives mypy a typed view of those helpers. ``ChoreographerHelpers`` is **not** a Protocol — Protocol with abstract members causes the composed ``Choreographer`` class to be flagged as instantiating an abstract class. Instead it's a plain class with stub signatures used ONLY under ``TYPE_CHECKING``; at runtime mixins inherit from ``object`` so there's no abstract-method baggage. The real implementations live on ``_LegacyChoreographer`` and are picked up by Python's MRO when the composed ``Choreographer`` runs. """ from __future__ import annotations from typing import TYPE_CHECKING, Any if TYPE_CHECKING: from uuid import UUID from roboco.services.gateway.choreographer._verb_runner import VerbRunner from roboco.services.gateway.envelope import Envelope class ChoreographerHelpers: """Typed stub of attributes + helpers role mixins call on ``self``. Stub bodies (``...``) are never executed; the real methods live on ``_LegacyChoreographer`` and resolve via MRO at runtime. """ task: Any work_session: Any git: Any a2a: Any journal: Any audit: Any evidence_repo: Any async def _emit_rejection( self, env: Envelope, *, agent_id: UUID, task_id: UUID | None, verb: str, ) -> Envelope: raise NotImplementedError async def _teardown_sandbox_best_effort(self, agent_id: UUID) -> None: raise NotImplementedError async def _toolchain_broken_guard( self, agent_id: UUID, task: Any, *, reviewer: bool = False ) -> Envelope | None: raise NotImplementedError async def _conventions_guard( self, agent_id: UUID, task: Any, briefing: dict[str, Any], preferred_parent: str | None = None, ) -> Envelope | None: raise NotImplementedError @classmethod def _free_text_soup( cls, checks: tuple[tuple[str, Any, int], ...] ) -> Envelope | None: raise NotImplementedError @staticmethod def _soup_or_decision_env( soup: Envelope | None, decision: Any, briefing: dict[str, Any] ) -> Envelope | None: raise NotImplementedError async def _guard_free_text( self, *, checks: tuple[tuple[str, Any, int], ...], task: Any, agent_id: UUID, role_str: str, verb: str, ) -> Envelope | None: raise NotImplementedError async def _briefing_for( self, agent_id: UUID, task_id: UUID | None, *, task: Any | None = None, include_ac_coverage: bool = False, full: bool = False, include_company_goals: bool = False, ) -> dict[str, Any]: raise NotImplementedError async def _project_slug_for(self, t: Any) -> str | None: raise NotImplementedError @staticmethod def _with_briefing( env: Envelope, briefing: dict[str, Any], ) -> Envelope: raise NotImplementedError async def _run_claim_guards( self, *, agent_id: UUID, task: Any, role_str: str | None = None, skip_dev_guards: bool = False, ) -> Envelope | None: raise NotImplementedError async def _touch(self, task_id: UUID | None) -> None: raise NotImplementedError def _verb_runner(self) -> VerbRunner: raise NotImplementedError async def _build_tracing_gap( self, agent_id: UUID, task_id: UUID, missing: list[str], *, task: Any | None = None, ) -> Envelope: raise NotImplementedError async def _resolve_ci_status(self, task_id: UUID, t: Any) -> dict[str, Any] | None: raise NotImplementedError def actor_context_fields(agent: Any) -> tuple[str | None, str | None]: """``(actor_slug, agent_team)`` for a spec ``Context``, None-agent safe. Every verb builds its policy Context with the same two conditional kwargs; inlining them pushed nine verbs over the xenon B threshold when the team-match sweep added ``agent_team`` to all 27 sites. """ if agent is None: return None, None team = getattr(agent, "team", None) return getattr(agent, "slug", None), str(team) if team else None