feat(sdm): inject structural dependency mapping tags across codebase

Adds [C: caller] tags to functions/methods and [M: mutation] / [U: usage] tags to class variables based on cross-module call analysis.
This commit is contained in:
2026-05-13 22:35:41 -04:00
parent 5bb3a9026f
commit b5e512f483
110 changed files with 1673 additions and 1008 deletions
+15 -10
View File
@@ -36,7 +36,7 @@ class VerificationLogger:
def log_state(self, field: str, before: Any, after: Any) -> None:
"""
[C: tests/test_ai_style_formatter.py:test_multiple_top_level_definitions, tests/test_conductor_engine_v2.py:test_conductor_engine_dynamic_parsing_and_execution, tests/test_conductor_engine_v2.py:test_conductor_engine_run_executes_tickets_in_order, tests/test_conductor_tech_lead.py:test_topological_sort_vlog, tests/test_headless_verification.py:test_headless_verification_error_and_qa_interceptor, tests/test_headless_verification.py:test_headless_verification_full_run, tests/test_tier4_interceptor.py:test_run_powershell_qa_callback_on_failure, tests/test_vlogger_availability.py:test_vlogger_available]
[C: tests/test_ai_style_formatter.py:test_multiple_top_level_definitions, tests/test_conductor_engine_v2.py:test_conductor_engine_dynamic_parsing_and_execution, tests/test_conductor_engine_v2.py:test_conductor_engine_run_executes_tickets_in_order, tests/test_conductor_tech_lead.py:test_topological_sort_vlog, tests/test_headless_verification.py:test_headless_verification_error_and_qa_interceptor, tests/test_headless_verification.py:test_headless_verification_full_run, tests/test_tier4_interceptor.py:test_run_powershell_qa_callback_on_failure, tests/test_vlogger_availability.py:test_vlogger_available]
"""
delta = ""
if isinstance(before, (int, float)) and isinstance(after, (int, float)):
@@ -51,7 +51,7 @@ class VerificationLogger:
def finalize(self, title: str, status: str, result_msg: str) -> None:
"""
[C: tests/test_ai_style_formatter.py:test_multiple_top_level_definitions, tests/test_conductor_engine_v2.py:test_conductor_engine_dynamic_parsing_and_execution, tests/test_conductor_engine_v2.py:test_conductor_engine_run_executes_tickets_in_order, tests/test_conductor_tech_lead.py:test_topological_sort_vlog, tests/test_headless_verification.py:test_headless_verification_error_and_qa_interceptor, tests/test_headless_verification.py:test_headless_verification_full_run, tests/test_tier4_interceptor.py:test_end_to_end_tier4_integration, tests/test_tier4_interceptor.py:test_run_powershell_qa_callback_on_failure, tests/test_tier4_interceptor.py:test_run_powershell_qa_callback_on_stderr_only, tests/test_vlogger_availability.py:test_vlogger_available]
[C: tests/test_ai_style_formatter.py:test_multiple_top_level_definitions, tests/test_conductor_engine_v2.py:test_conductor_engine_dynamic_parsing_and_execution, tests/test_conductor_engine_v2.py:test_conductor_engine_run_executes_tickets_in_order, tests/test_conductor_tech_lead.py:test_topological_sort_vlog, tests/test_headless_verification.py:test_headless_verification_error_and_qa_interceptor, tests/test_headless_verification.py:test_headless_verification_full_run, tests/test_tier4_interceptor.py:test_end_to_end_tier4_integration, tests/test_tier4_interceptor.py:test_run_powershell_qa_callback_on_failure, tests/test_tier4_interceptor.py:test_run_powershell_qa_callback_on_stderr_only, tests/test_vlogger_availability.py:test_vlogger_available]
"""
round(time.time() - self.start_time, 2)
log_file = self.logs_dir / f"{self.script_name}.txt"
@@ -71,7 +71,8 @@ class VerificationLogger:
def reset_paths() -> Generator[None, None, None]:
"""
Autouse fixture that resets the paths global state before each test.
Autouse fixture that resets the paths global state before each test.
"""
from src import paths
paths.reset_resolved()
@@ -82,8 +83,9 @@ def reset_paths() -> Generator[None, None, None]:
def reset_ai_client() -> Generator[None, None, None]:
"""
Autouse fixture that resets the ai_client global state before each test.
This is critical for preventing state pollution between tests.
Autouse fixture that resets the ai_client global state before each test.
This is critical for preventing state pollution between tests.
"""
from src import ai_client
from src import mcp_client
@@ -131,7 +133,8 @@ def kill_process_tree(pid: int | None) -> None:
def mock_app() -> Generator[App, None, None]:
"""
Mock version of the App for simple unit tests that don't need a loop.
Mock version of the App for simple unit tests that don't need a loop.
"""
with (
patch('src.models.load_config', return_value={
@@ -163,8 +166,9 @@ def mock_app() -> Generator[App, None, None]:
def app_instance() -> Generator[App, None, None]:
"""
Centralized App instance with all external side effects mocked.
Matches the pattern used in test_token_viz.py and test_gui_phase4.py.
Centralized App instance with all external side effects mocked.
Matches the pattern used in test_token_viz.py and test_gui_phase4.py.
[C: tests/test_gui2_events.py:test_app_subscribes_to_events]
"""
with (
@@ -199,8 +203,9 @@ def app_instance() -> Generator[App, None, None]:
def live_gui() -> Generator[tuple[subprocess.Popen, str], None, None]:
"""
Session-scoped fixture that starts sloppy.py with --enable-test-hooks.
Includes high-signal environment telemetry and workspace isolation.
Session-scoped fixture that starts sloppy.py with --enable-test-hooks.
Includes high-signal environment telemetry and workspace isolation.
"""
gui_script = os.path.abspath("sloppy.py")
diag = VerificationLogger("live_gui_startup", "live_gui_diag")
+2 -1
View File
@@ -10,7 +10,8 @@ from src.api_hook_client import ApiHookClient
def wait_for_value(client, field, expected, timeout=5):
"""
Polls the GUI state until a field matches the expected value.
Polls the GUI state until a field matches the expected value.
[C: tests/test_live_workflow.py:test_full_live_workflow]
"""
start = time.time()
+3 -2
View File
@@ -3,8 +3,9 @@ from src import ai_client
def test_list_models_gemini_cli() -> None:
"""
Verifies that 'ai_client.list_models' correctly returns a list of models
for the 'gemini_cli' provider.
Verifies that 'ai_client.list_models' correctly returns a list of models
for the 'gemini_cli' provider.
"""
models = ai_client.list_models("gemini_cli")
assert "gemini-3.1-pro-preview" in models
+4 -2
View File
@@ -37,7 +37,8 @@ def app_controller(tmp_session_dir):
def test_on_comms_entry_tool_result_offloading(app_controller, tmp_session_dir):
"""
Test that _on_comms_entry offloads tool_result output to a separate file.
Test that _on_comms_entry offloads tool_result output to a separate file.
"""
output_content = "This is a large tool output that should be offloaded."
entry = {
@@ -83,7 +84,8 @@ def test_on_comms_entry_tool_result_offloading(app_controller, tmp_session_dir):
def test_on_tool_log_offloading(app_controller, tmp_session_dir):
"""
Test that _on_tool_log calls session_logger.log_tool_call and log_tool_output.
Test that _on_tool_log calls session_logger.log_tool_call and log_tool_output.
"""
script = "Get-Process"
result = "Process list..."
+1 -1
View File
@@ -323,4 +323,4 @@ public:
assert 'void myMethod() {' in updated
assert 'int y = 2;' in updated
assert 'int x = 1;' not in updated
assert 'class MyClass {' in updated
assert 'class MyClass {' in updated
+6 -4
View File
@@ -9,8 +9,9 @@ from src import mcp_client
async def test_execute_tool_calls_concurrently_timing():
"""
Verifies that _execute_tool_calls_concurrently runs tools in parallel.
Total time should be approx 0.5s for 3 tools each taking 0.5s.
Verifies that _execute_tool_calls_concurrently runs tools in parallel.
Total time should be approx 0.5s for 3 tools each taking 0.5s.
"""
# 1. Setup mock tool calls (Gemini style)
class MockGeminiCall:
@@ -67,8 +68,9 @@ async def test_execute_tool_calls_concurrently_timing():
async def test_execute_tool_calls_concurrently_exception_handling():
"""
Verifies that if one tool call fails, it doesn't crash the whole group if caught,
but currently gather is used WITHOUT return_exceptions=True, so it should re-raise.
Verifies that if one tool call fails, it doesn't crash the whole group if caught,
but currently gather is used WITHOUT return_exceptions=True, so it should re-raise.
"""
class MockGeminiCall:
def __init__(self, name, args):
+3 -2
View File
@@ -22,8 +22,9 @@ class TestCliToolBridgeMapping(unittest.TestCase):
def test_mapping_from_api_format(self, mock_request: MagicMock, mock_stdout: MagicMock, mock_stdin: MagicMock) -> None:
"""
Verify that bridge correctly maps 'id', 'name', 'input' (Gemini API format)
into tool_name and tool_input for the hook client.
Verify that bridge correctly maps 'id', 'name', 'input' (Gemini API format)
into tool_name and tool_input for the hook client.
"""
api_tool_call = {
'id': 'call123',
+2 -1
View File
@@ -7,7 +7,8 @@ import threading
def test_conductor_abort_event_populated():
"""
Test that ConductorEngine populates _abort_events when spawning a worker.
Test that ConductorEngine populates _abort_events when spawning a worker.
"""
# 1. Mock WorkerPool.spawn to return a mock thread
with patch('src.multi_agent_conductor.WorkerPool.spawn') as mock_spawn:
+5 -3
View File
@@ -4,7 +4,8 @@ from src.api_hook_client import ApiHookClient
def simulate_conductor_phase_completion(client: ApiHookClient, track_id: str, phase_name: str) -> bool:
"""
Simulates the Conductor agent's logic for phase completion using ApiHookClient.
Simulates the Conductor agent's logic for phase completion using ApiHookClient.
"""
try:
# 1. Poll for state
@@ -24,8 +25,9 @@ def simulate_conductor_phase_completion(client: ApiHookClient, track_id: str, ph
def test_conductor_integrates_api_hook_client_for_verification(live_gui) -> None:
"""
Verify that Conductor's simulated phase completion logic properly integrates
with the ApiHookClient and the live Hook Server.
Verify that Conductor's simulated phase completion logic properly integrates
with the ApiHookClient and the live Hook Server.
"""
client = ApiHookClient()
assert client.wait_for_server(timeout=10)
+6 -4
View File
@@ -8,7 +8,8 @@ from src.models import Track
def test_conductor_engine_initializes_empty_worker_and_abort_dicts() -> None:
"""
Test that ConductorEngine correctly initializes _active_workers and _abort_events as empty dictionaries.
Test that ConductorEngine correctly initializes _active_workers and _abort_events as empty dictionaries.
"""
# Mock the track object
mock_track = MagicMock(spec=Track)
@@ -24,8 +25,9 @@ def test_conductor_engine_initializes_empty_worker_and_abort_dicts() -> None:
def test_kill_worker_sets_abort_and_joins_thread() -> None:
"""
Test kill_worker: mock a running thread in _active_workers, call kill_worker,
assert abort_event is set and thread is joined.
Test kill_worker: mock a running thread in _active_workers, call kill_worker,
assert abort_event is set and thread is joined.
"""
mock_track = MagicMock(spec=Track)
mock_track.tickets = []
@@ -38,7 +40,7 @@ def test_kill_worker_sets_abort_and_joins_thread() -> None:
# Create a thread that waits for the abort event
def worker():
"""
[C: tests/test_symbol_parsing.py:test_handle_generate_send_appends_definitions, tests/test_symbol_parsing.py:test_handle_generate_send_no_symbols]
[C: tests/test_symbol_parsing.py:test_handle_generate_send_appends_definitions, tests/test_symbol_parsing.py:test_handle_generate_send_no_symbols]
"""
abort_event.wait(timeout=2.0)
+25 -15
View File
@@ -10,7 +10,8 @@ from src import ai_client
def test_conductor_engine_initialization() -> None:
"""
Test that ConductorEngine can be initialized with a Track.
Test that ConductorEngine can be initialized with a Track.
"""
track = Track(id="test_track", description="Test Track")
from src.multi_agent_conductor import ConductorEngine
@@ -20,7 +21,8 @@ def test_conductor_engine_initialization() -> None:
def test_conductor_engine_run_executes_tickets_in_order(monkeypatch: pytest.MonkeyPatch, vlogger) -> None:
"""
Test that run iterates through executable tickets and calls the worker lifecycle.
Test that run iterates through executable tickets and calls the worker lifecycle.
"""
ticket1 = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1")
ticket2 = Ticket(id="T2", description="Task 2", status="todo", assigned_to="worker2", depends_on=["T1"])
@@ -67,7 +69,8 @@ def test_conductor_engine_run_executes_tickets_in_order(monkeypatch: pytest.Monk
def test_run_worker_lifecycle_calls_ai_client_send(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Test that run_worker_lifecycle triggers the AI client and updates ticket status on success.
Test that run_worker_lifecycle triggers the AI client and updates ticket status on success.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1")
context = WorkerContext(ticket_id="T1", model_name="test-model", messages=[])
@@ -88,7 +91,8 @@ def test_run_worker_lifecycle_calls_ai_client_send(monkeypatch: pytest.MonkeyPat
def test_run_worker_lifecycle_context_injection(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Test that run_worker_lifecycle can take a context_files list and injects AST views into the prompt.
Test that run_worker_lifecycle can take a context_files list and injects AST views into the prompt.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1")
context = WorkerContext(ticket_id="T1", model_name="test-model", messages=[])
@@ -134,7 +138,8 @@ def test_run_worker_lifecycle_context_injection(monkeypatch: pytest.MonkeyPatch)
def test_run_worker_lifecycle_handles_blocked_response(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Test that run_worker_lifecycle marks the ticket as blocked if the AI indicates it cannot proceed.
Test that run_worker_lifecycle marks the ticket as blocked if the AI indicates it cannot proceed.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1")
context = WorkerContext(ticket_id="T1", model_name="test-model", messages=[])
@@ -151,9 +156,10 @@ def test_run_worker_lifecycle_handles_blocked_response(monkeypatch: pytest.Monke
def test_run_worker_lifecycle_step_mode_confirmation(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Test that run_worker_lifecycle passes confirm_execution to ai_client.send when step_mode is True.
Verify that if confirm_execution is called (simulated by mocking ai_client.send to call its callback),
the flow works as expected.
Test that run_worker_lifecycle passes confirm_execution to ai_client.send when step_mode is True.
Verify that if confirm_execution is called (simulated by mocking ai_client.send to call its callback),
the flow works as expected.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1", step_mode=True)
context = WorkerContext(ticket_id="T1", model_name="test-model", messages=[])
@@ -188,8 +194,9 @@ def test_run_worker_lifecycle_step_mode_confirmation(monkeypatch: pytest.MonkeyP
def test_run_worker_lifecycle_step_mode_rejection(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Verify that if confirm_execution returns False, the logic (in ai_client, which we simulate here)
would prevent execution. In run_worker_lifecycle, we just check if it's passed.
Verify that if confirm_execution returns False, the logic (in ai_client, which we simulate here)
would prevent execution. In run_worker_lifecycle, we just check if it's passed.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1", step_mode=True)
context = WorkerContext(ticket_id="T1", model_name="test-model", messages=[])
@@ -213,7 +220,8 @@ def test_run_worker_lifecycle_step_mode_rejection(monkeypatch: pytest.MonkeyPatc
def test_conductor_engine_dynamic_parsing_and_execution(monkeypatch: pytest.MonkeyPatch, vlogger) -> None:
"""
Test that parse_json_tickets correctly populates the track and run executes them in dependency order.
Test that parse_json_tickets correctly populates the track and run executes them in dependency order.
"""
import json
from src.multi_agent_conductor import ConductorEngine
@@ -281,8 +289,9 @@ def test_conductor_engine_dynamic_parsing_and_execution(monkeypatch: pytest.Monk
def test_run_worker_lifecycle_pushes_response_via_queue(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Test that run_worker_lifecycle pushes a 'response' event with the correct stream_id
via _queue_put when event_queue is provided.
Test that run_worker_lifecycle pushes a 'response' event with the correct stream_id
via _queue_put when event_queue is provided.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1")
context = WorkerContext(ticket_id="T1", model_name="test-model", messages=[])
@@ -307,8 +316,9 @@ def test_run_worker_lifecycle_pushes_response_via_queue(monkeypatch: pytest.Monk
def test_run_worker_lifecycle_token_usage_from_comms_log(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Test that run_worker_lifecycle reads token usage from the comms log and
updates engine.tier_usage['Tier 3'] with real input/output token counts.
Test that run_worker_lifecycle reads token usage from the comms log and
updates engine.tier_usage['Tier 3'] with real input/output token counts.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1")
context = WorkerContext(ticket_id="T1", model_name="test-model", messages=[])
+19 -10
View File
@@ -10,7 +10,8 @@ from src.dag_engine import TrackDAG
def test_get_ready_tasks_linear():
"""
Verifies ready tasks detection in a simple linear dependency chain.
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"])
@@ -22,8 +23,9 @@ def test_get_ready_tasks_linear():
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.
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"])
@@ -38,7 +40,8 @@ def test_get_ready_tasks_branching():
def test_has_cycle_no_cycle():
"""
Validates that an acyclic graph is correctly identified as not having cycles.
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"])
@@ -48,7 +51,8 @@ def test_has_cycle_no_cycle():
def test_has_cycle_direct_cycle():
"""
Validates that a direct cycle (A depends on B, B depends on A) is correctly detected.
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"])
@@ -58,7 +62,8 @@ def test_has_cycle_direct_cycle():
def test_has_cycle_indirect_cycle():
"""
Validates that an indirect cycle (A->B->C->A) is correctly detected.
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"])
@@ -69,7 +74,8 @@ def test_has_cycle_indirect_cycle():
def test_has_cycle_complex_no_cycle():
"""
Validates cycle detection in a complex graph that merges branches but remains acyclic.
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"])
@@ -81,7 +87,8 @@ def test_has_cycle_complex_no_cycle():
def test_get_ready_tasks_multiple_deps():
"""
Validates that a task is not marked ready until ALL of its dependencies are completed.
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")
@@ -95,7 +102,8 @@ def test_get_ready_tasks_multiple_deps():
def test_topological_sort():
"""
Verifies that tasks are correctly ordered by dependencies regardless of input order.
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"])
@@ -107,7 +115,8 @@ def test_topological_sort():
def test_topological_sort_cycle():
"""
Verifies that topological sorting safely aborts and raises ValueError when a cycle is present.
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"])
+12 -7
View File
@@ -13,8 +13,9 @@ from src import project_manager
def test_credentials_error_mentions_deepseek(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Verify that the error message shown when credentials.toml is missing
includes deepseek instructions.
Verify that the error message shown when credentials.toml is missing
includes deepseek instructions.
"""
# Monkeypatch SLOP_CREDENTIALS to a non-existent file
monkeypatch.setenv("SLOP_CREDENTIALS", "non_existent_credentials_file.toml")
@@ -27,8 +28,9 @@ def test_credentials_error_mentions_deepseek(monkeypatch: pytest.MonkeyPatch) ->
def test_default_project_includes_reasoning_role() -> None:
"""
Verify that 'Reasoning' is included in the default discussion roles
to support DeepSeek-R1 reasoning traces.
Verify that 'Reasoning' is included in the default discussion roles
to support DeepSeek-R1 reasoning traces.
"""
proj = project_manager.default_project("test")
roles = proj["discussion"]["roles"]
@@ -37,7 +39,8 @@ def test_default_project_includes_reasoning_role() -> None:
def test_gui_providers_list() -> None:
"""
Check if 'deepseek' is in the GUI's provider list.
Check if 'deepseek' is in the GUI's provider list.
"""
from src.models import PROVIDERS
assert "deepseek" in PROVIDERS
@@ -45,7 +48,8 @@ def test_gui_providers_list() -> None:
def test_deepseek_model_listing() -> None:
"""
Verify that list_models for deepseek returns expected models.
Verify that list_models for deepseek returns expected models.
"""
models = ai_client.list_models("deepseek")
assert "deepseek-chat" in models
@@ -54,7 +58,8 @@ def test_deepseek_model_listing() -> None:
def test_gui_provider_list_via_hooks(live_gui: Any) -> None:
"""
Verify 'deepseek' is present in the GUI provider list using API hooks.
Verify 'deepseek' is present in the GUI provider list using API hooks.
"""
from api_hook_client import ApiHookClient
import time
+14 -7
View File
@@ -5,7 +5,8 @@ from src import ai_client
def test_deepseek_model_selection() -> None:
"""
Verifies that ai_client.set_provider('deepseek', 'deepseek-chat') correctly updates the internal state.
Verifies that ai_client.set_provider('deepseek', 'deepseek-chat') correctly updates the internal state.
"""
ai_client.set_provider("deepseek", "deepseek-chat")
assert ai_client._provider == "deepseek"
@@ -15,7 +16,8 @@ def test_deepseek_model_selection() -> None:
def test_deepseek_completion_logic(mock_post: MagicMock) -> None:
"""
Verifies that ai_client.send() correctly calls the DeepSeek API and returns content.
Verifies that ai_client.send() correctly calls the DeepSeek API and returns content.
"""
ai_client.set_provider("deepseek", "deepseek-chat")
with patch("src.ai_client._load_credentials", return_value={"deepseek": {"api_key": "test-key"}}):
@@ -34,7 +36,8 @@ def test_deepseek_completion_logic(mock_post: MagicMock) -> None:
def test_deepseek_reasoning_logic(mock_post: MagicMock) -> None:
"""
Verifies that reasoning_content is captured and wrapped in <thinking> tags.
Verifies that reasoning_content is captured and wrapped in <thinking> tags.
"""
ai_client.set_provider("deepseek", "deepseek-reasoner")
with patch("src.ai_client._load_credentials", return_value={"deepseek": {"api_key": "test-key"}}):
@@ -56,7 +59,8 @@ def test_deepseek_reasoning_logic(mock_post: MagicMock) -> None:
def test_deepseek_tool_calling(mock_post: MagicMock) -> None:
"""
Verifies that DeepSeek provider correctly identifies and executes tool calls.
Verifies that DeepSeek provider correctly identifies and executes tool calls.
"""
ai_client.set_provider("deepseek", "deepseek-chat")
with patch("src.ai_client._load_credentials", return_value={"deepseek": {"api_key": "test-key"}}), \
@@ -98,7 +102,8 @@ def test_deepseek_tool_calling(mock_post: MagicMock) -> None:
def test_deepseek_streaming(mock_post: MagicMock) -> None:
"""
Verifies that DeepSeek provider correctly aggregates streaming chunks.
Verifies that DeepSeek provider correctly aggregates streaming chunks.
"""
ai_client.set_provider("deepseek", "deepseek-chat")
with patch("src.ai_client._load_credentials", return_value={"deepseek": {"api_key": "test-key"}}):
@@ -121,7 +126,8 @@ def test_deepseek_streaming(mock_post: MagicMock) -> None:
def test_deepseek_payload_verification(mock_post: MagicMock) -> None:
"""
Verifies that the correct JSON payload (tools, history, params) is sent to DeepSeek.
Verifies that the correct JSON payload (tools, history, params) is sent to DeepSeek.
"""
ai_client.set_provider("deepseek", "deepseek-chat")
ai_client.reset_session()
@@ -149,7 +155,8 @@ def test_deepseek_payload_verification(mock_post: MagicMock) -> None:
def test_deepseek_reasoner_payload_verification(mock_post: MagicMock) -> None:
"""
Verifies that deepseek-reasoner payload excludes tools and temperature.
Verifies that deepseek-reasoner payload excludes tools and temperature.
"""
ai_client.set_provider("deepseek", "deepseek-reasoner")
ai_client.reset_session()
+1 -1
View File
@@ -69,4 +69,4 @@ def test_execution_sim_live(live_gui: Any) -> None:
client.set_value('auto_add_history', True)
sim.run()
time.sleep(2)
sim.teardown()
sim.teardown()
+1 -1
View File
@@ -55,4 +55,4 @@ def test_file_item_from_dict_defaults():
assert item.view_mode == "full"
assert item.ast_mask == {}
assert item.custom_slices == []
assert item.injected_at is None
assert item.injected_at is None
+3 -2
View File
@@ -12,8 +12,9 @@ from src.ai_client import get_gemini_cache_stats, reset_session
def test_get_gemini_cache_stats_with_mock_client() -> None:
"""
Test that get_gemini_cache_stats correctly processes cache lists
from a mocked client instance.
Test that get_gemini_cache_stats correctly processes cache lists
from a mocked client instance.
"""
# Ensure a clean state before the test by resetting the session
reset_session()
+3 -2
View File
@@ -12,8 +12,9 @@ def app_instance(monkeypatch: pytest.MonkeyPatch) -> type[App]:
def test_app_subscribes_to_events(app_instance: type[App]) -> None:
"""
This test checks that the App's __init__ method subscribes the necessary
event handlers to the ai_client.events emitter.
This test checks that the App's __init__ method subscribes the necessary
event handlers to the ai_client.events emitter.
"""
with patch.object(ai_client.events, 'on') as mock_on:
app = app_instance()
+6 -4
View File
@@ -3,8 +3,9 @@ from src.gui_2 import App
def test_gui2_hubs_exist_in_show_windows(app_instance: App) -> None:
"""
Verifies that the new consolidated Hub windows are defined in the App's show_windows.
This ensures they will be available in the 'Windows' menu.
Verifies that the new consolidated Hub windows are defined in the App's show_windows.
This ensures they will be available in the 'Windows' menu.
"""
expected_hubs = [
"Project Settings",
@@ -20,8 +21,9 @@ def test_gui2_hubs_exist_in_show_windows(app_instance: App) -> None:
def test_gui2_old_windows_removed_from_show_windows(app_instance: App) -> None:
"""
Verifies that the old fragmented windows are removed from show_windows.
Note: Message, Response, and Tool Calls are kept as they are now optional standalone windows.
Verifies that the old fragmented windows are removed from show_windows.
Note: Message, Response, and Tool Calls are kept as they are now optional standalone windows.
"""
old_windows = [
"Projects", "Files", "Screenshots",
+4 -3
View File
@@ -6,9 +6,10 @@ from src import ai_client
def test_mcp_tool_call_is_dispatched(app_instance: App) -> None:
"""
This test verifies that when the AI returns a tool call for an MCP function,
the ai_client correctly dispatches it to mcp_client.
This will fail until mcp_client is properly integrated.
This test verifies that when the AI returns a tool call for an MCP function,
the ai_client correctly dispatches it to mcp_client.
This will fail until mcp_client is properly integrated.
"""
# 1. Define the mock tool call from the AI
mock_fc = MagicMock()
+7 -4
View File
@@ -26,7 +26,8 @@ def cleanup_callback_file() -> None:
def test_gui2_set_value_hook_works(live_gui: Any) -> None:
"""
Tests that the 'set_value' GUI hook is correctly implemented.
Tests that the 'set_value' GUI hook is correctly implemented.
"""
client = ApiHookClient()
assert client.wait_for_server(timeout=10)
@@ -42,7 +43,8 @@ def test_gui2_set_value_hook_works(live_gui: Any) -> None:
def test_gui2_click_hook_works(live_gui: Any) -> None:
"""
Tests that the 'click' GUI hook for the 'Reset' button is implemented.
Tests that the 'click' GUI hook for the 'Reset' button is implemented.
"""
client = ApiHookClient()
assert client.wait_for_server(timeout=10)
@@ -60,7 +62,8 @@ def test_gui2_click_hook_works(live_gui: Any) -> None:
def test_gui2_custom_callback_hook_works(live_gui: Any) -> None:
"""
Tests that the 'custom_callback' GUI hook is correctly implemented.
Tests that the 'custom_callback' GUI hook is correctly implemented.
"""
client = ApiHookClient()
assert client.wait_for_server(timeout=10)
@@ -78,4 +81,4 @@ def test_gui2_custom_callback_hook_works(live_gui: Any) -> None:
assert temp_workspace_file.exists(), f"Custom callback was NOT executed, or file path is wrong! Expected: {temp_workspace_file}"
with open(temp_workspace_file, "r") as f:
content = f.read()
assert content == test_data, "Callback executed, but file content is incorrect."
assert content == test_data, "Callback executed, but file content is incorrect."
+6 -4
View File
@@ -20,8 +20,9 @@ _shared_metrics = {}
def test_performance_benchmarking(live_gui: tuple) -> None:
"""
Collects performance metrics for the current GUI script over a 5-second window.
Ensures the application does not lock up and can report its internal state.
Collects performance metrics for the current GUI script over a 5-second window.
Ensures the application does not lock up and can report its internal state.
"""
process, gui_script = live_gui
client = ApiHookClient()
@@ -67,8 +68,9 @@ def test_performance_benchmarking(live_gui: tuple) -> None:
def test_performance_baseline_check() -> None:
"""
Verifies that we have successfully collected performance metrics for sloppy.py
and that they meet the minimum 30 FPS baseline.
Verifies that we have successfully collected performance metrics for sloppy.py
and that they meet the minimum 30 FPS baseline.
"""
# Key is full path, find it by basename
gui_key = next((k for k in _shared_metrics if "sloppy.py" in k), None)
+4 -3
View File
@@ -15,9 +15,10 @@ def test_diagnostics_panel_initialization(app_instance: Any) -> None:
def test_diagnostics_history_updates(app_instance: Any) -> None:
"""
Verifies that the internal performance history is updated correctly.
This logic is inside the render loop in gui_2.py, but we can test
the data structure and initialization.
Verifies that the internal performance history is updated correctly.
This logic is inside the render loop in gui_2.py, but we can test
the data structure and initialization.
"""
assert "fps" in app_instance.perf_history
assert len(app_instance.perf_history["fps"]) == 100
+1 -1
View File
@@ -60,4 +60,4 @@ def test_render_files_and_media_fast(app_instance: App):
try:
app_instance._render_files_and_media()
except Exception as e:
pytest.fail(f"_render_files_and_media raised an exception: {e}")
pytest.fail(f"_render_files_and_media raised an exception: {e}")
+1 -1
View File
@@ -13,7 +13,7 @@ class MockApp:
def init_state(self):
"""
[C: tests/test_system_prompt_exposure.py:TestSystemPromptExposure.test_app_controller_init_state_loads_prompts]
[C: tests/test_system_prompt_exposure.py:TestSystemPromptExposure.test_app_controller_init_state_loads_prompts]
"""
pass
+2 -1
View File
@@ -11,7 +11,8 @@ from api_hook_client import ApiHookClient
def test_idle_performance_requirements(live_gui) -> None:
"""
Requirement: GUI must maintain stable performance on idle.
Requirement: GUI must maintain stable performance on idle.
"""
# Warmup to ensure GUI is ready
time.sleep(5.0)
+10 -7
View File
@@ -12,8 +12,9 @@ from src import paths
def test_track_proposal_editing(app_instance):
"""
Verifies the structural integrity of track proposal items.
Ensures that track proposals can be edited and removed from the active list.
Verifies the structural integrity of track proposal items.
Ensures that track proposals can be edited and removed from the active list.
"""
app_instance.proposed_tracks = [
{"title": "Old Title", "goal": "Old Goal"},
@@ -35,8 +36,9 @@ def test_track_proposal_editing(app_instance):
def test_conductor_setup_scan(app_instance, tmp_path, monkeypatch):
"""
Verifies that the conductor setup scan properly iterates through the conductor directory,
counts files and lines, and identifies active tracks.
Verifies that the conductor setup scan properly iterates through the conductor directory,
counts files and lines, and identifies active tracks.
"""
old_cwd = os.getcwd()
os.chdir(tmp_path)
@@ -63,8 +65,9 @@ def test_conductor_setup_scan(app_instance, tmp_path, monkeypatch):
def test_create_track(app_instance, tmp_path):
"""
Verifies that _cb_create_track properly creates the track folder
and populates the necessary boilerplate files (spec.md, plan.md, metadata.json).
Verifies that _cb_create_track properly creates the track folder
and populates the necessary boilerplate files (spec.md, plan.md, metadata.json).
"""
old_cwd = os.getcwd()
os.chdir(tmp_path)
@@ -91,4 +94,4 @@ def test_create_track(app_instance, tmp_path):
assert data['type'] == "feature"
assert data['id'] == track_dir.name
finally:
os.chdir(old_cwd)
os.chdir(old_cwd)
+2 -1
View File
@@ -3,7 +3,8 @@ import time
def test_gui_startup_smoke(live_gui):
"""
Smoke test to ensure the GUI starts and remains running.
Smoke test to ensure the GUI starts and remains running.
"""
proc, _ = live_gui
+3 -2
View File
@@ -5,7 +5,8 @@ from src.api_hook_client import ApiHookClient
def test_text_viewer_state_update(live_gui) -> None:
"""
Verifies that we can set text viewer state and it is reflected in GUI state.
Verifies that we can set text viewer state and it is reflected in GUI state.
"""
client = ApiHookClient()
client.click("btn_reset")
@@ -32,4 +33,4 @@ def test_text_viewer_state_update(live_gui) -> None:
assert state is not None
assert state.get('show_text_viewer') == True
assert state.get('text_viewer_title') == label
assert state.get('text_viewer_type') == text_type
assert state.get('text_viewer_type') == text_type
+12 -9
View File
@@ -17,9 +17,10 @@ from src.gui_2 import App
def test_telemetry_data_updates_correctly(app_instance: Any) -> None:
"""
Tests that the _refresh_api_metrics method correctly updates
the internal state for display by querying the ai_client.
Verifies the boundary between GUI state and API state.
Tests that the _refresh_api_metrics method correctly updates
the internal state for display by querying the ai_client.
Verifies the boundary between GUI state and API state.
"""
# 1. Set the provider to anthropic
app_instance._current_provider = "anthropic"
@@ -43,9 +44,10 @@ def test_telemetry_data_updates_correctly(app_instance: Any) -> None:
def test_performance_history_updates(app_instance: Any) -> None:
"""
Verify the data structure that feeds the sparkline.
This ensures that the rolling buffer for performance telemetry maintains
the correct size and default initialization to prevent GUI rendering crashes.
Verify the data structure that feeds the sparkline.
This ensures that the rolling buffer for performance telemetry maintains
the correct size and default initialization to prevent GUI rendering crashes.
"""
# ANTI-SIMPLIFICATION: Verifying exactly 100 elements ensures the sparkline won't overflow
assert len(app_instance.perf_history["frame_time"]) == 100
@@ -54,9 +56,10 @@ def test_performance_history_updates(app_instance: Any) -> None:
def test_gui_updates_on_event(app_instance: App) -> None:
"""
Verifies that when an API event is received (e.g. from ai_client),
the _on_api_event handler correctly updates internal metrics and
queues the update to be processed by the GUI event loop.
Verifies that when an API event is received (e.g. from ai_client),
the _on_api_event handler correctly updates internal metrics and
queues the update to be processed by the GUI event loop.
"""
mock_stats = {"percentage": 50.0, "current": 500, "limit": 1000}
app_instance.last_md = "mock_md"
+5 -4
View File
@@ -6,10 +6,11 @@ from src.api_hook_client import ApiHookClient
async def test_mma_track_lifecycle_simulation():
"""
This test simulates the sequence of API calls an external orchestrator
would make to manage an MMA track lifecycle via the Hook API.
It verifies that ApiHookClient correctly routes requests to the
corresponding endpoints in src/api_hooks.py.
This test simulates the sequence of API calls an external orchestrator
would make to manage an MMA track lifecycle via the Hook API.
It verifies that ApiHookClient correctly routes requests to the
corresponding endpoints in src/api_hooks.py.
"""
client = ApiHookClient("http://localhost:8999")
+8 -6
View File
@@ -10,10 +10,11 @@ from src import ai_client
async def test_headless_verification_full_run(vlogger) -> None:
"""
1. Initialize a ConductorEngine with a Track containing multiple dependent Tickets.
2. Simulate a full execution run using engine.run().
3. Mock ai_client.send to simulate successful tool calls and final responses.
4. Specifically verify that 'Context Amnesia' is maintained.
1. Initialize a ConductorEngine with a Track containing multiple dependent Tickets.
2. Simulate a full execution run using engine.run().
3. Mock ai_client.send to simulate successful tool calls and final responses.
4. Specifically verify that 'Context Amnesia' is maintained.
"""
t1 = Ticket(id="T1", description="Task 1", status="todo", assigned_to="worker1")
t2 = Ticket(id="T2", description="Task 2", status="todo", assigned_to="worker1", depends_on=["T1"])
@@ -49,8 +50,9 @@ async def test_headless_verification_full_run(vlogger) -> None:
async def test_headless_verification_error_and_qa_interceptor(vlogger) -> None:
"""
5. Simulate a shell error and verify that the Tier 4 QA interceptor is triggered
and its summary is injected into the worker's history for the next retry.
5. Simulate a shell error and verify that the Tier 4 QA interceptor is triggered
and its summary is injected into the worker's history for the next retry.
"""
t1 = Ticket(id="T1", description="Task with error", status="todo", assigned_to="worker1")
track = Track(id="track_error", description="Error Track", tickets=[t1])
+9 -5
View File
@@ -12,8 +12,9 @@ from src.gui_2 import App
def test_new_hubs_defined_in_show_windows(mock_app: App) -> None:
"""
Verifies that the new consolidated Hub windows are defined in the App's show_windows.
This ensures they will be available in the 'Windows' menu.
Verifies that the new consolidated Hub windows are defined in the App's show_windows.
This ensures they will be available in the 'Windows' menu.
"""
expected_hubs = [
"Project Settings",
@@ -27,7 +28,8 @@ def test_new_hubs_defined_in_show_windows(mock_app: App) -> None:
def test_old_windows_removed_from_gui2(app_instance_simple: Any) -> None:
"""
Verifies that the old fragmented windows are removed or renamed.
Verifies that the old fragmented windows are removed or renamed.
"""
old_tags = [
"win_projects", "win_files", "win_screenshots",
@@ -54,7 +56,8 @@ def app_instance_simple() -> Any:
def test_hub_windows_exist_in_gui2(app_instance_simple: Any) -> None:
"""
Verifies that the new Hub windows are present in the show_windows dictionary.
Verifies that the new Hub windows are present in the show_windows dictionary.
"""
hubs = ["Project Settings", "AI Settings", "Discussion Hub", "Operations Hub"]
for hub in hubs:
@@ -63,7 +66,8 @@ def test_hub_windows_exist_in_gui2(app_instance_simple: Any) -> None:
def test_indicators_logic_exists(app_instance_simple: Any) -> None:
"""
Verifies that the status indicators logic exists in the App.
Verifies that the status indicators logic exists in the App.
"""
assert hasattr(app_instance_simple, 'ai_status')
assert hasattr(app_instance_simple, 'mma_status')
+8 -6
View File
@@ -14,11 +14,12 @@ from src.api_hook_client import ApiHookClient
def test_user_request_integration_flow(mock_app: App) -> None:
"""
Verifies that pushing a UserRequestEvent to the event_queue:
1. Triggers ai_client.send
2. Results in a 'response' event back to the queue
3. Eventually updates the UI state (ai_response, ai_status) after processing GUI tasks.
ANTI-SIMPLIFICATION: This verifies the full cross-thread boundary.
Verifies that pushing a UserRequestEvent to the event_queue:
1. Triggers ai_client.send
2. Results in a 'response' event back to the queue
3. Eventually updates the UI state (ai_response, ai_status) after processing GUI tasks.
ANTI-SIMPLIFICATION: This verifies the full cross-thread boundary.
"""
app = mock_app
# Mock all ai_client methods called during _handle_request_event
@@ -76,7 +77,8 @@ def test_user_request_integration_flow(mock_app: App) -> None:
def test_user_request_error_handling(mock_app: App) -> None:
"""
Verifies that if ai_client.send raises an exception, the UI is updated with the error state.
Verifies that if ai_client.send raises an exception, the UI is updated with the error state.
"""
app = mock_app
with (
+6 -4
View File
@@ -16,7 +16,8 @@ from src.api_hook_client import ApiHookClient
def wait_for_value(client, field, expected, timeout=10):
"""
Helper to poll the GUI state until a field matches the expected value.
Helper to poll the GUI state until a field matches the expected value.
"""
start = time.time()
while time.time() - start < timeout:
@@ -31,9 +32,10 @@ def wait_for_value(client, field, expected, timeout=10):
def test_full_live_workflow(live_gui) -> None:
"""
Integration test that drives the GUI through a full workflow.
ANTI-SIMPLIFICATION: Asserts exact AI behavior, thinking state tracking,
and response logging in discussion history.
Integration test that drives the GUI through a full workflow.
ANTI-SIMPLIFICATION: Asserts exact AI behavior, thinking state tracking,
and response logging in discussion history.
"""
client = ApiHookClient()
assert client.wait_for_server(timeout=10)
+2 -2
View File
@@ -6,7 +6,7 @@ from src.gui_2 import App
def _make_app(**kwargs):
"""
[C: tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier1_renders_stream_content, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders]
[C: tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier1_renders_stream_content, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders]
"""
app = MagicMock()
app.mma_streams = kwargs.get("mma_streams", {})
@@ -65,7 +65,7 @@ def _make_app(**kwargs):
def _make_imgui_mock():
"""
[C: tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier1_renders_stream_content, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders]
[C: tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier1_renders_stream_content, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders]
"""
m = MagicMock()
m.begin_table.return_value = False
+6 -4
View File
@@ -11,7 +11,8 @@ from src import api_hook_client
def _poll_mma_status(client, timeout, condition, label):
"""
Poll get_mma_status() until condition(status) is True or timeout.
Poll get_mma_status() until condition(status) is True or timeout.
[C: tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow]
"""
last_status = {}
@@ -28,9 +29,10 @@ def _poll_mma_status(client, timeout, condition, label):
def test_mma_concurrent_tracks_execution(live_gui) -> None:
"""
Stress test for concurrent MMA track execution.
Verifies that starting multiple tracks simultaneously doesn't cause crashes
and that workers from both tracks are processed.
Stress test for concurrent MMA track execution.
Verifies that starting multiple tracks simultaneously doesn't cause crashes
and that workers from both tracks are processed.
"""
client = api_hook_client.ApiHookClient()
assert client.wait_for_server(timeout=15), "Hook server did not start"
@@ -25,8 +25,9 @@ def _poll_mma_workers(client: api_hook_client.ApiHookClient, timeout: int, condi
def test_mma_concurrent_tracks_stress(live_gui) -> None:
"""
Stress test: Start two tracks concurrently and verify they both progress
without crashing the GUI or losing state.
Stress test: Start two tracks concurrently and verify they both progress
without crashing the GUI or losing state.
"""
client = api_hook_client.ApiHookClient()
assert client.wait_for_server(timeout=15), "Hook server did not start"
+26 -17
View File
@@ -3,8 +3,9 @@ from src.models import Ticket, Track, WorkerContext
def test_ticket_instantiation() -> None:
"""
Verifies that a Ticket can be instantiated with its required fields:
id, description, status, assigned_to.
Verifies that a Ticket can be instantiated with its required fields:
id, description, status, assigned_to.
"""
ticket_id = "T1"
description = "Implement surgical code changes"
@@ -25,7 +26,8 @@ def test_ticket_instantiation() -> None:
def test_ticket_with_dependencies() -> None:
"""
Verifies that a Ticket can store dependencies.
Verifies that a Ticket can store dependencies.
"""
ticket = Ticket(
id="T2",
@@ -39,8 +41,9 @@ def test_ticket_with_dependencies() -> None:
def test_track_instantiation() -> None:
"""
Verifies that a Track can be instantiated with its required fields:
id, description, and a list of Tickets.
Verifies that a Track can be instantiated with its required fields:
id, description, and a list of Tickets.
"""
ticket1 = Ticket(id="T1", description="Task 1", status="todo", assigned_to="a")
ticket2 = Ticket(id="T2", description="Task 2", status="todo", assigned_to="b")
@@ -61,7 +64,8 @@ def test_track_instantiation() -> None:
def test_track_can_handle_empty_tickets() -> None:
"""
Verifies that a Track can be instantiated with an empty list of tickets.
Verifies that a Track can be instantiated with an empty list of tickets.
"""
track = Track(id="TRACK-2", description="Empty Track", tickets=[])
assert track.tickets == []
@@ -69,8 +73,9 @@ def test_track_can_handle_empty_tickets() -> None:
def test_worker_context_instantiation() -> None:
"""
Verifies that a WorkerContext can be instantiated with ticket_id,
model_name, and messages.
Verifies that a WorkerContext can be instantiated with ticket_id,
model_name, and messages.
"""
ticket_id = "T1"
model_name = "gemini-2.0-flash-lite"
@@ -90,8 +95,9 @@ def test_worker_context_instantiation() -> None:
def test_ticket_mark_blocked() -> None:
"""
Verifies that ticket.mark_blocked(reason) sets the status to 'blocked'.
Note: The reason field might need to be added to the Ticket class.
Verifies that ticket.mark_blocked(reason) sets the status to 'blocked'.
Note: The reason field might need to be added to the Ticket class.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="a")
ticket.mark_blocked("Waiting for API key")
@@ -100,7 +106,8 @@ def test_ticket_mark_blocked() -> None:
def test_ticket_mark_complete() -> None:
"""
Verifies that ticket.mark_complete() sets the status to 'completed'.
Verifies that ticket.mark_complete() sets the status to 'completed'.
"""
ticket = Ticket(id="T1", description="Task 1", status="todo", assigned_to="a")
ticket.mark_complete()
@@ -109,8 +116,9 @@ def test_ticket_mark_complete() -> None:
def test_track_get_executable_tickets() -> None:
"""
Verifies that track.get_executable_tickets() returns only 'todo' tickets
whose dependencies are all 'completed'.
Verifies that track.get_executable_tickets() returns only 'todo' tickets
whose dependencies are all 'completed'.
"""
# T1: todo, no deps -> executable
t1 = Ticket(id="T1", description="T1", status="todo", assigned_to="a")
@@ -134,10 +142,11 @@ def test_track_get_executable_tickets() -> None:
def test_track_get_executable_tickets_complex() -> None:
"""
Verifies executable tickets with complex dependency chains.
Chain: T1 (comp) -> T2 (todo) -> T3 (todo)
T4 (comp) -> T3
T5 (todo) -> T3
Verifies executable tickets with complex dependency chains.
Chain: T1 (comp) -> T2 (todo) -> T3 (todo)
T4 (comp) -> T3
T5 (todo) -> T3
"""
t1 = Ticket(id="T1", description="T1", status="completed", assigned_to="a")
t2 = Ticket(id="T2", description="T2", status="todo", assigned_to="a", depends_on=["T1"])
+2 -1
View File
@@ -24,7 +24,8 @@ def _poll_mma_status(client: api_hook_client.ApiHookClient, timeout: int, condit
def test_mma_step_mode_approval_flow(live_gui) -> None:
"""
Verify that we can manually approve a ticket in Step Mode and it proceeds.
Verify that we can manually approve a ticket in Step Mode and it proceeds.
"""
client = api_hook_client.ApiHookClient()
assert client.wait_for_server(timeout=15), "Hook server did not start"
+5 -3
View File
@@ -13,8 +13,9 @@ from src import api_hook_client
def test_patch_modal_appears_on_trigger(live_gui) -> None:
"""
Test that triggering a patch shows the modal in the GUI.
Uses live_gui fixture to start the GUI with test hooks enabled.
Test that triggering a patch shows the modal in the GUI.
Uses live_gui fixture to start the GUI with test hooks enabled.
"""
proc, _ = live_gui
client = api_hook_client.ApiHookClient()
@@ -51,7 +52,8 @@ def test_patch_modal_appears_on_trigger(live_gui) -> None:
def test_patch_apply_modal_workflow(live_gui) -> None:
"""
Test the full patch apply workflow: trigger -> apply -> verify modal closes.
Test the full patch apply workflow: trigger -> apply -> verify modal closes.
"""
proc, _ = live_gui
client = api_hook_client.ApiHookClient()
+1 -1
View File
@@ -65,4 +65,4 @@ def test_process_pending_gui_tasks_right_click(app_instance: App) -> None:
{"action": "right_click", "item": "item_id"}
]
app_instance.controller._process_pending_gui_tasks()
mock_callback.assert_called_once()
mock_callback.assert_called_once()
+2 -1
View File
@@ -25,7 +25,8 @@ def mock_project():
def test_rag_integration(mock_project):
"""
Integration test verifying the flow from AppController through RAGEngine to ai_client.
Integration test verifying the flow from AppController through RAGEngine to ai_client.
"""
# 1. Initializes a mock project and AppController.
# We patch several components to avoid side effects during initialization.
+3 -2
View File
@@ -10,8 +10,9 @@ class TestRunWorkerLifecycleAbort(unittest.TestCase):
def test_run_worker_lifecycle_returns_early_on_abort(self):
"""
Test that run_worker_lifecycle returns early and marks ticket as 'killed'
if the abort event is set for the ticket.
Test that run_worker_lifecycle returns early and marks ticket as 'killed'
if the abort event is set for the ticket.
"""
# Mock ai_client.send
with patch('src.ai_client.send') as mock_send:
+3 -2
View File
@@ -13,8 +13,9 @@ from src.gui_2 import App
def test_selectable_label_stability(live_gui) -> None:
"""
Verifies that the application starts correctly with --enable-test-hooks
and that the selectable label infrastructure is present and stable.
Verifies that the application starts correctly with --enable-test-hooks
and that the selectable label infrastructure is present and stable.
"""
client = ApiHookClient()
assert client.wait_for_server(timeout=20), "Hook server failed to start"
+3 -2
View File
@@ -16,8 +16,9 @@ from simulation.sim_ai_settings import AISettingsSimulation
def test_ai_settings_simulation_run() -> None:
"""
Verifies that AISettingsSimulation correctly cycles through models
to test the settings UI components.
Verifies that AISettingsSimulation correctly cycles through models
to test the settings UI components.
"""
mock_client = MagicMock()
mock_client.wait_for_server.return_value = True
+5 -3
View File
@@ -16,7 +16,8 @@ from simulation.sim_base import BaseSimulation
def test_base_simulation_init() -> None:
"""
Verifies that the BaseSimulation initializes the ApiHookClient correctly.
Verifies that the BaseSimulation initializes the ApiHookClient correctly.
"""
with patch('simulation.sim_base.ApiHookClient') as mock_client_class:
mock_client = MagicMock()
@@ -29,8 +30,9 @@ def test_base_simulation_init() -> None:
def test_base_simulation_setup() -> None:
"""
Verifies that the setup routine correctly resets the GUI state
and initializes a clean temporary project for simulation.
Verifies that the setup routine correctly resets the GUI state
and initializes a clean temporary project for simulation.
"""
mock_client = MagicMock()
mock_client.wait_for_server.return_value = True
+3 -2
View File
@@ -16,8 +16,9 @@ from simulation.sim_context import ContextSimulation
def test_context_simulation_run() -> None:
"""
Verifies that the ContextSimulation runs the correct sequence of user actions:
discussion switching, context building (md_only), and history truncation.
Verifies that the ContextSimulation runs the correct sequence of user actions:
discussion switching, context building (md_only), and history truncation.
"""
mock_client = MagicMock()
mock_client.wait_for_server.return_value = True
+3 -2
View File
@@ -16,8 +16,9 @@ from simulation.sim_execution import ExecutionSimulation
def test_execution_simulation_run() -> None:
"""
Verifies that ExecutionSimulation handles script confirmation modals.
Ensures that it waits for the modal and clicks the approve button.
Verifies that ExecutionSimulation handles script confirmation modals.
Ensures that it waits for the modal and clicks the approve button.
"""
mock_client = MagicMock()
mock_client.wait_for_server.return_value = True
+3 -2
View File
@@ -16,8 +16,9 @@ from simulation.sim_tools import ToolsSimulation
def test_tools_simulation_run() -> None:
"""
Verifies that ToolsSimulation requests specific tool executions
and verifies they appear in the resulting session history.
Verifies that ToolsSimulation requests specific tool executions
and verifies they appear in the resulting session history.
"""
mock_client = MagicMock()
mock_client.wait_for_server.return_value = True
+9 -8
View File
@@ -7,13 +7,14 @@ import os
def test_system_prompt_sim(live_gui):
"""
Simulation test for system prompt settings.
1. Wait for server.
2. Verify initial state.
3. Modify settings via API.
4. Verify updates.
5. Use 'Reset to Default' button via API.
6. Verify restoration to default text.
Simulation test for system prompt settings.
1. Wait for server.
2. Verify initial state.
3. Modify settings via API.
4. Verify updates.
5. Use 'Reset to Default' button via API.
6. Verify restoration to default text.
"""
_, gui_script = live_gui
client = ApiHookClient()
@@ -68,4 +69,4 @@ def test_system_prompt_sim(live_gui):
# Close it
client.set_value('show_base_prompt_diff_modal', False)
assert client.get_value('show_base_prompt_diff_modal') is False
assert client.get_value('show_base_prompt_diff_modal') is False
+4 -3
View File
@@ -62,9 +62,10 @@ def test_run_powershell_optional_qa_callback() -> None:
def test_end_to_end_tier4_integration(vlogger) -> None:
"""
1. Start a task that triggers a tool failure.
2. Ensure Tier 4 QA analysis is run.
3. Verify the analysis is merged into the next turn's prompt.
1. Start a task that triggers a tool failure.
2. Ensure Tier 4 QA analysis is run.
3. Verify the analysis is merged into the next turn's prompt.
"""
# Trigger a send that results in a tool failure
# (In reality, the tool loop handles this)
+6 -5
View File
@@ -8,11 +8,12 @@ from src.project_manager import save_track_state, load_track_state
def test_track_state_persistence(tmp_path) -> None:
"""
Tests saving and loading a TrackState object to/from a TOML file.
1. Create a TrackState object with sample metadata, discussion, and tasks.
2. Call save_track_state('test_track', state, base_dir).
3. Verify that base_dir/conductor/tracks/test_track/state.toml exists.
4. Call load_track_state('test_track', base_dir) and verify it returns an identical TrackState object.
Tests saving and loading a TrackState object to/from a TOML file.
1. Create a TrackState object with sample metadata, discussion, and tasks.
2. Call save_track_state('test_track', state, base_dir).
3. Verify that base_dir/conductor/tracks/test_track/state.toml exists.
4. Call load_track_state('test_track', base_dir) and verify it returns an identical TrackState object.
"""
base_dir = tmp_path
track_id = "test-track-999" # Metadata internal ID
+3 -2
View File
@@ -4,8 +4,9 @@ from tree_sitter import Language, Parser
def test_tree_sitter_python_setup() -> None:
"""
Verifies that tree-sitter and tree-sitter-python are correctly installed
and can parse a simple Python function string.
Verifies that tree-sitter and tree-sitter-python are correctly installed
and can parse a simple Python function string.
"""
# Initialize the Python language and parser
PY_LANGUAGE = Language(tspython.language())
+4 -3
View File
@@ -56,9 +56,10 @@ def _poll(client: api_hook_client.ApiHookClient, timeout: int, condition, label:
def test_mma_complete_lifecycle(live_gui) -> None:
"""
End-to-end MMA lifecycle using real Gemini API (gemini-2.5-flash-lite).
Incorporates frame-sync sleeps and explicit state-transition waits per
simulation_hardening_20260301 spec (Issues 2 & 3).
End-to-end MMA lifecycle using real Gemini API (gemini-2.5-flash-lite).
Incorporates frame-sync sleeps and explicit state-transition waits per
simulation_hardening_20260301 spec (Issues 2 & 3).
"""
client = api_hook_client.ApiHookClient()
assert client.wait_for_server(timeout=15), "Hook server did not start"
+7 -6
View File
@@ -14,12 +14,13 @@ from src import api_hook_client
def test_workspace_profiles_restoration(live_gui):
"""
Verifies that workspace profiles can save and restore UI state.
1. Sets a field (ui_separate_tier1) to True.
2. Saves a workspace profile.
3. Resets the field to False.
4. Loads the workspace profile.
5. Verifies the field is restored to True.
Verifies that workspace profiles can save and restore UI state.
1. Sets a field (ui_separate_tier1) to True.
2. Saves a workspace profile.
3. Resets the field to False.
4. Loads the workspace profile.
5. Verifies the field is restored to True.
"""
client = api_hook_client.ApiHookClient()
assert client.wait_for_server(timeout=20), "Hook server did not start"