A pure Rust organic memory substrate — sparse associative codes, write-ahead log, multi-writer, sub-millisecond recall. No external database. No NFS locks.
chitta-field is the sole storage substrate for cc-soul. It was designed to eliminate NFS file handle issues and D-state hangs on shared filesystems. It is a pure Rust library compiled to libchitta_field.a, statically linked into the C++ daemon. Zero external processes. Zero network sockets. Zero OS file handles on startup beyond the WAL segments.
Sparse field activation — each pulse encodes one memory as 64 / 16,384 features
Each memory is encoded as a sparse code: exactly 64 of 16,384 feature dimensions activate. The rest are zero. This is the same principle behind sparse distributed representations in biological cortex — high capacity, collision-resistant, and inherently associative.
Sparse codes are derived from the dense 768-dim BGE embedding by projecting through a learned sparse encoder. The result: two memories about the same concept share many active features. Two unrelated memories share almost none.
This makes retrieval geometric: find memories whose active features overlap most with the query's active features. No distance function. No HNSW graph traversal. Just intersection and counting.
SSL NL gloss: SSL-encoded memories (compact triplet form) are passed through gloss_ssl_content() — a translation layer in chitta/include/chitta/ssl_gloss.hpp that converts triplets into readable English sentences before embedding. This closes the representation gap between compact SSL storage and natural-language BGE queries, so structured memories surface from prose questions.
Alias memories: every new SSL memory auto-creates a linked kind=alias NL counterpart, connected by an alias-of triplet. NL and SSL representations stay synchronised without content duplication: the alias carries the glossed sentence, the SSL row carries the canonical triplet.
The posting index enables sub-millisecond recall without HNSW or any graph traversal. Each feature maintains a sorted list; recall intersects k lists and scores by hit count.
Every state change is an Op — a typed, serializable operation. Ops are appended to a segment file before they are applied in-memory. On restart, the daemon replays all segments in order and the field rebuilds in milliseconds from the WAL alone. No snapshots. No checkpoints. Just the log.
Durability: the write buffer is flushed to the OS after every append. An Op that returned a seqno is guaranteed to survive a crash.
Integrity: each entry carries a CRC32 over [seqno][op_type][payload]. On replay, a mismatch aborts with a CrcMismatch error rather than silently accepting corrupted state.
Segment rotation: segments rotate at 256 MB. Segment filenames encode instance ID and first seqno: {instance_id:08x}_{first_seqno:012}.seg. This makes ordering unambiguous across multiple writers.
Dense semantic search is handled by HNSW graphs and binary codes stored in flat binary sidecars alongside the snapshot. This separates fast-path ANN data from the main bincode payload, shrinking checkpoint I/O and opening the door to mmap-based loading at 1M-memory scale.
| Sidecar | Format | Size at 1M | Purpose |
|---|---|---|---|
.emb | magic(8) + count(8) + {id:u64, f32×256}×N | ~1 GB | Raw dense embeddings for ANN + rescore |
.bin | magic(8) + count(8) + {id:u64, u64×4}×N | ~40 MB | Binary sparse codes for Hamming pre-filter |
.hnsw | bincode-serialized HnswGraph | ~200 MB | Base HNSW graph (up to HNSW_TIER2_THRESHOLD) |
.delta.hnsw | bincode-serialized HnswGraph | <20 MB | Delta tier — new inserts above 100K, merged at checkpoint |
Below 100 K memories, all inserts go to the single base graph. Above that threshold (HNSW_TIER2_THRESHOLD), new inserts route to a small delta graph — O(log Ndelta) insert cost instead of O(log Ntotal). At checkpoint, when the delta exceeds 10% of base size (HNSW_DELTA_MERGE_RATIO), it is merged back into the base. Search queries both tiers and merges results via reciprocal rank fusion.
Every memory's embedding is binarized (sign bit per dimension) into 4 × u64 words. A Hamming scan over the full .bin sidecar selects the top 400 candidates; only those candidates are rescored with full float cosine. At 54K memories this is a 0.74% scan — strong recall at minimal CPU cost.
The recall path uses an inverted index over sparse feature activations — the same structure as a text search engine's posting list, applied to neural feature dimensions instead of words. This is why recall is sub-millisecond with no HNSW graph.
Why it's fast: each of the 64 query features maps to a pre-sorted posting list. Intersecting 64 small lists is O(k·log n) in the worst case, but in practice the lists are small because each feature is shared by only a fraction of all memories (sparsity guarantees this).
Associativity: two memories about the same topic will share many active features. When you recall one, the other lights up because it appears repeatedly in the posting lists being scanned. This is associative retrieval — not a similarity metric, but emergent from the index structure.
Hybrid recall: the posting index handles semantic overlap. A BM25 keyword index handles exact term matches. Both scores are fused in the resonance pipeline's early phases.
Multiple Claude Code windows can write to the same chitta-field simultaneously. Each daemon instance gets a unique 32-bit instance ID and writes exclusively to its own segment files. There is no shared write lock. No WAL contention. Readers replay all segments sorted alphabetically — the interleaving is always deterministic.
This model is called Upanishads-style concurrency: one source, many windows onto it. Each writer is authoritative for its own segment range; no writer can corrupt another's data. Readers see a merged view by replaying all segment files in order.
On startup, OpLog::open() scans the segments directory, finds the last segment for this instance ID, and continues appending there. If the last segment is at or above 256 MB, a new segment is created.
The manifest tracks the maximum seqno seen per instance, so a new instance knows where to start its own sequence without colliding with others.
Memories do not live forever. They decay through a demotion tier system driven by access recency and frequency. The daemon's subconscious thread runs demotion periodically — memories that are not accessed slide down the tiers and eventually become dormant. Frequent access promotes a memory back toward tier 0.
Demotion is logged as a DemoteMemory Op, so it survives restarts. A memory that was cold before a restart is still cold after replay. The tier is part of the persisted state, not recomputed on load.
The StateDelta Op handles strength and confidence adjustments separately — the ResonanceLearner applies Bayesian updates via UpdateState ops, which are also WAL-logged before application.
Four mechanisms shipped in v5.21.55–59 that turn chitta-field from a write-once store into a self-correcting one: write-gate admission, symbol-event correlation, introspection, and cross-harness disagreement detection.
All new memories start staged=true and are promoted to staged=false on first recall (access_count ≥ 1). Staged memories score 0.80× in the retrieval pipeline — they still surface when no promoted memory wins, but are ranked lower. Stale staged memories (age > 7 days, never recalled) are auto-pruned. A background pass runs every 50 embed cycles via promote_staged_memories(). The write_gate_stats MCP tool reports staged_count and oldest_staged_age_days.
A WAL-backed SymbolEventLog organ records typed events keyed on symbol identity: Edited, Created, Deleted, TestFailed, TestPassed, Committed. Each event carries symbol_name, file_path, session_id, harness, and an optional memory_id link. Indexed by symbol name and file path for O(1) lookup; fully rebuilt from WAL on restart (not stored in the full snapshot). upsert_symbol() auto-logs an Edited event on every symbol write. invalidated_by: Option<String> on MemoryState records the commit hash or symbol-change ID that made a memory stale — set via mark_memory_invalidated.
what_do_i_know_aboutA single MCP call that answers "what does this session believe about X, and how trustworthy is each claim?" For each recalled hit: staged flag, invalidated_by, source_session, source_tool, age_days (from memory_claim_info); a staleness verdict that checks invalidated_by then walks artifact refs against the live symbol index; contradiction peers from get_conflicts. Returns claims[], cross_harness_conflicts[], topic, total.
harness: Option<String> is inferred from source_tool on every put_memory() call ("codex" if the tool name starts with codex, "claude-code" otherwise). The cross_harness_conflicts tool scans all live non-staged memories, groups by HNSW proximity, and returns pairs where harnesses differ — ranked by 1 − cosine_similarity as the disagreement score. Wired into what_do_i_know_about as a per-cluster filter. Snapshot V13 (0xF011_5741_7E00_000D) adds LegacyMemoryPayloadV12 migration covering all V1–V12 snapshots on disk.
Memory representations self-organize according to the Free Energy Principle (Spisak & Friston, Neurocomputing 2026). The encoder, prototype index, and association graph jointly minimize prediction error while controlling model complexity.
The FEP-derived learning rule replaces pure Hebbian updates. Each atom update includes a complexity penalty (λ=10-4) that pushes unused weights toward zero, plus Gram-Schmidt decorrelation (1% per step) between co-active atoms. Over time, memory representations naturally become orthogonal — maximizing mutual information and resisting catastrophic forgetting.
Prototype transitions and triplet weights encode directionality. When memories are co-retrieved, the forward direction (A→B) receives full coupling strength; the reverse (B→A) is attenuated to 0.3×. Sequential data produces non-equilibrium steady-state dynamics — the same asymmetry Spisak & Friston show generalizes Boltzmann Machines.
Partial cues converge to stored attractor basins. attractor_settle() iteratively blends query sparse codes with prototype centroids and follows directed transitions (3-5 steps). Pattern completion emerges naturally — a noisy query settles into the nearest stable memory representation.
Reconstruction error (how poorly the encoder predicts a memory) serves as a surprise signal. High-surprise memories resist decay — they carry unique information. Low-surprise memories fade faster — they are redundant with existing knowledge. This balances accuracy and complexity, the core FEP tradeoff.
An asymmetric energy-based network over memory co-activations. settle() propagates activation through multi-hop directed couplings with dynamic neighbor discovery. Seeds are clamped; connected memories activate via sigmoid gating. The result: given a few seed memories, the network completes the pattern.
Deduplication uses a principled accuracy-vs-complexity tradeoff instead of a fixed cosine threshold. Two memories merge when the complexity saving of eliminating one outweighs the prediction accuracy lost by combining their representations. Fmerge = loss + λ · complexity < 0.
The natural first instinct for agent memory is a MEMORY.md file. It works at a few hundred entries. Then it stops working — for reasons that are architectural, not incidental.
A markdown file must be read in full to be searched. At 10,000+ memories the context window is the binding constraint — you cannot afford to inject everything. chitta-field selects the 5–15 most relevant memories from 24,000+ in under a millisecond using hybrid recall: semantic ANN + BM25 + cortical SDR bitset intersection + graph spreading activation.
A flat file is ordered by insertion time. chitta-field scores each candidate on 18 composable factors — semantic similarity, ACT-R base-level activation, memory strength, confidence, epistemic status, affect valence, surprise boost, mood congruence, frustration escalation, prediction boost, integration kernel weight, and more. A two-month-old memory that perfectly matches beats a five-minute-old memory that partially matches.
Flat files grow forever. chitta-field implements per-memory decay, tiered demotion, auto-deduplication by embedding similarity, contradiction tracking, and distillation from episodic memories into durable wisdom nodes. The field actively forgets what no longer matters and strengthens what repeatedly proves useful.
Conflicting beliefs need operational representation — contradicts, supersedes, and confirms edges that are queryable and that suppress contradicted memories during scoring. Markdown can describe a contradiction; it cannot enforce or query one.
Multiple Claude windows sharing one MEMORY.md produce merge conflicts. chitta-field gives each process its own {instance_id}.seg segment file. Readers replay all segments in sequence-number order. No locking, no conflicts, no D-state on NFS.
cc-soul syncs bidirectionally with Claude Code’s built-in MEMORY.md. What the user writes there is absorbed into chitta; what chitta knows is injected back. Flat files are a fine human-readable interface and import surface. They are not a viable primary substrate at scale.
chitta-field’s in-RAM state is organized into independent organs — each a self-contained store with its own data model, WAL replay path, and query interface. No organ imports another; the coordinator wires them together.
Centroid-based theme clustering over memory IDs. Each ThemeRecord holds a mean embedding centroid, coherence score, and member set partitioned by realm. recall_by_embedding returns top-k themes by cosine similarity. Periodic maintain() splits oversized themes (k-means, k=2) and merges near-identical centroids (>0.9 cosine). WAL: ThemeEvent (20).
Hysteresis-gated credit accumulator that translates surprise magnitude into memory strength adjustments. Evidence is quadratic: ((s−0.20)/0.80)². Credit decays at 0.85 per event; gate requires |credit| ≥ 0.75 and streak ≥ 2 consecutive same-direction signals before a ±0.08 max delta fires. Post-apply bleed (0.35×) prevents rapid re-triggering. Also drives integration-kernel feedback via hard/soft magnitude thresholds. WAL: UpdateSurpriseCredit (44).
Lifecycle FSM for recurring behavioral patterns: Candidate → Provisional → Trusted → Demoted. Candidates are keyed by cluster_key (idempotent upsert). Promotion requires support ≥ 4, cross-session ≥ 2, score ≥ 0.72, and zero contradictions. When promoted, a full memory is written and its ID stored in memory_id. One contradiction permanently blocks promotion until manually cleared. WAL: UpsertWisdomCandidate (45), UpdateWisdomLifecycle (46).
Online weight-delta overlay on the static ScoringConfig. Each factor carries a learned delta clamped to its own [min_delta, max_delta] range. The scorer calls effective_weight(factor, baseline) to get the calibrated value. Updates are full-model atomic snapshots keyed by monotonic model_version. baseline_version detects stale deltas after config bumps. EWMA loss and outcome count track calibration health. WAL: UpdateScorerModel (47).
Epistemic debts now carry Vec<DebtEvidence> — each with memory IDs, confidence, and optional note. auto_resolve_if_ready(threshold=0.70) resolves a debt when evidence meets the threshold, writing a WAL UpdateDebt with a human-readable resolution. The subconscious learning cycle runs this scan every 30 minutes. WAL: AttachDebtEvidence (48).
Append-only versioned registry of named skill blobs. Each skill maps to an ordered list of immutable SkillVersion records — version numbers are 1-based positional indices. deprecate() marks only the latest version; search(query) does case-insensitive substring matching across ID, tags, and content of non-deprecated latest versions. New uploads are immutable; revision requires a new version upload.
Key-value registry of typed entity records (user, org, person) with opaque JSON payloads and observation counting. upsert() performs a full overwrite; observe() increments the observation count without touching the payload. Supports list_by_type queries. State is reconstructable from higher-level WAL events rather than having its own op type.
First-class domain registries for AI session management. SessionRegistry tracks active Claude instances with heartbeats and message queues. TranscriptRegistry indexes conversation turns by session with episode creation. TaskRegistry handles sadhana agents, long-running tasks, dream cycles, and background workers — each as a typed state machine persisted to WAL. WAL: SessionEvent (16), TranscriptEvent (17), TaskEvent (18).
A second, parallel memory substrate that indexes state transitions (tool, entity, outcome) instead of content. Runs alongside HNSW/BM25/HDC recall lanes, which are untouched. The atom of memory is a causal edge, not a document.
Append-only log of (tool_id, entity_key, outcome_class, session_id, ts_ms) with deterministic entity canonicalization (path stripping, FQN lowercasing, URL hostname). Tool and entity names interned to u16/u32. Serialized in FullSnapshot. Also records DecisionPoint branch events (chosen sym + typed rejection reasons). Phase 12: compress_low_surprisal(threshold) tombstones predictable success events.
Online Blumer CDAWG over packed u64 symbols. O(1) amortized per extend(). Each state holds RoaringBitmap endpos, fail_count/succ_count, TD(λ) credit, and Q-value. Rebuilt from EventTape at load (ephemeral, not in snapshot). Supports PPM prediction, counterfactual sibling-edge comparison, top-k Q-value motif retrieval, and TD credit propagation up suffix links weighted by 1/|endpos|.
Tracks support (sym_a → expected sym_b) and contradict (sym_a → anything else) counts per Sequitur rule. Hysteresis: flip to Refuted at ratio > 0.4, reinstate below 0.2. Antecedent index (HashMap<u64, Vec<RefutEntry>>) enables O(1) per-event checks. On refutation, writes a refuted_by triplet to the KG. Ephemeral; rebuilt from EventTape after each Sequitur pass.
Wilson score CI (95%, z=1.96) + binary entropy per Sequitur rule. probe_value = H(p̂) × (1 − |p̂ − 0.5| × 2) — maximized at p̂=0.5 (maximum uncertainty), zero at certainty. top_probes(k) returns rules the system is most uncertain about, ranked by expected information gain. Drives Phase 14 self-directed experimentation. Ephemeral; rebuilt after each consolidation_pass().
Shadow-to-active policy lifecycle for CEC interventions. Three policy kinds: OpenTask, GuardPolicy, TurnInjection. Shadow eval gate: minimum 20 events + expected_lift > 0.15. Adversarial invariant: fire_active() checks refutation_ratio < 0.3 before firing — policies whose source rule is under active refutation are suspended. Auto-proposes tasks on Sequitur rule refutation and on Phase 14 experiment queue.
Pure read-only witness organ. Samples CDAWG state count, EventTape length, tracked/refuted Sequitur rules, HypothesisMarket mean probe_value, Q-value variance, FEP drift/shock EWMAs, and per-sample deltas after each consolidation_pass(). Rolling 100-sample VecDeque. Seven typed diagnoses in priority order: refutation_flood, stale, q_collapse, high_uncertainty, fep_context_drift (ewma_drift > 0.5 — world-model going silently stale), fep_emission_shock (ewma_shock > 0.3 — known context, novel outcomes), healthy. Persisted in FullSnapshot (V16). Zero write surface to any other organ.
Non-actuating generative model P(sym | context) over the EventTape symbol stream. Factored Dirichlet-multinomial emission: P(tool | state) · P(outcome | state, tool) — entity marginalized. Latent context = CDAWG active state plus its k=4 suffix-link chain (soft posterior, not point-mass). Online Bayesian count update with exponential forgetting (STATE_DECAY = 0.9995). Free energy per step: F = Eq[−log P(sym|z)] + KL(qt || priorz) — variational bound, tractable. Two EWMA diagnostic signals fed to TuriyaMonitor: ewma_drift (rising KL → world-model going stale) and ewma_shock (high NLL + low KL → known context, novel outcome). Fully ephemeral — rebuilt from EventTape on each consolidation_pass(), not persisted in snapshot.
Four typed memory kinds inferred at write time from kind tag, realm, and content prefix: Thought (speculation, synthesis), Observation (recorded external fact), Decision (chosen action with rationale), CodeFact (symbol, callgraph, file, type). Static edge-legality matrix enforced in add_assoc_edge() before materialization — (Observation, Thought) and (Decision, Thought) are illegal (rationalization: speculation laundered into fact). Existing memories default to Observation via #[serde(default)] on upgrade. The highest-ROI addition for provenance hygiene: prevents a whole class of hallucinated provenance chains by construction.
Typed query grammar over RecallRequest IR: kind_filter, realm, subject, predicate, freetext, time_from_ms/time_to_ms, causal_tool/causal_entity. route() returns a DispatchKind — Exact | Fuzzy | Temporal | Causal | Hybrid | NeedsDisambiguation(Vec<UnboundSlot>). LLM called only when the grammar leaves a named unbound slot — every token spend corresponds to a specific, auditable hole. Fully bound requests execute zero-token deterministic relational algebra. Four falsifiability metrics written per consolidation_pass(): token-displacement ratio, deterministic replay rate, router error rate, contradiction yield.
First-class provenance axis on every MemoryPayload: Human, Claude, Codex, OpenWeightDistilled, OpenWeightGenerated. can_write_kind(kind) gate: open-weight-generated writes always enter the candidate band — forbidden from direct Decision or CodeFact writes. candidate: bool on payload; promoted only by witness_memory() on a closed-loop signal (user [correction], tool-result outcome, or router hit-rate delta). Candidate-laundering guard in add_assoc_edge(): if src.candidate && !dst.candidate, the edge is rejected — a quarantined memory cannot cite established knowledge as evidence. Stored with #[serde(default)]; no snapshot migration required.
CPU-native deliberation operator — no model call, deterministically replayable. reconcile_all() scans all assoc_edges for MemoryKind legality violations and candidate→established laundering; results returned as illegal_edges, unresolved. detect_contradictions() groups payloads by (realm, first-6-word content prefix) — kind mismatches within the same prefix group produce a conflict_score=0.6 pair; same-kind body divergence produces 0.4. Capped at 50 pairs to avoid O(n²) on large stores. R0/R1 split is inviolable: R0 ops are structural graph traversal; R1 (model proposal) produces only proposals that R0 validates before commit. Results logged to triplet KG as (contradiction:A-B, “conflict_score”, “0.6”) entries.
Every state change is one of these typed operations. The op_type byte is written to the WAL alongside the msgpack payload, and validated on replay to detect corruption.
| Op | Byte | Description |
|---|---|---|
| PutPayload | 0 | Store a new memory with content, embedding, metadata, and artifact refs. |
| UpdateState | 1 | Adjust strength, confidence, decay_rate, or touch last_accessed_ms on an existing memory. |
| DeleteMemory | 2 | Soft-delete a memory at a given timestamp. |
| AddAssocEdge | 3 | Add a typed association edge between two memories (DerivedFrom, SameSession, CoRetrieved, Contradicts, Supports…). |
| UpsertArtifact | 4 | Register a file artifact (normalized path, repo root). |
| AddTriplet | 5 | Add a knowledge graph triplet (subject, predicate, object, weight, valid_from_ms). |
| InvalidateTriplet | 6 | Mark a triplet as superseded at a given timestamp. |
| UpsertSymbol | 7 | Insert or update a code symbol (function, class, method) with its embedding. |
| RemoveSymbol | 8 | Remove a code symbol and clean up call graph edges. |
| AddSymCallEdge | 9 | Add a caller→callee edge in the symbol call graph. |
| RemoveSymCallEdge | 10 | Remove a call graph edge. |
| UpsertCodeFile | 11 | Register or update a code file (path, project, mtime). |
| UpdateSparseCode | 12 | Store sparse code for a memory (feature_ids + activations). |
| DemoteMemory | 13 | Move a memory to a lower decay tier. |
| TrainPQ | 14 | Persist trained Product Quantizer codebooks (bincode-serialized). |
| UpdateResidualPQ | 15 | Store PQ residual codes for a single memory (32-byte compressed embedding). |
| SessionEvent | 16 | Session lifecycle event (register, heartbeat, deregister, message_send, message_ack). |
| TranscriptEvent | 17 | Transcript lifecycle event (register, update_progress, add_turn, create_episode). |
| TaskEvent | 18 | Task lifecycle event for sadhana, long_task, dream, background workers. |
| UserModelEvent | 19 | User model entity event (profile, goal, habit, anticipation, calibration). |
| ThemeEvent | 20 | Theme graph event (create, update_centroid, assign_member, remove_member). |
| AnalyticsEvent | 21 | Analytics event (exposure, recall_query, correction, usage_outcome). |
| ClearProject | 22 | Remove all code files and associated symbols for a project. |
| UpdateSymbolDescription | 23 | Update the description string for a symbol. |
| UpdateMemoryContent | 24 | Update content and/or embedding for an existing memory in-place. |
| AssertFact | 25 | Assert a Prolog-style logic fact into the constraint store (Layer 1). |
| RetractFact | 26 | Retract a constraint fact by ID. |
| BranchEvent | 27 | Hypothetical branch lifecycle — create, resolve, or discard. |
| TriggerEvent | 28 | Trigger tissue lifecycle — add, dismiss, or record a firing (Layer 2). |
| PredictorEvent | 29 | Markov chain transition update — bump edge probability or record access (Layer 3). |
| RecordSurprise | 39 | Record a prediction error tuple — expected vs actual outcome (Layer 4). |
| RegisterDebt | 40 | Register a new epistemic debt with competing hypotheses and discriminating tests (Layer 5). |
| UpdateDebt | 41 | Resolve, defer, or update status of an epistemic debt. |
| UpdateSourceWeight | 42 | Update learned recall source weight for a (domain, source) pair (Layer 6). |
| RecordFeedback | 43 | Record whether a recall source was useful — feeds Bayesian weight update. |
| UpdateSurpriseCredit | 44 | Persist per-memory rolling credit state after hysteresis gate — strength delta applied. |
| UpsertWisdomCandidate | 45 | Create or update a wisdom candidate with support evidence and promotion score. |
| UpdateWisdomLifecycle | 46 | Advance wisdom candidate through FSM — candidate → provisional → trusted → demoted. |
| UpdateScorerModel | 47 | Atomic snapshot of the learned scoring model — full factor weight delta map. |
| AttachDebtEvidence | 48 | Attach supporting evidence (memory IDs + confidence) to an epistemic debt. |
chitta-field is a separate Rust repository included as a git submodule. The C++ daemon calls into it exclusively via a C FFI layer (chitta_field.h), keeping the Rust and C++ build systems fully independent.
chitta-field builds to libchitta_field.a via ./build.sh build --release. The CMake build picks it up from ../chitta-field/ (relative to chitta/CMakeLists.txt) or from a -DCHITTA_FIELD_ROOT override. The smart-installer runs the Rust build automatically before cmake.
All calls go through cf_* C functions defined in chitta_field.h. The C++ side calls cf_open(), gets back an opaque FieldHandle*, and uses it for all subsequent ops. No C++ knows about Rust internals.
The RPC handler that registers all 100+ tools wraps FieldStore via the FFI. ChittaFieldHandler in rpc/chitta_field_handler.hpp is the sole RPC handler for all memory operations.
The chitta-field memory substrate draws on the following published work.
No external database. No NFS handles. No D-state. Just a field of patterns, each memory a sparse activation, decaying and strengthening over time.