Skip to content

feat(search): optional time-decay re-ranking with durable exemption (#337) - #2157

Open
tuyenlethrive wants to merge 1 commit into
MemPalace:developfrom
tuyenlethrive:feat/time-decay
Open

feat(search): optional time-decay re-ranking with durable exemption (#337)#2157
tuyenlethrive wants to merge 1 commit into
MemPalace:developfrom
tuyenlethrive:feat/time-decay

Conversation

@tuyenlethrive

@tuyenlethrive tuyenlethrive commented Aug 5, 2026

Copy link
Copy Markdown

What

Implements optional time-decay re-ranking for search — roadmap item #337 ("recent memories surface before older ones").

When enabled, search_memories multiplies each hit's similarity by an Ebbinghaus half-life factor 0.5 ^ (age_days / half_life) (age from the drawer's filed_at), re-ranks, and truncates. A slightly weaker-matching recent memory can now outrank a stale stronger match.

Off by default

decay.enabled defaults to false — behavior is byte-identical unless turned on. All logic lives at the single retrieval choke point (search_memories), so the MCP search tool inherits it.

Config (~/.mempalace/config.json)

"decay": {
  "enabled": true,
  "half_life_days": 60,
  "durable_wings": ["memory", "identity"],
  "durable_rooms": []
}

Durable exemption

Drawers in durable_wings / durable_rooms, or tagged type: "durable" / "wisdom", skip decay (freshness forced to 1.0) so canonical notes don't sink. Exempting by wing is recommended over room, since room names are auto-assigned by the miner (a bulk import auto-labeled architecture should not be treated as canonical).

Caveats

  • Decay re-ranks within an over-fetched candidate window (n_results × 6, capped) — it reorders near-matches, it does not rescue an item far outside the similarity top-N.
  • ChromaDB can't decay server-side, so this is a client-side over-fetch + re-rank. No reindex; no schema change; missing filed_at → no decay (back-compat).

Testing

Validated before/after on a ~8k-drawer palace: recent tickets lift, stale bulk content sinks, curated memory/* notes stay put. Decay math + exemption covered by a self-check.

Files: mempalace/searcher.py, mempalace/config.py, mempalace/mcp_server.py (~90 lines).

…emPalace#337)

Add opt-in Ebbinghaus recency decay to search_memories: multiply each hit's
similarity by 0.5^(age/half_life) over the drawer's filed_at, re-rank, and
truncate. Disabled by default (decay_half_life_days=0) so existing behavior is
unchanged unless enabled via config.

- searcher.py: _parse_filed_at / _decay_multiplier / _is_durable helpers;
  over-fetch + re-rank + truncate when decay is on.
- config.py: decay.{enabled,half_life_days,durable_wings,durable_rooms}.
- mcp_server.py: tool_search reads config and passes it through.

Durable exemption keeps curated wings (memory/identity) or type=durable drawers
at full score so canonical notes don't sink. Addresses roadmap MemPalace#337.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@igorls igorls added enhancement New feature or request area/search Search and retrieval needs-rebase PR has merge conflicts with develop and needs rebase labels Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/search Search and retrieval enhancement New feature or request needs-rebase PR has merge conflicts with develop and needs rebase

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants