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,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Defense
9
+ module Phantom
10
+ module Helpers
11
+ class PhantomLimb
12
+ ADAPT_DECAY_MULTIPLIER = 2.5
13
+
14
+ attr_reader :id, :capability_name, :capability_domain, :removed_at,
15
+ :activation_count, :last_triggered, :trigger_history
16
+
17
+ def initialize(capability_name:, capability_domain:)
18
+ @id = SecureRandom.uuid
19
+ @capability_name = capability_name
20
+ @capability_domain = capability_domain
21
+ @removed_at = Time.now.utc
22
+ @intensity = Constants::INITIAL_INTENSITY
23
+ @activation_count = 0
24
+ @last_triggered = nil
25
+ @trigger_history = []
26
+ end
27
+
28
+ def intensity
29
+ @intensity.round(10)
30
+ end
31
+
32
+ def state
33
+ Constants.state_for(@intensity)
34
+ end
35
+
36
+ def trigger!(stimulus)
37
+ return false if resolved?
38
+
39
+ @activation_count += 1
40
+ prev_triggered = @last_triggered
41
+ @last_triggered = Time.now.utc
42
+ signal = PhantomSignal.new(
43
+ phantom_limb_id: @id,
44
+ stimulus: stimulus,
45
+ trigger_type: classify_trigger(stimulus, prev_triggered),
46
+ intensity_at_trigger: @intensity
47
+ )
48
+ @trigger_history << signal
49
+ @trigger_history.shift while @trigger_history.size > 50
50
+ boost = (@intensity * 0.05).clamp(0.0, 0.1)
51
+ @intensity = (@intensity + boost).clamp(Constants::MIN_INTENSITY, 1.0)
52
+ signal
53
+ end
54
+
55
+ def decay!
56
+ return if resolved?
57
+
58
+ @intensity = (@intensity - Constants::INTENSITY_DECAY).clamp(Constants::MIN_INTENSITY, 1.0)
59
+ end
60
+
61
+ def adapt!
62
+ return if resolved?
63
+
64
+ accelerated = Constants::INTENSITY_DECAY * ADAPT_DECAY_MULTIPLIER
65
+ @intensity = (@intensity - accelerated).clamp(Constants::MIN_INTENSITY, 1.0)
66
+ end
67
+
68
+ def resolved?
69
+ @intensity <= Constants::MIN_INTENSITY
70
+ end
71
+
72
+ def to_h
73
+ {
74
+ id: @id,
75
+ capability_name: @capability_name,
76
+ capability_domain: @capability_domain,
77
+ removed_at: @removed_at,
78
+ intensity: intensity,
79
+ activation_count: @activation_count,
80
+ last_triggered: @last_triggered,
81
+ state: state,
82
+ resolved: resolved?
83
+ }
84
+ end
85
+
86
+ private
87
+
88
+ def classify_trigger(stimulus, prev_triggered)
89
+ return :stimulus_match if stimulus.is_a?(String) && stimulus.include?(@capability_name.to_s)
90
+
91
+ return :temporal_pattern if prev_triggered && (Time.now.utc - prev_triggered) < 60
92
+
93
+ return :habitual if @activation_count > 10
94
+
95
+ :contextual_association
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Defense
9
+ module Phantom
10
+ module Helpers
11
+ class PhantomSignal
12
+ attr_reader :id, :phantom_limb_id, :stimulus, :trigger_type,
13
+ :intensity_at_trigger, :timestamp
14
+
15
+ def initialize(phantom_limb_id:, stimulus:, trigger_type:, intensity_at_trigger:)
16
+ @id = SecureRandom.uuid
17
+ @phantom_limb_id = phantom_limb_id
18
+ @stimulus = stimulus
19
+ @trigger_type = trigger_type
20
+ @intensity_at_trigger = intensity_at_trigger.clamp(0.0, 1.0)
21
+ @timestamp = Time.now.utc
22
+ end
23
+
24
+ def to_h
25
+ {
26
+ id: @id,
27
+ phantom_limb_id: @phantom_limb_id,
28
+ stimulus: @stimulus,
29
+ trigger_type: @trigger_type,
30
+ intensity_at_trigger: @intensity_at_trigger.round(10),
31
+ timestamp: @timestamp
32
+ }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Phantom
8
+ module Runners
9
+ module CognitivePhantom
10
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
11
+ Legion::Extensions::Helpers.const_defined?(:Lex)
12
+
13
+ def register_removal(capability_name:, capability_domain: :general, engine: nil, **)
14
+ raise ArgumentError, 'capability_name is required' if capability_name.nil? || capability_name.to_s.strip.empty?
15
+
16
+ eng = engine || phantom_engine
17
+ limb = eng.register_removal(capability_name: capability_name, capability_domain: capability_domain)
18
+ return { success: false, error: 'MAX_PHANTOMS limit reached' } unless limb
19
+
20
+ Legion::Logging.debug "[cognitive_phantom] register_removal capability=#{capability_name}"
21
+ { success: true, phantom_id: limb.id, capability_name: capability_name, state: limb.state, intensity: limb.intensity }
22
+ rescue ArgumentError => e
23
+ { success: false, error: e.message }
24
+ end
25
+
26
+ def process_stimulus(stimulus:, domain: :general, engine: nil, **)
27
+ raise ArgumentError, 'stimulus is required' if stimulus.nil?
28
+
29
+ eng = engine || phantom_engine
30
+ fired = eng.process_stimulus(stimulus: stimulus, domain: domain)
31
+ Legion::Logging.debug "[cognitive_phantom] process_stimulus domain=#{domain} fired=#{fired.size}"
32
+ {
33
+ success: true,
34
+ fired_count: fired.size,
35
+ signals: fired.map(&:to_h),
36
+ domain: domain
37
+ }
38
+ rescue ArgumentError => e
39
+ { success: false, error: e.message }
40
+ end
41
+
42
+ def acknowledge_phantom(phantom_id:, engine: nil, **)
43
+ raise ArgumentError, 'phantom_id is required' if phantom_id.nil? || phantom_id.to_s.strip.empty?
44
+
45
+ eng = engine || phantom_engine
46
+ result = eng.acknowledge(phantom_id: phantom_id)
47
+ Legion::Logging.debug "[cognitive_phantom] acknowledge phantom_id=#{phantom_id[0..7]}"
48
+ result.merge(success: result[:acknowledged])
49
+ rescue ArgumentError => e
50
+ { success: false, error: e.message }
51
+ end
52
+
53
+ def phantom_status(engine: nil, **)
54
+ eng = engine || phantom_engine
55
+ report = eng.phantom_activity_report
56
+ Legion::Logging.debug "[cognitive_phantom] phantom_status total=#{report[:total]} active=#{report[:active]}"
57
+ { success: true, **report }
58
+ end
59
+
60
+ def decay_all(engine: nil, **)
61
+ eng = engine || phantom_engine
62
+ resolved_count = eng.decay_all!
63
+ report = eng.phantom_activity_report
64
+ Legion::Logging.debug "[cognitive_phantom] decay_all resolved=#{resolved_count}"
65
+ { success: true, resolved_this_cycle: resolved_count, **report }
66
+ end
67
+
68
+ private
69
+
70
+ def phantom_engine
71
+ @phantom_engine ||= Helpers::PhantomEngine.new
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ 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 Phantom
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'legion/extensions/agentic/defense/phantom/version'
5
+ require 'legion/extensions/agentic/defense/phantom/helpers/constants'
6
+ require 'legion/extensions/agentic/defense/phantom/helpers/phantom_signal'
7
+ require 'legion/extensions/agentic/defense/phantom/helpers/phantom_limb'
8
+ require 'legion/extensions/agentic/defense/phantom/helpers/phantom_engine'
9
+ require 'legion/extensions/agentic/defense/phantom/runners/cognitive_phantom'
10
+ require 'legion/extensions/agentic/defense/phantom/client'
11
+
12
+ module Legion
13
+ module Extensions
14
+ module Agentic
15
+ module Defense
16
+ module Phantom
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Quicksand
8
+ class Client
9
+ include Runners::CognitiveQuicksand
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Quicksand
8
+ module Helpers
9
+ module Constants
10
+ TRAP_TYPES = %i[overthinking rumination analysis_paralysis
11
+ perfectionism indecision].freeze
12
+
13
+ STRUGGLE_MODES = %i[thrash freeze sink float escape].freeze
14
+
15
+ MAX_TRAPS = 200
16
+ MAX_PITS = 50
17
+ SINK_RATE = 0.08
18
+ STRUGGLE_PENALTY = 0.12
19
+ ESCAPE_THRESHOLD = 0.3
20
+ CALM_RATE = 0.03
21
+
22
+ DEPTH_LABELS = [
23
+ [(0.8..), :submerged],
24
+ [(0.6...0.8), :chest_deep],
25
+ [(0.4...0.6), :waist_deep],
26
+ [(0.2...0.4), :ankle_deep],
27
+ [(..0.2), :surface]
28
+ ].freeze
29
+
30
+ VISCOSITY_LABELS = [
31
+ [(0.8..), :concrete],
32
+ [(0.6...0.8), :thick],
33
+ [(0.4...0.6), :moderate],
34
+ [(0.2...0.4), :thin],
35
+ [(..0.2), :dry]
36
+ ].freeze
37
+
38
+ def self.label_for(table, value)
39
+ table.each { |range, label| return label if range.cover?(value) }
40
+ table.last.last
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Quicksand
8
+ module Helpers
9
+ class Pit
10
+ attr_reader :id, :trap_ids, :created_at
11
+ attr_accessor :saturation, :danger_level
12
+
13
+ def initialize(saturation: nil, danger_level: nil)
14
+ @id = SecureRandom.uuid
15
+ @saturation = (saturation || 0.5).to_f.clamp(0.0, 1.0).round(10)
16
+ @danger_level = (danger_level || 0.3).to_f.clamp(0.0, 1.0).round(10)
17
+ @trap_ids = []
18
+ @created_at = Time.now.utc
19
+ end
20
+
21
+ def add_trap(trap_id)
22
+ return :already_present if @trap_ids.include?(trap_id)
23
+
24
+ @trap_ids << trap_id
25
+ recalculate_danger!
26
+ :added
27
+ end
28
+
29
+ def remove_trap(trap_id)
30
+ return :not_found unless @trap_ids.include?(trap_id)
31
+
32
+ @trap_ids.delete(trap_id)
33
+ recalculate_danger!
34
+ :removed
35
+ end
36
+
37
+ def saturate!(rate: 0.1)
38
+ @saturation = (@saturation + rate.abs).clamp(0.0, 1.0).round(10)
39
+ end
40
+
41
+ def drain!(rate: 0.1)
42
+ @saturation = (@saturation - rate.abs).clamp(0.0, 1.0).round(10)
43
+ recalculate_danger!
44
+ end
45
+
46
+ def deadly?
47
+ @danger_level >= 0.8
48
+ end
49
+
50
+ def safe?
51
+ @danger_level < 0.2
52
+ end
53
+
54
+ def trap_count
55
+ @trap_ids.size
56
+ end
57
+
58
+ def to_h
59
+ {
60
+ id: @id,
61
+ saturation: @saturation,
62
+ danger_level: @danger_level,
63
+ trap_count: trap_count,
64
+ deadly: deadly?,
65
+ safe: safe?,
66
+ created_at: @created_at
67
+ }
68
+ end
69
+
70
+ private
71
+
72
+ def recalculate_danger!
73
+ trap_factor = (@trap_ids.size / 10.0).clamp(0.0, 1.0)
74
+ @danger_level = ((trap_factor + @saturation) / 2.0).clamp(0.0, 1.0).round(10)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Quicksand
8
+ module Helpers
9
+ class QuicksandEngine
10
+ def initialize
11
+ @traps = {}
12
+ @pits = {}
13
+ end
14
+
15
+ def create_trap(trap_type:, domain:, content:, depth: nil, viscosity: nil)
16
+ raise ArgumentError, 'trap limit reached' if @traps.size >= Constants::MAX_TRAPS
17
+
18
+ t = Trap.new(trap_type: trap_type, domain: domain, content: content,
19
+ depth: depth, viscosity: viscosity)
20
+ @traps[t.id] = t
21
+ t
22
+ end
23
+
24
+ def create_pit(saturation: nil, danger_level: nil)
25
+ raise ArgumentError, 'pit limit reached' if @pits.size >= Constants::MAX_PITS
26
+
27
+ p = Pit.new(saturation: saturation, danger_level: danger_level)
28
+ @pits[p.id] = p
29
+ p
30
+ end
31
+
32
+ def sink_trap(trap_id:, rate: Constants::SINK_RATE)
33
+ trap = fetch_trap(trap_id)
34
+ trap.sink!(rate: rate)
35
+ trap
36
+ end
37
+
38
+ def struggle(trap_id:)
39
+ trap = fetch_trap(trap_id)
40
+ trap.struggle!
41
+ { trap: trap, depth: trap.depth, struggle_count: trap.struggle_count }
42
+ end
43
+
44
+ def calm(trap_id:, rate: Constants::CALM_RATE)
45
+ trap = fetch_trap(trap_id)
46
+ trap.calm!(rate: rate)
47
+ trap
48
+ end
49
+
50
+ def attempt_escape(trap_id:)
51
+ trap = fetch_trap(trap_id)
52
+ result = trap.escape!
53
+ { trap: trap, result: result }
54
+ end
55
+
56
+ def add_trap_to_pit(trap_id:, pit_id:)
57
+ fetch_trap(trap_id)
58
+ pit = fetch_pit(pit_id)
59
+ pit.add_trap(trap_id)
60
+ end
61
+
62
+ def sink_all!
63
+ @traps.each_value(&:sink!)
64
+ end
65
+
66
+ def calm_all!
67
+ @traps.each_value(&:calm!)
68
+ end
69
+
70
+ def traps_by_type
71
+ counts = Constants::TRAP_TYPES.to_h { |t| [t, 0] }
72
+ @traps.each_value { |t| counts[t.trap_type] += 1 }
73
+ counts
74
+ end
75
+
76
+ def deepest(limit: 5)
77
+ @traps.values.sort_by { |t| -t.depth }.first(limit)
78
+ end
79
+
80
+ def shallowest(limit: 5)
81
+ @traps.values.sort_by(&:depth).first(limit)
82
+ end
83
+
84
+ def submerged_traps
85
+ @traps.values.select(&:submerged?)
86
+ end
87
+
88
+ def stuck_traps
89
+ @traps.values.select(&:stuck?)
90
+ end
91
+
92
+ def deadliest_pits(limit: 5)
93
+ @pits.values.sort_by { |p| -p.danger_level }.first(limit)
94
+ end
95
+
96
+ def avg_depth
97
+ return 0.0 if @traps.empty?
98
+
99
+ (@traps.values.sum(&:depth) / @traps.size).round(10)
100
+ end
101
+
102
+ def quicksand_report
103
+ {
104
+ total_traps: @traps.size,
105
+ total_pits: @pits.size,
106
+ by_type: traps_by_type,
107
+ submerged: submerged_traps.size,
108
+ stuck: stuck_traps.size,
109
+ avg_depth: avg_depth,
110
+ deadly_pits: @pits.values.count(&:deadly?)
111
+ }
112
+ end
113
+
114
+ def all_traps
115
+ @traps.values
116
+ end
117
+
118
+ def all_pits
119
+ @pits.values
120
+ end
121
+
122
+ private
123
+
124
+ def fetch_trap(id)
125
+ @traps.fetch(id) { raise ArgumentError, "trap not found: #{id}" }
126
+ end
127
+
128
+ def fetch_pit(id)
129
+ @pits.fetch(id) { raise ArgumentError, "pit not found: #{id}" }
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Quicksand
8
+ module Helpers
9
+ class Trap
10
+ attr_reader :id, :trap_type, :domain, :content,
11
+ :struggle_count, :created_at
12
+ attr_accessor :depth, :viscosity
13
+
14
+ def initialize(trap_type:, domain:, content:,
15
+ depth: nil, viscosity: nil)
16
+ validate_trap_type!(trap_type)
17
+ @id = SecureRandom.uuid
18
+ @trap_type = trap_type.to_sym
19
+ @domain = domain.to_sym
20
+ @content = content.to_s
21
+ @depth = (depth || 0.3).to_f.clamp(0.0, 1.0).round(10)
22
+ @viscosity = (viscosity || 0.5).to_f.clamp(0.0, 1.0).round(10)
23
+ @struggle_count = 0
24
+ @created_at = Time.now.utc
25
+ end
26
+
27
+ def sink!(rate: Constants::SINK_RATE)
28
+ @depth = (@depth + rate.abs).clamp(0.0, 1.0).round(10)
29
+ end
30
+
31
+ def struggle!
32
+ @struggle_count += 1
33
+ penalty = Constants::STRUGGLE_PENALTY * @viscosity
34
+ @depth = (@depth + penalty).clamp(0.0, 1.0).round(10)
35
+ end
36
+
37
+ def calm!(rate: Constants::CALM_RATE)
38
+ @depth = (@depth - rate.abs).clamp(0.0, 1.0).round(10)
39
+ end
40
+
41
+ def escape!
42
+ return :too_deep if @depth > (1.0 - Constants::ESCAPE_THRESHOLD)
43
+
44
+ @depth = 0.0
45
+ :escaped
46
+ end
47
+
48
+ def submerged?
49
+ @depth >= 0.8
50
+ end
51
+
52
+ def surface?
53
+ @depth < 0.2
54
+ end
55
+
56
+ def stuck?
57
+ @depth >= 0.5 && @viscosity >= 0.5
58
+ end
59
+
60
+ def depth_label
61
+ Constants.label_for(Constants::DEPTH_LABELS, @depth)
62
+ end
63
+
64
+ def viscosity_label
65
+ Constants.label_for(Constants::VISCOSITY_LABELS, @viscosity)
66
+ end
67
+
68
+ def to_h
69
+ {
70
+ id: @id,
71
+ trap_type: @trap_type,
72
+ domain: @domain,
73
+ content: @content,
74
+ depth: @depth,
75
+ viscosity: @viscosity,
76
+ depth_label: depth_label,
77
+ viscosity_label: viscosity_label,
78
+ struggle_count: @struggle_count,
79
+ submerged: submerged?,
80
+ surface: surface?,
81
+ stuck: stuck?,
82
+ created_at: @created_at
83
+ }
84
+ end
85
+
86
+ private
87
+
88
+ def validate_trap_type!(val)
89
+ return if Constants::TRAP_TYPES.include?(val.to_sym)
90
+
91
+ raise ArgumentError,
92
+ "unknown trap type: #{val.inspect}; " \
93
+ "must be one of #{Constants::TRAP_TYPES.inspect}"
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end