diff --git a/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_imports.py b/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_imports.py new file mode 100644 index 00000000..d4e86a43 --- /dev/null +++ b/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_imports.py @@ -0,0 +1,167 @@ +"""One-time migration script: src.models import -> direct subsystem imports. + +Per post_module_taxonomy_de_cruft_20260627 Phase 2. Updates 95 consumer +sites that use 'from src.models import X' to use the direct subsystem +import path. Each 'from src.models import X' is rewritten based on the +class mapping: + + 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): + GenerateRequest, ConfirmRequest -> Phase 4 (api_hooks.py) + DEFAULT_TOOL_CATEGORIES -> Phase 3 (ai_client.py) + Metadata (the legacy alias) -> kept (re-exported at module level) + PROVIDERS -> kept (lazy __getattr__) + +Usage: + uv run python scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_imports.py + +This is a one-time script; it does not run as part of the test suite. +""" +from __future__ import annotations + +import re +import sys +from pathlib import Path + + +CLASS_TO_MODULE: dict[str, str] = { + "Ticket": "mma", + "Track": "mma", + "WorkerContext": "mma", + "TrackState": "mma", + "TrackMetadata": "mma", + "ThinkingSegment": "mma", + "EMPTY_TRACK_STATE": "mma", + "ProjectContext": "project", + "ProjectMeta": "project", + "ProjectOutput": "project", + "ProjectFiles": "project", + "ProjectScreenshots": "project", + "ProjectDiscussion": "project", + "EMPTY_PROJECT_CONTEXT": "project", + "FileItem": "project_files", + "Preset": "project_files", + "ContextPreset": "project_files", + "ContextFileEntry": "project_files", + "NamedViewPreset": "project_files", + "Tool": "tool_presets", + "ToolPreset": "tool_presets", + "BiasProfile": "tool_bias", + "TextEditorConfig": "external_editor", + "ExternalEditorConfig": "external_editor", + "EMPTY_TEXT_EDITOR_CONFIG": "external_editor", + "Persona": "personas", + "WorkspaceProfile": "workspace_manager", + "MCPServerConfig": "mcp_client", + "MCPConfiguration": "mcp_client", + "VectorStoreConfig": "mcp_client", + "RAGConfig": "mcp_client", + "load_mcp_config": "mcp_client", +} + +KEEP_ON_MODELS: set[str] = { + "GenerateRequest", + "ConfirmRequest", + "DEFAULT_TOOL_CATEGORIES", + "Metadata", + "PROVIDERS", +} + + +def migrate_file(path: Path) -> tuple[int, list[str]]: + """Rewrite 'from src.models import X' lines in path. Returns (count, errors).""" + try: + content = path.read_text(encoding="utf-8") + except (OSError, UnicodeDecodeError) as e: + return 0, [f" {path}: cannot read: {e}"] + original = content + errors: list[str] = [] + + pattern = re.compile(r"^(\s*)from\s+src\.models\s+import\s+(.+?)$", re.MULTILINE) + + def replace(m: re.Match[str]) -> str: + indent = m.group(1) + names_str = m.group(2) + names = [n.strip() for n in names_str.split(",")] + kept: list[str] = [] + moved: dict[str, list[str]] = {} + for name in names: + if not name: + continue + if name in KEEP_ON_MODELS: + kept.append(name) + continue + if " as " in name: + orig, alias = [s.strip() for s in name.split(" as ", 1)] + if orig in KEEP_ON_MODELS: + kept.append(name) + continue + if orig in CLASS_TO_MODULE: + target_mod = CLASS_TO_MODULE[orig] + moved.setdefault(target_mod, []).append(name) + else: + errors.append(f" {path}: unknown alias '{name}' (orig={orig})") + kept.append(name) + continue + if name in CLASS_TO_MODULE: + target_mod = CLASS_TO_MODULE[name] + moved.setdefault(target_mod, []).append(name) + else: + errors.append(f" {path}: unknown class '{name}'") + kept.append(name) + if not moved and kept == names: + return m.group(0) + lines: list[str] = [] + for mod, names_in_mod in sorted(moved.items()): + lines.append(f"{indent}from src.{mod} import {', '.join(names_in_mod)}") + if kept: + lines.append(f"{indent}from src.models import {', '.join(kept)}") + return "\n".join(lines) + + new_content = pattern.sub(replace, content) + if new_content != original: + try: + path.write_text(new_content, encoding="utf-8", newline="") + except OSError as e: + return 0, [f" {path}: cannot write: {e}"] + return len(pattern.findall(original)), [] + return 0, [] + + +def main() -> int: + root = Path(".") + src_files = sorted(root.glob("src/*.py")) + sorted(root.glob("tests/*.py")) + total_changed = 0 + files_changed = 0 + all_errors: list[str] = [] + for path in src_files: + count, errors = migrate_file(path) + all_errors.extend(errors) + if count > 0: + files_changed += 1 + total_changed += count + print(f" {path}: {count} import line(s) rewritten") + print(f"\nTotal: {total_changed} import line(s) rewritten in {files_changed} file(s)") + if all_errors: + print("\nWarnings:") + for err in all_errors: + print(err) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/ai_client.py b/src/ai_client.py index 8699c6de..917644a7 100644 --- a/src/ai_client.py +++ b/src/ai_client.py @@ -49,7 +49,9 @@ from src.vendor_capabilities import VendorCapabilities, get_capabilities # TODO(Ed): Eliminate these? from src.events import EventEmitter from src.gemini_cli_adapter import GeminiCliAdapter -from src.models import FileItem, ToolPreset, BiasProfile, Tool +from src.project_files import FileItem +from src.tool_bias import BiasProfile +from src.tool_presets import ToolPreset, Tool from src.paths import get_credentials_path from src.tool_bias import ToolBiasEngine from src.tool_presets import ToolPresetManager @@ -2561,7 +2563,7 @@ def _send_grok(md_content: str, user_message: str, base_dir: str, if file_items: for fi in file_items: if fi.get("is_image") and fi.get("base64_data"): - from src.models import FileItem as _FIC + from src.project_files import FileItem as _FIC fi_item = fi if isinstance(fi, _FIC) else _FIC.from_dict(fi) user_content = f"[IMAGE: {fi_item.path or 'attachment'}]\n{user_content}" if discussion_history and not history: @@ -2805,7 +2807,7 @@ def _send_qwen(md_content: str, user_message: str, base_dir: str, if file_items: for fi in file_items: if fi.get("is_image") and fi.get("base64_data"): - from src.models import FileItem as _FIC + from src.project_files import FileItem as _FIC fi_item = fi if isinstance(fi, _FIC) else _FIC.from_dict(fi) user_content = f"[IMAGE: {fi_item.path or 'attachment'}]\n{user_content}" if discussion_history and not history: @@ -2898,7 +2900,7 @@ def _send_llama(md_content: str, user_message: str, base_dir: str, if file_items: for fi in file_items: if fi.get("is_image") and fi.get("base64_data"): - from src.models import FileItem as _FIC + from src.project_files import FileItem as _FIC fi_item = fi if isinstance(fi, _FIC) else _FIC.from_dict(fi) user_content = f"[IMAGE: {fi_item.path or 'attachment'}]\n{user_content}" if discussion_history and not history: diff --git a/src/conductor_tech_lead.py b/src/conductor_tech_lead.py index d241370c..4bd65ae1 100644 --- a/src/conductor_tech_lead.py +++ b/src/conductor_tech_lead.py @@ -101,7 +101,7 @@ def generate_tickets(track_brief: str, module_skeletons: str) -> list[dict[str, ai_client.set_current_tier(None) from src.dag_engine import TrackDAG -from src.models import Ticket +from src.mma import Ticket from src.result_types import ErrorInfo, ErrorKind, Result def topological_sort(tickets: list[Ticket]) -> list[Ticket]: diff --git a/src/context_presets.py b/src/context_presets.py index 2265f457..1e650f9f 100644 --- a/src/context_presets.py +++ b/src/context_presets.py @@ -1,6 +1,6 @@ from typing import Dict, Any -from src.models import ContextPreset +from src.project_files import ContextPreset from src.result_types import Result, ErrorInfo, ErrorKind diff --git a/src/dag_engine.py b/src/dag_engine.py index ddba8ad4..cffe0cbc 100644 --- a/src/dag_engine.py +++ b/src/dag_engine.py @@ -28,7 +28,7 @@ See Also: """ from typing import List -from src.models import Ticket +from src.mma import Ticket from src.performance_monitor import get_monitor diff --git a/src/external_editor.py b/src/external_editor.py index 774e1891..46c46434 100644 --- a/src/external_editor.py +++ b/src/external_editor.py @@ -9,7 +9,7 @@ import tempfile from pathlib import Path from typing import Optional, List, Dict, Any -from src.models import ExternalEditorConfig, TextEditorConfig +from src.external_editor import ExternalEditorConfig, TextEditorConfig from src.result_types import ErrorInfo, ErrorKind, Result @@ -24,7 +24,7 @@ class ExternalEditorLauncher: """ [C: tests/test_external_editor.py:TestExternalEditorLauncher.test_get_editor_by_name, tests/test_external_editor.py:TestExternalEditorLauncher.test_get_editor_returns_default, tests/test_external_editor.py:TestExternalEditorLauncher.test_get_editor_unknown_name] """ - from src.models import EMPTY_TEXT_EDITOR_CONFIG + from src.external_editor import EMPTY_TEXT_EDITOR_CONFIG if editor_name: return self.config.editors.get(editor_name) or EMPTY_TEXT_EDITOR_CONFIG return self.config.get_default() @@ -96,7 +96,7 @@ def _find_vscode_common_paths() -> str: def auto_detect_vscode() -> TextEditorConfig: - from src.models import EMPTY_TEXT_EDITOR_CONFIG + from src.external_editor import EMPTY_TEXT_EDITOR_CONFIG global _cached_vscode_config if _cached_vscode_config is not None: return _cached_vscode_config diff --git a/src/multi_agent_conductor.py b/src/multi_agent_conductor.py index b94211f8..abc5a9ba 100644 --- a/src/multi_agent_conductor.py +++ b/src/multi_agent_conductor.py @@ -44,7 +44,7 @@ from src import paths from src import summarize from src.dag_engine import TrackDAG, ExecutionEngine -from src.models import Ticket, Track, WorkerContext +from src.mma import Ticket, Track, WorkerContext from src.personas import PersonaManager from src.result_types import ErrorInfo, ErrorKind, Result diff --git a/src/orchestrator_pm.py b/src/orchestrator_pm.py index 80dbbbf9..793e3690 100644 --- a/src/orchestrator_pm.py +++ b/src/orchestrator_pm.py @@ -8,7 +8,7 @@ from src import ai_client from src import mma_prompts from src import paths from src import summarize -from src.models import FileItem +from src.project_files import FileItem from src.result_types import Result, ErrorInfo, ErrorKind from src.type_aliases import Metadata diff --git a/src/personas.py b/src/personas.py index 574c8d40..35c6bb30 100644 --- a/src/personas.py +++ b/src/personas.py @@ -4,7 +4,7 @@ import tomli_w from pathlib import Path from typing import Dict, Any, Optional -from src.models import Persona +from src.personas import Persona from src import paths class PersonaManager: diff --git a/src/presets.py b/src/presets.py index 679848b5..93ec07a1 100644 --- a/src/presets.py +++ b/src/presets.py @@ -5,7 +5,7 @@ import tomli_w from pathlib import Path from typing import Dict, Any, Optional -from src.models import Preset +from src.project_files import Preset from src.paths import get_global_presets_path, get_project_presets_path from src.result_types import ErrorInfo, ErrorKind, Result diff --git a/src/project_manager.py b/src/project_manager.py index c59f198d..ba4c842c 100644 --- a/src/project_manager.py +++ b/src/project_manager.py @@ -32,7 +32,7 @@ from src.type_aliases import ( ) if TYPE_CHECKING: - from src.models import TrackState + from src.mma import TrackState TS_FMT: str = "%Y-%m-%dT%H:%M:%S" @@ -270,7 +270,7 @@ def flat_config(proj: Metadata, disc_name: Optional[str] = None, track_id: Optio The returned dataclass supports dict-compat (__getitem__ / get) so existing consumers using .get() and [] continue to work unchanged (Phase 2 Option A per SPEC_CORRECTION_phase_2.md).""" - from src.models import ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles, ProjectScreenshots, ProjectDiscussion + from src.project import ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles, ProjectScreenshots, ProjectDiscussion disc_sec = proj.get("discussion", {}) if track_id: history = load_track_history(track_id, proj.get("files", {}).get("base_dir", ".")) @@ -321,7 +321,7 @@ def load_track_state(track_id: str, base_dir: Union[str, Path] = ".") -> "TrackS Returns empty TrackState (zero-init) if not found. [C: tests/test_track_state_persistence.py:test_track_state_persistence] """ - from src.models import TrackState, EMPTY_TRACK_STATE + from src.mma import TrackState, EMPTY_TRACK_STATE state_file = paths.get_track_state_dir(track_id, project_path=str(base_dir)) / 'state.toml' if not state_file.exists(): return EMPTY_TRACK_STATE try: diff --git a/src/thinking_parser.py b/src/thinking_parser.py index 901c6c0f..c2ca1d52 100644 --- a/src/thinking_parser.py +++ b/src/thinking_parser.py @@ -2,7 +2,7 @@ import re from typing import List, Tuple -from src.models import ThinkingSegment +from src.mma import ThinkingSegment def parse_thinking_trace(text: str) -> Tuple[List[ThinkingSegment], str]: diff --git a/src/tool_bias.py b/src/tool_bias.py index 7fe38fc6..48f4e1ca 100644 --- a/src/tool_bias.py +++ b/src/tool_bias.py @@ -1,6 +1,8 @@ from typing import List, Dict, Any, Optional -from src.models import Tool, ToolPreset, BiasProfile +from src.tool_bias import BiasProfile + +from src.tool_presets import Tool, ToolPreset class ToolBiasEngine: diff --git a/src/tool_presets.py b/src/tool_presets.py index 708a2aeb..d4e3e40c 100644 --- a/src/tool_presets.py +++ b/src/tool_presets.py @@ -5,7 +5,8 @@ from pathlib import Path from typing import Dict, List, Optional, Union, Any from src import paths -from src.models import ToolPreset, BiasProfile +from src.tool_bias import BiasProfile +from src.tool_presets import ToolPreset class ToolPresetManager: diff --git a/src/workspace_manager.py b/src/workspace_manager.py index cfa2a58b..4ea5ad37 100644 --- a/src/workspace_manager.py +++ b/src/workspace_manager.py @@ -4,7 +4,7 @@ import tomli_w from pathlib import Path from typing import Dict, Any, Optional, Union -from src.models import WorkspaceProfile +from src.workspace_manager import WorkspaceProfile from src import paths diff --git a/tests/test_arch_boundary_phase3.py b/tests/test_arch_boundary_phase3.py index c5ce6af0..13e647fe 100644 --- a/tests/test_arch_boundary_phase3.py +++ b/tests/test_arch_boundary_phase3.py @@ -7,7 +7,7 @@ class TestArchBoundaryPhase3(unittest.TestCase): pass def test_cascade_blocks_simple(self) -> None: """Test that a blocked dependency blocks its immediate dependent.""" - from src.models import Ticket, Track + from src.mma import Ticket, Track t1 = Ticket(id="T1", description="d1", status="blocked", assigned_to="worker1") t2 = Ticket(id="T2", description="d2", status="todo", assigned_to="worker1", depends_on=["T1"]) track = Track(id="TR1", description="track", tickets=[t1, t2]) @@ -20,7 +20,7 @@ class TestArchBoundaryPhase3(unittest.TestCase): self.assertIn("T1", t2.blocked_reason) def test_cascade_blocks_multi_hop(self) -> None: """Test that blocking cascades through multiple dependencies.""" - from src.models import Ticket + from src.mma import Ticket from src.dag_engine import TrackDAG, ExecutionEngine t1 = Ticket(id="T1", description="d1", status="blocked", assigned_to="worker1") t2 = Ticket(id="T2", description="d2", status="todo", assigned_to="worker1", depends_on=["T1"]) @@ -32,7 +32,7 @@ class TestArchBoundaryPhase3(unittest.TestCase): self.assertEqual(t3.status, "blocked") def test_manual_unblock_restores_todo(self) -> None: """Test that unblocking a task manually works if dependencies are met.""" - from src.models import Ticket + from src.mma import Ticket from src.dag_engine import TrackDAG, ExecutionEngine t1 = Ticket(id="T1", description="d1", status="completed", assigned_to="worker1") t2 = Ticket(id="T2", description="d2", status="blocked", assigned_to="worker1", blocked_reason="manual") @@ -44,7 +44,7 @@ class TestArchBoundaryPhase3(unittest.TestCase): self.assertIn(t2, ready) def test_in_progress_not_blocked(self) -> None: """Test that in_progress tasks are not blocked automatically (only todo).""" - from src.models import Ticket + from src.mma import Ticket from src.dag_engine import TrackDAG, ExecutionEngine t1 = Ticket(id="T1", description="d1", status="blocked", assigned_to="worker1") t2 = Ticket(id="T2", description="d2", status="in_progress", assigned_to="worker1", depends_on=["T1"]) @@ -54,7 +54,7 @@ class TestArchBoundaryPhase3(unittest.TestCase): self.assertEqual(t2.status, "in_progress") def test_execution_engine_tick_cascades_blocks(self) -> None: """Test that ExecutionEngine.tick() triggers the cascading blocks.""" - from src.models import Ticket + from src.mma import Ticket from src.dag_engine import TrackDAG, ExecutionEngine t1 = Ticket(id="T1", description="d1", status="blocked", assigned_to="worker1") t2 = Ticket(id="T2", description="d2", status="todo", assigned_to="worker1", depends_on=["T1"]) diff --git a/tests/test_bias_efficacy.py b/tests/test_bias_efficacy.py index 9710b864..9e90c22d 100644 --- a/tests/test_bias_efficacy.py +++ b/tests/test_bias_efficacy.py @@ -1,6 +1,7 @@ import pytest from src import ai_client -from src.models import ToolPreset, Tool, BiasProfile +from src.tool_bias import BiasProfile +from src.tool_presets import ToolPreset, Tool from unittest.mock import MagicMock, patch def test_bias_efficacy_prompt_generation(): diff --git a/tests/test_bias_integration.py b/tests/test_bias_integration.py index ade4989b..1c33a2d7 100644 --- a/tests/test_bias_integration.py +++ b/tests/test_bias_integration.py @@ -1,6 +1,7 @@ import pytest from src import ai_client -from src.models import ToolPreset, Tool, BiasProfile +from src.tool_bias import BiasProfile +from src.tool_presets import ToolPreset, Tool from unittest.mock import MagicMock, patch def test_system_prompt_biasing(): diff --git a/tests/test_bias_models.py b/tests/test_bias_models.py index e7e547f4..e7eeac50 100644 --- a/tests/test_bias_models.py +++ b/tests/test_bias_models.py @@ -1,5 +1,6 @@ import pytest -from src.models import Tool, ToolPreset, BiasProfile +from src.tool_bias import BiasProfile +from src.tool_presets import Tool, ToolPreset def test_tool_model(): tool = Tool(name="read_file", weight=5, parameter_bias={"path": "preferred"}) diff --git a/tests/test_conductor_abort_event.py b/tests/test_conductor_abort_event.py index 2528b912..09f72d2a 100644 --- a/tests/test_conductor_abort_event.py +++ b/tests/test_conductor_abort_event.py @@ -1,7 +1,7 @@ import pytest from unittest.mock import MagicMock, patch from src.multi_agent_conductor import ConductorEngine -from src.models import Ticket, Track +from src.mma import Ticket, Track import threading def test_conductor_abort_event_populated(): diff --git a/tests/test_conductor_engine_abort.py b/tests/test_conductor_engine_abort.py index bfa1ec60..6ec4a455 100644 --- a/tests/test_conductor_engine_abort.py +++ b/tests/test_conductor_engine_abort.py @@ -3,7 +3,7 @@ from unittest.mock import MagicMock import threading import time from src.multi_agent_conductor import ConductorEngine -from src.models import Track +from src.mma import Track def test_conductor_engine_initializes_empty_worker_and_abort_dicts() -> None: """ diff --git a/tests/test_conductor_engine_v2.py b/tests/test_conductor_engine_v2.py index ecfaa2a7..51e22c45 100644 --- a/tests/test_conductor_engine_v2.py +++ b/tests/test_conductor_engine_v2.py @@ -4,7 +4,7 @@ They MUST NOT be simplified, and their assertions on exact call counts and depen """ import pytest from unittest.mock import MagicMock, patch -from src.models import Ticket, Track, WorkerContext +from src.mma import Ticket, Track, WorkerContext from src import ai_client from src.result_types import Result diff --git a/tests/test_conductor_tech_lead.py b/tests/test_conductor_tech_lead.py index 26fd8fa6..5f792a94 100644 --- a/tests/test_conductor_tech_lead.py +++ b/tests/test_conductor_tech_lead.py @@ -1,7 +1,7 @@ import unittest from unittest.mock import patch from src import conductor_tech_lead -from src.models import Ticket +from src.mma import Ticket from src.result_types import Result import pytest diff --git a/tests/test_context_composition_decoupled.py b/tests/test_context_composition_decoupled.py index 3851007f..d48a5e62 100644 --- a/tests/test_context_composition_decoupled.py +++ b/tests/test_context_composition_decoupled.py @@ -1,7 +1,7 @@ import pytest from pathlib import Path from src.app_controller import AppController -from src.models import FileItem +from src.project_files import FileItem def test_context_files_is_decoupled(): controller = AppController() diff --git a/tests/test_context_composition_phase3.py b/tests/test_context_composition_phase3.py index 053fb836..e060a950 100644 --- a/tests/test_context_composition_phase3.py +++ b/tests/test_context_composition_phase3.py @@ -1,6 +1,6 @@ import pytest from src.aggregate import group_files_by_dir, compute_file_stats -from src.models import FileItem +from src.project_files import FileItem def test_group_files_by_dir(): files = [ diff --git a/tests/test_context_composition_phase4.py b/tests/test_context_composition_phase4.py index ea6d0486..bbf22d7c 100644 --- a/tests/test_context_composition_phase4.py +++ b/tests/test_context_composition_phase4.py @@ -1,6 +1,6 @@ import pytest from src.gui_2 import App -from src.models import FileItem +from src.project_files import FileItem def test_view_mode_initialization(): app = App() diff --git a/tests/test_context_presets.py b/tests/test_context_presets.py index 437fb940..255bb71f 100644 --- a/tests/test_context_presets.py +++ b/tests/test_context_presets.py @@ -1,6 +1,6 @@ import pytest from src.context_presets import ContextPresetManager -from src.models import ContextPreset, ContextFileEntry +from src.project_files import ContextPreset, ContextFileEntry def test_save_context_preset(): manager = ContextPresetManager() diff --git a/tests/test_context_presets_manager.py b/tests/test_context_presets_manager.py index 3e1805e0..38865127 100644 --- a/tests/test_context_presets_manager.py +++ b/tests/test_context_presets_manager.py @@ -1,6 +1,6 @@ import pytest from src.context_presets import ContextPresetManager -from src.models import ContextPreset, ContextFileEntry +from src.project_files import ContextPreset, ContextFileEntry from src.app_controller import AppController from pathlib import Path import tomli_w diff --git a/tests/test_context_presets_models.py b/tests/test_context_presets_models.py index 684b6fce..d8c9d9d5 100644 --- a/tests/test_context_presets_models.py +++ b/tests/test_context_presets_models.py @@ -1,5 +1,5 @@ import pytest -from src.models import ContextPreset, ContextFileEntry +from src.project_files import ContextPreset, ContextFileEntry def test_context_file_entry_serialization(): p = ContextFileEntry(path="test.py", view_mode="skeleton") diff --git a/tests/test_context_preview_button.py b/tests/test_context_preview_button.py index 104d9eb8..639e29f2 100644 --- a/tests/test_context_preview_button.py +++ b/tests/test_context_preview_button.py @@ -2,7 +2,7 @@ import pytest from unittest.mock import Mock from pathlib import Path from src.gui_2 import App -from src.models import FileItem +from src.project_files import FileItem def test_preview_button_syncs_context_files_to_controller(): app = Mock(spec=App) @@ -51,7 +51,7 @@ def test_preview_generates_nonempty_for_real_files(monkeypatch): """Integration test: Preview button should generate content when context_files has real FileItems.""" import src.project_manager as pm import src.aggregate as agg - from src.models import FileItem + from src.project_files import FileItem app = Mock(spec=App) test_file = FileItem(path='tests/test_context_composition_decoupled.py', view_mode='summary') diff --git a/tests/test_context_pruner.py b/tests/test_context_pruner.py index ba072df1..05d84ea8 100644 --- a/tests/test_context_pruner.py +++ b/tests/test_context_pruner.py @@ -2,7 +2,7 @@ import pytest import time from pathlib import Path from src.file_cache import ASTParser -from src.models import Ticket, Track, WorkerContext +from src.mma import Ticket, Track, WorkerContext from src.multi_agent_conductor import run_worker_lifecycle from src.result_types import Result diff --git a/tests/test_custom_slices_annotations.py b/tests/test_custom_slices_annotations.py index 1c307b7b..59938e92 100644 --- a/tests/test_custom_slices_annotations.py +++ b/tests/test_custom_slices_annotations.py @@ -1,5 +1,5 @@ import pytest -from src.models import FileItem +from src.project_files import FileItem def test_file_item_custom_slices_serialization_with_annotations(): # Test that FileItem correctly serializes custom_slices with tag and comment. diff --git a/tests/test_dag_engine.py b/tests/test_dag_engine.py index 5cc88d21..bdcebeb5 100644 --- a/tests/test_dag_engine.py +++ b/tests/test_dag_engine.py @@ -4,7 +4,7 @@ They MUST NOT be simplified. They ensure that dependency resolution, cycle detec and topological sorting work perfectly to prevent catastrophic orchestrator deadlocks. """ import pytest -from src.models import Ticket +from src.mma import Ticket from src.dag_engine import TrackDAG def test_get_ready_tasks_linear(): diff --git a/tests/test_execution_engine.py b/tests/test_execution_engine.py index 4dce77d3..b1e319f3 100644 --- a/tests/test_execution_engine.py +++ b/tests/test_execution_engine.py @@ -1,4 +1,4 @@ -from src.models import Ticket +from src.mma import Ticket from src.dag_engine import TrackDAG, ExecutionEngine def test_execution_engine_basic_flow(): diff --git a/tests/test_external_editor.py b/tests/test_external_editor.py index 1c85f971..113b008f 100644 --- a/tests/test_external_editor.py +++ b/tests/test_external_editor.py @@ -1,7 +1,7 @@ """Tests for external editor integration.""" import pytest from unittest.mock import patch, MagicMock -from src.models import TextEditorConfig, ExternalEditorConfig +from src.external_editor import TextEditorConfig, ExternalEditorConfig from src.external_editor import ( ExternalEditorLauncher, get_default_launcher, diff --git a/tests/test_file_item_model.py b/tests/test_file_item_model.py index 7008d56a..65a684cc 100644 --- a/tests/test_file_item_model.py +++ b/tests/test_file_item_model.py @@ -1,5 +1,5 @@ import pytest -from src.models import FileItem +from src.project_files import FileItem def test_file_item_fields(): """Test that FileItem exists and has correct default values.""" diff --git a/tests/test_gui_2_result.py b/tests/test_gui_2_result.py index afb87cab..90ccbf13 100644 --- a/tests/test_gui_2_result.py +++ b/tests/test_gui_2_result.py @@ -2315,7 +2315,7 @@ def test_phase_10_l7271_dag_cycle_check_result_no_cycle(): opening the "Cycle Detected!" popup. """ from unittest.mock import MagicMock, patch - from src.models import Ticket + from src.mma import Ticket import src.gui_2 as gui2_mod app = MagicMock() app.active_tickets = [Ticket(id="T-001", description="T-001", depends_on=[])] @@ -2335,7 +2335,7 @@ def test_phase_10_l7271_dag_cycle_check_result_cycle_detected(): returns Result(data=True). The caller opens the "Cycle Detected!" popup. """ from unittest.mock import MagicMock, patch - from src.models import Ticket + from src.mma import Ticket import src.gui_2 as gui2_mod app = MagicMock() app.active_tickets = [ diff --git a/tests/test_gui_phase4.py b/tests/test_gui_phase4.py index d36c16dd..fcab6d99 100644 --- a/tests/test_gui_phase4.py +++ b/tests/test_gui_phase4.py @@ -2,7 +2,7 @@ import pytest from unittest.mock import MagicMock, patch from src import gui_2 from src.gui_2 import App -from src.models import Track +from src.mma import Track @pytest.fixture(autouse=True) def setup_mock_app(mock_app: App): diff --git a/tests/test_gui_progress.py b/tests/test_gui_progress.py index 104351c6..e7623de7 100644 --- a/tests/test_gui_progress.py +++ b/tests/test_gui_progress.py @@ -2,7 +2,7 @@ import pytest from unittest.mock import MagicMock, patch from src import gui_2 from src.gui_2 import App, C_LBL, C_VAL -from src.models import Ticket +from src.mma import Ticket def test_render_mma_dashboard_progress(): # Create a mock for the imgui module used in gui_2 diff --git a/tests/test_headless_verification.py b/tests/test_headless_verification.py index 1cfe67b2..820c46e0 100644 --- a/tests/test_headless_verification.py +++ b/tests/test_headless_verification.py @@ -1,7 +1,7 @@ from typing import Any import pytest from unittest.mock import MagicMock, patch -from src.models import Ticket, Track +from src.mma import Ticket, Track from src import multi_agent_conductor from src.multi_agent_conductor import ConductorEngine from src import ai_client diff --git a/tests/test_manual_block.py b/tests/test_manual_block.py index fab80494..506b28f1 100644 --- a/tests/test_manual_block.py +++ b/tests/test_manual_block.py @@ -1,5 +1,5 @@ import pytest -from src.models import Ticket +from src.mma import Ticket def test_ticket_has_manual_block_field(): t = Ticket(id="T-001", description="Test") diff --git a/tests/test_metadata_promotion_phase1.py b/tests/test_metadata_promotion_phase1.py index dd690229..92fa3e89 100644 --- a/tests/test_metadata_promotion_phase1.py +++ b/tests/test_metadata_promotion_phase1.py @@ -10,7 +10,7 @@ Verifies: import inspect from unittest.mock import patch -from src.models import Ticket +from src.mma import Ticket class TestActiveTicketsType: @@ -58,7 +58,7 @@ class TestActiveTicketsLoadBoundaries: def test_load_active_tickets_beads_branch_converts_dicts_to_tickets(self) -> None: """_load_active_tickets (beads branch) must wrap bead dicts as models.Ticket.""" from src.app_controller import AppController - from src.models import Ticket + from src.mma import Ticket ctrl = AppController.__new__(AppController) ctrl._last_request_errors = [] ctrl.ui_project_execution_mode = "beads" diff --git a/tests/test_mma_models.py b/tests/test_mma_models.py index 4f88a21d..5aa5dfdc 100644 --- a/tests/test_mma_models.py +++ b/tests/test_mma_models.py @@ -1,4 +1,4 @@ -from src.models import Ticket, Track, WorkerContext +from src.mma import Ticket, Track, WorkerContext from src.dag_engine import get_executable_tickets def test_ticket_instantiation() -> None: diff --git a/tests/test_mma_ticket_actions.py b/tests/test_mma_ticket_actions.py index c3f8eb80..63988096 100644 --- a/tests/test_mma_ticket_actions.py +++ b/tests/test_mma_ticket_actions.py @@ -1,5 +1,5 @@ from src.gui_2 import App -from src.models import Ticket +from src.mma import Ticket def test_cb_ticket_retry(app_instance: App) -> None: ticket_id = "test_ticket_1" diff --git a/tests/test_orchestration_logic.py b/tests/test_orchestration_logic.py index 06b42794..84872dba 100644 --- a/tests/test_orchestration_logic.py +++ b/tests/test_orchestration_logic.py @@ -3,7 +3,7 @@ from unittest.mock import patch, MagicMock from src import orchestrator_pm from src import multi_agent_conductor from src import conductor_tech_lead -from src.models import Ticket, Track, WorkerContext +from src.mma import Ticket, Track, WorkerContext from src.result_types import Result def test_generate_tracks() -> None: diff --git a/tests/test_parallel_execution.py b/tests/test_parallel_execution.py index 44408f9f..d6b07729 100644 --- a/tests/test_parallel_execution.py +++ b/tests/test_parallel_execution.py @@ -67,7 +67,7 @@ def test_worker_pool_completion_cleanup(): assert "t1" not in pool._active from unittest.mock import patch -from src.models import Track, Ticket +from src.mma import Track, Ticket from src.multi_agent_conductor import ConductorEngine @patch('src.multi_agent_conductor.run_worker_lifecycle') diff --git a/tests/test_per_ticket_model.py b/tests/test_per_ticket_model.py index 5357e79a..3a05869b 100644 --- a/tests/test_per_ticket_model.py +++ b/tests/test_per_ticket_model.py @@ -1,5 +1,5 @@ import pytest -from src.models import Ticket +from src.mma import Ticket def test_ticket_has_model_override_field(): t = Ticket(id="T-001", description="Test") diff --git a/tests/test_perf_dag.py b/tests/test_perf_dag.py index 68e93355..bed37ad3 100644 --- a/tests/test_perf_dag.py +++ b/tests/test_perf_dag.py @@ -1,5 +1,5 @@ import pytest -from src.models import Ticket +from src.mma import Ticket from src.dag_engine import TrackDAG from src.performance_monitor import get_monitor diff --git a/tests/test_persona_id.py b/tests/test_persona_id.py index c5470ebc..1ff6bbf8 100644 --- a/tests/test_persona_id.py +++ b/tests/test_persona_id.py @@ -1,5 +1,5 @@ import pytest -from src.models import Ticket, WorkerContext +from src.mma import Ticket, WorkerContext def test_ticket_persona_id_serialization(): diff --git a/tests/test_persona_manager.py b/tests/test_persona_manager.py index efc17cb7..b7507825 100644 --- a/tests/test_persona_manager.py +++ b/tests/test_persona_manager.py @@ -1,7 +1,7 @@ import pytest import tomli_w from pathlib import Path -from src.models import Persona +from src.personas import Persona from src.personas import PersonaManager from src import paths diff --git a/tests/test_persona_models.py b/tests/test_persona_models.py index 3a91896f..23ab0cdd 100644 --- a/tests/test_persona_models.py +++ b/tests/test_persona_models.py @@ -1,5 +1,5 @@ import pytest -from src.models import Persona +from src.personas import Persona def test_persona_serialization(): persona = Persona( diff --git a/tests/test_phase6_engine.py b/tests/test_phase6_engine.py index 5921a363..9fbddee9 100644 --- a/tests/test_phase6_engine.py +++ b/tests/test_phase6_engine.py @@ -1,6 +1,6 @@ from unittest.mock import MagicMock, patch from src.multi_agent_conductor import ConductorEngine, run_worker_lifecycle -from src.models import Ticket, Track, WorkerContext +from src.mma import Ticket, Track, WorkerContext from src import ai_client from src.result_types import Result diff --git a/tests/test_pipeline_pause.py b/tests/test_pipeline_pause.py index b454000f..21fe4742 100644 --- a/tests/test_pipeline_pause.py +++ b/tests/test_pipeline_pause.py @@ -1,6 +1,6 @@ import pytest from unittest.mock import MagicMock, patch -from src.models import Ticket, Track +from src.mma import Ticket, Track from src.multi_agent_conductor import ConductorEngine def test_conductor_engine_has_pause_event(): diff --git a/tests/test_preset_manager.py b/tests/test_preset_manager.py index 0579f89e..4c9d59b0 100644 --- a/tests/test_preset_manager.py +++ b/tests/test_preset_manager.py @@ -1,7 +1,7 @@ import pytest from pathlib import Path from src.presets import PresetManager -from src.models import Preset +from src.project_files import Preset def test_load_all_merged(tmp_path, monkeypatch): """Tests that load_all correctly merges global and project presets.""" diff --git a/tests/test_presets.py b/tests/test_presets.py index 4bb663ef..646a1d1f 100644 --- a/tests/test_presets.py +++ b/tests/test_presets.py @@ -4,7 +4,7 @@ from pathlib import Path import tempfile import shutil from src.presets import PresetManager -from src.models import Preset +from src.project_files import Preset class TestPresetManager(unittest.TestCase): def setUp(self): diff --git a/tests/test_progress_viz.py b/tests/test_progress_viz.py index f754f49a..ba81b3cd 100644 --- a/tests/test_progress_viz.py +++ b/tests/test_progress_viz.py @@ -1,6 +1,6 @@ import pytest from src.project_manager import calculate_track_progress -from src.models import Ticket +from src.mma import Ticket def test_calculate_track_progress_empty(): results = calculate_track_progress([]) diff --git a/tests/test_project_manager_tracks.py b/tests/test_project_manager_tracks.py index 2b919592..7faced16 100644 --- a/tests/test_project_manager_tracks.py +++ b/tests/test_project_manager_tracks.py @@ -2,7 +2,8 @@ import pytest from typing import Any import json from src.project_manager import get_all_tracks, save_track_state -from src.models import TrackState, Metadata, Ticket +from src.mma import TrackState, Ticket +from src.models import Metadata from datetime import datetime def test_get_all_tracks_empty(tmp_path: Any) -> None: diff --git a/tests/test_rag_sync_none_error.py b/tests/test_rag_sync_none_error.py index cab328ce..40cabb8b 100644 --- a/tests/test_rag_sync_none_error.py +++ b/tests/test_rag_sync_none_error.py @@ -5,7 +5,7 @@ import tempfile import pytest from src.rag_engine import RAGEngine -from src.models import RAGConfig, VectorStoreConfig +from src.mcp_client import RAGConfig, VectorStoreConfig LOCAL_EMBED_DIM = 384 diff --git a/tests/test_run_worker_lifecycle_abort.py b/tests/test_run_worker_lifecycle_abort.py index 68cfdcd7..cb1fb388 100644 --- a/tests/test_run_worker_lifecycle_abort.py +++ b/tests/test_run_worker_lifecycle_abort.py @@ -4,7 +4,7 @@ import threading import json import time from src.multi_agent_conductor import run_worker_lifecycle -from src.models import Ticket, WorkerContext +from src.mma import Ticket, WorkerContext class TestRunWorkerLifecycleAbort(unittest.TestCase): def test_run_worker_lifecycle_returns_early_on_abort(self): diff --git a/tests/test_slice_editor_behavior.py b/tests/test_slice_editor_behavior.py index 9418e049..b97f05f5 100644 --- a/tests/test_slice_editor_behavior.py +++ b/tests/test_slice_editor_behavior.py @@ -1,5 +1,5 @@ import pytest -from src.models import FileItem +from src.project_files import FileItem from src.fuzzy_anchor import FuzzyAnchor def test_add_slice_with_annotations(): diff --git a/tests/test_spawn_interception_v2.py b/tests/test_spawn_interception_v2.py index a90df318..d734fbde 100644 --- a/tests/test_spawn_interception_v2.py +++ b/tests/test_spawn_interception_v2.py @@ -1,7 +1,7 @@ import pytest from unittest.mock import MagicMock, patch from src import multi_agent_conductor -from src.models import Ticket, WorkerContext +from src.mma import Ticket, WorkerContext from src import events from src.result_types import Result import threading diff --git a/tests/test_thinking_gui.py b/tests/test_thinking_gui.py index ecb27a56..7bc9fac2 100644 --- a/tests/test_thinking_gui.py +++ b/tests/test_thinking_gui.py @@ -32,7 +32,7 @@ def test_discussion_entry_without_thinking(): def test_thinking_segment_model_compatibility(): - from src.models import ThinkingSegment + from src.mma import ThinkingSegment segment = ThinkingSegment(content="test", marker="thinking") assert segment.content == "test" diff --git a/tests/test_thinking_persistence.py b/tests/test_thinking_persistence.py index fa10ff79..b0d3a385 100644 --- a/tests/test_thinking_persistence.py +++ b/tests/test_thinking_persistence.py @@ -3,7 +3,7 @@ import tempfile import os from pathlib import Path from src import project_manager -from src.models import ThinkingSegment +from src.mma import ThinkingSegment def test_save_and_load_history_with_thinking_segments(): diff --git a/tests/test_ticket_queue.py b/tests/test_ticket_queue.py index f28e6660..90f58dbc 100644 --- a/tests/test_ticket_queue.py +++ b/tests/test_ticket_queue.py @@ -1,6 +1,6 @@ import pytest from unittest.mock import patch -from src.models import Ticket +from src.mma import Ticket def test_ticket_priority_default(): ticket = Ticket(id="T1", description="Test ticket") diff --git a/tests/test_tiered_aggregation.py b/tests/test_tiered_aggregation.py index 0adec02f..e5743cd2 100644 --- a/tests/test_tiered_aggregation.py +++ b/tests/test_tiered_aggregation.py @@ -1,5 +1,6 @@ import pytest -from src.models import Persona, Ticket, WorkerContext +from src.mma import Ticket, WorkerContext +from src.personas import Persona from src import multi_agent_conductor from src import app_controller from src import aggregate diff --git a/tests/test_tool_bias.py b/tests/test_tool_bias.py index 3842bf0f..34414590 100644 --- a/tests/test_tool_bias.py +++ b/tests/test_tool_bias.py @@ -1,6 +1,7 @@ import pytest from src.tool_bias import ToolBiasEngine -from src.models import ToolPreset, Tool, BiasProfile +from src.tool_bias import BiasProfile +from src.tool_presets import ToolPreset, Tool def test_apply_semantic_nudges(): engine = ToolBiasEngine() diff --git a/tests/test_tool_preset_manager.py b/tests/test_tool_preset_manager.py index b1e38262..91699828 100644 --- a/tests/test_tool_preset_manager.py +++ b/tests/test_tool_preset_manager.py @@ -2,7 +2,8 @@ import pytest import tomli_w from pathlib import Path from src.tool_presets import ToolPresetManager -from src.models import ToolPreset, BiasProfile, Tool +from src.tool_bias import BiasProfile +from src.tool_presets import ToolPreset, Tool from src import paths @pytest.fixture diff --git a/tests/test_tool_presets_execution.py b/tests/test_tool_presets_execution.py index 076a530e..dcdfedec 100644 --- a/tests/test_tool_presets_execution.py +++ b/tests/test_tool_presets_execution.py @@ -3,7 +3,7 @@ import asyncio from src import ai_client from src import mcp_client from src import models -from src.models import ToolPreset, Tool +from src.tool_presets import ToolPreset, Tool from unittest.mock import MagicMock, patch @pytest.mark.asyncio diff --git a/tests/test_track_state_persistence.py b/tests/test_track_state_persistence.py index 3db453c9..79d7f3bb 100644 --- a/tests/test_track_state_persistence.py +++ b/tests/test_track_state_persistence.py @@ -1,7 +1,8 @@ from datetime import datetime # Import the real models -from src.models import TrackState, Metadata, Ticket +from src.mma import TrackState, Ticket +from src.models import Metadata # Import the persistence functions from project_manager from src.project_manager import save_track_state, load_track_state diff --git a/tests/test_track_state_schema.py b/tests/test_track_state_schema.py index b85405f5..33fe30a2 100644 --- a/tests/test_track_state_schema.py +++ b/tests/test_track_state_schema.py @@ -1,7 +1,8 @@ from datetime import datetime, timezone, timedelta # Import necessary classes from models.py -from src.models import Metadata, TrackState, Ticket +from src.mma import TrackState, Ticket +from src.models import Metadata # --- Pytest Tests --- diff --git a/tests/test_workspace_manager.py b/tests/test_workspace_manager.py index 37c6d2aa..b4a299d2 100644 --- a/tests/test_workspace_manager.py +++ b/tests/test_workspace_manager.py @@ -1,7 +1,7 @@ import pytest from pathlib import Path from src.workspace_manager import WorkspaceManager -from src.models import WorkspaceProfile +from src.workspace_manager import WorkspaceProfile from src import paths def test_load_all_profiles_merged(tmp_path, monkeypatch): diff --git a/tests/test_workspace_profile_serialization.py b/tests/test_workspace_profile_serialization.py index e9a150cd..ccd0732d 100644 --- a/tests/test_workspace_profile_serialization.py +++ b/tests/test_workspace_profile_serialization.py @@ -2,7 +2,7 @@ import io import tomllib import pytest import tomli_w -from src.models import WorkspaceProfile +from src.workspace_manager import WorkspaceProfile def test_workspace_profile_empty_ini_content_roundtrips():