2026-05-02 03:11:49 +02:00
|
|
|
"""Tests for role-config catalog."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import pytest
|
2026-05-11 02:15:47 +02:00
|
|
|
from roboco.foundation.policy import lifecycle as spec
|
2026-05-02 03:11:49 +02:00
|
|
|
from roboco.services.gateway.role_config import (
|
2026-05-11 02:15:47 +02:00
|
|
|
_DEV_FLOW,
|
|
|
|
|
_QA_FLOW,
|
2026-05-02 03:11:49 +02:00
|
|
|
ROLE_CONFIGS,
|
|
|
|
|
get_role_config,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestRoleConfigCatalog:
|
|
|
|
|
def test_developer_config(self) -> None:
|
|
|
|
|
cfg = get_role_config("developer")
|
|
|
|
|
assert "give_me_work" in cfg.flow_tools
|
|
|
|
|
assert "i_will_work_on" in cfg.flow_tools
|
|
|
|
|
assert "i_am_done" in cfg.flow_tools
|
|
|
|
|
assert "commit" in cfg.do_tools
|
|
|
|
|
assert "note" in cfg.do_tools
|
|
|
|
|
assert "evidence" in cfg.do_tools
|
|
|
|
|
assert cfg.allows_write is True
|
|
|
|
|
assert cfg.allows_subagent is False # devs don't dispatch sub-research
|
|
|
|
|
|
|
|
|
|
def test_qa_config(self) -> None:
|
|
|
|
|
cfg = get_role_config("qa")
|
|
|
|
|
assert "claim_review" in cfg.flow_tools
|
2026-05-11 02:15:47 +02:00
|
|
|
# Spec canon: pass_review / fail_review (the legacy `pass`/`fail`
|
|
|
|
|
# MCP-facing aliases live in flow_server's _TOOLS map, not here).
|
|
|
|
|
assert "pass_review" in cfg.flow_tools
|
|
|
|
|
assert "fail_review" in cfg.flow_tools
|
2026-05-02 03:11:49 +02:00
|
|
|
# QA does NOT have i_am_done / commit
|
|
|
|
|
assert "i_am_done" not in cfg.flow_tools
|
|
|
|
|
assert "commit" not in cfg.do_tools
|
|
|
|
|
|
|
|
|
|
def test_documenter_config(self) -> None:
|
|
|
|
|
cfg = get_role_config("documenter")
|
|
|
|
|
assert "claim_doc_task" in cfg.flow_tools
|
|
|
|
|
assert "i_documented" in cfg.flow_tools
|
|
|
|
|
assert cfg.allows_write is True
|
|
|
|
|
|
|
|
|
|
def test_cell_pm_config(self) -> None:
|
|
|
|
|
cfg = get_role_config("cell_pm")
|
|
|
|
|
assert "complete" in cfg.flow_tools
|
|
|
|
|
assert "unblock" in cfg.flow_tools
|
|
|
|
|
assert "triage" in cfg.flow_tools
|
|
|
|
|
assert cfg.allows_subagent is True # PMs may need parallel research
|
|
|
|
|
|
|
|
|
|
def test_main_pm_config(self) -> None:
|
|
|
|
|
cfg = get_role_config("main_pm")
|
|
|
|
|
assert "complete" in cfg.flow_tools
|
|
|
|
|
assert "triage_all" in cfg.flow_tools
|
|
|
|
|
|
|
|
|
|
def test_unknown_role_raises(self) -> None:
|
|
|
|
|
with pytest.raises(KeyError, match="unknown role"):
|
|
|
|
|
get_role_config("not_a_role")
|
|
|
|
|
|
|
|
|
|
def test_all_roles_have_idle(self) -> None:
|
|
|
|
|
for role, cfg in ROLE_CONFIGS.items():
|
|
|
|
|
assert "i_am_idle" in cfg.flow_tools, f"{role} missing i_am_idle"
|
|
|
|
|
|
|
|
|
|
def test_no_role_has_toolsearch(self) -> None:
|
|
|
|
|
# ToolSearch is removed entirely — no manifest should include it
|
|
|
|
|
for cfg in ROLE_CONFIGS.values():
|
|
|
|
|
assert "ToolSearch" not in cfg.flow_tools
|
|
|
|
|
assert "ToolSearch" not in cfg.do_tools
|
2026-05-11 02:15:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_dev_flow_matches_spec_intents_for_role() -> None:
|
|
|
|
|
"""role_config._DEV_FLOW must equal spec.intents_for_role(Role.DEVELOPER)."""
|
|
|
|
|
assert tuple(_DEV_FLOW) == spec.intents_for_role(spec.Role.DEVELOPER)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_qa_flow_matches_spec_intents_for_role() -> None:
|
|
|
|
|
"""role_config._QA_FLOW must equal spec.intents_for_role(Role.QA)."""
|
|
|
|
|
assert tuple(_QA_FLOW) == spec.intents_for_role(spec.Role.QA)
|