aiwg
Version:
Cognitive architecture for AI-augmented software development with structured memory, ensemble validation, and closed-loop correction. FAIR-aligned artifacts, 84% cost reduction via human-in-the-loop, standards adopted by 100+ organizations.
360 lines (282 loc) • 11.7 kB
Markdown
Periodic state capture for External Ralph Loop sessions, enabling crash recovery and progress tracking during long-running Claude sessions (6-8 hours).
## Overview
The Checkpoint Manager captures periodic snapshots of project state during active Claude sessions. This enables:
- **Crash Recovery**: Know exactly what state the project was in when a session crashed
- **Progress Tracking**: See how the project evolved over time
- **Memory Tracking**: Monitor resource usage during long sessions
- **Cumulative Change Tracking**: Aggregate all files modified across checkpoints
## Architecture
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Checkpoint Manager │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ start() captureCheckpoint() │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────┐ ┌──────────────┐ │
│ │ Initial │ │ Capture │ │
│ │Checkpoint│──────────────│ Git Status │ │
│ └─────────┘ └──────────────┘ │
│ │ │ │
│ │ ┌──────────────┐ │
│ │ │ Capture │ │
│ │ │ .aiwg State │ │
│ │ └──────────────┘ │
│ │ │ │
│ ▼ ┌──────────────┐ │
│ ┌─────────┐ │ Capture │ │
│ │ Timer │──interval────▶│Memory Usage │ │
│ │ (30min) │ └──────────────┘ │
│ └─────────┘ │ │
│ │ ▼ │
│ │ ┌──────────────┐ │
│ │ │ Write │ │
│ │ │ Checkpoint │ │
│ │ │ File │ │
│ │ └──────────────┘ │
│ ▼ │
│ stop() ──────────────────▶ Final Checkpoint + Summary │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
## Quick Start
```javascript
import { CheckpointManager } from './checkpoint-manager.mjs';
const checkpoints = new CheckpointManager({
stateDir: '.aiwg/ralph-external/iterations/001',
projectRoot: '/path/to/project',
interval: 15 * 60 * 1000, // 15 minutes
sessionId: 'session-uuid',
});
// Start periodic checkpoints
checkpoints.start();
// ... Claude session runs ...
// Stop and get summary
const summary = checkpoints.stop();
console.log(`Captured ${summary.total} checkpoints`);
console.log(`Files modified: ${summary.filesModified.length}`);
```
```javascript
const checkpoints = new CheckpointManager(options);
```
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `stateDir` | string | required | Directory for checkpoint files |
| `projectRoot` | string | required | Project root directory |
| `interval` | number | 1800000 | Checkpoint interval in ms (30 min) |
| `sessionId` | string | 'unknown' | Claude session ID |
| `onCheckpoint` | function | null | Callback on each checkpoint |
### Methods
#### `start(options?)`
Start periodic checkpoint capture.
```javascript
checkpoints.start();
// or with options override
checkpoints.start({
interval: 10 * 60 * 1000, // 10 minutes
});
```
- Captures initial checkpoint immediately
- Starts periodic timer
- Returns `this` for chaining
Stop checkpoint timer and capture final checkpoint.
```javascript
const summary = checkpoints.stop();
```
**Returns**: Checkpoint summary (see below)
#### `captureCheckpoint(number)`
Manually capture a checkpoint.
```javascript
const checkpoint = checkpoints.captureCheckpoint(5);
```
**Returns**: `CheckpointData` object
Get all checkpoints for current session.
```javascript
const checkpoints = manager.getAllCheckpoints();
```
**Returns**: Array of `CheckpointData` objects
Generate summary of all checkpoints.
```javascript
const summary = checkpoints.summarizeCheckpoints();
// or for a specific directory
const summary = CheckpointManager.prototype.summarizeCheckpoints('.aiwg/ralph-external/iterations/001');
```
**Returns**: Summary object (see below)
### Static Methods
#### `CheckpointManager.getLatestCheckpoint(stateDir)`
Get latest checkpoint from a directory.
```javascript
const latest = CheckpointManager.getLatestCheckpoint(
'.aiwg/ralph-external/iterations/001'
);
```
Format duration in human-readable format.
```javascript
CheckpointManager.formatDuration(5400000); // "1h 30m"
CheckpointManager.formatDuration(90000); // "1m 30s"
CheckpointManager.formatDuration(5000); // "5s"
```
```typescript
interface CheckpointData {
number: number; // Checkpoint number
timestamp: string; // ISO timestamp
duration: number; // Milliseconds since session start
sessionId: string; // Claude session ID
gitStatus: {
branch: string; // Current git branch
modified: string[]; // Modified files
untracked: string[]; // Untracked files
staged: string[]; // Staged files
error?: string; // Error message if git command failed
};
aiwgState: {
files: string[]; // Files in .aiwg/
sizes: Record<string, number>; // File sizes in bytes
error?: string; // Error message if scan failed
};
filesModified: string[]; // Cumulative files modified
memory: {
heapUsed: number; // Heap memory used in bytes
rss: number; // Resident set size in bytes
};
}
```
```typescript
interface CheckpointSummary {
total: number; // Total checkpoint count
totalDuration: number; // Total session duration in ms
filesModified: string[]; // All files modified across checkpoints
checkpoints: Array<{
number: number;
timestamp: string;
duration: number;
filesModified: number; // Count of files
gitStatus: {
modified: number;
staged: number;
untracked: number;
};
aiwgFiles: number; // Count of .aiwg files
}>;
}
```
The CheckpointManager extends EventEmitter:
```javascript
checkpoints.on('started', ({ interval, checkpointsDir }) => {
console.log(`Started with ${interval}ms interval`);
});
checkpoints.on('checkpoint', (checkpoint) => {
console.log(`Checkpoint ${checkpoint.number} captured`);
});
checkpoints.on('stopped', ({ finalCheckpoint, summary }) => {
console.log(`Stopped after ${summary.total} checkpoints`);
});
```
Checkpoints are saved as JSON files:
```
.aiwg/ralph-external/iterations/001/
└── checkpoints/
├── 001-checkpoint.json
├── 002-checkpoint.json
├── 003-checkpoint.json
└── ...
```
```json
{
"number": 3,
"timestamp": "2026-01-18T14:30:00.000Z",
"duration": 3600000,
"sessionId": "abc123-def456",
"gitStatus": {
"branch": "feature/auth",
"modified": ["src/auth/login.ts"],
"untracked": ["src/auth/logout.ts"],
"staged": []
},
"aiwgState": {
"files": [
"requirements/UC-001-auth.md",
"planning/iteration-1.md"
],
"sizes": {
"requirements/UC-001-auth.md": 2048,
"planning/iteration-1.md": 1024
}
},
"filesModified": [
"src/auth/login.ts",
"src/auth/middleware.ts"
],
"memory": {
"heapUsed": 52428800,
"rss": 104857600
}
}
```
```javascript
// In orchestrator.mjs
if (this.config.enableCheckpoints) {
this.checkpointManager = new CheckpointManager({
stateDir: iterationDir,
projectRoot: this.projectRoot,
interval: (this.config.checkpointIntervalMinutes || 30) * 60 * 1000,
sessionId,
});
// Start checkpoints before session
this.checkpointManager.start();
// ... run Claude session ...
// Stop and get summary after session
const checkpointSummary = this.checkpointManager.stop();
iteration.checkpointSummary = checkpointSummary;
}
```
| Session Duration | Recommended Interval |
|------------------|---------------------|
| < 1 hour | 10-15 minutes |
| 1-3 hours | 15-20 minutes |
| 3-6 hours | 20-30 minutes |
| 6-8 hours | 30 minutes (default) |
- Checkpoint capture is synchronous but fast (~10-50ms)
- Git status is captured via shell command
- .aiwg directory is walked recursively (keep it organized)
- Memory tracking uses Node's `process.memoryUsage()`
## Error Handling
The checkpoint manager is designed to be resilient:
- Git command failures: Captured with error message in checkpoint
- Directory scan failures: Captured with error message
- File write failures: Thrown (caller should handle)
## Recovery Usage
To recover from a crash:
```javascript
// Get latest checkpoint from crashed session
const latest = CheckpointManager.getLatestCheckpoint(
'.aiwg/ralph-external/iterations/001'
);
if (latest) {
console.log(`Last checkpoint: ${latest.timestamp}`);
console.log(`Files modified: ${latest.filesModified.join(', ')}`);
console.log(`Duration at crash: ${CheckpointManager.formatDuration(latest.duration)}`);
}
```
- @tools/ralph-external/orchestrator.mjs - Main loop integration
- @tools/ralph-external/snapshot-manager.mjs - Pre/post snapshots
- @tools/ralph-external/state-assessor.mjs - Two-phase assessment
- @.aiwg/requirements/design-ralph-external.md - Design specification