spec: add Subplan System module specification (v3.3.0) [AUTO-ARCH-6]
CI / push-validation (pull_request) Successful in 26s
CI / helm (pull_request) Successful in 41s
CI / unit_tests (pull_request) Failing after 1m21s
CI / lint (pull_request) Failing after 5m21s
CI / build (pull_request) Successful in 7m8s
CI / quality (pull_request) Successful in 8m14s
CI / typecheck (pull_request) Successful in 8m16s
CI / security (pull_request) Successful in 8m38s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / e2e_tests (pull_request) Successful in 10m44s
CI / integration_tests (pull_request) Successful in 14m53s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 26s
CI / helm (pull_request) Successful in 41s
CI / unit_tests (pull_request) Failing after 1m21s
CI / lint (pull_request) Failing after 5m21s
CI / build (pull_request) Successful in 7m8s
CI / quality (pull_request) Successful in 8m14s
CI / typecheck (pull_request) Successful in 8m16s
CI / security (pull_request) Successful in 8m38s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / e2e_tests (pull_request) Successful in 10m44s
CI / integration_tests (pull_request) Successful in 14m53s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
Adds the Subplan System section covering: - Module boundaries and forbidden dependencies for cleveragents.subplans - Data models: Subplan, SubplanResult, SubplanTree - Database schema with indexes - Spawning algorithm (8-step Execute phase flow) - Concurrency control via semaphores (max_parallel, default 4, max 16) - Integration points with Plan Executor, Three-Way Merge, Decision Recording, Checkpoint System - Error types: SubplanSpawnError, SubplanExecutionError, MaxParallelExceededError, SubplanDepthLimitError - Cross-cutting concerns: observability, logging, cancellation propagation, timeouts
This commit is contained in:
@@ -47095,3 +47095,151 @@ These architectural invariants must be maintained across all milestones:
|
||||
8. **BDD tests**: All unit-level tests expressed as Behave/Gherkin scenarios. No xUnit-style tests.
|
||||
9. **File size limit**: No source file exceeds 500 lines. Split into modules if approaching limit.
|
||||
10. **Atomic commits**: One logical change per commit. No mixed concerns.
|
||||
|
||||
---
|
||||
|
||||
## Subplan System (v3.3.0)
|
||||
|
||||
### Overview
|
||||
|
||||
The Subplan System enables plans to spawn child plans (subplans) during execution. Subplans execute in parallel with configurable concurrency limits (`max_parallel`). Results are merged back into the parent plan using three-way merge strategies. The parent plan tracks all subplan statuses and waits for completion before proceeding.
|
||||
|
||||
### Module Boundaries
|
||||
|
||||
- **Module**: `cleveragents.subplans`
|
||||
- **Layer**: Domain (with Application orchestration)
|
||||
- **Responsibilities**:
|
||||
- Spawning subplans from a parent plan during Execute phase
|
||||
- Managing subplan lifecycle (pending → running → complete/failed)
|
||||
- Enforcing `max_parallel` concurrency limits
|
||||
- Tracking parent-child plan relationships
|
||||
- Providing subplan status to parent plan
|
||||
- **Public Interfaces**:
|
||||
- `SubplanSpawner` — creates and registers subplans from a parent plan
|
||||
- `SubplanRepository` — CRUD for subplan entities (domain repository interface)
|
||||
- `SubplanExecutor` — orchestrates parallel subplan execution with concurrency control
|
||||
- `SubplanStatusTracker` — tracks and reports subplan completion status
|
||||
- **Forbidden Dependencies**: Must not import from `cleveragents.cli` or `cleveragents.tui`
|
||||
|
||||
### Data Models
|
||||
|
||||
#### Subplan Entity
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class Subplan:
|
||||
id: UUID
|
||||
parent_plan_id: UUID
|
||||
root_plan_id: UUID # Top-level ancestor plan
|
||||
depth: int # 1 = direct child of root, 2 = grandchild, etc.
|
||||
title: str
|
||||
description: str
|
||||
action_id: UUID # Action template driving this subplan
|
||||
status: Literal["pending", "running", "complete", "failed", "cancelled"]
|
||||
max_parallel: int # Max concurrent sub-subplans this plan may spawn
|
||||
created_at: datetime
|
||||
started_at: Optional[datetime]
|
||||
completed_at: Optional[datetime]
|
||||
result: Optional[SubplanResult]
|
||||
metadata: dict
|
||||
```
|
||||
|
||||
#### SubplanResult
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class SubplanResult:
|
||||
subplan_id: UUID
|
||||
status: Literal["success", "partial", "failed"]
|
||||
output: dict # Structured output from the subplan
|
||||
artifacts: list[str] # File paths or resource IDs produced
|
||||
error: Optional[str]
|
||||
merge_conflicts: list[MergeConflict] # Conflicts detected during merge
|
||||
```
|
||||
|
||||
#### SubplanTree
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class SubplanTree:
|
||||
root_plan_id: UUID
|
||||
|
||||
def get_children(self, plan_id: UUID) -> list[Subplan]: ...
|
||||
def get_all_descendants(self, plan_id: UUID) -> list[Subplan]: ...
|
||||
def get_depth(self, plan_id: UUID) -> int: ...
|
||||
def get_running_count(self, plan_id: UUID) -> int: ...
|
||||
```
|
||||
|
||||
### Database Schema
|
||||
|
||||
```sql
|
||||
CREATE TABLE subplans (
|
||||
id UUID PRIMARY KEY,
|
||||
parent_plan_id UUID NOT NULL REFERENCES plans(id) ON DELETE CASCADE,
|
||||
root_plan_id UUID NOT NULL REFERENCES plans(id),
|
||||
depth INTEGER NOT NULL DEFAULT 1,
|
||||
title VARCHAR(500) NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
action_id UUID NOT NULL REFERENCES actions(id),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
||||
CHECK (status IN ('pending', 'running', 'complete', 'failed', 'cancelled')),
|
||||
max_parallel INTEGER NOT NULL DEFAULT 4,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
result JSONB,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'
|
||||
);
|
||||
|
||||
CREATE INDEX idx_subplans_parent_plan ON subplans(parent_plan_id);
|
||||
CREATE INDEX idx_subplans_root_plan ON subplans(root_plan_id);
|
||||
CREATE INDEX idx_subplans_status ON subplans(status);
|
||||
```
|
||||
|
||||
### Spawning Algorithm
|
||||
|
||||
During the Execute phase, the LangGraph execute node may spawn subplans:
|
||||
|
||||
1. The LLM decides to decompose a task into subtasks
|
||||
2. `SubplanSpawner.spawn(parent_plan_id, subtasks)` creates subplan records
|
||||
3. Each subplan is assigned an Action template appropriate for the subtask
|
||||
4. `SubplanExecutor.execute_parallel(subplans, max_parallel)` begins execution
|
||||
5. Subplans are dispatched in batches of `max_parallel`
|
||||
6. Each subplan runs its own Strategize → Execute → Apply lifecycle
|
||||
7. Subplans may themselves spawn sub-subplans (hierarchical decomposition, 4+ levels)
|
||||
8. Parent plan waits for all subplans to complete before proceeding
|
||||
|
||||
### Concurrency Control
|
||||
|
||||
- `max_parallel` is configurable per plan (default: 4, max: 16)
|
||||
- Concurrency is enforced using a semaphore per parent plan
|
||||
- If a subplan fails, sibling subplans continue unless `fail_fast=True`
|
||||
- Cancelled subplans are marked `cancelled` and their results are excluded from merge
|
||||
|
||||
### Integration Points
|
||||
|
||||
| Integration | Direction | Description |
|
||||
|---|---|---|
|
||||
| Plan Executor | Called by | Execute node spawns subplans via `SubplanSpawner` |
|
||||
| Three-Way Merge | Calls | `SubplanExecutor` calls merge strategy after all subplans complete |
|
||||
| Decision Recording | Calls | Subplan spawning decisions recorded via `DecisionRecorder` |
|
||||
| Checkpoint System | Calls | Checkpoints created before and after subplan execution |
|
||||
|
||||
### Error Handling
|
||||
|
||||
- `SubplanSpawnError(parent_plan_id, reason)` — failed to create subplan
|
||||
- `SubplanExecutionError(subplan_id, reason)` — subplan execution failed
|
||||
- `MaxParallelExceededError(plan_id, requested, max)` — concurrency limit exceeded
|
||||
- `SubplanDepthLimitError(plan_id, depth, max_depth)` — hierarchical depth limit exceeded (max: 8)
|
||||
|
||||
### Cross-Cutting Concerns
|
||||
|
||||
- **Observability**: Subplan count, depth, and completion rate tracked as metrics
|
||||
- **Logging**: All subplan lifecycle events logged at INFO level
|
||||
- **Cancellation**: Parent plan cancellation propagates to all running subplans
|
||||
- **Timeout**: Each subplan has a configurable timeout (default: 30 minutes)
|
||||
|
||||
---
|
||||
**Automated by CleverAgents Bot**
|
||||
Supervisor: Architecture | Agent: architecture-pool-supervisor
|
||||
Worker: [AUTO-ARCH-6]
|
||||
|
||||
Reference in New Issue
Block a user