lex-agentic-attention 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 (315) 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-attention.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/attention/arousal/client.rb +27 -0
  8. data/lib/legion/extensions/agentic/attention/arousal/helpers/arousal_model.rb +84 -0
  9. data/lib/legion/extensions/agentic/attention/arousal/helpers/constants.rb +44 -0
  10. data/lib/legion/extensions/agentic/attention/arousal/runners/arousal.rb +119 -0
  11. data/lib/legion/extensions/agentic/attention/arousal/version.rb +13 -0
  12. data/lib/legion/extensions/agentic/attention/arousal.rb +18 -0
  13. data/lib/legion/extensions/agentic/attention/blindspot/client.rb +19 -0
  14. data/lib/legion/extensions/agentic/attention/blindspot/helpers/blindspot.rb +98 -0
  15. data/lib/legion/extensions/agentic/attention/blindspot/helpers/blindspot_engine.rb +174 -0
  16. data/lib/legion/extensions/agentic/attention/blindspot/helpers/constants.rb +63 -0
  17. data/lib/legion/extensions/agentic/attention/blindspot/helpers/knowledge_boundary.rb +62 -0
  18. data/lib/legion/extensions/agentic/attention/blindspot/runners/cognitive_blindspot.rb +103 -0
  19. data/lib/legion/extensions/agentic/attention/blindspot/version.rb +13 -0
  20. data/lib/legion/extensions/agentic/attention/blindspot.rb +20 -0
  21. data/lib/legion/extensions/agentic/attention/blink/client.rb +19 -0
  22. data/lib/legion/extensions/agentic/attention/blink/helpers/blink_engine.rb +171 -0
  23. data/lib/legion/extensions/agentic/attention/blink/helpers/constants.rb +46 -0
  24. data/lib/legion/extensions/agentic/attention/blink/helpers/stimulus.rb +68 -0
  25. data/lib/legion/extensions/agentic/attention/blink/runners/attentional_blink.rb +75 -0
  26. data/lib/legion/extensions/agentic/attention/blink/version.rb +13 -0
  27. data/lib/legion/extensions/agentic/attention/blink.rb +19 -0
  28. data/lib/legion/extensions/agentic/attention/economy/client.rb +28 -0
  29. data/lib/legion/extensions/agentic/attention/economy/helpers/attention_budget.rb +143 -0
  30. data/lib/legion/extensions/agentic/attention/economy/helpers/constants.rb +38 -0
  31. data/lib/legion/extensions/agentic/attention/economy/helpers/demand.rb +72 -0
  32. data/lib/legion/extensions/agentic/attention/economy/runners/attention_economy.rb +90 -0
  33. data/lib/legion/extensions/agentic/attention/economy/version.rb +13 -0
  34. data/lib/legion/extensions/agentic/attention/economy.rb +19 -0
  35. data/lib/legion/extensions/agentic/attention/feature_binding/actors/decay.rb +45 -0
  36. data/lib/legion/extensions/agentic/attention/feature_binding/client.rb +29 -0
  37. data/lib/legion/extensions/agentic/attention/feature_binding/helpers/binding_field.rb +124 -0
  38. data/lib/legion/extensions/agentic/attention/feature_binding/helpers/bound_object.rb +89 -0
  39. data/lib/legion/extensions/agentic/attention/feature_binding/helpers/constants.rb +52 -0
  40. data/lib/legion/extensions/agentic/attention/feature_binding/helpers/feature.rb +52 -0
  41. data/lib/legion/extensions/agentic/attention/feature_binding/runners/feature_binding.rb +102 -0
  42. data/lib/legion/extensions/agentic/attention/feature_binding/version.rb +13 -0
  43. data/lib/legion/extensions/agentic/attention/feature_binding.rb +20 -0
  44. data/lib/legion/extensions/agentic/attention/focus/client.rb +30 -0
  45. data/lib/legion/extensions/agentic/attention/focus/helpers/constants.rb +38 -0
  46. data/lib/legion/extensions/agentic/attention/focus/helpers/focus.rb +78 -0
  47. data/lib/legion/extensions/agentic/attention/focus/helpers/focus_manager.rb +67 -0
  48. data/lib/legion/extensions/agentic/attention/focus/helpers/habituation.rb +61 -0
  49. data/lib/legion/extensions/agentic/attention/focus/runners/attention.rb +121 -0
  50. data/lib/legion/extensions/agentic/attention/focus/version.rb +13 -0
  51. data/lib/legion/extensions/agentic/attention/focus.rb +20 -0
  52. data/lib/legion/extensions/agentic/attention/kaleidoscope/client.rb +15 -0
  53. data/lib/legion/extensions/agentic/attention/kaleidoscope/helpers/constants.rb +48 -0
  54. data/lib/legion/extensions/agentic/attention/kaleidoscope/helpers/facet.rb +90 -0
  55. data/lib/legion/extensions/agentic/attention/kaleidoscope/helpers/kaleidoscope_engine.rb +142 -0
  56. data/lib/legion/extensions/agentic/attention/kaleidoscope/helpers/pattern.rb +110 -0
  57. data/lib/legion/extensions/agentic/attention/kaleidoscope/runners/cognitive_kaleidoscope.rb +91 -0
  58. data/lib/legion/extensions/agentic/attention/kaleidoscope/version.rb +13 -0
  59. data/lib/legion/extensions/agentic/attention/kaleidoscope.rb +22 -0
  60. data/lib/legion/extensions/agentic/attention/latent_inhibition/client.rb +28 -0
  61. data/lib/legion/extensions/agentic/attention/latent_inhibition/helpers/constants.rb +33 -0
  62. data/lib/legion/extensions/agentic/attention/latent_inhibition/helpers/inhibition_engine.rb +118 -0
  63. data/lib/legion/extensions/agentic/attention/latent_inhibition/helpers/stimulus_record.rb +70 -0
  64. data/lib/legion/extensions/agentic/attention/latent_inhibition/runners/latent_inhibition.rb +78 -0
  65. data/lib/legion/extensions/agentic/attention/latent_inhibition/version.rb +13 -0
  66. data/lib/legion/extensions/agentic/attention/latent_inhibition.rb +19 -0
  67. data/lib/legion/extensions/agentic/attention/lens/client.rb +29 -0
  68. data/lib/legion/extensions/agentic/attention/lens/helpers/constants.rb +58 -0
  69. data/lib/legion/extensions/agentic/attention/lens/helpers/lens.rb +99 -0
  70. data/lib/legion/extensions/agentic/attention/lens/helpers/lens_engine.rb +101 -0
  71. data/lib/legion/extensions/agentic/attention/lens/helpers/lens_stack.rb +134 -0
  72. data/lib/legion/extensions/agentic/attention/lens/runners/cognitive_lens.rb +90 -0
  73. data/lib/legion/extensions/agentic/attention/lens/version.rb +13 -0
  74. data/lib/legion/extensions/agentic/attention/lens.rb +22 -0
  75. data/lib/legion/extensions/agentic/attention/lighthouse/client.rb +25 -0
  76. data/lib/legion/extensions/agentic/attention/lighthouse/helpers/beacon.rb +76 -0
  77. data/lib/legion/extensions/agentic/attention/lighthouse/helpers/constants.rb +49 -0
  78. data/lib/legion/extensions/agentic/attention/lighthouse/helpers/fog.rb +74 -0
  79. data/lib/legion/extensions/agentic/attention/lighthouse/helpers/lighthouse_engine.rb +127 -0
  80. data/lib/legion/extensions/agentic/attention/lighthouse/runners/cognitive_lighthouse.rb +80 -0
  81. data/lib/legion/extensions/agentic/attention/lighthouse/version.rb +13 -0
  82. data/lib/legion/extensions/agentic/attention/lighthouse.rb +22 -0
  83. data/lib/legion/extensions/agentic/attention/priming/client.rb +21 -0
  84. data/lib/legion/extensions/agentic/attention/priming/helpers/activation_network.rb +130 -0
  85. data/lib/legion/extensions/agentic/attention/priming/helpers/concept_node.rb +92 -0
  86. data/lib/legion/extensions/agentic/attention/priming/helpers/constants.rb +54 -0
  87. data/lib/legion/extensions/agentic/attention/priming/runners/priming.rb +94 -0
  88. data/lib/legion/extensions/agentic/attention/priming/version.rb +13 -0
  89. data/lib/legion/extensions/agentic/attention/priming.rb +19 -0
  90. data/lib/legion/extensions/agentic/attention/prism/client.rb +26 -0
  91. data/lib/legion/extensions/agentic/attention/prism/helpers/beam.rb +169 -0
  92. data/lib/legion/extensions/agentic/attention/prism/helpers/constants.rb +46 -0
  93. data/lib/legion/extensions/agentic/attention/prism/helpers/prism_engine.rb +136 -0
  94. data/lib/legion/extensions/agentic/attention/prism/helpers/spectral_component.rb +72 -0
  95. data/lib/legion/extensions/agentic/attention/prism/runners/cognitive_prism.rb +79 -0
  96. data/lib/legion/extensions/agentic/attention/prism/version.rb +13 -0
  97. data/lib/legion/extensions/agentic/attention/prism.rb +22 -0
  98. data/lib/legion/extensions/agentic/attention/regulation/client.rb +19 -0
  99. data/lib/legion/extensions/agentic/attention/regulation/helpers/attention_controller.rb +157 -0
  100. data/lib/legion/extensions/agentic/attention/regulation/helpers/attention_target.rb +64 -0
  101. data/lib/legion/extensions/agentic/attention/regulation/helpers/constants.rb +41 -0
  102. data/lib/legion/extensions/agentic/attention/regulation/runners/attention_regulation.rb +88 -0
  103. data/lib/legion/extensions/agentic/attention/regulation/version.rb +13 -0
  104. data/lib/legion/extensions/agentic/attention/regulation.rb +20 -0
  105. data/lib/legion/extensions/agentic/attention/relevance_theory/helpers/client.rb +17 -0
  106. data/lib/legion/extensions/agentic/attention/relevance_theory/helpers/cognitive_input.rb +88 -0
  107. data/lib/legion/extensions/agentic/attention/relevance_theory/helpers/constants.rb +50 -0
  108. data/lib/legion/extensions/agentic/attention/relevance_theory/helpers/relevance_engine.rb +152 -0
  109. data/lib/legion/extensions/agentic/attention/relevance_theory/runners/relevance_theory.rb +98 -0
  110. data/lib/legion/extensions/agentic/attention/relevance_theory/version.rb +13 -0
  111. data/lib/legion/extensions/agentic/attention/relevance_theory.rb +19 -0
  112. data/lib/legion/extensions/agentic/attention/salience/client.rb +21 -0
  113. data/lib/legion/extensions/agentic/attention/salience/helpers/constants.rb +44 -0
  114. data/lib/legion/extensions/agentic/attention/salience/helpers/salience_map.rb +122 -0
  115. data/lib/legion/extensions/agentic/attention/salience/helpers/signal_integrator.rb +97 -0
  116. data/lib/legion/extensions/agentic/attention/salience/runners/salience.rb +70 -0
  117. data/lib/legion/extensions/agentic/attention/salience/version.rb +13 -0
  118. data/lib/legion/extensions/agentic/attention/salience.rb +19 -0
  119. data/lib/legion/extensions/agentic/attention/schema/actors/decay.rb +45 -0
  120. data/lib/legion/extensions/agentic/attention/schema/client.rb +28 -0
  121. data/lib/legion/extensions/agentic/attention/schema/helpers/attention_schema_model.rb +226 -0
  122. data/lib/legion/extensions/agentic/attention/schema/helpers/constants.rb +66 -0
  123. data/lib/legion/extensions/agentic/attention/schema/helpers/schema_item.rb +68 -0
  124. data/lib/legion/extensions/agentic/attention/schema/runners/attention_schema.rb +117 -0
  125. data/lib/legion/extensions/agentic/attention/schema/version.rb +13 -0
  126. data/lib/legion/extensions/agentic/attention/schema.rb +19 -0
  127. data/lib/legion/extensions/agentic/attention/sensory_gating/client.rb +15 -0
  128. data/lib/legion/extensions/agentic/attention/sensory_gating/helpers/constants.rb +44 -0
  129. data/lib/legion/extensions/agentic/attention/sensory_gating/helpers/gating_engine.rb +109 -0
  130. data/lib/legion/extensions/agentic/attention/sensory_gating/helpers/sensory_filter.rb +100 -0
  131. data/lib/legion/extensions/agentic/attention/sensory_gating/runners/sensory_gating.rb +73 -0
  132. data/lib/legion/extensions/agentic/attention/sensory_gating/version.rb +13 -0
  133. data/lib/legion/extensions/agentic/attention/sensory_gating.rb +19 -0
  134. data/lib/legion/extensions/agentic/attention/signal_detection/client.rb +28 -0
  135. data/lib/legion/extensions/agentic/attention/signal_detection/helpers/constants.rb +66 -0
  136. data/lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb +129 -0
  137. data/lib/legion/extensions/agentic/attention/signal_detection/helpers/detector.rb +136 -0
  138. data/lib/legion/extensions/agentic/attention/signal_detection/runners/signal_detection.rb +113 -0
  139. data/lib/legion/extensions/agentic/attention/signal_detection/version.rb +13 -0
  140. data/lib/legion/extensions/agentic/attention/signal_detection.rb +19 -0
  141. data/lib/legion/extensions/agentic/attention/spotlight/client.rb +29 -0
  142. data/lib/legion/extensions/agentic/attention/spotlight/helpers/attention_target.rb +61 -0
  143. data/lib/legion/extensions/agentic/attention/spotlight/helpers/constants.rb +44 -0
  144. data/lib/legion/extensions/agentic/attention/spotlight/helpers/spotlight.rb +78 -0
  145. data/lib/legion/extensions/agentic/attention/spotlight/helpers/spotlight_engine.rb +163 -0
  146. data/lib/legion/extensions/agentic/attention/spotlight/runners/attention_spotlight.rb +122 -0
  147. data/lib/legion/extensions/agentic/attention/spotlight/version.rb +13 -0
  148. data/lib/legion/extensions/agentic/attention/spotlight.rb +20 -0
  149. data/lib/legion/extensions/agentic/attention/subliminal/client.rb +19 -0
  150. data/lib/legion/extensions/agentic/attention/subliminal/helpers/constants.rb +74 -0
  151. data/lib/legion/extensions/agentic/attention/subliminal/helpers/influence_event.rb +44 -0
  152. data/lib/legion/extensions/agentic/attention/subliminal/helpers/subliminal_engine.rb +149 -0
  153. data/lib/legion/extensions/agentic/attention/subliminal/helpers/subliminal_trace.rb +101 -0
  154. data/lib/legion/extensions/agentic/attention/subliminal/runners/subliminal.rb +71 -0
  155. data/lib/legion/extensions/agentic/attention/subliminal/version.rb +13 -0
  156. data/lib/legion/extensions/agentic/attention/subliminal.rb +20 -0
  157. data/lib/legion/extensions/agentic/attention/surprise/client.rb +22 -0
  158. data/lib/legion/extensions/agentic/attention/surprise/helpers/constants.rb +35 -0
  159. data/lib/legion/extensions/agentic/attention/surprise/helpers/habituation_model.rb +62 -0
  160. data/lib/legion/extensions/agentic/attention/surprise/helpers/surprise_event.rb +43 -0
  161. data/lib/legion/extensions/agentic/attention/surprise/helpers/surprise_store.rb +74 -0
  162. data/lib/legion/extensions/agentic/attention/surprise/runners/surprise.rb +174 -0
  163. data/lib/legion/extensions/agentic/attention/surprise/version.rb +13 -0
  164. data/lib/legion/extensions/agentic/attention/surprise.rb +20 -0
  165. data/lib/legion/extensions/agentic/attention/switching/client.rb +19 -0
  166. data/lib/legion/extensions/agentic/attention/switching/helpers/constants.rb +64 -0
  167. data/lib/legion/extensions/agentic/attention/switching/helpers/switch_event.rb +60 -0
  168. data/lib/legion/extensions/agentic/attention/switching/helpers/switching_engine.rb +172 -0
  169. data/lib/legion/extensions/agentic/attention/switching/helpers/task_set.rb +91 -0
  170. data/lib/legion/extensions/agentic/attention/switching/runners/attention_switching.rb +92 -0
  171. data/lib/legion/extensions/agentic/attention/switching/version.rb +13 -0
  172. data/lib/legion/extensions/agentic/attention/switching.rb +20 -0
  173. data/lib/legion/extensions/agentic/attention/synesthesia/client.rb +29 -0
  174. data/lib/legion/extensions/agentic/attention/synesthesia/helpers/constants.rb +52 -0
  175. data/lib/legion/extensions/agentic/attention/synesthesia/helpers/sensory_mapping.rb +70 -0
  176. data/lib/legion/extensions/agentic/attention/synesthesia/helpers/synesthesia_engine.rb +177 -0
  177. data/lib/legion/extensions/agentic/attention/synesthesia/helpers/synesthetic_event.rb +49 -0
  178. data/lib/legion/extensions/agentic/attention/synesthesia/runners/cognitive_synesthesia.rb +83 -0
  179. data/lib/legion/extensions/agentic/attention/synesthesia/version.rb +13 -0
  180. data/lib/legion/extensions/agentic/attention/synesthesia.rb +20 -0
  181. data/lib/legion/extensions/agentic/attention/telescope/client.rb +15 -0
  182. data/lib/legion/extensions/agentic/attention/telescope/helpers/constants.rb +60 -0
  183. data/lib/legion/extensions/agentic/attention/telescope/helpers/observation.rb +68 -0
  184. data/lib/legion/extensions/agentic/attention/telescope/helpers/observatory_engine.rb +126 -0
  185. data/lib/legion/extensions/agentic/attention/telescope/helpers/telescope.rb +129 -0
  186. data/lib/legion/extensions/agentic/attention/telescope/runners/cognitive_telescope.rb +103 -0
  187. data/lib/legion/extensions/agentic/attention/telescope/version.rb +13 -0
  188. data/lib/legion/extensions/agentic/attention/telescope.rb +22 -0
  189. data/lib/legion/extensions/agentic/attention/version.rb +11 -0
  190. data/lib/legion/extensions/agentic/attention.rb +41 -0
  191. data/spec/legion/extensions/agentic/attention/arousal/client_spec.rb +42 -0
  192. data/spec/legion/extensions/agentic/attention/arousal/helpers/arousal_model_spec.rb +160 -0
  193. data/spec/legion/extensions/agentic/attention/arousal/helpers/constants_spec.rb +61 -0
  194. data/spec/legion/extensions/agentic/attention/arousal/runners/arousal_spec.rb +137 -0
  195. data/spec/legion/extensions/agentic/attention/blindspot/client_spec.rb +41 -0
  196. data/spec/legion/extensions/agentic/attention/blindspot/helpers/blindspot_engine_spec.rb +246 -0
  197. data/spec/legion/extensions/agentic/attention/blindspot/helpers/blindspot_spec.rb +204 -0
  198. data/spec/legion/extensions/agentic/attention/blindspot/helpers/constants_spec.rb +82 -0
  199. data/spec/legion/extensions/agentic/attention/blindspot/helpers/knowledge_boundary_spec.rb +104 -0
  200. data/spec/legion/extensions/agentic/attention/blindspot/runners/cognitive_blindspot_spec.rb +179 -0
  201. data/spec/legion/extensions/agentic/attention/blink/client_spec.rb +18 -0
  202. data/spec/legion/extensions/agentic/attention/blink/helpers/blink_engine_spec.rb +147 -0
  203. data/spec/legion/extensions/agentic/attention/blink/helpers/constants_spec.rb +27 -0
  204. data/spec/legion/extensions/agentic/attention/blink/helpers/stimulus_spec.rb +77 -0
  205. data/spec/legion/extensions/agentic/attention/blink/runners/attentional_blink_spec.rb +77 -0
  206. data/spec/legion/extensions/agentic/attention/economy/client_spec.rb +30 -0
  207. data/spec/legion/extensions/agentic/attention/economy/helpers/attention_budget_spec.rb +222 -0
  208. data/spec/legion/extensions/agentic/attention/economy/helpers/constants_spec.rb +112 -0
  209. data/spec/legion/extensions/agentic/attention/economy/helpers/demand_spec.rb +128 -0
  210. data/spec/legion/extensions/agentic/attention/economy/runners/attention_economy_spec.rb +163 -0
  211. data/spec/legion/extensions/agentic/attention/feature_binding/client_spec.rb +20 -0
  212. data/spec/legion/extensions/agentic/attention/feature_binding/helpers/binding_field_spec.rb +207 -0
  213. data/spec/legion/extensions/agentic/attention/feature_binding/helpers/bound_object_spec.rb +149 -0
  214. data/spec/legion/extensions/agentic/attention/feature_binding/helpers/feature_spec.rb +86 -0
  215. data/spec/legion/extensions/agentic/attention/feature_binding/runners/feature_binding_spec.rb +106 -0
  216. data/spec/legion/extensions/agentic/attention/focus/client_spec.rb +19 -0
  217. data/spec/legion/extensions/agentic/attention/focus/helpers/focus_manager_spec.rb +105 -0
  218. data/spec/legion/extensions/agentic/attention/focus/helpers/focus_spec.rb +148 -0
  219. data/spec/legion/extensions/agentic/attention/focus/helpers/habituation_spec.rb +97 -0
  220. data/spec/legion/extensions/agentic/attention/focus/runners/attention_spec.rb +134 -0
  221. data/spec/legion/extensions/agentic/attention/kaleidoscope/client_spec.rb +38 -0
  222. data/spec/legion/extensions/agentic/attention/kaleidoscope/helpers/constants_spec.rb +79 -0
  223. data/spec/legion/extensions/agentic/attention/kaleidoscope/helpers/facet_spec.rb +155 -0
  224. data/spec/legion/extensions/agentic/attention/kaleidoscope/helpers/kaleidoscope_engine_spec.rb +164 -0
  225. data/spec/legion/extensions/agentic/attention/kaleidoscope/helpers/pattern_spec.rb +157 -0
  226. data/spec/legion/extensions/agentic/attention/kaleidoscope/runners/cognitive_kaleidoscope_spec.rb +112 -0
  227. data/spec/legion/extensions/agentic/attention/latent_inhibition/client_spec.rb +49 -0
  228. data/spec/legion/extensions/agentic/attention/latent_inhibition/helpers/constants_spec.rb +57 -0
  229. data/spec/legion/extensions/agentic/attention/latent_inhibition/helpers/inhibition_engine_spec.rb +207 -0
  230. data/spec/legion/extensions/agentic/attention/latent_inhibition/helpers/stimulus_record_spec.rb +175 -0
  231. data/spec/legion/extensions/agentic/attention/latent_inhibition/runners/latent_inhibition_spec.rb +148 -0
  232. data/spec/legion/extensions/agentic/attention/lens/client_spec.rb +64 -0
  233. data/spec/legion/extensions/agentic/attention/lens/helpers/constants_spec.rb +91 -0
  234. data/spec/legion/extensions/agentic/attention/lens/helpers/lens_engine_spec.rb +158 -0
  235. data/spec/legion/extensions/agentic/attention/lens/helpers/lens_spec.rb +222 -0
  236. data/spec/legion/extensions/agentic/attention/lens/helpers/lens_stack_spec.rb +179 -0
  237. data/spec/legion/extensions/agentic/attention/lens/runners/cognitive_lens_spec.rb +182 -0
  238. data/spec/legion/extensions/agentic/attention/lighthouse/client_spec.rb +103 -0
  239. data/spec/legion/extensions/agentic/attention/lighthouse/helpers/beacon_spec.rb +170 -0
  240. data/spec/legion/extensions/agentic/attention/lighthouse/helpers/constants_spec.rb +94 -0
  241. data/spec/legion/extensions/agentic/attention/lighthouse/helpers/fog_spec.rb +166 -0
  242. data/spec/legion/extensions/agentic/attention/lighthouse/helpers/lighthouse_engine_spec.rb +238 -0
  243. data/spec/legion/extensions/agentic/attention/lighthouse/runners/cognitive_lighthouse_spec.rb +182 -0
  244. data/spec/legion/extensions/agentic/attention/priming/client_spec.rb +80 -0
  245. data/spec/legion/extensions/agentic/attention/priming/helpers/activation_network_spec.rb +176 -0
  246. data/spec/legion/extensions/agentic/attention/priming/helpers/concept_node_spec.rb +165 -0
  247. data/spec/legion/extensions/agentic/attention/priming/helpers/constants_spec.rb +51 -0
  248. data/spec/legion/extensions/agentic/attention/priming/runners/priming_spec.rb +141 -0
  249. data/spec/legion/extensions/agentic/attention/prism/client_spec.rb +86 -0
  250. data/spec/legion/extensions/agentic/attention/prism/helpers/beam_spec.rb +182 -0
  251. data/spec/legion/extensions/agentic/attention/prism/helpers/constants_spec.rb +93 -0
  252. data/spec/legion/extensions/agentic/attention/prism/helpers/prism_engine_spec.rb +253 -0
  253. data/spec/legion/extensions/agentic/attention/prism/helpers/spectral_component_spec.rb +171 -0
  254. data/spec/legion/extensions/agentic/attention/prism/runners/cognitive_prism_spec.rb +132 -0
  255. data/spec/legion/extensions/agentic/attention/regulation/client_spec.rb +58 -0
  256. data/spec/legion/extensions/agentic/attention/regulation/helpers/attention_controller_spec.rb +295 -0
  257. data/spec/legion/extensions/agentic/attention/regulation/helpers/attention_target_spec.rb +122 -0
  258. data/spec/legion/extensions/agentic/attention/regulation/runners/attention_regulation_spec.rb +147 -0
  259. data/spec/legion/extensions/agentic/attention/relevance_theory/helpers/cognitive_input_spec.rb +121 -0
  260. data/spec/legion/extensions/agentic/attention/relevance_theory/helpers/relevance_engine_spec.rb +149 -0
  261. data/spec/legion/extensions/agentic/attention/relevance_theory/relevance_theory_spec.rb +11 -0
  262. data/spec/legion/extensions/agentic/attention/relevance_theory/runners/relevance_theory_spec.rb +86 -0
  263. data/spec/legion/extensions/agentic/attention/salience/client_spec.rb +60 -0
  264. data/spec/legion/extensions/agentic/attention/salience/helpers/constants_spec.rb +100 -0
  265. data/spec/legion/extensions/agentic/attention/salience/helpers/salience_map_spec.rb +189 -0
  266. data/spec/legion/extensions/agentic/attention/salience/helpers/signal_integrator_spec.rb +149 -0
  267. data/spec/legion/extensions/agentic/attention/salience/runners/salience_spec.rb +143 -0
  268. data/spec/legion/extensions/agentic/attention/schema/client_spec.rb +47 -0
  269. data/spec/legion/extensions/agentic/attention/schema/helpers/attention_schema_model_spec.rb +219 -0
  270. data/spec/legion/extensions/agentic/attention/schema/helpers/schema_item_spec.rb +114 -0
  271. data/spec/legion/extensions/agentic/attention/schema/runners/attention_schema_spec.rb +185 -0
  272. data/spec/legion/extensions/agentic/attention/sensory_gating/helpers/gating_engine_spec.rb +112 -0
  273. data/spec/legion/extensions/agentic/attention/sensory_gating/helpers/sensory_filter_spec.rb +121 -0
  274. data/spec/legion/extensions/agentic/attention/sensory_gating/runners/sensory_gating_spec.rb +61 -0
  275. data/spec/legion/extensions/agentic/attention/signal_detection/client_spec.rb +20 -0
  276. data/spec/legion/extensions/agentic/attention/signal_detection/helpers/constants_spec.rb +85 -0
  277. data/spec/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine_spec.rb +143 -0
  278. data/spec/legion/extensions/agentic/attention/signal_detection/helpers/detector_spec.rb +179 -0
  279. data/spec/legion/extensions/agentic/attention/signal_detection/runners/signal_detection_spec.rb +151 -0
  280. data/spec/legion/extensions/agentic/attention/spotlight/client_spec.rb +31 -0
  281. data/spec/legion/extensions/agentic/attention/spotlight/helpers/attention_target_spec.rb +121 -0
  282. data/spec/legion/extensions/agentic/attention/spotlight/helpers/constants_spec.rb +82 -0
  283. data/spec/legion/extensions/agentic/attention/spotlight/helpers/spotlight_engine_spec.rb +275 -0
  284. data/spec/legion/extensions/agentic/attention/spotlight/helpers/spotlight_spec.rb +196 -0
  285. data/spec/legion/extensions/agentic/attention/spotlight/runners/attention_spotlight_spec.rb +251 -0
  286. data/spec/legion/extensions/agentic/attention/subliminal/client_spec.rb +21 -0
  287. data/spec/legion/extensions/agentic/attention/subliminal/helpers/influence_event_spec.rb +58 -0
  288. data/spec/legion/extensions/agentic/attention/subliminal/helpers/subliminal_engine_spec.rb +161 -0
  289. data/spec/legion/extensions/agentic/attention/subliminal/helpers/subliminal_trace_spec.rb +168 -0
  290. data/spec/legion/extensions/agentic/attention/subliminal/runners_spec.rb +78 -0
  291. data/spec/legion/extensions/agentic/attention/subliminal/subliminal_spec.rb +7 -0
  292. data/spec/legion/extensions/agentic/attention/surprise/client_spec.rb +122 -0
  293. data/spec/legion/extensions/agentic/attention/surprise/helpers/constants_spec.rb +112 -0
  294. data/spec/legion/extensions/agentic/attention/surprise/helpers/habituation_model_spec.rb +127 -0
  295. data/spec/legion/extensions/agentic/attention/surprise/helpers/surprise_event_spec.rb +102 -0
  296. data/spec/legion/extensions/agentic/attention/surprise/helpers/surprise_store_spec.rb +171 -0
  297. data/spec/legion/extensions/agentic/attention/surprise/runners/surprise_spec.rb +266 -0
  298. data/spec/legion/extensions/agentic/attention/switching/attention_switching_spec.rb +7 -0
  299. data/spec/legion/extensions/agentic/attention/switching/helpers/switch_event_spec.rb +74 -0
  300. data/spec/legion/extensions/agentic/attention/switching/helpers/switching_engine_spec.rb +164 -0
  301. data/spec/legion/extensions/agentic/attention/switching/helpers/task_set_spec.rb +134 -0
  302. data/spec/legion/extensions/agentic/attention/synesthesia/client_spec.rb +57 -0
  303. data/spec/legion/extensions/agentic/attention/synesthesia/helpers/constants_spec.rb +89 -0
  304. data/spec/legion/extensions/agentic/attention/synesthesia/helpers/sensory_mapping_spec.rb +135 -0
  305. data/spec/legion/extensions/agentic/attention/synesthesia/helpers/synesthesia_engine_spec.rb +260 -0
  306. data/spec/legion/extensions/agentic/attention/synesthesia/helpers/synesthetic_event_spec.rb +83 -0
  307. data/spec/legion/extensions/agentic/attention/synesthesia/runners/cognitive_synesthesia_spec.rb +192 -0
  308. data/spec/legion/extensions/agentic/attention/telescope/client_spec.rb +30 -0
  309. data/spec/legion/extensions/agentic/attention/telescope/helpers/constants_spec.rb +108 -0
  310. data/spec/legion/extensions/agentic/attention/telescope/helpers/observation_spec.rb +138 -0
  311. data/spec/legion/extensions/agentic/attention/telescope/helpers/observatory_engine_spec.rb +197 -0
  312. data/spec/legion/extensions/agentic/attention/telescope/helpers/telescope_spec.rb +251 -0
  313. data/spec/legion/extensions/agentic/attention/telescope/runners/cognitive_telescope_spec.rb +191 -0
  314. data/spec/spec_helper.rb +46 -0
  315. metadata +399 -0
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Attention::Surprise::Helpers::SurpriseEvent do
6
+ let(:event) do
7
+ described_class.new(
8
+ domain: :sensor,
9
+ predicted: 0.5,
10
+ actual: 0.9,
11
+ magnitude: 0.6,
12
+ valence: :negative
13
+ )
14
+ end
15
+
16
+ describe '#initialize' do
17
+ it 'assigns a uuid id' do
18
+ expect(event.id).to be_a(String)
19
+ expect(event.id).to match(/\A[0-9a-f-]{36}\z/)
20
+ end
21
+
22
+ it 'assigns domain' do
23
+ expect(event.domain).to eq(:sensor)
24
+ end
25
+
26
+ it 'assigns predicted value' do
27
+ expect(event.predicted).to eq(0.5)
28
+ end
29
+
30
+ it 'assigns actual value' do
31
+ expect(event.actual).to eq(0.9)
32
+ end
33
+
34
+ it 'clamps magnitude to [0.0, 1.0]' do
35
+ expect(event.magnitude).to be_between(0.0, 1.0)
36
+ end
37
+
38
+ it 'assigns valence' do
39
+ expect(event.valence).to eq(:negative)
40
+ end
41
+
42
+ it 'defaults orienting to false' do
43
+ expect(event.orienting).to be false
44
+ end
45
+
46
+ it 'sets timestamp to current UTC time' do
47
+ expect(event.timestamp).to be_a(Time)
48
+ end
49
+
50
+ it 'clamps magnitude above 1.0 down to 1.0' do
51
+ e = described_class.new(domain: :x, predicted: 0.0, actual: 0.0, magnitude: 5.0, valence: :neutral)
52
+ expect(e.magnitude).to eq(1.0)
53
+ end
54
+
55
+ it 'clamps magnitude below 0.0 up to 0.0' do
56
+ e = described_class.new(domain: :x, predicted: 0.0, actual: 0.0, magnitude: -1.0, valence: :neutral)
57
+ expect(e.magnitude).to eq(0.0)
58
+ end
59
+
60
+ it 'accepts orienting: true' do
61
+ e = described_class.new(domain: :x, predicted: 0.1, actual: 0.9, magnitude: 0.8, valence: :negative, orienting: true)
62
+ expect(e.orienting).to be true
63
+ end
64
+ end
65
+
66
+ describe '#to_h' do
67
+ subject(:hash) { event.to_h }
68
+
69
+ it 'includes all required keys' do
70
+ expect(hash.keys).to contain_exactly(:id, :domain, :predicted, :actual, :magnitude, :valence, :orienting, :timestamp)
71
+ end
72
+
73
+ it 'rounds magnitude to 4 decimal places' do
74
+ e = described_class.new(domain: :d, predicted: 0.1, actual: 0.2, magnitude: 0.123456789, valence: :neutral)
75
+ expect(e.to_h[:magnitude]).to eq(0.1235)
76
+ end
77
+
78
+ it 'preserves domain as-is' do
79
+ expect(hash[:domain]).to eq(:sensor)
80
+ end
81
+
82
+ it 'preserves valence as symbol' do
83
+ expect(hash[:valence]).to eq(:negative)
84
+ end
85
+
86
+ it 'returns false for orienting when not set' do
87
+ expect(hash[:orienting]).to be false
88
+ end
89
+
90
+ it 'each call produces the same id' do
91
+ expect(event.to_h[:id]).to eq(event.to_h[:id])
92
+ end
93
+ end
94
+
95
+ describe 'unique ids' do
96
+ it 'generates unique ids for different events' do
97
+ e1 = described_class.new(domain: :d, predicted: 0.0, actual: 1.0, magnitude: 1.0, valence: :negative)
98
+ e2 = described_class.new(domain: :d, predicted: 0.0, actual: 1.0, magnitude: 1.0, valence: :negative)
99
+ expect(e1.id).not_to eq(e2.id)
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Attention::Surprise::Helpers::SurpriseStore do
6
+ subject(:store) { described_class.new }
7
+
8
+ def make_event(domain: :test, magnitude: 0.5, valence: :neutral, orienting: false)
9
+ Legion::Extensions::Agentic::Attention::Surprise::Helpers::SurpriseEvent.new(
10
+ domain: domain,
11
+ predicted: 0.5,
12
+ actual: 0.8,
13
+ magnitude: magnitude,
14
+ valence: valence,
15
+ orienting: orienting
16
+ )
17
+ end
18
+
19
+ describe '#record' do
20
+ it 'adds the event to the store' do
21
+ event = make_event
22
+ store.record(event)
23
+ expect(store.events.size).to eq(1)
24
+ end
25
+
26
+ it 'returns the recorded event' do
27
+ event = make_event
28
+ result = store.record(event)
29
+ expect(result).to equal(event)
30
+ end
31
+
32
+ it 'updates the EMA baseline for the domain' do
33
+ event = make_event(domain: :ema_domain, magnitude: 0.8)
34
+ expect { store.record(event) }.to change { store.baseline_for(:ema_domain) }.from(0.0)
35
+ end
36
+ end
37
+
38
+ describe '#recent' do
39
+ it 'returns the last N events' do
40
+ 5.times { |i| store.record(make_event(domain: :"d#{i}")) }
41
+ expect(store.recent(3).size).to eq(3)
42
+ end
43
+
44
+ it 'returns all events when N exceeds store size' do
45
+ 2.times { store.record(make_event) }
46
+ expect(store.recent(10).size).to eq(2)
47
+ end
48
+
49
+ it 'defaults to 10 most recent' do
50
+ 15.times { store.record(make_event) }
51
+ expect(store.recent.size).to eq(10)
52
+ end
53
+
54
+ it 'returns events in insertion order (oldest first in the slice)' do
55
+ e1 = make_event(domain: :first)
56
+ e2 = make_event(domain: :second)
57
+ store.record(e1)
58
+ store.record(e2)
59
+ recent = store.recent(2)
60
+ expect(recent.first.domain).to eq(:first)
61
+ expect(recent.last.domain).to eq(:second)
62
+ end
63
+ end
64
+
65
+ describe '#by_domain' do
66
+ it 'returns only events matching the domain' do
67
+ store.record(make_event(domain: :alpha))
68
+ store.record(make_event(domain: :beta))
69
+ store.record(make_event(domain: :alpha))
70
+ expect(store.by_domain(:alpha).size).to eq(2)
71
+ end
72
+
73
+ it 'returns empty array for unknown domain' do
74
+ expect(store.by_domain(:unknown)).to eq([])
75
+ end
76
+ end
77
+
78
+ describe '#most_surprising' do
79
+ it 'returns events sorted by magnitude descending' do
80
+ store.record(make_event(magnitude: 0.3))
81
+ store.record(make_event(magnitude: 0.9))
82
+ store.record(make_event(magnitude: 0.5))
83
+ top = store.most_surprising(2)
84
+ expect(top.map(&:magnitude)).to eq([0.9, 0.5])
85
+ end
86
+
87
+ it 'returns at most N events' do
88
+ 3.times { store.record(make_event) }
89
+ expect(store.most_surprising(2).size).to eq(2)
90
+ end
91
+
92
+ it 'returns all when N exceeds store size' do
93
+ 2.times { store.record(make_event) }
94
+ expect(store.most_surprising(10).size).to eq(2)
95
+ end
96
+ end
97
+
98
+ describe '#baseline_for' do
99
+ it 'returns 0.0 for unknown domains' do
100
+ expect(store.baseline_for(:never_seen)).to eq(0.0)
101
+ end
102
+
103
+ it 'converges toward recent magnitudes via EMA' do
104
+ 5.times { store.record(make_event(domain: :conv, magnitude: 0.8)) }
105
+ baseline = store.baseline_for(:conv)
106
+ expect(baseline).to be > 0.0
107
+ expect(baseline).to be <= 0.8
108
+ end
109
+
110
+ it 'updates separately per domain' do
111
+ store.record(make_event(domain: :d1, magnitude: 0.9))
112
+ store.record(make_event(domain: :d2, magnitude: 0.1))
113
+ expect(store.baseline_for(:d1)).to be > store.baseline_for(:d2)
114
+ end
115
+ end
116
+
117
+ describe '#to_h' do
118
+ it 'returns a hash with expected keys' do
119
+ h = store.to_h
120
+ expect(h.keys).to include(:total_events, :domain_count, :average_magnitude, :most_surprising_domain, :baselines)
121
+ end
122
+
123
+ it 'reports 0 total events when empty' do
124
+ expect(store.to_h[:total_events]).to eq(0)
125
+ end
126
+
127
+ it 'reports correct total_events' do
128
+ 3.times { store.record(make_event) }
129
+ expect(store.to_h[:total_events]).to eq(3)
130
+ end
131
+
132
+ it 'reports correct domain_count' do
133
+ store.record(make_event(domain: :a))
134
+ store.record(make_event(domain: :b))
135
+ store.record(make_event(domain: :a))
136
+ expect(store.to_h[:domain_count]).to eq(2)
137
+ end
138
+
139
+ it 'computes a sensible average_magnitude' do
140
+ store.record(make_event(magnitude: 0.4))
141
+ store.record(make_event(magnitude: 0.6))
142
+ expect(store.to_h[:average_magnitude]).to eq(0.5)
143
+ end
144
+
145
+ it 'returns nil most_surprising_domain when empty' do
146
+ expect(store.to_h[:most_surprising_domain]).to be_nil
147
+ end
148
+
149
+ it 'reports the domain of the highest magnitude event' do
150
+ store.record(make_event(domain: :low, magnitude: 0.1))
151
+ store.record(make_event(domain: :high, magnitude: 0.9))
152
+ expect(store.to_h[:most_surprising_domain]).to eq(:high)
153
+ end
154
+ end
155
+
156
+ describe 'history trimming' do
157
+ it 'keeps at most MAX_SURPRISE_HISTORY events' do
158
+ max = Legion::Extensions::Agentic::Attention::Surprise::Helpers::Constants::MAX_SURPRISE_HISTORY
159
+ (max + 20).times { store.record(make_event) }
160
+ expect(store.events.size).to eq(max)
161
+ end
162
+
163
+ it 'removes oldest events first when trimming' do
164
+ max = Legion::Extensions::Agentic::Attention::Surprise::Helpers::Constants::MAX_SURPRISE_HISTORY
165
+ first = make_event(domain: :first_in)
166
+ store.record(first)
167
+ (max + 5).times { store.record(make_event) }
168
+ expect(store.events.map(&:id)).not_to include(first.id)
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,266 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Attention::Surprise::Runners::Surprise do
6
+ let(:runner) do
7
+ obj = Object.new
8
+ obj.extend(described_class)
9
+ obj
10
+ end
11
+
12
+ describe '#evaluate_surprise' do
13
+ it 'returns success with a surprise_event hash' do
14
+ result = runner.evaluate_surprise(domain: :memory, predicted: 0.5, actual: 0.9)
15
+ expect(result[:success]).to be true
16
+ expect(result[:surprise_event]).to be_a(Hash)
17
+ expect(result[:surprise_event][:domain]).to eq(:memory)
18
+ end
19
+
20
+ it 'includes orienting_triggered in the result' do
21
+ result = runner.evaluate_surprise(domain: :memory, predicted: 0.0, actual: 1.0, valence: :negative)
22
+ expect(result).to include(:orienting_triggered)
23
+ end
24
+
25
+ it 'triggers orienting when magnitude exceeds threshold' do
26
+ # With predicted=0.0, actual=1.0 and negative valence (weight=1.0), magnitude = 1.0 * 1.0 * 1.0 = 1.0
27
+ result = runner.evaluate_surprise(domain: :shock, predicted: 0.0, actual: 1.0, valence: :negative)
28
+ expect(result[:orienting_triggered]).to be true
29
+ end
30
+
31
+ it 'does not trigger orienting when magnitude is below threshold' do
32
+ # With predicted=0.5, actual=0.52 and neutral valence (weight=0.3), magnitude is tiny
33
+ result = runner.evaluate_surprise(domain: :calm, predicted: 0.5, actual: 0.52, valence: :neutral)
34
+ expect(result[:orienting_triggered]).to be false
35
+ end
36
+
37
+ it 'applies negative valence weight (1.0) for stronger response' do
38
+ neg = runner.evaluate_surprise(domain: :neg_d, predicted: 0.0, actual: 0.5, valence: :negative)
39
+ pos = runner.evaluate_surprise(domain: :pos_d, predicted: 0.0, actual: 0.5, valence: :positive)
40
+ expect(neg[:surprise_event][:magnitude]).to be > pos[:surprise_event][:magnitude]
41
+ end
42
+
43
+ it 'applies positive valence weight (0.6) correctly' do
44
+ result = runner.evaluate_surprise(domain: :pos_check, predicted: 0.0, actual: 1.0, valence: :positive)
45
+ expect(result[:surprise_event][:magnitude]).to be_within(0.001).of(0.6)
46
+ end
47
+
48
+ it 'applies neutral valence weight (0.3) correctly' do
49
+ result = runner.evaluate_surprise(domain: :neu_check, predicted: 0.0, actual: 1.0, valence: :neutral)
50
+ expect(result[:surprise_event][:magnitude]).to be_within(0.001).of(0.3)
51
+ end
52
+
53
+ it 'records the event in the store' do
54
+ runner.evaluate_surprise(domain: :store_test, predicted: 0.5, actual: 0.9, valence: :negative)
55
+ result = runner.recent_surprises(count: 1)
56
+ expect(result[:count]).to eq(1)
57
+ expect(result[:events].first[:domain]).to eq(:store_test)
58
+ end
59
+
60
+ it 'habituates the domain after evaluation' do
61
+ domain = :habituate_me
62
+ # Evaluate once to create a habituation entry
63
+ runner.evaluate_surprise(domain: domain, predicted: 0.0, actual: 1.0, valence: :negative)
64
+ sens = runner.domain_sensitivity(domain: domain)
65
+ expect(sens[:sensitivity]).to be < 1.0
66
+ end
67
+
68
+ it 'does not trigger orienting on the same domain during cooldown' do
69
+ domain = :cooldown_domain
70
+ # First evaluation should trigger (large surprise, negative valence)
71
+ first = runner.evaluate_surprise(domain: domain, predicted: 0.0, actual: 1.0, valence: :negative)
72
+ expect(first[:orienting_triggered]).to be true
73
+ # Second immediately after should be blocked by cooldown
74
+ second = runner.evaluate_surprise(domain: domain, predicted: 0.0, actual: 1.0, valence: :negative)
75
+ expect(second[:orienting_triggered]).to be false
76
+ end
77
+
78
+ it 'defaults valence to :neutral' do
79
+ result = runner.evaluate_surprise(domain: :default_val, predicted: 0.0, actual: 1.0)
80
+ expect(result[:surprise_event][:valence]).to eq(:neutral)
81
+ end
82
+ end
83
+
84
+ describe '#update_surprise' do
85
+ it 'returns success with evaluation counts' do
86
+ result = runner.update_surprise
87
+ expect(result[:success]).to be true
88
+ expect(result).to include(:evaluated, :orienting_count, :events)
89
+ end
90
+
91
+ it 'evaluates zero predictions when tick_result is empty' do
92
+ result = runner.update_surprise(tick_result: {})
93
+ expect(result[:evaluated]).to eq(0)
94
+ end
95
+
96
+ it 'evaluates predictions extracted from tick_result' do
97
+ tick_result = {
98
+ predictions: [
99
+ { domain: :cpu, predicted: 0.3, actual: 0.9, valence: :negative },
100
+ { domain: :mem, predicted: 0.5, actual: 0.6, valence: :neutral }
101
+ ]
102
+ }
103
+ result = runner.update_surprise(tick_result: tick_result)
104
+ expect(result[:evaluated]).to eq(2)
105
+ end
106
+
107
+ it 'counts orienting events correctly' do
108
+ tick_result = {
109
+ predictions: [
110
+ { domain: :spike, predicted: 0.0, actual: 1.0, valence: :negative }
111
+ ]
112
+ }
113
+ result = runner.update_surprise(tick_result: tick_result)
114
+ expect(result[:orienting_count]).to be >= 0
115
+ end
116
+
117
+ it 'skips predictions missing required fields' do
118
+ tick_result = {
119
+ predictions: [
120
+ { domain: :incomplete },
121
+ { domain: :also_bad, predicted: 0.5 }
122
+ ]
123
+ }
124
+ result = runner.update_surprise(tick_result: tick_result)
125
+ expect(result[:evaluated]).to eq(0)
126
+ end
127
+
128
+ it 'handles non-hash tick_result gracefully' do
129
+ result = runner.update_surprise(tick_result: nil)
130
+ expect(result[:success]).to be true
131
+ expect(result[:evaluated]).to eq(0)
132
+ end
133
+
134
+ it 'calls decay_all on habituation model each tick' do
135
+ runner.evaluate_surprise(domain: :decay_test, predicted: 0.0, actual: 1.0, valence: :negative)
136
+ before = runner.domain_sensitivity(domain: :decay_test)[:sensitivity]
137
+ runner.update_surprise(tick_result: {})
138
+ after = runner.domain_sensitivity(domain: :decay_test)[:sensitivity]
139
+ expect(after).to be >= before
140
+ end
141
+ end
142
+
143
+ describe '#surprise_stats' do
144
+ it 'returns success' do
145
+ result = runner.surprise_stats
146
+ expect(result[:success]).to be true
147
+ end
148
+
149
+ it 'includes all stat keys' do
150
+ result = runner.surprise_stats
151
+ expect(result.keys).to include(
152
+ :total_events,
153
+ :domain_count,
154
+ :average_magnitude,
155
+ :most_surprising_domain,
156
+ :top_surprise_magnitude
157
+ )
158
+ end
159
+
160
+ it 'reports 0 total_events initially' do
161
+ expect(runner.surprise_stats[:total_events]).to eq(0)
162
+ end
163
+
164
+ it 'reports correct total after recording events' do
165
+ 3.times { runner.evaluate_surprise(domain: :stats_d, predicted: 0.0, actual: 0.5, valence: :neutral) }
166
+ expect(runner.surprise_stats[:total_events]).to eq(3)
167
+ end
168
+
169
+ it 'returns nil top_surprise_magnitude when no events' do
170
+ expect(runner.surprise_stats[:top_surprise_magnitude]).to be_nil
171
+ end
172
+
173
+ it 'returns the magnitude of the most surprising event' do
174
+ runner.evaluate_surprise(domain: :low_s, predicted: 0.4, actual: 0.5, valence: :neutral)
175
+ runner.evaluate_surprise(domain: :high_s, predicted: 0.0, actual: 1.0, valence: :negative)
176
+ top = runner.surprise_stats[:top_surprise_magnitude]
177
+ expect(top).to be > 0.5
178
+ end
179
+ end
180
+
181
+ describe '#domain_sensitivity' do
182
+ it 'returns success with domain info' do
183
+ result = runner.domain_sensitivity(domain: :test_domain)
184
+ expect(result[:success]).to be true
185
+ expect(result[:domain]).to eq(:test_domain)
186
+ expect(result).to include(:sensitivity, :baseline, :event_count)
187
+ end
188
+
189
+ it 'reports 1.0 sensitivity for a fresh domain' do
190
+ result = runner.domain_sensitivity(domain: :fresh_ds)
191
+ expect(result[:sensitivity]).to eq(1.0)
192
+ end
193
+
194
+ it 'reports reduced sensitivity after habituation' do
195
+ runner.evaluate_surprise(domain: :hab_ds, predicted: 0.0, actual: 1.0, valence: :negative)
196
+ result = runner.domain_sensitivity(domain: :hab_ds)
197
+ expect(result[:sensitivity]).to be < 1.0
198
+ end
199
+
200
+ it 'reports event_count for the domain' do
201
+ runner.evaluate_surprise(domain: :count_ds, predicted: 0.3, actual: 0.7, valence: :neutral)
202
+ runner.evaluate_surprise(domain: :count_ds, predicted: 0.3, actual: 0.7, valence: :neutral)
203
+ result = runner.domain_sensitivity(domain: :count_ds)
204
+ expect(result[:event_count]).to eq(2)
205
+ end
206
+ end
207
+
208
+ describe '#recent_surprises' do
209
+ it 'returns success with events array' do
210
+ result = runner.recent_surprises
211
+ expect(result[:success]).to be true
212
+ expect(result[:events]).to be_an(Array)
213
+ end
214
+
215
+ it 'returns the requested number of recent events' do
216
+ 5.times { runner.evaluate_surprise(domain: :rs_d, predicted: 0.0, actual: 0.5, valence: :neutral) }
217
+ result = runner.recent_surprises(count: 3)
218
+ expect(result[:count]).to eq(3)
219
+ end
220
+
221
+ it 'returns all events when count exceeds store size' do
222
+ 2.times { runner.evaluate_surprise(domain: :rs_small, predicted: 0.0, actual: 0.5, valence: :neutral) }
223
+ result = runner.recent_surprises(count: 100)
224
+ expect(result[:count]).to eq(2)
225
+ end
226
+
227
+ it 'defaults to 10 most recent' do
228
+ 15.times { runner.evaluate_surprise(domain: :rs_many, predicted: 0.0, actual: 0.5, valence: :neutral) }
229
+ result = runner.recent_surprises
230
+ expect(result[:count]).to eq(10)
231
+ end
232
+ end
233
+
234
+ describe '#reset_habituation' do
235
+ it 'returns success with domain and sensitivity info' do
236
+ result = runner.reset_habituation(domain: :reset_d)
237
+ expect(result[:success]).to be true
238
+ expect(result[:domain]).to eq(:reset_d)
239
+ expect(result).to include(:old_sensitivity, :new_sensitivity)
240
+ end
241
+
242
+ it 'increases sensitivity after habituation' do
243
+ domain = :reset_test
244
+ 10.times { runner.evaluate_surprise(domain: domain, predicted: 0.0, actual: 1.0, valence: :negative) }
245
+ habituated = runner.domain_sensitivity(domain: domain)[:sensitivity]
246
+ runner.reset_habituation(domain: domain)
247
+ reset = runner.domain_sensitivity(domain: domain)[:sensitivity]
248
+ expect(reset).to be > habituated
249
+ end
250
+
251
+ it 'sets sensitivity close to 1.0' do
252
+ domain = :full_reset
253
+ 10.times { runner.evaluate_surprise(domain: domain, predicted: 0.0, actual: 1.0, valence: :negative) }
254
+ runner.reset_habituation(domain: domain)
255
+ expect(runner.domain_sensitivity(domain: domain)[:sensitivity]).to be_within(0.05).of(1.0)
256
+ end
257
+
258
+ it 'reports old_sensitivity accurately' do
259
+ domain = :old_sens
260
+ runner.evaluate_surprise(domain: domain, predicted: 0.0, actual: 1.0, valence: :negative)
261
+ before = runner.domain_sensitivity(domain: domain)[:sensitivity]
262
+ result = runner.reset_habituation(domain: domain)
263
+ expect(result[:old_sensitivity]).to eq(before)
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Switching do
4
+ it 'has a version number' do
5
+ expect(Legion::Extensions::Agentic::Attention::Switching::VERSION).to eq('0.1.0')
6
+ end
7
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Switching::Helpers::SwitchEvent do
4
+ subject(:event) do
5
+ described_class.new(
6
+ from_task_id: 'task-a',
7
+ to_task_id: 'task-b',
8
+ switch_cost: 0.4,
9
+ residual_interference: 0.3,
10
+ warmup_needed: 0.2
11
+ )
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'assigns a UUID id' do
16
+ expect(event.id).to match(/\A[0-9a-f-]{36}\z/)
17
+ end
18
+
19
+ it 'sets task ids' do
20
+ expect(event.from_task_id).to eq('task-a')
21
+ expect(event.to_task_id).to eq('task-b')
22
+ end
23
+
24
+ it 'sets switch cost' do
25
+ expect(event.switch_cost).to eq(0.4)
26
+ end
27
+
28
+ it 'clamps cost values' do
29
+ high = described_class.new(from_task_id: 'a', to_task_id: 'b',
30
+ switch_cost: 5.0, residual_interference: 0.0, warmup_needed: 0.0)
31
+ expect(high.switch_cost).to eq(1.0)
32
+ end
33
+ end
34
+
35
+ describe '#costly?' do
36
+ it 'is false for moderate cost' do
37
+ expect(event.costly?).to be false
38
+ end
39
+
40
+ it 'is true for high cost' do
41
+ high = described_class.new(from_task_id: 'a', to_task_id: 'b',
42
+ switch_cost: 0.8, residual_interference: 0.0, warmup_needed: 0.0)
43
+ expect(high.costly?).to be true
44
+ end
45
+ end
46
+
47
+ describe '#cheap?' do
48
+ it 'is false for moderate cost' do
49
+ expect(event.cheap?).to be false
50
+ end
51
+
52
+ it 'is true for low cost' do
53
+ low = described_class.new(from_task_id: 'a', to_task_id: 'b',
54
+ switch_cost: 0.1, residual_interference: 0.0, warmup_needed: 0.0)
55
+ expect(low.cheap?).to be true
56
+ end
57
+ end
58
+
59
+ describe '#cost_label' do
60
+ it 'returns a symbol' do
61
+ expect(event.cost_label).to be_a(Symbol)
62
+ end
63
+ end
64
+
65
+ describe '#to_h' do
66
+ it 'includes all fields' do
67
+ hash = event.to_h
68
+ expect(hash).to include(
69
+ :id, :from_task_id, :to_task_id, :switch_cost, :cost_label,
70
+ :costly, :cheap, :residual_interference, :warmup_needed, :created_at
71
+ )
72
+ end
73
+ end
74
+ end