Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

chaotic_semantic_memory is a Rust crate for AI memory systems built on:

  • 10240-bit hyperdimensional vectors - Dense binary representations for semantic similarity
  • Chaotic echo-state reservoirs - Temporal sequence processing with emergent dynamics
  • libSQL persistence - Durable storage with SQLite compatibility

Why Chaotic Memory?

Traditional vector databases store static embeddings. Chaotic semantic memory adds:

  1. Temporal processing - Sequences are compressed into single hypervectors
  2. Emergent dynamics - Reservoir chaos enables associative recall
  3. Sub-symbolic reasoning - Hypervector operations are neuro-symbolic

Vector Options

This crate uses Hyperdimensional Computing (HDC) for fast lexical similarity. For semantic similarity (synonyms, paraphrases), you can:

  • External embeddings: Use sentence-transformers or similar, inject via inject_concept()
  • Turso native vectors: Add F32_BLOB tables to the same libSQL/Turso database this crate uses
  • Hybrid approach: HDC for lexical matching + Turso vector_top_k() for semantic search

See Text Encoding for details.

Features

  • Native Rust with WASM target support
  • SIMD-accelerated hypervector operations
  • Sparse reservoir matrices for memory efficiency
  • Async I/O with Tokio
  • Connection pooling for remote databases
  • Export/import for data migration

Quick Example

use chaotic_semantic_memory::prelude::*;

#[tokio::main]
async fn main() -> Result<()> {
    let framework = ChaoticSemanticFramework::builder()
        .without_persistence()
        .build()
        .await?;

    let concept = ConceptBuilder::new("cat".to_string()).build();
    framework.inject_concept("cat".to_string(), concept.vector.clone()).await?;

    let hits = framework.probe(concept.vector.clone(), 5).await?;
    println!("Found {} similar concepts", hits.len());
    Ok(())
}

Getting Started

Installation

Add to your Cargo.toml:

cargo add chaotic_semantic_memory

For WASM bindings:

[dependencies]
chaotic_semantic_memory = { version = "0.3", features = ["wasm"] }

Requirements

  • Rust 1.85+ (MSRV)
  • For WASM: wasm32-unknown-unknown target

Minimal Example

use chaotic_semantic_memory::prelude::*;

#[tokio::main]
async fn main() -> Result<()> {
    // Create in-memory framework
    let framework = ChaoticSemanticFramework::builder()
        .without_persistence()
        .build()
        .await?;

    // Inject concepts
    let cat = ConceptBuilder::new("cat".to_string()).build();
    let dog = ConceptBuilder::new("dog".to_string()).build();
    
    framework.inject_concept("cat".to_string(), cat.vector.clone()).await?;
    framework.inject_concept("dog".to_string(), dog.vector.clone()).await?;

    // Create association
    framework.associate("cat".to_string(), "dog".to_string(), 0.8).await?;

    // Query similar concepts
    let hits = framework.probe(cat.vector.clone(), 5).await?;
    for (id, similarity) in hits {
        println!("{}: {:.3}", id, similarity);
    }

    Ok(())
}

With Persistence

use chaotic_semantic_memory::prelude::*;

#[tokio::main]
async fn main() -> Result<()> {
    let framework = ChaoticSemanticFramework::builder()
        .with_local_db("csm_memory.db")
        .build()
        .await?;

    // Data persists across restarts
    framework.load_replace().await?;
    
    Ok(())
}

CLI Installation

The csm binary is included with default features:

cargo install chaotic_semantic_memory --features cli
csm --help

Architecture

Overview

┌─────────────────────────────────────────────────────────┐
│                    ChaoticSemanticFramework              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │  Singularity │  │  Reservoir  │  │   Persistence   │  │
│  │  (Concepts)  │  │  (Temporal) │  │    (libSQL)     │  │
│  └──────┬──────┘  └──────┬──────┘  └────────┬────────┘  │
│         │                │                   │          │
│  ┌──────┴────────────────┴───────────────────┴──────┐   │
│  │                    Hyperdim                       │   │
│  │              (HVec10240 Operations)               │   │
│  └───────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘

Core Modules

Hyperdim (hyperdim.rs)

10240-bit binary hypervectors with SIMD-accelerated operations:

  • HVec10240 - Dense binary vector type
  • bundle() - Superposition (XOR + majority)
  • bind() - Binding (XOR)
  • permute() - Cyclic shift
  • cosine_similarity() - Similarity measure

Reservoir (reservoir.rs)

Echo State Network with chaotic dynamics:

  • Sparse CSR matrix (fixed degree k=64)
  • Spectral radius constraint [0.9, 1.1]
  • step() - Process single input
  • to_hypervector() - Project state to HVec10240

Singularity (singularity.rs)

Concept storage and semantic search:

  • HashMap-based concept storage
  • Association graph (weighted edges)
  • Zero-copy query cache for similarity queries
  • Rayon-parallel similarity search

Framework (framework.rs)

High-level async orchestration:

  • Builder pattern configuration
  • Persistence integration
  • Batch operations
  • Export/import

Data Flow

Concept Injection

inject_concept(id, vector)
    → Singularity::inject(id, vector)
    → Persistence::save_concept(id, vector) [if enabled]

Semantic Query

probe(vector, top_k)
    → Singularity::find_similar(vector, top_k)
    → Returns Vec<(id, similarity)>

Temporal Processing

process_sequence(inputs)
    → Reservoir::reset()
    → Reservoir::step(input) for each input
    → Reservoir::to_hypervector()
    → Returns HVec10240

Constraints

ConstraintValueRationale
LOC per file≤500Maintainability
Spectral radius[0.9, 1.1]Edge of chaos
WASM threadingGatedBrowser compatibility
Mutation testingscripts/mutation_test.shPrevent regressions
Fuzz testingcargo +nightly fuzz run hvec_from_bytesPrevent regressions

Inertial Reservoir

The standard Echo State Network uses a first-order leaky integrator that attenuates past inputs quickly. The inertial reservoir adds a second-order momentum term that improves long-range temporal memory retention.

Why It Matters

The default reservoir update rule:

state[t] = (1-α)·state[t-1] + α·tanh(W·state[t-1] + W_in·input)

decays past inputs at rate α per step, limiting how far back the reservoir “remembers.” The inertial extension adds momentum from previous state changes:

state[t] = (1-α)·state[t-1] + α·tanh(W·state[t-1] + W_in·input) + β·(state[t-1] - state[t-2])

The β term carries forward the direction of recent state change, allowing the reservoir to retain temporal context over longer input sequences.

Based on: Zhao et al., “Inertial ESN”, Neurocomputing Apr 2026, doi:10.1016/j.neucom.2026.133675

The Beta Parameter

PropertyValue
Valid range[0.0, 0.5]
Default0.0 (no inertia)
Recommended0.1–0.2 for most use cases
  • β = 0.0 — Original reservoir behavior, fully backward-compatible.
  • β = 0.1–0.2 — Good default range; improves temporal retention without instability.
  • β > 0.3 — Aggressive momentum; may amplify noise in short-context workloads.
  • β > 0.5 — Rejected by with_beta() to prevent divergence.

Enabling Inertia

Use the with_beta() builder method on Reservoir:

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::reservoir::Reservoir;

let reservoir = Reservoir::new_seeded(768, 50_000, 42)?
    .with_beta(0.15)?;
}

Or via ChaoticReservoir by constructing the base reservoir first.

The spectral radius constraint still applies — with_beta() does not alter weight scaling.

Backward Compatibility

When beta = 0.0 (the default), the inertial term evaluates to zero and the reservoir behaves identically to the original first-order dynamics. No API changes are required for existing code.

Trade-offs

CostImpact
Memory+1 Vec<f32> (prev_state) — ~200 KB at default 50K reservoir size
ThroughputOne extra multiply-add per active node per step; <10% overhead in benchmarks
Complexity34 LOC in reservoir_inertial.rs; step loop adds 2 lines

The prev_state vector is allocated at construction time regardless of beta, keeping the hot path branch-free.

Tuning Guidance

  1. Start with β = 0.15 — a safe middle ground.
  2. Increase β if retrieval quality degrades on long documents or multi-turn conversations.
  3. Decrease β (or set to 0.0) if you observe amplified noise on very short inputs.
  4. Monitor via reservoir.metrics_snapshot() — step latency should remain within 10% of baseline.

Further Reading

API Reference

Prelude

Import common types:

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::prelude::*;
}

This exports:

  • HVec10240, ChaoticSemanticFramework, FrameworkBuilder
  • Concept, ConceptBuilder, MemoryError, Result

Core Types

HVec10240

10240-bit binary hypervector.

#![allow(unused)]
fn main() {
let v1 = HVec10240::random();
let v2 = HVec10240::random();

// Operations
let bundled = HVec10240::bundle(&[v1, v2])?;
let bound = v1.bind(&v2);
let permuted = v1.permute(128);

// Similarity
let sim = v1.cosine_similarity(&v2);
}

ChaoticSemanticFramework

Main orchestration type.

#![allow(unused)]
fn main() {
let framework = ChaoticSemanticFramework::builder()
    .with_reservoir_size(50_000)
    .with_chaos_strength(0.1)
    .with_local_db("csm_memory.db")
    .build()
    .await?;
}

Concept

Stored concept with vector and metadata.

#![allow(unused)]
fn main() {
let concept = ConceptBuilder::new("my-id".to_string())
    .with_vector(HVec10240::random())
    .with_metadata("key", "value")
    .build()?;
}

Async Operations

All framework operations are async:

#![allow(unused)]
fn main() {
// Single operations
framework.inject_concept(id, vector).await?;
framework.associate(from, to, strength).await?;
let hits = framework.probe(vector, 10).await?;

// Batch operations
framework.inject_concepts(&concepts).await?;
framework.associate_many(&edges).await?;
let results = framework.probe_batch(&vectors, 10).await?;
}

Error Handling

All fallible APIs return Result<T, MemoryError>:

#![allow(unused)]
fn main() {
match framework.probe(vector, 10).await {
    Ok(hits) => println!("Found {} hits", hits.len()),
    Err(MemoryError::NotFound { entity, id }) => eprintln!("{} not found: {}", entity, id),
    Err(e) => eprintln!("Error: {}", e),
}
}

Text Encoding

TextEncoder maps text to HVec10240 for direct use with concept injection and probing.

Why It Exists

  • Deterministic text-to-vector conversion for repeatable indexing/querying
  • No external model dependency
  • Works in native Rust and WASM builds

Basic Usage

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::encoder::TextEncoder;

let encoder = TextEncoder::new();
let vector = encoder.encode("rust async memory");
}

N-gram Encoding

N-grams improve local phrase sensitivity:

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::encoder::TextEncoder;

let encoder = TextEncoder::new();
let vector = encoder.encode_with_ngrams("chaotic semantic memory", 3);
}

Framework Convenience APIs

use chaotic_semantic_memory::prelude::*;

#[tokio::main]
async fn main() -> Result<()> {
    let framework = ChaoticSemanticFramework::builder()
        .without_persistence()
        .build()
        .await?;

    framework.inject_text("doc-1", "Rust uses ownership for memory safety").await?;
    let hits = framework.probe_text("memory safety in rust", 5).await?;
    assert!(!hits.is_empty());
    Ok(())
}

Semantic Similarity Alternative

TextEncoder produces vectors for lexical similarity (same tokens, same order). For semantic similarity (synonyms, paraphrases), you have two options:

Option 1: External Embedding Model

Use sentence-transformers or similar, then inject the resulting vector:

#![allow(unused)]
fn main() {
let embedding: HVec10240 = my_model.encode("an overview of echo-state networks");
framework.inject_concept("doc-2", embedding).await?;
}

Option 2: Turso Native Vectors

This crate uses libSQL (local SQLite or remote Turso) for persistence. You can add Turso’s native F32_BLOB vector tables alongside the crate’s HDC storage:

#![allow(unused)]
fn main() {
use libsql::Builder;

// Connect to the same database this crate uses
let db = Builder::new_local("csm_memory.db").build().await?;
let conn = db.connect()?;

conn.execute_batch("
    CREATE TABLE IF NOT EXISTS semantic_vectors (
        id TEXT PRIMARY KEY,
        embedding F32_BLOB(384)
    );
    CREATE INDEX IF NOT EXISTS semantic_idx ON semantic_vectors(
        libsql_vector_idx(embedding, 'metric=cosine')
    );
").await?;
}

Both HDC concepts and semantic vectors live in the same database. The crate manages concepts and associations tables, while you manage semantic_vectors for float-vector similarity search via vector_top_k().

Hashing Notes

  • Default hashing is FNV-1a for stable cross-platform behavior.
  • Switching hash algorithms changes produced vectors for the same text.
  • If you persist encoder-generated vectors, re-encoding policy should be part of migration planning.

Graph Traversal

Singularity stores weighted directed associations and exposes graph traversal APIs.

Available Traversals

  • neighbors(id, min_strength) for one-hop expansion
  • bfs(start, config) for bounded breadth-first traversal
  • shortest_path(from, to, config) for weighted Dijkstra traversal
  • shortest_path_hops(from, to, config) for hop-count pathing

Example

use chaotic_semantic_memory::graph_traversal::TraversalConfig;
use chaotic_semantic_memory::prelude::{ConceptBuilder, Result};
use chaotic_semantic_memory::singularity::Singularity;

fn main() -> Result<()> {
    let mut sing = Singularity::new();
    sing.inject(ConceptBuilder::new("a").build()?)?;
    sing.inject(ConceptBuilder::new("b").build()?)?;
    sing.inject(ConceptBuilder::new("c").build()?)?;
    sing.associate("a", "b", 0.9)?;
    sing.associate("b", "c", 0.8)?;

    let cfg = TraversalConfig::default();
    let bfs = sing.bfs("a", &cfg)?;
    let path = sing.shortest_path("a", "c", &cfg)?;
    assert!(!bfs.is_empty());
    assert!(path.is_some());
    Ok(())
}

Weighted Cost Model

shortest_path converts edge strengths to costs using -ln(strength).

  • Higher strength -> lower cost
  • strength <= 0.0 is treated as non-traversable
  • This preserves intuitive preference for stronger semantic links

WASM Support

WASM bindings expose:

  • neighbors(id, min_strength)
  • bfs(start)
  • shortest_path(from, to)

Semantic Bridge

SemanticBridge provides symbolic concept expansion on top of deterministic HDC recall, combining concept-graph traversal with vector similarity for hybrid retrieval.

Why It Exists

  • Expands queries through synonym and related-concept graphs without mutating stored vectors
  • Combines deterministic HDC scores with concept expansion scores for richer recall
  • Produces compressed MemoryPacket structs ready for LLM context injection
  • Optional semantic reranking layer that never modifies deterministic scores

Core Types

CanonicalConcept

Represents a semantic equivalence class (e.g., “agent memory” ≈ “cross-session context”):

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::semantic_bridge::CanonicalConcept;

let concept = CanonicalConcept::new("concept.agent_memory")
    .with_label("agent memory")
    .with_label("cross-session context")
    .with_related("concept.session_state");
}

ConceptGraph

In-memory graph of canonical concepts with case-insensitive label matching:

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::semantic_bridge::{CanonicalConcept, ConceptGraph};

let mut graph = ConceptGraph::new();

graph.add_concept(
    CanonicalConcept::new("concept.agent_memory")
        .with_label("agent memory")
        .with_label("ai memory")
        .with_related("concept.session"),
);
graph.add_concept(
    CanonicalConcept::new("concept.session")
        .with_label("session context")
        .with_label("cross-session state"),
);

// Case-insensitive token matching
let ids = graph.match_tokens(&["Agent-Memory".into()]);

// Expand through related concepts (depth=2)
let labels = graph.expand(&ids, 2);
}

The graph supports JSON serialization for persistence:

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::semantic_bridge::ConceptGraph;
let graph = ConceptGraph::new();
// Save
let file = std::fs::File::create("concepts.json").unwrap();
graph.save_to_json(file).unwrap();

// Load
let file = std::fs::File::open("concepts.json").unwrap();
let graph = ConceptGraph::load_from_json(file).unwrap();
}

BridgeConfig

Controls retrieval behavior and score weighting:

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::semantic_bridge::BridgeConfig;

let config = BridgeConfig {
    max_expansion_depth: 2,    // How deep to traverse related concepts
    max_packet_facts: 20,      // Max facts in a MemoryPacket
    token_budget: 1000,        // Token cap for packet compression
    deterministic_weight: 0.6, // HDC similarity weight
    concept_weight: 0.3,       // Concept expansion weight
    semantic_weight: 0.1,      // Reranker weight
};
}

Default weights sum to 1.0: deterministic (0.6), concept (0.3), semantic (0.1).

Query Pipeline

BridgeRetrieval orchestrates the full retrieval pipeline:

Query text
  │
  ├─► Tokenize & encode ──► HDC similarity (deterministic recall)
  │
  ├─► Token matching ──► Concept expansion ──► Encode expanded labels
  │                                               │
  │                                               └─► HDC similarity (expanded recall)
  │
  ├─► Merge results with ScoreBreakdown
  │
  ├─► Optional SemanticReranker
  │
  └─► Final weighted score ──► Top-K hits

Basic Query

use chaotic_semantic_memory::encoder::TextEncoder;
use chaotic_semantic_memory::semantic_bridge::{
    BridgeConfig, CanonicalConcept, ConceptGraph,
};
use chaotic_semantic_memory::bridge_retrieval::BridgeRetrieval;
use chaotic_semantic_memory::prelude::{ConceptBuilder, Result};
use chaotic_semantic_memory::singularity::Singularity;

fn main() -> Result<()> {
    let encoder = TextEncoder::new();

    // Build concept graph
    let mut graph = ConceptGraph::new();
    graph.add_concept(
        CanonicalConcept::new("concept.memory")
            .with_label("agent memory")
            .with_label("session context")
            .with_related("concept.persistence"),
    );
    graph.add_concept(
        CanonicalConcept::new("concept.persistence")
            .with_label("durable storage")
            .with_label("database"),
    );

    // Create retrieval pipeline
    let bridge = BridgeRetrieval::with_defaults(encoder.clone(), graph);

    // Populate singularity
    let mut singularity = Singularity::new();
    singularity.inject(
        ConceptBuilder::new("doc-1")
            .with_vector(encoder.encode("agent memory across sessions"))
            .build()?,
    )?;
    singularity.inject(
        ConceptBuilder::new("doc-2")
            .with_vector(encoder.encode("durable storage for AI state"))
            .build()?,
    )?;

    // Query: deterministic + concept-expanded recall
    let hits = bridge.query(&singularity, "session context", 5, None)?;
    for hit in &hits {
        println!("{}: {:.3} (det={:.3}, concept={:.3})",
            hit.id,
            hit.scores.final_score,
            hit.scores.deterministic,
            hit.scores.concept,
        );
    }
    Ok(())
}

Memory Packets

memory_packet() runs the query pipeline and compresses results into a token-budgeted packet for LLM context:

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::encoder::TextEncoder;
use chaotic_semantic_memory::semantic_bridge::ConceptGraph;
use chaotic_semantic_memory::bridge_retrieval::BridgeRetrieval;
use chaotic_semantic_memory::singularity::Singularity;
let encoder = TextEncoder::new();
let bridge = BridgeRetrieval::with_defaults(encoder, ConceptGraph::new());
let singularity = Singularity::new();
let packet = bridge.memory_packet(&singularity, "agent memory", 10, None).unwrap();

println!("Intent: {}", packet.query_intent);
println!("Facts: {:?}", packet.facts);
println!("Confidence: {:.2}", packet.confidence);
println!("Est. tokens: {}", packet.estimated_tokens());
}

Result Types

BridgeHit

Each hit carries a full ScoreBreakdown:

FieldDescription
idConcept ID in the singularity
text_previewOptional text snippet
scores.deterministicHDC cosine similarity score
scores.conceptConcept expansion match score
scores.semanticReranker score (0.0 if unused)
scores.final_scoreWeighted combination of all scores
scores.evidenceTrail of scoring sources (e.g., "deterministic_recall", "concept_expansion")

MemoryPacket

Compressed output for LLM context injection:

FieldDescription
query_intentOriginal query text
factsDeduplicated, token-budgeted fact strings
sourcesSource concept IDs
confidenceAverage final score across top hits

Supports to_json() and to_json_pretty() for serialization.

Custom Reranking

Implement SemanticReranker to plug in model-based or rule-based reranking:

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::semantic_bridge::{BridgeHit, SemanticReranker};

struct MyReranker;

impl SemanticReranker for MyReranker {
    fn version(&self) -> &str { "custom-v1" }

    fn rerank(&self, query: &str, hits: &mut [BridgeHit]) {
        for hit in hits {
            // Boost hits whose ID contains a query token
            let query_lower = query.to_lowercase();
            if hit.id.to_lowercase().contains(&query_lower) {
                hit.scores.semantic = 0.5;
            }
        }
    }
}
}

Pass it to query() or memory_packet():

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::bridge_retrieval::BridgeRetrieval;
use chaotic_semantic_memory::singularity::Singularity;
struct MyReranker;
impl chaotic_semantic_memory::semantic_bridge::SemanticReranker for MyReranker {
    fn version(&self) -> &str { "v1" }
    fn rerank(&self, _q: &str, _h: &mut [chaotic_semantic_memory::semantic_bridge::BridgeHit]) {}
}
let bridge = BridgeRetrieval::with_defaults(
    chaotic_semantic_memory::encoder::TextEncoder::new(),
    chaotic_semantic_memory::semantic_bridge::ConceptGraph::new(),
);
let singularity = Singularity::new();
let reranker = MyReranker;
let hits = bridge.query(&singularity, "agent memory", 5, Some(&reranker)).unwrap();
}

Score Weighting

Final scores are computed as:

final = deterministic_weight × deterministic
      + concept_weight      × concept
      + semantic_weight     × semantic

Tune via BridgeConfig to control the balance between exact HDC recall and concept expansion. Higher deterministic_weight favors precision; higher concept_weight favors broader semantic recall.

CLI Usage

The csm binary provides command-line access to the memory system.

Installation

cargo install chaotic_semantic_memory --features cli

Commands

inject

Inject a new concept:

# Random vector
csm inject my-concept --database csm_memory.db

# Vector from file
csm inject my-concept --from-file vector.bin --database memory.db

# Vector from stdin
echo "vector data" | csm inject my-concept --vector-source stdin --database memory.db

# With metadata
csm inject my-concept --metadata '{"key":"value"}' --database memory.db

probe

Find similar concepts:

# By concept ID
csm probe my-concept -k 10 --database csm_memory.db

# Output as JSON
csm probe my-concept -k 10 --output-format json --database memory.db

query

Text-based similarity search (encodes text and finds similar concepts):

# Hybrid search (keyword + semantic)
csm query "machine learning neural networks" -k 10 --database csm_memory.db

# Semantic-only HDC search
csm query "machine learning" --semantic-only -k 5 --database memory.db

# Keyword-only BM25 search
csm query "exact term match" --keyword-only -k 5 --database memory.db

# With minimum score threshold
csm query "AI concepts" -k 10 --min-score 0.5 --database memory.db

# Compact output (trim long text)
csm query "long document content" --compact -k 5 --database memory.db

# Code-aware encoding for source code
csm query "fn process_data" --code-aware -k 5 --database memory.db

index-dir

Index Markdown files from a directory into memory:

# Index all markdown files in a directory
csm index-dir -g "docs/**/*.md" --database csm_memory.db

# Index with multiple glob patterns
csm index-dir -g "src/**/*.md" -g "book/**/*.md" --database memory.db

# Index code files with code-aware encoding
csm index-dir -g "src/**/*.rs" --code-aware --database memory.db

# Control heading chunking level (default: 2 for ## sections)
csm index-dir -g "docs/**/*.md" --heading-level 3 --database memory.db

Important: index-dir requires --glob <PATTERN> (not a direct path). Concept IDs follow format: md:<path>:<heading_level>:<chunk_index>

index-jsonl

Index JSONL file content into memory:

# Index from JSONL file
csm index-jsonl data.jsonl --database csm_memory.db

# Each line must be valid JSON with 'id' and optional 'text'/'metadata' fields

associate

Create associations:

csm associate source target --strength 0.8 --database csm_memory.db

export

Export memory state:

# JSON format
csm export --output backup.json --database csm_memory.db

# Binary format (smaller)
csm export --output backup.bin --format binary --database csm_memory.db

import

Import memory state:

# Replace existing
csm import backup.json --database csm_memory.db

# Merge with existing
csm import backup.json --merge --database memory.db

completions

Generate shell completions:

# Bash
csm completions bash > ~/.local/share/bash-completion/completions/csm

# Zsh
csm completions zsh > ~/.zsh/completions/_csm

# Fish
csm completions fish > ~/.config/fish/completions/csm.fish

# PowerShell
csm completions powershell > $HOME\.config\powershell\completions\csm.ps1

Output Formats

FormatFlagDescription
Table--output-format tableHuman-readable table (default)
JSON--output-format jsonMachine-parseable JSON

Exit Codes

CodeMeaning
0Success
1Configuration error
2Database error
3Input error
4Output error
5Validation error
6Memory error
7I/O error
255Unknown error

WASM Bindings

Building

rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --no-default-features --features wasm

Using wasm-pack:

wasm-pack build --target web --no-default-features --features wasm

JavaScript API

import init, { WasmFramework } from 'chaotic_semantic_memory';

await init();

// Create framework
const framework = new WasmFramework();

// Inject concept
const vector = WasmFramework.random_vector();
await framework.inject_concept('my-concept', vector);

// Query similar
const hits = await framework.probe(vector, 10);
console.log(hits); // [{id: 'my-concept', score: 1.0}]

// Create association
await framework.associate('cat', 'dog', 0.8);

// Process sequence
const sequence = [
    new Float32Array([0.1, 0.2, ...]),
    new Float32Array([0.3, 0.4, ...])
];
const resultVector = await framework.process_sequence(sequence);

// Export/Import
const exported = await framework.export_to_bytes();
await framework.import_from_bytes(exported);

TypeScript Types

interface Concept {
    id: string;
    vector: Uint8Array;
    metadata?: string;
}

interface SimilarityHit {
    id: string;
    score: number;
}

declare class WasmFramework {
    inject_concept(id: string, vector: Uint8Array): Promise<void>;
    get_concept(id: string): Promise<Concept | null>;
    delete_concept(id: string): Promise<void>;
    probe(vector: Uint8Array, topK: number): Promise<SimilarityHit[]>;
    associate(from: string, to: string, strength: number): Promise<void>;
    get_associations(id: string): Promise<SimilarityHit[]>;
    disassociate(from: string, to: string): Promise<void>;
    update_concept(id: string, vector: Uint8Array): Promise<void>;
    process_sequence(inputs: Float32Array[]): Promise<Uint8Array>;
    export_to_bytes(): Promise<Uint8Array>;
    import_from_bytes(data: Uint8Array): Promise<number>;
    neighbors(id: string, minStrength: number): Promise<string[]>;
    bfs(start: string): Promise<string[]>;
    shortest_path(from: string, to: string): Promise<string[] | null>;
}

declare class WasmFramework {
    static random_vector(): Uint8Array;
    static bundle(vectors: Uint8Array[]): Uint8Array;
    static bind(a: Uint8Array, b: Uint8Array): Uint8Array;
    static cosine_similarity(a: Uint8Array, b: Uint8Array): number;
}

Limitations

  • No persistence - libSQL persistence is bypassed/unavailable on wasm32-unknown-unknown and threading guards dictate compilation.
  • No threading - Rayon parallelization is gated
  • Memory only - All data is in-memory for browser context

NPM Package

npm install @d-o-hub/chaotic_semantic_memory

Or use directly with npx:

npx @d-o-hub/chaotic_semantic_memory

Configuration

Framework Builder

#![allow(unused)]
fn main() {
let framework = ChaoticSemanticFramework::builder()
    // Reservoir settings
    .with_reservoir_size(50_000)
    .with_reservoir_input_size(10_240)
    .with_chaos_strength(0.1)
    
    // Persistence settings
    .with_local_db("csm_memory.db")
    .with_connection_pool_size(10)
    
    // Memory limits
    .with_max_concepts(1_000_000)
    .with_max_associations_per_concept(100)
    .with_max_metadata_bytes(4096)
    
    // Cache settings
    .with_concept_cache_size(1_000)
    .with_max_cached_top_k(100)
    
    // Query limits
    .with_max_probe_top_k(10_000)
    
    .build()
    .await?;
}

Parameters

ParameterDefaultRangeDescription
reservoir_size50,000>0Reservoir node count
reservoir_input_size10,240>0Input dimension
chaos_strength0.10.0-1.0Noise amplitude
connection_pool_size10≥1Remote DB pool
max_conceptsNone>0Evict oldest when reached
max_associations_per_conceptNone>0Keep strongest only
max_metadata_bytesNone>0Metadata size limit
concept_cache_size128≥1LRU cache capacity
max_cached_top_k100≥1Bypass cache above this
max_probe_top_k10,000≥1Query guard limit

Persistence Options

No Persistence

#![allow(unused)]
fn main() {
.without_persistence()
}

In-memory only, no database.

Local SQLite

#![allow(unused)]
fn main() {
.with_local_db("csm_memory.db")
}

Local SQLite file.

Remote Turso

#![allow(unused)]
fn main() {
.with_turso("libsql://...", auth_token)
}

Remote Turso/LibSQL database with authentication.

Concept TTL

Concepts can be given a time-to-live (TTL) so they automatically expire. Expired concepts are filtered from probe results and can be bulk-purged from memory.

Why It Exists

  • Ephemeral context (chat turns, session data) should not persist forever
  • Avoids unbounded memory growth without manual cleanup
  • Expired concepts are still stored until explicitly purged, keeping deletion costs amortised

Setting TTL on a Concept

With ConceptBuilder

#![allow(unused)]
fn main() {
use chaotic_semantic_memory::singularity::ConceptBuilder;
use chaotic_semantic_memory::HVec10240;

let concept = ConceptBuilder::new("session-ctx-42")
    .with_vector(HVec10240::random())
    .with_ttl(3600) // expires in 1 hour
    .build()
    .unwrap();

assert!(concept.expires_at.is_some());
}

If with_ttl is omitted the concept never expires (expires_at is None).

Framework Convenience APIs

use chaotic_semantic_memory::prelude::*;

#[tokio::main]
async fn main() -> Result<()> {
    let framework = ChaoticSemanticFramework::builder()
        .without_persistence()
        .build()
        .await?;

    // Inject a raw vector with TTL
    framework
        .inject_concept_with_ttl("vec-1", HVec10240::random(), 600)
        .await?;

    // Inject text with TTL (encodes via TextEncoder)
    framework
        .inject_text_with_ttl("note-1", "meeting notes from standup", 1800)
        .await?;

    Ok(())
}

How Expiry Works

A concept is considered expired when expires_at <= now (UNIX seconds). The Singularity layer exposes helpers to inspect and act on expiry:

MethodDescription
is_expired(id)Check whether a single concept has expired
active_concept_ids()List all concept IDs that are still alive
purge_expired()Delete all expired concepts and invalidate the similarity cache

Purging Expired Concepts

use chaotic_semantic_memory::prelude::*;

#[tokio::main]
async fn main() -> Result<()> {
    let framework = ChaoticSemanticFramework::builder()
        .without_persistence()
        .build()
        .await?;

    // ... inject concepts with TTL ...

    let removed = framework.purge_expired().await?;
    println!("Purged {removed} expired concepts");
    Ok(())
}

purge_expired iterates stored concepts, collects those past their deadline, deletes them, and invalidates the similarity cache so subsequent probes reflect the new state.

Behaviour Notes

  • Probe filtering — expired concepts are automatically excluded during probe operations so stale results are never returned.
  • Lazy deletion — expiry does not remove data in the background. Call purge_expired on a schedule (e.g., after each request batch) to reclaim memory.
  • Persistence — when persistence is enabled, inject_concept_with_ttl and inject_text_with_ttl save the concept (including its expires_at timestamp) to the database. Purging only removes concepts from the in-memory Singularity; see Configuration for persistence details.

Performance

Benchmarks

Run benchmarks:

cargo bench --bench benchmark -- --save-baseline main
cargo bench --bench benchmark -- --baseline main

Targets

MetricTargetActual
reservoir_step_50k<100μs~76μs
turso_roundtrip<20msPassing
10m_concepts_memory<12MBPassing
wasm_binary_size<500KB~438KB

Tuning Guide

Small Workloads (<10k concepts)

#![allow(unused)]
fn main() {
let framework = ChaoticSemanticFramework::builder()
    .without_persistence()
    .with_reservoir_size(10_240)
    .with_concept_cache_size(128)
    .build()
    .await?;
}

Medium Workloads (10k-1M concepts)

#![allow(unused)]
fn main() {
let framework = ChaoticSemanticFramework::builder()
    .with_local_db("csm_memory.db")
    .with_max_concepts(1_000_000)
    .with_concept_cache_size(1_000)
    .build()
    .await?;
}

Large Workloads (>1M concepts)

#![allow(unused)]
fn main() {
let framework = ChaoticSemanticFramework::builder()
    .with_remote_db(turso_url, auth_token)
    .with_connection_pool_size(20)
    .with_max_concepts(10_000_000)
    .with_max_probe_top_k(1_000)
    .with_concept_cache_size(10_000)
    .build()
    .await?;
}

Memory Footprint

ComponentsPer-Unit1M Concepts
Concept ID~32 bytes32 MB
HVec102401,280 bytes1.28 GB
Associations~24 bytes/edgeVaries

Tips:

  • Set max_concepts to enforce memory ceiling
  • Use max_associations_per_concept to limit edges
  • Cache hit rate improves with concept_cache_size

Optimization Techniques

SIMD Hypervector Operations

Automatic via std::simd on x86-64:

#![allow(unused)]
fn main() {
// These use SIMD when available
HVec10240::bundle(&vectors);
HVec10240::cosine_similarity(&a, &b);
}

Automatic via Rayon:

#![allow(unused)]
fn main() {
// Uses all cores for similarity computation
framework.probe(vector, 100).await?;
}

Batch Operations

Prefer batch over individual:

#![allow(unused)]
fn main() {
// Slower: N round trips
for (id, vec) in concepts {
    framework.inject_concept(id, vec).await?;
}

// Faster: 1 round trip
framework.inject_concepts(&concepts).await?;
}

Connection Pooling

For remote databases:

#![allow(unused)]
fn main() {
.with_connection_pool_size(20) // More connections for concurrent access
}

Release Engineering

Overview

Releases are automated via scripts/release-manager.sh with GitHub Actions for publishing. The system uses:

  • Structured logging with JSON output for CI debugging
  • Exit-code validation (no fragile grep patterns)
  • Rollback automation for failed releases
  • Version sync across Cargo.toml and wasm/package.json

Release Manager

# Validate all gates (tests, clippy, fmt, LOC, dry-run)
scripts/release-manager.sh validate

# Prepare release (version bump, changelog, sync)
scripts/release-manager.sh prepare 0.2.0

# Publish (creates git tag, pushes - triggers GitHub release via CI)
scripts/release-manager.sh publish 0.2.0

# Full pipeline (validate + prepare + publish)
scripts/release-manager.sh full 0.2.0

# CI mode (non-interactive)
scripts/release-manager.sh full 0.2.0 --yes --log release.log

# Dry run (simulate without side effects)
scripts/release-manager.sh full 0.2.0 --dry-run

Validation Gates

The validate command checks:

GateMethod
Clean workspacegit diff --quiet
Correct branchMust be main
Compilationcargo check --all-targets --all-features
Formattingcargo fmt --check
Lintingcargo clippy -- -D warnings
Testscargo test --all-features
Documentationcargo doc --no-deps
Publish dry-runcargo publish --dry-run
LOC limitsAll src/*.rs ≤ 500 lines
WASM targetcargo check --target wasm32-unknown-unknown
Security auditcargo audit (if installed)

Documentation Sync

The prepare command automatically updates version references across all documentation:

FileUpdates
Cargo.tomlversion = "X.Y.Z"
wasm/package.json"version": "X.Y.Z"
Cargo.lockRegenerated via cargo check
README.mdStatus table + install examples
SECURITY.mdSupported versions table
book/src/getting-started.mdInstall examples
wasm/README.mdnpm install examples
llms.txt, llms-full.txtRegenerated via scripts/gen-llms-txt.sh
CHANGELOG.md[Unreleased] → [X.Y.Z]
AGENTS.mdVersion references (if present)

CI Workflows

Release (release.yml)

Triggered by git tag push (v*):

  1. validate — Extract version from git tag, match Cargo.toml, dry-run publish
  2. build-artifacts — Build release binary + WASM, create tarballs
  3. publish-cratescargo publish to crates.io
  4. create-github-release — Upload artifacts, extract changelog notes
  5. notify — Report success or failure with per-job status table
  6. update-rolling-tags — Update major/minor tags (v1, v1.2)

npm Publish (npm-publish.yml)

Triggered by tag push (v*):

  • Builds WASM package via wasm-pack
  • Publishes @d-o-hub/chaotic_semantic_memory to npm
  • Includes npm provenance (--provenance)

GitHub Pages (pages.yml)

Triggered by push to main (book/ changes):

  • Builds mdBook documentation
  • Generates API docs via cargo doc
  • Deploys to GitHub Pages

Commit Conventions

TypeVersion BumpExample
featMinorfeat(cli): add export command
fixPatchfix(reservoir): correct spectral radius
perfPatchperf(hyperdim): optimize bundle
feat!:Majorfeat!: redesign API
docs, chore, test, ciNo release

Rollback

If a release has issues:

# Automated rollback (deletes tag + GitHub release)
scripts/release-manager.sh rollback 0.2.0

# If already published to crates.io, yank manually:
cargo yank --version 0.2.0 chaotic_semantic_memory

Security

  • No long-lived API tokens — Uses CARGO_REGISTRY_TOKEN secret scoped to environment
  • Concurrency control — Release workflow uses cancel-in-progress: false
  • Minimal permissions — Only contents: write + id-token: write
  • Branch protectionmain branch requires PR with passing CI
  • Provenance — npm packages include build provenance attestation
  • Auditcargo audit runs as part of validation (when installed)

Architecture Decision Records

  • ADR-0039 — Release engineering strategy
  • ADR-0042 — Release automation and v0.1.0 readiness