Class: SwarmSDK::V3::Memory::ExposureTracker

Inherits:
Object
  • Object
show all
Defined in:
lib/swarm_sdk/v3/memory/exposure_tracker.rb

Overview

Calculates exposure scores for memory cards

Exposure score = α·frequency + β·recency + γ·dwell (weighted sum)

Uses an additive formula so each signal contributes independently. A multiplicative formula would zero out the score whenever any single factor is zero (e.g., a fresh card with access_count=0), which would make every new card an immediate compression candidate.

Used by the compressor to decide which cards get lossy compression first. Low-exposure cards are candidates for compression or eviction.

Examples:

tracker = ExposureTracker.new(adapter)
score = tracker.exposure_score(card)

Constant Summary collapse

DEFAULT_FREQUENCY_WEIGHT =

Default weights for the additive exposure formula

0.4
DEFAULT_RECENCY_WEIGHT =
0.4
DEFAULT_DWELL_WEIGHT =
0.2
DEFAULT_RECENCY_HALF_LIFE =

Default half-life for recency decay in seconds (7 days)

7 * 24 * 3600

Instance Method Summary collapse

Constructor Details

#initialize(adapter, frequency_weight: nil, recency_weight: nil, dwell_weight: nil, recency_half_life: nil) ⇒ ExposureTracker

Returns a new instance of ExposureTracker.

Parameters:

  • adapter (Adapters::Base)

    Storage adapter

  • frequency_weight (Float) (defaults to: nil)

    Weight for frequency component (α)

  • recency_weight (Float) (defaults to: nil)

    Weight for recency component (β)

  • dwell_weight (Float) (defaults to: nil)

    Weight for dwell component (γ)

  • recency_half_life (Integer) (defaults to: nil)

    Half-life for recency decay in seconds



35
36
37
38
39
40
41
42
# File 'lib/swarm_sdk/v3/memory/exposure_tracker.rb', line 35

def initialize(adapter, frequency_weight: nil, recency_weight: nil, dwell_weight: nil, recency_half_life: nil)
  @adapter = adapter
  config = Configuration.instance
  @frequency_weight = frequency_weight || config.exposure_frequency_weight
  @recency_weight = recency_weight || config.exposure_recency_weight
  @dwell_weight = dwell_weight || config.exposure_dwell_weight
  @recency_half_life = recency_half_life || config.exposure_recency_half_life
end

Instance Method Details

#exposure_score(card) ⇒ Float

Calculate exposure score for a card

Combines three signals additively:

  • Frequency: log(1 + access_count) — dampens high-access cards

  • Recency: exponential decay from last access time

  • Dwell: accumulated time in working context

E = α·log(1 + access_count) + β·recency(last_accessed) + γ·dwell

Examples:

score = tracker.exposure_score(card)
# High score: frequently accessed, recently used, high dwell
# Low score: rarely accessed, long ago, low dwell

Parameters:

  • card (Card)

    Card to score

Returns:

  • (Float)

    Exposure score (higher = more exposed)



60
61
62
63
64
65
66
67
68
# File 'lib/swarm_sdk/v3/memory/exposure_tracker.rb', line 60

def exposure_score(card)
  frequency = Math.log(1 + card.access_count)
  recency = recency_factor(card.last_accessed)
  dwell = card.dwell

  @frequency_weight * frequency +
    @recency_weight * recency +
    @dwell_weight * dwell
end

#low_exposure_cards(threshold: 1.0) ⇒ Array<Card>

Find cards with low exposure (candidates for compression)

Parameters:

  • threshold (Float) (defaults to: 1.0)

    Maximum exposure score

Returns:

  • (Array<Card>)

    Low-exposure cards



83
84
85
86
87
# File 'lib/swarm_sdk/v3/memory/exposure_tracker.rb', line 83

def low_exposure_cards(threshold: 1.0)
  rank_by_exposure
    .select { |entry| entry[:score] < threshold }
    .map { |entry| entry[:card] }
end

#rank_by_exposureArray<Hash>

Rank all cards by exposure score (ascending = least exposed first)

Returns:

  • (Array<Hash>)

    Array of { card:, score: } sorted ascending



73
74
75
76
77
# File 'lib/swarm_sdk/v3/memory/exposure_tracker.rb', line 73

def rank_by_exposure
  @adapter.list_cards.map do |card|
    { card: card, score: exposure_score(card) }
  end.sort_by { |entry| entry[:score] }
end