Fade time-sensitive memories, and rename the repo to match the product - #5
Conversation
Decay
-----
A month-old "currently implementing X" was recalled with exactly the same
confidence as a fresh fact. That is worse than forgetting: it actively
misleads the next session.
Similarity is now multiplied by 0.5 ** (age / half-life), so a memory at
its half-life must be twice the match to rank where it did when fresh:
state 7 days "currently working on…" goes stale fastest
handoff 7 days next steps are done or abandoned by then
worklog 21 days what happened still orients you, but fades
decision, project, issue, fact — never
Not everything should fade. "Bookings are stored in UTC" is as true in a
year as on the day it was written; fading it would quietly lose the
memories most worth keeping. What goes stale is the record of a moment.
Correct a decision with memory_update; let a status note fade on its own.
Combined with the relevance floor, a stale status note eventually leaves
recall without any cleanup: at 45 days a `state` memory is down to 1% of
its score while a `decision` of the same age is untouched.
Details that matter:
- Only positive similarities are scaled. Scaling a negative one moves it
toward zero, which would promote an unrelated old memory rather than
bury it.
- An unreadable timestamp decays not at all, rather than sinking a
memory no one can date.
- Future timestamps are clamped, so clock skew cannot boost a memory.
- `agent-memory list` now shows each memory's age and how far it has
faded — that is the command you run to decide what to correct, so it
should show what is going stale. `recall --no-decay` disables it.
The published evaluation is unchanged: its memories are written fresh, so
every factor is 1.0.
Rename
------
The repository was still called ai-agent-memory-scaffold while shipping
agent-memory-engine, so searching for the project by name found nothing
and the first impression was a mismatch. Renamed on GitHub — the old URL
301-redirects — and every reference updated: badges, clone instructions,
pyproject URLs, the scaffold's own README. The repository description
also still carried the "78% fewer tokens" framing the README corrected
weeks ago; it now describes what is actually claimed.
Tests 123 -> 141.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ea2f50a1da
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "handoff": 7.0, # next steps are usually done or abandoned by then | ||
| "worklog": 21.0, # what happened still orients, but fades |
There was a problem hiding this comment.
Apply decay to automatically injected session notes
The new half-lives do not affect the primary startup paths: MemoryStore.boot() unconditionally returns the latest handoff, while hooks.session_start() directly injects the latest handoff and worklog. Consequently, after a project is idle for weeks, these entries are still presented at full prominence on every boot despite their configured 7/21-day half-lives; decay currently applies only when entries pass through cosine recall.
Useful? React with 👍 / 👎.
| factors = np.array( | ||
| [decay_factor(e) for e in self._entries], dtype=np.float32 | ||
| ) |
There was a problem hiding this comment.
Refresh time-sensitive memories when revising them
When memory_update revises an old state or changes an old entry to a decaying type, _revise() preserves the original created_at; this factor therefore treats the newly corrected content as already stale and may immediately rank it near zero or filter it below min_score. The timestamp used for decay needs to reflect the revision time, such as by refreshing it for changed time-sensitive entries or tracking an updated_at value.
Useful? React with 👍 / 👎.
Two things: the last item on the roadmap, and the repo name.
Memory decay
A month-old "currently implementing multilingual support" was recalled with exactly the same confidence as a fresh fact. That's worse than forgetting — it actively misleads the next session.
Similarity is now multiplied by
0.5 ** (age / half-life):statehandoffworklogdecisionprojectissuefactNot everything should fade, and that's the design decision worth calling out. "Bookings are stored in UTC" is as true in a year as on the day it was written — fading it would quietly lose the memories most worth keeping. What goes stale is the record of a moment. Correct a decision with
memory_update; let a status note fade on its own.Combined with the relevance floor, stale notes leave recall with no cleanup required. Measured: at 45 days a
statememory is down to 1% of its score while adecisionof the same age is untouched.Four details that took thought:
agent-memory listshows age and fade. It's the command you run to decide what to correct, so it should show what's going stale.recall --no-decayranks on similarity alone. The published evaluation is unchanged — its memories are written fresh, so every factor is 1.0.Rename
The repo was still
ai-agent-memory-scaffoldwhile shippingagent-memory-engine: searching for the project by name found nothing, and the first impression was a mismatch. Renamed on GitHub (the old URL 301-redirects), with every reference updated — badges, clone instructions,pyprojectURLs, the scaffold's own README.The repository description also still carried the
"78% fewer context tokens at 93% recall"framing that the README corrected weeks ago. It now describes what's actually claimed.Tests: 123 → 141.
🤖 Generated with Claude Code