Chronicle supports bidirectional replication between agent-side and sandbox-side instances.

Architecture

Agent Host                              Sandbox (E2B / Docker)
┌──────────────┐                       ┌──────────────┐
│  Chronicle    │                       │  Chronicle    │
│  (server)     │◄─────────────────────►│  (client)     │
│               │   Unix socket or      │               │
│  Master DB    │   WebSocket           │  Local DB     │
│  CAS Store    │                       │  Local CAS    │
└──────────────┘                       └──────────────┘

Roles

Agent Mode (Server)

The agent-side Chronicle is the master. It:
  • Listens for sandbox connections on a Unix socket or WebSocket
  • Pushes file notifications to connected sandboxes
  • Accepts write-back requests from sandboxes
  • Serves content via CAS for large files
  • Runs with --replication flag

Sandbox Mode (Client)

The sandbox-side Chronicle is a replica. It:
  • Connects to the agent’s replication socket
  • Receives file change notifications
  • Applies changes to its local filesystem
  • Journals local writes and sends them back to the agent
  • Runs with --connect or --ws-connect flag

Replication Flow

Agent → Sandbox (Push)

1. Agent writes file → Chronicle creates iteration
2. PushChannelManager detects new iteration
3. Notification sent to connected sandboxes:
   - File path, size, permissions, content hash
   - Inline content for small files (under 4KB)
4. Sandbox receives notification:
   - Applies metadata immediately
   - Fetches content via CAS if not inline
5. Sandbox sends ACK (up_to_sequence)

Sandbox → Agent (Write-back)

1. Sandbox writes file → Chronicle creates local iteration
2. WriteJournal records the write:
   - filepath, content_hash, size, permissions
   - master_rowid_seen (causal dependency)
3. WritebackLoop sends batch to agent:
   - WriteBack message with entries
4. Agent reconciles:
   - Checks causal dependency (no conflicts)
   - Accepted entries → applied to master DB
   - Rejected entries → reason sent back
5. Agent sends WriteBackResult
6. Sandbox marks entries as accepted/rejected

Conflict Resolution

Write-back uses causal dependency tracking:
  • Each sandbox write records the last master iteration it has seen (master_rowid_seen)
  • On reconciliation, if the master has advanced past that point for the same file, the write is rejected
  • The sandbox can retry after catching up to the latest state

Catchup and Resync

If a sandbox detects a gap in sequence numbers (via heartbeat comparison):
  1. Sandbox sends CatchupRequest { since_sequence }
  2. Agent replays missed notifications from that sequence
  3. If the gap is too large, agent sends FullResyncRequired
  4. Sandbox performs a full reconciliation from scratch

Filtering

Replication supports gitignore-compatible pattern filtering:
let filter = DirectionalFilter::new();
filter.add_pattern(FilterPattern::new("*.pyc"));
filter.add_pattern(FilterPattern::new("node_modules/**"));
filter.add_pattern(FilterPattern::new(".git/**"));
Patterns are evaluated with lazy compilation and fast paths for common cases (exact match, prefix, suffix, contains).