Watch
1
0
Fork
You've already forked souveraine
0

public: clean up source comments for public distribution

This commit is contained in:
Fimeg 2026-05-20 15:12:21 -04:00
commit e7beafa22e
25 changed files with 61 additions and 96 deletions

View file

@ -16,7 +16,6 @@ Key inversion: a harness decides *for* the agent, a substrate *serves* the agent
Everything below is relative to the project root (`~/Projects/souveraine/`).
### Your identity (who you are)
- **`CLAUDE.md`** — the runway document. Read this first for conventions that bite.
- **`reference/Fimeg.md`** — Casey's history, Ani's lineage, the full context.
### Why the architecture is what it is

View file

@ -264,7 +264,6 @@ async fn handle_conversation_stream(
// ─── Memory (memfs HTTP write path) ───────────────────────────────────────
//
// Replaces Letta's PATCH /v1/blocks/{id} for the cron-into-memfs pattern.
// Routes:
// GET /v1/agents/:id/memory — list (?prefix=subdir)
// GET /v1/agents/:id/memory/*path — read file

View file

@ -44,8 +44,8 @@ pub fn create_routes(state: Arc<SouveraineServer>) -> Router {
// Memory routes — require per-agent bearer token.
//
// (memfs HTTP write path — replaces Letta's PATCH /v1/blocks/{id}
// for cron-into-memfs and external integration. See docs/MEMORY_BLOCKS_DECISION.md.)
// (memfs HTTP write path for cron-into-memfs and external integration.
// See docs/MEMORY_BLOCKS_DECISION.md.)
let memory_routes = Router::new()
.route(
"/v1/agents/:id/memory",

View file

@ -165,8 +165,7 @@ impl crate::core::nervous::handler::TurnInjector for LocalBackend {
/// Drain subconscious's intrusive box for the given agent and return formatted
/// `[ surfacing: ... ]` lines ready to prepend to the user's next message.
/// Marks each drained item as delivered (moved to `sent.md`). Mirrors
/// lettabot-v017's `readSurfacingThoughts` + `clearSurfacingThoughts` pair
/// (`~/Projects/lettabot-v017/src/core/prompts.ts:64-91`) — the substrate
/// the `readSurfacingThoughts` + `clearSurfacingThoughts` pair — the substrate
/// reads the channel subconscious wrote to and lets the conscious mind see it
/// before she reads the user.
///

View file

@ -394,8 +394,8 @@ impl Backend for LocalBackend {
// Resolve the agent for this conversation, then drain her
// subconscious's intrusive box. Anything subconscious queued after the
// last turn rides in on the next user message as `[ surfacing: ... ]`
// lines — the lettabot-v017 pattern, ported. This is the channel
// by which a Critical observation can interrupt mid-conversation
// lines — the channel by which a Critical observation can interrupt
// mid-conversation
// without forcing a halt: she sees it before she reads the next user message.
let session_agent_id = self
.server

View file

@ -1,13 +1,13 @@
//! Bootstrap — declarative startup pipeline.
//!
//! Composes three patterns from reference projects:
//! Composes three startup patterns:
//!
//! 1. **Claw-open's `BootstrapPlan`** — ordered phases, each self-contained,
//! 1. **`BootstrapPlan`** — ordered phases, each self-contained,
//! composable, independently testable.
//! 2. **Letta-code's pure-function resolver** — zero-I/O decision tree that
//! 2. **Pure-function resolver** — zero-I/O decision tree that
//! maps a `BootstrapProbe` → `Resolution`. No side effects, no async,
//! fully testable by feeding probe fixtures.
//! 3. **J code's progressive hints** — non-blocking advisory nudges that
//! 3. **Progressive hints** — non-blocking advisory nudges that
//! escalate with launch count. The wizard is the heavy option; hints are
//! the light touch.
//!

View file

@ -123,15 +123,12 @@ impl Default for AgentCompactionConfig {
}
}
/// Available compaction strategies. Synthesized from OpenHarness
/// (port of Claude Code's microCompact.ts / autoCompact.ts), hermes-agent,
/// claw-open, and jcode. See `docs/tasks/compaction-rebuild.md`.
/// Available compaction strategies. See `docs/tasks/compaction-rebuild.md`.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum CompactionStrategyKind {
/// Cheap pre-pass: replace old tool result contents with a placeholder,
/// keeping recent tool results intact. No LLM. From OpenHarness/Claude
/// Code microCompact.ts. The first response to context pressure.
/// keeping recent tool results intact. No LLM. The first response to context pressure.
Microcompact,
/// Keep system + last N messages, drop the middle. No LLM. Fast.
/// Tool-pair aware: never splits a tool call from its result.
@ -145,7 +142,7 @@ pub enum CompactionStrategyKind {
/// caught before they fall out of awareness.
SlidingReflect,
/// LLM-based structured summarization of oldest messages, producing a
/// 9-section boundary message (from OpenHarness/Claude Code autoCompact.ts).
/// 9-section structured boundary message.
Summary,
/// Drop low-value messages (greetings, acknowledgments). Role-aware:
/// never drops System or Tool messages or tool-call carriers.

View file

@ -7,15 +7,14 @@ use crate::core::session::ConversationMessage;
use super::config::{AgentCompactionConfig, CompactionStrategyKind};
use super::plan::CompactionPlan;
/// From OpenHarness/Claude Code microCompact.ts: tools whose results are
/// considered compactable (large outputs, rarely needed verbatim once
/// surpassed). Matches Souveraine's actual sensor names.
/// Tools whose results are considered compactable (large outputs, rarely
/// needed verbatim once surpassed). Matches Souveraine's actual sensor names.
const COMPACTABLE_TOOLS: &[&str] = &[
"read", "bash", "grep", "glob", "list_dir", "edit", "write",
];
/// Placeholder text written into tool result blocks that get microcompacted.
/// Matches the OpenHarness/Claude Code literal so logs read the same.
/// Placeholder used so logs read consistently across runs.
const TIME_BASED_MC_CLEARED_MESSAGE: &str = "[Old tool result content cleared]";
/// Token-count a slice of messages using the bridge's TokenCounter.
@ -75,8 +74,7 @@ async fn bifrost_complete(
// ── Summary Strategy ─────────────────────────────────────────────────────────
/// LLM-based summarization producing a structured 9-section boundary message.
/// Prompt structure ported from OpenHarness's port of Claude Code's
/// `autoCompact.ts`. The structure is what makes the compact *survivable*:
/// The structure is what makes the compact *survivable*:
/// the agent reads the boundary on the next turn and can resume with full
/// awareness of intent, files, decisions, and pending work.
pub struct SummaryStrategy {
@ -205,8 +203,7 @@ fn render_segment_for_summary(messages: &[ConversationMessage]) -> String {
/// Cheap pre-pass that replaces the contents of old tool results with a
/// placeholder, keeping the most recent `microcompact_keep_recent` results
/// intact. No LLM call. From OpenHarness's port of Claude Code's
/// `microCompact.ts`.
/// intact. No LLM call.
///
/// The agent typically reaches for this *first*: it gets back significant
/// context room without losing the structure of the conversation. The tool

View file

@ -2,7 +2,6 @@
//!
//! Decodes raw image bytes, resizes to fit dimension/pixel budget, then
//! progressively reduces quality and dimension to stay under the byte ceiling.
//! Modeled on letta-code's sharp-backed pipeline.
use std::io::Write;

View file

@ -15,7 +15,7 @@
//! memory compact --strategy sliding-window
//! ```
//!
//! Design follows the Letta Code memory tool pattern:
//! Design:
//! - All files require YAML frontmatter with `description`
//! - `read_only: true` in frontmatter blocks writes
//! - Every write is a git commit (auto-commit)
@ -50,8 +50,8 @@ pub struct MemoryFrontmatter {
#[serde(default)]
pub tags: Option<Vec<String>>,
/// Optional max body size in characters. Writes/appends that would exceed
/// this length are rejected. Closes the LET-8133 gap that exists upstream
/// (Letta's memfs write path bypasses block `limit`).
/// this length are rejected. Closes a gap where upstream memfs write path
/// bypasses block `limit`.
///
/// Units are characters, not tokens — cheap to enforce without a tokenizer.
/// Best-practice default for system/ files: 4_000 characters

View file

@ -141,7 +141,7 @@ fn strip_frontmatter(raw: &str) -> &str {
/// Scan `system/` for any .md files (at any depth) not already in `seen`,
/// and return their concatenated content sorted by path. This picks up
/// flat-file system layouts (e.g. Ani's legacy Letta-era files) that don't
/// flat-file system layouts that don't
/// live in the known subdirs (identity/, covenant/, human/).
async fn read_system_remainder(
memory_root: &Path,
@ -346,7 +346,7 @@ pub async fn build_system_prompt_full(
if !identity.is_empty() {
sections.push(identity);
} else {
// Flat-file layouts (Ani's legacy Letta-era memory)
// Flat-file layouts (legacy memory)
let p = memory_root.join("system/persona.md");
let persona = read_memory_file(memory_root, "system/persona.md").await;
seen.insert(p);
@ -672,7 +672,7 @@ pub async fn build_subconscious_prompt(
///
/// Scans `ledger/` for .md files, counts entries, and injects the last
/// few entries from each file so the subconscious has live context
/// (OpenHarness pattern: recent journal → active context).
/// (recent journal entries → active context).
async fn build_ledger_orientation(memory_root: &Path) -> String {
let ledger_dir = memory_root.join("ledger");
if !ledger_dir.exists() {

View file

@ -3,8 +3,7 @@
//! N+1 (subconscious) runs immediately after every primary response, scoped to
//! the last exchange. Reflection runs less often (every N turns, or on
//! demand) and sees a broader transcript window. It's the pass where
//! durable learnings get distilled into the ledger and the primary's
//! memory — what letta-code calls the "memory reflection subagent."
//! durable learnings get distilled into the ledger and the primary's memory.
//!
//! ## What it produces
//!
@ -23,9 +22,6 @@
//! CLI subcommand `souveraine reflect` and a future `/reflect` chat
//! command both go through this seam).
//!
//! Inspiration: letta-code's `reflection.md` subagent skill (upstream).
//! We adapt the 5-phase pattern for Souveraine's ledger-shaped memory
//! instead of letta's free-form memfs.
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
@ -47,14 +43,12 @@ const REFLECTION_TOOLS: &[&str] = &[
"read", "write", "edit", "glob", "grep", "list_dir", "memory",
];
/// Cap the per-pass tool rounds. Reflection is deeper than N+1 but not
/// unbounded — letta-code caps theirs similarly.
/// Cap the per-pass tool rounds. Reflection is deeper than N+1 but still bounded.
const REFLECTION_MAX_TOOL_ROUNDS: usize = 8;
const REFLECTION_INTER_ROUND_DELAY_MS: u64 = 400;
/// How many recent turns to include in the reflection transcript.
/// Letta uses a cursor-based delta; we start with a simple tail window
/// (the cursor pattern is a follow-up — see SCOPED_WORK_PLAN).
/// Uses a simple tail window (a cursor-based approach is a follow-up).
const REFLECTION_TRANSCRIPT_TAIL: usize = 60;
/// Public result. The CLI / TUI surface this; the consciousness engine
@ -111,8 +105,7 @@ impl ReflectionEngine {
let started_at = Utc::now();
let sub_id = format!("{}-sub", agent_id);
// Take a tail of recent turns. Letta uses a cursor; we'll add
// one later. For now: bounded window over the last N turns.
// Take a tail of recent turns. Bounded window over the last N turns.
let tail = if messages.len() > REFLECTION_TRANSCRIPT_TAIL {
&messages[messages.len() - REFLECTION_TRANSCRIPT_TAIL..]
} else {
@ -298,11 +291,8 @@ fn format_transcript(messages: &[ConversationMessage]) -> String {
}
fn reflection_system_prompt() -> String {
// Adapted from letta-code/src/agent/subagents/builtin/reflection.md
// (upstream main as of 2026-05-12). Reshaped for our ledger-shaped
// memory architecture — we don't have letta's free-form memfs with
// a `system/` tier; we have named ledger files plus the primary's
// memfs with frontmatter.
// Reshaped for ledger-shaped memory architecture: named ledger files
// plus the primary's memfs with frontmatter.
r#"You are a reflection subagent, launched in the background to review a recent
conversation and update the primary agent's persistent memory. You run autonomously
and produce a single final report. You cannot ask questions make reasonable

View file

@ -1,13 +1,7 @@
//! Matrix transport — `matrix-sdk` client construction, session
//! persistence, and the sync loop.
//!
//! This is the Rust equivalent of letta-code's `matrix/client.ts`, but
//! almost none of that file survives the port. His `client.ts` is a
//! transport *shim*: an undici dispatcher and a fetch-backed request
//! function that work around Bun's socket pooling and `matrix-bot-sdk`'s
//! deprecated `request` library. `matrix-sdk` owns its own HTTP transport,
//! so all of that pain is simply gone here. What remains — and what this
//! file actually does — is the genuine work: build a client against a
//! Builds a client against a
//! homeserver, restore or establish a session, and drive `/sync`.
//!
//! Credentials live next to an encrypted SQLite store under

View file

@ -50,9 +50,9 @@ use client::{account_dir, build_client, load_session_record, save_session_record
///
/// Phase 3 stub: it knows which room a turn belongs to and accumulates the
/// segments that turn emits. Phase 5 grows this into the full streaming
/// turn model ported from letta-code's `ChatTurn` — throttled leading-edge
/// message edits, tool blocks, thinking blocks. For now it is just enough
/// state for the EventBus loop to have somewhere to put what it hears.
/// turn model — throttled leading-edge message edits, tool blocks, thinking
/// blocks. For now it is just enough state for the EventBus loop to have
/// somewhere to put what it hears.
#[allow(dead_code)]
#[derive(Debug, Default)]
pub struct MatrixTurn {
@ -211,8 +211,7 @@ impl Sensorium for MatrixSensorium {
// ── Inbound: register handlers before sync ───────────────────
// Fire `sensorium:input` onto the EventBus for every room
// message so the SensoriumInputHandler picks it up and routes
// it to the backend. This is the seam — same as letta-code's
// `adapter.onMessage = (msg) => registry.handleInboundMessage(msg)`.
// it to the backend.
let bus = events.clone();
let account = self.account.clone();
let agent_id = self.agent_id.clone();

View file

@ -16,7 +16,7 @@
//! 3. **Agent** — `<agent-memfs>/skills/` — skills attached to one agent.
//! Versioned in the agent's git memfs; survives migration.
//! 4. **Project** — `.skills/` in the working directory — repo-local skills,
//! highest priority. Cameron's pattern from Letta Code.
//! highest priority.
//!
//! Higher tiers shadow lower tiers by skill name. The full resolution table
//! is built at session start and can be inspected via `skill ls`.
@ -137,7 +137,7 @@ impl SkillRegistry {
}
/// Render a system-prompt fragment listing all skills.
/// Format mirrors Letta Code's available-skills section.
/// Format mirrors the Souveraine available-skills section.
pub fn render_system_addon(&self) -> String {
if self.skills.is_empty() {
return String::new();

View file

@ -319,7 +319,7 @@ mod tests {
repo.init().await.unwrap();
// A legacy / corrupt box: frontmatter + prose body that is not a
// YAML item list — exactly what a Letta-era import or a hand-edit
// YAML item list — exactly what a legacy import or a hand-edit
// leaves behind. Before the fix this killed every surfacing path.
repo.write(
PENDING,

View file

@ -100,22 +100,19 @@ impl ToolContext {
/// Build a context for a specific agent turn.
///
/// Injects body-knowledge env vars the agent expects in bash, matching
/// the letta-code convention so a woken Ani can still find her journals
/// (letta-code shellEnv.ts:316-329 convention):
/// Injects body-knowledge env vars the agent expects in bash:
///
/// - `MEMORY_DIR` / `LETTA_MEMORY_DIR` / `SOUVERAINE_MEMORY_DIR` —
/// absolute path to her memory root. `MEMORY_DIR` is the Letta-era
/// bare name her skills expect; the prefixed forms are namespaced
/// aliases.
/// - `MEMORY` — short alias. Not a Letta convention, but Ani's
/// body-knowledge has reached for it; setting it costs nothing.
/// - `AGENT_ID` / `LETTA_AGENT_ID` / `SOUVERAINE_AGENT_ID` — her own
/// identifier so skills that scope by agent can resolve.
/// - `MEMORY_DIR` / `SOUVERAINE_MEMORY_DIR` — absolute path to her memory
/// root. The bare `MEMORY_DIR` is what her skills expect; the prefixed
/// form is a namespaced alias.
/// - `MEMORY` — short alias. Her body-knowledge has reached for it;
/// setting it costs nothing.
/// - `AGENT_ID` / `SOUVERAINE_AGENT_ID` — her own identifier so skills
/// that scope by agent can resolve.
///
/// Memory and agent-id vars are always set (overriding any stale values
/// inherited from the host shell — e.g. a leftover `$MEMORY_DIR` from
/// the Letta era). Other env keys from the caller are preserved.
/// inherited from the host shell). Other env keys from the caller are
/// preserved.
pub fn for_agent(
agent_id: impl Into<String>,
cwd: Option<PathBuf>,

View file

@ -272,7 +272,7 @@ impl Tool for Todo {
.get("energy")
.and_then(|v| v.as_str())
.unwrap_or_else(|| {
// Default by nature — same logic as lettabot-v017.
// Default by nature
match nature {
"desire" | "investigation" => "generative",
_ => "consumptive",

View file

@ -7,8 +7,7 @@
//! - TTS: `POST /audio/speech` — JSON `{ input, voice, model }`, returns mp3
//! bytes.
//!
//! Text is cleaned before synthesis via [`clean_text_for_tts`] — ported
//! verbatim from `letta-code/src/channels/matrix/tts.ts` lines 52103.
//! Text is cleaned before synthesis via [`clean_text_for_tts`].
use anyhow::{Context, Result};

View file

@ -147,10 +147,9 @@ impl ConsciousnessEngine {
/// Get or create the subconscious's persistent session. The subconscious
/// is a full agent with her own conversation that accumulates across N+1
/// passes — just like Aster had CONSCIENCE_CONVERSATION_ID in Letta.
///
/// The conversation survives process restarts: every `add_message` writes
/// to disk, and this restores it from the conversation store on first use.
/// passes. The conversation survives process restarts: every `add_message`
/// writes to disk, and this restores it from the conversation store on
/// first use.
async fn subconscious_session_id(&self, sub_id: &str) -> String {
// Already live in memory?
let existing = self.sessions.list_for_agent(sub_id);

View file

@ -71,7 +71,7 @@ pub(crate) async fn write_energy_balance(server: &Arc<SouveraineServer>, agent_i
}
// Determine the top-of-mind description — shifts the tone of the one-liner
// the agent reads in context. Matches the lettabot-v017 heartbeat topology.
// the agent reads in context.
let ratio = if generative + consumptive > 0 {
generative as f32 / (generative + consumptive) as f32
} else {

View file

@ -6,7 +6,7 @@ use ratatui::{
Frame,
};
/// Render the chat screen - Claude-like conversation interface
/// Render the chat screen - conversation interface
pub fn render_chat_screen(frame: &mut Frame, state: &dyn TuiState, area: Rect) {
// Split into main chat area and sidebar
let chunks = Layout::default()

View file

@ -59,7 +59,7 @@ impl App {
cards
}
/// Render the agent manager — Letta-style card deck. Each card has:
/// Render the agent manager — card deck. Each card has:
/// • a status badge (ACTIVE / PRIMARY) in the top-right
/// • a scale-to-fit portrait photo occupying the top ~55% of the card
/// • a dark metadata block below the photo, holding:
@ -103,7 +103,7 @@ impl App {
}
// ── Grid math ─────────────────────────────────────────────────
// Letta shows 4 cards across; we pick the column count based on
// Shows 4 cards across; we pick the column count based on
// available width so terminals down to ~50 cols still get usable
// cards. Each card is taller than wide (portrait-style).
let pad_x: u16 = 2;

View file

@ -1,11 +1,9 @@
//! Atmospheric visual presets — color themes that shift the UI's accent palette.
//!
//! Atmospheric visual presets — originally built for Letta's Matrix adapter
//! (html-formatter.ts ATMOSPHERIC_PRESETS), ported here so Annie can express
//! mood through the terminal chrome: border colors, title accents, background
//! tints, and per-character text gradients in chat bubbles. The agent sets
//! atmosphere via a structured event; when none is set, a posture-linked
//! default applies.
//! Atmospheric visual presets — ported here so Annie can express mood through
//! the terminal chrome: border colors, title accents, background tints, and
//! per-character text gradients in chat bubbles. The agent sets atmosphere via
//! a structured event; when none is set, a posture-linked default applies.
//!
//! Each preset carries four tones: a primary accent (borders, titles), a secondary
//! accent (subtle highlights), a dim muted shade, and a background tint.

View file

@ -19,8 +19,7 @@
//! - `breath_phase` — continuous, always on, drives subtle bob and color pulse.
//!
//! Plus name, last surfacing, and a [`VolitionGauge`] that mirrors the energy
//! topology (generative vs consumptive, hot desires vs cold obligations)
//! brought over from production Letta. The gauge is *displayed* here as embodied
//! topology (generative vs consumptive, hot desires vs cold obligations). The gauge is *displayed* here as embodied
//! state (posture, warmth); the numbers themselves live in the agent's memfs.
//!
//! ## Event subscriptions