"""The prompt composer injects the autogen verb table. `compose_prompt` reads `agents/prompts/_generated/.md` and includes it as a composition layer (between role and team). This pins that contract: when the file exists, its content appears in the composed prompt. """ from __future__ import annotations from typing import TYPE_CHECKING import pytest from roboco.agents.factories._base import compose_prompt from roboco.models.base import AgentRole, Team if TYPE_CHECKING: from pathlib import Path def _write_layer(root: Path, rel: str, body: str) -> None: target = root / rel target.parent.mkdir(parents=True, exist_ok=True) target.write_text(body) @pytest.fixture def fake_prompts(tmp_path: Path) -> Path: """Build a fake prompts directory with a known _generated/.md.""" _write_layer(tmp_path, "base.md", "# BASE LAYER") _write_layer(tmp_path, "roles/developer.md", "# ROLE LAYER (developer)") _write_layer(tmp_path, "teams/backend.md", "# TEAM LAYER (backend)") _write_layer( tmp_path, "_generated/developer.md", "# AUTOGEN LAYER (developer)\n\n" "## Verbs available to you (autogenerated source of truth)\n\n" "| Verb | Body schema |\n|------|-------------|\n" "| `give_me_work` | `give_me_work()` |\n", ) _write_layer(tmp_path, "identities/be-dev-1.md", "# IDENTITY (be-dev-1)") return tmp_path def test_compose_prompt_includes_autogen_layer(fake_prompts: Path) -> None: composed = compose_prompt( role=AgentRole.DEVELOPER, team=Team.BACKEND, agent_slug="be-dev-1", base_path=fake_prompts, ) assert "AUTOGEN LAYER (developer)" in composed assert "give_me_work()" in composed def test_compose_prompt_orders_layers_correctly(fake_prompts: Path) -> None: """base → role → autogen → team → identity (composer's documented order).""" composed = compose_prompt( role=AgentRole.DEVELOPER, team=Team.BACKEND, agent_slug="be-dev-1", base_path=fake_prompts, ) base_idx = composed.index("BASE LAYER") role_idx = composed.index("ROLE LAYER (developer)") autogen_idx = composed.index("AUTOGEN LAYER (developer)") team_idx = composed.index("TEAM LAYER (backend)") identity_idx = composed.index("IDENTITY (be-dev-1)") assert base_idx < role_idx < autogen_idx < team_idx < identity_idx def test_compose_prompt_omits_autogen_when_file_missing(tmp_path: Path) -> None: """No _generated/.md → composer skips that layer cleanly.""" _write_layer(tmp_path, "base.md", "# BASE") _write_layer(tmp_path, "roles/developer.md", "# DEV ROLE") _write_layer(tmp_path, "identities/be-dev-1.md", "# IDENTITY") composed = compose_prompt( role=AgentRole.DEVELOPER, team=None, agent_slug="be-dev-1", base_path=tmp_path, ) assert "BASE" in composed assert "DEV ROLE" in composed assert "IDENTITY" in composed assert "AUTOGEN" not in composed # no autogen layer file