Skip to content

feat(palace): add boost/decay/reinforce/supersede/set_metadata to MemoryProvider (mp-migration 1/8)#19

Merged
quangdang46 merged 1 commit into
mainfrom
feat/mp-pr1-mutation-methods
Jun 3, 2026
Merged

feat(palace): add boost/decay/reinforce/supersede/set_metadata to MemoryProvider (mp-migration 1/8)#19
quangdang46 merged 1 commit into
mainfrom
feat/mp-pr1-mutation-methods

Conversation

@quangdang46
Copy link
Copy Markdown
Owner

Summary

Add 5 per-entry mutation methods to MemoryProvider so external consumers (jcode's adapter, third-party agents) have a typed API for evolving drawer state without going through add_drawer (destructive) or raw metadata keys:

Method Maps to jcode What it does
boost(&id, amount) MemoryEntry::boost_confidence bumps metadata["access_count"], updates metadata["last_accessed"]
decay(&id, amount) MemoryEntry::decay_confidence updates metadata["last_accessed"] (confidence is computed at read time)
reinforce(&id, sid, idx) MemoryEntry::reinforce appends to metadata["reinforcements"] + bumps access_count
supersede(&old, &new) MemoryEntry::supersede sets metadata["superseded_by"] and metadata["active"]=false on old
set_metadata(&id, k, v) (adapter convenience) typed single-key metadata write

Motivation

Required for the jcode → mempalace Mode C library migration (mp-migration 1/8). jcode's MemoryManager exposes all 5 of these and they're called pervasively:

  • boost_confidence on every successful retrieval (memory.rs:339)
  • decay_confidence on every negative sidecar check (memory.rs:344)
  • reinforce on every dedup hit (memory.rs:371, 382, 406, 420)
  • supersede when content changes (memory.rs:381)
  • metadata mutation for trust, source-URL, etc. (memory_agent.rs)

This is PR 1/8 in the migration series.

Change

crates/core/src/palace.rs — adds 5 default methods to MemoryProvider trait (after graph_stats, before fingerprint) and 1 private helper function default_mutate_drawer.

The where Self: Sized bound on each default method is required because the helper takes &dyn MemoryProvider (a ?Sized type). Implementers that need ?Sized Self (very rare) override; everyone else gets the default for free.

Default impls use the metadata key path (metadata["access_count"], metadata["last_accessed"], etc.) so this PR does NOT depend on PR #7. When #7 lands, the typed fields become the canonical home and the metadata path becomes a backwards-compat read shim.

Performance: O(n) on every mutation via get_drawers(None, None) + store.upsert(...). Fine for the embedvec tier (≤5 k drawers). Implementations targeting larger palaces (usearch, lancedb) should override the public methods with a direct WHERE id = ? store call — the helper is intentionally private so it can't be called from outside the crate.

Test plan

  • cargo test -p mempalace-core --lib1127 passed, 0 failed (228s)
  • cargo check -p mempalace-core clean
  • cargo fmt --check -p mempalace-core clean
  • CI green on ubuntu/macos/windows

Series status

# Title Status
6 docs(palace): document Embedder reuse on search_with_embedding merged #16
7 feat(palace): add tags/trust/access_count/reinforcements/superseded_by to Drawer open #17
8 feat(palace): add MemoryProvider::graph_stats_legacy (jcode shape) open #18
1 feat(palace): add boost/decay/reinforce/supersede/set_metadata to MemoryProvider this PR
2 feat(palace): add tag/untag/link/list_tags to MemoryProvider next
4 feat(palace): add MemoryProvider::recent for retention-ranked recall next
3 feat(palace): add MemoryScope::All and Wing/Room variants next
5 feat(palace): add ActivityEvent sink on PalaceBuilder next

🤖 Generated with Claude Code

…oryProvider

jcode's MemoryManager exposes 5 per-entry mutation methods that today
have no equivalent on the MemoryProvider trait:

  - boost(&id, amount)         — boost_confidence + touch
  - decay(&id, amount)         — decay_confidence + touch
  - reinforce(&id, sid, idx)   — push Reinforcement breadcrumb
  - supersede(&old, &new)      — mark old as superseded_by new
  - set_metadata(&id, k, v)     — typed metadata mutation

Add them as default-implemented methods on MemoryProvider. All five
use a shared helper (`default_mutate_drawer`) that does an
O(n) get-mutate-upsert dance via get_drawers + store.upsert.

The `where Self: Sized` bound on each default method is required
because the helper takes `&dyn MemoryProvider` (a ?Sized type).
Implementers that need ?Sized Self (very rare) override; everyone
else gets the default for free.

Default impls use the metadata key path (`metadata[access_count]`,
`metadata[last_accessed]`, etc.) so this PR does NOT depend on
PR #7. When #7 lands, the typed fields become the canonical home
and the metadata path becomes a backwards-compat read shim.

Performance: O(n) on every mutation. Fine for the embedvec tier
(≤5 k drawers). Implementations targeting larger palaces
(usearch, lancedb) should override the public methods with a
direct `WHERE id = ?` store call — the helper is intentionally
private so it can't be called from outside the crate.

This is PR 1/8 in the jcode → mempalace Mode C library migration
series (the trait methods piece, after the foundational PRs 6+7+8
on docs, fields, and stats).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant