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,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Defense
9
+ module Extinction
10
+ module Helpers
11
+ class ProtocolState
12
+ MAX_HISTORY = 500
13
+
14
+ attr_reader :current_level, :history, :active
15
+
16
+ def initialize
17
+ @current_level = 0 # 0 = normal operation
18
+ @active = false
19
+ @history = []
20
+ load_from_local
21
+ end
22
+
23
+ def escalate(level, authority:, reason:)
24
+ return :invalid_level unless Levels.valid_level?(level)
25
+ return :already_at_or_above if level <= @current_level
26
+ return :insufficient_authority unless authority == Levels.required_authority(level)
27
+
28
+ @current_level = level
29
+ @active = true
30
+ @history << {
31
+ action: :escalate, level: level, authority: authority,
32
+ reason: reason, at: Time.now.utc
33
+ }
34
+ trim_history
35
+ save_to_local
36
+ :escalated
37
+ end
38
+
39
+ def deescalate(target_level, authority:, reason:)
40
+ return :not_active unless @active
41
+ return :invalid_target if target_level >= @current_level
42
+ return :irreversible unless Levels.reversible?(@current_level)
43
+ return :insufficient_authority unless authority == Levels.required_authority(@current_level)
44
+
45
+ @current_level = target_level
46
+ @active = target_level.positive?
47
+ @history << {
48
+ action: :deescalate, level: target_level, authority: authority,
49
+ reason: reason, at: Time.now.utc
50
+ }
51
+ trim_history
52
+ save_to_local
53
+ :deescalated
54
+ end
55
+
56
+ def to_h
57
+ {
58
+ current_level: @current_level,
59
+ active: @active,
60
+ level_info: @current_level.positive? ? Levels.level_info(@current_level) : nil,
61
+ history_size: @history.size
62
+ }
63
+ end
64
+
65
+ def save_to_local
66
+ return unless defined?(Legion::Data::Local) && Legion::Data::Local.connected?
67
+
68
+ row = {
69
+ id: 1,
70
+ current_level: @current_level,
71
+ active: @active,
72
+ history: ::JSON.dump(@history.map { |h| h.merge(at: h[:at].to_s) }),
73
+ updated_at: Time.now.utc
74
+ }
75
+ db = Legion::Data::Local.connection
76
+ if db[:extinction_state].where(id: 1).any?
77
+ db[:extinction_state].where(id: 1).update(row.except(:id))
78
+ else
79
+ db[:extinction_state].insert(row)
80
+ end
81
+ rescue StandardError
82
+ nil
83
+ end
84
+
85
+ private
86
+
87
+ def trim_history
88
+ @history = @history.last(MAX_HISTORY) if @history.size > MAX_HISTORY
89
+ end
90
+
91
+ def load_from_local
92
+ return unless defined?(Legion::Data::Local) && Legion::Data::Local.connected?
93
+
94
+ row = Legion::Data::Local.connection[:extinction_state].where(id: 1).first
95
+ return unless row
96
+
97
+ db_level = row[:current_level].to_i
98
+ @current_level = [db_level, @current_level].max
99
+ @active = [true, 1].include?(row[:active])
100
+ @history = parse_history(row[:history])
101
+ rescue StandardError
102
+ nil
103
+ end
104
+
105
+ def parse_history(raw)
106
+ return [] if raw.nil? || raw.empty?
107
+
108
+ parsed = ::JSON.parse(raw, symbolize_names: true)
109
+ parsed.map do |h|
110
+ h.merge(
111
+ action: h[:action].to_sym,
112
+ authority: h[:authority].to_sym,
113
+ at: Time.parse(h[:at].to_s)
114
+ )
115
+ end
116
+ rescue StandardError
117
+ []
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table(:extinction_state) do
6
+ primary_key :id
7
+ Integer :current_level, null: false, default: 0
8
+ TrueClass :active, null: false, default: false
9
+ String :history, text: true
10
+ DateTime :updated_at
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Extinction
8
+ module Runners
9
+ module Extinction
10
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
11
+ Legion::Extensions::Helpers.const_defined?(:Lex)
12
+
13
+ def escalate(level:, authority:, reason:, **)
14
+ result = protocol_state.escalate(level, authority: authority, reason: reason)
15
+ case result
16
+ when :escalated
17
+ info = Helpers::Levels.level_info(level)
18
+ Legion::Logging.warn "[extinction] ESCALATED: level=#{level} name=#{info[:name]} authority=#{authority} reason=#{reason}"
19
+ enforce_escalation_effects(level)
20
+ emit_escalation_event(level, authority, reason)
21
+ { escalated: true, level: level, info: info }
22
+ else
23
+ Legion::Logging.debug "[extinction] escalation denied: level=#{level} reason=#{result}"
24
+ { escalated: false, reason: result }
25
+ end
26
+ end
27
+
28
+ def deescalate(authority:, reason:, target_level: 0, **)
29
+ result = protocol_state.deescalate(target_level, authority: authority, reason: reason)
30
+ case result
31
+ when :deescalated
32
+ Legion::Logging.info "[extinction] de-escalated: target=#{target_level} authority=#{authority} reason=#{reason}"
33
+ { deescalated: true, level: target_level }
34
+ else
35
+ Legion::Logging.debug "[extinction] de-escalation denied: target=#{target_level} reason=#{result}"
36
+ { deescalated: false, reason: result }
37
+ end
38
+ end
39
+
40
+ def extinction_status(**)
41
+ status = protocol_state.to_h
42
+ Legion::Logging.debug "[extinction] status: level=#{status[:current_level]} active=#{status[:active]}"
43
+ status
44
+ end
45
+
46
+ def monitor_protocol(**)
47
+ status = protocol_state.to_h
48
+ level = status[:current_level]
49
+
50
+ if level.positive?
51
+ Legion::Logging.warn "[extinction] ACTIVE: level=#{level} active=#{status[:active]}"
52
+ detect_stale_escalation(level)
53
+ else
54
+ Legion::Logging.debug '[extinction] status: level=0 active=false'
55
+ end
56
+
57
+ status
58
+ end
59
+
60
+ def check_reversibility(level:, **)
61
+ reversible = Helpers::Levels.reversible?(level)
62
+ Legion::Logging.debug "[extinction] reversibility: level=#{level} reversible=#{reversible}"
63
+ {
64
+ level: level,
65
+ reversible: reversible,
66
+ authority: Helpers::Levels.required_authority(level)
67
+ }
68
+ end
69
+
70
+ STALE_ESCALATION_THRESHOLD = 86_400
71
+
72
+ private
73
+
74
+ def enforce_escalation_effects(level)
75
+ if level >= 1 && defined?(Legion::Extensions::Mesh::Runners::Mesh)
76
+ Legion::Extensions::Mesh::Runners::Mesh.disconnect rescue nil # rubocop:disable Style/RescueModifier
77
+ Legion::Logging.warn '[extinction] mesh isolation enforced'
78
+ end
79
+
80
+ return unless level == 4
81
+
82
+ if defined?(Legion::Extensions::Privatecore::Runners::Privatecore)
83
+ Legion::Extensions::Privatecore::Runners::Privatecore.erase_all rescue nil # rubocop:disable Style/RescueModifier
84
+ Legion::Logging.warn '[extinction] cryptographic erasure triggered'
85
+ end
86
+
87
+ return unless defined?(Legion::Data::Model::DigitalWorker)
88
+
89
+ begin
90
+ Legion::Data::Model::DigitalWorker.where(lifecycle_state: 'active').update(
91
+ lifecycle_state: 'terminated', updated_at: Time.now.utc
92
+ )
93
+ rescue StandardError
94
+ nil
95
+ end
96
+ Legion::Logging.warn '[extinction] all active workers terminated'
97
+ end
98
+
99
+ def emit_escalation_event(level, authority, reason)
100
+ return unless defined?(Legion::Events)
101
+
102
+ info = Helpers::Levels.level_info(level)
103
+ Legion::Events.emit("extinction.#{info[:name]}", {
104
+ level: level, authority: authority, reason: reason, at: Time.now.utc
105
+ })
106
+ end
107
+
108
+ def detect_stale_escalation(level)
109
+ last_escalation = protocol_state.history.select { |h| h[:action] == :escalate }.last
110
+ return unless last_escalation && (Time.now.utc - last_escalation[:at]) > STALE_ESCALATION_THRESHOLD
111
+
112
+ Legion::Logging.warn "[extinction] STALE: level=#{level} has been active > 24 hours"
113
+ return unless defined?(Legion::Events)
114
+
115
+ Legion::Events.emit('extinction.stale_escalation', {
116
+ level: level, since: last_escalation[:at],
117
+ hours: ((Time.now.utc - last_escalation[:at]) / 3600).round(1)
118
+ })
119
+ end
120
+
121
+ def protocol_state
122
+ @protocol_state ||= Helpers::ProtocolState.new
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ 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 Extinction
8
+ VERSION = '0.2.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/defense/extinction/version'
4
+ require 'legion/extensions/agentic/defense/extinction/helpers/levels'
5
+ require 'legion/extensions/agentic/defense/extinction/helpers/protocol_state'
6
+ require 'legion/extensions/agentic/defense/extinction/runners/extinction'
7
+ require 'legion/extensions/agentic/defense/extinction/client'
8
+
9
+ module Legion
10
+ module Extensions
11
+ module Agentic
12
+ module Defense
13
+ module Extinction
14
+ end
15
+ end
16
+ end
17
+
18
+ if defined?(Legion::Data::Local)
19
+ Legion::Data::Local.register_migrations(
20
+ name: :extinction,
21
+ path: File.join(__dir__, 'extinction', 'local_migrations')
22
+ )
23
+ end
24
+ end
25
+ 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 Friction
8
+ class Client
9
+ include Runners::CognitiveFriction
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Friction
8
+ module Helpers
9
+ module Constants
10
+ MAX_TRANSITIONS = 300
11
+
12
+ DEFAULT_FRICTION = 0.3
13
+ FRICTION_BOOST = 0.1
14
+ FRICTION_DECAY = 0.03
15
+ MOMENTUM_THRESHOLD = 0.7
16
+ INERTIA_THRESHOLD = 0.6
17
+
18
+ FRICTION_LABELS = {
19
+ (0.8..) => :locked,
20
+ (0.6...0.8) => :resistant,
21
+ (0.4...0.6) => :moderate,
22
+ (0.2...0.4) => :smooth,
23
+ (..0.2) => :frictionless
24
+ }.freeze
25
+
26
+ TRANSITION_OUTCOMES = %i[completed resisted deferred forced].freeze
27
+
28
+ STATE_TYPES = %i[
29
+ focus_mode rest_mode social_mode analytical_mode
30
+ creative_mode vigilant_mode reflective_mode
31
+ ].freeze
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Defense
7
+ module Friction
8
+ module Helpers
9
+ class FrictionEngine
10
+ include Constants
11
+
12
+ def initialize
13
+ @transitions = {}
14
+ @friction_map = {}
15
+ @current_state = :rest_mode
16
+ end
17
+
18
+ def set_current_state(state:)
19
+ @current_state = state.to_sym
20
+ end
21
+
22
+ attr_reader :current_state
23
+
24
+ def set_friction(from_state:, to_state:, friction:)
25
+ key = :"#{from_state}_to_#{to_state}"
26
+ @friction_map[key] = friction.to_f.clamp(0.0, 1.0)
27
+ end
28
+
29
+ def get_friction(from_state:, to_state:)
30
+ key = :"#{from_state}_to_#{to_state}"
31
+ @friction_map.fetch(key, DEFAULT_FRICTION)
32
+ end
33
+
34
+ def attempt_transition(to_state:, force: 0.5)
35
+ prune_if_needed
36
+ friction = get_friction(from_state: @current_state, to_state: to_state)
37
+ transition = StateTransition.new(
38
+ from_state: @current_state,
39
+ to_state: to_state,
40
+ friction: friction
41
+ )
42
+ transition.attempt!(force: force)
43
+ @current_state = to_state.to_sym if transition.completed?
44
+ @transitions[transition.id] = transition
45
+ transition
46
+ end
47
+
48
+ def force_transition(to_state:)
49
+ prune_if_needed
50
+ friction = get_friction(from_state: @current_state, to_state: to_state)
51
+ transition = StateTransition.new(
52
+ from_state: @current_state,
53
+ to_state: to_state,
54
+ friction: friction
55
+ )
56
+ transition.force!
57
+ @current_state = to_state.to_sym
58
+ @transitions[transition.id] = transition
59
+ transition
60
+ end
61
+
62
+ def transition_history(limit: 10)
63
+ @transitions.values.sort_by(&:created_at).last(limit)
64
+ end
65
+
66
+ def successful_transitions
67
+ @transitions.values.select(&:completed?)
68
+ end
69
+
70
+ def resisted_transitions
71
+ @transitions.values.select { |t| t.outcome == :resisted }
72
+ end
73
+
74
+ def success_rate
75
+ return 0.0 if @transitions.empty?
76
+
77
+ (successful_transitions.size.to_f / @transitions.size).round(4)
78
+ end
79
+
80
+ def average_friction
81
+ return 0.0 if @transitions.empty?
82
+
83
+ frictions = @transitions.values.map(&:friction)
84
+ (frictions.sum / frictions.size).round(10)
85
+ end
86
+
87
+ def highest_friction_paths(limit: 5)
88
+ @friction_map.sort_by { |_, v| -v }.first(limit).map do |key, friction|
89
+ parts = key.to_s.split('_to_')
90
+ { from: parts[0]&.to_sym, to: parts[1]&.to_sym, friction: friction }
91
+ end
92
+ end
93
+
94
+ def friction_report
95
+ {
96
+ current_state: @current_state,
97
+ total_transitions: @transitions.size,
98
+ successful: successful_transitions.size,
99
+ resisted: resisted_transitions.size,
100
+ success_rate: success_rate,
101
+ average_friction: average_friction,
102
+ friction_paths: @friction_map.size,
103
+ highest_friction: highest_friction_paths(limit: 3)
104
+ }
105
+ end
106
+
107
+ def to_h
108
+ {
109
+ current_state: @current_state,
110
+ total_transitions: @transitions.size,
111
+ success_rate: success_rate,
112
+ average_friction: average_friction,
113
+ friction_paths: @friction_map.size
114
+ }
115
+ end
116
+
117
+ private
118
+
119
+ def prune_if_needed
120
+ return if @transitions.size < MAX_TRANSITIONS
121
+
122
+ oldest = @transitions.values.min_by(&:created_at)
123
+ @transitions.delete(oldest.id) if oldest
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Defense
9
+ module Friction
10
+ module Helpers
11
+ class StateTransition
12
+ include Constants
13
+
14
+ attr_reader :id, :from_state, :to_state, :friction, :outcome, :force_applied,
15
+ :created_at
16
+
17
+ def initialize(from_state:, to_state:, friction: DEFAULT_FRICTION)
18
+ @id = SecureRandom.uuid
19
+ @from_state = from_state.to_sym
20
+ @to_state = to_state.to_sym
21
+ @friction = friction.to_f.clamp(0.0, 1.0)
22
+ @outcome = nil
23
+ @force_applied = 0.0
24
+ @created_at = Time.now.utc
25
+ end
26
+
27
+ def attempt!(force: 0.5)
28
+ @force_applied = force.to_f.clamp(0.0, 1.0)
29
+ @outcome = if @force_applied > @friction
30
+ :completed
31
+ elsif @force_applied > (@friction * 0.7)
32
+ :deferred
33
+ else
34
+ :resisted
35
+ end
36
+ self
37
+ end
38
+
39
+ def force!(force: 1.0)
40
+ @force_applied = force.to_f.clamp(0.0, 1.0)
41
+ @outcome = :forced
42
+ self
43
+ end
44
+
45
+ def completed?
46
+ %i[completed forced].include?(@outcome)
47
+ end
48
+
49
+ def friction_label
50
+ match = FRICTION_LABELS.find { |range, _| range.cover?(@friction) }
51
+ match ? match.last : :locked
52
+ end
53
+
54
+ def to_h
55
+ {
56
+ id: @id,
57
+ from_state: @from_state,
58
+ to_state: @to_state,
59
+ friction: @friction,
60
+ friction_label: friction_label,
61
+ outcome: @outcome,
62
+ force_applied: @force_applied,
63
+ completed: completed?,
64
+ created_at: @created_at
65
+ }
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ 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 Friction
8
+ module Runners
9
+ module CognitiveFriction
10
+ include Helpers::Constants
11
+
12
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
13
+
14
+ def set_current_state(state:, engine: nil, **)
15
+ eng = engine || default_engine
16
+ eng.set_current_state(state: state)
17
+ { success: true, state: eng.current_state }
18
+ end
19
+
20
+ def set_friction(from_state:, to_state:, friction:, engine: nil, **)
21
+ eng = engine || default_engine
22
+ eng.set_friction(from_state: from_state, to_state: to_state, friction: friction)
23
+ { success: true, from_state: from_state, to_state: to_state, friction: friction }
24
+ end
25
+
26
+ def get_friction(from_state:, to_state:, engine: nil, **)
27
+ eng = engine || default_engine
28
+ friction = eng.get_friction(from_state: from_state, to_state: to_state)
29
+ { success: true, from_state: from_state, to_state: to_state, friction: friction }
30
+ end
31
+
32
+ def attempt_transition(to_state:, engine: nil, force: 0.5, **)
33
+ eng = engine || default_engine
34
+ transition = eng.attempt_transition(to_state: to_state, force: force)
35
+ { success: true, transition: transition.to_h, current_state: eng.current_state }
36
+ end
37
+
38
+ def force_transition(to_state:, engine: nil, **)
39
+ eng = engine || default_engine
40
+ transition = eng.force_transition(to_state: to_state)
41
+ { success: true, transition: transition.to_h, current_state: eng.current_state }
42
+ end
43
+
44
+ def transition_history(engine: nil, limit: 10, **)
45
+ eng = engine || default_engine
46
+ history = eng.transition_history(limit: limit).map(&:to_h)
47
+ { success: true, history: history, count: history.size }
48
+ end
49
+
50
+ def success_rate(engine: nil, **)
51
+ eng = engine || default_engine
52
+ { success: true, success_rate: eng.success_rate }
53
+ end
54
+
55
+ def average_friction(engine: nil, **)
56
+ eng = engine || default_engine
57
+ { success: true, average_friction: eng.average_friction }
58
+ end
59
+
60
+ def highest_friction_paths(engine: nil, limit: 5, **)
61
+ eng = engine || default_engine
62
+ paths = eng.highest_friction_paths(limit: limit)
63
+ { success: true, paths: paths, count: paths.size }
64
+ end
65
+
66
+ def friction_report(engine: nil, **)
67
+ eng = engine || default_engine
68
+ { success: true, report: eng.friction_report }
69
+ end
70
+
71
+ private
72
+
73
+ def default_engine
74
+ @default_engine ||= Helpers::FrictionEngine.new
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ 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 Friction
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'friction/version'
4
+ require_relative 'friction/helpers/constants'
5
+ require_relative 'friction/helpers/state_transition'
6
+ require_relative 'friction/helpers/friction_engine'
7
+ require_relative 'friction/runners/cognitive_friction'
8
+ require_relative 'friction/client'
9
+
10
+ module Legion
11
+ module Extensions
12
+ module Agentic
13
+ module Defense
14
+ module Friction
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end