"""What the orchestrator must do without a model in the loop. The interesting properties here are structural: which specialists exist, what they advertise, and what happens to a delegation that is refused or that comes back waiting on a decision. None of that needs inference to test, and testing it without inference is what makes it a check rather than an observation. """ from __future__ import annotations import pytest from assistant_agent.delegation import Answer from assistant_agent.specialists import SPECIALISTS, by_name, describe class TestRegistry: def test_every_specialist_is_reachable_by_name(self) -> None: for specialist in SPECIALISTS: assert by_name(specialist.name) is specialist or by_name(specialist.name) == specialist def test_an_unknown_name_yields_none_rather_than_raising(self) -> None: # The model can emit a tool call for something that no longer exists. # That must reach it as an answer, not as a stack trace. assert by_name("ventes") is None def test_a_specialist_url_is_overridable_for_local_runs(self, monkeypatch) -> None: monkeypatch.setenv("ASSISTANT_URL_CATALOGUE", "http://localhost:8099/") assert by_name("catalogue").url == "http://localhost:8099/" def test_every_specialist_names_a_distinct_audience_scope(self) -> None: # One token per callee is the whole point: a token minted for one # specialist must be refused by every other. scopes = [s.audience_scope for s in SPECIALISTS] assert len(scopes) == len(set(scopes)) @pytest.mark.parametrize("specialist", SPECIALISTS, ids=lambda s: s.name) def test_a_specialist_advertises_decisions_not_a_query(self, specialist) -> None: # An agent advertised as "ask it anything" has become a data proxy and # defeats the per-domain scoping the estate is built on. text = describe(specialist).casefold() assert "it answers; it does not hand back raw records" in text assert specialist.decides, "a specialist with no stated decisions is a query endpoint" class TestAnswer: def test_input_required_is_recognised_as_needing_the_user(self) -> None: answer = Answer("catalogue", "…", "TASK_STATE_INPUT_REQUIRED") assert answer.needs_the_user is True @pytest.mark.parametrize( "state", ["TASK_STATE_COMPLETED", "TASK_STATE_FAILED", "TASK_STATE_CANCELLED"], ) def test_every_other_state_is_the_orchestrator_s_to_compose(self, state: str) -> None: assert Answer("catalogue", "…", state).needs_the_user is False