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:
- Temporal processing - Sequences are compressed into single hypervectors
- Emergent dynamics - Reservoir chaos enables associative recall
- 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-transformersor similar, inject viainject_concept() - Turso native vectors: Add
F32_BLOBtables 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-unknowntarget
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 typebundle()- Superposition (XOR + majority)bind()- Binding (XOR)permute()- Cyclic shiftcosine_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 inputto_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
| Constraint | Value | Rationale |
|---|---|---|
| LOC per file | ≤500 | Maintainability |
| Spectral radius | [0.9, 1.1] | Edge of chaos |
| WASM threading | Gated | Browser compatibility |
| Mutation testing | scripts/mutation_test.sh | Prevent regressions |
| Fuzz testing | cargo +nightly fuzz run hvec_from_bytes | Prevent 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
| Property | Value |
|---|---|
| Valid range | [0.0, 0.5] |
| Default | 0.0 (no inertia) |
| Recommended | 0.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
| Cost | Impact |
|---|---|
| Memory | +1 Vec<f32> (prev_state) — ~200 KB at default 50K reservoir size |
| Throughput | One extra multiply-add per active node per step; <10% overhead in benchmarks |
| Complexity | 34 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
- Start with β = 0.15 — a safe middle ground.
- Increase β if retrieval quality degrades on long documents or multi-turn conversations.
- Decrease β (or set to 0.0) if you observe amplified noise on very short inputs.
- Monitor via
reservoir.metrics_snapshot()— step latency should remain within 10% of baseline.
Further Reading
- ADR-0064: Inertial Reservoir Dynamics
- Architecture — overall system design
- Performance — benchmarking methodology
API Reference
Prelude
Import common types:
#![allow(unused)]
fn main() {
use chaotic_semantic_memory::prelude::*;
}
This exports:
HVec10240,ChaoticSemanticFramework,FrameworkBuilderConcept,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 expansionbfs(start, config)for bounded breadth-first traversalshortest_path(from, to, config)for weighted Dijkstra traversalshortest_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.0is 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
MemoryPacketstructs 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:
| Field | Description |
|---|---|
id | Concept ID in the singularity |
text_preview | Optional text snippet |
scores.deterministic | HDC cosine similarity score |
scores.concept | Concept expansion match score |
scores.semantic | Reranker score (0.0 if unused) |
scores.final_score | Weighted combination of all scores |
scores.evidence | Trail of scoring sources (e.g., "deterministic_recall", "concept_expansion") |
MemoryPacket
Compressed output for LLM context injection:
| Field | Description |
|---|---|
query_intent | Original query text |
facts | Deduplicated, token-budgeted fact strings |
sources | Source concept IDs |
confidence | Average 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
| Format | Flag | Description |
|---|---|---|
| Table | --output-format table | Human-readable table (default) |
| JSON | --output-format json | Machine-parseable JSON |
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Configuration error |
| 2 | Database error |
| 3 | Input error |
| 4 | Output error |
| 5 | Validation error |
| 6 | Memory error |
| 7 | I/O error |
| 255 | Unknown 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 -
libSQLpersistence is bypassed/unavailable onwasm32-unknown-unknownand 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
| Parameter | Default | Range | Description |
|---|---|---|---|
reservoir_size | 50,000 | >0 | Reservoir node count |
reservoir_input_size | 10,240 | >0 | Input dimension |
chaos_strength | 0.1 | 0.0-1.0 | Noise amplitude |
connection_pool_size | 10 | ≥1 | Remote DB pool |
max_concepts | None | >0 | Evict oldest when reached |
max_associations_per_concept | None | >0 | Keep strongest only |
max_metadata_bytes | None | >0 | Metadata size limit |
concept_cache_size | 128 | ≥1 | LRU cache capacity |
max_cached_top_k | 100 | ≥1 | Bypass cache above this |
max_probe_top_k | 10,000 | ≥1 | Query 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:
| Method | Description |
|---|---|
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_expiredon a schedule (e.g., after each request batch) to reclaim memory. - Persistence — when persistence is enabled,
inject_concept_with_ttlandinject_text_with_ttlsave the concept (including itsexpires_attimestamp) to the database. Purging only removes concepts from the in-memorySingularity; see Configuration for persistence details.
Performance
Benchmarks
Run benchmarks:
cargo bench --bench benchmark -- --save-baseline main
cargo bench --bench benchmark -- --baseline main
Targets
| Metric | Target | Actual |
|---|---|---|
reservoir_step_50k | <100μs | ~76μs |
turso_roundtrip | <20ms | Passing |
10m_concepts_memory | <12MB | Passing |
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
| Components | Per-Unit | 1M Concepts |
|---|---|---|
| Concept ID | ~32 bytes | 32 MB |
| HVec10240 | 1,280 bytes | 1.28 GB |
| Associations | ~24 bytes/edge | Varies |
Tips:
- Set
max_conceptsto enforce memory ceiling - Use
max_associations_per_conceptto 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);
}
Parallel Similarity Search
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:
| Gate | Method |
|---|---|
| Clean workspace | git diff --quiet |
| Correct branch | Must be main |
| Compilation | cargo check --all-targets --all-features |
| Formatting | cargo fmt --check |
| Linting | cargo clippy -- -D warnings |
| Tests | cargo test --all-features |
| Documentation | cargo doc --no-deps |
| Publish dry-run | cargo publish --dry-run |
| LOC limits | All src/*.rs ≤ 500 lines |
| WASM target | cargo check --target wasm32-unknown-unknown |
| Security audit | cargo audit (if installed) |
Documentation Sync
The prepare command automatically updates version references across all documentation:
| File | Updates |
|---|---|
Cargo.toml | version = "X.Y.Z" |
wasm/package.json | "version": "X.Y.Z" |
Cargo.lock | Regenerated via cargo check |
README.md | Status table + install examples |
SECURITY.md | Supported versions table |
book/src/getting-started.md | Install examples |
wasm/README.md | npm install examples |
llms.txt, llms-full.txt | Regenerated via scripts/gen-llms-txt.sh |
CHANGELOG.md | [Unreleased] → [X.Y.Z] |
AGENTS.md | Version references (if present) |
CI Workflows
Release (release.yml)
Triggered by git tag push (v*):
- validate — Extract version from git tag, match Cargo.toml, dry-run publish
- build-artifacts — Build release binary + WASM, create tarballs
- publish-crates —
cargo publishto crates.io - create-github-release — Upload artifacts, extract changelog notes
- notify — Report success or failure with per-job status table
- 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_memoryto 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
| Type | Version Bump | Example |
|---|---|---|
feat | Minor | feat(cli): add export command |
fix | Patch | fix(reservoir): correct spectral radius |
perf | Patch | perf(hyperdim): optimize bundle |
feat!: | Major | feat!: redesign API |
docs, chore, test, ci | No 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 protection —
mainbranch requires PR with passing CI - Provenance — npm packages include build provenance attestation
- Audit —
cargo auditruns as part of validation (when installed)