Files
temp/features/steps/plan_executor_edge_cases_coverage_steps.py
freemo 2eb31a598c test(coverage): add Behave BDD tests for 8 under-covered modules
Added targeted Behave BDD feature files and step definitions to improve
unit test coverage for:

- decision_service.py: Full coverage of all 7 service methods (18 scenarios)
- plan_apply_service.py: Branch coverage for handle_merge_failure (2 scenarios)
- plan_executor.py: Edge cases for rollback, checkpoint, and parse_steps (15 scenarios)
- cli/commands/plan.py: Uncovered region lines 1950-2273 (23 scenarios)
- repositories.py: Remaining missed branches and lines (14 scenarios)
- sandbox/checkpoint.py: Full coverage of CheckpointManager (26 scenarios)
- langgraph/bridge.py: Remaining uncovered lines and branches (10 scenarios)
- cli/commands/config.py: Safety net to maintain 100% coverage (42 scenarios)

Total: 150 new scenarios, 596 steps, all passing.

Also fixed a step definition collision in plan_lifecycle_coverage by renaming
"the delete result should be false" to "the plan delete result should be false".

ISSUES CLOSED: #475
2026-03-01 03:09:51 +00:00

570 lines
22 KiB
Python

"""Step definitions for plan_executor_edge_cases_coverage.feature.
Targets uncovered lines and branches in plan_executor.py:
- Line 378 / branch 377→378: _try_rollback_to_last_checkpoint with non-empty checkpoints
- Lines 410-411: _resolve_sandbox_for_checkpoint → _SandboxRootProxy fallback
- Lines 161-163 / branches 160→161, 162→163: _parse_steps non-empty path
- Lines 417-419: run_strategize function definition
All step names use the 'edge3' prefix to avoid collisions with existing step files.
"""
from __future__ import annotations
from typing import Any
from unittest.mock import MagicMock, patch
from behave import given, then, when
from behave.runner import Context
from cleveragents.application.services.plan_executor import (
ExecuteResult,
PlanExecutor,
)
from cleveragents.domain.models.core.plan import (
PlanPhase,
PlanTimestamps,
ProcessingState,
)
from cleveragents.infrastructure.sandbox.checkpoint import SandboxCheckpoint
# ---------------------------------------------------------------------------
# Constants
# ---------------------------------------------------------------------------
EDGE3_PLAN_ID = "01KEDGE3PLANID00000000PLN"
EDGE3_ROOT_ID = "01KEDGE3ROOTID00000000RTD"
EDGE3_SANDBOX_ROOT = "/tmp/edge3-sandbox"
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _edge3_make_plan(
*,
phase: PlanPhase = PlanPhase.EXECUTE,
state: ProcessingState = ProcessingState.QUEUED,
definition_of_done: str | None = "Implement feature\nWrite tests",
decision_root_id: str | None = EDGE3_ROOT_ID,
) -> MagicMock:
"""Build a mock plan object with sensible defaults."""
plan = MagicMock()
plan.phase = phase
plan.state = state
plan.definition_of_done = definition_of_done
plan.decision_root_id = decision_root_id
plan.invariants = []
plan.timestamps = PlanTimestamps()
plan.changeset_id = None
plan.sandbox_refs = []
plan.error_details = None
plan.read_only = False
return plan
def _edge3_make_lifecycle(plan: Any | None = None) -> MagicMock:
"""Build a mock lifecycle service."""
lcs = MagicMock()
if plan is not None:
lcs.get_plan.return_value = plan
lcs.start_strategize = MagicMock()
lcs.complete_strategize = MagicMock()
lcs.fail_strategize = MagicMock()
lcs.start_execute = MagicMock()
lcs.complete_execute = MagicMock()
lcs.fail_execute = MagicMock()
lcs._commit_plan = MagicMock()
return lcs
def _edge3_make_checkpoint_mock() -> SandboxCheckpoint:
"""Create a mock SandboxCheckpoint."""
from datetime import UTC, datetime
return SandboxCheckpoint(
checkpoint_id="01KEDGE3CPID0000000000CP",
sandbox_id="root-EDGE3PLAN",
plan_id="EDGE3PLAN",
phase="pre_execute",
created_at=datetime.now(tz=UTC),
metadata={},
snapshot_path="/tmp/edge3-snapshot",
)
# ---------------------------------------------------------------------------
# _resolve_sandbox_for_checkpoint → _SandboxRootProxy path
# ---------------------------------------------------------------------------
@given(
"an edge3 PlanExecutor with checkpoint manager and sandbox root but no execution context"
)
def step_edge3_given_executor_sandbox_root_no_ctx(context: Context) -> None:
"""Create PlanExecutor with checkpoint_manager and sandbox_root, no exec context."""
context.edge3_checkpoint_mgr = MagicMock()
context.edge3_executor = PlanExecutor(
lifecycle_service=_edge3_make_lifecycle(),
sandbox_root=EDGE3_SANDBOX_ROOT,
execution_context=None,
checkpoint_manager=context.edge3_checkpoint_mgr,
)
@given(
"an edge3 PlanExecutor with checkpoint manager and sandbox root and context without sandbox manager"
)
def step_edge3_given_executor_ctx_no_sbmgr(context: Context) -> None:
"""Create PlanExecutor with exec context that has no sandbox_manager attr."""
context.edge3_checkpoint_mgr = MagicMock()
# Execution context without sandbox_manager attribute
exec_ctx = MagicMock(spec=[]) # empty spec → no attributes
context.edge3_executor = PlanExecutor(
lifecycle_service=_edge3_make_lifecycle(),
sandbox_root=EDGE3_SANDBOX_ROOT,
execution_context=exec_ctx,
checkpoint_manager=context.edge3_checkpoint_mgr,
)
@given(
"an edge3 PlanExecutor with checkpoint manager and sandbox root and context with empty sandboxes"
)
def step_edge3_given_executor_ctx_empty_sandboxes(context: Context) -> None:
"""Create PlanExecutor with exec context whose sandbox_manager returns []."""
context.edge3_checkpoint_mgr = MagicMock()
exec_ctx = MagicMock()
exec_ctx.sandbox_manager = MagicMock()
exec_ctx.sandbox_manager.list_sandboxes.return_value = []
context.edge3_executor = PlanExecutor(
lifecycle_service=_edge3_make_lifecycle(),
sandbox_root=EDGE3_SANDBOX_ROOT,
execution_context=exec_ctx,
checkpoint_manager=context.edge3_checkpoint_mgr,
)
@given(
"an edge3 PlanExecutor with checkpoint manager but no sandbox root and no execution context"
)
def step_edge3_given_executor_no_sandbox_no_ctx(context: Context) -> None:
"""Create PlanExecutor with checkpoint_manager but no sandbox_root and no exec context."""
context.edge3_checkpoint_mgr = MagicMock()
context.edge3_executor = PlanExecutor(
lifecycle_service=_edge3_make_lifecycle(),
sandbox_root=None,
execution_context=None,
checkpoint_manager=context.edge3_checkpoint_mgr,
)
@when('I edge3 resolve sandbox for checkpoint with plan id "{plan_id}"')
def step_edge3_resolve_sandbox(context: Context, plan_id: str) -> None:
"""Call _resolve_sandbox_for_checkpoint directly."""
context.edge3_resolved_sandbox = (
context.edge3_executor._resolve_sandbox_for_checkpoint(plan_id)
)
@then("the edge3 resolved sandbox should not be None")
def step_edge3_resolved_not_none(context: Context) -> None:
"""Verify resolved sandbox is not None."""
assert context.edge3_resolved_sandbox is not None, (
"Expected a sandbox-like object but got None"
)
@then("the edge3 resolved sandbox should have a synthetic sandbox id")
def step_edge3_resolved_has_sandbox_id(context: Context) -> None:
"""Verify the resolved sandbox has a sandbox_id starting with 'root-'."""
sid = context.edge3_resolved_sandbox.sandbox_id
assert sid.startswith("root-"), (
f"Expected sandbox_id starting with 'root-', got '{sid}'"
)
@then("the edge3 resolved sandbox context should have the sandbox path")
def step_edge3_resolved_has_sandbox_path(context: Context) -> None:
"""Verify the resolved sandbox context has the correct sandbox_path."""
ctx = context.edge3_resolved_sandbox.context
assert ctx is not None, "Expected context to be non-None"
assert ctx.sandbox_path == EDGE3_SANDBOX_ROOT, (
f"Expected sandbox_path='{EDGE3_SANDBOX_ROOT}', got '{ctx.sandbox_path}'"
)
@then("the edge3 resolved sandbox should be None")
def step_edge3_resolved_is_none(context: Context) -> None:
"""Verify resolved sandbox is None."""
assert context.edge3_resolved_sandbox is None, (
f"Expected None but got {context.edge3_resolved_sandbox}"
)
# ---------------------------------------------------------------------------
# _try_rollback_to_last_checkpoint with non-empty checkpoints
# ---------------------------------------------------------------------------
@given(
"the edge3 checkpoint manager has existing checkpoints that rollback successfully"
)
def step_edge3_given_checkpoints_rollback_ok(context: Context) -> None:
"""Configure checkpoint_manager to return checkpoints and succeed on rollback."""
cp = _edge3_make_checkpoint_mock()
context.edge3_checkpoint_mgr.list_checkpoints.return_value = [cp]
context.edge3_checkpoint_mgr.rollback_to.return_value = True
@given("the edge3 checkpoint manager has checkpoints but rollback raises an exception")
def step_edge3_given_checkpoints_rollback_raises(context: Context) -> None:
"""Configure checkpoint_manager with checkpoints but rollback_to raises."""
cp = _edge3_make_checkpoint_mock()
context.edge3_checkpoint_mgr.list_checkpoints.return_value = [cp]
context.edge3_checkpoint_mgr.rollback_to.side_effect = RuntimeError(
"edge3 rollback boom"
)
@given("the edge3 checkpoint manager returns no checkpoints")
def step_edge3_given_no_checkpoints(context: Context) -> None:
"""Configure checkpoint_manager to return empty checkpoints list."""
context.edge3_checkpoint_mgr.list_checkpoints.return_value = []
@when('I edge3 try rollback to last checkpoint for plan "{plan_id}"')
def step_edge3_try_rollback(context: Context, plan_id: str) -> None:
"""Call _try_rollback_to_last_checkpoint directly."""
context.edge3_rollback_result = (
context.edge3_executor._try_rollback_to_last_checkpoint(plan_id)
)
@then("the edge3 rollback result should be True")
def step_edge3_rollback_true(context: Context) -> None:
"""Verify rollback returned True."""
assert context.edge3_rollback_result is True, (
f"Expected True, got {context.edge3_rollback_result}"
)
@then("the edge3 rollback result should be False")
def step_edge3_rollback_false(context: Context) -> None:
"""Verify rollback returned False."""
assert context.edge3_rollback_result is False, (
f"Expected False, got {context.edge3_rollback_result}"
)
# ---------------------------------------------------------------------------
# _try_create_checkpoint via _SandboxRootProxy
# ---------------------------------------------------------------------------
@given("the edge3 checkpoint manager accepts checkpoint creation")
def step_edge3_given_checkpoint_create_ok(context: Context) -> None:
"""Configure checkpoint_manager.create_checkpoint to return a checkpoint."""
cp = _edge3_make_checkpoint_mock()
context.edge3_checkpoint_mgr.create_checkpoint.return_value = cp
@given("the edge3 checkpoint manager raises on create_checkpoint")
def step_edge3_given_checkpoint_create_fails(context: Context) -> None:
"""Configure checkpoint_manager.create_checkpoint to raise."""
context.edge3_checkpoint_mgr.create_checkpoint.side_effect = RuntimeError(
"edge3 create boom"
)
@when('I edge3 try create checkpoint for plan "{plan_id}" with phase "{phase}"')
def step_edge3_try_create_checkpoint(
context: Context, plan_id: str, phase: str
) -> None:
"""Call _try_create_checkpoint directly."""
context.edge3_checkpoint_result = context.edge3_executor._try_create_checkpoint(
plan_id, phase
)
@then("the edge3 checkpoint result should not be None")
def step_edge3_checkpoint_not_none(context: Context) -> None:
"""Verify checkpoint creation returned a checkpoint."""
assert context.edge3_checkpoint_result is not None, (
"Expected a SandboxCheckpoint but got None"
)
@then("the edge3 checkpoint result should be None")
def step_edge3_checkpoint_is_none(context: Context) -> None:
"""Verify checkpoint creation returned None (non-fatal failure)."""
assert context.edge3_checkpoint_result is None, (
f"Expected None but got {context.edge3_checkpoint_result}"
)
@then("the edge3 checkpoint manager should have been called with sandbox path metadata")
def step_edge3_checkpoint_called_with_path(context: Context) -> None:
"""Verify create_checkpoint was called with sandbox_path in metadata."""
context.edge3_checkpoint_mgr.create_checkpoint.assert_called_once()
call_kwargs = context.edge3_checkpoint_mgr.create_checkpoint.call_args
# Keyword arg 'metadata' or positional
metadata = call_kwargs.kwargs.get("metadata") or call_kwargs[1].get("metadata", {})
assert "sandbox_path" in metadata, (
f"Expected 'sandbox_path' in metadata, got keys: {list(metadata.keys())}"
)
assert metadata["sandbox_path"] == EDGE3_SANDBOX_ROOT, (
f"Expected sandbox_path='{EDGE3_SANDBOX_ROOT}', got '{metadata['sandbox_path']}'"
)
# ---------------------------------------------------------------------------
# Stub execute with checkpoint rollback on failure
# ---------------------------------------------------------------------------
@given("an edge3 mock lifecycle service for execute")
def step_edge3_given_lifecycle_execute(context: Context) -> None:
"""Create a mock lifecycle service for execute scenarios."""
context.edge3_lifecycle = _edge3_make_lifecycle()
context.edge3_plan_id = EDGE3_PLAN_ID
@given("an edge3 plan in Execute-Queued state with decision root")
def step_edge3_given_plan_execute_queued(context: Context) -> None:
"""Set up a plan in Execute-Queued state with decision root."""
plan = _edge3_make_plan(
phase=PlanPhase.EXECUTE,
state=ProcessingState.QUEUED,
definition_of_done="Implement feature\nWrite tests",
decision_root_id=EDGE3_ROOT_ID,
)
context.edge3_lifecycle.get_plan.return_value = plan
context.edge3_mock_plan = plan
@given(
"an edge3 PlanExecutor with checkpoint manager sandbox root and failing execute actor"
)
def step_edge3_given_executor_failing_stub_with_cp(context: Context) -> None:
"""Create PlanExecutor with checkpoint manager, sandbox root, and a failing execute actor."""
context.edge3_checkpoint_mgr = MagicMock()
context.edge3_executor = PlanExecutor(
lifecycle_service=context.edge3_lifecycle,
sandbox_root=EDGE3_SANDBOX_ROOT,
execution_context=None,
checkpoint_manager=context.edge3_checkpoint_mgr,
)
# Make execute actor always fail
context.edge3_executor._execute_actor = MagicMock()
context.edge3_executor._execute_actor.execute.side_effect = RuntimeError(
"edge3 stub execute boom"
)
@when("I edge3 call run execute expecting failure")
def step_edge3_run_execute_fail(context: Context) -> None:
"""Call run_execute expecting an exception."""
context.edge3_raised = None
try:
context.edge3_executor.run_execute(context.edge3_plan_id)
except Exception as exc:
context.edge3_raised = exc
@then("an edge3 exception should have been raised")
def step_edge3_exception_raised(context: Context) -> None:
"""Verify an exception was raised."""
assert context.edge3_raised is not None, "Expected an exception but none was raised"
@then("the edge3 checkpoint manager rollback_to should have been called")
def step_edge3_rollback_called(context: Context) -> None:
"""Verify checkpoint_manager.rollback_to was called."""
context.edge3_checkpoint_mgr.rollback_to.assert_called_once()
@then("the edge3 lifecycle should have called fail_execute for edge3")
def step_edge3_check_fail_execute(context: Context) -> None:
"""Verify lifecycle.fail_execute was called."""
context.edge3_lifecycle.fail_execute.assert_called_once()
call_args = context.edge3_lifecycle.fail_execute.call_args[0]
assert context.edge3_plan_id in call_args, (
f"Expected plan_id in fail_execute args, got {call_args}"
)
# ---------------------------------------------------------------------------
# Runtime execute with checkpoint rollback on failure
# ---------------------------------------------------------------------------
@given("an edge3 mock execution context for runtime")
def step_edge3_given_exec_ctx_runtime(context: Context) -> None:
"""Create a mock execution context for runtime mode."""
from cleveragents.application.services.plan_execution_context import (
PlanExecutionContext,
)
context.edge3_exec_ctx = PlanExecutionContext(plan_id=EDGE3_PLAN_ID)
@given(
"an edge3 PlanExecutor with runtime context checkpoint manager sandbox root and failing runtime actor"
)
def step_edge3_given_executor_runtime_failing_with_cp(context: Context) -> None:
"""Create PlanExecutor with runtime context, checkpoint manager, and failing runtime."""
from cleveragents.application.services.plan_execution_context import (
RuntimeExecuteActor,
)
from cleveragents.tool.registry import ToolRegistry
from cleveragents.tool.runner import ToolRunner
context.edge3_checkpoint_mgr = MagicMock()
runner = ToolRunner(registry=ToolRegistry())
context.edge3_executor = PlanExecutor(
lifecycle_service=context.edge3_lifecycle,
tool_runner=runner,
sandbox_root=EDGE3_SANDBOX_ROOT,
execution_context=context.edge3_exec_ctx,
checkpoint_manager=context.edge3_checkpoint_mgr,
)
# Patch RuntimeExecuteActor.execute to raise
patcher = patch.object(
RuntimeExecuteActor,
"execute",
side_effect=RuntimeError("edge3 runtime execute boom"),
)
patcher.start()
if not hasattr(context, "_cleanup_handlers"):
context._cleanup_handlers = []
context._cleanup_handlers.append(patcher.stop)
# ---------------------------------------------------------------------------
# _parse_steps non-empty path exercised via run_strategize
# ---------------------------------------------------------------------------
@given("an edge3 mock lifecycle service for strategize")
def step_edge3_given_lifecycle_strategize(context: Context) -> None:
"""Create a mock lifecycle service for strategize scenarios."""
context.edge3_lifecycle = _edge3_make_lifecycle()
context.edge3_plan_id = EDGE3_PLAN_ID
@given('an edge3 plan in Strategize phase with multi-line definition "{defn}"')
def step_edge3_given_plan_strategize_multiline(context: Context, defn: str) -> None:
"""Set up a plan in Strategize phase with a multi-line definition."""
raw = defn.replace("\\n", "\n")
plan = _edge3_make_plan(
phase=PlanPhase.STRATEGIZE,
state=ProcessingState.QUEUED,
definition_of_done=raw,
decision_root_id=None,
)
context.edge3_lifecycle.get_plan.return_value = plan
context.edge3_mock_plan = plan
@given("an edge3 plan in Strategize phase with empty definition")
def step_edge3_given_plan_strategize_empty_defn(context: Context) -> None:
"""Set up a plan in Strategize phase with empty definition_of_done."""
plan = _edge3_make_plan(
phase=PlanPhase.STRATEGIZE,
state=ProcessingState.QUEUED,
definition_of_done="",
decision_root_id=None,
)
context.edge3_lifecycle.get_plan.return_value = plan
context.edge3_mock_plan = plan
@given("an edge3 PlanExecutor for strategize without execution context")
def step_edge3_given_executor_strategize_no_ctx(context: Context) -> None:
"""Create a PlanExecutor for strategize without execution context."""
context.edge3_executor = PlanExecutor(
lifecycle_service=context.edge3_lifecycle,
execution_context=None,
)
@when("I edge3 call run strategize successfully")
def step_edge3_run_strategize(context: Context) -> None:
"""Call run_strategize and store the result."""
context.edge3_raised = None
try:
context.edge3_strat_result = context.edge3_executor.run_strategize(
context.edge3_plan_id
)
except Exception as exc:
context.edge3_raised = exc
@then("the edge3 strategize result should have {n:d} decisions")
def step_edge3_check_decision_count(context: Context, n: int) -> None:
"""Verify the strategize result decision count."""
assert context.edge3_raised is None, f"Unexpected error: {context.edge3_raised}"
actual = len(context.edge3_strat_result.decisions)
assert actual == n, f"Expected {n} decisions, got {actual}"
@then("the edge3 lifecycle should have called complete_strategize for edge3")
def step_edge3_check_complete_strategize(context: Context) -> None:
"""Verify complete_strategize was called."""
context.edge3_lifecycle.complete_strategize.assert_called_once_with(
context.edge3_plan_id
)
# ---------------------------------------------------------------------------
# Successful stub execute with checkpoint creation via sandbox root proxy
# ---------------------------------------------------------------------------
@given(
"an edge3 PlanExecutor with checkpoint manager and sandbox root for stub execute"
)
def step_edge3_given_executor_cp_sandbox_stub(context: Context) -> None:
"""Create PlanExecutor with checkpoint manager and sandbox root for stub execute."""
context.edge3_checkpoint_mgr = MagicMock()
context.edge3_executor = PlanExecutor(
lifecycle_service=context.edge3_lifecycle,
sandbox_root=EDGE3_SANDBOX_ROOT,
execution_context=None,
checkpoint_manager=context.edge3_checkpoint_mgr,
)
@when("I edge3 call run execute successfully")
def step_edge3_run_execute_success(context: Context) -> None:
"""Call run_execute expecting success."""
context.edge3_raised = None
try:
context.edge3_exec_result = context.edge3_executor.run_execute(
context.edge3_plan_id
)
except Exception as exc:
context.edge3_raised = exc
@then("the edge3 execute result should be an ExecuteResult")
def step_edge3_check_exec_result_type(context: Context) -> None:
"""Verify the result is an ExecuteResult."""
assert context.edge3_raised is None, f"Unexpected error: {context.edge3_raised}"
assert isinstance(context.edge3_exec_result, ExecuteResult), (
f"Expected ExecuteResult, got {type(context.edge3_exec_result).__name__}"
)
@then(
"the edge3 checkpoint manager create_checkpoint should have been called at least twice"
)
def step_edge3_checkpoint_create_called_twice(context: Context) -> None:
"""Verify create_checkpoint was called at least twice (pre and post execute)."""
call_count = context.edge3_checkpoint_mgr.create_checkpoint.call_count
assert call_count >= 2, (
f"Expected create_checkpoint called >= 2 times, got {call_count}"
)