============================= test session starts =============================
platform win32 -- Python 3.11.6, pytest-9.0.2, pluggy-1.6.0
rootdir: C:\projects\manual_slop
configfile: pyproject.toml
plugins: anyio-4.12.1
collected 113 items

tests\conductor\test_infrastructure.py ....                              [  3%]
tests\test_agent_capabilities.py .                                       [  4%]
tests\test_agent_tools_wiring.py ..                                      [  6%]
tests\test_ai_client_cli.py .                                            [  7%]
tests\test_ai_context_history.py .                                       [  7%]
tests\test_api_events.py ....                                            [ 11%]
tests\test_api_hook_client.py ......                                     [ 16%]
tests\test_api_hook_extensions.py .....                                  [ 21%]
tests\test_cli_tool_bridge.py .FF                                        [ 23%]
tests\test_conductor_api_hook_integration.py ...                         [ 26%]
tests\test_extended_sims.py ....                                         [ 30%]
tests\test_gemini_cli_adapter.py ....                                    [ 33%]
tests\test_gemini_cli_integration.py FF                                  [ 35%]
tests\test_gemini_metrics.py .                                           [ 36%]
tests\test_gui2_events.py .                                              [ 37%]
tests\test_gui2_layout.py ..                                             [ 38%]
tests\test_gui2_mcp.py .                                                 [ 39%]
tests\test_gui2_parity.py ...                                            [ 42%]
tests\test_gui2_performance.py .s                                        [ 44%]
tests\test_gui_diagnostics.py ..                                         [ 46%]
tests\test_gui_events.py .                                               [ 46%]
tests\test_gui_performance_requirements.py .                             [ 47%]
tests\test_gui_stress_performance.py .                                   [ 48%]
tests\test_gui_updates.py ..                                             [ 50%]
tests\test_headless_api.py .........                                     [ 58%]
tests\test_headless_dependencies.py ..                                   [ 60%]
tests\test_headless_startup.py ..                                        [ 61%]
tests\test_history_blacklist.py ..                                       [ 63%]
tests\test_history_bleed.py F

================================== FAILURES ===================================
____________________ TestCliToolBridge.test_deny_decision _____________________

self = <test_cli_tool_bridge.TestCliToolBridge testMethod=test_deny_decision>
mock_request = <MagicMock name='request_confirmation' id='2685850806608'>
mock_stdout = <_io.StringIO object at 0x00000271259C3B50>
mock_stdin = <_io.StringIO object at 0x0000027158FFF2E0>

    @patch('sys.stdin', new_callable=io.StringIO)
    @patch('sys.stdout', new_callable=io.StringIO)
    @patch('api_hook_client.ApiHookClient.request_confirmation')
    def test_deny_decision(self, mock_request, mock_stdout, mock_stdin):
        # Mock stdin
        mock_stdin.write(json.dumps(self.tool_call))
        mock_stdin.seek(0)
    
        # 4. Mock ApiHookClient to return denied
        mock_request.return_value = {'approved': False}
    
        main()
    
        # Assert deny
        output = json.loads(mock_stdout.getvalue().strip())
>       self.assertEqual(output.get('decision'), 'deny')
E       AssertionError: 'allow' != 'deny'
E       - allow
E       + deny

tests\test_cli_tool_bridge.py:54: AssertionError
_______________ TestCliToolBridge.test_unreachable_hook_server ________________

self = <test_cli_tool_bridge.TestCliToolBridge testMethod=test_unreachable_hook_server>
mock_request = <MagicMock name='request_confirmation' id='2685851588240'>
mock_stdout = <_io.StringIO object at 0x0000027158FFF1C0>
mock_stdin = <_io.StringIO object at 0x00000271593A0A60>

    @patch('sys.stdin', new_callable=io.StringIO)
    @patch('sys.stdout', new_callable=io.StringIO)
    @patch('api_hook_client.ApiHookClient.request_confirmation')
    def test_unreachable_hook_server(self, mock_request, mock_stdout, mock_stdin):
        # Mock stdin
        mock_stdin.write(json.dumps(self.tool_call))
        mock_stdin.seek(0)
    
        # 5. Test case where hook server is unreachable (exception)
        mock_request.side_effect = Exception("Connection refused")
    
        main()
    
        # Assert deny on error
        output = json.loads(mock_stdout.getvalue().strip())
>       self.assertEqual(output.get('decision'), 'deny')
E       AssertionError: 'allow' != 'deny'
E       - allow
E       + deny

tests\test_cli_tool_bridge.py:71: AssertionError
______________________ test_gemini_cli_full_integration _______________________

live_gui = (<Popen: returncode: None args: ['uv', 'run', 'python', '-u', 'gui_2.py', '--...>, 'gui_2.py')

    def test_gemini_cli_full_integration(live_gui):
        """
        Integration test for the Gemini CLI provider and tool bridge.
        """
        client = ApiHookClient("http://127.0.0.1:8999")
    
        # 1. Setup paths and configure the GUI
        mock_script = os.path.abspath("tests/mock_gemini_cli.py")
        # Wrap in quotes for shell execution if path has spaces
        cli_cmd = f'"{sys.executable}" "{mock_script}"'
    
        # Set provider and binary path via GUI hooks
        # Note: Using set_value which now triggers the property setter in gui_2.py
        print(f"[TEST] Setting current_provider to gemini_cli")
        client.set_value("current_provider", "gemini_cli")
        print(f"[TEST] Setting gcli_path to {cli_cmd}")
        client.set_value("gcli_path", cli_cmd)
    
        # Verify settings were applied
        assert client.get_value("current_provider") == "gemini_cli"
        assert client.get_value("gcli_path") == cli_cmd
    
        # Clear events
        client.get_events()
    
        # 2. Trigger a message in the GUI
        print("[TEST] Sending user message...")
        client.set_value("ai_input", "Please read test.txt")
        client.click("btn_gen_send")
    
        # 3. Monitor for the 'ask_received' event
        print("[TEST] Waiting for ask_received event...")
        request_id = None
        timeout = 30
        start_time = time.time()
        while time.time() - start_time < timeout:
            events = client.get_events()
            if events:
                print(f"[TEST] Received {len(events)} events: {[e.get('type') for e in events]}")
            for ev in events:
                if ev.get("type") == "ask_received":
                    request_id = ev.get("request_id")
                    print(f"[TEST] Found request_id: {request_id}")
                    break
            if request_id:
                break
            time.sleep(0.5)
    
        assert request_id is not None, "Timed out waiting for 'ask_received' event from the bridge"
    
        # 4. Respond to the permission request
        print("[TEST] Responding to ask with approval")
        resp = requests.post(
            "http://127.0.0.1:8999/api/ask/respond",
            json={
                "request_id": request_id,
                "response": {"approved": True}
            }
        )
        assert resp.status_code == 200
    
        # 5. Verify that the final response is displayed in the GUI
        print("[TEST] Waiting for final message in history...")
        final_message_received = False
        start_time = time.time()
        while time.time() - start_time < timeout:
            session = client.get_session()
            entries = session.get("session", {}).get("entries", [])
            for entry in entries:
                content = entry.get("content", "")
                if "Hello from mock!" in content:
                    print(f"[TEST] Success! Found message: {content[:50]}...")
                    final_message_received = True
                    break
            if final_message_received:
                break
            time.sleep(1.0)
    
>       assert final_message_received, "Final message from mock CLI was not found in the GUI history"
E       AssertionError: Final message from mock CLI was not found in the GUI history
E       assert False

tests\test_gemini_cli_integration.py:86: AssertionError
---------------------------- Captured stdout call -----------------------------
[TEST] Setting current_provider to gemini_cli
[TEST] Setting gcli_path to "C:\projects\manual_slop\.venv\Scripts\python.exe" "C:\projects\manual_slop\tests\mock_gemini_cli.py"
[TEST] Sending user message...
[TEST] Waiting for ask_received event...
[TEST] Received 1 events: ['ask_received']
[TEST] Found request_id: e24686e7-274a-4cd0-a8a4-dc026d322dc9
[TEST] Responding to ask with approval
[TEST] Waiting for final message in history...
____________________ test_gemini_cli_rejection_and_history ____________________

live_gui = (<Popen: returncode: None args: ['uv', 'run', 'python', '-u', 'gui_2.py', '--...>, 'gui_2.py')

    def test_gemini_cli_rejection_and_history(live_gui):
        """
        Integration test for the Gemini CLI provider: Rejection flow and history.
        """
        client = ApiHookClient("http://127.0.0.1:8999")
    
        # 1. Setup paths and configure the GUI
        mock_script = os.path.abspath("tests/mock_gemini_cli.py")
        cli_cmd = f'"{sys.executable}" "{mock_script}"'
    
        client.set_value("current_provider", "gemini_cli")
        client.set_value("gcli_path", cli_cmd)
    
        # 2. Trigger a message that will be denied
        print("[TEST] Sending user message (to be denied)...")
        client.set_value("ai_input", "Deny me")
        client.click("btn_gen_send")
    
        # 3. Wait for 'ask_received' and respond with rejection
        request_id = None
        timeout = 15
        start_time = time.time()
        while time.time() - start_time < timeout:
            for ev in client.get_events():
                if ev.get("type") == "ask_received":
                    request_id = ev.get("request_id")
                    break
            if request_id: break
            time.sleep(0.5)
    
        assert request_id is not None
    
        print("[TEST] Responding to ask with REJECTION")
        requests.post("http://127.0.0.1:8999/api/ask/respond",
                     json={"request_id": request_id, "response": {"approved": False}})
    
        # 4. Verify rejection message in history
        print("[TEST] Waiting for rejection message in history...")
        rejection_found = False
        start_time = time.time()
        while time.time() - start_time < timeout:
            session = client.get_session()
            entries = session.get("session", {}).get("entries", [])
            for entry in entries:
                if "Tool execution was denied. Decision: deny" in entry.get("content", ""):
                    rejection_found = True
                    break
            if rejection_found: break
            time.sleep(1.0)
    
>       assert rejection_found, "Rejection message not found in history"
E       AssertionError: Rejection message not found in history
E       assert False

tests\test_gemini_cli_integration.py:138: AssertionError
---------------------------- Captured stdout call -----------------------------
[TEST] Sending user message (to be denied)...
[TEST] Responding to ask with REJECTION
[TEST] Waiting for rejection message in history...
_____________________ test_get_history_bleed_stats_basic ______________________

    def test_get_history_bleed_stats_basic():
        # Reset state
        ai_client.reset_session()
    
        # Mock some history
        ai_client.history_trunc_limit = 1000
        # Simulate 500 tokens used
        with MagicMock() as mock_stats:
            # This would usually involve patching the encoder or session logic
            pass
    
        stats = ai_client.get_history_bleed_stats()
        assert 'current' in stats
        assert 'limit' in stats
        # ai_client.py hardcodes Gemini limit to 900_000
>       assert stats['limit'] == 900000
E       assert 0 == 900000

tests\test_history_bleed.py:26: AssertionError
-------------------------- Captured stdout teardown ---------------------------

[Fixture] Finally block triggered: Shutting down gui_2.py...
[Fixture] Attempting to kill process tree for PID 5788...
[Fixture] Process tree 5788 killed.
=========================== short test summary info ===========================
FAILED tests/test_cli_tool_bridge.py::TestCliToolBridge::test_deny_decision - AssertionError: 'allow' != 'deny'
- allow
+ deny
FAILED tests/test_cli_tool_bridge.py::TestCliToolBridge::test_unreachable_hook_server - AssertionError: 'allow' != 'deny'
- allow
+ deny
FAILED tests/test_gemini_cli_integration.py::test_gemini_cli_full_integration - AssertionError: Final message from mock CLI was not found in the GUI history
assert False
FAILED tests/test_gemini_cli_integration.py::test_gemini_cli_rejection_and_history - AssertionError: Rejection message not found in history
assert False
FAILED tests/test_history_bleed.py::test_get_history_bleed_stats_basic - assert 0 == 900000
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 5 failures !!!!!!!!!!!!!!!!!!!!!!!!!!
============= 5 failed, 67 passed, 1 skipped in 163.79s (0:02:43) =============
