Files
cleveragents-core/docs/api/checkpoints.md
T

238 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Checkpoint and Rollback API (v3.3.0)
CleverAgents supports checkpointing and rollback to snapshot sandbox state during plan
execution and restore it later. This page documents the CLI commands and Python API for
managing checkpoints.
---
## Overview
Checkpointing introduced in **v3.3.0** allows operators to:
- Snapshot sandbox state at key points during plan execution.
- Roll back to a previous snapshot to undo tool side-effects.
- Integrate with the decision-correction revert flow for targeted re-execution.
Checkpoints are immutable records stored in the `checkpoint_metadata` SQLite table and
backed by a `CheckpointRepository`. The `CheckpointService` is registered in the DI
container and injected into `ToolRunner`, `SubplanExecutionService`, and `PlanExecutor`.
---
## CLI Reference
### `agents plan checkpoint list`
List all checkpoints for a plan.
```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
agents plan checkpoint list 01HXYZ1234567890ABCDEFGH
# JSON output for scripting
agents plan checkpoint list 01HXYZ1234567890ABCDEFGH --format json
```
Each checkpoint entry shows:
| Field | Description |
|-------|-------------|
| `checkpoint_id` | ULID identifier |
| `checkpoint_type` | `pre_write`, `post_step`, or `manual` |
| `decision_id` | Optional decision this checkpoint is aligned to |
| `sandbox_ref` | Git commit hash or patch reference |
| `size_bytes` | Size of the checkpoint data |
| `created_at` | UTC creation timestamp |
---
### `agents plan rollback`
Roll back a plan's sandbox to a previously captured checkpoint.
```bash
agents plan rollback [--yes|-y] <PLAN_ID> <CHECKPOINT_ID>
```
**Options:**
| Flag | Description |
|------|-------------|
| `--yes`, `-y` | Skip the interactive confirmation prompt |
**Examples:**
```bash
# Rollback with confirmation prompt
agents plan rollback 01HXYZ1234567890ABCDEFGH 01HABC1234567890ABCDEFGH
# Skip confirmation (for scripts/CI)
agents plan rollback --yes 01HXYZ1234567890ABCDEFGH 01HABC1234567890ABCDEFGH
```
**JSON output envelope** (when using `--format json`):
```json
{
"rollback_summary": {
"plan_id": "...",
"from_checkpoint_id": "...",
"restored_files_count": 3
},
"changes_reverted": ["path/to/file1.py", "path/to/file2.py"],
"impact": {
"files_affected": 3
},
"post_rollback_state": {
"active_checkpoint": "...",
"plan_id": "..."
},
"timing": {
"elapsed_seconds": 0.042
},
"messages": ["Rollback completed successfully."]
}
```
**Error cases:**
| Error | Cause |
|-------|-------|
| `Rollback blocked: plan is already applied` | Plan has reached 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 |
---
## Checkpoint Lifecycle
### Checkpoint Types
| Type | When Created |
|------|-------------|
| `pre_write` | Automatically before each write-tool execution |
| `post_step` | Automatically after each write-tool execution |
| `manual` | Via `CheckpointService.create_checkpoint()` directly |
### Automatic Checkpoint Triggers (v3.8.0+)
The execution engine supports four automatic triggers, configurable via
`core.checkpoints.auto_create_on`:
| Trigger | When | Component |
|---------|------|-----------|
| `on_tool_write` | Before each write-tool execution | `ToolRunner` |
| `on_tool_write_complete` | After each write-tool execution | `ToolRunner` |
| `on_subplan_spawn` | Before first subplan execution attempt | `SubplanExecutionService` |
| `on_error` | When the Execute phase fails | `PlanExecutor` |
**Configuration:**
```toml
[core.checkpoints]
auto_create_on = ["on_tool_write", "on_tool_write_complete", "on_subplan_spawn", "on_error"]
```
To disable all automatic checkpoints:
```toml
[core.checkpoints]
auto_create_on = []
```
### Retention Policy
A `CheckpointRetentionPolicy` governs how many checkpoints a plan may keep:
| Field | Default | Range |
|-------|---------|-------|
| `max_checkpoints` | 50 | 1100 |
| `auto_prune` | `true` | — |
When `auto_prune` is enabled and the count exceeds `max_checkpoints`, the oldest
**interior** checkpoints are removed. The first (earliest) and most recent checkpoints
are always preserved.
---
## Checkpoint Data Model
Each checkpoint stores:
| Field | Type | Description |
|-------|------|-------------|
| `checkpoint_id` | ULID | Unique identifier |
| `plan_id` | ULID | The plan that owns this checkpoint |
| `sandbox_ref` | str | Git commit hash or patch reference |
| `decision_id` | ULID \| None | Optional decision alignment |
| `checkpoint_type` | str | `pre_write`, `post_step`, or `manual` |
| `resource_id` | ULID \| None | Optional resource 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` | dict | Audit metadata: `reason`, `source_tool`, `phase`, `extra` |
---
## Python API
The `CheckpointService` is obtained from the DI container:
```python
from cleveragents.application.container import get_container
checkpoint_service = get_container().checkpoint_service()
# Create a manual checkpoint
checkpoint = checkpoint_service.create_checkpoint(
plan_id="01HV...",
sandbox_ref="abc123",
checkpoint_type="manual",
metadata={"reason": "pre-correction snapshot", "phase": "execute"},
)
# List checkpoints for a plan
checkpoints = checkpoint_service.list_checkpoints(plan_id="01HV...")
# Roll back to a checkpoint
result = checkpoint_service.rollback_to_checkpoint(
plan_id="01HV...",
checkpoint_id="01HABC...",
)
print(f"Restored {result.restored_files_count} files")
```
---
## Rollback Guards
The rollback operation enforces two guards:
1. **Plan is applied** — Once a plan reaches the `applied` terminal state, rollback is
rejected with a `BusinessRuleViolation`.
2. **Sandbox is missing** — If the sandbox has been cleaned up, rollback is rejected
because there is nothing to restore.
---
## See Also
- [`docs/reference/checkpointing.md`](../reference/checkpointing.md) — Full checkpointing domain model reference
- [`docs/api/plan-corrections.md`](plan-corrections.md) — Plan correction modes (revert uses checkpoints)
- [ADR-015: Sandbox & Checkpoint](../adr/ADR-015-sandbox-and-checkpoint.md)
- [ADR-035: Decision Tree Rollback & Replay](../adr/ADR-035-decision-tree-rollback-and-replay.md)