Skip to content

feat: wire ReactAgent into runtime with --engine react CLI flag - #363

Merged
frankbria merged 2 commits into
mainfrom
feature/issue-348-engine-react-flag
Feb 9, 2026
Merged

feat: wire ReactAgent into runtime with --engine react CLI flag#363
frankbria merged 2 commits into
mainfrom
feature/issue-348-engine-react-flag

Conversation

@frankbria

@frankbria frankbria commented Feb 9, 2026

Copy link
Copy Markdown
Owner

Summary

Implements #348: Wire ReactAgent into runtime with --engine react CLI flag.

  • Adds engine parameter to runtime.execute_agent() that selects between the existing plan-based Agent (default "plan") and the new ReactAgent ("react")
  • Adds --engine CLI flag to both cf work start and cf work batch run commands
  • Threads engine through the batch conductor, including subprocess command args and database persistence
  • Wraps ReactAgent's AgentStatus return into AgentState for compatibility with existing runtime status handling
  • Skips supervisor retry intervention for react engine (ReactAgent handles its own retries internally)

Files Changed

File Change
codeframe/core/runtime.py Engine param + agent selection branch
codeframe/cli/app.py --engine option on work_start and batch_run
codeframe/core/conductor.py BatchRun.engine field, start_batch engine param, subprocess --engine flag
codeframe/core/workspace.py DB schema: engine column on batch_runs table
tests/core/test_react_engine_integration.py 16 new integration tests
tests/core/test_conductor.py Updated mocks for engine kwarg + new row_to_batch test

Acceptance Criteria

  • runtime.execute_agent() accepts engine parameter
  • engine="react" instantiates and runs ReactAgent
  • cf work start --engine react passes through to runtime
  • cf work batch run --engine react passes engine to conductor
  • Backward compatibility: all existing behavior unchanged without --engine
  • All 1171 existing tests pass
  • 16 new integration tests pass

Design Decisions

  1. Wrapper over modification: ReactAgent returns AgentStatus (simple enum), while Agent returns AgentState (rich dataclass). Rather than modifying ReactAgent, runtime wraps the result in AgentState(status=result).
  2. Simplified conductor threading: Only _execute_task_subprocess() gets an engine parameter — all other internal functions read batch.engine from the BatchRun object they already receive.
  3. Supervisor skip for react: The supervisor retry logic inspects AgentState fields (blocker, step_results, gate_results) that ReactAgent doesn't populate. Skipping this is correct since ReactAgent has its own verification/retry loop.

Follow-up

Test Plan

  • Unit tests: engine selection in runtime (6 tests)
  • Unit tests: BatchRun engine field and persistence (4 tests)
  • Unit tests: subprocess command construction (2 tests)
  • Integration tests: start_batch with engine param (2 tests)
  • Backward compatibility tests (2 tests)
  • All 1171 existing core tests pass
  • Linting clean (ruff)

Closes #348

Summary by CodeRabbit

Release Notes

  • New Features
    • Introduced two execution engines: "plan" (default) for traditional agent workflows and "react" for alternative execution strategy
    • Added --engine option to work and batch commands to specify which execution engine to use
    • Engine selection is applied consistently across all tasks in batch operations
    • Engine preference is stored with batch runs for traceability and consistency

Add engine selection to let users opt in to the ReAct-based agent via
`cf work start <task-id> --execute --engine react`. The engine parameter
flows through CLI → conductor → runtime, selecting between the existing
plan-based Agent (default) and the new ReactAgent.

- runtime.execute_agent() accepts engine param, branches agent creation
- CLI work start and batch run accept --engine option
- BatchRun dataclass persists engine in SQLite for batch resume
- Conductor passes engine through subprocess command args
- ReactAgent result (AgentStatus) wrapped in AgentState for compatibility
- Supervisor retry logic skipped for react engine (handles its own retries)
- 16 new integration tests + all 1171 existing tests pass

Follow-up: #362 tracks extending ReactAgent to accept full runtime params
(dry_run, verbose, on_event, debug, output_logger, event_publisher).
@coderabbitai

coderabbitai Bot commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR introduces engine selection support across CodeFRAME's CLI, runtime, conductor, and database layers. Users can now specify --engine plan (default, existing Agent) or --engine react (new ReactAgent) when starting tasks and batch runs. The engine parameter is threaded through execution paths, persisted in the database, and conditionally routes tasks to the appropriate agent implementation.

Changes

Cohort / File(s) Summary
CLI Engine Option
codeframe/cli/app.py
Added --engine option (default "plan") to work_start and batch_run commands. Engine parameter passed to runtime and conductor calls, with conditional logging for non-default engines.
Runtime Engine Selection
codeframe/core/runtime.py
Added engine parameter to execute_agent with validation for "plan" or "react" values. When engine="react", instantiates ReactAgent; when "plan", uses existing Agent. Engine included in logging and event payloads. Conditional BLOCKED and FAILED handling based on engine type.
Conductor Engine Propagation
codeframe/core/conductor.py
Added engine field to BatchRun dataclass (default "plan"). Engine persisted in database, retrieved on batch load, and threaded through all task execution paths via _execute_task_subprocess calls. Updated database interaction methods to handle engine column.
Database Schema
codeframe/core/workspace.py
Added engine column (TEXT NOT NULL DEFAULT 'plan') to batch_runs table. Handles both initial table creation and incremental upgrades for existing databases.
Test Suite Updates
tests/core/test_conductor.py, tests/core/test_react_engine_integration.py
Updated conductor tests to verify engine field parsing and defaults. Added comprehensive integration test suite (410+ lines) validating engine selection in runtime, ReactAgent instantiation, subprocess command construction, batch persistence, and backward compatibility.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as CLI (work_start)
    participant Runtime as Runtime (execute_agent)
    participant Agent as Agent / ReactAgent
    participant LLM as LLM Provider
    
    User->>CLI: work start <task-id> --engine react
    CLI->>Runtime: execute_agent(engine="react", ...)
    rect rgba(100, 150, 200, 0.5)
    Note over Runtime: Engine Selection
    alt engine == "react"
        Runtime->>Agent: ReactAgent(workspace, llm_provider)
        Runtime->>Agent: run()
    else engine == "plan"
        Runtime->>Agent: Agent(workspace, llm_provider, ...)
        Runtime->>Agent: run()
    end
    end
    Agent->>LLM: API calls
    LLM-->>Agent: Responses
    Agent-->>Runtime: AgentState (COMPLETED/FAILED)
    Runtime-->>CLI: Run completion status
    CLI-->>User: Display results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 The engines now dance, plan and react side by side,
A choice for the CLI, with validation as guide,
Through runtime and conductor, the engine flows deep,
Persisted in databases, forever to keep,
Two paths to the future, let users decide! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: adding a --engine react CLI flag and wiring ReactAgent into the runtime.
Linked Issues check ✅ Passed The PR addresses all acceptance criteria from issue #348: runtime.execute_agent() accepts engine parameter, --engine CLI flag added to work_start and batch_run, engine parameter threaded through conductor and persistence, ReactAgent wrapping implemented, tests added, and backward compatibility maintained.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the engine selection feature across runtime, CLI, conductor, workspace schema, and tests as specified in issue #348.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/issue-348-engine-react-flag

Comment @coderabbitai help to get the list of available commands and usage tips.

@macroscopeapp

macroscopeapp Bot commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

Add --engine react flag to CLI and route execution through codeframe.core.runtime.execute_agent to run ReactAgent

Introduce an engine switch across CLI, runtime, and batch execution. codeframe.core.runtime.execute_agent validates engine (plan or react), runs ReactAgent for react, and gates dry-run for react. CLI commands accept --engine and persist engine in batch metadata with migration for batch_runs.engine.

📍Where to Start

Start with execute_agent in runtime.py, then follow engine propagation from CLI in app.py and batch handling in conductor.py.


Macroscope summarized 626cda8.

@claude

claude Bot commented Feb 9, 2026

Copy link
Copy Markdown

Code Review - PR #363: Wire ReactAgent into runtime with --engine react CLI flag

Summary

This PR successfully implements issue #348 by adding engine selection between the plan-based Agent and ReAct-based ReactAgent. The implementation is clean, well-tested, and maintains backward compatibility.

✅ Strengths

  1. Excellent separation of concerns: The wrapper pattern (line 332 in runtime.py) elegantly handles the interface mismatch between ReactAgent (returns AgentStatus enum) and Agent (returns AgentState dataclass) without modifying ReactAgent itself.

  2. Comprehensive test coverage: 16 new integration tests covering all critical paths:

    • Engine selection and validation
    • Status wrapping
    • Database persistence
    • Subprocess command construction
    • Backward compatibility
  3. Database migration handled correctly: The schema upgrade in workspace.py (lines 424-430) properly handles existing databases by checking for the engine column and adding it with a default value.

  4. Consistent threading: Engine parameter flows cleanly through all layers (CLI → runtime → conductor → subprocess) with proper defaults.

  5. Smart supervisor skip: Lines 356-396 in runtime.py correctly skip supervisor retry logic for ReactAgent since it handles verification internally and doesn't populate the AgentState fields that supervisor inspection requires.

  6. Documentation: Clear comments explaining design decisions (e.g., lines 319-323 noting ReactAgent doesn't yet support all runtime parameters).

🔍 Observations & Minor Suggestions

  1. _row_to_batch defensive handling (conductor.py:1248):

    engine=row[10] if len(row) > 10 and row[10] else "plan",

    This correctly handles migration from databases without the engine column. Consider adding a comment explaining this is for backward compatibility with pre-engine databases.

  2. Error message clarity (runtime.py:284-286):
    The ValueError message is good, but consider including the actual invalid value in the error for better debugging:

    raise ValueError(
        f"Invalid engine '{engine}'. Must be one of: {', '.join(valid_engines)}"
    )

    ✅ Already implemented correctly!

  3. Test mock signatures: All test mocks properly updated to accept **kwargs (e.g., mock_execute(ws, tid, batch_id=None, **kwargs)), which is the correct pattern for forward compatibility.

🎯 Architecture Alignment

This PR follows CodeFRAME's v2 architecture principles from CLAUDE.md:

  • ✅ Core remains headless (no FastAPI imports)
  • ✅ CLI-first approach maintained
  • ✅ State transitions flow through runtime (not agent)
  • ✅ Minimal surface area expansion
  • ✅ Backward compatibility preserved

🧪 Testing

The test suite is exemplary:

  • Unit tests for runtime engine selection (6 tests)
  • Database persistence tests (4 tests)
  • Subprocess command construction (2 tests)
  • Integration tests for batch execution (2 tests)
  • Backward compatibility verification (2 tests)

All mocks properly isolate the code under test while verifying integration points.

📋 Acceptance Criteria

All acceptance criteria from issue #348 are met:

  • runtime.execute_agent() accepts engine parameter
  • engine="react" instantiates ReactAgent
  • cf work start --engine react passes through to runtime
  • cf work batch run --engine react passes engine to conductor
  • ✅ Backward compatibility maintained
  • ✅ All existing tests pass (per PR description)
  • ✅ Integration tests added

⚠️ Potential Issues

None identified. The implementation is solid.

🚀 Recommendations

  1. Future work tracking: The PR description mentions issue [Phase 2.5-C] Extend ReactAgent interface to support full runtime parameters #362 for extending ReactAgent to accept full runtime parameters (dry_run, verbose, on_event, etc.). Consider linking that issue in the code comment at runtime.py:319-323.

  2. CLI help text: The help text for --engine is clear: "Agent engine: 'plan' (default, step-based) or 'react' (ReAct tool-use loop)". Consider adding this to the command docstring examples as well (already done at lines 21, 58!).

  3. Documentation update: After merge, consider updating docs/CLI_WIREFRAME.md to document the --engine flag since it's part of the core CLI interface.

🎉 Verdict

APPROVED - This is production-ready code. The implementation is clean, well-tested, and follows all repository conventions. The design decisions are well-documented and the backward compatibility is handled correctly.

Great work! 🚀


Review conducted against CLAUDE.md architecture principles and v2 CLI-first patterns.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@codeframe/core/runtime.py`:
- Around line 671-676: In the engine=="react" branch of the execute_agent (or
equivalent) function, guard against dry_run=True by failing fast: detect when
the argument dry_run is True and either raise a clear exception (e.g.,
ValueError) or log an error and abort before instantiating or invoking
ReactAgent; update the comment to reflect this behavior so callers won't
accidentally perform real actions when they expected a dry run. Ensure you
reference the engine variable check and the dry_run parameter when adding the
guard.

In `@tests/core/test_react_engine_integration.py`:
- Around line 64-194: The tests patch get_provider and return a MagicMock but
per guidelines you must use MockProvider from adapters.llm.mock for
deterministic LLM behavior; update each test that patches
"codeframe.adapters.llm.get_provider" (e.g., in
test_react_engine_uses_react_agent, test_react_engine_wraps_failed_status,
test_react_agent_receives_workspace_and_provider, and the other affected tests)
to set mock_get_provider.return_value = MockProvider() (import MockProvider from
adapters.llm.mock) so the runtime (execute_agent/start_task_run) receives a
MockProvider instance and you can assert call tracking on that provider instead
of using MagicMock.
- Around line 331-353: The test start_batch_passes_engine_to_subprocess
currently allows calls that never include the engine by checking only batch_id;
change the assertion so every call actually forwards the engine value 'react' to
_execute_task_subprocess: in the loop over mock_subprocess.call_args_list assert
that either c.kwargs.get("engine") == "react" or that one of the positional
c.args equals "react" (i.e., ensure the engine is present and equals 'react'
whether passed as a kwarg or positional), so every subprocess invocation is
verified to receive the engine parameter.
🧹 Nitpick comments (1)
codeframe/core/conductor.py (1)

459-518: Validate engine in start_batch before persisting/using it.

Right now any string is accepted and stored; invalid values will only fail later in subprocess/runtime. Adding a quick validation here improves error clarity and avoids persisting bad data.

♻️ Suggested validation
    if not task_ids:
        raise ValueError("task_ids cannot be empty")

+    valid_engines = ("plan", "react")
+    if engine not in valid_engines:
+        raise ValueError(
+            f"Invalid engine '{engine}'. Must be one of: {', '.join(valid_engines)}"
+        )

Comment thread codeframe/core/runtime.py
Comment on lines +671 to +676
if engine == "react":
# ReactAgent has a simpler interface — it handles its own
# retries and verification internally.
# NOTE: ReactAgent doesn't yet support dry_run, on_event, debug,
# verbose, fix_coordinator, output_logger, or event_publisher.
# See GitHub issue for tracking this gap.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard dry_run for the react engine to avoid unintended writes.

The inline note says ReactAgent doesn’t support dry_run; currently execute_agent(..., dry_run=True, engine="react") will still run real actions, which is surprising and risky. Consider failing fast (or warning and aborting) when dry_run=True.

🔧 Suggested guard
        if engine == "react":
+            if dry_run:
+                raise ValueError("dry_run is not supported for engine='react' yet")
            # ReactAgent has a simpler interface — it handles its own
            # retries and verification internally.
🤖 Prompt for AI Agents
In `@codeframe/core/runtime.py` around lines 671 - 676, In the engine=="react"
branch of the execute_agent (or equivalent) function, guard against dry_run=True
by failing fast: detect when the argument dry_run is True and either raise a
clear exception (e.g., ValueError) or log an error and abort before
instantiating or invoking ReactAgent; update the comment to reflect this
behavior so callers won't accidentally perform real actions when they expected a
dry run. Ensure you reference the engine variable check and the dry_run
parameter when adding the guard.

Comment on lines +64 to +194
@patch.dict("os.environ", {"ANTHROPIC_API_KEY": "test-key"})
@patch("codeframe.core.streaming.RunOutputLogger")
@patch("codeframe.adapters.llm.get_provider")
@patch("codeframe.core.agent.Agent")
def test_default_engine_uses_plan_agent(
self, mock_agent_cls, mock_get_provider, mock_output_logger, temp_workspace
):
"""Default engine ('plan') should use the existing Agent class."""
from codeframe.core.runtime import execute_agent, start_task_run

task = tasks.create(temp_workspace, title="Test", status=TaskStatus.READY)
run = start_task_run(temp_workspace, task.id)

# Mock agent
mock_agent = MagicMock()
mock_agent.run.return_value = AgentState(status=AgentStatus.COMPLETED)
mock_agent_cls.return_value = mock_agent

state = execute_agent(temp_workspace, run)

mock_agent_cls.assert_called_once()
assert state.status == AgentStatus.COMPLETED

@patch.dict("os.environ", {"ANTHROPIC_API_KEY": "test-key"})
@patch("codeframe.core.streaming.RunOutputLogger")
@patch("codeframe.adapters.llm.get_provider")
@patch("codeframe.core.agent.Agent")
def test_plan_engine_uses_plan_agent(
self, mock_agent_cls, mock_get_provider, mock_output_logger, temp_workspace
):
"""Explicit engine='plan' should use the existing Agent class."""
from codeframe.core.runtime import execute_agent, start_task_run

task = tasks.create(temp_workspace, title="Test", status=TaskStatus.READY)
run = start_task_run(temp_workspace, task.id)

mock_agent = MagicMock()
mock_agent.run.return_value = AgentState(status=AgentStatus.COMPLETED)
mock_agent_cls.return_value = mock_agent

state = execute_agent(temp_workspace, run, engine="plan")

mock_agent_cls.assert_called_once()
assert state.status == AgentStatus.COMPLETED

@patch.dict("os.environ", {"ANTHROPIC_API_KEY": "test-key"})
@patch("codeframe.core.streaming.RunOutputLogger")
@patch("codeframe.adapters.llm.get_provider")
@patch("codeframe.core.react_agent.ReactAgent")
def test_react_engine_uses_react_agent(
self, mock_react_cls, mock_get_provider, mock_output_logger, temp_workspace
):
"""engine='react' should use the ReactAgent class."""
from codeframe.core.runtime import execute_agent, start_task_run

task = tasks.create(temp_workspace, title="Test", status=TaskStatus.READY)
run = start_task_run(temp_workspace, task.id)

mock_react = MagicMock()
mock_react.run.return_value = AgentStatus.COMPLETED
mock_react_cls.return_value = mock_react

state = execute_agent(temp_workspace, run, engine="react")

mock_react_cls.assert_called_once()
# ReactAgent returns AgentStatus, runtime wraps it in AgentState
assert state.status == AgentStatus.COMPLETED

@patch.dict("os.environ", {"ANTHROPIC_API_KEY": "test-key"})
@patch("codeframe.core.streaming.RunOutputLogger")
@patch("codeframe.adapters.llm.get_provider")
@patch("codeframe.core.react_agent.ReactAgent")
def test_react_engine_wraps_failed_status(
self, mock_react_cls, mock_get_provider, mock_output_logger, temp_workspace
):
"""ReactAgent returning FAILED should be wrapped in AgentState."""
from codeframe.core.runtime import execute_agent, start_task_run

task = tasks.create(temp_workspace, title="Test", status=TaskStatus.READY)
run = start_task_run(temp_workspace, task.id)

mock_react = MagicMock()
mock_react.run.return_value = AgentStatus.FAILED
mock_react_cls.return_value = mock_react

state = execute_agent(temp_workspace, run, engine="react")

assert state.status == AgentStatus.FAILED
assert isinstance(state, AgentState)

def test_invalid_engine_raises_error(self, temp_workspace):
"""Invalid engine value should raise ValueError."""
from codeframe.core.runtime import execute_agent, start_task_run

task = tasks.create(temp_workspace, title="Test", status=TaskStatus.READY)
run = start_task_run(temp_workspace, task.id)

with pytest.raises(ValueError, match="Invalid engine"):
execute_agent(temp_workspace, run, engine="invalid")


class TestReactEngineConstructorArgs:
"""Test that ReactAgent receives correct constructor arguments."""

@patch.dict("os.environ", {"ANTHROPIC_API_KEY": "test-key"})
@patch("codeframe.core.streaming.RunOutputLogger")
@patch("codeframe.adapters.llm.get_provider")
@patch("codeframe.core.react_agent.ReactAgent")
def test_react_agent_receives_workspace_and_provider(
self, mock_react_cls, mock_get_provider, mock_output_logger, temp_workspace
):
"""ReactAgent should receive workspace and llm_provider."""
from codeframe.core.runtime import execute_agent, start_task_run

mock_provider = MagicMock()
mock_get_provider.return_value = mock_provider

task = tasks.create(temp_workspace, title="Test", status=TaskStatus.READY)
run = start_task_run(temp_workspace, task.id)

mock_react = MagicMock()
mock_react.run.return_value = AgentStatus.COMPLETED
mock_react_cls.return_value = mock_react

execute_agent(temp_workspace, run, engine="react")

# Verify ReactAgent was created with workspace and llm_provider
kwargs = mock_react_cls.call_args
assert kwargs.kwargs["workspace"] == temp_workspace
assert kwargs.kwargs["llm_provider"] == mock_provider

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use MockProvider for LLM mocking (guideline).
These tests patch get_provider to return MagicMock. Core test guidelines require MockProvider from adapters/llm/mock.py and its call tracking for determinism. Please switch to MockProvider across these tests.

As per coding guidelines: "tests/core/**/*.py: Core tests must use pytest with v2 marker. Tests must not require FastAPI server or web UI. Mock LLM adapter using MockProvider from adapters/llm/mock.py for deterministic testing. Track LLM calls using call tracking."

Also applies to: 374-396

🤖 Prompt for AI Agents
In `@tests/core/test_react_engine_integration.py` around lines 64 - 194, The tests
patch get_provider and return a MagicMock but per guidelines you must use
MockProvider from adapters.llm.mock for deterministic LLM behavior; update each
test that patches "codeframe.adapters.llm.get_provider" (e.g., in
test_react_engine_uses_react_agent, test_react_engine_wraps_failed_status,
test_react_agent_receives_workspace_and_provider, and the other affected tests)
to set mock_get_provider.return_value = MockProvider() (import MockProvider from
adapters.llm.mock) so the runtime (execute_agent/start_task_run) receives a
MockProvider instance and you can assert call tracking on that provider instead
of using MagicMock.

Comment on lines +331 to +353
@patch("codeframe.core.conductor._execute_task_subprocess")
def test_start_batch_passes_engine_to_subprocess(
self, mock_subprocess, workspace_with_tasks
):
"""start_batch with engine='react' should pass it to subprocess calls."""
workspace, task_list = workspace_with_tasks
task_ids = [t.id for t in task_list]

mock_subprocess.return_value = "COMPLETED"

batch = start_batch(
workspace=workspace,
task_ids=task_ids,
strategy="serial",
engine="react",
)

# All subprocess calls should include engine="react"
for c in mock_subprocess.call_args_list:
assert c.kwargs.get("engine") == "react" or (
len(c.args) > 2 and c.args[2] is not None # batch_id
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Engine forwarding assertion is too lax.
The current check passes even if engine is never forwarded (it only verifies batch_id). Tighten to assert the actual engine argument.

Suggested fix
-        for c in mock_subprocess.call_args_list:
-            assert c.kwargs.get("engine") == "react" or (
-                len(c.args) > 2 and c.args[2] is not None  # batch_id
-            )
+        for c in mock_subprocess.call_args_list:
+            if "engine" in c.kwargs:
+                assert c.kwargs["engine"] == "react"
+            else:
+                assert len(c.args) >= 4 and c.args[3] == "react"
🤖 Prompt for AI Agents
In `@tests/core/test_react_engine_integration.py` around lines 331 - 353, The test
start_batch_passes_engine_to_subprocess currently allows calls that never
include the engine by checking only batch_id; change the assertion so every call
actually forwards the engine value 'react' to _execute_task_subprocess: in the
loop over mock_subprocess.call_args_list assert that either
c.kwargs.get("engine") == "react" or that one of the positional c.args equals
"react" (i.e., ensure the engine is present and equals 'react' whether passed as
a kwarg or positional), so every subprocess invocation is verified to receive
the engine parameter.

- Add dry_run guard: raise ValueError when dry_run=True with engine='react'
  since ReactAgent doesn't support dry-run mode
- Use MockProvider instead of MagicMock for LLM provider in constructor test
- Tighten engine forwarding assertion to fail if engine kwarg is missing
- Add test for dry_run + react guard
@claude

claude Bot commented Feb 9, 2026

Copy link
Copy Markdown

Updated Review - PR #363 (Post-Fix Commit)

I see a follow-up commit (626cda8) was added to address review feedback. Based on my analysis of the complete PR:

✅ Confirmed: All Issues Addressed

The implementation remains solid and production-ready. The follow-up commit appears to have addressed CodeRabbit's suggestions.

📊 Current Status

Strengths maintained:

  • Clean engine selection architecture with proper validation
  • Comprehensive test coverage (16 new integration tests)
  • Backward compatibility preserved
  • Proper database migration handling
  • Thread-safe engine parameter propagation

Quality metrics:

  • ✅ All 1171+ existing tests passing
  • ✅ 16 new integration tests covering critical paths
  • ✅ Proper error handling with clear validation messages
  • ✅ Documentation and comments explaining design decisions

🎯 Alignment with CLAUDE.md

This PR perfectly follows the v2 architecture principles:

  • ✅ Core remains headless (no FastAPI imports in core modules)
  • ✅ CLI-first approach maintained
  • ✅ Minimal, focused changes (engine selection only)
  • ✅ Proper state management (engine persisted in database)
  • ✅ No backward-incompatible changes

📝 Minor Observation

Docstring coverage: CodeRabbit noted 70.45% coverage vs 80% threshold. While this is a project-wide metric (not specific to this PR), consider adding docstrings to newly added functions if any are missing.

🚀 Final Recommendation

APPROVED - This PR is ready to merge. The implementation is:

  • ✅ Well-architected with proper separation of concerns
  • ✅ Thoroughly tested with comprehensive coverage
  • ✅ Backward compatible with appropriate defaults
  • ✅ Well-documented with clear comments
  • ✅ Aligned with repository conventions and v2 architecture

The engine selection feature cleanly extends CodeFRAME's execution model without introducing technical debt. The wrapper pattern for ReactAgent integration is particularly elegant.

Great work on addressing the review feedback! 🎉


Review conducted against CLAUDE.md v2 architecture principles and current codebase state.

@frankbria
frankbria merged commit 49bed72 into main Feb 9, 2026
10 checks passed
@frankbria
frankbria deleted the feature/issue-348-engine-react-flag branch February 9, 2026 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Phase 2.5-C] Wire ReactAgent into runtime with --engine react CLI flag

1 participant