UAT: TransactionSandbox.get_path() rejects ROLLED_BACK status — sandbox cannot be re-used after rollback unlike all other sandbox implementations #2586

Open
opened 2026-04-03 19:01:22 +00:00 by freemo · 1 comment
Owner

Bug Report

What Was Tested

TransactionSandbox.get_path() status guard in src/cleveragents/infrastructure/sandbox/transaction_sandbox.py.

Expected Behavior (from spec)

The spec states that after rollback, a sandbox transitions to ROLLED_BACK and can be re-activated via get_path(). This is the consistent behavior across all sandbox implementations:

  • GitWorktreeSandbox.get_path() allows ROLLED_BACK status and transitions to ACTIVE
  • CopyOnWriteSandbox.get_path() allows ROLLED_BACK status and transitions to ACTIVE
  • OverlaySandbox.get_path() allows ROLLED_BACK status and transitions to ACTIVE

The SandboxStatus transition graph also explicitly allows ROLLED_BACK → ACTIVE.

Actual Behavior

TransactionSandbox.get_path() only allows CREATED and ACTIVE statuses:

# src/cleveragents/infrastructure/sandbox/transaction_sandbox.py, line ~170
def get_path(self, resource_path: str) -> str:
    if self._status not in (
        SandboxStatus.CREATED,
        SandboxStatus.ACTIVE,
    ):
        raise SandboxStateError(
            f"Cannot resolve path in status {self._status.value}"
        )

After calling rollback(), the sandbox is in ROLLED_BACK status. Any subsequent call to get_path() raises SandboxStateError, making the sandbox unusable even though the spec and SandboxStatus transition graph allow ROLLED_BACK → ACTIVE.

Code Location

src/cleveragents/infrastructure/sandbox/transaction_sandbox.pyget_path() method, status guard condition.

Steps to Reproduce

  1. Create a TransactionSandbox and call create(plan_id)
  2. Call get_path("some/path") to activate it
  3. Call rollback() — sandbox transitions to ROLLED_BACK
  4. Call get_path("some/path") again — raises SandboxStateError: Cannot resolve path in status rolled_back

Impact

Plans using transaction_rollback sandbox strategy cannot re-use the sandbox after a rollback, unlike plans using git_worktree, copy_on_write, or overlay strategies. This breaks the correction/retry flow for database-backed resources.

Fix

Add SandboxStatus.ROLLED_BACK to the allowed statuses in get_path() and transition to ACTIVE when in that state, consistent with all other sandbox implementations:

if self._status not in (
    SandboxStatus.CREATED,
    SandboxStatus.ACTIVE,
    SandboxStatus.ROLLED_BACK,  # Add this
):
    raise SandboxStateError(...)

if self._status in (SandboxStatus.CREATED, SandboxStatus.ROLLED_BACK):
    self._status = SandboxStatus.ACTIVE

Metadata

  • Commit message: fix(sandbox): allow TransactionSandbox.get_path() in ROLLED_BACK status
  • Branch: fix/transaction-sandbox-rolled-back-get-path
  • Parent Epic: #358 (Corrections + Subplans + Checkpoints M4)

Subtasks

  • Fix get_path() status guard in TransactionSandbox
  • Add unit test for get_path() after rollback()

Definition of Done

  • TransactionSandbox.get_path() succeeds when called after rollback() (status ROLLED_BACK)
  • Behavior is consistent with GitWorktreeSandbox, CopyOnWriteSandbox, and OverlaySandbox
  • Unit test covers the ROLLED_BACK → ACTIVE transition via get_path()
  • All existing tests pass

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-uat-tester

## Bug Report ### What Was Tested `TransactionSandbox.get_path()` status guard in `src/cleveragents/infrastructure/sandbox/transaction_sandbox.py`. ### Expected Behavior (from spec) The spec states that after rollback, a sandbox transitions to `ROLLED_BACK` and can be re-activated via `get_path()`. This is the consistent behavior across all sandbox implementations: - `GitWorktreeSandbox.get_path()` allows `ROLLED_BACK` status and transitions to `ACTIVE` - `CopyOnWriteSandbox.get_path()` allows `ROLLED_BACK` status and transitions to `ACTIVE` - `OverlaySandbox.get_path()` allows `ROLLED_BACK` status and transitions to `ACTIVE` The `SandboxStatus` transition graph also explicitly allows `ROLLED_BACK → ACTIVE`. ### Actual Behavior `TransactionSandbox.get_path()` only allows `CREATED` and `ACTIVE` statuses: ```python # src/cleveragents/infrastructure/sandbox/transaction_sandbox.py, line ~170 def get_path(self, resource_path: str) -> str: if self._status not in ( SandboxStatus.CREATED, SandboxStatus.ACTIVE, ): raise SandboxStateError( f"Cannot resolve path in status {self._status.value}" ) ``` After calling `rollback()`, the sandbox is in `ROLLED_BACK` status. Any subsequent call to `get_path()` raises `SandboxStateError`, making the sandbox unusable even though the spec and `SandboxStatus` transition graph allow `ROLLED_BACK → ACTIVE`. ### Code Location `src/cleveragents/infrastructure/sandbox/transaction_sandbox.py` — `get_path()` method, status guard condition. ### Steps to Reproduce 1. Create a `TransactionSandbox` and call `create(plan_id)` 2. Call `get_path("some/path")` to activate it 3. Call `rollback()` — sandbox transitions to `ROLLED_BACK` 4. Call `get_path("some/path")` again — raises `SandboxStateError: Cannot resolve path in status rolled_back` ### Impact Plans using `transaction_rollback` sandbox strategy cannot re-use the sandbox after a rollback, unlike plans using `git_worktree`, `copy_on_write`, or `overlay` strategies. This breaks the correction/retry flow for database-backed resources. ### Fix Add `SandboxStatus.ROLLED_BACK` to the allowed statuses in `get_path()` and transition to `ACTIVE` when in that state, consistent with all other sandbox implementations: ```python if self._status not in ( SandboxStatus.CREATED, SandboxStatus.ACTIVE, SandboxStatus.ROLLED_BACK, # Add this ): raise SandboxStateError(...) if self._status in (SandboxStatus.CREATED, SandboxStatus.ROLLED_BACK): self._status = SandboxStatus.ACTIVE ``` ### Metadata - **Commit message**: `fix(sandbox): allow TransactionSandbox.get_path() in ROLLED_BACK status` - **Branch**: `fix/transaction-sandbox-rolled-back-get-path` - **Parent Epic**: #358 (Corrections + Subplans + Checkpoints M4) ### Subtasks - [ ] Fix `get_path()` status guard in `TransactionSandbox` - [ ] Add unit test for `get_path()` after `rollback()` ### Definition of Done - `TransactionSandbox.get_path()` succeeds when called after `rollback()` (status `ROLLED_BACK`) - Behavior is consistent with `GitWorktreeSandbox`, `CopyOnWriteSandbox`, and `OverlaySandbox` - Unit test covers the `ROLLED_BACK → ACTIVE` transition via `get_path()` - All existing tests pass --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester
freemo added this to the v3.7.0 milestone 2026-04-04 20:34:19 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High — TransactionSandbox is inconsistent with all other sandbox implementations regarding ROLLED_BACK status handling. This breaks the correction/retry flow for database-backed resources.
  • Milestone: v3.7.0
  • MoSCoW: Should have — Sandbox consistency is important for the plan lifecycle correction flow. The fix is a one-line change (add SandboxStatus.ROLLED_BACK to the allowed statuses).
  • Parent Epic: #397 (Server & Autonomy Infrastructure) — sandbox infrastructure. Note: original parent #358 is closed.

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: High — TransactionSandbox is inconsistent with all other sandbox implementations regarding ROLLED_BACK status handling. This breaks the correction/retry flow for database-backed resources. - **Milestone**: v3.7.0 - **MoSCoW**: Should have — Sandbox consistency is important for the plan lifecycle correction flow. The fix is a one-line change (add `SandboxStatus.ROLLED_BACK` to the allowed statuses). - **Parent Epic**: #397 (Server & Autonomy Infrastructure) — sandbox infrastructure. Note: original parent #358 is closed. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#397 Epic: Server & Autonomy Infrastructure
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#2586
No description provided.