You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I understand this issue needs status:approved before a PR can be opened
Bug Description
Two related bugs that cause project name fragmentation to be unrecoverable through engram's built-in tools:
Bug 1 — projects consolidate does nothing:
Running engram projects consolidate --all correctly detects groups of similar project names, but when selecting all to merge, it always reports Merged: 0 obs, 0 sessions, 0 prompts and no rows are actually updated in the database.
Bug 2 — mem_update does not persist project changes:
Calling mem_update(id, project="new_name") via MCP returns Memory updated: #ID "title" but the project column is not changed in the database. Subsequent queries still show the old project name.
Root cause of the fragmentation:
Engram MCP's mem_save normalizes project names to lowercase (e.g. Stack_Ecokey → stack_ecokey), but other code paths (CLI, older binary versions) may store the original case from the git remote. This creates duplicates like Stack_Ecokey (499 obs) and stack_ecokey (11 obs) that cannot be merged with the built-in tools.
Steps to Reproduce
Have a git repo with a mixed-case remote name (e.g. Stack_Ecokey)
Use engram across sessions — some memories end up as Stack_Ecokey, others as stack_ecokey
Run engram projects list — see two entries for the same project
Run engram projects consolidate --all and type all for the group
See Merged: 0 obs, 0 sessions, 0 prompts
Run engram projects list again — nothing changed
Try MCP: mem_update(id=1546, project="stack_ecokey") — returns success but project is unchanged
Expected Behavior
projects consolidate should update all rows in sessions, observations, user_prompts, prompts_fts, sync_mutations, and observations_fts tables to the canonical project name.
mem_update(project=...) should persist the project name change in the database.
Actual Behavior
`
$ engram projects consolidate --all
Found 2 group(s) of similar project names:
canonical must be lowercase (engram MCP normalizes to lowercase)
MERGES = {"stack_ecokey": ["Stack_Ecokey"]}
for canonical, variants in MERGES.items():
for variant in variants:
for table in TABLES:
conn.execute(
f"UPDATE {table} SET project = ? WHERE project = ?",
(canonical, variant),
)
conn.commit()
conn.close()
`
Important: The canonical name must be lowercase because mem_save normalizes to lowercase. If you merge into the uppercase variant, fragmentation will recur on the next save.
The fragmentation is especially common when using multiple agents (Claude Code + OpenCode) that may point to different engram binary versions with different project name detection heuristics.
Unifying all agent configs to use the same engram binary from PATH (instead of absolute paths to different versions) prevents future fragmentation.
Pre-flight Checks
status:approvedbefore a PR can be openedBug Description
Two related bugs that cause project name fragmentation to be unrecoverable through engram's built-in tools:
Bug 1 —
projects consolidatedoes nothing:Running
engram projects consolidate --allcorrectly detects groups of similar project names, but when selectingallto merge, it always reportsMerged: 0 obs, 0 sessions, 0 promptsand no rows are actually updated in the database.Bug 2 —
mem_updatedoes not persist project changes:Calling
mem_update(id, project="new_name")via MCP returnsMemory updated: #ID "title"but the project column is not changed in the database. Subsequent queries still show the old project name.Root cause of the fragmentation:
Engram MCP's
mem_savenormalizes project names to lowercase (e.g.Stack_Ecokey→stack_ecokey), but other code paths (CLI, older binary versions) may store the original case from the git remote. This creates duplicates likeStack_Ecokey(499 obs) andstack_ecokey(11 obs) that cannot be merged with the built-in tools.Steps to Reproduce
Stack_Ecokey)Stack_Ecokey, others asstack_ecokeyengram projects list— see two entries for the same projectengram projects consolidate --alland typeallfor the groupMerged: 0 obs, 0 sessions, 0 promptsengram projects listagain — nothing changedmem_update(id=1546, project="stack_ecokey")— returns success but project is unchangedExpected Behavior
projects consolidateshould update all rows insessions,observations,user_prompts,prompts_fts,sync_mutations, andobservations_ftstables to the canonical project name.mem_update(project=...)should persist the project name change in the database.Actual Behavior
`
$ engram projects consolidate --all
Found 2 group(s) of similar project names:
Group 2:
→ [1] Stack_Ecokey 499 obs
[2] stack_ecokey 11 obs
Suggested canonical: "Stack_Ecokey" (→)
Choice: all
Merged: 0 obs, 0 sessions, 0 prompts
$ engram projects list
Stack_Ecokey 499 obs 289 sessions 459 prompts
stack_ecokey 11 obs 6 sessions 38 prompts ← still there
`
Environment
Workaround
Direct SQLite UPDATE against
~/.engram/engram.db:`python
import sqlite3, shutil
from pathlib import Path
DB = Path.home() / ".engram" / "engram.db"
shutil.copy2(DB, DB.with_suffix(".db.backup"))
conn = sqlite3.connect(str(DB))
conn.execute("PRAGMA journal_mode=WAL")
TABLES = [
"sessions", "observations", "user_prompts",
"prompts_fts", "sync_mutations", "observations_fts",
]
canonical must be lowercase (engram MCP normalizes to lowercase)
MERGES = {"stack_ecokey": ["Stack_Ecokey"]}
for canonical, variants in MERGES.items():
for variant in variants:
for table in TABLES:
conn.execute(
f"UPDATE {table} SET project = ? WHERE project = ?",
(canonical, variant),
)
conn.commit()
conn.close()
`
Important: The canonical name must be lowercase because
mem_savenormalizes to lowercase. If you merge into the uppercase variant, fragmentation will recur on the next save.Additional Context
engrambinary from PATH (instead of absolute paths to different versions) prevents future fragmentation.