lex-agentic-defense 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +12 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +21 -0
  5. data/README.md +13 -0
  6. data/lex-agentic-defense.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/defense/avalanche/client.rb +22 -0
  8. data/lib/legion/extensions/agentic/defense/avalanche/helpers/avalanche_engine.rb +132 -0
  9. data/lib/legion/extensions/agentic/defense/avalanche/helpers/cascade.rb +76 -0
  10. data/lib/legion/extensions/agentic/defense/avalanche/helpers/constants.rb +44 -0
  11. data/lib/legion/extensions/agentic/defense/avalanche/helpers/snowpack.rb +86 -0
  12. data/lib/legion/extensions/agentic/defense/avalanche/runners/cognitive_avalanche.rb +75 -0
  13. data/lib/legion/extensions/agentic/defense/avalanche/version.rb +13 -0
  14. data/lib/legion/extensions/agentic/defense/avalanche.rb +22 -0
  15. data/lib/legion/extensions/agentic/defense/bias/actors/update.rb +45 -0
  16. data/lib/legion/extensions/agentic/defense/bias/client.rb +30 -0
  17. data/lib/legion/extensions/agentic/defense/bias/helpers/bias_detector.rb +107 -0
  18. data/lib/legion/extensions/agentic/defense/bias/helpers/bias_event.rb +44 -0
  19. data/lib/legion/extensions/agentic/defense/bias/helpers/bias_store.rb +84 -0
  20. data/lib/legion/extensions/agentic/defense/bias/helpers/constants.rb +28 -0
  21. data/lib/legion/extensions/agentic/defense/bias/runners/bias.rb +151 -0
  22. data/lib/legion/extensions/agentic/defense/bias/version.rb +13 -0
  23. data/lib/legion/extensions/agentic/defense/bias.rb +20 -0
  24. data/lib/legion/extensions/agentic/defense/confabulation/actors/decay.rb +45 -0
  25. data/lib/legion/extensions/agentic/defense/confabulation/client.rb +28 -0
  26. data/lib/legion/extensions/agentic/defense/confabulation/helpers/claim.rb +67 -0
  27. data/lib/legion/extensions/agentic/defense/confabulation/helpers/confabulation_engine.rb +120 -0
  28. data/lib/legion/extensions/agentic/defense/confabulation/helpers/constants.rb +29 -0
  29. data/lib/legion/extensions/agentic/defense/confabulation/runners/confabulation.rb +74 -0
  30. data/lib/legion/extensions/agentic/defense/confabulation/version.rb +13 -0
  31. data/lib/legion/extensions/agentic/defense/confabulation.rb +19 -0
  32. data/lib/legion/extensions/agentic/defense/dissonance/client.rb +32 -0
  33. data/lib/legion/extensions/agentic/defense/dissonance/helpers/belief.rb +46 -0
  34. data/lib/legion/extensions/agentic/defense/dissonance/helpers/constants.rb +27 -0
  35. data/lib/legion/extensions/agentic/defense/dissonance/helpers/dissonance_event.rb +52 -0
  36. data/lib/legion/extensions/agentic/defense/dissonance/helpers/dissonance_model.rb +159 -0
  37. data/lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb +163 -0
  38. data/lib/legion/extensions/agentic/defense/dissonance/version.rb +13 -0
  39. data/lib/legion/extensions/agentic/defense/dissonance.rb +20 -0
  40. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/actors/update.rb +45 -0
  41. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/client.rb +27 -0
  42. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/claim.rb +78 -0
  43. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/client.rb +23 -0
  44. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/constants.rb +37 -0
  45. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/source.rb +64 -0
  46. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/vigilance_engine.rb +195 -0
  47. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/runners/epistemic_vigilance.rb +91 -0
  48. data/lib/legion/extensions/agentic/defense/epistemic_vigilance/version.rb +13 -0
  49. data/lib/legion/extensions/agentic/defense/epistemic_vigilance.rb +20 -0
  50. data/lib/legion/extensions/agentic/defense/erosion/client.rb +23 -0
  51. data/lib/legion/extensions/agentic/defense/erosion/helpers/channel.rb +84 -0
  52. data/lib/legion/extensions/agentic/defense/erosion/helpers/constants.rb +47 -0
  53. data/lib/legion/extensions/agentic/defense/erosion/helpers/erosion_engine.rb +134 -0
  54. data/lib/legion/extensions/agentic/defense/erosion/helpers/formation.rb +100 -0
  55. data/lib/legion/extensions/agentic/defense/erosion/runners/cognitive_erosion.rb +93 -0
  56. data/lib/legion/extensions/agentic/defense/erosion/version.rb +13 -0
  57. data/lib/legion/extensions/agentic/defense/erosion.rb +21 -0
  58. data/lib/legion/extensions/agentic/defense/error_monitoring/actors/tick.rb +45 -0
  59. data/lib/legion/extensions/agentic/defense/error_monitoring/client.rb +28 -0
  60. data/lib/legion/extensions/agentic/defense/error_monitoring/helpers/constants.rb +50 -0
  61. data/lib/legion/extensions/agentic/defense/error_monitoring/helpers/error_monitor.rb +174 -0
  62. data/lib/legion/extensions/agentic/defense/error_monitoring/helpers/error_signal.rb +60 -0
  63. data/lib/legion/extensions/agentic/defense/error_monitoring/runners/error_monitoring.rb +102 -0
  64. data/lib/legion/extensions/agentic/defense/error_monitoring/version.rb +13 -0
  65. data/lib/legion/extensions/agentic/defense/error_monitoring.rb +19 -0
  66. data/lib/legion/extensions/agentic/defense/extinction/actors/protocol_monitor.rb +45 -0
  67. data/lib/legion/extensions/agentic/defense/extinction/client.rb +27 -0
  68. data/lib/legion/extensions/agentic/defense/extinction/helpers/levels.rb +43 -0
  69. data/lib/legion/extensions/agentic/defense/extinction/helpers/protocol_state.rb +125 -0
  70. data/lib/legion/extensions/agentic/defense/extinction/local_migrations/20260316000040_create_extinction_state.rb +13 -0
  71. data/lib/legion/extensions/agentic/defense/extinction/runners/extinction.rb +130 -0
  72. data/lib/legion/extensions/agentic/defense/extinction/version.rb +13 -0
  73. data/lib/legion/extensions/agentic/defense/extinction.rb +25 -0
  74. data/lib/legion/extensions/agentic/defense/friction/client.rb +15 -0
  75. data/lib/legion/extensions/agentic/defense/friction/helpers/constants.rb +38 -0
  76. data/lib/legion/extensions/agentic/defense/friction/helpers/friction_engine.rb +131 -0
  77. data/lib/legion/extensions/agentic/defense/friction/helpers/state_transition.rb +73 -0
  78. data/lib/legion/extensions/agentic/defense/friction/runners/cognitive_friction.rb +82 -0
  79. data/lib/legion/extensions/agentic/defense/friction/version.rb +13 -0
  80. data/lib/legion/extensions/agentic/defense/friction.rb +19 -0
  81. data/lib/legion/extensions/agentic/defense/immune_response/client.rb +19 -0
  82. data/lib/legion/extensions/agentic/defense/immune_response/helpers/antibody.rb +72 -0
  83. data/lib/legion/extensions/agentic/defense/immune_response/helpers/antigen.rb +87 -0
  84. data/lib/legion/extensions/agentic/defense/immune_response/helpers/constants.rb +75 -0
  85. data/lib/legion/extensions/agentic/defense/immune_response/helpers/immune_engine.rb +184 -0
  86. data/lib/legion/extensions/agentic/defense/immune_response/helpers/immune_response.rb +76 -0
  87. data/lib/legion/extensions/agentic/defense/immune_response/runners/cognitive_immune_response.rb +114 -0
  88. data/lib/legion/extensions/agentic/defense/immune_response/version.rb +13 -0
  89. data/lib/legion/extensions/agentic/defense/immune_response.rb +21 -0
  90. data/lib/legion/extensions/agentic/defense/immunology/client.rb +29 -0
  91. data/lib/legion/extensions/agentic/defense/immunology/helpers/antibody.rb +55 -0
  92. data/lib/legion/extensions/agentic/defense/immunology/helpers/constants.rb +43 -0
  93. data/lib/legion/extensions/agentic/defense/immunology/helpers/immune_engine.rb +187 -0
  94. data/lib/legion/extensions/agentic/defense/immunology/helpers/threat.rb +67 -0
  95. data/lib/legion/extensions/agentic/defense/immunology/runners/cognitive_immunology.rb +92 -0
  96. data/lib/legion/extensions/agentic/defense/immunology/version.rb +13 -0
  97. data/lib/legion/extensions/agentic/defense/immunology.rb +20 -0
  98. data/lib/legion/extensions/agentic/defense/phantom/client.rb +29 -0
  99. data/lib/legion/extensions/agentic/defense/phantom/helpers/constants.rb +54 -0
  100. data/lib/legion/extensions/agentic/defense/phantom/helpers/phantom_engine.rb +106 -0
  101. data/lib/legion/extensions/agentic/defense/phantom/helpers/phantom_limb.rb +103 -0
  102. data/lib/legion/extensions/agentic/defense/phantom/helpers/phantom_signal.rb +40 -0
  103. data/lib/legion/extensions/agentic/defense/phantom/runners/cognitive_phantom.rb +79 -0
  104. data/lib/legion/extensions/agentic/defense/phantom/version.rb +13 -0
  105. data/lib/legion/extensions/agentic/defense/phantom.rb +21 -0
  106. data/lib/legion/extensions/agentic/defense/quicksand/client.rb +15 -0
  107. data/lib/legion/extensions/agentic/defense/quicksand/helpers/constants.rb +48 -0
  108. data/lib/legion/extensions/agentic/defense/quicksand/helpers/pit.rb +82 -0
  109. data/lib/legion/extensions/agentic/defense/quicksand/helpers/quicksand_engine.rb +137 -0
  110. data/lib/legion/extensions/agentic/defense/quicksand/helpers/trap.rb +101 -0
  111. data/lib/legion/extensions/agentic/defense/quicksand/runners/cognitive_quicksand.rb +84 -0
  112. data/lib/legion/extensions/agentic/defense/quicksand/version.rb +13 -0
  113. data/lib/legion/extensions/agentic/defense/quicksand.rb +22 -0
  114. data/lib/legion/extensions/agentic/defense/quicksilver/client.rb +29 -0
  115. data/lib/legion/extensions/agentic/defense/quicksilver/helpers/constants.rb +50 -0
  116. data/lib/legion/extensions/agentic/defense/quicksilver/helpers/droplet.rb +126 -0
  117. data/lib/legion/extensions/agentic/defense/quicksilver/helpers/pool.rb +83 -0
  118. data/lib/legion/extensions/agentic/defense/quicksilver/helpers/quicksilver_engine.rb +124 -0
  119. data/lib/legion/extensions/agentic/defense/quicksilver/runners/cognitive_quicksilver.rb +130 -0
  120. data/lib/legion/extensions/agentic/defense/quicksilver/version.rb +13 -0
  121. data/lib/legion/extensions/agentic/defense/quicksilver.rb +21 -0
  122. data/lib/legion/extensions/agentic/defense/version.rb +11 -0
  123. data/lib/legion/extensions/agentic/defense/whirlpool/client.rb +65 -0
  124. data/lib/legion/extensions/agentic/defense/whirlpool/helpers/captured_thought.rb +67 -0
  125. data/lib/legion/extensions/agentic/defense/whirlpool/helpers/constants.rb +45 -0
  126. data/lib/legion/extensions/agentic/defense/whirlpool/helpers/vortex.rb +91 -0
  127. data/lib/legion/extensions/agentic/defense/whirlpool/helpers/whirlpool_engine.rb +92 -0
  128. data/lib/legion/extensions/agentic/defense/whirlpool/runners/cognitive_whirlpool.rb +117 -0
  129. data/lib/legion/extensions/agentic/defense/whirlpool/version.rb +13 -0
  130. data/lib/legion/extensions/agentic/defense/whirlpool.rb +22 -0
  131. data/lib/legion/extensions/agentic/defense.rb +32 -0
  132. data/spec/legion/extensions/agentic/defense/avalanche/client_spec.rb +96 -0
  133. data/spec/legion/extensions/agentic/defense/avalanche/helpers/avalanche_engine_spec.rb +276 -0
  134. data/spec/legion/extensions/agentic/defense/avalanche/helpers/cascade_spec.rb +190 -0
  135. data/spec/legion/extensions/agentic/defense/avalanche/helpers/constants_spec.rb +129 -0
  136. data/spec/legion/extensions/agentic/defense/avalanche/helpers/snowpack_spec.rb +197 -0
  137. data/spec/legion/extensions/agentic/defense/avalanche/runners/cognitive_avalanche_spec.rb +211 -0
  138. data/spec/legion/extensions/agentic/defense/bias/client_spec.rb +16 -0
  139. data/spec/legion/extensions/agentic/defense/bias/helpers/bias_detector_spec.rb +160 -0
  140. data/spec/legion/extensions/agentic/defense/bias/helpers/bias_event_spec.rb +64 -0
  141. data/spec/legion/extensions/agentic/defense/bias/helpers/bias_store_spec.rb +143 -0
  142. data/spec/legion/extensions/agentic/defense/bias/runners/bias_spec.rb +155 -0
  143. data/spec/legion/extensions/agentic/defense/confabulation/client_spec.rb +34 -0
  144. data/spec/legion/extensions/agentic/defense/confabulation/helpers/claim_spec.rb +119 -0
  145. data/spec/legion/extensions/agentic/defense/confabulation/helpers/confabulation_engine_spec.rb +163 -0
  146. data/spec/legion/extensions/agentic/defense/confabulation/helpers/constants_spec.rb +55 -0
  147. data/spec/legion/extensions/agentic/defense/confabulation/runners/confabulation_spec.rb +119 -0
  148. data/spec/legion/extensions/agentic/defense/dissonance/client_spec.rb +51 -0
  149. data/spec/legion/extensions/agentic/defense/dissonance/helpers/belief_spec.rb +103 -0
  150. data/spec/legion/extensions/agentic/defense/dissonance/helpers/constants_spec.rb +60 -0
  151. data/spec/legion/extensions/agentic/defense/dissonance/helpers/dissonance_event_spec.rb +113 -0
  152. data/spec/legion/extensions/agentic/defense/dissonance/helpers/dissonance_model_spec.rb +252 -0
  153. data/spec/legion/extensions/agentic/defense/dissonance/runners/dissonance_spec.rb +323 -0
  154. data/spec/legion/extensions/agentic/defense/epistemic_vigilance/client_spec.rb +28 -0
  155. data/spec/legion/extensions/agentic/defense/epistemic_vigilance/helpers/claim_spec.rb +135 -0
  156. data/spec/legion/extensions/agentic/defense/epistemic_vigilance/helpers/constants_spec.rb +59 -0
  157. data/spec/legion/extensions/agentic/defense/epistemic_vigilance/helpers/source_spec.rb +117 -0
  158. data/spec/legion/extensions/agentic/defense/epistemic_vigilance/helpers/vigilance_engine_spec.rb +273 -0
  159. data/spec/legion/extensions/agentic/defense/epistemic_vigilance/runners/epistemic_vigilance_spec.rb +157 -0
  160. data/spec/legion/extensions/agentic/defense/erosion/client_spec.rb +90 -0
  161. data/spec/legion/extensions/agentic/defense/erosion/helpers/channel_spec.rb +173 -0
  162. data/spec/legion/extensions/agentic/defense/erosion/helpers/constants_spec.rb +137 -0
  163. data/spec/legion/extensions/agentic/defense/erosion/helpers/erosion_engine_spec.rb +263 -0
  164. data/spec/legion/extensions/agentic/defense/erosion/helpers/formation_spec.rb +206 -0
  165. data/spec/legion/extensions/agentic/defense/erosion/runners/cognitive_erosion_spec.rb +153 -0
  166. data/spec/legion/extensions/agentic/defense/error_monitoring/client_spec.rb +40 -0
  167. data/spec/legion/extensions/agentic/defense/error_monitoring/helpers/error_monitor_spec.rb +178 -0
  168. data/spec/legion/extensions/agentic/defense/error_monitoring/helpers/error_signal_spec.rb +76 -0
  169. data/spec/legion/extensions/agentic/defense/error_monitoring/runners/error_monitoring_spec.rb +87 -0
  170. data/spec/legion/extensions/agentic/defense/extinction/actors/protocol_monitor_spec.rb +45 -0
  171. data/spec/legion/extensions/agentic/defense/extinction/client_spec.rb +13 -0
  172. data/spec/legion/extensions/agentic/defense/extinction/helpers/levels_spec.rb +180 -0
  173. data/spec/legion/extensions/agentic/defense/extinction/helpers/protocol_state_spec.rb +291 -0
  174. data/spec/legion/extensions/agentic/defense/extinction/local_persistence_spec.rb +188 -0
  175. data/spec/legion/extensions/agentic/defense/extinction/runners/extinction_spec.rb +114 -0
  176. data/spec/legion/extensions/agentic/defense/friction/helpers/constants_spec.rb +46 -0
  177. data/spec/legion/extensions/agentic/defense/friction/helpers/friction_engine_spec.rb +175 -0
  178. data/spec/legion/extensions/agentic/defense/friction/helpers/state_transition_spec.rb +124 -0
  179. data/spec/legion/extensions/agentic/defense/friction/runners/cognitive_friction_spec.rb +89 -0
  180. data/spec/legion/extensions/agentic/defense/immune_response/client_spec.rb +32 -0
  181. data/spec/legion/extensions/agentic/defense/immune_response/cognitive_immune_response_spec.rb +7 -0
  182. data/spec/legion/extensions/agentic/defense/immune_response/helpers/antibody_spec.rb +117 -0
  183. data/spec/legion/extensions/agentic/defense/immune_response/helpers/antigen_spec.rb +125 -0
  184. data/spec/legion/extensions/agentic/defense/immune_response/helpers/constants_spec.rb +45 -0
  185. data/spec/legion/extensions/agentic/defense/immune_response/helpers/immune_engine_spec.rb +222 -0
  186. data/spec/legion/extensions/agentic/defense/immune_response/helpers/immune_response_spec.rb +84 -0
  187. data/spec/legion/extensions/agentic/defense/immune_response/runners_spec.rb +141 -0
  188. data/spec/legion/extensions/agentic/defense/immunology/client_spec.rb +61 -0
  189. data/spec/legion/extensions/agentic/defense/immunology/helpers/antibody_spec.rb +98 -0
  190. data/spec/legion/extensions/agentic/defense/immunology/helpers/constants_spec.rb +86 -0
  191. data/spec/legion/extensions/agentic/defense/immunology/helpers/immune_engine_spec.rb +275 -0
  192. data/spec/legion/extensions/agentic/defense/immunology/helpers/threat_spec.rb +133 -0
  193. data/spec/legion/extensions/agentic/defense/immunology/runners/cognitive_immunology_spec.rb +177 -0
  194. data/spec/legion/extensions/agentic/defense/phantom/client_spec.rb +53 -0
  195. data/spec/legion/extensions/agentic/defense/phantom/helpers/constants_spec.rb +87 -0
  196. data/spec/legion/extensions/agentic/defense/phantom/helpers/phantom_engine_spec.rb +222 -0
  197. data/spec/legion/extensions/agentic/defense/phantom/helpers/phantom_limb_spec.rb +180 -0
  198. data/spec/legion/extensions/agentic/defense/phantom/helpers/phantom_signal_spec.rb +59 -0
  199. data/spec/legion/extensions/agentic/defense/phantom/runners/cognitive_phantom_spec.rb +193 -0
  200. data/spec/legion/extensions/agentic/defense/quicksand/client_spec.rb +35 -0
  201. data/spec/legion/extensions/agentic/defense/quicksand/helpers/constants_spec.rb +58 -0
  202. data/spec/legion/extensions/agentic/defense/quicksand/helpers/pit_spec.rb +103 -0
  203. data/spec/legion/extensions/agentic/defense/quicksand/helpers/quicksand_engine_spec.rb +153 -0
  204. data/spec/legion/extensions/agentic/defense/quicksand/helpers/trap_spec.rb +166 -0
  205. data/spec/legion/extensions/agentic/defense/quicksand/runners/cognitive_quicksand_spec.rb +90 -0
  206. data/spec/legion/extensions/agentic/defense/quicksilver/client_spec.rb +72 -0
  207. data/spec/legion/extensions/agentic/defense/quicksilver/helpers/constants_spec.rb +105 -0
  208. data/spec/legion/extensions/agentic/defense/quicksilver/helpers/droplet_spec.rb +310 -0
  209. data/spec/legion/extensions/agentic/defense/quicksilver/helpers/pool_spec.rb +174 -0
  210. data/spec/legion/extensions/agentic/defense/quicksilver/helpers/quicksilver_engine_spec.rb +226 -0
  211. data/spec/legion/extensions/agentic/defense/quicksilver/runners/cognitive_quicksilver_spec.rb +227 -0
  212. data/spec/legion/extensions/agentic/defense/whirlpool/client_spec.rb +63 -0
  213. data/spec/legion/extensions/agentic/defense/whirlpool/helpers/captured_thought_spec.rb +171 -0
  214. data/spec/legion/extensions/agentic/defense/whirlpool/helpers/constants_spec.rb +65 -0
  215. data/spec/legion/extensions/agentic/defense/whirlpool/helpers/vortex_spec.rb +189 -0
  216. data/spec/legion/extensions/agentic/defense/whirlpool/helpers/whirlpool_engine_spec.rb +227 -0
  217. data/spec/legion/extensions/agentic/defense/whirlpool/runners/cognitive_whirlpool_spec.rb +226 -0
  218. data/spec/spec_helper.rb +46 -0
  219. metadata +303 -0
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Confabulation
8
+ module Helpers
9
+ class ConfabulationEngine
10
+ attr_reader :claims
11
+
12
+ def initialize
13
+ @claims = {}
14
+ end
15
+
16
+ def register_claim(content:, claim_type: :factual, confidence: 0.5, evidence_strength: 0.5)
17
+ claim_type = claim_type.to_sym
18
+ claim_type = :factual unless Constants::CLAIM_TYPES.include?(claim_type)
19
+
20
+ claim = Claim.new(
21
+ content: content,
22
+ claim_type: claim_type,
23
+ confidence: confidence,
24
+ evidence_strength: evidence_strength
25
+ )
26
+ prune_if_needed
27
+ @claims[claim.id] = claim
28
+ claim
29
+ end
30
+
31
+ def verify_claim(claim_id:)
32
+ claim = @claims[claim_id]
33
+ return { found: false, claim_id: claim_id } unless claim
34
+
35
+ claim.verify!
36
+ { found: true, claim_id: claim_id, verified: true }
37
+ end
38
+
39
+ def flag_confabulation(claim_id:)
40
+ claim = @claims[claim_id]
41
+ return { found: false, claim_id: claim_id } unless claim
42
+
43
+ claim.mark_confabulated!
44
+ { found: true, claim_id: claim_id, confabulated: true }
45
+ end
46
+
47
+ def high_risk_claims
48
+ @claims.values.select { |c| c.confabulation_risk >= Constants::CONFABULATION_THRESHOLD }
49
+ end
50
+
51
+ def verified_claims
52
+ @claims.values.select(&:verified)
53
+ end
54
+
55
+ def confabulation_rate
56
+ total = @claims.size
57
+ return 0.0 if total.zero?
58
+
59
+ flagged = @claims.values.count(&:confabulated)
60
+ (flagged.to_f / total).round(10)
61
+ end
62
+
63
+ def average_calibration
64
+ return 0.0 if @claims.empty?
65
+
66
+ total_gap = @claims.values.sum { |c| (c.confidence - c.evidence_strength).abs }
67
+ gap = total_gap / @claims.size.to_f
68
+ (1.0 - gap).clamp(0.0, 1.0).round(10)
69
+ end
70
+
71
+ def confabulation_report
72
+ total = @claims.size
73
+ high_risk = high_risk_claims.size
74
+ verified = verified_claims.size
75
+ confabulated = @claims.values.count(&:confabulated)
76
+ overall_risk = total.zero? ? 0.0 : high_risk.to_f / total
77
+ risk_label = risk_label_for(overall_risk)
78
+
79
+ {
80
+ total_claims: total,
81
+ high_risk_claims: high_risk,
82
+ verified_claims: verified,
83
+ confabulated_claims: confabulated,
84
+ confabulation_rate: confabulation_rate,
85
+ average_calibration: average_calibration,
86
+ overall_risk: overall_risk.round(10),
87
+ risk_label: risk_label
88
+ }
89
+ end
90
+
91
+ def prune_if_needed
92
+ return unless @claims.size >= Constants::MAX_CLAIMS
93
+
94
+ oldest_key = @claims.min_by { |_, c| c.created_at }&.first
95
+ @claims.delete(oldest_key)
96
+ end
97
+
98
+ def to_h
99
+ {
100
+ claim_count: @claims.size,
101
+ confabulation_rate: confabulation_rate,
102
+ average_calibration: average_calibration
103
+ }
104
+ end
105
+
106
+ private
107
+
108
+ def risk_label_for(value)
109
+ Constants::RISK_LABELS.each do |range, label|
110
+ return label if range.cover?(value)
111
+ end
112
+ :extreme
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Confabulation
8
+ module Helpers
9
+ module Constants
10
+ MAX_CLAIMS = 500
11
+ CONFABULATION_THRESHOLD = 0.6
12
+ EVIDENCE_DECAY = 0.02
13
+
14
+ RISK_LABELS = {
15
+ 0.0..0.2 => :minimal,
16
+ 0.2..0.4 => :low,
17
+ 0.4..0.6 => :moderate,
18
+ 0.6..0.8 => :high,
19
+ 0.8..1.0 => :extreme
20
+ }.freeze
21
+
22
+ CLAIM_TYPES = %i[factual causal explanatory predictive autobiographical].freeze
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Confabulation
8
+ module Runners
9
+ module Confabulation
10
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
11
+ Legion::Extensions::Helpers.const_defined?(:Lex)
12
+
13
+ def register_claim(content:, claim_type: :factual, confidence: 0.5, evidence_strength: 0.5, **)
14
+ claim = confabulation_engine.register_claim(
15
+ content: content,
16
+ claim_type: claim_type,
17
+ confidence: confidence,
18
+ evidence_strength: evidence_strength
19
+ )
20
+ Legion::Logging.debug "[confabulation] register: id=#{claim.id} type=#{claim.claim_type} " \
21
+ "risk=#{claim.confabulation_risk.round(2)} label=#{claim.risk_label}"
22
+ claim.to_h
23
+ end
24
+
25
+ def verify_claim(claim_id:, **)
26
+ result = confabulation_engine.verify_claim(claim_id: claim_id)
27
+ if result[:found]
28
+ Legion::Logging.info "[confabulation] verified: claim_id=#{claim_id}"
29
+ else
30
+ Legion::Logging.debug "[confabulation] verify: claim_id=#{claim_id} not found"
31
+ end
32
+ result
33
+ end
34
+
35
+ def flag_confabulation(claim_id:, **)
36
+ result = confabulation_engine.flag_confabulation(claim_id: claim_id)
37
+ if result[:found]
38
+ Legion::Logging.warn "[confabulation] flagged: claim_id=#{claim_id} marked as confabulated"
39
+ else
40
+ Legion::Logging.debug "[confabulation] flag: claim_id=#{claim_id} not found"
41
+ end
42
+ result
43
+ end
44
+
45
+ def confabulation_report(**)
46
+ report = confabulation_engine.confabulation_report
47
+ Legion::Logging.debug "[confabulation] report: total=#{report[:total_claims]} " \
48
+ "high_risk=#{report[:high_risk_claims]} " \
49
+ "rate=#{report[:confabulation_rate].round(2)} label=#{report[:risk_label]}"
50
+ report
51
+ end
52
+
53
+ def high_risk_claims(**)
54
+ claims = confabulation_engine.high_risk_claims
55
+ Legion::Logging.debug "[confabulation] high_risk_claims: count=#{claims.size}"
56
+ { claims: claims.map(&:to_h), count: claims.size }
57
+ end
58
+
59
+ def confabulation_status(**)
60
+ { engine: confabulation_engine.to_h }
61
+ end
62
+
63
+ private
64
+
65
+ def confabulation_engine
66
+ @confabulation_engine ||= Helpers::ConfabulationEngine.new
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Confabulation
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/defense/confabulation/version'
4
+ require 'legion/extensions/agentic/defense/confabulation/helpers/constants'
5
+ require 'legion/extensions/agentic/defense/confabulation/helpers/claim'
6
+ require 'legion/extensions/agentic/defense/confabulation/helpers/confabulation_engine'
7
+ require 'legion/extensions/agentic/defense/confabulation/runners/confabulation'
8
+ require 'legion/extensions/agentic/defense/confabulation/client'
9
+
10
+ module Legion
11
+ module Extensions
12
+ module Agentic
13
+ module Defense
14
+ module Confabulation
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/defense/dissonance/helpers/constants'
4
+ require 'legion/extensions/agentic/defense/dissonance/helpers/belief'
5
+ require 'legion/extensions/agentic/defense/dissonance/helpers/dissonance_event'
6
+ require 'legion/extensions/agentic/defense/dissonance/helpers/dissonance_model'
7
+ require 'legion/extensions/agentic/defense/dissonance/runners/dissonance'
8
+
9
+ module Legion
10
+ module Extensions
11
+ module Agentic
12
+ module Defense
13
+ module Dissonance
14
+ class Client
15
+ include Runners::Dissonance
16
+
17
+ attr_reader :model
18
+
19
+ def initialize(model: nil, **)
20
+ @model = model || Helpers::DissonanceModel.new
21
+ @dissonance_model = @model
22
+ end
23
+
24
+ private
25
+
26
+ attr_accessor :dissonance_model
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Defense
9
+ module Dissonance
10
+ module Helpers
11
+ class Belief
12
+ attr_reader :id, :domain, :content, :confidence, :importance, :created_at
13
+
14
+ def initialize(domain:, content:, confidence: 0.7, importance: :moderate)
15
+ @id = SecureRandom.uuid
16
+ @domain = domain
17
+ @content = content
18
+ @confidence = confidence.clamp(0.0, 1.0)
19
+ @importance = importance
20
+ @created_at = Time.now.utc
21
+ end
22
+
23
+ def contradicts?(other)
24
+ return false if id == other.id
25
+ return false unless domain == other.domain
26
+
27
+ content.strip.downcase != other.content.strip.downcase
28
+ end
29
+
30
+ def to_h
31
+ {
32
+ id: id,
33
+ domain: domain,
34
+ content: content,
35
+ confidence: confidence,
36
+ importance: importance,
37
+ created_at: created_at
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Dissonance
8
+ module Helpers
9
+ module Constants
10
+ DISSONANCE_THRESHOLD = 0.4
11
+ MAX_BELIEFS = 200
12
+ MAX_DISSONANCE_EVENTS = 100
13
+ DECAY_RATE = 0.03
14
+ RESOLUTION_RELIEF = 0.3
15
+ RATIONALIZATION_FACTOR = 0.5
16
+ IMPORTANCE_WEIGHTS = { core: 1.0, significant: 0.7, moderate: 0.5, peripheral: 0.25 }.freeze
17
+ RESOLUTION_STRATEGIES = %i[belief_revision rationalization avoidance].freeze
18
+ STRESS_CEILING = 1.0
19
+ STRESS_FLOOR = 0.0
20
+ CONTRADICTION_TYPES = %i[direct inverse conditional temporal].freeze
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Defense
9
+ module Dissonance
10
+ module Helpers
11
+ class DissonanceEvent
12
+ attr_reader :id, :belief_a_id, :belief_b_id, :domain, :magnitude,
13
+ :contradiction_type, :resolved, :resolution_strategy, :timestamp
14
+
15
+ def initialize(belief_a_id:, belief_b_id:, domain:, magnitude:, contradiction_type: :direct)
16
+ @id = SecureRandom.uuid
17
+ @belief_a_id = belief_a_id
18
+ @belief_b_id = belief_b_id
19
+ @domain = domain
20
+ @magnitude = magnitude.clamp(0.0, 1.0)
21
+ @contradiction_type = contradiction_type
22
+ @resolved = false
23
+ @resolution_strategy = nil
24
+ @timestamp = Time.now.utc
25
+ end
26
+
27
+ def resolve!(strategy)
28
+ @resolved = true
29
+ @resolution_strategy = strategy
30
+ self
31
+ end
32
+
33
+ def to_h
34
+ {
35
+ id: id,
36
+ belief_a_id: belief_a_id,
37
+ belief_b_id: belief_b_id,
38
+ domain: domain,
39
+ magnitude: magnitude,
40
+ contradiction_type: contradiction_type,
41
+ resolved: resolved,
42
+ resolution_strategy: resolution_strategy,
43
+ timestamp: timestamp
44
+ }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Dissonance
8
+ module Helpers
9
+ class DissonanceModel
10
+ include Constants
11
+
12
+ attr_reader :beliefs, :events, :stress
13
+
14
+ def initialize
15
+ @beliefs = {}
16
+ @events = {}
17
+ @stress = STRESS_FLOOR
18
+ end
19
+
20
+ def add_belief(domain:, content:, confidence: 0.7, importance: :moderate)
21
+ prune_beliefs if @beliefs.size >= MAX_BELIEFS
22
+
23
+ belief = Belief.new(domain: domain, content: content,
24
+ confidence: confidence, importance: importance)
25
+ @beliefs[belief.id] = belief
26
+
27
+ new_events = detect_contradictions_for(belief)
28
+ new_events.each { |ev| @events[ev.id] = ev }
29
+
30
+ { belief: belief, new_dissonance_events: new_events }
31
+ end
32
+
33
+ def detect_contradictions
34
+ new_events = []
35
+ belief_list = @beliefs.values
36
+
37
+ belief_list.each_with_index do |bel_a, idx|
38
+ belief_list[(idx + 1)..].each do |bel_b|
39
+ next unless bel_a.contradicts?(bel_b)
40
+ next if contradiction_tracked?(bel_a.id, bel_b.id)
41
+
42
+ ev = build_event(bel_a, bel_b)
43
+ @events[ev.id] = ev
44
+ new_events << ev
45
+ end
46
+ end
47
+
48
+ new_events
49
+ end
50
+
51
+ def resolve(event_id, strategy:)
52
+ event = @events[event_id]
53
+ return nil unless event
54
+ return nil if event.resolved
55
+ return nil unless RESOLUTION_STRATEGIES.include?(strategy)
56
+
57
+ event.resolve!(strategy)
58
+ relief = compute_relief(strategy)
59
+ @stress = (@stress - relief).clamp(STRESS_FLOOR, STRESS_CEILING)
60
+ event
61
+ end
62
+
63
+ def stress_level
64
+ @stress
65
+ end
66
+
67
+ def domain_stress(domain)
68
+ unresolved = unresolved_events.select { |ev| ev.domain == domain }
69
+ return STRESS_FLOOR if unresolved.empty?
70
+
71
+ raw = unresolved.sum(&:magnitude) / MAX_DISSONANCE_EVENTS.to_f
72
+ raw.clamp(STRESS_FLOOR, STRESS_CEILING)
73
+ end
74
+
75
+ def unresolved_events
76
+ @events.values.reject(&:resolved)
77
+ end
78
+
79
+ def decay
80
+ unresolved = unresolved_events
81
+ if unresolved.any?
82
+ increment = DECAY_RATE * unresolved.size
83
+ @stress = (@stress + increment).clamp(STRESS_FLOOR, STRESS_CEILING)
84
+ else
85
+ @stress = (@stress - DECAY_RATE).clamp(STRESS_FLOOR, STRESS_CEILING)
86
+ end
87
+ @stress
88
+ end
89
+
90
+ def to_h
91
+ {
92
+ beliefs: @beliefs.values.map(&:to_h),
93
+ events: @events.values.map(&:to_h),
94
+ stress: @stress,
95
+ unresolved_count: unresolved_events.size,
96
+ total_beliefs: @beliefs.size,
97
+ total_events: @events.size
98
+ }
99
+ end
100
+
101
+ private
102
+
103
+ def detect_contradictions_for(new_belief)
104
+ new_events = []
105
+
106
+ @beliefs.each_value do |existing|
107
+ next if existing.id == new_belief.id
108
+ next unless new_belief.contradicts?(existing)
109
+ next if contradiction_tracked?(new_belief.id, existing.id)
110
+
111
+ ev = build_event(new_belief, existing)
112
+ new_events << ev
113
+ end
114
+
115
+ new_events
116
+ end
117
+
118
+ def build_event(bel_a, bel_b)
119
+ magnitude = compute_magnitude(bel_a, bel_b)
120
+ DissonanceEvent.new(
121
+ belief_a_id: bel_a.id,
122
+ belief_b_id: bel_b.id,
123
+ domain: bel_a.domain,
124
+ magnitude: magnitude,
125
+ contradiction_type: :direct
126
+ )
127
+ end
128
+
129
+ def compute_magnitude(bel_a, bel_b)
130
+ weight_a = IMPORTANCE_WEIGHTS.fetch(bel_a.importance, 0.5)
131
+ weight_b = IMPORTANCE_WEIGHTS.fetch(bel_b.importance, 0.5)
132
+ avg_weight = (weight_a + weight_b) / 2.0
133
+ avg_confidence = (bel_a.confidence + bel_b.confidence) / 2.0
134
+ (avg_weight * avg_confidence).clamp(0.0, 1.0)
135
+ end
136
+
137
+ def compute_relief(strategy)
138
+ base = RESOLUTION_RELIEF
139
+ strategy == :rationalization ? base * RATIONALIZATION_FACTOR : base
140
+ end
141
+
142
+ def contradiction_tracked?(id_a, id_b)
143
+ @events.values.any? do |ev|
144
+ (ev.belief_a_id == id_a && ev.belief_b_id == id_b) ||
145
+ (ev.belief_a_id == id_b && ev.belief_b_id == id_a)
146
+ end
147
+ end
148
+
149
+ def prune_beliefs
150
+ oldest = @beliefs.values.min_by(&:created_at)
151
+ @beliefs.delete(oldest.id) if oldest
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end