Watch
1
0
Fork
You've already forked souveraine
0

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.
This commit is contained in:
Fimeg 2026-06-19 10:17:06 -04:00
commit 3ff6ffaa7f
22 changed files with 2732 additions and 200 deletions

148
saf/architecture.md Normal file
View file

@ -0,0 +1,148 @@
# 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"
```