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,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Blink::Helpers::BlinkEngine do
4
+ subject(:engine) { described_class.new }
5
+
6
+ describe '#submit_stimulus' do
7
+ it 'returns a processed Stimulus' do
8
+ result = engine.submit_stimulus(stimulus_type: :visual, content: 'flash', salience: 0.7)
9
+ expect(result).to be_a(Legion::Extensions::Agentic::Attention::Blink::Helpers::Stimulus)
10
+ expect(result.processed).to be true
11
+ end
12
+
13
+ it 'triggers blink for salient stimuli' do
14
+ engine.submit_stimulus(stimulus_type: :visual, content: 'bright', salience: 0.9)
15
+ expect(engine.blink_active?).to be true
16
+ end
17
+
18
+ it 'does not trigger blink for low-salience stimuli' do
19
+ engine.submit_stimulus(stimulus_type: :visual, content: 'dim', salience: 0.2)
20
+ expect(engine.blink_active?).to be false
21
+ end
22
+
23
+ it 'reduces processing quality during blink' do
24
+ engine.submit_stimulus(stimulus_type: :visual, content: 'trigger', salience: 0.9)
25
+ second = engine.submit_stimulus(stimulus_type: :visual, content: 'missed', salience: 0.3)
26
+ expect(second.processing_quality).to be < 0.6
27
+ end
28
+ end
29
+
30
+ describe '#blink_active?' do
31
+ it 'returns false initially' do
32
+ expect(engine.blink_active?).to be false
33
+ end
34
+ end
35
+
36
+ describe '#recovery_level' do
37
+ it 'returns 1.0 when no blink' do
38
+ expect(engine.recovery_level).to eq(1.0)
39
+ end
40
+ end
41
+
42
+ describe '#recovery_label' do
43
+ it 'returns :recovered when not blinking' do
44
+ expect(engine.recovery_label).to eq(:recovered)
45
+ end
46
+ end
47
+
48
+ describe '#force_blink!' do
49
+ it 'activates blink' do
50
+ result = engine.force_blink!(duration: 5.0)
51
+ expect(result[:blink_active]).to be true
52
+ expect(result[:total_blinks]).to eq(1)
53
+ expect(engine.blink_active?).to be true
54
+ end
55
+
56
+ it 'clamps duration' do
57
+ result = engine.force_blink!(duration: 0.1)
58
+ expect(result[:duration]).to be >= 0.5
59
+ end
60
+ end
61
+
62
+ describe '#force_recover!' do
63
+ it 'deactivates blink' do
64
+ engine.force_blink!
65
+ result = engine.force_recover!
66
+ expect(result[:blink_active]).to be false
67
+ expect(engine.blink_active?).to be false
68
+ end
69
+ end
70
+
71
+ describe '#adjust_blink_duration' do
72
+ it 'sets new duration' do
73
+ engine.adjust_blink_duration(duration: 7.0)
74
+ result = engine.force_blink!
75
+ expect(result[:duration]).to be <= 10.0
76
+ end
77
+ end
78
+
79
+ describe '#miss_rate' do
80
+ it 'returns 0.0 with no stimuli' do
81
+ expect(engine.miss_rate).to eq(0.0)
82
+ end
83
+
84
+ it 'tracks missed stimuli ratio' do
85
+ engine.force_blink!
86
+ 5.times { engine.submit_stimulus(stimulus_type: :visual, content: 'x', salience: 0.1) }
87
+ expect(engine.miss_rate).to be >= 0.0
88
+ end
89
+ end
90
+
91
+ describe '#recent_stimuli' do
92
+ it 'returns empty when no stimuli' do
93
+ expect(engine.recent_stimuli).to be_empty
94
+ end
95
+
96
+ it 'returns most recent stimuli' do
97
+ 3.times { |i| engine.submit_stimulus(stimulus_type: :auditory, content: "s#{i}", salience: 0.3) }
98
+ expect(engine.recent_stimuli(limit: 2).size).to eq(2)
99
+ end
100
+ end
101
+
102
+ describe '#missed_stimuli' do
103
+ it 'returns only missed stimuli' do
104
+ engine.force_blink!
105
+ engine.submit_stimulus(stimulus_type: :visual, content: 'dim', salience: 0.1)
106
+ missed = engine.missed_stimuli
107
+ expect(missed.all?(&:missed?)).to be true
108
+ end
109
+ end
110
+
111
+ describe '#stimuli_by_type' do
112
+ it 'filters by stimulus type' do
113
+ engine.submit_stimulus(stimulus_type: :visual, content: 'a', salience: 0.3)
114
+ engine.submit_stimulus(stimulus_type: :auditory, content: 'b', salience: 0.3)
115
+ result = engine.stimuli_by_type(stimulus_type: :visual)
116
+ expect(result.size).to eq(1)
117
+ end
118
+ end
119
+
120
+ describe '#processing_quality_average' do
121
+ it 'returns 0.0 with no stimuli' do
122
+ expect(engine.processing_quality_average).to eq(0.0)
123
+ end
124
+
125
+ it 'computes average quality' do
126
+ 3.times { engine.submit_stimulus(stimulus_type: :visual, content: 'x', salience: 0.3) }
127
+ expect(engine.processing_quality_average).to be > 0.0
128
+ end
129
+ end
130
+
131
+ describe '#blink_report' do
132
+ it 'returns comprehensive report' do
133
+ engine.submit_stimulus(stimulus_type: :visual, content: 'x', salience: 0.3)
134
+ report = engine.blink_report
135
+ expect(report).to include(:total_stimuli, :total_blinks, :total_misses,
136
+ :miss_rate, :blink_active, :recovery_level,
137
+ :recovery_label, :avg_quality, :recent_missed)
138
+ end
139
+ end
140
+
141
+ describe '#to_h' do
142
+ it 'returns engine stats' do
143
+ h = engine.to_h
144
+ expect(h).to include(:total_stimuli, :total_blinks, :miss_rate, :blink_active, :avg_quality)
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Blink::Helpers::Constants do
4
+ let(:klass) { Class.new { include Legion::Extensions::Agentic::Attention::Blink::Helpers::Constants } }
5
+
6
+ it 'defines MAX_STIMULI' do
7
+ expect(klass::MAX_STIMULI).to eq(500)
8
+ end
9
+
10
+ it 'defines DEFAULT_BLINK_DURATION' do
11
+ expect(klass::DEFAULT_BLINK_DURATION).to eq(3.0)
12
+ end
13
+
14
+ it 'defines PROCESSING_LABELS as frozen hash' do
15
+ expect(klass::PROCESSING_LABELS).to be_frozen
16
+ expect(klass::PROCESSING_LABELS.size).to eq(5)
17
+ end
18
+
19
+ it 'defines RECOVERY_LABELS as frozen hash' do
20
+ expect(klass::RECOVERY_LABELS).to be_frozen
21
+ end
22
+
23
+ it 'defines STIMULUS_TYPES as frozen array' do
24
+ expect(klass::STIMULUS_TYPES).to be_frozen
25
+ expect(klass::STIMULUS_TYPES).to include(:visual, :auditory, :threat)
26
+ end
27
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Blink::Helpers::Stimulus do
4
+ subject(:stimulus) { described_class.new(stimulus_type: :visual, content: 'flash', salience: 0.7) }
5
+
6
+ describe '#initialize' do
7
+ it 'assigns a uuid id' do
8
+ expect(stimulus.id).to match(/\A[0-9a-f-]{36}\z/)
9
+ end
10
+
11
+ it 'sets type and content' do
12
+ expect(stimulus.stimulus_type).to eq(:visual)
13
+ expect(stimulus.content).to eq('flash')
14
+ end
15
+
16
+ it 'starts unprocessed' do
17
+ expect(stimulus.processed).to be false
18
+ expect(stimulus.processing_quality).to eq(0.0)
19
+ end
20
+ end
21
+
22
+ describe '#salient?' do
23
+ it 'returns true when salience >= threshold' do
24
+ expect(stimulus.salient?).to be true
25
+ end
26
+
27
+ it 'returns false when below threshold' do
28
+ s = described_class.new(stimulus_type: :visual, content: 'dim', salience: 0.3)
29
+ expect(s.salient?).to be false
30
+ end
31
+ end
32
+
33
+ describe '#process!' do
34
+ it 'marks as processed with quality' do
35
+ stimulus.process!(quality: 0.8)
36
+ expect(stimulus.processed).to be true
37
+ expect(stimulus.processing_quality).to eq(0.8)
38
+ end
39
+
40
+ it 'clamps quality to 0..1' do
41
+ stimulus.process!(quality: 1.5)
42
+ expect(stimulus.processing_quality).to eq(1.0)
43
+ end
44
+ end
45
+
46
+ describe '#processing_label' do
47
+ it 'returns :blinked when unprocessed' do
48
+ expect(stimulus.processing_label).to eq(:blinked)
49
+ end
50
+
51
+ it 'returns :fully_available for high quality' do
52
+ stimulus.process!(quality: 0.9)
53
+ expect(stimulus.processing_label).to eq(:fully_available)
54
+ end
55
+ end
56
+
57
+ describe '#missed?' do
58
+ it 'returns true when processed with very low quality' do
59
+ stimulus.process!(quality: 0.1)
60
+ expect(stimulus.missed?).to be true
61
+ end
62
+
63
+ it 'returns false for adequate quality' do
64
+ stimulus.process!(quality: 0.5)
65
+ expect(stimulus.missed?).to be false
66
+ end
67
+ end
68
+
69
+ describe '#to_h' do
70
+ it 'includes all fields' do
71
+ h = stimulus.to_h
72
+ expect(h).to include(:id, :stimulus_type, :content, :salience,
73
+ :processed, :processing_quality, :processing_label,
74
+ :salient, :missed, :arrival_time, :created_at)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Blink::Runners::AttentionalBlink do
4
+ subject(:runner) do
5
+ Class.new do
6
+ include Legion::Extensions::Agentic::Attention::Blink::Runners::AttentionalBlink
7
+
8
+ def engine
9
+ @engine ||= Legion::Extensions::Agentic::Attention::Blink::Helpers::BlinkEngine.new
10
+ end
11
+ end.new
12
+ end
13
+
14
+ describe '#submit_stimulus' do
15
+ it 'returns success with stimulus data' do
16
+ result = runner.submit_stimulus(stimulus_type: :visual, content: 'flash', salience: 0.7)
17
+ expect(result[:success]).to be true
18
+ expect(result[:stimulus_type]).to eq(:visual)
19
+ end
20
+ end
21
+
22
+ describe '#check_blink_status' do
23
+ it 'returns blink status' do
24
+ result = runner.check_blink_status
25
+ expect(result[:success]).to be true
26
+ expect(result[:blink_active]).to be false
27
+ end
28
+ end
29
+
30
+ describe '#force_blink' do
31
+ it 'activates blink' do
32
+ result = runner.force_blink(duration: 5.0)
33
+ expect(result[:success]).to be true
34
+ expect(result[:blink_active]).to be true
35
+ end
36
+ end
37
+
38
+ describe '#force_recover' do
39
+ it 'deactivates blink' do
40
+ runner.force_blink
41
+ result = runner.force_recover
42
+ expect(result[:success]).to be true
43
+ expect(result[:blink_active]).to be false
44
+ end
45
+ end
46
+
47
+ describe '#recent_stimuli_report' do
48
+ it 'returns stimuli list' do
49
+ runner.submit_stimulus(stimulus_type: :visual, content: 'x')
50
+ result = runner.recent_stimuli_report(limit: 5)
51
+ expect(result[:success]).to be true
52
+ expect(result[:count]).to eq(1)
53
+ end
54
+ end
55
+
56
+ describe '#missed_stimuli_report' do
57
+ it 'returns missed stimuli' do
58
+ result = runner.missed_stimuli_report
59
+ expect(result[:success]).to be true
60
+ expect(result[:count]).to eq(0)
61
+ end
62
+ end
63
+
64
+ describe '#blink_report' do
65
+ it 'returns comprehensive report' do
66
+ result = runner.blink_report
67
+ expect(result).to include(:total_stimuli, :total_blinks, :miss_rate)
68
+ end
69
+ end
70
+
71
+ describe '#attentional_blink_stats' do
72
+ it 'returns engine stats' do
73
+ result = runner.attentional_blink_stats
74
+ expect(result).to include(:total_stimuli, :total_blinks, :miss_rate)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/attention/economy/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Attention::Economy::Client do
6
+ let(:client) { described_class.new }
7
+
8
+ it 'responds to all runner methods' do
9
+ expect(client).to respond_to(:add_demand)
10
+ expect(client).to respond_to(:allocate_demand)
11
+ expect(client).to respond_to(:deallocate_demand)
12
+ expect(client).to respond_to(:recover_budget)
13
+ expect(client).to respond_to(:prioritized_demands)
14
+ expect(client).to respond_to(:best_roi_demands)
15
+ expect(client).to respond_to(:rebalance_budget)
16
+ expect(client).to respond_to(:attention_status)
17
+ expect(client).to respond_to(:attention_snapshot)
18
+ end
19
+
20
+ it 'starts with empty demands' do
21
+ expect(client.attention_status[:demand_count]).to eq(0)
22
+ end
23
+
24
+ it 'maintains isolated state per instance' do
25
+ c1 = described_class.new
26
+ c2 = described_class.new
27
+ c1.add_demand(label: 'solo', demand_type: :task, priority: 0.5, cost: 0.1)
28
+ expect(c2.attention_status[:demand_count]).to eq(0)
29
+ end
30
+ end
@@ -0,0 +1,222 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/attention/economy/helpers/attention_budget'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Attention::Economy::Helpers::AttentionBudget do
6
+ subject(:budget) { described_class.new }
7
+
8
+ def add_demand(label: 'work', demand_type: :task, priority: 0.5, cost: 0.2, roi: 0.6)
9
+ budget.create_demand(label: label, demand_type: demand_type, priority: priority, cost: cost, roi: roi)
10
+ end
11
+
12
+ describe '#initialize' do
13
+ it 'starts with full available budget' do
14
+ expect(budget.available_budget).to eq(1.0)
15
+ end
16
+
17
+ it 'starts with 0.0 spent' do
18
+ expect(budget.spent).to eq(0.0)
19
+ end
20
+
21
+ it 'starts with 0.0 recovered' do
22
+ expect(budget.recovered).to eq(0.0)
23
+ end
24
+
25
+ it 'accepts custom total_budget' do
26
+ b = described_class.new(total_budget: 2.0)
27
+ expect(b.total_budget).to eq(2.0)
28
+ end
29
+ end
30
+
31
+ describe '#create_demand' do
32
+ it 'returns a Demand object' do
33
+ demand = add_demand
34
+ expect(demand).to be_a(Legion::Extensions::Agentic::Attention::Economy::Helpers::Demand)
35
+ end
36
+
37
+ it 'raises ArgumentError for invalid demand_type' do
38
+ expect { budget.create_demand(label: 'x', demand_type: :invalid, priority: 0.5, cost: 0.1) }
39
+ .to raise_error(ArgumentError, /demand_type/)
40
+ end
41
+
42
+ it 'raises ArgumentError when max demands reached' do
43
+ stub_const('Legion::Extensions::Agentic::Attention::Economy::Helpers::Constants::MAX_DEMANDS', 1)
44
+ add_demand(label: 'first')
45
+ expect { add_demand(label: 'second') }.to raise_error(ArgumentError, /max demands/)
46
+ end
47
+ end
48
+
49
+ describe '#allocate' do
50
+ it 'allocates demand at its cost' do
51
+ demand = add_demand(cost: 0.3)
52
+ result = budget.allocate(demand_id: demand.id)
53
+ expect(result[:allocated]).to be true
54
+ expect(result[:amount]).to eq(0.3)
55
+ end
56
+
57
+ it 'deducts from budget' do
58
+ demand = add_demand(cost: 0.3)
59
+ budget.allocate(demand_id: demand.id)
60
+ expect(budget.available_budget).to be_within(0.001).of(0.7)
61
+ end
62
+
63
+ it 'allows explicit amount override' do
64
+ demand = add_demand(cost: 0.3)
65
+ result = budget.allocate(demand_id: demand.id, amount: 0.1)
66
+ expect(result[:amount]).to eq(0.1)
67
+ end
68
+
69
+ it 'returns not_found for unknown demand_id' do
70
+ result = budget.allocate(demand_id: 'nonexistent')
71
+ expect(result[:allocated]).to be false
72
+ expect(result[:reason]).to eq(:not_found)
73
+ end
74
+
75
+ it 'returns insufficient_budget when budget exhausted' do
76
+ add_demand(cost: 0.9).tap { |d| budget.allocate(demand_id: d.id) }
77
+ demand2 = add_demand(label: 'big', cost: 0.5)
78
+ result = budget.allocate(demand_id: demand2.id)
79
+ expect(result[:allocated]).to be false
80
+ expect(result[:reason]).to eq(:insufficient_budget)
81
+ end
82
+ end
83
+
84
+ describe '#deallocate' do
85
+ it 'frees allocated amount' do
86
+ demand = add_demand(cost: 0.4)
87
+ budget.allocate(demand_id: demand.id)
88
+ result = budget.deallocate(demand_id: demand.id)
89
+ expect(result[:deallocated]).to be true
90
+ expect(result[:freed]).to be_within(0.001).of(0.4)
91
+ expect(budget.available_budget).to be_within(0.001).of(1.0)
92
+ end
93
+
94
+ it 'returns not_found for unknown demand_id' do
95
+ result = budget.deallocate(demand_id: 'unknown')
96
+ expect(result[:deallocated]).to be false
97
+ end
98
+ end
99
+
100
+ describe '#recover!' do
101
+ it 'restores budget by recovery rate' do
102
+ demand = add_demand(cost: 0.3)
103
+ budget.allocate(demand_id: demand.id)
104
+ budget.recover!
105
+ expect(budget.spent).to be_within(0.001).of(0.25)
106
+ end
107
+
108
+ it 'accepts custom amount' do
109
+ demand = add_demand(cost: 0.5)
110
+ budget.allocate(demand_id: demand.id)
111
+ budget.recover!(amount: 0.2)
112
+ expect(budget.spent).to be_within(0.001).of(0.3)
113
+ end
114
+
115
+ it 'does not go below 0 spent' do
116
+ budget.recover!(amount: 0.5)
117
+ expect(budget.spent).to eq(0.0)
118
+ end
119
+
120
+ it 'accumulates recovered total' do
121
+ demand = add_demand(cost: 0.3)
122
+ budget.allocate(demand_id: demand.id)
123
+ budget.recover!
124
+ expect(budget.recovered).to be > 0
125
+ end
126
+ end
127
+
128
+ describe '#utilization' do
129
+ it 'returns 0.0 when nothing spent' do
130
+ expect(budget.utilization).to eq(0.0)
131
+ end
132
+
133
+ it 'returns proportion of budget spent' do
134
+ demand = add_demand(cost: 0.5)
135
+ budget.allocate(demand_id: demand.id)
136
+ expect(budget.utilization).to be_within(0.001).of(0.5)
137
+ end
138
+ end
139
+
140
+ describe '#prioritized_demands' do
141
+ it 'returns demands sorted by priority descending' do
142
+ budget.create_demand(label: 'low', demand_type: :task, priority: 0.2, cost: 0.1)
143
+ budget.create_demand(label: 'high', demand_type: :task, priority: 0.9, cost: 0.1)
144
+ budget.create_demand(label: 'mid', demand_type: :task, priority: 0.5, cost: 0.1)
145
+ sorted = budget.prioritized_demands
146
+ expect(sorted.first.priority).to be >= sorted.last.priority
147
+ end
148
+ end
149
+
150
+ describe '#best_roi' do
151
+ it 'returns top demands by efficiency' do
152
+ budget.create_demand(label: 'poor', demand_type: :task, priority: 0.5, cost: 0.9, roi: 0.1)
153
+ budget.create_demand(label: 'great', demand_type: :task, priority: 0.5, cost: 0.1, roi: 0.9)
154
+ best = budget.best_roi(limit: 1)
155
+ expect(best.first.label).to eq('great')
156
+ end
157
+
158
+ it 'respects limit parameter' do
159
+ 3.times { |i| budget.create_demand(label: "d#{i}", demand_type: :task, priority: 0.5, cost: 0.1, roi: 0.5) }
160
+ expect(budget.best_roi(limit: 2).size).to eq(2)
161
+ end
162
+ end
163
+
164
+ describe '#over_budget?' do
165
+ it 'returns false when within budget' do
166
+ expect(budget.over_budget?).to be false
167
+ end
168
+ end
169
+
170
+ describe '#budget_pressure' do
171
+ it 'equals utilization' do
172
+ expect(budget.budget_pressure).to eq(budget.utilization)
173
+ end
174
+ end
175
+
176
+ describe '#rebalance' do
177
+ it 'returns rebalanced: 0 when not over budget' do
178
+ result = budget.rebalance
179
+ expect(result[:rebalanced]).to eq(0)
180
+ end
181
+
182
+ it 'frees lowest-priority demands when over budget' do
183
+ b = described_class.new(total_budget: 0.5)
184
+ d1 = b.create_demand(label: 'lo', demand_type: :task, priority: 0.1, cost: 0.3)
185
+ d2 = b.create_demand(label: 'hi', demand_type: :task, priority: 0.9, cost: 0.3)
186
+ b.allocate(demand_id: d1.id)
187
+ b.allocate(demand_id: d2.id)
188
+ b.instance_variable_set(:@spent, 0.7)
189
+ result = b.rebalance
190
+ expect(result[:rebalanced]).to be >= 1
191
+ end
192
+ end
193
+
194
+ describe '#budget_report' do
195
+ it 'includes all expected keys' do
196
+ report = budget.budget_report
197
+ %i[total_budget spent available utilization recovered over_budget budget_pressure demand_count allocated_count].each do |key|
198
+ expect(report).to have_key(key)
199
+ end
200
+ end
201
+ end
202
+
203
+ describe '#to_h' do
204
+ it 'includes demands array' do
205
+ add_demand
206
+ h = budget.to_h
207
+ expect(h[:demands]).to be_an(Array)
208
+ expect(h[:demands].size).to eq(1)
209
+ end
210
+ end
211
+
212
+ describe '#find_demand' do
213
+ it 'returns demand by id' do
214
+ demand = add_demand
215
+ expect(budget.find_demand(demand.id)).to eq(demand)
216
+ end
217
+
218
+ it 'returns nil for unknown id' do
219
+ expect(budget.find_demand('nope')).to be_nil
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/attention/economy/helpers/demand'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Attention::Economy::Helpers::Constants do
6
+ describe 'MAX_DEMANDS' do
7
+ it 'is 200' do
8
+ expect(described_class::MAX_DEMANDS).to eq(200)
9
+ end
10
+ end
11
+
12
+ describe 'DEFAULT_BUDGET' do
13
+ it 'is 1.0' do
14
+ expect(described_class::DEFAULT_BUDGET).to eq(1.0)
15
+ end
16
+ end
17
+
18
+ describe 'BUDGET_RECOVERY_RATE' do
19
+ it 'is 0.05' do
20
+ expect(described_class::BUDGET_RECOVERY_RATE).to eq(0.05)
21
+ end
22
+ end
23
+
24
+ describe 'MIN_ALLOCATION' do
25
+ it 'is 0.01' do
26
+ expect(described_class::MIN_ALLOCATION).to eq(0.01)
27
+ end
28
+ end
29
+
30
+ describe 'PRIORITY_LABELS via Demand#priority_label' do
31
+ def demand_with_priority(pri)
32
+ Legion::Extensions::Agentic::Attention::Economy::Helpers::Demand.new(
33
+ label: 'x', demand_type: :task, priority: pri, cost: 0.1
34
+ )
35
+ end
36
+
37
+ it 'labels 0.9 as critical' do
38
+ expect(demand_with_priority(0.9).priority_label).to eq(:critical)
39
+ end
40
+
41
+ it 'labels 0.7 as high' do
42
+ expect(demand_with_priority(0.7).priority_label).to eq(:high)
43
+ end
44
+
45
+ it 'labels 0.5 as moderate' do
46
+ expect(demand_with_priority(0.5).priority_label).to eq(:moderate)
47
+ end
48
+
49
+ it 'labels 0.3 as low' do
50
+ expect(demand_with_priority(0.3).priority_label).to eq(:low)
51
+ end
52
+
53
+ it 'labels 0.1 as background' do
54
+ expect(demand_with_priority(0.1).priority_label).to eq(:background)
55
+ end
56
+
57
+ it 'labels boundary 0.8 as critical' do
58
+ expect(demand_with_priority(0.8).priority_label).to eq(:critical)
59
+ end
60
+
61
+ it 'labels boundary 0.6 as high' do
62
+ expect(demand_with_priority(0.6).priority_label).to eq(:high)
63
+ end
64
+ end
65
+
66
+ describe 'EFFICIENCY_LABELS via Demand#efficiency_label' do
67
+ def demand_with_efficiency(roi, cost)
68
+ Legion::Extensions::Agentic::Attention::Economy::Helpers::Demand.new(
69
+ label: 'x', demand_type: :task, priority: 0.5, cost: cost, roi: roi
70
+ )
71
+ end
72
+
73
+ it 'labels 0.9 efficiency as excellent' do
74
+ d = demand_with_efficiency(0.9, 1.0)
75
+ expect(d.efficiency_label).to eq(:excellent)
76
+ end
77
+
78
+ it 'labels 0.7 efficiency as good' do
79
+ d = demand_with_efficiency(0.7, 1.0)
80
+ expect(d.efficiency_label).to eq(:good)
81
+ end
82
+
83
+ it 'labels 0.5 efficiency as adequate' do
84
+ d = demand_with_efficiency(0.5, 1.0)
85
+ expect(d.efficiency_label).to eq(:adequate)
86
+ end
87
+
88
+ it 'labels 0.3 efficiency as poor' do
89
+ d = demand_with_efficiency(0.3, 1.0)
90
+ expect(d.efficiency_label).to eq(:poor)
91
+ end
92
+
93
+ it 'labels 0.1 efficiency as wasted' do
94
+ d = demand_with_efficiency(0.1, 1.0)
95
+ expect(d.efficiency_label).to eq(:wasted)
96
+ end
97
+ end
98
+
99
+ describe 'DEMAND_TYPES' do
100
+ it 'includes all six types' do
101
+ expect(described_class::DEMAND_TYPES).to include(:task, :sensory, :social, :emotional, :cognitive, :maintenance)
102
+ end
103
+
104
+ it 'is frozen' do
105
+ expect(described_class::DEMAND_TYPES).to be_frozen
106
+ end
107
+
108
+ it 'has exactly six types' do
109
+ expect(described_class::DEMAND_TYPES.size).to eq(6)
110
+ end
111
+ end
112
+ end