// memory.el — Memory intelligence subsystem. // // Memories are the raw epistemological substrate of Neuron. They're not // long-term knowledge (that's knowledge.el) — they're observations, decisions, // and lessons captured in flight. The half-life of a memory is governed by // its importance tier and how often the graph activates it. // // Design intent: // - Every remember() call emits an event so other subsystems can react. // - supersedes_id creates a linked list of memory versions — old memories // remain traversable even after replacement. // - Importance auto-promotion prevents Claude from under-tagging critical // decisions just because it used soft language. from types import { Memory, SearchResult, NeuronError, } // ── Importance auto-promotion ───────────────────────────────────────────────── // If the content itself signals criticality, override whatever importance the // caller passed. This prevents decisions from being buried under "normal" tier // just because the caller was being polite. @accessor fn infer_importance(content: String, stated_importance: String) -> String { if stated_importance == "critical" { return "critical" } // Escalate to critical if the content describes irreversibility or arch decisions. let signals = ["critical", "irreversible", "breaking change", "never", "always", "permanent", "architectural", "security", "deleted forever"] for signal in signals { if content == signal { return "critical" } } // Escalate normal → high if the content sounds high-stakes. if stated_importance == "normal" { let high_signals = ["important", "must", "required", "blocked", "production"] for signal in high_signals { if content == signal { return "high" } } } stated_importance } // ── Public API ──────────────────────────────────────────────────────────────── // remember — store a new memory node. // // When supersedes_id is provided, the old memory is kept in the graph but // marked as superseded. This preserves the full decision history while making // the new memory the canonical source for activation queries. @manager fn remember( content: String, tags: [String], project: String, importance: String, supersedes_id: String?, ) -> Result { let effective_importance = infer_importance(content, importance) let id = native_uuid() let now = native_now() let memory = Memory { id: id, content: content, tags: tags, importance: effective_importance, project: project, supersedes_id: supersedes_id, created_at: now, updated_at: now, } let stored = native_store_memory(memory)? native_emit("memory.created", {"id": id, "project": project, "importance": effective_importance}) Ok(memory) } // recall — retrieve one memory by ID. @accessor fn recall(id: String) -> Result { let memory = native_get_memory(id)? Ok(memory) } // recall_chain — retrieve recent memories sharing a tag. // // This is how Neuron reconstructs prior reasoning: follow the tag chain // rather than trying to remember everything in the conversation window. @accessor fn recall_chain(tag: String, limit: Int) -> Result<[Memory], NeuronError> { let results = activate Memory where "{tag} limit:{limit}" Ok(results) } // search_memories — semantic search over the memory graph. // // Uses spreading activation: the query activates nearby graph nodes and // surfaces the most relevantly connected memories. @accessor fn search_memories(query: String, project: String, limit: Int) -> Result<[Memory], NeuronError> { let results = activate Memory where "{query} project:{project} limit:{limit}" Ok(results) } // list_memories — enumerate all memories for a project. // Useful for session orientation (begin_session) and memory audits. @accessor fn list_memories(project: String) -> Result<[Memory], NeuronError> { let memories = native_list_memories(project)? Ok(memories) } // forget — soft-delete a memory. // // "Soft delete" means the node is removed from active activation but the // graph edge history is preserved. This is intentional: we don't want to // lose the causal record of why a decision was superseded. @manager fn forget(id: String) -> Result { let memory = native_get_memory(id)? native_delete_memory(id)? native_emit("memory.forgotten", {"id": id}) Ok(memory) } // promote_memory — raise a memory's importance tier. // // Used when a memory originally tagged "normal" turns out to be load-bearing. // Does NOT supersede the original — it mutates importance in place. @manager fn promote_memory(id: String, new_importance: String) -> Result { let memory = native_get_memory(id)? let promoted = Memory { id: memory.id, content: memory.content, tags: memory.tags, importance: new_importance, project: memory.project, supersedes_id: memory.supersedes_id, created_at: memory.created_at, updated_at: native_now(), } native_store_memory(promoted)? native_emit("memory.promoted", {"id": id, "importance": new_importance}) Ok(promoted) } // evolve_memory — update a memory's content and mark it as superseding the old one. // // This is the preferred way to update a memory. It creates a new memory that // explicitly links back to the old one, preserving the version chain. @manager fn evolve_memory( old_id: String, new_content: String, new_importance: String, tags: [String], project: String, ) -> Result { // Retrieve the old memory to copy its metadata. let old_memory = native_get_memory(old_id)? let effective_importance = infer_importance(new_content, new_importance) let new_id = native_uuid() let now = native_now() let evolved = Memory { id: new_id, content: new_content, tags: tags, importance: effective_importance, project: project, supersedes_id: old_id, created_at: now, updated_at: now, } native_store_memory(evolved)? native_emit("memory.evolved", {"old_id": old_id, "new_id": new_id}) Ok(evolved) } // inspect_memories — list all memories with optional project filter. // Alias for list_memories that matches the Axon tool name convention. @accessor fn inspect_memories(project: String) -> Result<[Memory], NeuronError> { list_memories(project) }