# Cairn — Modules

## Source Layout

```
cairn/src/cairn/
├── __init__.py          # __version__
├── cli.py               # Click CLI: serve, dispatch
├── server/
│   ├── app.py           # FastAPI app, lifespan, router mount
│   ├── db.py            # SQLite connection, schema, migrations
│   ├── models.py        # Pydantic request/response models
│   ├── services.py      # Shared DB helpers (expire, validate, ID gen)
│   └── routers/
│       ├── projects.py  # CRUD + reason/complete/reopen
│       ├── intents.py   # Create, heartbeat, release, conclude
│       ├── hints.py     # Create hint
│       ├── export.py    # YAML + timeline export
│       └── settings.py  # Get/update timeout settings
└── dispatcher/
    ├── config.py        # DispatchConfig (Pydantic, YAML loader)
    ├── contracts.py     # Payload validation for task outputs
    ├── logging.py       # Structured logging config
    ├── models.py        # RunningTask, ReasonCheckpoint dataclasses
    ├── output_parser.py # JSON extraction from LLM stdout
    ├── prompting.py     # Template rendering
    ├── protocol/
    │   └── client.py    # CairnClient — HTTP wrapper for server API
    ├── runtime/
    │   ├── cancellation.py     # TaskCancellation (thread-safe flag)
    │   ├── containers.py       # ContainerManager (Docker SDK)
    │   ├── heartbeat.py        # Heartbeat thread
    │   ├── process.py          # Subprocess runner for worker commands
    │   └── startup_healthcheck.py  # Worker health checks at startup
    ├── scheduler/
    │   ├── loop.py      # DispatcherLoop — main scheduling loop
    │   └── worker_select.py  # Worker selection algorithm
    ├── tasks/
    │   ├── bootstrap.py # Bootstrap task executor
    │   ├── common.py    # Shared task utilities
    │   ├── explore.py   # Explore task executor
    │   └── reason.py    # Reason task executor
    └── workers/
        ├── __init__.py
        ├── base.py      # BaseWorker interface
        ├── registry.py  # Worker registry
        └── adapters/
            ├── claudecode.py  # Claude Code adapter
            ├── codex.py       # OpenAI Codex adapter
            ├── pi.py          # Pi adapter
            ├── mock.py        # Mock adapter (testing)
            └── _curl.py       # Low-level HTTP helper
```

## Module Details

### cli.py
Click CLI with two commands: `serve` (starts FastAPI via uvicorn) and `dispatch` (starts DispatcherLoop). Both accept `--log-level`. `serve` adds `--host`, `--port`, `--db-path`. `dispatch` adds `--config`, `--once`, `--startup-healthcheck-only`.

### server/
FastAPI application. Only responsible for graph consistency — no scheduling logic.

| Router | Prefix | Key Operations |
|--------|--------|---------------|
| projects | `/projects` | CRUD, reason claim/heartbeat/release, complete, reopen |
| intents | `/projects/{id}/intents` | Create, heartbeat, release, conclude |
| hints | `/projects/{id}/hints` | Create |
| export | `/projects/{id}/export` | YAML + timeline text export |
| settings | `/settings` | GET/PUT timeout config |

### server/services.py
Shared helpers used by all routers: `expire_workers()`, `expire_reason_leases()`, `get_project_or_404()`, `validate_facts_exist()`, ID generators (`next_project_id`, `next_fact_id`, etc.), `utcnow()`.

### dispatcher/config.py
Pydantic config model loaded from YAML. Validates worker env keys per type, prompt template existence, mock behavior probabilities. Supports `common_env` merged into all workers.

### dispatcher/contracts.py
Validates structured JSON output from LLM workers. Three validation paths: `validate_reason_payload`, `validate_bootstrap_execute_payload/conclude_payload`, `validate_explore_payload`. Returns outcome type + parsed data.

### dispatcher/scheduler/loop.py
**Core scheduling loop.** `DispatcherLoop.run()` cycles: list projects → initialize checkpoints → refresh runtime → cancel inactive → queue cleanups → dispatch available. Uses ThreadPoolExecutor for concurrent task execution. Tracks per-worker counts, unhealthy/rejected cooldowns, reason checkpoints.

### dispatcher/runtime/containers.py
Docker SDK wrapper. Creates per-project containers with mounted prompt templates, env vars from config, network mode from config. Handles cleanup on project completion/stopping.

### dispatcher/workers/adapters/
One adapter per worker type. Each implements: healthcheck, execute command, parse output. ClaudeCode uses `claude` CLI, Codex uses `codex` CLI, Pi uses Pi API, Mock uses probabilistic outcome selection.
