Module: Legion::Gaia::PartnerModel

Defined in:
lib/legion/gaia/partner_model.rb

Constant Summary collapse

MAX_WORKING_MEMORY_SLOTS =

Working-memory slot competition (ยง12.4). Only filter/transform/autonomous tier synapses compete โ€” observe-tier synapses are tracked separately via observe_mode_entries and never consume working-memory slots.

7
PREFERENCE_SOURCE_CONFIDENCE =

Source-confidence defaults for preference candidates.

{
  explicit: 1.0,
  preference_learning: 0.75,
  llm_inference: 0.65,
  observation: 0.55
}.freeze

Class Method Summary collapse

Class Method Details

.autonomy_tier(confidence) ⇒ Object



125
126
127
# File 'lib/legion/gaia/partner_model.rb', line 125

def autonomy_tier(confidence)
  Legion::Gaia::BehavioralSynapse::Math.autonomy_mode(confidence.to_f)
end

.build(identity:, synapses: nil, traces: nil, preferences: nil) ⇒ Array<Hash>

Build the working-memory slot array for this identity.

Parameters:

  • identity (String, Symbol)

    the partner identity key

  • synapses (Array, nil) (defaults to: nil)

    BehavioralSynapse entries; fetched from store if nil

  • traces (Array, nil) (defaults to: nil)

    episodic/semantic trace hashes from lex-agentic-memory

  • preferences (Array, nil) (defaults to: nil)

    PreferenceProfile directives with :source and :content

Returns:

  • (Array<Hash>)

    at most MAX_WORKING_MEMORY_SLOTS slot hashes, sorted by score desc



28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/legion/gaia/partner_model.rb', line 28

def build(identity:, synapses: nil, traces: nil, preferences: nil)
  identity_str = identity.to_s
  candidates = []
  candidates.concat(synapse_candidates(identity: identity_str, synapses: synapses))
  candidates.concat(trace_candidates(traces))
  candidates.concat(preference_candidates(preferences))

  max_slots = Legion::Gaia.settings&.dig(:partner_model, :max_slots) || MAX_WORKING_MEMORY_SLOTS

  candidates
    .sort_by { |c| -slot_score(c) }
    .first(max_slots)
    .map { |c| c.slice(:type, :domain, :content, :strength, :source_id, :autonomy_mode) }
end

.observe_mode_entries(identity:) ⇒ Array<Hash>

Returns observe-tier synapses for this identity (transparency surface โ€” not in working memory).

Parameters:

  • identity (String, Symbol)

Returns:

  • (Array<Hash>)


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/legion/gaia/partner_model.rb', line 47

def observe_mode_entries(identity:)
  identity_str = identity.to_s
  all = Legion::Gaia::BehavioralSynapse.all_for(identity: identity_str)
  all.select { |entry| autonomy_tier(entry[:confidence]) == :observe }
     .map do |entry|
       {
         type: :synapse,
         domain: entry[:domain],
         content: entry[:directive],
         strength: entry[:confidence],
         source_id: entry[:id],
         autonomy_mode: :observe
       }
     end
end

.preference_candidates(preferences) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/legion/gaia/partner_model.rb', line 101

def preference_candidates(preferences)
  return [] unless preferences.is_a?(Array)

  preferences.map do |pref|
    source_key = pref[:source].to_s.to_sym
    strength = PREFERENCE_SOURCE_CONFIDENCE.fetch(source_key, 0.55)
    {
      type: :preference,
      domain: pref[:domain].to_s,
      content: pref[:content] || pref[:directive],
      strength: strength,
      emotional_intensity: 0.3,
      source_id: pref[:id],
      autonomy_mode: nil
    }
  end
end

.slot_score(candidate) ⇒ Object



119
120
121
122
123
# File 'lib/legion/gaia/partner_model.rb', line 119

def slot_score(candidate)
  strength  = candidate[:strength].to_f
  intensity = candidate[:emotional_intensity].to_f
  strength * (1.0 + intensity)
end

.synapse_candidates(identity:, synapses:) ⇒ Object

--- private helpers ---



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/legion/gaia/partner_model.rb', line 65

def synapse_candidates(identity:, synapses:)
  entries = synapses || Legion::Gaia::BehavioralSynapse.all_for(identity: identity)
  entries.filter_map do |entry|
    tier = autonomy_tier(entry[:confidence])
    next unless %i[filter transform autonomous].include?(tier)

    {
      type: :synapse,
      domain: entry[:domain],
      content: entry[:directive],
      strength: entry[:confidence].to_f,
      emotional_intensity: entry[:emotional_intensity].to_f,
      source_id: entry[:id],
      autonomy_mode: tier
    }
  end
end

.trace_candidates(traces) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/legion/gaia/partner_model.rb', line 83

def trace_candidates(traces)
  return [] unless traces.is_a?(Array)

  traces.map do |trace|
    strength = (trace[:strength] || trace[:confidence]).to_f
    intensity = (trace[:emotional_intensity] || 0.5).to_f
    {
      type: :trace,
      domain: Array(trace[:domain_tags]).first.to_s,
      content: trace[:content_payload],
      strength: strength,
      emotional_intensity: intensity,
      source_id: trace[:trace_id],
      autonomy_mode: nil
    }
  end
end