feat(palace): promote tags/trust/access_count/last_accessed/reinforcements/superseded_by/active to first-class Drawer fields (mp-migration 7/8)#17
Closed
quangdang46 wants to merge 1 commit into
Conversation
…ments/superseded_by/active to first-class Drawer fields
The new fields mirror values previously stored only in the
`metadata` HashMap under the keys 'tags', 'trust', 'access_count',
'last_accessed', 'reinforcements', 'superseded_by', 'active'. They
are now typed first-class fields for:
- type-safe access from the upcoming MemoryProvider trait methods
(boost/decay/reinforce/supersede/tag/link in mp-migration 1+2/8)
- clean serde round-trip without manual value extraction
- query-builder support (drawer.tags([...]).trust('high'))
`#[serde(default, skip_serializing_if = ...)]` on every new field
keeps backwards compatibility — drawers serialised before this change
still load cleanly. The reverse direction (writing the typed field)
is handled by `Drawer::migrate_metadata` which is idempotent and
safe to call repeatedly; it lifts legacy metadata keys into typed
fields when those fields are still at their default value, and
cleans the metadata HashMap so the source-of-truth is unambiguous.
`Reinforcement` is promoted to a pub struct in palace.rs (mirrors
jcode's `memory_types::Reinforcement`). `DrawerId` is reused for
`superseded_by` to keep the ID type consistent across the API.
Existing call sites in:
- crates/core/src/palace/store/usearch_sqlite.rs (Drawer literal x2)
- crates/core/src/layers.rs:652 (Drawer literal x1)
updated to initialise the new fields with their defaults.
This is PR 7/8 in the jcode → mempalace Mode C library migration
series. Required for PR 1 (mutation methods) and PR 2 (tag/link).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jun 3, 2026
Merged
Owner
Author
|
Code already merged via PR #24 (cherry-picked). Closing. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Promote 7 fields previously stored only in
Drawer::metadatato first-class typed fields:tagsVec<String>"tags"trustOption<String>"trust"access_countu64"access_count"last_accessedOption<DateTime<Utc>>"last_accessed"reinforcementsVec<Reinforcement>(new pub struct)"reinforcements"superseded_byOption<DrawerId>"superseded_by"activebool(defaulttrue)"active"Motivation
The upcoming
MemoryProvidertrait methods (PRs 1 + 2 of the migration series) need typed access to these fields:boost(&id, amount)/decay(&id, amount)→ mutateaccess_count+last_accessedreinforce(&id, session_id, message_index)→ push toreinforcementssupersede(&old, &new)→ setsuperseded_byon old,active = falseon oldtag(&id, tag)/untag(&id, tag)→ mutatetagslink(&from, &to, weight)→ doesn't touch these directly but uses same lifecycleWithout typed fields, every trait method would have to do
metadata.insert("access_count", json!(...))round-trips, which is lossy (no type checking), error-prone (typos in key strings), and harder to test.This is PR 7/8 in the jcode → mempalace Mode C library migration series.
Change
crates/core/src/palace.rs:Drawerstruct, each with#[serde(default, skip_serializing_if = …)]for backwards compatpub struct Reinforcement { session_id, message_index, timestamp }Drawer::newinitializes all 7 new fields to defaultsDrawer::tags(Vec<String>)andDrawer::trust(&str)Drawer::migrate_metadata(&mut self)— idempotent, lifts legacy metadata keys to typed fields and cleans the HashMapcrates/core/src/palace/store/usearch_sqlite.rs:Drawer { … }literals updated to initialize the 7 new fields (the only pre-existing call sites in the codebase)crates/core/src/layers.rs:Drawer { … }literal updated to initialize the 7 new fieldsTests (
crates/core/src/palace.rs:tests):drawer_new_field_defaults— all 7 default to expected valuesdrawer_typed_builders—.tags([...]).trust("high")workdrawer_legacy_serde_load— old JSON with metadata-only fields loads cleanlydrawer_migrate_metadata— legacy keys lifted to typed fieldsdrawer_migrate_metadata_idempotent— safe to call twicedrawer_new_field_serde_roundtrip— typed fields survive serdeBackwards compatibility
Drawers serialised before this change continue to load:
tags/trust/etc. are absent from the JSON →#[serde(default)]fills themmetadata["tags"]value remains in the HashMap untilmigrate_metadatais calledTest plan
cargo test -p mempalace-core --lib→ 1133 passed, 0 failed (1499s, includes 7 new tests)cargo check -p mempalace-corecleancargo fmt --check -p mempalace-corecleanSeries
docs/mp-pr6-document-embedder-reusefeat/mp-pr7-drawer-fieldsfeat/mp-pr8-graph-stats-legacyfeat/mp-pr1-mutation-methodsfeat/mp-pr2-tag-linkfeat/mp-pr4-recentfeat/mp-pr3-scope-variantsfeat/mp-pr5-activity-sink🤖 Generated with Claude Code