Skip to content

Commit f61db8d

Browse files
authored
feat(core): absorb parallel-cc worktree + E2B into CodeFrame namespace (#535)
## Summary - Add `codeframe/core/sandbox/worktree.py` re-export shim exposing `TaskWorktree`, `WorktreeRegistry`, `MergeResult`, `get_base_branch` from the `codeframe.core.sandbox` namespace - Expand `codeframe/core/sandbox/__init__.py` to re-export worktree symbols - Update `CLAUDE.md`: add `core/sandbox/` and `adapters/e2b/` to repo structure; add `E2B_API_KEY` env var - Update `docs/V2_STRATEGIC_ROADMAP.md`: mark parallel-cc absorption complete, remove stale dependency-arc language ## Validation - Review feedback: All addressed (2 items — markdown table column fix, pytestmark placement) - Demo: All 5 acceptance criteria verified via showboat - Tests: 84 targeted tests + 5,061 unit tests passing - CI: All checks green (6 pass, 3 skip) - Linting: Clean Closes #535
1 parent 8d35a21 commit f61db8d

5 files changed

Lines changed: 94 additions & 21 deletions

File tree

CLAUDE.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,21 @@ codeframe/
153153
│ ├── stall_detector.py # Synchronous stall detector + StallAction enum + StallDetectedError
154154
│ ├── stall_monitor.py # Thread-based stall watchdog with callback
155155
│ ├── streaming.py # Real-time output streaming for cf work follow
156+
│ ├── worktrees.py # TaskWorktree, WorktreeRegistry, get_base_branch
157+
│ ├── sandbox/ # Execution isolation abstractions
158+
│ │ ├── context.py # ExecutionContext + IsolationLevel (none/worktree/cloud)
159+
│ │ └── worktree.py # Re-exports worktree symbols from core/worktrees.py
156160
│ └── ...
157161
├── adapters/
158-
│ └── llm/ # LLM provider adapters
159-
│ ├── base.py # Protocol + ModelSelector + Purpose enum
160-
│ ├── anthropic.py # Anthropic Claude provider
161-
│ └── mock.py # Mock provider for testing
162+
│ ├── llm/ # LLM provider adapters
163+
│ │ ├── base.py # Protocol + ModelSelector + Purpose enum
164+
│ │ ├── anthropic.py # Anthropic Claude provider
165+
│ │ └── mock.py # Mock provider for testing
166+
│ └── e2b/ # E2B cloud sandbox adapter (optional — requires `pip install codeframe[cloud]`)
167+
│ ├── __init__.py # Exports E2BAgentAdapter
168+
│ ├── adapter.py # E2BAgentAdapter (engine="cloud")
169+
│ ├── budget.py # Cost tracking utilities
170+
│ └── credential_scanner.py # Pre-upload secrets scanner
162171
├── cli/
163172
│ └── app.py # Typer CLI entry + subcommands
164173
├── ui/ # FastAPI server (Phase 2 - thin adapter over core)
@@ -884,6 +893,9 @@ uv run pytest --cov=codeframe --cov-report=html
884893
# Required for agent execution
885894
ANTHROPIC_API_KEY=sk-ant-...
886895

896+
# Required for cloud sandbox execution (--engine cloud)
897+
E2B_API_KEY=e2b_...
898+
887899
# Optional - Database
888900
DATABASE_PATH=./codeframe.db
889901

codeframe/core/sandbox/__init__.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
"""Execution environment sandbox abstraction.
22
33
Provides ExecutionContext and IsolationLevel for isolating task execution
4-
from the shared filesystem.
4+
from the shared filesystem, plus worktree registry helpers.
55
"""
66

77
from codeframe.core.sandbox.context import (
88
ExecutionContext,
99
IsolationLevel,
1010
create_execution_context,
1111
)
12+
from codeframe.core.sandbox.worktree import (
13+
MergeResult,
14+
TaskWorktree,
15+
WorktreeRegistry,
16+
get_base_branch,
17+
)
1218

13-
__all__ = ["ExecutionContext", "IsolationLevel", "create_execution_context"]
19+
__all__ = [
20+
"ExecutionContext",
21+
"IsolationLevel",
22+
"create_execution_context",
23+
"MergeResult",
24+
"TaskWorktree",
25+
"WorktreeRegistry",
26+
"get_base_branch",
27+
]

codeframe/core/sandbox/worktree.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""Worktree registry re-export for the sandbox namespace.
2+
3+
Re-exports ``TaskWorktree``, ``MergeResult``, ``WorktreeRegistry``, and
4+
``get_base_branch`` from ``codeframe.core.worktrees`` so callers can import
5+
from a single ``codeframe.core.sandbox`` sub-package.
6+
"""
7+
8+
from codeframe.core.worktrees import (
9+
MergeResult,
10+
TaskWorktree,
11+
WorktreeRegistry,
12+
get_base_branch,
13+
)
14+
15+
__all__ = [
16+
"MergeResult",
17+
"TaskWorktree",
18+
"WorktreeRegistry",
19+
"get_base_branch",
20+
]

docs/V2_STRATEGIC_ROADMAP.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,15 @@ Phase 4 has three parallel tracks:
278278

279279
**Motivation**: `cf work batch run --strategy parallel` currently runs concurrent threads on the same filesystem with no isolation. Agents can corrupt each other's work, hit git index locks, or overwrite changes.
280280

281-
**Integration strategy**: `parallel-cc` is a production-grade tool that already solves this with git worktrees + E2B cloud sandboxes. It will be consumed as a dependency initially, then absorbed into CodeFrame as the integration matures. It will not remain a separate independent project long-term.
281+
**Status**: The execution environment layer is complete. Worktree isolation and E2B cloud execution are fully absorbed into CodeFrame's own namespace — no external dependency was ever introduced.
282282

283-
#### Absorption arc
283+
#### Absorption arc (complete ✅)
284284

285-
| Phase | What happens |
286-
|-------|-------------|
287-
| **Dependency** (now → Phase 4) | CodeFrame calls `parallel-cc` CLI/library for worktree + E2B management |
288-
| **Integration** (during Phase 4) | parallel-cc concepts formalized as CodeFrame `ExecutionContext` abstraction |
289-
| **Absorption** (Phase 4 complete) | parallel-cc code moves into `codeframe/core/sandbox/` and `codeframe/adapters/e2b/` |
285+
| Phase | What happened |
286+
|-------|--------------|
287+
| ~~**Dependency**~~ | Skipped — logic was ported directly (parallel-cc never added as a dep) |
288+
| **Integration** (Phase 4) | `ExecutionContext` abstraction formalized in `core/sandbox/context.py` |
289+
| **Absorption** (Phase 4.B complete) | ✅ Worktree code in `core/worktrees.py` + `core/sandbox/worktree.py`; E2B adapter in `adapters/e2b/` |
290290

291291
#### Deliverables
292292

@@ -296,9 +296,9 @@ Phase 4 has three parallel tracks:
296296
- CLI: `--isolation none | worktree | cloud`
297297

298298
2. **Worktree isolation for parallel batch** (codeframe-c0rx)
299-
- Each parallel task gets its own git worktree via `gtr` (from parallel-cc)
300-
- Atomic session registration prevents race conditions
301-
- Auto-cleanup on task completion
299+
- Each parallel task gets its own git worktree via `TaskWorktree` (`core/worktrees.py`)
300+
- `WorktreeRegistry` provides atomic session registration (prevents race conditions)
301+
- Auto-cleanup on task completion via `ExecutionContext.cleanup()`
302302
- Fixes the live filesystem conflict problem in `conductor.py`
303303

304304
3. **`E2BAgentAdapter`** (codeframe-csyd)
@@ -307,10 +307,10 @@ Phase 4 has three parallel tracks:
307307
- Up to 1-hour autonomous execution with timeout management
308308
- Budget tracking per task/batch
309309

310-
4. **parallel-cc absorption** (codeframe-xz0f)
311-
- Port worktree coordination logic to `codeframe/core/sandbox/`
312-
- Port E2B pipeline to `codeframe/adapters/e2b/`
313-
- parallel-cc repo archived once absorption is complete
310+
4. **parallel-cc absorption** (codeframe-xz0f)
311+
- Worktree coordination lives in `codeframe/core/worktrees.py` and `codeframe/core/sandbox/`
312+
- E2B pipeline lives in `codeframe/adapters/e2b/`
313+
- parallel-cc was never added as a dependency; repo archived
314314

315315
---
316316

@@ -346,7 +346,7 @@ Phase 4 has three parallel tracks:
346346
| codeframe-la86 | ExecutionContext abstraction | 4.B | HIGH |
347347
| codeframe-c0rx | Worktree isolation for parallel batch | 4.B | HIGH |
348348
| codeframe-csyd | E2BAgentAdapter (cloud execution) | 4.B | MEDIUM |
349-
| codeframe-xz0f | parallel-cc absorption into CodeFrame | 4.B | MEDIUM |
349+
| codeframe-xz0f | parallel-cc absorption into CodeFrame | 4.B | MEDIUM |
350350
| #310 | Agent roles | 4.C | MEDIUM |
351351
| #311 | Conflict detection & resolution | 4.C | MEDIUM |
352352
| #312 | Handoff protocols | 4.C | MEDIUM |

tests/core/test_sandbox_context.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
create_execution_context,
2020
)
2121

22+
pytestmark = pytest.mark.v2
23+
2224

2325
@pytest.fixture
2426
def git_repo(tmp_path: Path) -> Path:
@@ -153,3 +155,28 @@ class TestCreateExecutionContextCloud:
153155
def test_raises_not_implemented(self, tmp_path: Path):
154156
with pytest.raises(NotImplementedError, match="E2B"):
155157
create_execution_context("task-1", IsolationLevel.CLOUD, tmp_path)
158+
159+
160+
class TestSandboxWorktreeReexports:
161+
"""sandbox.worktree re-exports resolve correctly (issue #535)."""
162+
163+
def test_task_worktree_importable_from_sandbox(self):
164+
from codeframe.core.sandbox import TaskWorktree
165+
assert TaskWorktree is not None
166+
167+
def test_merge_result_importable_from_sandbox(self):
168+
from codeframe.core.sandbox import MergeResult
169+
assert MergeResult is not None
170+
171+
def test_worktree_registry_importable_from_sandbox(self):
172+
from codeframe.core.sandbox import WorktreeRegistry
173+
assert WorktreeRegistry is not None
174+
175+
def test_get_base_branch_importable_from_sandbox(self):
176+
from codeframe.core.sandbox import get_base_branch
177+
assert callable(get_base_branch)
178+
179+
def test_sandbox_worktree_module_importable(self):
180+
from codeframe.core.sandbox import worktree as wt_mod
181+
assert hasattr(wt_mod, "TaskWorktree")
182+
assert hasattr(wt_mod, "WorktreeRegistry")

0 commit comments

Comments
 (0)