Module: ClaudeMemory::Recall::StaleDetector
- Defined in:
- lib/claude_memory/recall/stale_detector.rb
Overview
#35 access-based staleness — read-only query layer over the last_recalled_at column populated by Sweep::RecallTimestampRefresher.
An active fact is “stale” when:
-
It hasn’t been recalled or context-injected within ‘threshold_days` (last_recalled_at < cutoff OR last_recalled_at is NULL), AND
-
It was created before the cutoff too — freshly extracted facts aren’t dead weight, they just haven’t had a chance to be used.
No auto-deletion. The point is to surface a count and a list to the user so they can review and reject; the sweeper never acts on this.
Class Method Summary collapse
-
.stale_count(manager, threshold_days:) ⇒ Integer
Scope-agnostic count helper for the dashboard sidebar.
- .stale_dataset(store, cutoff) ⇒ Object
-
.stale_facts(manager, threshold_days:, limit: 50) ⇒ Hash
[…], global: […], total: Int.
- .stale_rows_for(store, cutoff, limit) ⇒ Object
Class Method Details
.stale_count(manager, threshold_days:) ⇒ Integer
Scope-agnostic count helper for the dashboard sidebar. Avoids materializing rows when only a count is needed.
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/claude_memory/recall/stale_detector.rb', line 42 def stale_count(manager, threshold_days:) cutoff = (Time.now.utc - threshold_days * 86_400).iso8601 count = 0 %w[project global].each do |scope| store = manager.store_if_exists(scope) next unless store count += stale_dataset(store, cutoff).count end count end |
.stale_dataset(store, cutoff) ⇒ Object
53 54 55 56 57 58 |
# File 'lib/claude_memory/recall/stale_detector.rb', line 53 def stale_dataset(store, cutoff) store.facts .where(status: "active") .where { created_at < cutoff } .where { (last_recalled_at < cutoff) | {last_recalled_at: nil} } end |
.stale_facts(manager, threshold_days:, limit: 50) ⇒ Hash
Returns […], global: […], total: Int.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/claude_memory/recall/stale_detector.rb', line 23 def stale_facts(manager, threshold_days:, limit: 50) cutoff = (Time.now.utc - threshold_days * 86_400).iso8601 result = {project: [], global: [], total: 0} %w[project global].each do |scope| store = manager.store_if_exists(scope) next unless store rows = stale_rows_for(store, cutoff, limit) result[scope.to_sym] = rows result[:total] += rows.size end result end |
.stale_rows_for(store, cutoff, limit) ⇒ Object
60 61 62 63 64 |
# File 'lib/claude_memory/recall/stale_detector.rb', line 60 def stale_rows_for(store, cutoff, limit) ds = stale_dataset(store, cutoff).order(Sequel.asc(:last_recalled_at)).order_append(:created_at) ds = ds.limit(limit) if limit > 0 ds.all end |