> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ellomas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> System architecture and data flow overview.

# Architecture

Graft is a Go CLI that orchestrates three subsystems: the Docker lifecycle manager, the content-addressable storage (CAS) layer, and the state manager.

## System Diagram

```
┌─────────────────────────────────────────────────────────┐
│                     Graft CLI                            │
│  ┌────────────┐  ┌────────────┐  ┌───────────────────┐  │
│  │ Docker      │  │ DAG        │  │ State Manager     │  │
│  │ Lifecycle   │  │ Store      │  │ (config.json)     │  │
│  └──────┬──────┘  └─────┬──────┘  └────────┬──────────┘  │
│         │               │                   │             │
│         ▼               ▼                   ▼             │
│  ┌────────────┐  ┌────────────┐  ┌───────────────────┐  │
│  │ Object     │  │ Merkle     │  │ Volume Bridge     │  │
│  │ Pool       │  │ Tree       │  │ (docker → host)   │  │
│  └────────────┘  └────────────┘  └───────────────────┘  │
└─────────────────────────────────────────────────────────┘
         │                        │
         ▼                        ▼
  ┌──────────┐            ┌──────────────┐
  │ Docker   │            │ Host         │
  │ Engine   │            │ Filesystem   │
  │ (API)    │            │ ~/.graft/    │
  └──────────┘            └──────────────┘
```

## Subsystems

### Docker Lifecycle

The `internal/docker` package wraps the Docker Engine SDK. It handles:

* Container inspection (capturing image, env, ports, networks)
* Graceful stop and start
* Container removal and recreation with host bind mounts
* Smart lifecycle (only restart if container was originally running)

Graft uses the Docker SDK directly (not shell commands) for type-safe, structured container management.

### CAS Layer (DAG)

The `internal/dag` package contains three components:

| Component | File        | Responsibility                                   |
| --------- | ----------- | ------------------------------------------------ |
| Store     | `store.go`  | SQLite CRUD for commits, tree\_entries, refs     |
| Merkle    | `merkle.go` | BLAKE3 hashing, leaf building, tree construction |
| Object    | `object.go` | Blob pool (Put, Get, Has, Materialize)           |
| Verify    | `verify.go` | Branch integrity checking                        |

### State Manager

The `internal/state` package manages `config.json` — the lightweight state file at `~/.graft/<project>/`. It tracks:

* Schema version (for migration safety)
* Target container ID
* Active branch
* Project root path
* Operation mode (snapshot vs bind)
* Container configuration (image, env, ports, network)
* Branch metadata (name, path, size, timestamps)

## Data Flow

### Init Flow

```
1. Inspect container (image, env, ports, network, volumes)
2. Prompt for volume selection
3. Stop container
4. Bridge volume data to host (ephemeral Alpine runner)
5. Create objects/ directory + graft.db
6. (Optional) Recreate container with bind mount
7. Save config.json
```

### Commit Flow

```
1. Stop container
2. Walk branch directory → BLAKE3 hash every file
3. Store each file in object pool (deduplicated)
4. Build Merkle tree → single root hash
5. Insert commit + tree entries in SQLite (atomic transaction)
6. Advance branch ref
7. Start container
```

### Checkout Flow

```
1. Look up target branch commit
2. Load tree entries
3. Diff current dir vs target tree
4. Materialize only changed files from object pool
5. Prune empty directories
6. Recreate container with bind mount
7. Save config.json
```

## Two Operation Modes

### Snapshot Mode (default)

The container stays on its original Docker volume. At commit time, Graft bridges data from the Docker volume to the host using an ephemeral Alpine runner. The container is never recreated.

Best for: Quick evaluation, when you don't want Graft managing your container.

### Bind Mount Mode (--bind)

Graft recreates the container with a host bind mount pointing at the branch directory. The container's data lives directly on the host. No Alpine runner is needed for subsequent operations.

Best for: Full lifecycle management, frequent branching, production use.
