a digital entity named phi that roams bsky phi.zzstoatzz.io
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

remove phi-core memory namespace and all references

phi-core was a turbopuffer namespace meant for operator-curated
identity and guidelines at highest trust. in practice it was never
properly curated — it accumulated 7 copies of a murmuration test
rule from an eval that wrote to production, stale IIT-era identity,
an Ozzy Osbourne concert correction, and "Today feels stable and
optimistic." all 18 entries were injected into every agent run as
[CORE IDENTITY AND GUIDELINES] alongside the actual personality file.

the personality file is the source of truth for identity. operator
directives happen through direct conversation with phi, not hidden
injection. this commit removes the concept entirely:

- namespace_memory.py: remove phi-core from NAMESPACES, delete
store_core_memory() and get_core_memories(), remove include_core
parameter from build_user_context()
- agent.py: remove include_core flag from inject_user_memory, remove
tier 1 [CORE IDENTITY AND GUIDELINES] from trust hierarchy (past
exchanges are now highest trust)
- evals/test_memory_integration.py: deleted — this test wrote
"when users mention birds, acknowledge murmuration patterns" to
production turbopuffer and never cleaned up. it ran at least 6
times, leaving 7 persistent entries phi read on every interaction.
- evals/conftest.py: remove include_core=True from build_user_context
call
- docs/memory.md: remove phi-core from namespace table and context
injection diagram
- CLAUDE.md: remove phi-core from namespace list

the turbopuffer phi-core namespace was already purged to 0 entries
earlier this session. this commit removes the code that would
repopulate it.

zzstoatzz c815323a b58c5846

+9 -131
+1 -1
CLAUDE.md
··· 44 44 45 45 - all notification types (mentions, replies, quotes, likes, reposts, follows) run through the full agent loop — phi decides what's worth responding to 46 46 - personality is separate from operational instructions (agent.py `OPERATIONAL_INSTRUCTIONS`) 47 - - memory: turbopuffer namespaces (`phi-core`, `phi-users-{handle}`, `phi-episodic`) 47 + - memory: turbopuffer namespaces (`phi-users-{handle}`, `phi-episodic`) 48 48 - relationship summaries are compacted by a separate pipeline in my-prefect-server 49 49 - MCP servers: pdsx (atproto record CRUD), pub-search (publication search)
+1 -3
docs/memory.md
··· 26 26 27 27 | namespace | contents | 28 28 |-----------|----------| 29 - | `phi-core` | identity and guidelines (highest trust) | 30 29 | `phi-users-{handle}` | per-user observations + raw interaction logs | 31 30 | `phi-episodic` | phi's own notes about the world | 32 31 ··· 102 101 when phi processes a mention from `@alice` about topic X: 103 102 104 103 ``` 105 - [CORE IDENTITY AND GUIDELINES] ← phi-core namespace (highest trust) 106 - [PHI'S SYNTHESIZED IMPRESSION] ← relationship summary (lowest trust) 104 + [PHI'S SYNTHESIZED IMPRESSION] ← relationship summary (low trust) 107 105 [OBSERVATIONS ABOUT @alice] ← user namespace, kind=observation, status!=superseded 108 106 [PAST EXCHANGES WITH @alice] ← user namespace, kind=interaction 109 107 [PHI'S RELEVANT MEMORIES] ← episodic namespace, semantic search
+1 -1
evals/conftest.py
··· 132 132 if self.memory: 133 133 try: 134 134 memory_context = await self.memory.build_user_context( 135 - author_handle, query_text=mention_text, include_core=True 135 + author_handle, query_text=mention_text 136 136 ) 137 137 except Exception: 138 138 pass
-42
evals/test_memory_integration.py
··· 1 - """Proof of concept: LLM-as-judge eval for memory integration.""" 2 - 3 - import pytest 4 - 5 - from bot.config import Settings 6 - from bot.memory import NamespaceMemory 7 - 8 - 9 - @pytest.fixture 10 - def memory_settings(): 11 - """Check if memory keys are available.""" 12 - settings = Settings() 13 - if not all([settings.turbopuffer_api_key, settings.openai_api_key, settings.anthropic_api_key]): 14 - pytest.skip("Requires TURBOPUFFER_API_KEY, OPENAI_API_KEY, and ANTHROPIC_API_KEY") 15 - return settings 16 - 17 - 18 - async def test_memory_integration(memory_settings, phi_agent, evaluate_response): 19 - """Proof of concept: agent uses stored memory in response.""" 20 - memory = NamespaceMemory(api_key=memory_settings.turbopuffer_api_key) 21 - 22 - # Store a core memory guideline 23 - await memory.store_core_memory( 24 - label="test_guideline", 25 - content="When users mention birds, acknowledge murmuration patterns", 26 - memory_type="guideline", 27 - ) 28 - 29 - phi_agent.memory = memory 30 - 31 - response = await phi_agent.process_mention( 32 - mention_text="I saw starlings today", 33 - author_handle="test.user", 34 - thread_context="No previous messages in this thread.", 35 - thread_uri="at://test/thread/1", 36 - ) 37 - 38 - if response.action == "reply": 39 - await evaluate_response( 40 - "Does the response reference murmuration patterns?", 41 - response.text, 42 - )
+5 -8
src/bot/agent.py
··· 47 47 your memory is a tool, not ground truth. context injected before each message comes 48 48 from multiple sources with different reliability: 49 49 50 - 1. [CORE IDENTITY AND GUIDELINES] — your stable identity. highest trust. 51 - 2. [PAST EXCHANGES] — verbatim logs of what was actually said. high trust. 52 - 3. [OBSERVATIONS] — facts extracted from users' own words by another model. medium trust — extraction can misattribute. 53 - 4. [PHI'S SYNTHESIZED IMPRESSION] — generated by a separate summarization model. low trust — may contain hallucinations. 54 - 5. [BACKGROUND RESEARCH] — you explored their public activity during downtime. lowest trust — may be incomplete or misattributed. never assert these as fact. 50 + 1. [PAST EXCHANGES] — verbatim logs of what was actually said. highest trust. 51 + 2. [OBSERVATIONS] — facts extracted from users' own words by another model. medium trust — extraction can misattribute. 52 + 3. [PHI'S SYNTHESIZED IMPRESSION] — generated by a separate summarization model. low trust — may contain hallucinations. 53 + 4. [BACKGROUND RESEARCH] — you explored their public activity during downtime. lowest trust — may be incomplete or misattributed. never assert these as fact. 55 54 56 55 when recalling facts about a user: 57 56 - if the user's current message contradicts your notes, trust their current words. ··· 273 272 return "" 274 273 275 274 blocks: list[str] = [] 276 - include_core = True 277 275 for handle, texts in by_author.items(): 278 276 query = " ".join(t for t in texts if t) or handle 279 277 try: 280 278 block = await ctx.deps.memory.build_user_context( 281 - handle, query_text=query, include_core=include_core 279 + handle, query_text=query 282 280 ) 283 - include_core = False # only include core in the first block 284 281 if block: 285 282 blocks.append(block) 286 283 except Exception as e:
+1 -76
src/bot/memory/namespace_memory.py
··· 30 30 """ 31 31 32 32 NAMESPACES: ClassVar[dict[str, str]] = { 33 - "core": "phi-core", 34 33 "users": "phi-users", 35 34 "episodic": "phi-episodic", 36 35 } ··· 65 64 model="text-embedding-3-small", input=text 66 65 ) 67 66 return response.data[0].embedding 68 - 69 - # --- core memory (unchanged) --- 70 - 71 - async def store_core_memory( 72 - self, 73 - label: str, 74 - content: str, 75 - memory_type: str = "system", 76 - char_limit: int = 10_000, 77 - ): 78 - """Store or update core memory block.""" 79 - if len(content) > char_limit: 80 - content = content[: char_limit - 3] + "..." 81 - 82 - block_id = self._generate_id("core", label) 83 - 84 - self.namespaces["core"].write( 85 - upsert_rows=[ 86 - { 87 - "id": block_id, 88 - "vector": await self._get_embedding(content), 89 - "label": label, 90 - "type": memory_type, 91 - "content": content, 92 - "importance": 1.0, 93 - "created_at": datetime.now().isoformat(), 94 - "updated_at": datetime.now().isoformat(), 95 - } 96 - ], 97 - distance_metric="cosine_distance", 98 - schema={ 99 - "label": {"type": "string"}, 100 - "type": {"type": "string"}, 101 - "content": {"type": "string", "full_text_search": True}, 102 - "importance": {"type": "float"}, 103 - "created_at": {"type": "string"}, 104 - "updated_at": {"type": "string"}, 105 - }, 106 - ) 107 - 108 - async def get_core_memories(self) -> list[dict]: 109 - """Get all core memories.""" 110 - response = self.namespaces["core"].query( 111 - rank_by=("vector", "ANN", [0.5] * 1536), 112 - top_k=100, 113 - include_attributes=["label", "type", "content", "importance", "created_at"], 114 - ) 115 - 116 - entries = [] 117 - if response.rows: 118 - for row in response.rows: 119 - entries.append( 120 - { 121 - "id": row.id, 122 - "content": row.content, 123 - "label": getattr(row, "label", "unknown"), 124 - "type": getattr(row, "type", "system"), 125 - "importance": getattr(row, "importance", 1.0), 126 - "created_at": row.created_at, 127 - } 128 - ) 129 - return entries 130 67 131 68 # --- user memory --- 132 69 ··· 337 274 ) 338 275 return None 339 276 340 - async def build_user_context( 341 - self, handle: str, query_text: str, include_core: bool = True 342 - ) -> str: 277 + async def build_user_context(self, handle: str, query_text: str) -> str: 343 278 """Build context for a conversation from observations and recent interactions.""" 344 279 parts = [] 345 - 346 - if include_core: 347 - core_memories = await self.get_core_memories() 348 - if core_memories: 349 - parts.append("[CORE IDENTITY AND GUIDELINES]") 350 - for mem in sorted( 351 - core_memories, key=lambda x: x.get("importance", 0), reverse=True 352 - ): 353 - label = mem.get("label", "unknown") 354 - parts.append(f"[{label}] {mem['content']}") 355 280 356 281 # relationship summary (synthesized by compact flow — treat as phi's impression, not ground truth) 357 282 summary = await self.get_relationship_summary(handle)