1
0

[loop-cycle-62] fix: MEMORY.md corruption and hot memory staleness (#252) (#256)

This commit is contained in:
2026-03-15 15:01:19 -04:00
parent 7bc355eed6
commit dd34dc064f
4 changed files with 201 additions and 31 deletions

View File

@@ -641,6 +641,38 @@ def store_personal_fact(fact: str, agent_id: str | None = None) -> MemoryEntry:
)
def store_last_reflection(reflection: str) -> None:
"""Store the last reflection, replacing any previous one.
Uses a single row with memory_type='reflection' to avoid accumulation.
"""
if not reflection or not reflection.strip():
return
with get_connection() as conn:
# Delete previous reflections — only the latest matters
conn.execute("DELETE FROM memories WHERE memory_type = 'reflection'")
conn.execute(
"""
INSERT INTO memories
(id, content, memory_type, source, created_at)
VALUES (?, ?, 'reflection', 'system', ?)
""",
(str(uuid.uuid4()), reflection.strip(), datetime.now(UTC).isoformat()),
)
conn.commit()
logger.debug("Stored last reflection in DB")
def recall_last_reflection() -> str | None:
"""Recall the most recent reflection, or None if absent."""
with get_connection() as conn:
row = conn.execute(
"SELECT content FROM memories WHERE memory_type = 'reflection' "
"ORDER BY created_at DESC LIMIT 1"
).fetchone()
return row["content"] if row else None
# ───────────────────────────────────────────────────────────────────────────────
# Hot Memory (computed from DB instead of MEMORY.md)
# ───────────────────────────────────────────────────────────────────────────────
@@ -655,13 +687,23 @@ class HotMemory:
self._last_modified: float | None = None
def read(self, force_refresh: bool = False) -> str:
"""Read hot memory — computed view of top facts from DB."""
"""Read hot memory — computed view of top facts + last reflection from DB."""
try:
facts = recall_personal_facts()
lines = ["# Timmy Hot Memory\n"]
if facts:
lines = ["# Timmy Hot Memory\n", "## Known Facts\n"]
lines.append("## Known Facts\n")
for f in facts[:15]:
lines.append(f"- {f}")
# Include the last reflection if available
reflection = recall_last_reflection()
if reflection:
lines.append("\n## Last Reflection\n")
lines.append(reflection)
if len(lines) > 1:
return "\n".join(lines)
except Exception:
pass
@@ -707,12 +749,16 @@ class HotMemory:
new_section = f"## {section}\n\n{content}\n\n"
full_content = full_content[: match.start()] + new_section + full_content[match.end() :]
else:
# Append section before last updated line
# Append section — guard against missing prune marker
insert_point = full_content.rfind("*Prune date:")
new_section = f"## {section}\n\n{content}\n\n"
full_content = (
full_content[:insert_point] + new_section + "\n" + full_content[insert_point:]
)
if insert_point < 0:
# No prune marker — just append at end
full_content = full_content.rstrip() + "\n\n" + new_section
else:
full_content = (
full_content[:insert_point] + new_section + "\n" + full_content[insert_point:]
)
self.path.write_text(full_content)
self._content = full_content