Skip to content

4.5.0 - atomic memories and self-maintaining tags

Latest

Choose a tag to compare

@MaxFreedomPollard MaxFreedomPollard released this 02 Aug 09:47

Memories are now atomized data points rather than longer format descriptions, and tags maintain themselves as the vault grows.

One fact per memory

A memory is an atomized data point, not a summary or a session log. memory_store_many stores a whole batch in one call, so six separate facts cost the same single round trip that bundling them into a longer format description used to buy - which was the standing incentive to bundle. The MCP instructions carry the rule and a worked example. Opinions, preferences and conclusions are stored exactly as much as they always were; they are simply stored as atomized data points too, each recording what was held and why it was needed.

Two dates, kept apart

Compartment stamps when a memory was saved, with the time of day. It separately records the day a fact was discovered and how it was established, appended to the memory as a short [web search, 2026-08-01] clause so a claim stays self-describing wherever it ends up. Those are two different dates: a price you check on the Friday and write up on the Monday keeps Friday as its discovery and Monday as its save.

The clause is excluded from the embedding, so the same fact learned twice by different means is still recognised as the same fact, and a whole afternoon's memories no longer look alike to the encoder.

Claims are dated, not eternal

Prices, plans, locations and other "facts" about things that change often change, but a memory created prior to a change is often called after these facts change. We've improved memory creation and associative memory to automatically update tags, so that a point-in-time fact isn't confused as an eternal truth, and old facts which are relevant to the same things under new names or with different details are called correctly.

Tags that stay true

What a memory is about never changes. What it is relevant to changes constantly, and a tag written once, on the day the memory was stored, cannot know that.

Here is an example of the failure this solves. Working on a project called Northwind, you learn that your client wants figures before conclusions: never open with the recommendation, open with the numbers. That is a durable fact about a person. The agent stores it and tags it northwind, reporting, because Northwind is what was in front of it that day.

Northwind ends. Two years later the same client, now going by the name Harbour, hires you again. Your agent narrows recall to harbour, the way anyone narrows a search once a vault holds thousands of memories. The one thing you most want applied is filed under a name that no longer exists. It is still true and still exactly the right rule, but a tag-filtered search cannot return it, because tag filtering is a subset match and a memory lacking the tag is simply not in the set. The memory did not decay. Its index entry did.

Compartment repairs that automatically, offline, in the background, without using an LLM. As Harbour memories accumulate - the client asking for numbers up front again, a deck reordered to lead with them - they land by design beside that old preference in embedding space, because they are about the same subject and placed similarly through ordered logic. A background pass gives every memory the tags its nearest neighbours carry, weighted by cosine, and the preference picks up harbour from them. Two more offline signals run alongside it: tags that nearly always occur together come to imply one another, and any existing tag whose phrase appears in a memory's own text is attached. Nothing in Compartment ever knew what Northwind or Harbour were.

The pass can only write the tags column, never the text, the dates or the embeddings. It is additive unless you pass --prune, tags_origin keeps the tags a memory was born with forever, and compartment retag --dry-run shows exactly what would change before anything does.

A tag has to earn the right to travel: it must already be carried by at least three records, sit on no more than a quarter of the vault, and not be date-shaped. Measured on a real 7,206-record vault, that is a median of two tags added per record and a pass that finishes in under six seconds.

retag_interval_hours (default 6) and retag_prune (default false) control the background pass; set the interval to 0 to turn it off.

Search returns what is relevant

How many memories answer a question is a property of the question, not a constant. Compartment returns every memory whose evidence stands up against the best answer to that same query, capped at 100. Pass top_k when you want exactly that many.

The cut is relative because measurement forced it: scores are not comparable across queries. On a real vault the nonsense query "how to bake sourdough bread" peaked at 2.73 while the genuine question "what did Max decide about Airtable" peaked at 1.59, so any fixed score threshold admits the nonsense and rejects the question. A noise floor sits underneath for when nothing is relevant at all: "the capital of France" returns zero results.

Search also gains discovered_since and discovered_until, so the discovery date can be queried and not only recorded.

Every memory records how it was learned

source is required on memory_store, memory_store_many and compartment store: a memory carrying a date but no method is a claim with no way to check it. The tool schema enforces it, so the correct call is the only one available.

Upgrading

Vaults sealed by earlier versions gain the new columns the moment they are opened, and nothing needs rebuilding or re-embedding. Import and export now carry the discovery method and preserve creation dates, which they previously discarded.

Downloads

Artifact For
Compartment-4.5.0.pkg macOS, one click, with the optional menu bar utility
Compartment-4.5.0.dmg macOS, drag to Applications
compartment-4.5.0-py3-none-any.whl pip / offline installs, any OS
compartment-4.5.0.tar.gz source distribution, packagers, air-gapped builds
pip install compartment