SAF (souveraine architecture files) is now the in-repo doc set. working notes (CLAUDE.md, docs/) stay on disk, gitignored.
148 lines
9.6 KiB
Markdown
148 lines
9.6 KiB
Markdown
# 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"
|
|
```
|