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.
125 lines
4.7 KiB
Python
125 lines
4.7 KiB
Python
"""
|
|
ANTI-SIMPLIFICATION: These tests verify the core Directed Acyclic Graph (DAG) execution engine logic.
|
|
They MUST NOT be simplified. They ensure that dependency resolution, cycle detection,
|
|
and topological sorting work perfectly to prevent catastrophic orchestrator deadlocks.
|
|
"""
|
|
import pytest
|
|
from src.mma import Ticket
|
|
from src.dag_engine import TrackDAG
|
|
|
|
def test_get_ready_tasks_linear():
|
|
"""
|
|
|
|
|
|
Verifies ready tasks detection in a simple linear dependency chain.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1")
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
dag = TrackDAG([t1, t2])
|
|
ready = dag.get_ready_tasks()
|
|
assert len(ready) == 1
|
|
assert ready[0].id == "T1"
|
|
|
|
def test_get_ready_tasks_branching():
|
|
"""
|
|
|
|
|
|
Verifies ready tasks detection in a branching dependency graph where multiple tasks
|
|
are unlocked simultaneously after a prerequisite is met.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="completed", assigned_to="worker1")
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
t3 = Ticket(id="T3", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
dag = TrackDAG([t1, t2, t3])
|
|
ready = dag.get_ready_tasks()
|
|
assert len(ready) == 2
|
|
ids = [t.id for t in ready]
|
|
assert "T2" in ids
|
|
assert "T3" in ids
|
|
|
|
def test_has_cycle_no_cycle():
|
|
"""
|
|
|
|
|
|
Validates that an acyclic graph is correctly identified as not having cycles.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1")
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
dag = TrackDAG([t1, t2])
|
|
assert dag.has_cycle() is False
|
|
|
|
def test_has_cycle_direct_cycle():
|
|
"""
|
|
|
|
|
|
Validates that a direct cycle (A depends on B, B depends on A) is correctly detected.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1", depends_on=["T2"])
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
dag = TrackDAG([t1, t2])
|
|
assert dag.has_cycle() is True
|
|
|
|
def test_has_cycle_indirect_cycle():
|
|
"""
|
|
|
|
|
|
Validates that an indirect cycle (A->B->C->A) is correctly detected.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1", depends_on=["T3"])
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
t3 = Ticket(id="T3", description="desc", status="todo", assigned_to="worker1", depends_on=["T2"])
|
|
dag = TrackDAG([t1, t2, t3])
|
|
assert dag.has_cycle() is True
|
|
|
|
def test_has_cycle_complex_no_cycle():
|
|
"""
|
|
|
|
|
|
Validates cycle detection in a complex graph that merges branches but remains acyclic.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1")
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
t3 = Ticket(id="T3", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
t4 = Ticket(id="T4", description="desc", status="todo", assigned_to="worker1", depends_on=["T2", "T3"])
|
|
dag = TrackDAG([t1, t2, t3, t4])
|
|
assert dag.has_cycle() is False
|
|
|
|
def test_get_ready_tasks_multiple_deps():
|
|
"""
|
|
|
|
|
|
Validates that a task is not marked ready until ALL of its dependencies are completed.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="completed", assigned_to="worker1")
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1")
|
|
t3 = Ticket(id="T3", description="desc", status="todo", assigned_to="worker1", depends_on=["T1", "T2"])
|
|
dag = TrackDAG([t1, t2, t3])
|
|
# Only T2 is ready because T3 depends on T2 (todo)
|
|
ready = dag.get_ready_tasks()
|
|
assert len(ready) == 1
|
|
assert ready[0].id == "T2"
|
|
|
|
def test_topological_sort():
|
|
"""
|
|
|
|
|
|
Verifies that tasks are correctly ordered by dependencies regardless of input order.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1")
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
dag = TrackDAG([t2, t1]) # Out of order input
|
|
sorted_tasks = dag.topological_sort()
|
|
# Topological sort returns list of IDs in current implementation
|
|
assert sorted_tasks == ["T1", "T2"]
|
|
|
|
def test_topological_sort_cycle():
|
|
"""
|
|
|
|
|
|
Verifies that topological sorting safely aborts and raises ValueError when a cycle is present.
|
|
"""
|
|
t1 = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1", depends_on=["T2"])
|
|
t2 = Ticket(id="T2", description="desc", status="todo", assigned_to="worker1", depends_on=["T1"])
|
|
dag = TrackDAG([t1, t2])
|
|
with pytest.raises(ValueError, match="Dependency cycle detected"):
|
|
dag.topological_sort() |