Watch
1
0
Fork
You've already forked souveraine
0
souveraine/saf/architecture.md
Fimeg 3ff6ffaa7f license: relicense AGPL-3.0; bring SAF docs online; keep CLAUDE.md + docs/ local
SAF (souveraine architecture files) is now the in-repo doc set. working notes
(CLAUDE.md, docs/) stay on disk, gitignored.
2026-06-19 10:17:56 -04:00

9.6 KiB

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:

#[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

# 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"