feat(#160): Implement basic orchestration loop
Implements the Coordinator class with main orchestration loop: - Async loop architecture with configurable poll interval - process_queue() method gets next ready issue and spawns agent (stub) - Graceful shutdown handling with stop() method - Error handling that allows loop to continue after failures - Logging for all actions (start, stop, processing, errors) - Integration with QueueManager from #159 - Active agent tracking for future agent management Configuration settings added: - COORDINATOR_POLL_INTERVAL (default: 5.0s) - COORDINATOR_MAX_CONCURRENT_AGENTS (default: 10) - COORDINATOR_ENABLED (default: true) Tests: 27 new tests covering all acceptance criteria Coverage: 92% overall (100% for coordinator.py) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
"""Tests for issue parser agent."""
|
||||
|
||||
import os
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch, AsyncMock
|
||||
from anthropic import Anthropic
|
||||
from anthropic.types import Message, TextBlock, Usage
|
||||
|
||||
from src.parser import parse_issue_metadata, clear_cache
|
||||
from src.models import IssueMetadata
|
||||
from src.parser import clear_cache, parse_issue_metadata
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@@ -88,7 +87,10 @@ def mock_anthropic_response() -> Message:
|
||||
content=[
|
||||
TextBlock(
|
||||
type="text",
|
||||
text='{"estimated_context": 46800, "difficulty": "medium", "assigned_agent": "sonnet", "blocks": [159], "blocked_by": [157]}'
|
||||
text=(
|
||||
'{"estimated_context": 46800, "difficulty": "medium", '
|
||||
'"assigned_agent": "sonnet", "blocks": [159], "blocked_by": [157]}'
|
||||
),
|
||||
)
|
||||
],
|
||||
model="claude-sonnet-4.5-20250929",
|
||||
@@ -107,7 +109,10 @@ def mock_anthropic_minimal_response() -> Message:
|
||||
content=[
|
||||
TextBlock(
|
||||
type="text",
|
||||
text='{"estimated_context": 50000, "difficulty": "medium", "assigned_agent": "sonnet", "blocks": [], "blocked_by": []}'
|
||||
text=(
|
||||
'{"estimated_context": 50000, "difficulty": "medium", '
|
||||
'"assigned_agent": "sonnet", "blocks": [], "blocked_by": []}'
|
||||
),
|
||||
)
|
||||
],
|
||||
model="claude-sonnet-4.5-20250929",
|
||||
@@ -306,7 +311,10 @@ class TestParseIssueMetadata:
|
||||
content=[
|
||||
TextBlock(
|
||||
type="text",
|
||||
text='{"estimated_context": 10000, "difficulty": "invalid", "assigned_agent": "sonnet", "blocks": [], "blocked_by": []}'
|
||||
text=(
|
||||
'{"estimated_context": 10000, "difficulty": "invalid", '
|
||||
'"assigned_agent": "sonnet", "blocks": [], "blocked_by": []}'
|
||||
),
|
||||
)
|
||||
],
|
||||
model="claude-sonnet-4.5-20250929",
|
||||
@@ -341,7 +349,10 @@ class TestParseIssueMetadata:
|
||||
content=[
|
||||
TextBlock(
|
||||
type="text",
|
||||
text='{"estimated_context": 10000, "difficulty": "medium", "assigned_agent": "invalid_agent", "blocks": [], "blocked_by": []}'
|
||||
text=(
|
||||
'{"estimated_context": 10000, "difficulty": "medium", '
|
||||
'"assigned_agent": "invalid_agent", "blocks": [], "blocked_by": []}'
|
||||
),
|
||||
)
|
||||
],
|
||||
model="claude-sonnet-4.5-20250929",
|
||||
|
||||
Reference in New Issue
Block a user