Skip to content

v0.16.0 — memory hygiene

Latest

Choose a tag to compare

@cremenescu cremenescu released this 24 Jul 08:07

Memory hygiene

A store that has been accumulating for months grows its own maintenance problems: near-duplicate records saying the same thing three ways, scratch notes nobody ever cleaned up, and an injection budget spent on memories you never actually reach for. This release is the housekeeping layer — local, non-destructive by default, and review-gated where it touches your content.

  • mem.py consolidate — clusters near-duplicate memories (deterministic token clustering over summary + body; an optional local-LLM pass writes the merged text) and proposes the merge on a separate mem-consolidation git branch. Nothing on main is rewritten until you read the diff and merge it yourself. The extraction queue behind it is now crash-safe: candidates are keyed by content, so an interrupted run re-queues nothing twice.
  • Scheduled maintenance — mem_maintenance.py — a launchd job (install / uninstall / status / run) that keeps the derived state fresh while you are not looking: rebuild the FTS5 index, re-embed what changed, report stale working notes, commit the store, refresh consolidation proposals. Report-only by default — pruning happens only if you opt in with MEM_MAINT_PRUNE_WORKING=1, and even then it is logged and git-reversible. Local scheduler, no daemon, no cloud, no new dependency.
  • Access-aware injection — reads are recorded in a derived .access.db, and SessionStart uses that to order what it shows: the memories you actually reach for float to the top of the budget. Paired with a per-record body cap (MEM_INJECT_RECORD_CAP, default 1000 chars) so one long record can no longer eat the whole injection, with the retrieval command printed in its place.
  • Session provenance — every write now stamps the conversation that produced it (session:), so months later "where did this claim come from?" is answerable. Pairs with session_search from v0.15.0: from a memory to the raw conversation that created it.
  • POST /api/propose — a uniform HTTP ingestion channel for agents and scripts that speak neither MCP nor the CLI. Queue-only by design: proposals are redacted, injection-scanned and deduped, and never reach the store without review.

Also

  • protected: true (opt-in, via mem.py add --protected) refuses in-place edit, delete and supersede of a record on every tool path — for the handful of standing rules you never want an agent, or a stray click, to rewrite. Off by default; and since a record is just a block in a markdown file you own, unsetting it by hand is always available.
  • The settings page exposes the new knobs (maintenance window, working-note retention, per-record injection cap).
  • bge-m3 is the default embedder. Measured on the author's real store with paraphrased, non-English queries, it put the intended memory at median rank 1, where the previous default sat at 231 — semantic recall that had been effectively decorative now works.
  • Web UI: long strings no longer overflow the memories table.
  • The README now opens with a recorded demo — save a lesson, recall it from a plain-language question, resume the project.

No store-format migration: existing records are read unchanged, and the new meta keys are additive.