Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a0b884359 |
@@ -5,6 +5,34 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Documentation
|
||||
|
||||
- **CLI Reference: Decisions (v3.2.0)**: Added `docs/api/decisions.md` documenting
|
||||
`agents plan tree` and `agents plan explain` commands, decision recording during
|
||||
the Strategize phase, the full decision data model (id, plan_id, phase,
|
||||
context_snapshot, alternatives), and the `DecisionService` Python API.
|
||||
|
||||
- **CLI Reference: Invariants (v3.2.0)**: Added `docs/api/invariants.md` documenting
|
||||
`agents invariant add`, `agents invariant list`, and `agents invariant remove`
|
||||
commands, the invariant scope hierarchy (global/project/action/plan), merge
|
||||
precedence rules, enforcement records, violation model, and the `InvariantService`
|
||||
Python API.
|
||||
|
||||
- **CLI Reference: Checkpoints (v3.3.0)**: Added `docs/api/checkpoints.md` documenting
|
||||
`agents plan checkpoint list` and `agents plan rollback <checkpoint_id>` commands,
|
||||
automatic checkpoint triggers (`on_tool_write`, `on_tool_write_complete`,
|
||||
`on_subplan_spawn`, `on_error`), the checkpoint data model, retention policy, and
|
||||
the `CheckpointService` Python API.
|
||||
|
||||
- **CLI Reference: Plan Corrections & Subplans (v3.3.0)**: Added
|
||||
`docs/api/plan-corrections.md` documenting `agents plan correct --mode=revert`
|
||||
and `agents plan correct --mode=append` commands, the correction data model,
|
||||
`CorrectionAttemptRecord` lifecycle, and a subplan system overview covering
|
||||
execution modes, merge strategies, and the `SubplanService` Python API.
|
||||
|
||||
- **API Index Update**: Extended `docs/api/index.md` with a new "Plan Intelligence
|
||||
(v3.2.0 / v3.3.0)" section linking to all four new API reference pages.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Automation Profile Silent Fallback** (#8232): `_resolve_profile_for_plan` in
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
# Checkpoints API Reference
|
||||
|
||||
Checkpoints allow operators to snapshot sandbox state during plan execution and
|
||||
restore it later. They are used for recovering from mistakes, reverting tool
|
||||
side-effects, and supporting the decision-correction revert flow.
|
||||
|
||||
> **Version:** Introduced in v3.3.0. Automatic checkpoint triggers added in v3.8.0.
|
||||
> **See also:** [`docs/reference/checkpointing.md`](../reference/checkpointing.md)
|
||||
|
||||
---
|
||||
|
||||
## Concept and Purpose
|
||||
|
||||
A **Checkpoint** is an immutable record of sandbox state at a specific point in
|
||||
time. The execution engine creates checkpoints automatically at key moments
|
||||
(before and after write-tool executions, before subplan spawning, and on
|
||||
errors). Operators can also roll back to any checkpoint via the CLI.
|
||||
|
||||
### Automatic Checkpoint Triggers (v3.8.0+)
|
||||
|
||||
| Trigger | When |
|
||||
|--------------------------|---------------------------------------------------|
|
||||
| `on_tool_write` | Before each write-tool execution |
|
||||
| `on_tool_write_complete` | After each write-tool execution |
|
||||
| `on_subplan_spawn` | Before first subplan execution attempt |
|
||||
| `on_error` | When the Execute phase fails |
|
||||
|
||||
All four triggers are enabled by default. See
|
||||
[Configuration](#configuration) to disable specific triggers.
|
||||
|
||||
---
|
||||
|
||||
## CLI Commands
|
||||
|
||||
### `agents plan checkpoint list`
|
||||
|
||||
Lists all checkpoints available for a plan.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents plan checkpoint list <PLAN_ID> [OPTIONS]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|-------------------|-------------------------------------------------------|
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich`|
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# List checkpoints for a plan (rich table)
|
||||
agents plan checkpoint list 01HXYZ1234567890ABCDEFGH
|
||||
|
||||
# JSON output for scripting
|
||||
agents plan checkpoint list 01HXYZ1234567890ABCDEFGH --format json
|
||||
```
|
||||
|
||||
#### Output (rich)
|
||||
|
||||
The rich renderer displays a table with columns:
|
||||
|
||||
| Column | Description |
|
||||
|-----------------|-------------------------------------------------------|
|
||||
| ID | Truncated checkpoint ULID |
|
||||
| Type | `pre_write`, `post_step`, or `manual` |
|
||||
| Decision | Aligned decision ULID (if set) |
|
||||
| Size | Checkpoint data size in bytes |
|
||||
| Created | Creation timestamp (UTC) |
|
||||
| Phase | Plan phase when checkpoint was created |
|
||||
|
||||
---
|
||||
|
||||
### `agents plan rollback`
|
||||
|
||||
Rolls back sandbox state to a previously captured checkpoint.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents plan rollback [--yes|-y] <PLAN_ID> <CHECKPOINT_ID> [OPTIONS]
|
||||
```
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Argument | Description |
|
||||
|------------------|-------------------------------------------------------|
|
||||
| `PLAN_ID` | ULID of the plan to roll back |
|
||||
| `CHECKPOINT_ID` | ULID of the checkpoint to restore |
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|-------------------|-------------------------------------------------------|
|
||||
| `--yes`, `-y` | Skip the interactive confirmation prompt |
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich`|
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Interactive rollback (prompts for confirmation)
|
||||
agents plan rollback 01HPLAN... 01HCHKPT...
|
||||
|
||||
# Skip confirmation (useful in scripts)
|
||||
agents plan rollback --yes 01HPLAN... 01HCHKPT...
|
||||
|
||||
# JSON output
|
||||
agents plan rollback --yes 01HPLAN... 01HCHKPT... --format json
|
||||
```
|
||||
|
||||
#### JSON Output Envelope
|
||||
|
||||
```json
|
||||
{
|
||||
"rollback_summary": {
|
||||
"plan_id": "01HPLAN...",
|
||||
"from_checkpoint_id": "01HCHKPT...",
|
||||
"restored_files_count": 3
|
||||
},
|
||||
"changes_reverted": [
|
||||
"path/to/file1.py",
|
||||
"path/to/file2.py",
|
||||
"path/to/file3.py"
|
||||
],
|
||||
"impact": {
|
||||
"files_affected": 3
|
||||
},
|
||||
"post_rollback_state": {
|
||||
"active_checkpoint": "01HCHKPT...",
|
||||
"plan_id": "01HPLAN..."
|
||||
},
|
||||
"timing": {
|
||||
"elapsed_seconds": 0.042
|
||||
},
|
||||
"messages": ["Rollback completed successfully."]
|
||||
}
|
||||
```
|
||||
|
||||
#### Error Cases
|
||||
|
||||
| Error | Cause |
|
||||
|----------------------------------------------|----------------------------------------------------|
|
||||
| `Rollback blocked: plan is already applied` | Plan has reached the terminal `applied` state |
|
||||
| `Rollback blocked: sandbox is missing` | Sandbox was cleaned up before rollback |
|
||||
| `Not found: checkpoint` | Checkpoint ID does not exist |
|
||||
| `Validation Error` | Checkpoint does not belong to the specified plan |
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
Automatic checkpoint triggers are configured via `core.checkpoints.auto_create_on`:
|
||||
|
||||
```toml
|
||||
[core.checkpoints]
|
||||
auto_create_on = ["on_tool_write", "on_tool_write_complete", "on_subplan_spawn", "on_error"]
|
||||
```
|
||||
|
||||
To disable a specific trigger, remove it from the list:
|
||||
|
||||
```toml
|
||||
[core.checkpoints]
|
||||
# Disable post-write checkpoints to reduce storage usage
|
||||
auto_create_on = ["on_tool_write", "on_subplan_spawn", "on_error"]
|
||||
```
|
||||
|
||||
To disable all automatic checkpoints:
|
||||
|
||||
```toml
|
||||
[core.checkpoints]
|
||||
auto_create_on = []
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checkpoint Data Model
|
||||
|
||||
**Module:** `cleveragents.domain.models.core.checkpoint`
|
||||
|
||||
| Field | Type | Description |
|
||||
|--------------------|-----------------|-----------------------------------------------------|
|
||||
| `checkpoint_id` | `str` (ULID) | Unique identifier |
|
||||
| `plan_id` | `str` (ULID) | The plan that owns this checkpoint |
|
||||
| `sandbox_ref` | `str` | Git commit hash or patch reference |
|
||||
| `decision_id` | `str \| None` | Optional decision ULID this checkpoint is aligned to|
|
||||
| `checkpoint_type` | `CheckpointType`| `pre_write`, `post_step`, or `manual` |
|
||||
| `resource_id` | `str \| None` | Optional resource ULID association |
|
||||
| `filesystem_path` | `str` | Relative path within the checkpoint directory |
|
||||
| `size_bytes` | `int` | Size of the checkpoint data in bytes |
|
||||
| `created_at` | `datetime` | UTC creation timestamp |
|
||||
| `metadata` | `CheckpointMetadata` | Audit metadata (reason, source tool, phase) |
|
||||
|
||||
### `CheckpointMetadata`
|
||||
|
||||
| Field | Type | Description |
|
||||
|---------------|--------------|-----------------------------------------------------|
|
||||
| `reason` | `str` | Why the checkpoint was created |
|
||||
| `source_tool` | `str \| None`| Which tool triggered the checkpoint |
|
||||
| `phase` | `str \| None`| Which plan phase was active |
|
||||
| `extra` | `dict` | Arbitrary key-value pairs for extension |
|
||||
|
||||
### Retention Policy
|
||||
|
||||
A `CheckpointRetentionPolicy` governs how many checkpoints a plan may keep:
|
||||
|
||||
| Field | Default | Range |
|
||||
|-------------------|---------|---------|
|
||||
| `max_checkpoints` | 50 | 1–100 |
|
||||
| `auto_prune` | `true` | |
|
||||
|
||||
When `auto_prune` is enabled and the checkpoint count exceeds `max_checkpoints`,
|
||||
the oldest **interior** checkpoints are automatically removed. The first
|
||||
(earliest) and most recent checkpoints are always preserved.
|
||||
|
||||
---
|
||||
|
||||
## Python API
|
||||
|
||||
### `CheckpointService`
|
||||
|
||||
**Module:** `cleveragents.application.services.checkpoint_service`
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.checkpoint_service import CheckpointService
|
||||
from cleveragents.domain.models.core.checkpoint import CheckpointType
|
||||
|
||||
svc = CheckpointService(repository=repo, settings=settings)
|
||||
|
||||
# Create a manual checkpoint
|
||||
checkpoint = svc.create_checkpoint(
|
||||
plan_id="01HPLAN...",
|
||||
sandbox_ref="abc123def456",
|
||||
checkpoint_type=CheckpointType.MANUAL,
|
||||
decision_id=None,
|
||||
metadata={"reason": "pre-migration snapshot", "phase": "execute"},
|
||||
)
|
||||
|
||||
# List checkpoints for a plan
|
||||
checkpoints = svc.list_checkpoints(plan_id="01HPLAN...")
|
||||
|
||||
# Get a specific checkpoint
|
||||
cp = svc.get_checkpoint(checkpoint_id="01HCHKPT...")
|
||||
|
||||
# Roll back to a checkpoint
|
||||
result = svc.rollback_to_checkpoint(
|
||||
plan_id="01HPLAN...",
|
||||
checkpoint_id="01HCHKPT...",
|
||||
)
|
||||
# result.restored_files_count, result.changed_paths, result.from_checkpoint_id
|
||||
|
||||
# Delete a checkpoint
|
||||
svc.delete_checkpoint(checkpoint_id="01HCHKPT...")
|
||||
```
|
||||
|
||||
### Dependency Injection
|
||||
|
||||
The `CheckpointService` is registered in the DI container and can be obtained
|
||||
via:
|
||||
|
||||
```python
|
||||
from cleveragents.di import get_container
|
||||
|
||||
container = get_container()
|
||||
checkpoint_service = container.checkpoint_service()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Checkpointing and Rollback Reference](../reference/checkpointing.md) — full reference
|
||||
- [Decision Correction Reference](../reference/decision_correction.md) — correction-service integration
|
||||
- [Plan CLI Reference](../reference/plan_cli.md) — plan commands overview
|
||||
- [Subplan Service](../reference/subplan_service.md) — `on_subplan_spawn` trigger
|
||||
@@ -0,0 +1,259 @@
|
||||
# Decisions API Reference
|
||||
|
||||
The decisions subsystem records every choice point in a plan's lifecycle as a
|
||||
**Decision** node in a persistent tree. Decisions are created during the
|
||||
Strategize and Execute phases and form the basis for targeted correction and
|
||||
replay.
|
||||
|
||||
> **Version:** Introduced in v3.2.0.
|
||||
> **See also:** [`docs/reference/decision_model.md`](../reference/decision_model.md),
|
||||
> [`docs/reference/decision_service.md`](../reference/decision_service.md),
|
||||
> [`docs/reference/decision_correction.md`](../reference/decision_correction.md)
|
||||
|
||||
---
|
||||
|
||||
## CLI Commands
|
||||
|
||||
### `agents plan tree`
|
||||
|
||||
Renders the full decision tree for a plan, showing every recorded choice point
|
||||
and how they relate to one another.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents plan tree <PLAN_ID> [OPTIONS]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|----------------------|---------------------------------------------------------------|
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich` |
|
||||
| `--show-superseded` | Include superseded (corrected) decisions in the tree |
|
||||
| `--depth` | Maximum tree depth to display (`0` = unlimited, default: `0`) |
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Default rich tree view
|
||||
agents plan tree 01HXYZ1234567890ABCDEFGH
|
||||
|
||||
# Table format
|
||||
agents plan tree 01HXYZ1234567890ABCDEFGH --format table
|
||||
|
||||
# Include superseded decisions (useful when reviewing corrections)
|
||||
agents plan tree 01HXYZ1234567890ABCDEFGH --show-superseded
|
||||
|
||||
# Limit depth to 2 levels
|
||||
agents plan tree 01HXYZ1234567890ABCDEFGH --depth 2
|
||||
|
||||
# JSON output for scripting
|
||||
agents plan tree 01HXYZ1234567890ABCDEFGH --format json
|
||||
```
|
||||
|
||||
#### Output (rich)
|
||||
|
||||
The rich renderer displays a tree rooted at the `prompt_definition` decision.
|
||||
Each node shows:
|
||||
|
||||
- Decision ID (truncated ULID)
|
||||
- Decision type (e.g., `strategy_choice`, `implementation_choice`)
|
||||
- Chosen option (truncated)
|
||||
- Confidence score (if set)
|
||||
- Superseded indicator (`[superseded]`) when `--show-superseded` is active
|
||||
|
||||
---
|
||||
|
||||
### `agents plan explain`
|
||||
|
||||
Shows full details for a single decision, including the question that was
|
||||
answered, the chosen option, all alternatives considered, and optional context
|
||||
snapshot and actor reasoning.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents plan explain <DECISION_ID> [OPTIONS]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|----------------------|---------------------------------------------------------------|
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich` |
|
||||
| `--show-context` | Include context snapshot details (hash, resource refs) |
|
||||
| `--show-reasoning` | Include rationale and raw actor reasoning trace |
|
||||
|
||||
Alternatives considered are always included in the output.
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Default rich output
|
||||
agents plan explain 01HXYZ1234567890ABCDEFGH
|
||||
|
||||
# JSON with full context snapshot
|
||||
agents plan explain 01HXYZ1234567890ABCDEFGH --format json --show-context
|
||||
|
||||
# Show actor reasoning trace
|
||||
agents plan explain 01HXYZ1234567890ABCDEFGH --show-reasoning
|
||||
|
||||
# YAML output with all details
|
||||
agents plan explain 01HXYZ1234567890ABCDEFGH --format yaml \
|
||||
--show-context --show-reasoning
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Decision Recording During Strategize
|
||||
|
||||
During the **Strategize** phase, the strategy actor records decisions for every
|
||||
significant choice it makes. The decision tree is built incrementally:
|
||||
|
||||
1. A `prompt_definition` root decision is created when the plan is initialised.
|
||||
2. An `invariant_enforced` decision is recorded for each invariant applied by
|
||||
the Invariant Reconciliation Actor.
|
||||
3. One or more `strategy_choice` decisions capture the high-level approach.
|
||||
4. `subplan_spawn` or `subplan_parallel_spawn` decisions are recorded when the
|
||||
strategy decomposes work into child plans.
|
||||
|
||||
During the **Execute** phase, `implementation_choice`, `resource_selection`,
|
||||
`tool_invocation`, `error_recovery`, and `validation_response` decisions are
|
||||
added as children of the relevant strategy decisions.
|
||||
|
||||
---
|
||||
|
||||
## Decision Data Model
|
||||
|
||||
**Module:** `cleveragents.domain.models.core.decision`
|
||||
|
||||
### Identity Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|------------------------|-----------------|-----------------------------------------------------|
|
||||
| `decision_id` | `str` (ULID) | Auto-generated unique identifier |
|
||||
| `plan_id` | `str` (ULID) | Parent plan (required) |
|
||||
| `parent_decision_id` | `str \| None` | Parent decision; `None` for the root |
|
||||
| `sequence_number` | `int` | Monotonic order within the plan (0-indexed) |
|
||||
|
||||
### Classification
|
||||
|
||||
| Field | Type | Description |
|
||||
|-----------------|----------------|------------------------------------------------------|
|
||||
| `decision_type` | `DecisionType` | One of 11 enum values (see table below) |
|
||||
|
||||
#### `DecisionType` Values
|
||||
|
||||
| Value | Phase | Description |
|
||||
|--------------------------|------------|-------------------------------------------|
|
||||
| `prompt_definition` | Strategize | Root decision — the plan prompt |
|
||||
| `invariant_enforced` | Strategize | An invariant constraint was applied |
|
||||
| `strategy_choice` | Strategize | High-level approach chosen |
|
||||
| `implementation_choice` | Execute | How to implement a specific task |
|
||||
| `resource_selection` | Execute | Which resources to read / modify |
|
||||
| `subplan_spawn` | Strategize | Decision to create a child plan |
|
||||
| `subplan_parallel_spawn` | Strategize | Spawn a group of child plans in parallel |
|
||||
| `tool_invocation` | Execute | Which skill / tool to use |
|
||||
| `error_recovery` | Execute | How to handle a failure |
|
||||
| `validation_response` | Execute | Response to a validation failure |
|
||||
| `user_intervention` | Any | User-provided guidance / correction |
|
||||
|
||||
### Content Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|--------------------------|-----------------|-----------------------------------------------------|
|
||||
| `question` | `str` | What question was being answered (required) |
|
||||
| `chosen_option` | `str` | The option that was selected (required) |
|
||||
| `alternatives_considered`| `list[str]` | Other options evaluated |
|
||||
| `confidence_score` | `float \| None` | 0.0–1.0 confidence, or `None` |
|
||||
|
||||
### Context Snapshot
|
||||
|
||||
Every decision captures a `ContextSnapshot` for replay:
|
||||
|
||||
| Field | Type | Description |
|
||||
|---------------------|--------------|--------------------------------------------------|
|
||||
| `hot_context_hash` | `str` | SHA-256 hash of the context window |
|
||||
| `hot_context_ref` | `str` | Storage pointer to the full serialised context |
|
||||
| `relevant_resources`| `list[ResourceRef]` | Resources referenced at decision time |
|
||||
| `actor_state_ref` | `str \| None`| LangGraph actor checkpoint reference |
|
||||
|
||||
### Rationale Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|------------------|--------------|-----------------------------------------------------|
|
||||
| `rationale` | `str` | Human-readable explanation |
|
||||
| `actor_reasoning`| `str \| None`| Raw LLM reasoning trace, if available |
|
||||
|
||||
### Correction Metadata
|
||||
|
||||
| Field | Type | Description |
|
||||
|------------------------|-----------------|-------------------------------------------------|
|
||||
| `is_correction` | `bool` | `True` if this decision corrects another |
|
||||
| `corrects_decision_id` | `str \| None` | ULID of the original decision |
|
||||
| `correction_reason` | `str \| None` | Why the correction was made |
|
||||
| `superseded_by` | `str \| None` | ULID of the decision that replaced this one |
|
||||
|
||||
---
|
||||
|
||||
## Python API
|
||||
|
||||
### `DecisionService`
|
||||
|
||||
**Module:** `cleveragents.application.services.decision_service`
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.decision_service import DecisionService
|
||||
from cleveragents.domain.models.core.decision import DecisionType
|
||||
|
||||
svc = DecisionService(settings=settings, unit_of_work=uow)
|
||||
|
||||
# Record a decision during Strategize
|
||||
decision = svc.record_decision(
|
||||
plan_id="01HV...",
|
||||
decision_type=DecisionType.STRATEGY_CHOICE,
|
||||
question="Which approach should we use?",
|
||||
chosen_option="Build a REST API with FastAPI",
|
||||
alternatives_considered=["GraphQL", "gRPC"],
|
||||
confidence_score=0.85,
|
||||
rationale="REST is simpler and better supported by existing tooling.",
|
||||
)
|
||||
|
||||
# Retrieve the full decision tree (BFS, level by level)
|
||||
tree = svc.get_tree(plan_id="01HV...")
|
||||
|
||||
# Get a single decision
|
||||
d = svc.get_decision(decision_id="01HXYZ...")
|
||||
|
||||
# List all decisions for a plan (ordered by sequence number)
|
||||
decisions = svc.list_decisions(plan_id="01HV...")
|
||||
|
||||
# List decisions of a specific type
|
||||
strategy_decisions = svc.list_by_type(
|
||||
plan_id="01HV...",
|
||||
decision_type=DecisionType.STRATEGY_CHOICE,
|
||||
)
|
||||
|
||||
# Walk from a decision up to the root
|
||||
path = svc.get_path_to_root(decision_id="01HXYZ...")
|
||||
```
|
||||
|
||||
### Exceptions
|
||||
|
||||
| Exception | When raised |
|
||||
|-------------------------|--------------------------------------------------|
|
||||
| `DecisionNotFoundError` | Decision ID does not exist |
|
||||
| `DuplicateDecisionError`| Decision ID already exists |
|
||||
| `SequenceConflictError` | Sequence number already used for this plan |
|
||||
| `ValidationError` | Required fields missing or empty |
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Decision Domain Model](../reference/decision_model.md) — full field reference
|
||||
- [Decision Service Reference](../reference/decision_service.md) — service API details
|
||||
- [Decision Correction Reference](../reference/decision_correction.md) — correction modes
|
||||
- [Plan CLI Reference](../reference/plan_cli.md) — `agents plan tree` / `agents plan explain`
|
||||
- [Subplan Service](../reference/subplan_service.md) — spawn decisions
|
||||
@@ -19,6 +19,19 @@ classes, functions, and exceptions with signatures and usage examples.
|
||||
| [`cleveragents.providers`](providers.md) | AI provider registry — discovery, selection, LLM factory, and capability metadata |
|
||||
| [`cleveragents.tui`](tui.md) | Interactive Terminal UI — app, persona system, input routing, slash commands, session export/import |
|
||||
|
||||
## Plan Intelligence (v3.2.0 / v3.3.0)
|
||||
|
||||
The following pages document the CLI commands and Python APIs introduced in
|
||||
v3.2.0 (Decisions & Invariants) and v3.3.0 (Corrections, Subplans &
|
||||
Checkpoints).
|
||||
|
||||
| Page | Description |
|
||||
|------|-------------|
|
||||
| [Decisions](decisions.md) | `agents plan tree`, `agents plan explain`, decision recording during Strategize, decision data model and Python API |
|
||||
| [Invariants](invariants.md) | `agents invariant add/list/remove`, invariant scopes, enforcement, data model and Python API |
|
||||
| [Checkpoints](checkpoints.md) | `agents plan checkpoint list`, `agents plan rollback`, automatic triggers, data model and Python API |
|
||||
| [Plan Corrections](plan-corrections.md) | `agents plan correct --mode=revert\|append`, correction data model, subplan system overview and Python API |
|
||||
|
||||
> **Note:** Internal modules (prefixed with `_`) and implementation details
|
||||
> not listed in a module's `__all__` are considered private and may change
|
||||
> without notice.
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
# Invariants API Reference
|
||||
|
||||
Invariants are natural-language constraints on plan execution. They flow into
|
||||
the decision tree during the Strategize phase and are reconciled by the
|
||||
Invariant Reconciliation Actor before any strategy work begins.
|
||||
|
||||
> **Version:** Introduced in v3.2.0.
|
||||
> **See also:** [`docs/reference/invariants.md`](../reference/invariants.md)
|
||||
|
||||
---
|
||||
|
||||
## Concept and Purpose
|
||||
|
||||
An **invariant** is a constraint that must hold throughout plan execution.
|
||||
Examples:
|
||||
|
||||
- `"Never delete production data"`
|
||||
- `"All API changes need tests"`
|
||||
- `"Use Python 3.13 only"`
|
||||
|
||||
Invariants are evaluated at the start of the Strategize phase. If any
|
||||
invariant is violated during execution, an `INVARIANT_VIOLATED` event is
|
||||
emitted and the phase transition is blocked.
|
||||
|
||||
### Scope Hierarchy
|
||||
|
||||
| Scope | Description |
|
||||
|-----------|----------------------------------------------------------|
|
||||
| `GLOBAL` | Applies to every plan in the system |
|
||||
| `PROJECT` | Applies to plans targeting a specific project |
|
||||
| `ACTION` | Defined in an action template; promoted on `plan use` |
|
||||
| `PLAN` | Attached directly to a specific plan |
|
||||
|
||||
### Merge Precedence
|
||||
|
||||
When computing the effective invariant set for a plan:
|
||||
|
||||
```
|
||||
plan > project > global
|
||||
```
|
||||
|
||||
Action-level invariants are promoted to plan scope when `plan use` is called.
|
||||
Invariants are de-duplicated by text (case-insensitive); when the same
|
||||
constraint appears at multiple scopes, only the highest-precedence copy is kept.
|
||||
|
||||
---
|
||||
|
||||
## CLI Commands
|
||||
|
||||
### `agents invariant add`
|
||||
|
||||
Creates a new invariant at the specified scope.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents invariant add [SCOPE_FLAG] <TEXT> [OPTIONS]
|
||||
```
|
||||
|
||||
#### Scope Flags (mutually exclusive)
|
||||
|
||||
| Flag | Description |
|
||||
|-------------------|-------------------------------------------------------|
|
||||
| `--global` | Create a global invariant (applies to all plans) |
|
||||
| `--project NAME` | Create a project-scoped invariant |
|
||||
| `--plan PLAN_ID` | Create a plan-scoped invariant |
|
||||
| `--action NAME` | Create an action-scoped invariant |
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|-------------------|-------------------------------------------------------|
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich`|
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Global invariant (applies to every plan)
|
||||
agents invariant add --global "Never delete production data"
|
||||
|
||||
# Project-scoped invariant
|
||||
agents invariant add --project myapp "All API changes need tests"
|
||||
|
||||
# Plan-specific invariant
|
||||
agents invariant add --plan 01HXYZ... "Use Python 3.13 only"
|
||||
|
||||
# Action-scoped invariant
|
||||
agents invariant add --action local/code-coverage "Minimum 80% coverage"
|
||||
|
||||
# JSON output
|
||||
agents invariant add --global "No hardcoded secrets" --format json
|
||||
```
|
||||
|
||||
#### Output
|
||||
|
||||
On success, the command prints the created invariant's ID and text:
|
||||
|
||||
```
|
||||
✓ OK Invariant 01HABC... created
|
||||
Scope: global
|
||||
Text: Never delete production data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `agents invariant list`
|
||||
|
||||
Displays invariants, optionally filtered by scope or matched by regex.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents invariant list [REGEX] [OPTIONS]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|-------------------------|---------------------------------------------------------------|
|
||||
| `--global` | Show only global invariants |
|
||||
| `--project NAME` | Show only invariants for the specified project |
|
||||
| `--plan PLAN_ID` | Show only invariants for the specified plan |
|
||||
| `--action NAME` | Show only invariants for the specified action |
|
||||
| `--effective` | Show the merged effective set (requires `--project`) |
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich` |
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# List all active invariants
|
||||
agents invariant list
|
||||
|
||||
# Filter by scope
|
||||
agents invariant list --global
|
||||
agents invariant list --project myapp
|
||||
|
||||
# Show merged effective set for a project
|
||||
agents invariant list --effective --project myapp
|
||||
|
||||
# Filter by regex
|
||||
agents invariant list "data.*safe"
|
||||
|
||||
# JSON output
|
||||
agents invariant list --format json
|
||||
```
|
||||
|
||||
#### Output (rich)
|
||||
|
||||
The rich renderer displays a table with columns:
|
||||
|
||||
| Column | Description |
|
||||
|-------------|---------------------------------------------------|
|
||||
| ID | Truncated invariant ULID |
|
||||
| Scope | `global`, `project`, `action`, or `plan` |
|
||||
| Scope Target| Project/plan/action name (if applicable) |
|
||||
| Text | Invariant constraint text |
|
||||
| Created | Creation timestamp |
|
||||
|
||||
---
|
||||
|
||||
### `agents invariant remove`
|
||||
|
||||
Removes an invariant by ID.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents invariant remove [--yes|-y] <INVARIANT_ID> [OPTIONS]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|-------------------|-------------------------------------------------------|
|
||||
| `--yes`, `-y` | Skip the interactive confirmation prompt |
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich`|
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# With confirmation prompt
|
||||
agents invariant remove 01HXYZ...
|
||||
|
||||
# Skip confirmation (useful in scripts)
|
||||
agents invariant remove --yes 01HXYZ...
|
||||
```
|
||||
|
||||
#### Notes
|
||||
|
||||
- Removing a `GLOBAL` or `PROJECT` invariant does not retroactively affect
|
||||
plans that have already been strategized — the invariant was already
|
||||
evaluated and recorded in the decision tree.
|
||||
- Removing a `PLAN`-scoped invariant from a plan that is still in the
|
||||
Strategize phase will affect the next reconciliation run.
|
||||
|
||||
---
|
||||
|
||||
## Invariant Data Model
|
||||
|
||||
**Module:** `cleveragents.domain.models.core.invariant`
|
||||
|
||||
| Field | Type | Description |
|
||||
|---------------|---------------|-----------------------------------------------------|
|
||||
| `id` | `str` (ULID) | Auto-generated unique identifier |
|
||||
| `name` | `str` | Short human-readable label (optional) |
|
||||
| `description` | `str` | The constraint text (required, non-empty) |
|
||||
| `scope` | `InvariantScope` | `GLOBAL`, `PROJECT`, `ACTION`, or `PLAN` |
|
||||
| `scope_target`| `str \| None` | Project name, plan ID, or action name (scope-dependent) |
|
||||
| `created_at` | `datetime` | UTC creation timestamp |
|
||||
| `is_active` | `bool` | Whether the invariant is currently enforced |
|
||||
|
||||
### `InvariantScope` Enum
|
||||
|
||||
```python
|
||||
from cleveragents.domain.models.core.invariant import InvariantScope
|
||||
|
||||
InvariantScope.GLOBAL # "global"
|
||||
InvariantScope.PROJECT # "project"
|
||||
InvariantScope.ACTION # "action"
|
||||
InvariantScope.PLAN # "plan"
|
||||
```
|
||||
|
||||
### Enforcement Record
|
||||
|
||||
When the Invariant Reconciliation Actor evaluates an invariant, it creates an
|
||||
`InvariantEnforcementRecord`:
|
||||
|
||||
| Field | Description |
|
||||
|------------------|--------------------------------------------------|
|
||||
| `invariant_id` | ULID of the invariant |
|
||||
| `enforced` | Whether the invariant was successfully enforced |
|
||||
| `actor_response` | Response text from the reconciliation actor |
|
||||
| `decision_id` | ULID of the associated `invariant_enforced` decision |
|
||||
|
||||
### Violation Model
|
||||
|
||||
When an invariant is violated during execution, an `InvariantViolation` is
|
||||
created:
|
||||
|
||||
| Field | Description |
|
||||
|-----------------|---------------------------------------------------|
|
||||
| `invariant_id` | ULID of the violated invariant |
|
||||
| `violated_text` | The invariant text that was violated |
|
||||
| `severity` | `error`, `warning`, or `info` |
|
||||
| `details` | Additional violation context |
|
||||
|
||||
---
|
||||
|
||||
## Python API
|
||||
|
||||
### `InvariantService`
|
||||
|
||||
**Module:** `cleveragents.application.services.invariant_service`
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.invariant_service import InvariantService
|
||||
from cleveragents.domain.models.core.invariant import InvariantScope
|
||||
|
||||
svc = InvariantService(unit_of_work=uow)
|
||||
|
||||
# Create a global invariant
|
||||
inv = svc.create_invariant(
|
||||
description="Never delete production data",
|
||||
scope=InvariantScope.GLOBAL,
|
||||
)
|
||||
|
||||
# Create a project-scoped invariant
|
||||
inv = svc.create_invariant(
|
||||
description="All API changes need tests",
|
||||
scope=InvariantScope.PROJECT,
|
||||
scope_target="myapp",
|
||||
)
|
||||
|
||||
# List all invariants
|
||||
all_invariants = svc.list_invariants()
|
||||
|
||||
# List by scope
|
||||
global_invariants = svc.list_invariants(scope=InvariantScope.GLOBAL)
|
||||
project_invariants = svc.list_invariants(
|
||||
scope=InvariantScope.PROJECT,
|
||||
scope_target="myapp",
|
||||
)
|
||||
|
||||
# Get the merged effective set for a project
|
||||
effective = svc.get_effective_invariants(project_name="myapp")
|
||||
|
||||
# Remove an invariant
|
||||
svc.remove_invariant(invariant_id="01HXYZ...")
|
||||
```
|
||||
|
||||
### `InvariantReconciliationActor`
|
||||
|
||||
The reconciliation actor runs automatically at every plan phase transition.
|
||||
It is wired into the plan lifecycle and does not need to be invoked manually.
|
||||
|
||||
```python
|
||||
# The actor is resolved from the DI container:
|
||||
from cleveragents.di import get_container
|
||||
|
||||
container = get_container()
|
||||
actor = container.invariant_reconciliation_actor()
|
||||
|
||||
# Manually trigger reconciliation (advanced use):
|
||||
result = await actor.reconcile(plan=plan, context=ctx)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Invariants Reference](../reference/invariants.md) — scope hierarchy, merge precedence, enforcement
|
||||
- [Decision Model](../reference/decision_model.md) — `invariant_enforced` decision type
|
||||
- [Plan CLI Reference](../reference/plan_cli.md) — `--invariant` flag on `agents plan use`
|
||||
- [Automation Profiles](../reference/automation_profiles.md) — profile-level invariant interaction
|
||||
@@ -0,0 +1,354 @@
|
||||
# Plan Corrections API Reference
|
||||
|
||||
The plan correction subsystem allows operators to modify a plan's decision tree
|
||||
after execution by either **reverting** a subtree of decisions or **appending**
|
||||
new decisions as a child plan. This enables targeted re-execution without
|
||||
discarding the entire plan.
|
||||
|
||||
> **Version:** Introduced in v3.3.0. Correction attempts tracking added in v3.8.0.
|
||||
> **See also:** [`docs/reference/decision_correction.md`](../reference/decision_correction.md),
|
||||
> [`docs/reference/subplans.md`](../reference/subplans.md),
|
||||
> [`docs/reference/subplan_service.md`](../reference/subplan_service.md)
|
||||
|
||||
---
|
||||
|
||||
## Concept
|
||||
|
||||
### Correction Modes
|
||||
|
||||
#### Revert Mode
|
||||
|
||||
Invalidates the targeted decision and every descendant reachable via BFS
|
||||
traversal. Associated artifacts are archived and affected child plans are
|
||||
rolled back.
|
||||
|
||||
```text
|
||||
┌─── D1 (target) ◄── revert starts here
|
||||
│ │
|
||||
│ ┌──┴──┐
|
||||
│ D2 D3 ← all invalidated
|
||||
│ │
|
||||
│ D4 ← also invalidated
|
||||
```
|
||||
|
||||
Use revert when the original decision was wrong and you want to re-execute
|
||||
from that point with different guidance.
|
||||
|
||||
#### Append Mode
|
||||
|
||||
Preserves the original decision and spawns a **new child plan** rooted at the
|
||||
target node. The child plan carries the operator's guidance and produces
|
||||
additional decisions without disturbing the existing tree.
|
||||
|
||||
```text
|
||||
D1 (target)
|
||||
│
|
||||
┌──┴──────────┐
|
||||
D2 (original) CP-new ← child plan appended
|
||||
```
|
||||
|
||||
Use append when the original decision was correct but you want to add
|
||||
supplementary work without recomputing.
|
||||
|
||||
---
|
||||
|
||||
## CLI Commands
|
||||
|
||||
### `agents plan correct --mode=revert`
|
||||
|
||||
Re-executes from a targeted decision point by invalidating the decision subtree
|
||||
and re-running from that node with new guidance.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents plan correct --mode=revert <PLAN_ID> <DECISION_ID> [OPTIONS]
|
||||
```
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Argument | Description |
|
||||
|---------------|-------------------------------------------------------|
|
||||
| `PLAN_ID` | ULID of the plan to correct |
|
||||
| `DECISION_ID` | ULID of the decision to revert from |
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|-----------------------|-------------------------------------------------------|
|
||||
| `--mode` | Correction mode: `revert` or `append` (required) |
|
||||
| `--guidance TEXT` | Operator guidance for the re-execution (required) |
|
||||
| `--dry-run` | Preview impact without making changes |
|
||||
| `--yes`, `-y` | Skip the interactive confirmation prompt |
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich`|
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Revert a decision and re-execute with guidance
|
||||
agents plan correct --mode=revert \
|
||||
--guidance "Use a safer migration approach with explicit rollback" \
|
||||
01HPLAN... 01HDECISION...
|
||||
|
||||
# Preview impact before committing
|
||||
agents plan correct --mode=revert --dry-run \
|
||||
--guidance "Use a safer migration approach" \
|
||||
01HPLAN... 01HDECISION...
|
||||
|
||||
# Skip confirmation prompt
|
||||
agents plan correct --mode=revert --yes \
|
||||
--guidance "Use a safer migration approach" \
|
||||
01HPLAN... 01HDECISION...
|
||||
```
|
||||
|
||||
#### Dry-Run Output
|
||||
|
||||
A dry-run report includes:
|
||||
|
||||
- **impact** — Full `CorrectionImpact` with affected decisions, files, child
|
||||
plans, estimated cost, and risk level
|
||||
- **decisions_to_invalidate** — Decision IDs that *would* be marked invalid
|
||||
- **child_plans_to_rollback** — Child plans that *would* be rolled back
|
||||
- **estimated_recompute_time_seconds** — Wall-clock estimate
|
||||
- **warnings** — Human-readable cautions (e.g., high risk)
|
||||
|
||||
#### Risk Classification
|
||||
|
||||
| Affected Decisions | Risk Level |
|
||||
|--------------------|------------|
|
||||
| ≤ 3 | low |
|
||||
| 4 – 10 | medium |
|
||||
| > 10 | high |
|
||||
|
||||
---
|
||||
|
||||
### `agents plan correct --mode=append`
|
||||
|
||||
Adds guidance to a plan by spawning a new child plan rooted at the target
|
||||
decision, without recomputing the existing decision tree.
|
||||
|
||||
#### Synopsis
|
||||
|
||||
```bash
|
||||
agents plan correct --mode=append <PLAN_ID> <DECISION_ID> [OPTIONS]
|
||||
```
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Argument | Description |
|
||||
|---------------|-------------------------------------------------------|
|
||||
| `PLAN_ID` | ULID of the plan to correct |
|
||||
| `DECISION_ID` | ULID of the decision to append from |
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Description |
|
||||
|-----------------------|-------------------------------------------------------|
|
||||
| `--mode` | Correction mode: `revert` or `append` (required) |
|
||||
| `--guidance TEXT` | Operator guidance for the child plan (required) |
|
||||
| `--dry-run` | Preview impact without making changes |
|
||||
| `--yes`, `-y` | Skip the interactive confirmation prompt |
|
||||
| `--format`, `-f` | Output format: `json`, `yaml`, `plain`, `table`, `rich`|
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Append a child plan with additional guidance
|
||||
agents plan correct --mode=append \
|
||||
--guidance "Also add integration tests for the new endpoint" \
|
||||
01HPLAN... 01HDECISION...
|
||||
|
||||
# Preview what would be created
|
||||
agents plan correct --mode=append --dry-run \
|
||||
--guidance "Also add integration tests" \
|
||||
01HPLAN... 01HDECISION...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Correction Status Lifecycle
|
||||
|
||||
```text
|
||||
PENDING → ANALYZING → EXECUTING → APPLIED
|
||||
→ FAILED
|
||||
PENDING → CANCELLED
|
||||
ANALYZING → CANCELLED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Correction Data Model
|
||||
|
||||
**Module:** `cleveragents.domain.models.core.correction`
|
||||
|
||||
| Field | Type | Description |
|
||||
|------------------------|-------------------|-------------------------------------------------|
|
||||
| `correction_id` | `str` (ULID) | Unique identifier |
|
||||
| `plan_id` | `str` (ULID) | Plan being corrected |
|
||||
| `target_decision_id` | `str` (ULID) | Decision being corrected |
|
||||
| `mode` | `CorrectionMode` | `revert` or `append` |
|
||||
| `guidance` | `str` | Operator guidance text (1–10,000 chars) |
|
||||
| `status` | `CorrectionStatus`| Current status (see lifecycle above) |
|
||||
| `created_at` | `datetime` | UTC creation timestamp |
|
||||
| `completed_at` | `datetime \| None`| UTC completion timestamp (terminal states only) |
|
||||
|
||||
### `CorrectionAttemptRecord` (v3.8.0+)
|
||||
|
||||
Each execution of a correction is tracked as a `CorrectionAttemptRecord`.
|
||||
Multiple attempts may exist for a single correction (e.g., if a first attempt
|
||||
fails and the operator retries).
|
||||
|
||||
| Field | Type | Description |
|
||||
|--------------------------|-------------------------|-------------------------------------------------|
|
||||
| `id` | `str` (ULID) | Unique identifier for this attempt |
|
||||
| `correction_id` | `str` (ULID) | Parent correction ULID |
|
||||
| `plan_id` | `str` (ULID) | Plan this correction targets |
|
||||
| `original_decision_id` | `str` (ULID) | Decision being corrected |
|
||||
| `new_decision_id` | `str \| None` | Replacement decision (set on success) |
|
||||
| `mode` | `CorrectionMode` | `revert` or `append` |
|
||||
| `state` | `CorrectionAttemptState`| `pending`, `executing`, `complete`, or `failed` |
|
||||
| `guidance` | `str` | Operator guidance text |
|
||||
| `created_at` | `datetime` | UTC creation timestamp |
|
||||
| `completed_at` | `datetime \| None` | UTC completion timestamp |
|
||||
| `archived_artifacts_path`| `str \| None` | Path to archived artifacts (revert mode) |
|
||||
|
||||
---
|
||||
|
||||
## Subplan System Overview
|
||||
|
||||
Subplans allow a parent plan to decompose work into coordinated child plans.
|
||||
Each child plan runs in its own sandbox, and results are merged back into the
|
||||
parent plan using a configurable merge strategy.
|
||||
|
||||
### How Subplans Are Spawned
|
||||
|
||||
During the **Strategize** phase, the strategy actor may decide to decompose
|
||||
work by recording `subplan_spawn` or `subplan_parallel_spawn` decisions. The
|
||||
`SubplanService` then:
|
||||
|
||||
1. Extracts spawn decisions from the `DecisionService`
|
||||
2. Builds `SpawnEntry` objects from those decisions
|
||||
3. Validates the spawn request (resource scopes, merge strategy, parallelism)
|
||||
4. Creates `SubplanStatus` and `SpawnMetadata` for each entry
|
||||
5. Returns the result for the caller to persist on the parent plan
|
||||
|
||||
### Execution Modes
|
||||
|
||||
| Mode | Description |
|
||||
|-----------------------|--------------------------------------------------|
|
||||
| `sequential` | Execute one at a time in order |
|
||||
| `parallel` | Execute concurrently (up to `max_parallel`) |
|
||||
| `dependency_ordered` | Respect DAG dependencies via topological sort |
|
||||
|
||||
### Merge Strategies
|
||||
|
||||
After subplans complete, their sandbox outputs are merged:
|
||||
|
||||
| Strategy | Description |
|
||||
|-----------------------|--------------------------------------------------|
|
||||
| `git_three_way` | Three-way merge via `git merge-file` |
|
||||
| `sequential_apply` | Apply changes in completion order |
|
||||
| `fail_on_conflict` | Raise `MergeConflictError` on any conflict |
|
||||
| `last_wins` | Final subplan's output overwrites earlier ones |
|
||||
|
||||
### Subplan Configuration
|
||||
|
||||
```yaml
|
||||
subplan_config:
|
||||
execution_mode: parallel # sequential | parallel | dependency_ordered
|
||||
merge_strategy: git_three_way # git_three_way | sequential_apply | fail_on_conflict | last_wins
|
||||
max_parallel: 5 # 1-50, for parallel mode
|
||||
fail_fast: false # stop all on first failure
|
||||
timeout_per_subplan_seconds: ~ # optional per-subplan timeout
|
||||
retry_failed: true # auto-retry failed subplans
|
||||
max_retries: 2 # 0-5, max retry attempts
|
||||
```
|
||||
|
||||
### Checkpoint Integration
|
||||
|
||||
Before the first subplan execution attempt, the `SubplanExecutionService`
|
||||
automatically creates a checkpoint (the `on_subplan_spawn` trigger). This
|
||||
allows rolling back to the pre-spawn state if subplan execution fails
|
||||
catastrophically.
|
||||
|
||||
---
|
||||
|
||||
## Python API
|
||||
|
||||
### `CorrectionService`
|
||||
|
||||
**Module:** `cleveragents.application.services.correction_service`
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.correction_service import CorrectionService
|
||||
from cleveragents.domain.models.core.correction import CorrectionMode
|
||||
|
||||
svc = CorrectionService(
|
||||
decision_service=decision_svc,
|
||||
plan_service=plan_svc,
|
||||
checkpoint_service=checkpoint_svc, # optional
|
||||
)
|
||||
|
||||
# Create a correction request
|
||||
correction = svc.request_correction(
|
||||
plan_id="01HPLAN...",
|
||||
target_decision_id="01HDECISION...",
|
||||
mode=CorrectionMode.REVERT,
|
||||
guidance="Use a safer migration approach with explicit rollback",
|
||||
)
|
||||
|
||||
# Analyze impact (BFS over decision tree)
|
||||
impact = svc.analyze_impact(correction_id=correction.correction_id)
|
||||
# impact.affected_decisions, impact.affected_files, impact.risk_level
|
||||
|
||||
# Generate a dry-run report (no side effects)
|
||||
report = svc.generate_dry_run_report(correction_id=correction.correction_id)
|
||||
|
||||
# Execute the correction
|
||||
result = svc.execute_correction(correction_id=correction.correction_id)
|
||||
|
||||
# List corrections for a plan
|
||||
corrections = svc.list_corrections(plan_id="01HPLAN...")
|
||||
|
||||
# Cancel a pending correction
|
||||
svc.cancel_correction(correction_id=correction.correction_id)
|
||||
```
|
||||
|
||||
### `SubplanService`
|
||||
|
||||
**Module:** `cleveragents.application.services.subplan_service`
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.subplan_service import SubplanService
|
||||
|
||||
svc = SubplanService(
|
||||
decision_service=decision_svc,
|
||||
config=plan.subplan_config,
|
||||
)
|
||||
|
||||
# Get spawn decisions for the parent plan
|
||||
decisions = svc.get_spawn_decisions(parent_plan_id="01HPLAN...")
|
||||
|
||||
# Build spawn entries from decisions
|
||||
entries = svc.build_spawn_entries(decisions)
|
||||
|
||||
# Spawn child plans (validates first)
|
||||
result = svc.spawn(
|
||||
parent_plan=parent_plan,
|
||||
config=parent_plan.subplan_config,
|
||||
spawn_entries=entries,
|
||||
available_resources=frozenset(known_resource_ids),
|
||||
)
|
||||
# result.spawned_statuses, result.metadata, result.total_spawned
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Decision Correction Reference](../reference/decision_correction.md) — full correction reference
|
||||
- [Subplans: Execution and Merge](../reference/subplans.md) — subplan execution modes and merge strategies
|
||||
- [Subplan Service Reference](../reference/subplan_service.md) — spawn workflow details
|
||||
- [Checkpoints API Reference](checkpoints.md) — checkpoint and rollback
|
||||
- [Decisions API Reference](decisions.md) — decision tree and recording
|
||||
- [Plan CLI Reference](../reference/plan_cli.md) — plan commands overview
|
||||
Reference in New Issue
Block a user