"""Tests for the worker_prompt module."""
import pytest
from maniple_mcp.worker_prompt import (
AgentType,
generate_worker_prompt,
get_coordinator_guidance,
)
class TestGenerateWorkerPrompt:
"""Tests for generate_worker_prompt function."""
def test_includes_worker_name(self):
"""Prompt should address the worker by name."""
prompt = generate_worker_prompt("worker-1", "Ringo")
assert "Ringo" in prompt
def test_includes_do_work_fully_rule(self):
"""Prompt should contain the 'do work fully' instruction."""
prompt = generate_worker_prompt("test-session", "George")
assert "Do the work fully" in prompt
def test_prompt_is_non_empty_string(self):
"""Prompt should be a non-empty string."""
prompt = generate_worker_prompt("test", "Worker")
assert isinstance(prompt, str)
assert len(prompt) > 100 # Should be substantial
class TestAssignmentCases:
"""Tests for the 4 assignment cases in worker prompts."""
def test_case1_issue_only(self, tmp_path):
"""With issue only, should show assignment and tracker workflow."""
# Create a project with pebbles marker for testing
project_path = tmp_path / "test-repo"
project_path.mkdir()
(project_path / ".pebbles").mkdir()
issue_id = "cic-123"
prompt = generate_worker_prompt(
"test", "Worker",
issue_id=issue_id,
project_path=str(project_path)
)
assert f"Your assignment is `{issue_id}`" in prompt
assert "workflow" in prompt
assert "Mark in progress" in prompt
assert "Close issue" in prompt
assert "Get to work!" in prompt
def test_case2_issue_and_custom_prompt(self):
"""With issue and custom prompt, should show both."""
issue_id = "cic-456"
prompt = generate_worker_prompt(
"test", "Worker",
issue_id=issue_id,
custom_prompt="Focus on the edge cases"
)
assert f"`{issue_id}`" in prompt
assert "Focus on the edge cases" in prompt
assert "workflow" in prompt
assert "Get to work!" in prompt
def test_case3_custom_prompt_only(self):
"""With custom prompt only, should show the task."""
prompt = generate_worker_prompt(
"test", "Worker",
custom_prompt="Review the auth module for security issues"
)
assert "Review the auth module for security issues" in prompt
assert "The coordinator assigned you the following task" in prompt
assert "Get to work!" in prompt
# Should not have tracker workflow
assert "workflow" not in prompt
def test_case4_no_issue_no_prompt(self):
"""With neither issue nor prompt, should say coordinator will message."""
prompt = generate_worker_prompt("test", "Worker")
assert "The coordinator will send your first task shortly" in prompt
# Should not have assignment section
assert "YOUR ASSIGNMENT" not in prompt
assert "workflow" not in prompt
class TestIssueTrackerWorkflow:
"""Tests for issue tracker workflow instructions."""
def test_workflow_includes_update_and_close(self, tmp_path):
"""Workflow should include update and close commands."""
# Create a project with pebbles marker for testing
project_path = tmp_path / "test-repo"
project_path.mkdir()
(project_path / ".pebbles").mkdir()
issue_id = "cic-abc"
prompt = generate_worker_prompt(
"test", "Worker",
issue_id=issue_id,
project_path=str(project_path)
)
assert f"update {issue_id}" in prompt
assert f"close {issue_id}" in prompt
assert "status in_progress" in prompt
def test_workflow_includes_commit_instruction(self, tmp_path):
"""Workflow should include commit with issue reference."""
# Create a project with pebbles marker for testing
project_path = tmp_path / "test-repo"
project_path.mkdir()
(project_path / ".pebbles").mkdir()
issue_id = "cic-abc"
prompt = generate_worker_prompt(
"test", "Worker",
issue_id=issue_id,
project_path=str(project_path)
)
assert f'git commit -m "{issue_id}:' in prompt
class TestGetCoordinatorGuidance:
"""Tests for get_coordinator_guidance function."""
def test_returns_non_empty_string(self):
"""Should return a non-empty string."""
guidance = get_coordinator_guidance([{"name": "Groucho", "issue_id": "cic-123"}])
assert isinstance(guidance, str)
assert len(guidance) > 0
def test_contains_team_dispatched_header(self):
"""Guidance should have team dispatched header."""
guidance = get_coordinator_guidance([{"name": "Groucho", "issue_id": "cic-123"}])
assert "TEAM DISPATCHED" in guidance
def test_shows_worker_with_issue(self):
"""Should show worker name and issue assignment."""
guidance = get_coordinator_guidance([{"name": "Groucho", "issue_id": "cic-123"}])
assert "Groucho" in guidance
assert "cic-123" in guidance
assert "mark in_progress" in guidance
def test_shows_worker_with_custom_prompt(self):
"""Should show worker with custom task."""
guidance = get_coordinator_guidance([
{"name": "Harpo", "custom_prompt": "Review the auth module"}
])
assert "Harpo" in guidance
assert "Review the auth module" in guidance
def test_shows_worker_awaiting_task(self):
"""Should show warning for worker awaiting task."""
guidance = get_coordinator_guidance([
{"name": "Chico", "awaiting_task": True}
])
assert "Chico" in guidance
assert "AWAITING TASK" in guidance
def test_shows_multiple_workers(self):
"""Should show all workers."""
guidance = get_coordinator_guidance([
{"name": "Groucho", "issue_id": "cic-123"},
{"name": "Harpo", "custom_prompt": "Do something"},
{"name": "Chico", "awaiting_task": True},
])
assert "Groucho" in guidance
assert "Harpo" in guidance
assert "Chico" in guidance
def test_includes_coordination_reminder(self):
"""Should include coordination style reminder."""
guidance = get_coordinator_guidance([{"name": "Groucho", "issue_id": "cic-123"}])
assert "Coordination style" in guidance or "Hands-off" in guidance
def test_truncates_long_custom_prompt(self):
"""Should truncate long custom prompts."""
long_prompt = "A" * 100
guidance = get_coordinator_guidance([
{"name": "Harpo", "custom_prompt": long_prompt}
])
assert "..." in guidance
# Should not contain the full 100-char string
assert long_prompt not in guidance
class TestWorktreeMode:
"""Tests for worktree-aware prompt generation."""
def test_worker_prompt_without_worktree_no_commit(self):
"""Worker prompt without worktree should not mention committing (unless issue)."""
prompt = generate_worker_prompt("test", "Worker", use_worktree=False)
# Without issue or worktree, no commit instruction
assert "Commit when done" not in prompt
def test_worker_prompt_with_worktree_includes_commit(self):
"""Worker prompt with worktree (no issue) should instruct committing."""
prompt = generate_worker_prompt("test", "Worker", use_worktree=True)
assert "Commit when done" in prompt
assert "cherry-pick" in prompt
def test_worker_prompt_with_issue_has_commit_in_workflow(self):
"""Worker prompt with issue has commit as part of tracker workflow."""
prompt = generate_worker_prompt("test", "Worker", issue_id="cic-123")
# Commit is in the tracker workflow, not separate
assert "git commit" in prompt
assert "cic-123" in prompt
def test_worktree_with_issue_no_separate_commit_section(self):
"""With issue, commit is in tracker workflow - no separate commit section."""
prompt = generate_worker_prompt("test", "Worker", use_worktree=True, issue_id="cic-123")
# Should have tracker workflow with commit
assert 'git commit -m "cic-123:' in prompt
# Should NOT have separate "Commit when done" section
assert "Commit when done" not in prompt
class TestAgentTypeParameter:
"""Tests for agent_type parameter in generate_worker_prompt."""
def test_default_agent_type_is_claude(self):
"""Default agent_type should be claude."""
prompt = generate_worker_prompt("test", "Worker")
# Claude prompt has "claude-team" reference
assert "claude-team" in prompt
def test_explicit_claude_agent_type(self):
"""Explicit claude agent_type should produce Claude prompt."""
prompt = generate_worker_prompt("test", "Worker", agent_type="claude")
assert "claude-team" in prompt
assert "automatically report" in prompt
def test_codex_agent_type_produces_different_prompt(self):
"""Codex agent_type should produce Codex-specific prompt."""
prompt = generate_worker_prompt("test", "Worker", agent_type="codex")
# Codex prompt should NOT have claude-team specific references
assert "claude-team" not in prompt
# Codex prompt should have different completion detection instructions
assert "COMPLETED" in prompt or "BLOCKED" in prompt
class TestCodexWorkerPrompt:
"""Tests for Codex-specific worker prompt generation."""
def test_codex_includes_worker_name(self):
"""Codex prompt should address the worker by name."""
prompt = generate_worker_prompt("test", "Zeppo", agent_type="codex")
assert "Zeppo" in prompt
def test_codex_has_no_mcp_markers(self):
"""Codex prompt should not reference MCP markers."""
prompt = generate_worker_prompt("test", "Worker", agent_type="codex")
assert "claude-team" not in prompt
assert "automatically report your session" not in prompt
def test_codex_has_status_completion_instructions(self):
"""Codex prompt should instruct to end with COMPLETED or BLOCKED."""
prompt = generate_worker_prompt("test", "Worker", agent_type="codex")
assert "COMPLETED" in prompt
assert "BLOCKED" in prompt
def test_codex_tracker_workflow_same_as_claude(self, tmp_path):
"""Codex tracker workflow should match Claude's."""
# Create a project with pebbles marker for testing
project_path = tmp_path / "test-repo"
project_path.mkdir()
(project_path / ".pebbles").mkdir()
issue_id = "cic-123"
codex_prompt = generate_worker_prompt(
"test", "Worker",
agent_type="codex",
issue_id=issue_id,
project_path=str(project_path)
)
claude_prompt = generate_worker_prompt(
"test", "Worker",
agent_type="claude",
issue_id=issue_id,
project_path=str(project_path)
)
for prompt in (codex_prompt, claude_prompt):
assert f"update {issue_id}" in prompt
assert f"close {issue_id}" in prompt
assert "status in_progress" in prompt
def test_codex_with_issue_only(self):
"""Codex with issue only should show assignment."""
issue_id = "cic-456"
prompt = generate_worker_prompt("test", "Worker", agent_type="codex", issue_id=issue_id)
assert f"Your assignment is `{issue_id}`" in prompt
assert "workflow" in prompt
assert "Mark in progress" in prompt
def test_codex_with_custom_prompt(self):
"""Codex with custom prompt should show the task."""
prompt = generate_worker_prompt(
"test", "Worker",
agent_type="codex",
custom_prompt="Fix the auth bug"
)
assert "Fix the auth bug" in prompt
assert "The coordinator assigned you the following task" in prompt
def test_codex_with_worktree_includes_commit(self):
"""Codex with worktree should include commit instructions."""
prompt = generate_worker_prompt(
"test", "Worker",
agent_type="codex",
use_worktree=True
)
assert "Commit when done" in prompt
assert "cherry-pick" in prompt
class TestMixedTeamCoordinatorGuidance:
"""Tests for coordinator guidance with mixed Claude/Codex teams."""
def test_single_agent_type_no_indicator(self):
"""With only one agent type, no [type] indicator should appear."""
guidance = get_coordinator_guidance([
{"name": "Groucho", "issue_id": "cic-123", "agent_type": "claude"},
{"name": "Harpo", "issue_id": "cic-456", "agent_type": "claude"},
])
assert "[claude]" not in guidance
assert "[codex]" not in guidance
def test_mixed_team_shows_type_indicators(self):
"""With mixed team, should show [type] indicators."""
guidance = get_coordinator_guidance([
{"name": "Groucho", "issue_id": "cic-123", "agent_type": "claude"},
{"name": "GPT-4", "issue_id": "cic-456", "agent_type": "codex"},
])
assert "[claude]" in guidance
assert "[codex]" in guidance
def test_mixed_team_shows_guidance_note(self):
"""Mixed team should include guidance about different idle detection."""
guidance = get_coordinator_guidance([
{"name": "Groucho", "agent_type": "claude", "issue_id": "cic-123"},
{"name": "Codex-1", "agent_type": "codex", "issue_id": "cic-456"},
])
assert "Mixed team note" in guidance
assert "Claude workers" in guidance
assert "Codex workers" in guidance
def test_default_agent_type_is_claude(self):
"""Workers without explicit agent_type should default to claude."""
guidance = get_coordinator_guidance([
{"name": "Groucho", "issue_id": "cic-123"}, # No agent_type
{"name": "Codex-1", "agent_type": "codex", "issue_id": "cic-456"},
])
# Should still be mixed team because one is explicitly codex
assert "[claude]" in guidance
assert "[codex]" in guidance
def test_codex_only_team_no_mixed_note(self):
"""Codex-only team should not show mixed team note."""
guidance = get_coordinator_guidance([
{"name": "Codex-1", "agent_type": "codex", "issue_id": "cic-123"},
{"name": "Codex-2", "agent_type": "codex", "issue_id": "cic-456"},
])
assert "Mixed team note" not in guidance
# Should still not show type indicators (not mixed)
assert "[codex]" not in guidance