Skip to content

[High] Implement Session Checkpointing #20

@marklicata

Description

@marklicata

Summary

Implement automatic git-based checkpointing that creates restore points before file modifications, allowing users to rewind to any previous state with a simple Esc Esc gesture or /checkpoint restore command.

Current State

Amplifier CLI stores session transcripts as JSONL but has no:

  • Automatic checkpointing of file system state
  • Git-based snapshots before tool execution
  • Rewind/restore functionality
  • Diff viewing between checkpoints

Proposed Implementation

1. Checkpoint Architecture

.amplifier/
└── checkpoints/
    └── {session_id}/
        ├── metadata.json           # Session info
        ├── 001_initial.json        # First checkpoint
        ├── 002_before_write.json   # Before file write
        ├── 003_before_bash.json    # Before bash command
        └── ...

Each checkpoint stores:

{
  "id": "cp_001",
  "timestamp": "2024-01-15T10:30:00Z",
  "trigger": "before_tool",
  "tool": "Write",
  "args": {"path": "src/main.py", "content": "..."},
  "git_ref": "amplifier/checkpoint/cp_001",
  "conversation_index": 5,
  "description": "Before writing to src/main.py"
}

2. Git Integration

Checkpoints use git refs (not commits on main branch):

# Create checkpoint
git stash create "amplifier checkpoint cp_001"
git update-ref refs/amplifier/checkpoints/cp_001 <stash-sha>

# Restore checkpoint
git stash apply refs/amplifier/checkpoints/cp_001

# Clean up old checkpoints
git update-ref -d refs/amplifier/checkpoints/cp_001

This approach:

  • Doesn't pollute git history
  • Works even with uncommitted changes
  • Can be restored at any time
  • Cleans up automatically when session ends

3. Automatic Checkpoint Triggers

checkpoints:
  enabled: true
  triggers:
    - before_write        # Before any file write
    - before_edit         # Before any file edit
    - before_bash         # Before bash commands (configurable)
    - on_request          # Manual /checkpoint command
  
  # Only checkpoint bash commands matching these patterns
  bash_patterns:
    - "rm *"
    - "mv *"
    - "git *"
    - "npm *"
    
  # Auto-cleanup
  max_checkpoints: 50
  retention_hours: 24

4. Rewind Gesture (Esc Esc)

In interactive mode, pressing Esc twice quickly:

  1. Shows last checkpoint info
  2. Prompts for confirmation
  3. Restores file system state
  4. Optionally rolls back conversation
amplifier> [Esc Esc pressed]

Last checkpoint: cp_003 (2 minutes ago)
  Trigger: Before writing to src/main.py
  Files changed since: src/main.py, tests/test_main.py
  
Restore options:
  [1] Restore files only (keep conversation)
  [2] Restore files and rewind conversation
  [3] View diff since checkpoint
  [c] Cancel

Choice: 

5. Slash Commands

/checkpoint                    # List recent checkpoints
/checkpoint list               # Same as above
/checkpoint show <id>          # Show checkpoint details
/checkpoint diff <id>          # Show diff since checkpoint
/checkpoint restore <id>       # Restore to checkpoint
/checkpoint create [message]   # Create manual checkpoint

6. New Module Structure

src/amplifier_app_cli/checkpoints/
├── __init__.py
├── manager.py        # Main checkpoint management
├── git.py            # Git operations (ref-based)
├── storage.py        # Metadata storage
├── triggers.py       # Automatic trigger detection
├── restore.py        # Restore operations
└── cleanup.py        # Old checkpoint cleanup

7. Core Interfaces

from dataclasses import dataclass
from pathlib import Path
from datetime import datetime

@dataclass
class Checkpoint:
    id: str
    session_id: str
    timestamp: datetime
    trigger: Literal["before_write", "before_edit", "before_bash", "manual"]
    tool: str | None
    tool_args: dict | None
    git_ref: str
    conversation_index: int
    description: str
    files_changed: list[Path]  # Files modified since this checkpoint

class CheckpointManager:
    def __init__(
        self, 
        session_id: str,
        working_dir: Path,
        config: CheckpointConfig
    ): ...
    
    def create(
        self, 
        trigger: str,
        tool: str | None = None,
        tool_args: dict | None = None,
        description: str | None = None
    ) -> Checkpoint:
        """Create a new checkpoint."""
        ...
    
    def list(self, limit: int = 10) -> list[Checkpoint]:
        """List recent checkpoints."""
        ...
    
    def get(self, checkpoint_id: str) -> Checkpoint | None:
        """Get checkpoint by ID."""
        ...
    
    def restore(
        self, 
        checkpoint_id: str,
        restore_conversation: bool = False
    ) -> RestoreResult:
        """Restore to a checkpoint."""
        ...
    
    def diff(self, checkpoint_id: str) -> str:
        """Get diff since checkpoint."""
        ...
    
    def cleanup(self, max_age_hours: int = 24) -> int:
        """Remove old checkpoints, return count removed."""
        ...

@dataclass
class RestoreResult:
    success: bool
    checkpoint: Checkpoint
    files_restored: list[Path]
    conversation_rewound: bool
    error: str | None = None

8. Integration Points

  1. PreToolUse hook: Create checkpoint before file/bash operations
  2. Interactive mode: Handle Esc Esc gesture
  3. Session end: Clean up old checkpoints
  4. Slash commands: Register checkpoint commands

9. Non-Git Fallback

For directories without git:

class FileBackupCheckpoint:
    """Fallback checkpoint using file copies."""
    
    def create(self, files: list[Path]) -> str:
        """Copy files to .amplifier/checkpoints/backup/"""
        ...
    
    def restore(self, checkpoint_id: str) -> None:
        """Restore from backup copies."""
        ...

10. CLI Flags

# Disable checkpointing
amplifier run -p "task" --no-checkpoints

# Restore before starting
amplifier run --restore-checkpoint cp_003

# List checkpoints for a session
amplifier checkpoints list --session abc123
amplifier checkpoints restore cp_003

Acceptance Criteria

  • Automatic checkpoint before file writes
  • Automatic checkpoint before file edits
  • Configurable checkpoint before bash commands
  • Git ref-based storage (doesn't pollute history)
  • Fallback for non-git directories
  • Esc Esc gesture triggers restore prompt
  • /checkpoint slash commands work
  • Diff viewing between checkpoints
  • Conversation rewind option
  • Automatic cleanup of old checkpoints
  • Checkpoints survive session restart
  • Unit tests for checkpoint operations
  • Integration tests for restore flow

Related

  • Depends on: None
  • Enhances: User safety, confidence in AI operations

Estimated Effort

High - 2-3 weeks

Files to Create/Modify

  • src/amplifier_app_cli/checkpoints/ (new module)
  • src/amplifier_app_cli/ui/interactive.py (Esc Esc handling)
  • src/amplifier_app_cli/commands/slash.py (/checkpoint commands)
  • src/amplifier_app_cli/ui/approval.py (checkpoint before tools)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions