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,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/defense/confabulation/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Defense::Confabulation::Runners::Confabulation do
6
+ let(:client) { Legion::Extensions::Agentic::Defense::Confabulation::Client.new }
7
+
8
+ describe '#register_claim' do
9
+ it 'returns a claim hash with an id' do
10
+ result = client.register_claim(content: 'Pigeons navigate by smell', claim_type: :factual,
11
+ confidence: 0.7, evidence_strength: 0.2)
12
+ expect(result[:id]).not_to be_nil
13
+ expect(result[:claim_type]).to eq(:factual)
14
+ end
15
+
16
+ it 'includes confabulation_risk and risk_label' do
17
+ result = client.register_claim(content: 'x', claim_type: :causal, confidence: 0.9, evidence_strength: 0.1)
18
+ expect(result).to have_key(:confabulation_risk)
19
+ expect(result).to have_key(:risk_label)
20
+ end
21
+
22
+ it 'accepts all valid claim types' do
23
+ Legion::Extensions::Agentic::Defense::Confabulation::Helpers::Constants::CLAIM_TYPES.each do |type|
24
+ result = client.register_claim(content: 'x', claim_type: type, confidence: 0.5, evidence_strength: 0.5)
25
+ expect(result[:claim_type]).to eq(type)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '#verify_claim' do
31
+ it 'verifies an existing claim' do
32
+ claim = client.register_claim(content: 'testable fact', claim_type: :factual,
33
+ confidence: 0.6, evidence_strength: 0.6)
34
+ result = client.verify_claim(claim_id: claim[:id])
35
+ expect(result[:found]).to be true
36
+ expect(result[:verified]).to be true
37
+ end
38
+
39
+ it 'returns found: false for a missing claim' do
40
+ result = client.verify_claim(claim_id: 'does-not-exist')
41
+ expect(result[:found]).to be false
42
+ end
43
+ end
44
+
45
+ describe '#flag_confabulation' do
46
+ it 'flags an existing claim as confabulated' do
47
+ claim = client.register_claim(content: 'false memory', claim_type: :autobiographical,
48
+ confidence: 0.9, evidence_strength: 0.05)
49
+ result = client.flag_confabulation(claim_id: claim[:id])
50
+ expect(result[:found]).to be true
51
+ expect(result[:confabulated]).to be true
52
+ end
53
+
54
+ it 'returns found: false for a missing claim' do
55
+ result = client.flag_confabulation(claim_id: 'no-such-id')
56
+ expect(result[:found]).to be false
57
+ end
58
+ end
59
+
60
+ describe '#confabulation_report' do
61
+ it 'returns a report hash' do
62
+ client.register_claim(content: 'risky', claim_type: :factual, confidence: 0.9, evidence_strength: 0.05)
63
+ report = client.confabulation_report
64
+ expect(report[:total_claims]).to eq(1)
65
+ expect(report[:risk_label]).to be_a(Symbol)
66
+ end
67
+
68
+ it 'includes overall_risk and average_calibration' do
69
+ report = client.confabulation_report
70
+ expect(report).to have_key(:overall_risk)
71
+ expect(report).to have_key(:average_calibration)
72
+ end
73
+ end
74
+
75
+ describe '#high_risk_claims' do
76
+ it 'returns claims above the threshold' do
77
+ client.register_claim(content: 'overconfident', claim_type: :predictive,
78
+ confidence: 0.95, evidence_strength: 0.05)
79
+ client.register_claim(content: 'calibrated', claim_type: :predictive,
80
+ confidence: 0.5, evidence_strength: 0.5)
81
+ result = client.high_risk_claims
82
+ expect(result[:count]).to eq(1)
83
+ expect(result[:claims].first[:content]).to eq('overconfident')
84
+ end
85
+
86
+ it 'returns empty list when no high-risk claims' do
87
+ client.register_claim(content: 'ok', claim_type: :factual, confidence: 0.5, evidence_strength: 0.5)
88
+ result = client.high_risk_claims
89
+ expect(result[:count]).to eq(0)
90
+ end
91
+ end
92
+
93
+ describe '#confabulation_status' do
94
+ it 'returns engine summary' do
95
+ result = client.confabulation_status
96
+ expect(result[:engine]).to have_key(:claim_count)
97
+ expect(result[:engine]).to have_key(:confabulation_rate)
98
+ expect(result[:engine]).to have_key(:average_calibration)
99
+ end
100
+ end
101
+
102
+ describe 'full cycle' do
103
+ it 'registers, verifies, flags and reports correctly' do
104
+ c1 = client.register_claim(content: 'valid fact', claim_type: :factual,
105
+ confidence: 0.6, evidence_strength: 0.6)
106
+ c2 = client.register_claim(content: 'false memory', claim_type: :autobiographical,
107
+ confidence: 0.9, evidence_strength: 0.05)
108
+
109
+ client.verify_claim(claim_id: c1[:id])
110
+ client.flag_confabulation(claim_id: c2[:id])
111
+
112
+ report = client.confabulation_report
113
+ expect(report[:total_claims]).to eq(2)
114
+ expect(report[:verified_claims]).to eq(1)
115
+ expect(report[:confabulated_claims]).to eq(1)
116
+ expect(report[:confabulation_rate]).to be_within(0.001).of(0.5)
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/defense/dissonance/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Defense::Dissonance::Client do
6
+ describe '#initialize' do
7
+ it 'creates a default DissonanceModel when none provided' do
8
+ client = described_class.new
9
+ expect(client.model).to be_a(Legion::Extensions::Agentic::Defense::Dissonance::Helpers::DissonanceModel)
10
+ end
11
+
12
+ it 'accepts a custom model' do
13
+ custom_model = Legion::Extensions::Agentic::Defense::Dissonance::Helpers::DissonanceModel.new
14
+ client = described_class.new(model: custom_model)
15
+ expect(client.model).to be(custom_model)
16
+ end
17
+ end
18
+
19
+ describe 'responds to all runner methods' do
20
+ let(:client) { described_class.new }
21
+
22
+ it { expect(client).to respond_to(:add_belief) }
23
+ it { expect(client).to respond_to(:update_dissonance) }
24
+ it { expect(client).to respond_to(:resolve_dissonance) }
25
+ it { expect(client).to respond_to(:dissonance_status) }
26
+ it { expect(client).to respond_to(:domain_dissonance) }
27
+ it { expect(client).to respond_to(:beliefs_for) }
28
+ it { expect(client).to respond_to(:unresolved) }
29
+ it { expect(client).to respond_to(:dissonance_stats) }
30
+ end
31
+
32
+ describe 'state isolation between instances' do
33
+ it 'two clients do not share belief state' do
34
+ client1 = described_class.new
35
+ client2 = described_class.new
36
+ client1.add_belief(domain: 'x', content: 'some belief')
37
+ result = client2.beliefs_for(domain: 'x')
38
+ expect(result[:count]).to eq(0)
39
+ end
40
+ end
41
+
42
+ describe 'custom model integration' do
43
+ it 'uses the beliefs already in a pre-populated model' do
44
+ model = Legion::Extensions::Agentic::Defense::Dissonance::Helpers::DissonanceModel.new
45
+ model.add_belief(domain: 'shared', content: 'a shared belief')
46
+ client = described_class.new(model: model)
47
+ result = client.beliefs_for(domain: 'shared')
48
+ expect(result[:count]).to eq(1)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::Dissonance::Helpers::Belief do
4
+ let(:belief) { described_class.new(domain: 'ethics', content: 'honesty is required', confidence: 0.9, importance: :core) }
5
+
6
+ describe '#initialize' do
7
+ it 'assigns a uuid id' do
8
+ expect(belief.id).to match(/\A[0-9a-f-]{36}\z/)
9
+ end
10
+
11
+ it 'assigns domain' do
12
+ expect(belief.domain).to eq('ethics')
13
+ end
14
+
15
+ it 'assigns content' do
16
+ expect(belief.content).to eq('honesty is required')
17
+ end
18
+
19
+ it 'assigns confidence' do
20
+ expect(belief.confidence).to eq(0.9)
21
+ end
22
+
23
+ it 'assigns importance' do
24
+ expect(belief.importance).to eq(:core)
25
+ end
26
+
27
+ it 'assigns created_at as UTC Time' do
28
+ expect(belief.created_at).to be_a(Time)
29
+ end
30
+
31
+ it 'clamps confidence to 0-1 range (above)' do
32
+ b = described_class.new(domain: 'd', content: 'c', confidence: 1.5)
33
+ expect(b.confidence).to eq(1.0)
34
+ end
35
+
36
+ it 'clamps confidence to 0-1 range (below)' do
37
+ b = described_class.new(domain: 'd', content: 'c', confidence: -0.5)
38
+ expect(b.confidence).to eq(0.0)
39
+ end
40
+
41
+ it 'defaults confidence to 0.7' do
42
+ b = described_class.new(domain: 'd', content: 'c')
43
+ expect(b.confidence).to eq(0.7)
44
+ end
45
+
46
+ it 'defaults importance to :moderate' do
47
+ b = described_class.new(domain: 'd', content: 'c')
48
+ expect(b.importance).to eq(:moderate)
49
+ end
50
+ end
51
+
52
+ describe '#contradicts?' do
53
+ let(:other_same) do
54
+ described_class.new(domain: 'ethics', content: 'honesty is required', confidence: 0.8, importance: :moderate)
55
+ end
56
+
57
+ let(:other_different) do
58
+ described_class.new(domain: 'ethics', content: 'deception is acceptable', confidence: 0.6, importance: :moderate)
59
+ end
60
+
61
+ let(:other_domain) do
62
+ described_class.new(domain: 'safety', content: 'honesty is required', confidence: 0.8, importance: :moderate)
63
+ end
64
+
65
+ it 'returns false for same content' do
66
+ expect(belief.contradicts?(other_same)).to be false
67
+ end
68
+
69
+ it 'returns true for different content in same domain' do
70
+ expect(belief.contradicts?(other_different)).to be true
71
+ end
72
+
73
+ it 'returns false for different domain' do
74
+ expect(belief.contradicts?(other_domain)).to be false
75
+ end
76
+
77
+ it 'returns false when compared to itself' do
78
+ expect(belief.contradicts?(belief)).to be false
79
+ end
80
+
81
+ it 'is case-insensitive for content comparison' do
82
+ upper = described_class.new(domain: 'ethics', content: 'HONESTY IS REQUIRED', confidence: 0.8, importance: :moderate)
83
+ expect(belief.contradicts?(upper)).to be false
84
+ end
85
+
86
+ it 'ignores leading/trailing whitespace in content comparison' do
87
+ padded = described_class.new(domain: 'ethics', content: ' honesty is required ', confidence: 0.8, importance: :moderate)
88
+ expect(belief.contradicts?(padded)).to be false
89
+ end
90
+ end
91
+
92
+ describe '#to_h' do
93
+ it 'returns a hash with all fields' do
94
+ h = belief.to_h
95
+ expect(h[:id]).to eq(belief.id)
96
+ expect(h[:domain]).to eq('ethics')
97
+ expect(h[:content]).to eq('honesty is required')
98
+ expect(h[:confidence]).to eq(0.9)
99
+ expect(h[:importance]).to eq(:core)
100
+ expect(h[:created_at]).to be_a(Time)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::Dissonance::Helpers::Constants do
4
+ it 'defines DISSONANCE_THRESHOLD' do
5
+ expect(described_class::DISSONANCE_THRESHOLD).to eq(0.4)
6
+ end
7
+
8
+ it 'defines MAX_BELIEFS' do
9
+ expect(described_class::MAX_BELIEFS).to eq(200)
10
+ end
11
+
12
+ it 'defines MAX_DISSONANCE_EVENTS' do
13
+ expect(described_class::MAX_DISSONANCE_EVENTS).to eq(100)
14
+ end
15
+
16
+ it 'defines DECAY_RATE' do
17
+ expect(described_class::DECAY_RATE).to eq(0.03)
18
+ end
19
+
20
+ it 'defines RESOLUTION_RELIEF' do
21
+ expect(described_class::RESOLUTION_RELIEF).to eq(0.3)
22
+ end
23
+
24
+ it 'defines RATIONALIZATION_FACTOR' do
25
+ expect(described_class::RATIONALIZATION_FACTOR).to eq(0.5)
26
+ end
27
+
28
+ it 'defines IMPORTANCE_WEIGHTS with four levels' do
29
+ weights = described_class::IMPORTANCE_WEIGHTS
30
+ expect(weights[:core]).to eq(1.0)
31
+ expect(weights[:significant]).to eq(0.7)
32
+ expect(weights[:moderate]).to eq(0.5)
33
+ expect(weights[:peripheral]).to eq(0.25)
34
+ end
35
+
36
+ it 'defines RESOLUTION_STRATEGIES' do
37
+ expect(described_class::RESOLUTION_STRATEGIES).to contain_exactly(:belief_revision, :rationalization, :avoidance)
38
+ end
39
+
40
+ it 'defines STRESS_CEILING and STRESS_FLOOR' do
41
+ expect(described_class::STRESS_CEILING).to eq(1.0)
42
+ expect(described_class::STRESS_FLOOR).to eq(0.0)
43
+ end
44
+
45
+ it 'defines CONTRADICTION_TYPES' do
46
+ expect(described_class::CONTRADICTION_TYPES).to contain_exactly(:direct, :inverse, :conditional, :temporal)
47
+ end
48
+
49
+ it 'freezes IMPORTANCE_WEIGHTS' do
50
+ expect(described_class::IMPORTANCE_WEIGHTS).to be_frozen
51
+ end
52
+
53
+ it 'freezes RESOLUTION_STRATEGIES' do
54
+ expect(described_class::RESOLUTION_STRATEGIES).to be_frozen
55
+ end
56
+
57
+ it 'freezes CONTRADICTION_TYPES' do
58
+ expect(described_class::CONTRADICTION_TYPES).to be_frozen
59
+ end
60
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::Dissonance::Helpers::DissonanceEvent do
4
+ let(:event) do
5
+ described_class.new(
6
+ belief_a_id: 'uuid-a',
7
+ belief_b_id: 'uuid-b',
8
+ domain: 'ethics',
9
+ magnitude: 0.6,
10
+ contradiction_type: :direct
11
+ )
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'assigns a uuid id' do
16
+ expect(event.id).to match(/\A[0-9a-f-]{36}\z/)
17
+ end
18
+
19
+ it 'assigns belief_a_id' do
20
+ expect(event.belief_a_id).to eq('uuid-a')
21
+ end
22
+
23
+ it 'assigns belief_b_id' do
24
+ expect(event.belief_b_id).to eq('uuid-b')
25
+ end
26
+
27
+ it 'assigns domain' do
28
+ expect(event.domain).to eq('ethics')
29
+ end
30
+
31
+ it 'assigns magnitude' do
32
+ expect(event.magnitude).to eq(0.6)
33
+ end
34
+
35
+ it 'assigns contradiction_type' do
36
+ expect(event.contradiction_type).to eq(:direct)
37
+ end
38
+
39
+ it 'starts as unresolved' do
40
+ expect(event.resolved).to be false
41
+ end
42
+
43
+ it 'starts with nil resolution_strategy' do
44
+ expect(event.resolution_strategy).to be_nil
45
+ end
46
+
47
+ it 'assigns timestamp as UTC Time' do
48
+ expect(event.timestamp).to be_a(Time)
49
+ end
50
+
51
+ it 'clamps magnitude above 1.0' do
52
+ ev = described_class.new(belief_a_id: 'a', belief_b_id: 'b', domain: 'd', magnitude: 1.5)
53
+ expect(ev.magnitude).to eq(1.0)
54
+ end
55
+
56
+ it 'clamps magnitude below 0.0' do
57
+ ev = described_class.new(belief_a_id: 'a', belief_b_id: 'b', domain: 'd', magnitude: -0.5)
58
+ expect(ev.magnitude).to eq(0.0)
59
+ end
60
+
61
+ it 'defaults contradiction_type to :direct' do
62
+ ev = described_class.new(belief_a_id: 'a', belief_b_id: 'b', domain: 'd', magnitude: 0.5)
63
+ expect(ev.contradiction_type).to eq(:direct)
64
+ end
65
+ end
66
+
67
+ describe '#resolve!' do
68
+ it 'marks the event as resolved' do
69
+ event.resolve!(:belief_revision)
70
+ expect(event.resolved).to be true
71
+ end
72
+
73
+ it 'records the resolution strategy' do
74
+ event.resolve!(:rationalization)
75
+ expect(event.resolution_strategy).to eq(:rationalization)
76
+ end
77
+
78
+ it 'returns self for chaining' do
79
+ result = event.resolve!(:avoidance)
80
+ expect(result).to be(event)
81
+ end
82
+
83
+ it 'can be resolved with any valid strategy' do
84
+ Legion::Extensions::Agentic::Defense::Dissonance::Helpers::Constants::RESOLUTION_STRATEGIES.each do |strategy|
85
+ ev = described_class.new(belief_a_id: 'a', belief_b_id: 'b', domain: 'd', magnitude: 0.5)
86
+ ev.resolve!(strategy)
87
+ expect(ev.resolution_strategy).to eq(strategy)
88
+ end
89
+ end
90
+ end
91
+
92
+ describe '#to_h' do
93
+ it 'returns hash with all fields when unresolved' do
94
+ h = event.to_h
95
+ expect(h[:id]).to eq(event.id)
96
+ expect(h[:belief_a_id]).to eq('uuid-a')
97
+ expect(h[:belief_b_id]).to eq('uuid-b')
98
+ expect(h[:domain]).to eq('ethics')
99
+ expect(h[:magnitude]).to eq(0.6)
100
+ expect(h[:contradiction_type]).to eq(:direct)
101
+ expect(h[:resolved]).to be false
102
+ expect(h[:resolution_strategy]).to be_nil
103
+ expect(h[:timestamp]).to be_a(Time)
104
+ end
105
+
106
+ it 'reflects resolved state in to_h' do
107
+ event.resolve!(:belief_revision)
108
+ h = event.to_h
109
+ expect(h[:resolved]).to be true
110
+ expect(h[:resolution_strategy]).to eq(:belief_revision)
111
+ end
112
+ end
113
+ end