WIP: Regression hell

This commit is contained in:
2026-03-06 21:22:21 -05:00
parent 528f0a04c3
commit f65e9b40b2
14 changed files with 359 additions and 97 deletions

View File

@@ -123,7 +123,7 @@ def mock_app() -> Generator[App, None, None]:
'projects': {'paths': [], 'active': ''},
'gui': {'show_windows': {}}
}),
patch('src.gui_2.save_config'),
patch('src.models.save_config'),
patch('src.gui_2.project_manager'),
patch('src.gui_2.session_logger'),
patch('src.gui_2.immapp.run'),
@@ -155,7 +155,7 @@ def app_instance() -> Generator[App, None, None]:
'projects': {'paths': [], 'active': ''},
'gui': {'show_windows': {}}
}),
patch('src.gui_2.save_config'),
patch('src.models.save_config'),
patch('src.gui_2.project_manager'),
patch('src.gui_2.session_logger'),
patch('src.gui_2.immapp.run'),

View File

@@ -34,10 +34,15 @@ def test_conductor_engine_run_executes_tickets_in_order(monkeypatch: pytest.Monk
# Mocking lifecycle to mark ticket as complete so dependencies can be resolved
def side_effect(ticket, context, *args, **kwargs):
ticket.mark_complete()
import threading
def do_work():
import time
time.sleep(0.1)
ticket.mark_complete()
threading.Thread(target=do_work).start()
return "Success"
mock_lifecycle.side_effect = side_effect
engine.run()
engine.run(max_ticks=20)
vlogger.log_state("T1 Status Final", "todo", ticket1.status)
vlogger.log_state("T2 Status Final", "todo", ticket2.status)
@@ -108,8 +113,8 @@ def test_run_worker_lifecycle_context_injection(monkeypatch: pytest.MonkeyPatch)
run_worker_lifecycle(ticket, context, context_files=context_files)
# Verify ASTParser calls:
# First file (primary) should get curated view, others (secondary) get skeleton
mock_ast_parser.get_curated_view.assert_called_once_with("def primary(): pass")
mock_ast_parser.get_skeleton.assert_called_once_with("def secondary(): pass")
mock_ast_parser.get_curated_view.assert_called_once_with("def primary(): pass", path="primary.py")
mock_ast_parser.get_skeleton.assert_called_once_with("def secondary(): pass", path="secondary.py")
# Verify user_message contains the views
_, kwargs = mock_send.call_args
user_message = kwargs["user_message"]
@@ -238,10 +243,15 @@ def test_conductor_engine_dynamic_parsing_and_execution(monkeypatch: pytest.Monk
# Mock run_worker_lifecycle to mark tickets as complete
with patch("src.multi_agent_conductor.run_worker_lifecycle") as mock_lifecycle:
def side_effect(ticket, context, *args, **kwargs):
ticket.mark_complete()
import threading
def do_work():
import time
time.sleep(0.1)
ticket.mark_complete()
threading.Thread(target=do_work).start()
return "Success"
mock_lifecycle.side_effect = side_effect
engine.run()
engine.run(max_ticks=20)
assert mock_lifecycle.call_count == 3
# Verify dependency order: T1 must be called before T2
calls = [call[0][0].id for call in mock_lifecycle.call_args_list]

View File

@@ -111,3 +111,55 @@ def test_deepseek_streaming(mock_post: MagicMock) -> None:
result = ai_client.send(md_content="Context", user_message="Stream test", base_dir=".", stream=True)
assert result == "Hello World"
@patch("requests.post")
def test_deepseek_payload_verification(mock_post: MagicMock) -> None:
"""
Verifies that the correct JSON payload (tools, history, params) is sent to DeepSeek.
"""
ai_client.set_provider("deepseek", "deepseek-chat")
ai_client.reset_session()
with patch("src.ai_client._load_credentials", return_value={"deepseek": {"api_key": "test-key"}}):
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"choices": [{"message": {"content": "OK"}, "finish_reason": "stop"}]
}
mock_post.return_value = mock_response
ai_client.send(md_content="Context", user_message="Message 1", base_dir=".", discussion_history="History")
args, kwargs = mock_post.call_args
payload = kwargs["json"]
assert payload["model"] == "deepseek-chat"
assert "tools" in payload
assert len(payload["messages"]) == 2 # system + user
assert "[DISCUSSION HISTORY]\n\nHistory" in payload["messages"][1]["content"]
assert "temperature" in payload
assert "max_tokens" in payload
@patch("requests.post")
def test_deepseek_reasoner_payload_verification(mock_post: MagicMock) -> None:
"""
Verifies that deepseek-reasoner payload excludes tools and temperature.
"""
ai_client.set_provider("deepseek", "deepseek-reasoner")
ai_client.reset_session()
with patch("src.ai_client._load_credentials", return_value={"deepseek": {"api_key": "test-key"}}):
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"choices": [{"message": {"content": "OK"}, "finish_reason": "stop"}]
}
mock_post.return_value = mock_response
ai_client.send(md_content="Context", user_message="Message 1", base_dir=".")
args, kwargs = mock_post.call_args
payload = kwargs["json"]
assert payload["model"] == "deepseek-reasoner"
assert "tools" not in payload
assert "temperature" not in payload
assert "max_tokens" not in payload

View File

@@ -19,11 +19,12 @@ 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.
"""
old_windows = [
"Projects", "Files", "Screenshots",
"Provider", "System Prompts",
"Message", "Response", "Tool Calls", "Comms History"
"Comms History"
]
for old_win in old_windows:
assert old_win not in app_instance.show_windows, f"Old window '{old_win}' should have been removed from show_windows"

View File

@@ -77,7 +77,11 @@ def test_render_log_management_logic(app_instance: App) -> None:
patch("src.gui_2.imgui.table_headers_row"), \
patch("src.gui_2.imgui.table_next_row"), \
patch("src.gui_2.imgui.table_next_column"), \
patch("src.gui_2.imgui.same_line"), \
patch("src.gui_2.imgui.text_colored"), \
patch("src.gui_2.imgui.separator"), \
patch("src.gui_2.imgui.button"):
mock_reg = MockRegistry.return_value
mock_reg.data = {
"session_1": {

View File

@@ -39,11 +39,18 @@ def test_visual_mma_components(live_gui):
client.push_event("mma_state_update", payload)
print(" - MMA state update pushed.")
# Use ApiHookClient.wait_for_event if we had a specific event to wait for,
# but here we just want to verify state.
time.sleep(1) # Small sleep for UI to catch up with event queue
# Poll for state update
success = False
for _ in range(50): # 10 seconds total
if client.get_value("mma_active_tier") == "Tier 3":
success = True
break
time.sleep(0.2)
assert success, f"State did not update to Tier 3. Current: {client.get_value('mma_active_tier')}"
# 3. Trigger HITL modal
print("Pushing 'mma_step_approval' event to trigger HITL modal...")
approval_payload = {
"ticket_id": "TICKET-002",