From 67dc076861c15d13ffd54cb7cab6404b8d5fcf8c Mon Sep 17 00:00:00 2001 From: CleverThis Date: Thu, 9 Apr 2026 12:11:35 +0000 Subject: [PATCH] =?UTF-8?q?docs(spec):=20architecture=20corrections=20cycl?= =?UTF-8?q?e=203=20=E2=80=94=20sandbox=20state=20persistence=20and=20LangG?= =?UTF-8?q?raph=20TypedDict=20requirement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add explicit sandbox state persistence requirement: SandboxManager must persist sandbox records to database (v3_sandboxes table) so that plan execute, diff, and apply can work across separate CLI invocations. Fixes spec gap identified by UAT issue #5721. - Clarify LangGraph state schema requirement: GraphState passed to StateGraph() must be TypedDict, not Pydantic BaseModel. LangGraph requires TypedDict for state merging semantics and reducer annotations. Addresses architectural deviation identified in UAT issue #5587. - Clarify RxPY role: reactive stream processing is for event routing BETWEEN actors, not for graph node execution. Graph node execution uses native LangGraph StateGraph exclusively. Addresses critical architectural deviation identified in UAT issue #5598. --- docs/specification.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/specification.md b/docs/specification.md index 4accaad8b..d0f5bea55 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -25140,6 +25140,25 @@ Not every resource in the DAG is independently sandboxable — a file cannot be 3. Multiple files in the same git checkout share one git_worktree sandbox. 4. When a virtual resource has physical manifestations in **different sandbox domains** (e.g., a file in both a git-checkout domain and a container-instance domain), cross-mechanism coordination is needed at commit time (see Cross-Mechanism Write Coordination above). +**Sandbox State Persistence:** + +Sandbox state (the mapping from `(plan_id, sandbox_boundary_id)` to the physical sandbox location, e.g., git worktree path) **must be persisted to the database**. This is required because `agents plan execute`, `agents plan diff`, and `agents plan apply` are separate CLI invocations — the sandbox created by `execute` must be discoverable by `diff` and `apply` in a subsequent process. + +The `SandboxManager` maintains an in-memory cache of active sandboxes keyed by `(plan_id, sandbox_boundary_id)`. On startup, it loads existing sandbox records from the database. On sandbox creation, it writes to both the cache and the database. On sandbox cleanup (after apply or rollback), it removes from both. + +The database schema includes a `v3_sandboxes` table: + +| Column | Type | Description | +|--------|------|-------------| +| `id` | TEXT (ULID) | Primary key | +| `plan_id` | TEXT | Foreign key to `v3_plans.plan_id` | +| `sandbox_boundary_id` | TEXT | Resource ID of the sandbox boundary | +| `strategy` | TEXT | Sandbox strategy (`git_worktree`, `copy_on_write`, etc.) | +| `location` | TEXT | Physical location (worktree path, snapshot directory, etc.) | +| `status` | TEXT | `active`, `committed`, `rolled_back`, `cleaned_up` | +| `created_at` | DATETIME | Creation timestamp (UTC) | +| `updated_at` | DATETIME | Last update timestamp (UTC) | + **Dependency ordering for lifecycle operations:** | Operation | Traversal Direction | Rationale | @@ -43848,10 +43867,10 @@ This section enumerates every technology choice in the CleverAgents stack, organ | Technology | Version | Role | Rationale | |---|---|---|---| | **LangChain** | >= 0.2.14 | LLM abstraction layer | Provider-agnostic interface for chat models, embeddings, output parsing, prompt templates, and tool calling. The `BaseLanguageModel` protocol enables swapping providers without changing application code. | -| **LangGraph** | (transitive) | Stateful workflow orchestration | `StateGraph` with conditional edges, checkpointing (`MemorySaver`), and streaming execution. Used for the plan generation graph (`load_context -> analyze -> generate -> validate`) and auto-debug graph. | +| **LangGraph** | (transitive) | Stateful workflow orchestration | `StateGraph` with conditional edges, checkpointing (`MemorySaver`), and streaming execution. Used for the plan generation graph (`load_context -> analyze -> generate -> validate`) and auto-debug graph. **State schemas passed to `StateGraph()` must be `TypedDict` subclasses** — not Pydantic `BaseModel`. LangGraph requires `TypedDict` for state merging semantics and reducer annotations (e.g., `Annotated[list, operator.add]`). Actor YAML-defined graphs compile to native `StateGraph` instances via `StateGraph.compile(checkpointer=MemorySaver())`. | | **LangChain Provider Packages** | varies | LLM provider integrations | `langchain-openai` (>= 0.2.0), `langchain-google-genai` (>= 0.2.0), `langchain-anthropic`, `langchain-groq`, `langchain-together`, `langchain-cohere`. Each provides a `ChatModel` implementation. | | **LangChain Community** | >= 0.2.14 | Community integrations | FAISS vector store, FakeListLLM/FakeEmbeddings for testing. | -| **RxPY** | >= 3.2.0 | Reactive stream processing | `Subject`, `BehaviorSubject`, `ReplaySubject`, and operators (`map`, `filter`, `flat_map`, `debounce`, `throttle`, `scan`) for real-time event routing between actors, stream-to-graph bridging, and backpressure management. | +| **RxPY** | >= 3.2.0 | Reactive stream processing | `Subject`, `BehaviorSubject`, `ReplaySubject`, and operators (`map`, `filter`, `flat_map`, `debounce`, `throttle`, `scan`) for **real-time event routing between actors** and stream-to-graph bridging. RxPY handles the messaging layer between actors — it is **not** used for graph node execution, which is handled exclusively by native LangGraph `StateGraph`. | | **MCP SDK** | >= 1.4.0 | Model Context Protocol | Client SDK for communicating with MCP servers. Enables CleverAgents to discover and invoke tools exposed by any MCP-compliant server. | #### Data and Persistence -- 2.52.0