feat(memory): track access_count and last_accessed_at on reads - #53
Conversation
Additive usage telemetry only. No time-based decay or run_decay_scan. Responds to maintainer feedback on PR ScottRBK#45.
|
Thanks for this — keeping it scoped to pure observability (no decay/GC) per the #45 feedback is the right call, and the atomic 1. This should reuse the existing Right now
Given that, usage tracking fits naturally as an event_bus.subscribe("memory.read", handle_access)
event_bus.subscribe("memory.queried", handle_access)This gets you three things for free that the current implementation doesn't have:
One trade-off to flag explicitly if you go this route: event bus delivery is in-process and best-effort (a handler exception or a mid-dispatch process death means the count is silently missed). Since this PR already frames the feature as best-effort telemetry, that seems like an acceptable fit — just worth being a deliberate choice rather than a surprise. 2. No test coverage for the
|
|
@bertheto hope the above makes sense - if not hit me up on discord and we can discuss further. This is a really nice feature so i am keen to add it one way or another :) |
|
Thanks. I'll move access tracking onto EventBus subscribers for memory.read / memory.queried so it reuses ACTIVITY_TRACK_READS and stays non-blocking. Best-effort delivery is fine for this. I'll also add a query_memory integration case for primary + linked IDs on that path. Note: with ACTIVITY_TRACK_READS defaulting to false, access_count stays at zero unless the flag is on. Same convention as the other read-activity events. I'll mention that in the PR description. Pushing a follow-up shortly. Ping me on Discord if anything looks off. |
Scott's PR ScottRBK#53 review: record access via memory.read / memory.queried handlers instead of inline writes. Add query_memory integration coverage and ACTIVITY_TRACK_READS=false negative test.
Impl-review follow-ups: register_access_tracking_handlers helper, assert updated_at invariants, verify QUERIED snapshot IDs for query path.
REST e2e for GET/search access_count with ACTIVITY_TRACK_READS on, plus negative gate when tracking disabled.
|
Confirmed — access tracking now runs entirely through the |
Summary
Adds read-side usage telemetry for memories:
access_countandlast_accessed_atcolumns, repositoryrecord_memory_access, and best-effort access updates via EventBus subscribers onmemory.read/memory.queried.Motivation
Maintainer feedback on #45: time-based decay is not the right product direction for upstream. This PR keeps only the observability layer (how often memories are actually returned on read paths) without any clock-based GC, confidence decay, or
run_decay_scantool.Scope
20260704_add_memory_usage_trackingrecord_memory_accessin both repositories + protocolMemory.access_count/last_accessed_at(read-only; not onMemoryUpdate)handle_memory_access_event) wired in bootstrap + e2e lifespanquery_memory/get_memoryemitmemory.queried/memory.readwhenACTIVITY_TRACK_READS=true; access counters update in the subscriberupdated_atis never mutated by access trackingOpt-in gates
access_count/last_accessed_atupdate only when both are true:ACTIVITY_ENABLED=true(event bus exists)ACTIVITY_TRACK_READS=true(defaultfalse)Delivery is best-effort async via EventBus; handler failures are logged and do not fail the read path.
Out of scope
run_decay_scan, no decay formula, noget_decay_candidatesRefs #45
Test plan
uv run pytest tests/integration/test_memory_usage_tracking.py -q(4 tests: repo direct, get_memory EventBus, query_memory primaries+linked, TRACK_READS=false negative)uv run ruff checkon touched filesrecord_memory_accessinquery_memory/get_memory