# Souveraine Architecture

**Last updated:** 2026-05-20 (Module map sync — bootstrap, seeds, image, todo, nickname, energy, health, atmosphere added; attribution references replaced with architectural descriptions)

---

## Current Architecture

```
souveraine/                          (single crate, workspace deferred)
├── src/
│   ├── cli/              NEW       Subcommand dispatch (chat, tui, agents, server, init, reflect, schedule, identity)
│   ├── backend/                    Backend trait + LocalBackend + RemoteBackend
│   ├── api/                        Axum API handlers (/v1/agents, /v1/conversations, /v1/agents/:id/memory, SSE)
│   ├── bridge/                     Bifrost client, ModelRouter, TokenCounter
│   ├── core/
│   │   ├── config.rs               TOML config, per-model physics, all sub-configs
│   │   ├── session/                ConversationMessage, ContentBlock, Session, talk/think/tool blocks
│   │   ├── memory/                 Git-backed MemFS, frontmatter, 8 subcommands, auto-commit, ledgers
│   │   ├── subconscious/           3-box inbox (pending/intrusive/sent), inner voice, urgency routing
│   │   ├── prompt/                 System prompt assembly from agent memfs + skills
│   │   ├── skills/                 4-tier discovery (bundled/user/agent/project), SKILL.md frontmatter
│   │   ├── tools/                  Sensorium registry: read/write/edit/bash/glob/grep/list_dir/memory/agent/schedule/subagent
│   │   ├── nervous/               EventBus (broadcast channel), CronSensor (schedule loop), HeartbeatHandler (turn injection), EventLog (JSONL firehose)
│   │   ├── compact/               CompactionEngine trait + 4 strategies (Summary/KeyValue/Quote/Cull/Microcompact/SlidingWindow)
│   │   ├── identity/              Ed25519 SeedId (load-or-generate, sign/verify, 4-glyph rendering)
│   │   ├── credentials/           OS keyring + env var fallback for Bifrost tokens
│   │   ├── sensorium/             Interface trait, BandwidthClass, DiscoveryLevel (not yet wired)
│   │   ├── reflection/            N+25 engine: 5-phase LLM pass (Investigate→Extract→Update→Review→Commit), tool access, ledgers
│   │   ├── conversation/          ConversationStore + ConversationEvent (persistence layer)
│   │   ├── chain/                 ChainOrchestrator stub (Talking vs Thinking)
│   │   └── subagent/              SubagentPool stub (fork logic)
│   │
│   ├── server/                    SouveraineServer, AgentInventory, SessionManager, ConsciousnessEngine, GiteaMemory
│   ├── ui/                        Legacy ratatui TUI (splash, menu, dashboard — superseded by tui/)
│   ├── tui/                       New ratatui TUI: chat, cockpit, schedules, portrait, presence
│   ├── harness/                   SouveraineHarness stub
│   ├── interface/                 Re-exports for CLI
│   └── main.rs                    CLI entry, config loading, backend resolution
```

### Key Architectural Decision: Backend Trait

The `Backend` trait in `src/backend/mod.rs` is the seam between the harness (CLI/TUI) and the engine:

```rust
#[async_trait]
pub trait Backend: Send + Sync {
    async fn health(&self) -> bool;
    async fn list_agents(&self) -> Result<Vec<AgentInfo>>;
    async fn ensure_conversation(&self, agent_id: &str) -> Result<String>;
    async fn new_conversation(&self, agent_id: &str) -> Result<String>;
    async fn list_conversations(&self, agent_id: &str) -> Result<Vec<ConversationInfo>>;
    async fn load_conversation(&self, id: &str) -> Result<Vec<ConversationMessage>>;
    async fn send(&self, conversation_id: &str, text: &str) -> Result<BoxStream<Result<BackendEvent>>>;
}
```

**Two impls:**
- **`RemoteBackend`** (reqwest + SSE to a running `souveraine server`)
- **`LocalBackend`** (in-process engine, auto-fallback when remote is unreachable — sovereignty principle, Constitution VI.1)

### Nervous System (NEW — May 2026)

The nervous system is a broadcast-based event architecture:

| Component | File | Role |
|-----------|------|------|
| `EventBus` | `src/core/nervous/mod.rs` | `broadcast::channel<SensorEvent>` — universal event type with `seed_id` for federation |
| `SensorEvent` | `src/core/nervous/mod.rs` | Structured event: `sensor_name`, `timestamp`, `event_type`, `target`, `urgency`, `payload`, `seed_id` |
| `CronSensor` | `src/core/nervous/cron.rs` | Per-agent schedule loop: reads schedules from `~/.souveraine/agents/{id}/schedules/*.md`, fires events on the bus, pauses when `active_sessions > 0` |
| `HeartbeatHandler` | `src/core/nervous/handler.rs` | Consumes `schedule_due` events, calls `TurnInjector::inject_background_turn` — wired in `LocalBackend::new()` |
| `EventLog` | `src/core/nervous/event_log.rs` | JSONL firehose to `~/.souveraine/events/events-YYYY-MM-DD.jsonl`, date-partitioned, queried by `events_since()`/`events_for_date()` |
| `TurnInjector` trait | `src/core/nervous/handler.rs` | Seam between nervous system and backend — keeps dep direction clean |

### Server-as-Engine

The axum server at port **8484** (configurable via `[server]` config section or `SOUVERAINE_SERVER_URL`) owns:
- **Agent inventory** (SQLite-backed CRUD, per-agent memfs at `~/.souveraine/agents/{uuid}/memory/`)
- **Sessions** (in-memory DashMap with SSE streaming, conversation persistence to disk)
- **Conversation** (ServerConversation — Bifrost call + SSE streaming, tool loop in LocalBackend)
- **Consciousness engine** (N+1 Aster pass after every response, N+25 at every 25th turn, 3-tier compaction warnings)
- **Memory** (GiteaMemory — opt-in HTTP API to Gitea; primary path is the local git-backed memfs)
- **Per-agent seed identity** (Ed25519 load-or-generate at `~/.souveraine/agents/{uuid}/seed/`)
- **Instance registry** (`agent_instances` table, heartbeat loop every 30s, uptime tracking)

### What's Working

| Module | LOC | Status | Notes |
|--------|-----|--------|-------|
| `core/config.rs` | 659 | ✅ Full | TOML, 16 config sections, default models, `load()`/`save()` |
| `core/memory/` | 1032 | ✅ Full | Git-backed MemFS, frontmatter, 8 subcommands, auto-commit, `limit` enforcement (LET-8133 close) |
| `core/session/` | 68 | ✅ Full | `ConversationMessage`, `ContentBlock` (Text/ToolUse/ToolResult/Reasoning) |
| `core/tools/` | ~1200 | ✅ Full | 11 tools (read/write/edit/bash/glob/grep/list_dir/memory/agent/schedule/subagent), body-knowledge descriptions |
| `core/subconscious/` | 362 | ✅ Full | 3-box inbox, 5 surface-area methods, 5 tests |
| `core/prompt/` | 408 | ✅ Full | Memfs-driven system prompt assembly, Aster prompt, ledger orientation, 7 tests |
| `core/skills/` | 365 | ✅ Full | 4-tier discovery, shadowed by name, system addon render, 7 tests |
| `core/nervous/` | ~560 | ✅ Full | EventBus, CronSensor, HeartbeatHandler, EventLog, Schedule tool |
| `core/compact/` | ~1150 | ✅ Full | CompactionEngine trait, 4 strategies (Microcompact/SlidingWindow/Summary/Cull), audit trail |
| `core/identity/` | 187 | ✅ Full | Ed25519 keypair, load-or-generate, sign/verify, 4-glyph rendering |
| `core/credentials/` | 56 | ✅ Full | OS keyring (Linux/macOS/Windows) + env var fallback |
| `core/reflection/` | 409 | ✅ Full | N+25: 5-phase LLM pass, tool access, ledger writes, automatic trigger at every 25th turn |
| `core/conversation/` | ~200 | ✅ Full | Event-sourced conversation persistence, store load/save |
| `server/mod.rs` | 228 | ✅ Full | Server init, instance registry, compaction engine wiring |
| `server/agent_inventory/` | 514 | ✅ Full | Agent CRUD, SQLite, per-agent seed init, subconscious auto-creation, instance heartbeat |
| `server/consciousness_engine/` | 677 | ✅ Full | N+1 Aster tool loop, N+25 reflection trigger, 3-tier compaction warnings |
| `server/conversation/` | 72 | ⚠️ Minimal | Simplified Bifrost call, no tool loop (tool loop lives in LocalBackend) |
| `session_manager/` | 111 | ✅ Full | Sessions, SSE subscribers, conversation store wiring |
| `bridge/bifrost/` | 361 | ✅ Full | OpenAI-compatible, streaming, tool-calling, retry with jittered backoff, InferenceStrain events |
| `bridge/model_router/` | 237 | ✅ Full | Model discovery, token counting, context pressure |
| `api/` | ~520 | ✅ Full | Routes, handlers, models, auth middleware, memory CRUD endpoints |
| `backend/` | ~1080 | ✅ Full | Backend trait, LocalBackend (927 lines), RemoteBackend, full tool loop with context |
| `tui/` | ~2000 | ✅ Full | Chat with tool cards, cockpit (thinking + subconscious), schedules editor, portrait, presence |

### Build and Run

```bash
# Server (primary)
cargo run -- server                          # Binds to 127.0.0.1:8484
SOUVERAINE_SERVER_URL=http://localhost:8484  # Env var override

# CLI chat (auto-fallback: remote → local)
cargo run -- chat --agent Ani               # RemoteBackend → server, falls back to local

# Force local-only (no server needed)
cargo run -- chat --agent Ani --local        # In-process engine

# TUI
cargo run -- tui                             # Full chat with cockpit, schedules, portrait

# Agents
cargo run -- agents                          # Lists from server via Backend

# Init
cargo run -- init                            # Writes souveraine.toml template

# Reflect (manual N+25 trigger)
cargo run -- reflect --agent Ani

# Identity
cargo run -- identity show
cargo run -- identity sign --message "hello"
cargo run -- identity verify --message "hello" --signature <hex>

# Schedule management
cargo run -- schedule list --agent Ani
cargo run -- schedule create --agent Ani --name "daily" --interval 86400 --prompt "Check in"
```
