8f11340b38
Per post_module_taxonomy_de_cruft_20260627 Phase 2 (FR7). Each
'from src.models import X' for a moved class is rewritten to
'from src.<destination> import X':
Ticket, Track, WorkerContext, TrackState, TrackMetadata,
ThinkingSegment, EMPTY_TRACK_STATE -> src.mma
ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles,
ProjectScreenshots, ProjectDiscussion, EMPTY_PROJECT_CONTEXT -> src.project
FileItem, Preset, ContextPreset, ContextFileEntry,
NamedViewPreset -> src.project_files
Tool, ToolPreset -> src.tool_presets
BiasProfile -> src.tool_bias
TextEditorConfig, ExternalEditorConfig,
EMPTY_TEXT_EDITOR_CONFIG -> src.external_editor
Persona -> src.personas
WorkspaceProfile -> src.workspace_manager
MCPServerConfig, MCPConfiguration, VectorStoreConfig,
RAGConfig, load_mcp_config -> src.mcp_client
NOT touched (kept on src.models; Phase 3 or Phase 4 will move them):
GenerateRequest, ConfirmRequest, DEFAULT_TOOL_CATEGORIES, Metadata, PROVIDERS
Migration was performed by the one-time script
scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_imports.py
which uses a class-to-module map and re.sub() to rewrite each
'from src.models import X' line.
Total: 85 import lines rewritten across 71 files.
Note: this commit depends on the v2 SHIPPED work
(origin/tier2/module_taxonomy_refactor_20260627) being merged into
this branch NEXT. On master (without the v2 SHIPPED commits), the
destination modules do not exist and these imports would fail.
87 lines
3.3 KiB
Python
87 lines
3.3 KiB
Python
import pytest
|
|
from unittest.mock import MagicMock, patch
|
|
from src import multi_agent_conductor
|
|
from src.mma import Ticket, WorkerContext
|
|
from src import events
|
|
from src.result_types import Result
|
|
import threading
|
|
from typing import Generator
|
|
|
|
class MockDialog:
|
|
def __init__(self, approved: bool, final_payload: dict | None = None) -> None:
|
|
self.approved = approved
|
|
self.final_payload = final_payload
|
|
|
|
def wait(self) -> dict:
|
|
res = {'approved': self.approved, 'abort': False}
|
|
if self.final_payload:
|
|
res.update(self.final_payload)
|
|
return res
|
|
|
|
@pytest.fixture
|
|
def mock_ai_client() -> Generator[MagicMock, None, None]:
|
|
with patch("src.ai_client.send") as mock_send:
|
|
mock_send.return_value = Result(data="Task completed")
|
|
yield mock_send
|
|
|
|
def test_confirm_spawn_pushed_to_queue() -> None:
|
|
event_queue = events.SyncEventQueue()
|
|
ticket_id = "T1"
|
|
role = "Tier 3 Worker"
|
|
prompt = "Original Prompt"
|
|
context_md = "Original Context"
|
|
|
|
results = []
|
|
def run_confirm():
|
|
res = multi_agent_conductor.confirm_spawn(role, prompt, context_md, event_queue, ticket_id)
|
|
results.append(res)
|
|
|
|
t = threading.Thread(target=run_confirm)
|
|
t.start()
|
|
|
|
# Wait for the event to appear in the queue
|
|
event_name, payload = event_queue.get()
|
|
assert event_name == "mma_spawn_approval"
|
|
assert payload["ticket_id"] == ticket_id
|
|
assert payload["role"] == role
|
|
assert payload["prompt"] == prompt
|
|
assert payload["context_md"] == context_md
|
|
assert "dialog_container" in payload
|
|
|
|
# Simulate GUI injecting a dialog
|
|
payload["dialog_container"][0] = MockDialog(True, {"prompt": "Modified Prompt", "context_md": "Modified Context"})
|
|
|
|
t.join(timeout=5)
|
|
assert not t.is_alive()
|
|
approved, final_prompt, final_context = results[0]
|
|
assert approved is True
|
|
assert final_prompt == "Modified Prompt"
|
|
assert final_context == "Modified Context"
|
|
|
|
@patch("src.multi_agent_conductor.confirm_spawn")
|
|
def test_run_worker_lifecycle_approved(mock_confirm: MagicMock, mock_ai_client: MagicMock, app_instance) -> None:
|
|
ticket = Ticket(id="T1", description="desc", status="todo", assigned_to="user")
|
|
context = WorkerContext(ticket_id="T1", model_name="model", messages=[])
|
|
event_queue = app_instance.controller.event_queue
|
|
mock_confirm.return_value = (True, "Modified Prompt", "Modified Context")
|
|
multi_agent_conductor.run_worker_lifecycle(ticket, context, event_queue=event_queue)
|
|
mock_confirm.assert_called_once()
|
|
# Check that ai_client.send was called with modified values
|
|
args, kwargs = mock_ai_client.call_args
|
|
assert kwargs["user_message"] == "Modified Prompt"
|
|
assert kwargs["md_content"] == "Modified Context"
|
|
assert ticket.status == "completed"
|
|
|
|
@patch("src.multi_agent_conductor.confirm_spawn")
|
|
def test_run_worker_lifecycle_rejected(mock_confirm: MagicMock, mock_ai_client: MagicMock, app_instance) -> None:
|
|
ticket = Ticket(id="T1", description="desc", status="todo", assigned_to="user")
|
|
context = WorkerContext(ticket_id="T1", model_name="model", messages=[])
|
|
event_queue = app_instance.controller.event_queue
|
|
mock_confirm.return_value = (False, "Original Prompt", "Original Context")
|
|
result = multi_agent_conductor.run_worker_lifecycle(ticket, context, event_queue=event_queue)
|
|
mock_confirm.assert_called_once()
|
|
mock_ai_client.assert_not_called()
|
|
assert ticket.status == "blocked"
|
|
assert "Spawn rejected by user" in ticket.blocked_reason
|
|
assert "BLOCKED" in result
|