From 3085515587deb3b92a21ec4ee87edfe5d3ebc08a Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 9 Feb 2026 14:55:25 -0700 Subject: [PATCH 1/3] test: add CLI integration tests for ReactAgent runtime parameters (#368) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exercise the full CLI → runtime → ReactAgent path with MockProvider to catch wiring issues that unit tests with mocked dependencies miss. --- tests/cli/test_v2_cli_integration.py | 104 ++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/tests/cli/test_v2_cli_integration.py b/tests/cli/test_v2_cli_integration.py index ecc354d2..4d6695f3 100644 --- a/tests/cli/test_v2_cli_integration.py +++ b/tests/cli/test_v2_cli_integration.py @@ -771,6 +771,9 @@ def greet(name: str) -> str: return f"Hello, {name}!" ''' +# ReactAgent completes when LLM returns text-only (no tool calls). +MOCK_REACT_COMPLETION = "Task analysis complete. No changes needed." + def _make_mock_provider(responses: list[str]): """Create a MockProvider with queued text responses. @@ -958,7 +961,106 @@ def test_ai_golden_path(self, temp_repo, mock_llm): # --------------------------------------------------------------------------- -# 16. PR commands (GitHub integration) +# 16. ReactAgent CLI integration (issue #368) +# --------------------------------------------------------------------------- + + +class TestReactAgentIntegration: + """Integration tests for ReactAgent runtime parameters via CLI. + + Exercises the full CLI → runtime → ReactAgent path with MockProvider. + Covers verbose mode, dry-run mode, and streaming output (cf work follow). + + Ref: https://github.com/frankbria/codeframe/issues/368 + """ + + def test_react_verbose_mode(self, workspace_with_ready_tasks, mock_llm): + """work start --execute --verbose --engine react shows ReactAgent output.""" + mock_llm([MOCK_REACT_COMPLETION]) + + ws = create_or_load_workspace(workspace_with_ready_tasks) + task_list = tasks.list_tasks(ws, status=TaskStatus.READY) + assert len(task_list) > 0 + tid = task_list[0].id[:8] + + result = runner.invoke( + app, + [ + "work", "start", tid, + "--execute", "--verbose", "--engine", "react", + "-w", str(workspace_with_ready_tasks), + ], + ) + assert result.exit_code == 0, f"react verbose failed: {result.output}" + assert "engine=react" in result.output + assert "[ReactAgent]" in result.output + + def test_react_dry_run(self, workspace_with_ready_tasks, mock_llm): + """work start --execute --dry-run --engine react completes without error.""" + mock_llm([MOCK_REACT_COMPLETION]) + + ws = create_or_load_workspace(workspace_with_ready_tasks) + task_list = tasks.list_tasks(ws, status=TaskStatus.READY) + assert len(task_list) > 0 + tid = task_list[0].id[:8] + + result = runner.invoke( + app, + [ + "work", "start", tid, + "--execute", "--dry-run", "--engine", "react", + "-w", str(workspace_with_ready_tasks), + ], + ) + assert result.exit_code == 0, f"react dry-run failed: {result.output}" + assert "dry run" in result.output.lower() + + def test_react_streaming_output_log(self, workspace_with_ready_tasks, mock_llm): + """ReactAgent execution creates output.log readable by cf work follow.""" + mock_llm([MOCK_REACT_COMPLETION]) + + ws = create_or_load_workspace(workspace_with_ready_tasks) + task_list = tasks.list_tasks(ws, status=TaskStatus.READY) + assert len(task_list) > 0 + tid = task_list[0].id[:8] + + # Execute with react engine — creates output.log via RunOutputLogger + result = runner.invoke( + app, + [ + "work", "start", tid, + "--execute", "--engine", "react", + "-w", str(workspace_with_ready_tasks), + ], + ) + assert result.exit_code == 0, f"react execute failed: {result.output}" + + # Verify output.log was created by the ReactAgent execution + from codeframe.core import runtime + runs = runtime.list_runs(ws, task_id=task_list[0].id) + assert len(runs) > 0, "Expected at least one run for the task" + last_run = runs[-1] + + from codeframe.core.streaming import run_output_exists + assert run_output_exists(ws, last_run.id), ( + f"output.log should exist for run {last_run.id}" + ) + + # Verify cf work follow can read the completed run output + follow_result = runner.invoke( + app, + [ + "work", "follow", tid, + "-w", str(workspace_with_ready_tasks), + ], + ) + assert follow_result.exit_code == 0, ( + f"follow failed: {follow_result.output}" + ) + + +# --------------------------------------------------------------------------- +# 17. PR commands (GitHub integration) # --------------------------------------------------------------------------- From 9b279298f48d2174d710894343772bf2c76daeb9 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 9 Feb 2026 14:59:02 -0700 Subject: [PATCH 2/3] fix: add provider.call_count assertions to ReactAgent integration tests Captures mock_llm return value and asserts call_count >= 1 in all three tests, matching the existing pattern in TestAIAgentExecution. --- tests/cli/test_v2_cli_integration.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/cli/test_v2_cli_integration.py b/tests/cli/test_v2_cli_integration.py index 4d6695f3..3e4da1bd 100644 --- a/tests/cli/test_v2_cli_integration.py +++ b/tests/cli/test_v2_cli_integration.py @@ -976,7 +976,7 @@ class TestReactAgentIntegration: def test_react_verbose_mode(self, workspace_with_ready_tasks, mock_llm): """work start --execute --verbose --engine react shows ReactAgent output.""" - mock_llm([MOCK_REACT_COMPLETION]) + provider = mock_llm([MOCK_REACT_COMPLETION]) ws = create_or_load_workspace(workspace_with_ready_tasks) task_list = tasks.list_tasks(ws, status=TaskStatus.READY) @@ -994,10 +994,11 @@ def test_react_verbose_mode(self, workspace_with_ready_tasks, mock_llm): assert result.exit_code == 0, f"react verbose failed: {result.output}" assert "engine=react" in result.output assert "[ReactAgent]" in result.output + assert provider.call_count >= 1 def test_react_dry_run(self, workspace_with_ready_tasks, mock_llm): """work start --execute --dry-run --engine react completes without error.""" - mock_llm([MOCK_REACT_COMPLETION]) + provider = mock_llm([MOCK_REACT_COMPLETION]) ws = create_or_load_workspace(workspace_with_ready_tasks) task_list = tasks.list_tasks(ws, status=TaskStatus.READY) @@ -1014,10 +1015,11 @@ def test_react_dry_run(self, workspace_with_ready_tasks, mock_llm): ) assert result.exit_code == 0, f"react dry-run failed: {result.output}" assert "dry run" in result.output.lower() + assert provider.call_count >= 1 def test_react_streaming_output_log(self, workspace_with_ready_tasks, mock_llm): """ReactAgent execution creates output.log readable by cf work follow.""" - mock_llm([MOCK_REACT_COMPLETION]) + provider = mock_llm([MOCK_REACT_COMPLETION]) ws = create_or_load_workspace(workspace_with_ready_tasks) task_list = tasks.list_tasks(ws, status=TaskStatus.READY) @@ -1034,6 +1036,7 @@ def test_react_streaming_output_log(self, workspace_with_ready_tasks, mock_llm): ], ) assert result.exit_code == 0, f"react execute failed: {result.output}" + assert provider.call_count >= 1 # Verify output.log was created by the ReactAgent execution from codeframe.core import runtime From 528e91a384811e9479427115df2aec338b4d530d Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 9 Feb 2026 15:02:16 -0700 Subject: [PATCH 3/3] fix: address PR review feedback for ReactAgent integration tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix runs[-1] → runs[0]: list_runs returns newest first (CodeRabbit) - Move inline imports to top-level for consistency (Claude) - Assert follow output is non-empty to verify content display (Claude) - Rename last_run → latest_run for clarity --- tests/cli/test_v2_cli_integration.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/cli/test_v2_cli_integration.py b/tests/cli/test_v2_cli_integration.py index 3e4da1bd..b2cce076 100644 --- a/tests/cli/test_v2_cli_integration.py +++ b/tests/cli/test_v2_cli_integration.py @@ -18,8 +18,9 @@ from typer.testing import CliRunner from codeframe.cli.app import app -from codeframe.core import prd, tasks +from codeframe.core import prd, runtime, tasks from codeframe.core.state_machine import TaskStatus +from codeframe.core.streaming import run_output_exists from codeframe.core.workspace import create_or_load_workspace pytestmark = pytest.mark.v2 @@ -1039,14 +1040,12 @@ def test_react_streaming_output_log(self, workspace_with_ready_tasks, mock_llm): assert provider.call_count >= 1 # Verify output.log was created by the ReactAgent execution - from codeframe.core import runtime runs = runtime.list_runs(ws, task_id=task_list[0].id) assert len(runs) > 0, "Expected at least one run for the task" - last_run = runs[-1] + latest_run = runs[0] # list_runs returns newest first - from codeframe.core.streaming import run_output_exists - assert run_output_exists(ws, last_run.id), ( - f"output.log should exist for run {last_run.id}" + assert run_output_exists(ws, latest_run.id), ( + f"output.log should exist for run {latest_run.id}" ) # Verify cf work follow can read the completed run output @@ -1060,6 +1059,9 @@ def test_react_streaming_output_log(self, workspace_with_ready_tasks, mock_llm): assert follow_result.exit_code == 0, ( f"follow failed: {follow_result.output}" ) + assert len(follow_result.output.strip()) > 0, ( + "follow should display output from the completed run" + ) # ---------------------------------------------------------------------------