Module: Legion::Extensions::Agentic::Defense::Dissonance::Runners::Dissonance

Includes:
Helpers::Lex
Included in:
Client
Defined in:
lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb

Instance Method Summary collapse

Instance Method Details

#add_belief(domain:, content:, confidence: 0.7, importance: :moderate) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb', line 13

def add_belief(domain:, content:, confidence: 0.7, importance: :moderate, **)
  unless Helpers::Constants::IMPORTANCE_WEIGHTS.key?(importance)
    return { success: false, error: :invalid_importance,
             valid: Helpers::Constants::IMPORTANCE_WEIGHTS.keys }
  end

  result  = dissonance_model.add_belief(domain: domain, content: content,
                                        confidence: confidence, importance: importance)
  belief  = result[:belief]
  new_evs = result[:new_dissonance_events]

  log.debug("[dissonance] add_belief: id=#{belief.id[0..7]} domain=#{domain} importance=#{importance} new_events=#{new_evs.size}")

  {
    success:               true,
    belief_id:             belief.id,
    domain:                domain,
    new_dissonance_events: new_evs.map(&:to_h),
    dissonance_triggered:  new_evs.any? { |ev| ev.magnitude >= Helpers::Constants::DISSONANCE_THRESHOLD }
  }
end

#beliefs_for(domain:) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb', line 97

def beliefs_for(domain:, **)
  beliefs = dissonance_model.beliefs.values.select { |b| b.domain == domain }

  log.debug("[dissonance] beliefs_for: domain=#{domain} count=#{beliefs.size}")

  {
    success: true,
    domain:  domain,
    count:   beliefs.size,
    beliefs: beliefs.map(&:to_h)
  }
end

#dissonance_statsObject



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb', line 122

def dissonance_stats(**)
  model    = dissonance_model
  snapshot = model.to_h

  domains = model.beliefs.values.map(&:domain).uniq
  domain_stresses = domains.to_h { |d| [d, model.domain_stress(d)] }

  unresolved = model.unresolved_events
  resolved   = model.events.values.select(&:resolved)

  resolution_breakdown = Helpers::Constants::RESOLUTION_STRATEGIES.to_h do |s|
    [s, resolved.count { |ev| ev.resolution_strategy == s }]
  end

  log.debug("[dissonance] stats: beliefs=#{snapshot[:total_beliefs]} " \
            "events=#{snapshot[:total_events]} stress=#{snapshot[:stress].round(3)}")

  {
    success:              true,
    stress:               snapshot[:stress],
    total_beliefs:        snapshot[:total_beliefs],
    total_events:         snapshot[:total_events],
    unresolved_count:     unresolved.size,
    resolved_count:       resolved.size,
    domain_stresses:      domain_stresses,
    resolution_breakdown: resolution_breakdown,
    above_threshold:      unresolved.any? { |ev| ev.magnitude >= Helpers::Constants::DISSONANCE_THRESHOLD }
  }
end

#dissonance_statusObject



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb', line 66

def dissonance_status(**)
  model    = dissonance_model
  snapshot = model.to_h

  log.debug("[dissonance] status: stress=#{snapshot[:stress].round(3)} " \
            "beliefs=#{snapshot[:total_beliefs]} unresolved=#{snapshot[:unresolved_count]}")

  {
    success:          true,
    stress:           snapshot[:stress],
    total_beliefs:    snapshot[:total_beliefs],
    total_events:     snapshot[:total_events],
    unresolved_count: snapshot[:unresolved_count]
  }
end

#domain_dissonance(domain:) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb', line 82

def domain_dissonance(domain:, **)
  stress = dissonance_model.domain_stress(domain)
  unresolved = dissonance_model.unresolved_events.select { |ev| ev.domain == domain }

  log.debug("[dissonance] domain_dissonance: domain=#{domain} stress=#{stress.round(3)} unresolved=#{unresolved.size}")

  {
    success:          true,
    domain:           domain,
    stress:           stress,
    unresolved_count: unresolved.size,
    events:           unresolved.map(&:to_h)
  }
end

#resolve_dissonance(event_id:, strategy: :belief_revision) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb', line 50

def resolve_dissonance(event_id:, strategy: :belief_revision, **)
  unless Helpers::Constants::RESOLUTION_STRATEGIES.include?(strategy)
    return { success: false, error: :invalid_strategy,
             valid: Helpers::Constants::RESOLUTION_STRATEGIES }
  end

  event = dissonance_model.resolve(event_id, strategy: strategy)
  if event
    log.debug("[dissonance] resolved: id=#{event_id[0..7]} strategy=#{strategy}")
    { success: true, resolved: true, strategy: strategy, event: event.to_h }
  else
    log.debug("[dissonance] resolve failed: id=#{event_id[0..7]} not_found_or_already_resolved")
    { success: false, error: :not_found_or_already_resolved }
  end
end

#unresolvedObject



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb', line 110

def unresolved(**)
  events = dissonance_model.unresolved_events

  log.debug("[dissonance] unresolved: count=#{events.size}")

  {
    success: true,
    count:   events.size,
    events:  events.map(&:to_h)
  }
end

#update_dissonanceObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb', line 35

def update_dissonance(**)
  dissonance_model.detect_contradictions
  new_stress = dissonance_model.decay
  unresolved = dissonance_model.unresolved_events

  log.debug("[dissonance] update: stress=#{new_stress.round(3)} unresolved=#{unresolved.size}")

  {
    success:          true,
    stress:           new_stress,
    unresolved_count: unresolved.size,
    above_threshold:  unresolved.any? { |ev| ev.magnitude >= Helpers::Constants::DISSONANCE_THRESHOLD }
  }
end