"""Unit tests for timmy.vassal.dispatch — routing and label helpers.""" from __future__ import annotations import pytest from timmy.vassal.backlog import AgentTarget, TriagedIssue from timmy.vassal.dispatch import ( DispatchRecord, clear_dispatch_registry, get_dispatch_registry, ) def _make_triaged( number: int, title: str, agent: AgentTarget, priority: int = 50, ) -> TriagedIssue: return TriagedIssue( number=number, title=title, body="", agent_target=agent, priority_score=priority, rationale="test rationale", url=f"http://gitea/issues/{number}", ) # --------------------------------------------------------------------------- # Registry helpers # --------------------------------------------------------------------------- def test_registry_starts_empty(): clear_dispatch_registry() assert get_dispatch_registry() == {} def test_registry_returns_copy(): clear_dispatch_registry() reg = get_dispatch_registry() reg[999] = None # type: ignore[assignment] assert 999 not in get_dispatch_registry() # --------------------------------------------------------------------------- # dispatch_issue — Timmy self-dispatch (no Gitea required) # --------------------------------------------------------------------------- @pytest.mark.asyncio async def test_dispatch_timmy_self_no_gitea(): """Timmy self-dispatch records without hitting Gitea.""" clear_dispatch_registry() issue = _make_triaged(1, "Fix docs typo", AgentTarget.TIMMY) from timmy.vassal.dispatch import dispatch_issue record = await dispatch_issue(issue) assert isinstance(record, DispatchRecord) assert record.issue_number == 1 assert record.agent == AgentTarget.TIMMY assert 1 in get_dispatch_registry() @pytest.mark.asyncio async def test_dispatch_claude_no_gitea_token(): """Claude dispatch gracefully degrades when Gitea token is absent.""" clear_dispatch_registry() issue = _make_triaged(2, "Refactor auth", AgentTarget.CLAUDE) from timmy.vassal.dispatch import dispatch_issue record = await dispatch_issue(issue) assert record.issue_number == 2 assert record.agent == AgentTarget.CLAUDE # label/comment not applied — no token assert record.label_applied is False assert 2 in get_dispatch_registry() @pytest.mark.asyncio async def test_dispatch_kimi_no_gitea_token(): clear_dispatch_registry() issue = _make_triaged(3, "Research embeddings", AgentTarget.KIMI) from timmy.vassal.dispatch import dispatch_issue record = await dispatch_issue(issue) assert record.agent == AgentTarget.KIMI assert record.label_applied is False # --------------------------------------------------------------------------- # DispatchRecord fields # --------------------------------------------------------------------------- def test_dispatch_record_defaults(): r = DispatchRecord( issue_number=5, issue_title="Test issue", agent=AgentTarget.TIMMY, rationale="because", ) assert r.label_applied is False assert r.comment_posted is False assert r.dispatched_at # has a timestamp