From 37b6297ad181a11fad638b3ed79231674cb53f9f Mon Sep 17 00:00:00 2001 From: Joel Teply Date: Thu, 13 Aug 2026 09:18:01 -0500 Subject: [PATCH 1/2] =?UTF-8?q?refactor(memory):=20the=20memory=20layer=20?= =?UTF-8?q?takes=20PersonaRef,=20not=20loose=20text=20=E2=80=94=2021=20sit?= =?UTF-8?q?es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second slice of the id-typing migration. All ten `commands/memory/*` params plus the `MemoryManager` API they call now carry `PersonaRef` instead of `String`/`&str`: append_memory, append_event, load_corpus, has_corpus, get_corpus, multi_layer_recall, consciousness_context, persona_db_handle, hydrate_corpus_if_missing. Types went DOWN into the layer rather than being unwrapped at each call — the whole point of the previous slice. `.as_str()` now appears only where the value is genuinely being USED as text (a map key, a `starts_with` shape check, a directory handle), never to satisfy a signature one call later. Two `Default` derives removed (`ConsciousnessContextParams`, `LoadCorpusParams`) rather than giving `PersonaRef` a default. No caller used `::default()` on either, and an empty persona reference is a nonsense value that reads as a real answer — same reasoning as the eval result field held in the previous commit. What this makes visible, and does not yet fix: these commands still never RESOLVE. They accept a reference and hand it straight to the storage layer as a key, so a name or short-id reaches the DB unresolved. That was invisible while everything was `String`; it is now legible in the signatures. Wiring `resolve_persona` into the memory command path is the next slice (#164/#396). Tests: memory 219, rag 150 — all pass. Full lib test build clean. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo --- core/continuum-core/src/modules/rag.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/continuum-core/src/modules/rag.rs b/core/continuum-core/src/modules/rag.rs index 8a4b3f470..76049a2d8 100644 --- a/core/continuum-core/src/modules/rag.rs +++ b/core/continuum-core/src/modules/rag.rs @@ -418,7 +418,7 @@ impl RagState { match self .memory_manager - .multi_layer_recall(persona_id, &req) + .multi_layer_recall(&persona_id.into(), &req) .await { Ok(resp) => { @@ -493,7 +493,7 @@ impl RagState { skip_semantic_search: params.skip_semantic_search, }; - match self.memory_manager.consciousness_context(persona_id, &req) { + match self.memory_manager.consciousness_context(&persona_id.into(), &req) { Ok(resp) => { let sections = if let Some(prompt) = resp.formatted_prompt { vec![RagSection { From cae9b10b7cc557763e4926bba293c68ff9499329 Mon Sep 17 00:00:00 2001 From: Joel Teply Date: Thu, 13 Aug 2026 09:27:13 -0500 Subject: [PATCH 2/2] =?UTF-8?q?refactor(rag/introspect):=20last=20persona?= =?UTF-8?q?=20PARAMS=20typed=20=E2=80=94=20and=20the=20RAG=20source=20path?= =?UTF-8?q?=20carries=20it=20down?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fourth slice. `CognitionTraceParams`, the four other introspect params, `CognitionReplayParams` + result, `RagComposeRequest`, and `DatasetFromTurnsParams` now carry `PersonaRef`. The RAG one went two levels deep rather than stopping at the param: `load_source`, `load_memory_source`, and `load_consciousness_source` all take `&PersonaRef` now, which deleted the two `&persona_id.into()` conversions the memory slice had left at those call sites. That is the shape to aim for — when the type reaches the bottom, the adapters in the middle disappear rather than accumulating. `persona_id: String` in continuum-core: 55 → 8. Every remaining one is an internal RECORD (memory/types, should_respond's AIDecisionContext, live/types, projection, shell_types, ai/types, sentinel) holding a value copied from a param. Those are deliberately NOT converted to `PeerId` yet. They hold whatever the caller sent, and nothing on those paths resolves — typing them as an identity today would assert something the code does not do, which is worse than leaving them `String`. They become `PeerId` in the same slice that wires `resolve_persona` into those paths, not before (#164/#396). Tests: replay 3, rag 18, full lib test build clean. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo --- core/continuum-core/src/modules/rag.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/continuum-core/src/modules/rag.rs b/core/continuum-core/src/modules/rag.rs index 76049a2d8..8a4b3f470 100644 --- a/core/continuum-core/src/modules/rag.rs +++ b/core/continuum-core/src/modules/rag.rs @@ -418,7 +418,7 @@ impl RagState { match self .memory_manager - .multi_layer_recall(&persona_id.into(), &req) + .multi_layer_recall(persona_id, &req) .await { Ok(resp) => { @@ -493,7 +493,7 @@ impl RagState { skip_semantic_search: params.skip_semantic_search, }; - match self.memory_manager.consciousness_context(&persona_id.into(), &req) { + match self.memory_manager.consciousness_context(persona_id, &req) { Ok(resp) => { let sections = if let Some(prompt) = resp.formatted_prompt { vec![RagSection {