# Cairn — Architecture

## Overview

Cairn is a general-purpose problem-solving engine using a **Blackboard Architecture** with an explicit fact-intent graph. AI penetration testing is the first validated domain. The system searches for a path through an unknown state space from `origin` to `goal`.

**Core primitives:**

| Concept | Meaning |
|---------|---------|
| **Fact** | Confirmed, objective finding written to the board |
| **Intent** | Declared direction of exploration, not yet executed |
| **Hint** | Human judgment injected at any time; absorbed by agents on next read |

## Layer Model

```
┌──────────────────────────────────┐
│         Cairn Server (FastAPI)   │  Graph consistency only
│      Facts + Intents + Hints     │  SQLite WAL backend
└─────────────────┬────────────────┘
                  │ HTTP API
┌─────────────────┴────────────────┐
│          Dispatcher              │  Schedules tasks, manages containers
│   Scheduler + ContainerManager   │  Sole writer to protocol log
└──────────┬───────────────┬───────┘
           │               │
┌──────────┴──┐     ┌──────┴──────────┐
│ Worker Ctn  │     │ Worker Ctn      │
│ (Project A) │     │ (Project B)     │
│ ┌────┐┌────┐│     │ ┌────┐┌────┐    │
│ │ W. ││ W. ││     │ │ W. ││ W. │    │
│ └────┘└────┘│     │ └────┘└────┘    │
└─────────────┘     └─────────────────┘
```

| Layer | Responsibility | Key Module |
|-------|---------------|------------|
| **Server** | Graph CRUD, lease expiry, export | `cairn/server/` — FastAPI + SQLite |
| **Dispatcher** | Task scheduling, worker selection, container lifecycle | `cairn/dispatcher/scheduler/loop.py` |
| **Workers** | Execute OODA loop, return structured JSON | `cairn/dispatcher/workers/adapters/` |

## Data Flow

```
1. User creates Project(origin, goal)
2. Dispatcher detects new project → dispatches Bootstrap task
3. Worker receives prompt with origin+goal → returns Fact + Complete or new Intents
4. If Intents returned → Dispatcher dispatches Explore tasks
5. Explorer claims Intent → executes exploration → returns new Fact
6. Dispatcher dispatches Reason task to evaluate graph
7. Reason reads full graph → decides: Complete / new Intents / no-op
8. Cycle repeats until goal reached (Complete) or graph exhausted
```

**Coordination: Stigmergy** — agents never communicate directly. All coordination through the shared graph. Worker reads graph state, decides next action, writes result back.

## Task Types

| Task | Trigger | Input | Output |
|------|---------|-------|--------|
| **Bootstrap** | New project with only origin+goal | origin, goal, hints | Fact + possible Complete |
| **Reason** | Graph changed (new facts/hints, all intents resolved) | Full graph YAML | Complete / new Intents / no-op |
| **Explore** | Unclaimed Intent exists | Graph YAML + intent | One Fact (via conclude) |

## Key Design Decisions

| Decision | Rationale |
|----------|-----------|
| SQLite single-writer | Graph consistency via serial writes; no distributed transactions |
| Lease-based claiming | Heartbeat mechanism prevents stale workers from blocking intents |
| Pydantic models everywhere | Input validation + structured output parsing in one layer |
| Dispatcher owns containers | Clean lifecycle: create → use → cleanup on project status change |
| Prompt templates as resources | Prompt group validation at config load; swap prompts without code changes |
| Mock worker for testing | Probabilistic outcomes configurable via env vars; no live LLM needed |

## Entry Points

| Entry | File | Purpose |
|-------|------|---------|
| CLI | `cairn/src/cairn/cli.py` | `cairn serve` / `cairn dispatch` |
| Server app | `cairn/src/cairn/server/app.py` | FastAPI lifespan, router registration |
| Dispatcher loop | `cairn/src/cairn/dispatcher/scheduler/loop.py` | Main scheduling loop |
| Worker adapters | `cairn/src/cairn/dispatcher/workers/adapters/` | ClaudeCode, Codex, Pi, Mock |
