Module: Legion::Gaia::PhaseWiring

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

Overview

rubocop:disable Metrics/ModuleLength

Constant Summary collapse

PHASE_MAP =
{
  sensory_processing: { ext: :Attention, runner: :Attention, fn: :filter_signals },
  emotional_evaluation: { ext: :Emotion, runner: :Valence,       fn: :evaluate_valence },
  memory_retrieval: { ext: :Memory, runner: :Traces, fn: :retrieve_and_reinforce },
  knowledge_retrieval: { ext: :Apollo, runner: :Request, fn: :retrieve },
  identity_entropy_check: { ext: :Identity, runner: :Identity, fn: :check_entropy },
  working_memory_integration: [
    { ext: :Curiosity, runner: :Curiosity,   fn: :detect_gaps },
    { ext: :Synapse,   runner: :GaiaReport,  fn: :gaia_summary }
  ],
  procedural_check: { ext: :Coldstart, runner: :Coldstart, fn: :coldstart_progress },
  prediction_engine: { ext: :Prediction, runner: :Prediction, fn: :predict },
  mesh_interface: { ext: :Mesh, runner: :Mesh, fn: :mesh_status },
  social_cognition: { ext: :Social, runner: :Social, fn: :update_social },
  theory_of_mind: { ext: :Social, runner: :TheoryOfMind, fn: :update_theory_of_mind },
  gut_instinct: { ext: :Emotion, runner: :Gut, fn: :gut_instinct },
  action_selection: { ext: :Volition, runner: :Volition, fn: :form_intentions },
  memory_consolidation: { ext: :Memory, runner: :Consolidation, fn: :decay_cycle },
  homeostasis_regulation: { ext: :Homeostasis, runner: :Homeostasis, fn: :regulate },
  post_tick_reflection: [
    { ext: :Reflection, runner: :Reflection,  fn: :reflect },
    { ext: :Synapse,    runner: :GaiaReport,  fn: :gaia_reflection },
    { ext: :Detect,     runner: :TaskObserver, fn: :observe }
  ],

  # Dream cycle phases
  memory_audit: { ext: :Memory, runner: :Traces, fn: :retrieve_ranked },
  association_walk: { ext: :Memory, runner: :Consolidation, fn: :hebbian_link },
  contradiction_resolution: { ext: :Conflict, runner: :Conflict, fn: :active_conflicts },
  agenda_formation: { ext: :Curiosity, runner: :Curiosity, fn: :form_agenda },
  consolidation_commit: { ext: :Memory, runner: :Consolidation, fn: :migrate_tier },
  knowledge_promotion: { ext: :Apollo, runner: :Knowledge, fn: :handle_ingest },
  dream_reflection: { ext: :Reflection, runner: :Reflection, fn: :reflect },
  dream_narration: { ext: :Narrator, runner: :Narrator, fn: :narrate }
}.freeze
PHASE_ARGS =
{
  sensory_processing: lambda { |ctx|
    { signals: ctx[:signals] || [],
      active_wonders: ctx.dig(:prior_results, :agenda_formation, :agenda) || [] }
  },
  emotional_evaluation: lambda { |ctx|
    { signal: ctx[:current_signal] || {}, source_type: :ambient,
      human_observations: ctx.dig(:state, :partner_observations) || [] }
  },
  memory_retrieval: ->(_ctx) { { limit: knowledge_setting(:memory_retrieval_limit, 10) } },
  knowledge_retrieval: lambda { |ctx|
    current_signal = ctx[:signals]&.last
    memory_results = ctx.dig(:prior_results, :memory_retrieval)
    skip_threshold = knowledge_setting(:memory_skip_threshold, 0.8)

    if current_signal.nil? || (memory_results.is_a?(Hash) &&
       memory_results[:traces]&.any? { |t| t[:strength].to_f > skip_threshold })
      return { skip: true }
    end

    {
      text: current_signal[:content] || current_signal.to_s,
      limit: knowledge_setting(:retrieval_limit, 5),
      min_confidence: knowledge_setting(:retrieval_min_confidence, 0.3),
      tags: current_signal[:tags]
    }
  },
  identity_entropy_check: ->(_ctx) { {} },
  procedural_check: ->(_ctx) { {} },
  prediction_engine: ->(ctx) { { mode: :functional_mapping, context: ctx[:prior_results] || {} } },
  mesh_interface: ->(_ctx) { {} },
  social_cognition: lambda { |ctx|
    { tick_results: ctx[:prior_results] || {},
      human_observations: ctx.dig(:state, :partner_observations) || [] }
  },
  theory_of_mind: lambda { |ctx|
    { tick_results: ctx[:prior_results] || {},
      human_observations: ctx.dig(:state, :partner_observations) || [] }
  },
  gut_instinct: ->(ctx) { { valences: ctx[:valences] || [] } },
  action_selection: ->(ctx) { { tick_results: ctx[:prior_results] || {}, cognitive_state: {} } },
  working_memory_integration: ->(ctx) { { prior_results: ctx[:prior_results] || {} } },
  memory_consolidation: ->(_ctx) { {} },
  homeostasis_regulation: ->(ctx) { { tick_results: ctx[:prior_results] || {} } },
  post_tick_reflection: lambda { |ctx|
    { tick_results: ctx[:prior_results] || {}, since: ctx.dig(:state, :last_observer_tick) }
  },
  memory_audit: ->(_ctx) { { limit: knowledge_setting(:memory_audit_limit, 20) } },
  association_walk: lambda { |ctx|
    audit = ctx.dig(:prior_results, :memory_audit)
    traces = audit.is_a?(Hash) ? audit[:traces] : nil
    traces = [] unless traces.is_a?(Array) && traces.size >= 2
    { trace_id_a: traces.dig(0, :trace_id), trace_id_b: traces.dig(1, :trace_id) }
  },
  contradiction_resolution: ->(_ctx) { {} },
  agenda_formation: ->(_ctx) { {} },
  consolidation_commit: ->(_ctx) { {} },
  knowledge_promotion: lambda { |ctx|
    content = build_promotion_content(ctx[:prior_results] || {})
    return { skip: true } if content.nil?

    { content: content, content_type: :observation, tags: %w[dream_cycle promoted],
      source_agent: 'gaia', source_channel: 'dream_cycle' }
  },
  dream_reflection: ->(ctx) { { tick_results: ctx[:prior_results] || {} } },
  dream_narration: lambda { |ctx|
    { tick_results: ctx[:prior_results] || {}, cognitive_state: { source: :dream } }
  }
}.freeze

Class Method Summary collapse

Class Method Details

.build_phase_handlers(runner_instances) ⇒ Object



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/legion/gaia/phase_wiring.rb', line 199

def build_phase_handlers(runner_instances)
  handlers = {}

  PHASE_MAP.each do |phase, value|
    next if value.nil?

    maps = mappings_for(value)
    active = maps.filter_map do |mapping|
      instance_key = :"#{mapping[:ext]}_#{mapping[:runner]}"
      instance = runner_instances[instance_key]
      next unless instance

      { instance: instance, fn: mapping[:fn] }
    end
    next if active.empty?

    arg_builder = PHASE_ARGS[phase]

    handlers[phase] = lambda { |state:, signals:, prior_results:|
      ctx = { state: state, signals: signals, prior_results: prior_results,
              current_signal: signals&.last, valences: collect_valences(prior_results) }
      args = arg_builder ? arg_builder.call(ctx) : {}
      results = active.map { |h| h[:instance].send(h[:fn], **args) }
      results.size == 1 ? results.first : results
    }
  end

  handlers
end

.build_promotion_content(prior_results) ⇒ Object



247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/legion/gaia/phase_wiring.rb', line 247

def build_promotion_content(prior_results)
  parts = [
    extract_association(prior_results[:association_walk]),
    extract_conflicts(prior_results[:contradiction_resolution]),
    extract_consolidation(prior_results[:consolidation_commit]),
    extract_reflection(prior_results[:dream_reflection]),
    extract_agenda(prior_results[:agenda_formation])
  ].compact

  return nil if parts.empty?

  "Dream cycle synthesis: #{parts.join('. ')}"
end

.collect_valences(prior_results) ⇒ Object



292
293
294
295
296
297
298
299
# File 'lib/legion/gaia/phase_wiring.rb', line 292

def collect_valences(prior_results)
  return [] unless prior_results.is_a?(Hash)

  valence_result = prior_results[:emotional_evaluation]
  return [] unless valence_result.is_a?(Hash) && valence_result[:valence]

  [valence_result[:valence]]
end

.core_library_runner(ext_sym, runner_sym) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/legion/gaia/phase_wiring.rb', line 134

def core_library_runner(ext_sym, runner_sym)
  return nil unless Legion.const_defined?(ext_sym, false)

  mod = Legion.const_get(ext_sym, false)
  return nil unless mod.is_a?(Module)

  # Check flat runners (e.g., Legion::Apollo::Runners::Request)
  if mod.const_defined?(:Runners, false)
    runners_mod = mod.const_get(:Runners, false)
    return runners_mod.const_get(runner_sym, false) if runners_mod.const_defined?(runner_sym, false)
  end

  nil
rescue StandardError
  nil
end

.deep_agentic_runner(ext_sym, runner_sym) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/legion/gaia/phase_wiring.rb', line 151

def deep_agentic_runner(ext_sym, runner_sym)
  return nil unless Legion::Extensions.const_defined?(:Agentic, false)

  agentic = Legion::Extensions::Agentic
  agentic.constants(false).each do |domain_const|
    domain_mod = agentic.const_get(domain_const, false)
    next unless domain_mod.is_a?(Module) && domain_mod.const_defined?(ext_sym, false)

    sub_mod = domain_mod.const_get(ext_sym, false)
    next unless sub_mod.is_a?(Module) && sub_mod.const_defined?(:Runners, false)

    runners_mod = sub_mod.const_get(:Runners, false)
    return runners_mod.const_get(runner_sym, false) if runners_mod.const_defined?(runner_sym, false)
  end
  nil
end

.discover_available_extensionsObject



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/legion/gaia/phase_wiring.rb', line 229

def discover_available_extensions
  available = {}

  PHASE_MAP.each_value do |value|
    next if value.nil?

    mappings_for(value).each do |mapping|
      key = :"#{mapping[:ext]}_#{mapping[:runner]}"
      next if available.key?(key)

      runner_class = resolve_runner_class(mapping[:ext], mapping[:runner])
      available[key] = { ext: mapping[:ext], runner: mapping[:runner], loaded: !runner_class.nil? }
    end
  end

  available
end

.extract_agenda(agenda) ⇒ Object



285
286
287
288
289
290
# File 'lib/legion/gaia/phase_wiring.rb', line 285

def extract_agenda(agenda)
  return unless agenda.is_a?(Hash) && agenda[:agenda].is_a?(Array) && agenda[:agenda].any?

  items = agenda[:agenda].first(3).map { |a| a.is_a?(Hash) ? (a[:question] || a[:topic]) : a.to_s }
  "Agenda: #{items.compact.join('; ')}" if items.compact.any?
end

.extract_association(assoc) ⇒ Object



261
262
263
264
265
# File 'lib/legion/gaia/phase_wiring.rb', line 261

def extract_association(assoc)
  return unless assoc.is_a?(Hash) && assoc[:linked]

  "Association: linked trace #{assoc[:trace_id_a]} to #{assoc[:trace_id_b]}"
end

.extract_conflicts(conflicts) ⇒ Object



267
268
269
270
271
# File 'lib/legion/gaia/phase_wiring.rb', line 267

def extract_conflicts(conflicts)
  return unless conflicts.is_a?(Hash) && conflicts[:resolved].to_i.positive?

  "Resolved #{conflicts[:resolved]} contradiction(s)"
end

.extract_consolidation(consol) ⇒ Object



273
274
275
276
277
# File 'lib/legion/gaia/phase_wiring.rb', line 273

def extract_consolidation(consol)
  return unless consol.is_a?(Hash) && consol[:migrated].to_i.positive?

  "Consolidated #{consol[:migrated]} memory trace(s) to long-term storage"
end

.extract_reflection(reflection) ⇒ Object



279
280
281
282
283
# File 'lib/legion/gaia/phase_wiring.rb', line 279

def extract_reflection(reflection)
  return unless reflection.is_a?(Hash) && reflection[:insight].is_a?(String) && !reflection[:insight].empty?

  "Insight: #{reflection[:insight][0, 500]}"
end

.flat_runner(ext_mod, runner_sym) ⇒ Object



177
178
179
180
181
182
# File 'lib/legion/gaia/phase_wiring.rb', line 177

def flat_runner(ext_mod, runner_sym)
  return nil unless ext_mod.const_defined?(:Runners, false)

  runners_mod = ext_mod.const_get(:Runners, false)
  runners_mod.const_get(runner_sym, false) if runners_mod.const_defined?(runner_sym, false)
end

.knowledge_setting(key, default) ⇒ Object



114
115
116
117
118
119
120
# File 'lib/legion/gaia/phase_wiring.rb', line 114

def knowledge_setting(key, default)
  return default unless defined?(Legion::Settings) && !Legion::Settings[:gaia].nil?

  Legion::Settings[:gaia].dig(:knowledge, key) || default
rescue StandardError
  default
end

.locate_ext_mod(ext_sym) ⇒ Object



168
169
170
171
172
173
174
175
# File 'lib/legion/gaia/phase_wiring.rb', line 168

def locate_ext_mod(ext_sym)
  if Legion::Extensions.const_defined?(ext_sym, false)
    Legion::Extensions.const_get(ext_sym, false)
  elsif Legion::Extensions.const_defined?(:Agentic, false) &&
        Legion::Extensions::Agentic.const_defined?(ext_sym, false)
    Legion::Extensions::Agentic.const_get(ext_sym, false)
  end
end

.mappings_for(value) ⇒ Object



195
196
197
# File 'lib/legion/gaia/phase_wiring.rb', line 195

def mappings_for(value)
  value.is_a?(Array) ? value : [value]
end

.resolve_runner_class(ext_sym, runner_sym) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
# File 'lib/legion/gaia/phase_wiring.rb', line 122

def resolve_runner_class(ext_sym, runner_sym)
  # Check core library namespace first (e.g., Legion::Apollo)
  core = core_library_runner(ext_sym, runner_sym)
  return core if core

  # Then check extensions namespace
  ext_mod = locate_ext_mod(ext_sym)
  return flat_runner(ext_mod, runner_sym) || subdomain_runner(ext_mod, runner_sym) if ext_mod

  deep_agentic_runner(ext_sym, runner_sym)
end

.subdomain_runner(ext_mod, runner_sym) ⇒ Object



184
185
186
187
188
189
190
191
192
193
# File 'lib/legion/gaia/phase_wiring.rb', line 184

def subdomain_runner(ext_mod, runner_sym)
  ext_mod.constants(false).each do |sub_const|
    sub_mod = ext_mod.const_get(sub_const, false)
    next unless sub_mod.is_a?(Module) && sub_mod.const_defined?(:Runners, false)

    runners_mod = sub_mod.const_get(:Runners, false)
    return runners_mod.const_get(runner_sym, false) if runners_mod.const_defined?(runner_sym, false)
  end
  nil
end