Class: ClaudeMemory::Observe::Reflector

Inherits:
Object
  • Object
show all
Defined in:
lib/claude_memory/observe/reflector.rb

Overview

Deterministic, free (no LLM) Reflector for the episodic observation log.

Runs inside Sweep, which fires on PreCompact and SessionEnd — Claude Code’s context-pressure lifecycle events. That is the analog of Mastra’s token-threshold-triggered reflection: “reflect when memory gets big” maps onto “reflect when the session is about to compact”, without a wall-clock timer (Claude Code has no cron hook) and without extra API cost.

Two passes, both provenance-preserving (tombstone, never hard-delete):

- dedupe: collapse near-identical active observations (same scope,
  normalized body) into the newest, linking losers via consolidated_into.
- expire_stale_info: retire info-level (🟢 / priority 3) observations
  older than the TTL to bound context size. Important (🔴) and maybe
  (🟡) are never expired — only the lowest-signal tier ages out.

Semantic consolidation (“combine related items, surface patterns”) is deliberately NOT here — it needs the LLM and lands in the Phase-4 Claude-as-reflector pass. This pass is pure Ruby so it can run shell-side in the sweep hook for free.

Defined Under Namespace

Classes: Result

Constant Summary collapse

DEFAULT_INFO_TTL_DAYS =
30

Instance Method Summary collapse

Constructor Details

#initialize(store, info_ttl_days: DEFAULT_INFO_TTL_DAYS) ⇒ Reflector

Returns a new instance of Reflector.



34
35
36
37
# File 'lib/claude_memory/observe/reflector.rb', line 34

def initialize(store, info_ttl_days: DEFAULT_INFO_TTL_DAYS)
  @store = store
  @info_ttl_days = info_ttl_days
end

Instance Method Details

#reflect!Result

Returns number of observations deduped and expired.

Returns:

  • (Result)

    number of observations deduped and expired



40
41
42
43
44
45
46
47
48
# File 'lib/claude_memory/observe/reflector.rb', line 40

def reflect!
  deduped = 0
  expired = 0
  @store.db.transaction do
    deduped = dedupe
    expired = expire_stale_info
  end
  Result.new(deduped: deduped, expired: expired)
end