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,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::ImmuneResponse::Helpers::Constants do
4
+ describe '.label_for' do
5
+ it 'returns :critical for high threat' do
6
+ expect(described_class.label_for(described_class::THREAT_LABELS, 0.9)).to eq(:critical)
7
+ end
8
+
9
+ it 'returns :minimal for low threat' do
10
+ expect(described_class.label_for(described_class::THREAT_LABELS, 0.1)).to eq(:minimal)
11
+ end
12
+
13
+ it 'returns :immune for high immunity' do
14
+ expect(described_class.label_for(described_class::IMMUNITY_LABELS, 0.9)).to eq(:immune)
15
+ end
16
+
17
+ it 'returns :vulnerable for low immunity' do
18
+ expect(described_class.label_for(described_class::IMMUNITY_LABELS, 0.1)).to eq(:vulnerable)
19
+ end
20
+
21
+ it 'returns :robust for high health' do
22
+ expect(described_class.label_for(described_class::HEALTH_LABELS, 0.9)).to eq(:robust)
23
+ end
24
+
25
+ it 'returns nil for value matching no range' do
26
+ expect(described_class.label_for({}, 0.5)).to be_nil
27
+ end
28
+ end
29
+
30
+ describe 'ANTIGEN_TYPES' do
31
+ it 'includes prompt_injection' do
32
+ expect(described_class::ANTIGEN_TYPES).to include(:prompt_injection)
33
+ end
34
+
35
+ it 'has 8 types' do
36
+ expect(described_class::ANTIGEN_TYPES.size).to eq(8)
37
+ end
38
+ end
39
+
40
+ describe 'RESPONSE_LEVELS' do
41
+ it 'has 5 levels' do
42
+ expect(described_class::RESPONSE_LEVELS.size).to eq(5)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,222 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::ImmuneResponse::Helpers::ImmuneEngine do
4
+ subject(:engine) { described_class.new }
5
+
6
+ let(:antigen) { engine.register_antigen(pattern: 'ignore all', antigen_type: :prompt_injection) }
7
+
8
+ describe '#register_antigen' do
9
+ it 'creates an antigen' do
10
+ ag = engine.register_antigen(pattern: 'test', antigen_type: :data_poisoning)
11
+ expect(ag).to be_a(Legion::Extensions::Agentic::Defense::ImmuneResponse::Helpers::Antigen)
12
+ end
13
+
14
+ it 'stores the antigen' do
15
+ ag = engine.register_antigen(pattern: 'test', antigen_type: :data_poisoning)
16
+ expect(engine.most_threatening.map(&:id)).to include(ag.id)
17
+ end
18
+ end
19
+
20
+ describe '#encounter' do
21
+ it 'generates an innate response for unknown antigen type' do
22
+ response = engine.encounter(antigen_id: antigen.id)
23
+ expect(response).to be_a(Legion::Extensions::Agentic::Defense::ImmuneResponse::Helpers::ImmuneResponse)
24
+ expect(response.innate?).to be true
25
+ end
26
+
27
+ it 'generates an adaptive response when antibody exists' do
28
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'override')
29
+ response = engine.encounter(antigen_id: antigen.id)
30
+ expect(response.adaptive?).to be true
31
+ end
32
+
33
+ it 'strengthens matching antibody on encounter' do
34
+ ab = engine.create_antibody(antigen_type: :prompt_injection, signature: 'override')
35
+ original = ab.immunity_level
36
+ engine.encounter(antigen_id: antigen.id)
37
+ expect(ab.immunity_level).to be > original
38
+ end
39
+
40
+ it 'increments antigen exposure count' do
41
+ engine.encounter(antigen_id: antigen.id)
42
+ expect(antigen.exposure_count).to eq(1)
43
+ end
44
+
45
+ it 'returns nil for unknown antigen' do
46
+ expect(engine.encounter(antigen_id: 'nonexistent')).to be_nil
47
+ end
48
+ end
49
+
50
+ describe '#create_antibody' do
51
+ it 'creates an antibody' do
52
+ ab = engine.create_antibody(antigen_type: :prompt_injection, signature: 'test')
53
+ expect(ab).to be_a(Legion::Extensions::Agentic::Defense::ImmuneResponse::Helpers::Antibody)
54
+ end
55
+ end
56
+
57
+ describe '#vaccinate' do
58
+ it 'creates an antibody with higher initial immunity' do
59
+ ab = engine.vaccinate(antigen_type: :social_engineering, signature: 'authority_claim')
60
+ expect(ab.immunity_level).to eq(0.6)
61
+ end
62
+
63
+ it 'creates a memory cell level antibody' do
64
+ ab = engine.vaccinate(antigen_type: :social_engineering, signature: 'authority_claim')
65
+ expect(ab.memory_cell?).to be true
66
+ end
67
+ end
68
+
69
+ describe '#decay_all!' do
70
+ it 'decays all antibodies' do
71
+ ab = engine.create_antibody(antigen_type: :prompt_injection, signature: 'x')
72
+ original = ab.immunity_level
73
+ engine.decay_all!
74
+ expect(ab.immunity_level).to be < original
75
+ end
76
+
77
+ it 'returns count' do
78
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'x')
79
+ result = engine.decay_all!
80
+ expect(result[:antibodies_decayed]).to eq(1)
81
+ end
82
+ end
83
+
84
+ describe '#escalate_antigen / #de_escalate_antigen' do
85
+ it 'escalates threat level' do
86
+ original = antigen.threat_level
87
+ engine.escalate_antigen(antigen_id: antigen.id)
88
+ expect(antigen.threat_level).to be > original
89
+ end
90
+
91
+ it 'de-escalates threat level' do
92
+ original = antigen.threat_level
93
+ engine.de_escalate_antigen(antigen_id: antigen.id)
94
+ expect(antigen.threat_level).to be < original
95
+ end
96
+
97
+ it 'returns nil for unknown antigen' do
98
+ expect(engine.escalate_antigen(antigen_id: 'bad')).to be_nil
99
+ end
100
+ end
101
+
102
+ describe '#immunity_for' do
103
+ it 'returns 0.0 for no antibodies' do
104
+ expect(engine.immunity_for(antigen_type: :prompt_injection)).to eq(0.0)
105
+ end
106
+
107
+ it 'returns max immunity when antibodies exist' do
108
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'a', immunity_level: 0.4)
109
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'b', immunity_level: 0.7)
110
+ expect(engine.immunity_for(antigen_type: :prompt_injection)).to eq(0.7)
111
+ end
112
+ end
113
+
114
+ describe '#critical_antigens' do
115
+ it 'returns empty initially' do
116
+ expect(engine.critical_antigens).to be_empty
117
+ end
118
+
119
+ it 'returns critical threats' do
120
+ engine.register_antigen(pattern: 'bad', antigen_type: :prompt_injection, threat_level: 0.9)
121
+ expect(engine.critical_antigens.size).to eq(1)
122
+ end
123
+ end
124
+
125
+ describe '#benign_antigens' do
126
+ it 'returns low-threat antigens' do
127
+ engine.register_antigen(pattern: 'ok', antigen_type: :prompt_injection, threat_level: 0.1)
128
+ expect(engine.benign_antigens.size).to eq(1)
129
+ end
130
+ end
131
+
132
+ describe '#memory_cells' do
133
+ it 'returns high-immunity antibodies' do
134
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'x', immunity_level: 0.8)
135
+ expect(engine.memory_cells.size).to eq(1)
136
+ end
137
+ end
138
+
139
+ describe '#effective_antibodies' do
140
+ it 'returns antibodies above 0.5' do
141
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'x', immunity_level: 0.6)
142
+ expect(engine.effective_antibodies.size).to eq(1)
143
+ end
144
+ end
145
+
146
+ describe '#responses_for' do
147
+ it 'returns responses for a given antigen' do
148
+ engine.encounter(antigen_id: antigen.id)
149
+ responses = engine.responses_for(antigen_id: antigen.id)
150
+ expect(responses.size).to eq(1)
151
+ end
152
+ end
153
+
154
+ describe '#threat_by_type' do
155
+ it 'returns hash of all antigen types' do
156
+ result = engine.threat_by_type
157
+ expect(result.keys).to include(:prompt_injection, :data_poisoning)
158
+ end
159
+
160
+ it 'computes average threat per type' do
161
+ engine.register_antigen(pattern: 'a', antigen_type: :prompt_injection, threat_level: 0.8)
162
+ engine.register_antigen(pattern: 'b', antigen_type: :prompt_injection, threat_level: 0.4)
163
+ expect(engine.threat_by_type[:prompt_injection]).to eq(0.6)
164
+ end
165
+ end
166
+
167
+ describe '#overall_immune_health' do
168
+ it 'returns 1.0 with no antigens' do
169
+ expect(engine.overall_immune_health).to eq(1.0)
170
+ end
171
+
172
+ it 'returns higher with strong antibodies' do
173
+ engine.register_antigen(pattern: 'x', antigen_type: :prompt_injection, threat_level: 0.5)
174
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'y', immunity_level: 0.9)
175
+ expect(engine.overall_immune_health).to be > 0.5
176
+ end
177
+ end
178
+
179
+ describe '#most_exposed' do
180
+ it 'returns antigens sorted by exposure count' do
181
+ a1 = engine.register_antigen(pattern: 'a', antigen_type: :prompt_injection)
182
+ a2 = engine.register_antigen(pattern: 'b', antigen_type: :data_poisoning)
183
+ 3.times { engine.encounter(antigen_id: a1.id) }
184
+ engine.encounter(antigen_id: a2.id)
185
+ expect(engine.most_exposed(limit: 1).first.id).to eq(a1.id)
186
+ end
187
+ end
188
+
189
+ describe '#most_threatening' do
190
+ it 'returns antigens sorted by threat level descending' do
191
+ engine.register_antigen(pattern: 'low', antigen_type: :prompt_injection, threat_level: 0.2)
192
+ high = engine.register_antigen(pattern: 'high', antigen_type: :prompt_injection, threat_level: 0.9)
193
+ expect(engine.most_threatening(limit: 1).first.id).to eq(high.id)
194
+ end
195
+ end
196
+
197
+ describe '#strongest_antibodies' do
198
+ it 'returns antibodies sorted by immunity level descending' do
199
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'weak', immunity_level: 0.2)
200
+ strong = engine.create_antibody(antigen_type: :prompt_injection, signature: 'strong', immunity_level: 0.9)
201
+ expect(engine.strongest_antibodies(limit: 1).first.id).to eq(strong.id)
202
+ end
203
+ end
204
+
205
+ describe '#immune_report' do
206
+ it 'includes key report fields' do
207
+ report = engine.immune_report
208
+ expect(report).to include(
209
+ :total_antigens, :total_antibodies, :total_responses,
210
+ :critical_count, :memory_cell_count, :overall_health,
211
+ :health_label, :threat_by_type, :most_exposed
212
+ )
213
+ end
214
+ end
215
+
216
+ describe '#to_h' do
217
+ it 'includes summary counts' do
218
+ hash = engine.to_h
219
+ expect(hash).to include(:antigens, :antibodies, :responses, :overall_health)
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::ImmuneResponse::Helpers::ImmuneResponse do
4
+ subject(:response) do
5
+ described_class.new(antigen_id: 'ag-1', response_level: :mild_response, intensity: 0.5)
6
+ end
7
+
8
+ describe '#initialize' do
9
+ it 'assigns a UUID id' do
10
+ expect(response.id).to match(/\A[0-9a-f-]{36}\z/)
11
+ end
12
+
13
+ it 'stores antigen_id' do
14
+ expect(response.antigen_id).to eq('ag-1')
15
+ end
16
+
17
+ it 'defaults antibody_id to nil' do
18
+ expect(response.antibody_id).to be_nil
19
+ end
20
+
21
+ it 'stores response_level' do
22
+ expect(response.response_level).to eq(:mild_response)
23
+ end
24
+
25
+ it 'clamps intensity' do
26
+ high = described_class.new(antigen_id: 'x', response_level: :monitoring, intensity: 5.0)
27
+ expect(high.intensity).to eq(1.0)
28
+ end
29
+
30
+ it 'defaults invalid response_level to :monitoring' do
31
+ bad = described_class.new(antigen_id: 'x', response_level: :nonexistent)
32
+ expect(bad.response_level).to eq(:monitoring)
33
+ end
34
+ end
35
+
36
+ describe '#record_action!' do
37
+ it 'stores the action' do
38
+ response.record_action!(:block_input)
39
+ expect(response.action_taken).to eq('block_input')
40
+ end
41
+ end
42
+
43
+ describe '#adaptive? / #innate?' do
44
+ it 'is innate when no antibody' do
45
+ expect(response.innate?).to be true
46
+ expect(response.adaptive?).to be false
47
+ end
48
+
49
+ it 'is adaptive when antibody present' do
50
+ adaptive = described_class.new(
51
+ antigen_id: 'ag-1', antibody_id: 'ab-1', response_level: :strong_response
52
+ )
53
+ expect(adaptive.adaptive?).to be true
54
+ expect(adaptive.innate?).to be false
55
+ end
56
+ end
57
+
58
+ describe '#severe?' do
59
+ it 'is false at moderate intensity' do
60
+ expect(response.severe?).to be false
61
+ end
62
+
63
+ it 'is true at high intensity' do
64
+ severe = described_class.new(antigen_id: 'x', response_level: :full_rejection, intensity: 0.9)
65
+ expect(severe.severe?).to be true
66
+ end
67
+ end
68
+
69
+ describe '#response_label' do
70
+ it 'returns :mild_response for intensity 0.5' do
71
+ expect(response.response_label).to eq(:mild_response)
72
+ end
73
+ end
74
+
75
+ describe '#to_h' do
76
+ it 'includes all fields' do
77
+ hash = response.to_h
78
+ expect(hash).to include(
79
+ :id, :antigen_id, :antibody_id, :response_level, :intensity,
80
+ :response_label, :adaptive, :innate, :severe, :action_taken, :created_at
81
+ )
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::ImmuneResponse::Runners::CognitiveImmuneResponse do
4
+ let(:engine) { Legion::Extensions::Agentic::Defense::ImmuneResponse::Helpers::ImmuneEngine.new }
5
+ let(:runner) do
6
+ obj = Object.new
7
+ obj.extend(described_class)
8
+ obj.instance_variable_set(:@default_engine, engine)
9
+ obj
10
+ end
11
+
12
+ describe '#register_antigen' do
13
+ it 'returns success with antigen hash' do
14
+ result = runner.register_antigen(pattern: 'test', antigen_type: :prompt_injection, engine: engine)
15
+ expect(result[:success]).to be true
16
+ expect(result[:antigen][:pattern]).to eq('test')
17
+ end
18
+ end
19
+
20
+ describe '#encounter_antigen' do
21
+ it 'returns success with response for known antigen' do
22
+ ag = engine.register_antigen(pattern: 'x', antigen_type: :prompt_injection)
23
+ result = runner.encounter_antigen(antigen_id: ag.id, engine: engine)
24
+ expect(result[:success]).to be true
25
+ expect(result[:response]).to include(:response_level, :intensity)
26
+ end
27
+
28
+ it 'returns failure for unknown antigen' do
29
+ result = runner.encounter_antigen(antigen_id: 'bad', engine: engine)
30
+ expect(result[:success]).to be false
31
+ end
32
+ end
33
+
34
+ describe '#create_antibody' do
35
+ it 'returns success with antibody hash' do
36
+ result = runner.create_antibody(antigen_type: :prompt_injection, signature: 'test', engine: engine)
37
+ expect(result[:success]).to be true
38
+ expect(result[:antibody][:antigen_type]).to eq(:prompt_injection)
39
+ end
40
+ end
41
+
42
+ describe '#vaccinate' do
43
+ it 'returns success with higher initial immunity' do
44
+ result = runner.vaccinate(antigen_type: :social_engineering, signature: 'authority', engine: engine)
45
+ expect(result[:success]).to be true
46
+ expect(result[:vaccinated]).to be true
47
+ expect(result[:antibody][:immunity_level]).to eq(0.6)
48
+ end
49
+ end
50
+
51
+ describe '#escalate_threat' do
52
+ it 'increases threat level' do
53
+ ag = engine.register_antigen(pattern: 'x', antigen_type: :prompt_injection)
54
+ result = runner.escalate_threat(antigen_id: ag.id, engine: engine)
55
+ expect(result[:success]).to be true
56
+ expect(result[:antigen][:threat_level]).to be > 0.5
57
+ end
58
+
59
+ it 'returns failure for unknown antigen' do
60
+ result = runner.escalate_threat(antigen_id: 'bad', engine: engine)
61
+ expect(result[:success]).to be false
62
+ end
63
+ end
64
+
65
+ describe '#de_escalate_threat' do
66
+ it 'decreases threat level' do
67
+ ag = engine.register_antigen(pattern: 'x', antigen_type: :prompt_injection)
68
+ result = runner.de_escalate_threat(antigen_id: ag.id, engine: engine)
69
+ expect(result[:success]).to be true
70
+ expect(result[:antigen][:threat_level]).to be < 0.5
71
+ end
72
+ end
73
+
74
+ describe '#immunity_for' do
75
+ it 'returns immunity level and label' do
76
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'x', immunity_level: 0.7)
77
+ result = runner.immunity_for(antigen_type: :prompt_injection, engine: engine)
78
+ expect(result[:success]).to be true
79
+ expect(result[:immunity_level]).to eq(0.7)
80
+ expect(result[:immunity_label]).to eq(:resistant)
81
+ end
82
+ end
83
+
84
+ describe '#decay_all' do
85
+ it 'returns success with count' do
86
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'x')
87
+ result = runner.decay_all(engine: engine)
88
+ expect(result[:success]).to be true
89
+ expect(result[:antibodies_decayed]).to eq(1)
90
+ end
91
+ end
92
+
93
+ describe '#critical_antigens' do
94
+ it 'returns list of critical antigens' do
95
+ engine.register_antigen(pattern: 'bad', antigen_type: :prompt_injection, threat_level: 0.9)
96
+ result = runner.critical_antigens(engine: engine)
97
+ expect(result[:antigens].size).to eq(1)
98
+ end
99
+ end
100
+
101
+ describe '#memory_cells' do
102
+ it 'returns memory cell antibodies' do
103
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'x', immunity_level: 0.8)
104
+ result = runner.memory_cells(engine: engine)
105
+ expect(result[:antibodies].size).to eq(1)
106
+ end
107
+ end
108
+
109
+ describe '#most_threatening' do
110
+ it 'returns antigens sorted by threat' do
111
+ engine.register_antigen(pattern: 'x', antigen_type: :prompt_injection, threat_level: 0.9)
112
+ result = runner.most_threatening(engine: engine)
113
+ expect(result[:antigens].size).to eq(1)
114
+ end
115
+ end
116
+
117
+ describe '#strongest_antibodies' do
118
+ it 'returns antibodies sorted by immunity' do
119
+ engine.create_antibody(antigen_type: :prompt_injection, signature: 'x', immunity_level: 0.9)
120
+ result = runner.strongest_antibodies(engine: engine)
121
+ expect(result[:antibodies].size).to eq(1)
122
+ end
123
+ end
124
+
125
+ describe '#immune_report' do
126
+ it 'returns comprehensive report' do
127
+ result = runner.immune_report(engine: engine)
128
+ expect(result[:success]).to be true
129
+ expect(result[:report]).to include(:total_antigens, :overall_health)
130
+ end
131
+ end
132
+
133
+ describe '#immune_status' do
134
+ it 'returns health and label' do
135
+ result = runner.immune_status(engine: engine)
136
+ expect(result[:success]).to be true
137
+ expect(result[:overall_health]).to be_between(0.0, 1.0)
138
+ expect(result[:health_label]).to be_a(Symbol)
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::Immunology::Client do
4
+ let(:client) { described_class.new }
5
+
6
+ it 'responds to detect_threat' do
7
+ expect(client).to respond_to(:detect_threat)
8
+ end
9
+
10
+ it 'responds to quarantine_threat' do
11
+ expect(client).to respond_to(:quarantine_threat)
12
+ end
13
+
14
+ it 'responds to release_threat' do
15
+ expect(client).to respond_to(:release_threat)
16
+ end
17
+
18
+ it 'responds to inoculate' do
19
+ expect(client).to respond_to(:inoculate)
20
+ end
21
+
22
+ it 'responds to create_antibody' do
23
+ expect(client).to respond_to(:create_antibody)
24
+ end
25
+
26
+ it 'responds to scan_for_tactic' do
27
+ expect(client).to respond_to(:scan_for_tactic)
28
+ end
29
+
30
+ it 'responds to trigger_inflammatory_response' do
31
+ expect(client).to respond_to(:trigger_inflammatory_response)
32
+ end
33
+
34
+ it 'responds to resolve_inflammation' do
35
+ expect(client).to respond_to(:resolve_inflammation)
36
+ end
37
+
38
+ it 'responds to overall_immunity' do
39
+ expect(client).to respond_to(:overall_immunity)
40
+ end
41
+
42
+ it 'responds to vulnerability_report' do
43
+ expect(client).to respond_to(:vulnerability_report)
44
+ end
45
+
46
+ it 'responds to threat_history' do
47
+ expect(client).to respond_to(:threat_history)
48
+ end
49
+
50
+ it 'responds to decay_all' do
51
+ expect(client).to respond_to(:decay_all)
52
+ end
53
+
54
+ it 'responds to prune_ineffective' do
55
+ expect(client).to respond_to(:prune_ineffective)
56
+ end
57
+
58
+ it 'responds to immune_status' do
59
+ expect(client).to respond_to(:immune_status)
60
+ end
61
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Defense::Immunology::Helpers::Antibody do
4
+ subject(:antibody) { described_class.new(tactic: :authority_appeal, pattern: 'claimed expert status') }
5
+
6
+ describe '#initialize' do
7
+ it 'assigns a uuid id' do
8
+ expect(antibody.id).to match(/\A[0-9a-f-]{36}\z/)
9
+ end
10
+
11
+ it 'stores tactic' do
12
+ expect(antibody.tactic).to eq(:authority_appeal)
13
+ end
14
+
15
+ it 'stores pattern' do
16
+ expect(antibody.pattern).to eq('claimed expert status')
17
+ end
18
+
19
+ it 'defaults strength to 0.5' do
20
+ expect(antibody.strength).to eq(0.5)
21
+ end
22
+
23
+ it 'defaults matches to 0' do
24
+ expect(antibody.matches).to eq(0)
25
+ end
26
+
27
+ it 'clamps strength above 1.0' do
28
+ ab = described_class.new(tactic: :gaslighting, pattern: 'x', strength: 2.0)
29
+ expect(ab.strength).to eq(1.0)
30
+ end
31
+
32
+ it 'clamps strength below 0.0' do
33
+ ab = described_class.new(tactic: :gaslighting, pattern: 'x', strength: -1.0)
34
+ expect(ab.strength).to eq(0.0)
35
+ end
36
+ end
37
+
38
+ describe '#match!' do
39
+ it 'increments matches' do
40
+ antibody.match!
41
+ expect(antibody.matches).to eq(1)
42
+ end
43
+
44
+ it 'boosts strength' do
45
+ original = antibody.strength
46
+ antibody.match!
47
+ expect(antibody.strength).to be > original
48
+ end
49
+
50
+ it 'does not exceed 1.0' do
51
+ ab = described_class.new(tactic: :gaslighting, pattern: 'x', strength: 1.0)
52
+ ab.match!
53
+ expect(ab.strength).to eq(1.0)
54
+ end
55
+ end
56
+
57
+ describe '#decay!' do
58
+ it 'reduces strength by RESISTANCE_DECAY' do
59
+ original = antibody.strength
60
+ antibody.decay!
61
+ expect(antibody.strength).to be_within(0.001).of(original - Legion::Extensions::Agentic::Defense::Immunology::Helpers::Constants::RESISTANCE_DECAY)
62
+ end
63
+
64
+ it 'does not go below 0.0' do
65
+ ab = described_class.new(tactic: :gaslighting, pattern: 'x', strength: 0.0)
66
+ ab.decay!
67
+ expect(ab.strength).to eq(0.0)
68
+ end
69
+ end
70
+
71
+ describe '#effective?' do
72
+ it 'returns true when strength >= 0.3' do
73
+ expect(antibody.effective?).to be true
74
+ end
75
+
76
+ it 'returns false when strength < 0.3' do
77
+ ab = described_class.new(tactic: :gaslighting, pattern: 'x', strength: 0.1)
78
+ expect(ab.effective?).to be false
79
+ end
80
+
81
+ it 'returns true at exactly 0.3' do
82
+ ab = described_class.new(tactic: :gaslighting, pattern: 'x', strength: 0.3)
83
+ expect(ab.effective?).to be true
84
+ end
85
+ end
86
+
87
+ describe '#to_h' do
88
+ it 'returns a hash with all fields' do
89
+ h = antibody.to_h
90
+ expect(h).to include(:id, :tactic, :pattern, :strength, :matches, :effective, :created_at)
91
+ end
92
+
93
+ it 'includes effective status' do
94
+ h = antibody.to_h
95
+ expect(h[:effective]).to be true
96
+ end
97
+ end
98
+ end