Module: Legion::Extensions::Agentic::Self::Reflection::Helpers::Monitors

Defined in:
lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb

Class Method Summary collapse

Class Method Details

.detect_accuracy_trend(history) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb', line 162

def detect_accuracy_trend(history)
  accuracies = history.filter_map { |h| h.dig(:prediction_engine, :confidence) }
  return [] if accuracies.size < 5

  recent = accuracies.last(5).sum / 5.0
  older = accuracies.first(5).sum / 5.0
  drop = older - recent

  return [] unless drop > Constants::PREDICTION_ACCURACY_DROP

  [ReflectionFactory.new_reflection(
    category:       :prediction_calibration,
    observation:    "Prediction accuracy trending down: #{(older * 100).round}% -> #{(recent * 100).round}%",
    severity:       ReflectionFactory.severity_for_drop(drop),
    metrics:        { trend_drop: drop, recent_avg: recent, older_avg: older },
    recommendation: :increase_curiosity
  )]
end

.monitor_cognitive_load(tick_results) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb', line 145

def monitor_cognitive_load(tick_results)
  elapsed = tick_results[:elapsed]
  budget = tick_results[:budget]
  return [] unless elapsed.is_a?(Numeric) && budget.is_a?(Numeric) && budget.positive?

  utilization = elapsed / budget
  return [] unless utilization > Constants::BUDGET_OVER_THRESHOLD

  [ReflectionFactory.new_reflection(
    category:       :cognitive_load,
    observation:    "Tick budget utilization at #{(utilization * 100).round}%",
    severity:       utilization > 1.0 ? :significant : :notable,
    metrics:        { utilization: utilization, elapsed: elapsed, budget: budget },
    recommendation: :reduce_load
  )]
end

.monitor_curiosity(tick_results) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb', line 44

def monitor_curiosity(tick_results)
  curiosity = tick_results[:working_memory_integration]
  return [] unless curiosity.is_a?(Hash)

  reflections = []

  resolution_rate = curiosity[:resolution_rate] if curiosity.key?(:resolution_rate)
  if resolution_rate.is_a?(Numeric)
    if resolution_rate < Constants::CURIOSITY_RESOLUTION_LOW
      reflections << ReflectionFactory.new_reflection(
        category:       :curiosity_effectiveness,
        observation:    "Curiosity resolution rate is low at #{(resolution_rate * 100).round}%",
        severity:       :notable,
        metrics:        { resolution_rate: resolution_rate },
        recommendation: :decrease_curiosity
      )
    elsif resolution_rate > Constants::CURIOSITY_RESOLUTION_HIGH
      reflections << ReflectionFactory.new_reflection(
        category:       :curiosity_effectiveness,
        observation:    "Curiosity resolution rate is excellent at #{(resolution_rate * 100).round}%",
        severity:       :trivial,
        metrics:        { resolution_rate: resolution_rate },
        recommendation: :celebrate_success
      )
    end
  end

  reflections
end

.monitor_emotions(tick_results) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb', line 74

def monitor_emotions(tick_results)
  emotion = tick_results[:emotional_evaluation]
  return [] unless emotion.is_a?(Hash)

  reflections = []
  stability = emotion[:stability] || emotion.dig(:momentum, :stability)

  if stability.is_a?(Numeric)
    if stability < Constants::EMOTION_INSTABILITY_THRESHOLD
      reflections << ReflectionFactory.new_reflection(
        category:       :emotional_stability,
        observation:    "Emotional state is unstable (stability: #{stability.round(2)})",
        severity:       :significant,
        metrics:        { stability: stability },
        recommendation: :stabilize_emotion
      )
    elsif stability > (1.0 - Constants::EMOTION_FLATNESS_THRESHOLD)
      reflections << ReflectionFactory.new_reflection(
        category:       :emotional_stability,
        observation:    'Emotional state is unusually flat — possible disengagement',
        severity:       :notable,
        metrics:        { stability: stability },
        recommendation: :investigate
      )
    end
  end

  reflections
end

.monitor_memory(tick_results) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb', line 126

def monitor_memory(tick_results)
  memory = tick_results[:memory_consolidation]
  return [] unless memory.is_a?(Hash)

  pruned = memory[:pruned] || 0
  total = memory[:total] || 1
  ratio = pruned.to_f / [total, 1].max

  return [] unless ratio > Constants::MEMORY_DECAY_RATIO_HIGH

  [ReflectionFactory.new_reflection(
    category:       :memory_health,
    observation:    "High memory decay ratio: #{(ratio * 100).round}% of traces pruned",
    severity:       :significant,
    metrics:        { pruned: pruned, total: total, ratio: ratio },
    recommendation: :consolidate_memory
  )]
end

.monitor_predictions(tick_results, history) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb', line 23

def monitor_predictions(tick_results, history)
  prediction = tick_results[:prediction_engine]
  return [] unless prediction.is_a?(Hash)

  reflections = []
  confidence = prediction[:confidence]

  if confidence.is_a?(Numeric) && confidence < Constants::PREDICTION_ACCURACY_LOW
    reflections << ReflectionFactory.new_reflection(
      category:       :prediction_calibration,
      observation:    "Prediction confidence is low at #{(confidence * 100).round}%",
      severity:       ReflectionFactory.severity_for_drop(1.0 - confidence),
      metrics:        { confidence: confidence },
      recommendation: :increase_curiosity
    )
  end

  reflections.concat(detect_accuracy_trend(history))
  reflections
end

.monitor_trust(tick_results, history) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb', line 104

def monitor_trust(tick_results, history)
  trust = tick_results[:action_selection]
  return [] unless trust.is_a?(Hash) && trust[:trust_score].is_a?(Numeric)

  trust_scores = history.filter_map { |h| h.dig(:action_selection, :trust_score) }
  return [] if trust_scores.size < 3

  recent_avg = trust_scores.last(5).sum / trust_scores.last(5).size.to_f
  older_avg = trust_scores.first(5).sum / trust_scores.first(5).size.to_f
  drop = older_avg - recent_avg

  return [] unless drop > Constants::TRUST_DROP_THRESHOLD

  [ReflectionFactory.new_reflection(
    category:       :trust_drift,
    observation:    "Trust scores have dropped by #{(drop * 100).round}% recently",
    severity:       ReflectionFactory.severity_for_drop(drop),
    metrics:        { drop: drop, recent_avg: recent_avg, older_avg: older_avg },
    recommendation: :rebuild_trust
  )]
end

.run_all(tick_results, metric_history) ⇒ Object



12
13
14
15
16
17
18
19
20
21
# File 'lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb', line 12

def run_all(tick_results, metric_history)
  reflections = []
  reflections.concat(monitor_predictions(tick_results, metric_history))
  reflections.concat(monitor_curiosity(tick_results))
  reflections.concat(monitor_emotions(tick_results))
  reflections.concat(monitor_trust(tick_results, metric_history))
  reflections.concat(monitor_memory(tick_results))
  reflections.concat(monitor_cognitive_load(tick_results))
  reflections
end