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,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Prism::Helpers::Beam do
4
+ let(:beam_id) { 'test-beam-001' }
5
+ let(:domain) { :cognition }
6
+ let(:content) { 'The idea of emergence in complex systems where local interactions produce global patterns' }
7
+ subject(:beam) { described_class.new(beam_id: beam_id, domain: domain, content: content) }
8
+
9
+ describe '#initialize' do
10
+ it 'sets beam_id' do
11
+ expect(beam.beam_id).to eq(beam_id)
12
+ end
13
+
14
+ it 'sets domain' do
15
+ expect(beam.domain).to eq(domain)
16
+ end
17
+
18
+ it 'sets content' do
19
+ expect(beam.content).to eq(content)
20
+ end
21
+
22
+ it 'starts with no components' do
23
+ expect(beam.components).to be_empty
24
+ end
25
+
26
+ it 'starts with purity 0.0' do
27
+ expect(beam.purity).to eq(0.0)
28
+ end
29
+ end
30
+
31
+ describe '#decompose!' do
32
+ before { beam.decompose! }
33
+
34
+ it 'returns self for chaining' do
35
+ fresh = described_class.new(beam_id: 'x', domain: :test, content: 'test')
36
+ expect(fresh.decompose!).to be(fresh)
37
+ end
38
+
39
+ it 'creates one component per spectral band' do
40
+ expect(beam.components.size).to eq(Legion::Extensions::Agentic::Attention::Prism::Helpers::Constants::SPECTRAL_BANDS.size)
41
+ end
42
+
43
+ it 'creates components as SpectralComponent instances' do
44
+ beam.components.each do |c|
45
+ expect(c).to be_a(Legion::Extensions::Agentic::Attention::Prism::Helpers::SpectralComponent)
46
+ end
47
+ end
48
+
49
+ it 'covers all spectral bands' do
50
+ bands = beam.components.map(&:band)
51
+ expect(bands).to contain_exactly(*Legion::Extensions::Agentic::Attention::Prism::Helpers::Constants::SPECTRAL_BANDS)
52
+ end
53
+
54
+ it 'sets purity after decomposition' do
55
+ expect(beam.purity).to be >= 0.0
56
+ expect(beam.purity).to be <= 1.0
57
+ end
58
+
59
+ it 'all component intensities are in 0..1' do
60
+ beam.components.each do |c|
61
+ expect(c.intensity).to be_between(0.0, 1.0)
62
+ end
63
+ end
64
+
65
+ it 'works with empty content' do
66
+ empty_beam = described_class.new(beam_id: 'empty', domain: :test, content: '')
67
+ empty_beam.decompose!
68
+ expect(empty_beam.components.size).to eq(8)
69
+ end
70
+ end
71
+
72
+ describe '#recompose' do
73
+ it 'returns empty string when no components' do
74
+ expect(beam.recompose).to eq('')
75
+ end
76
+
77
+ it 'returns a synthesis string after decomposition' do
78
+ beam.decompose!
79
+ result = beam.recompose
80
+ expect(result).to be_a(String)
81
+ expect(result).not_to be_empty
82
+ end
83
+
84
+ it 'excludes faded components' do
85
+ beam.decompose!
86
+ beam.components.each { |c| c.attenuate!(rate: 0.99) }
87
+ result = beam.recompose
88
+ # all faded -> empty
89
+ expect(result).to eq('')
90
+ end
91
+
92
+ it 'sorts by descending intensity in synthesis' do
93
+ beam.decompose!
94
+ active = beam.components.reject(&:faded?)
95
+ next if active.empty?
96
+
97
+ active.sort_by { |c| -c.intensity }.map(&:intensity)
98
+ result = beam.recompose
99
+ # verify result is non-empty and structured
100
+ expect(result).to include('|') if active.size > 1
101
+ end
102
+ end
103
+
104
+ describe '#dominant_band' do
105
+ it 'returns nil when no components' do
106
+ expect(beam.dominant_band).to be_nil
107
+ end
108
+
109
+ it 'returns a band symbol after decomposition' do
110
+ beam.decompose!
111
+ band = beam.dominant_band
112
+ expect(band).to be_a(Symbol)
113
+ expect(Legion::Extensions::Agentic::Attention::Prism::Helpers::Constants::SPECTRAL_BANDS).to include(band)
114
+ end
115
+
116
+ it 'returns the band with highest intensity' do
117
+ beam.decompose!
118
+ beam.components.max_by(&:intensity).band
119
+ # dominant_band prefers dominant? ones but falls back to max intensity
120
+ expect(beam.dominant_band).to be_a(Symbol)
121
+ expect(beam.dominant_band).not_to be_nil
122
+ end
123
+ end
124
+
125
+ describe '#spectral_balance' do
126
+ it 'returns empty hash when no components' do
127
+ expect(beam.spectral_balance).to eq({})
128
+ end
129
+
130
+ it 'returns a hash with band keys after decomposition' do
131
+ beam.decompose!
132
+ balance = beam.spectral_balance
133
+ expect(balance).to be_a(Hash)
134
+ balance.each_key do |k|
135
+ expect(Legion::Extensions::Agentic::Attention::Prism::Helpers::Constants::SPECTRAL_BANDS).to include(k)
136
+ end
137
+ end
138
+
139
+ it 'balance values sum to approximately 1.0' do
140
+ beam.decompose!
141
+ balance = beam.spectral_balance
142
+ next if balance.empty?
143
+
144
+ expect(balance.values.sum).to be_within(0.001).of(1.0)
145
+ end
146
+
147
+ it 'all balance values are between 0 and 1' do
148
+ beam.decompose!
149
+ beam.spectral_balance.each_value do |v|
150
+ expect(v).to be_between(0.0, 1.0)
151
+ end
152
+ end
153
+ end
154
+
155
+ describe '#to_h' do
156
+ it 'returns a hash with expected keys when not decomposed' do
157
+ h = beam.to_h
158
+ expect(h).to have_key(:beam_id)
159
+ expect(h).to have_key(:domain)
160
+ expect(h).to have_key(:content)
161
+ expect(h).to have_key(:purity)
162
+ expect(h).to have_key(:components)
163
+ end
164
+
165
+ it 'includes purity_label' do
166
+ expect(beam.to_h).to have_key(:purity_label)
167
+ end
168
+
169
+ it 'includes spectral_balance' do
170
+ expect(beam.to_h).to have_key(:spectral_balance)
171
+ end
172
+
173
+ it 'includes dominant_band' do
174
+ expect(beam.to_h).to have_key(:dominant_band)
175
+ end
176
+
177
+ it 'includes component_count' do
178
+ beam.decompose!
179
+ expect(beam.to_h[:component_count]).to eq(8)
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Prism::Helpers::Constants do
4
+ describe 'SPECTRAL_BANDS' do
5
+ it 'contains exactly 8 bands' do
6
+ expect(described_class::SPECTRAL_BANDS.size).to eq(8)
7
+ end
8
+
9
+ it 'includes all expected bands in order' do
10
+ expect(described_class::SPECTRAL_BANDS).to eq(
11
+ %i[infrared red orange yellow green blue violet ultraviolet]
12
+ )
13
+ end
14
+
15
+ it 'is frozen' do
16
+ expect(described_class::SPECTRAL_BANDS).to be_frozen
17
+ end
18
+ end
19
+
20
+ describe 'WAVELENGTH_RANGES' do
21
+ it 'has a range for every spectral band' do
22
+ described_class::SPECTRAL_BANDS.each do |band|
23
+ expect(described_class::WAVELENGTH_RANGES).to have_key(band)
24
+ end
25
+ end
26
+
27
+ it 'infrared covers 700..1000' do
28
+ expect(described_class::WAVELENGTH_RANGES[:infrared]).to eq(700..1000)
29
+ end
30
+
31
+ it 'red covers 620..699' do
32
+ expect(described_class::WAVELENGTH_RANGES[:red]).to eq(620..699)
33
+ end
34
+
35
+ it 'ultraviolet covers 10..379' do
36
+ expect(described_class::WAVELENGTH_RANGES[:ultraviolet]).to eq(10..379)
37
+ end
38
+
39
+ it 'all ranges are Range objects' do
40
+ described_class::WAVELENGTH_RANGES.each_value do |range|
41
+ expect(range).to be_a(Range)
42
+ end
43
+ end
44
+ end
45
+
46
+ describe 'MAX_BEAMS' do
47
+ it 'is 200' do
48
+ expect(described_class::MAX_BEAMS).to eq(200)
49
+ end
50
+ end
51
+
52
+ describe 'INTENSITY_LABELS' do
53
+ it 'has 5 entries' do
54
+ expect(described_class::INTENSITY_LABELS.size).to eq(5)
55
+ end
56
+
57
+ it 'labels trace for intensity 0.0..0.19' do
58
+ entry = described_class::INTENSITY_LABELS.find { |e| e[:range].cover?(0.0) }
59
+ expect(entry[:label]).to eq(:trace)
60
+ end
61
+
62
+ it 'labels brilliant for intensity 0.8..1.0' do
63
+ entry = described_class::INTENSITY_LABELS.find { |e| e[:range].cover?(1.0) }
64
+ expect(entry[:label]).to eq(:brilliant)
65
+ end
66
+
67
+ it 'labels moderate for intensity 0.5' do
68
+ entry = described_class::INTENSITY_LABELS.find { |e| e[:range].cover?(0.5) }
69
+ expect(entry[:label]).to eq(:moderate)
70
+ end
71
+ end
72
+
73
+ describe 'PURITY_LABELS' do
74
+ it 'has 5 entries' do
75
+ expect(described_class::PURITY_LABELS.size).to eq(5)
76
+ end
77
+
78
+ it 'labels turbid for purity 0.0' do
79
+ entry = described_class::PURITY_LABELS.find { |e| e[:range].cover?(0.0) }
80
+ expect(entry[:label]).to eq(:turbid)
81
+ end
82
+
83
+ it 'labels prismatic for purity 1.0' do
84
+ entry = described_class::PURITY_LABELS.find { |e| e[:range].cover?(1.0) }
85
+ expect(entry[:label]).to eq(:prismatic)
86
+ end
87
+
88
+ it 'labels pure for purity 0.8' do
89
+ entry = described_class::PURITY_LABELS.find { |e| e[:range].cover?(0.8) }
90
+ expect(entry[:label]).to eq(:pure)
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,253 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Prism::Helpers::PrismEngine do
4
+ subject(:engine) { described_class.new }
5
+
6
+ describe '#create_beam' do
7
+ it 'creates a beam and returns success' do
8
+ result = engine.create_beam(domain: :cognition, content: 'test idea')
9
+ expect(result[:success]).to be true
10
+ expect(result[:beam_id]).to be_a(String)
11
+ expect(result[:domain]).to eq(:cognition)
12
+ end
13
+
14
+ it 'uses provided beam_id when given' do
15
+ result = engine.create_beam(domain: :logic, content: 'custom id', beam_id: 'my-beam')
16
+ expect(result[:beam_id]).to eq('my-beam')
17
+ end
18
+
19
+ it 'generates a uuid beam_id when not provided' do
20
+ result = engine.create_beam(domain: :logic, content: 'auto id')
21
+ expect(result[:beam_id]).to match(/\A[0-9a-f-]{36}\z/)
22
+ end
23
+
24
+ it 'stores the created beam' do
25
+ result = engine.create_beam(domain: :test, content: 'stored')
26
+ expect(engine.beam_count).to eq(1)
27
+ expect(engine.get_beam(result[:beam_id])).not_to be_nil
28
+ end
29
+
30
+ it 'raises ArgumentError when MAX_BEAMS is reached' do
31
+ stub_const('Legion::Extensions::Agentic::Attention::Prism::Helpers::Constants::MAX_BEAMS', 2)
32
+ engine.create_beam(domain: :d, content: 'a')
33
+ engine.create_beam(domain: :d, content: 'b')
34
+ expect { engine.create_beam(domain: :d, content: 'c') }.to raise_error(ArgumentError, /MAX_BEAMS/)
35
+ end
36
+
37
+ it 'increments beam_count each time' do
38
+ 3.times { |i| engine.create_beam(domain: :test, content: "idea #{i}") }
39
+ expect(engine.beam_count).to eq(3)
40
+ end
41
+ end
42
+
43
+ describe '#decompose' do
44
+ let(:beam_id) { engine.create_beam(domain: :science, content: 'quantum entanglement across spacetime')[:beam_id] }
45
+
46
+ it 'returns success with component count' do
47
+ result = engine.decompose(beam_id)
48
+ expect(result[:success]).to be true
49
+ expect(result[:component_count]).to eq(8)
50
+ end
51
+
52
+ it 'returns dominant_band' do
53
+ result = engine.decompose(beam_id)
54
+ expect(result[:dominant_band]).to be_a(Symbol)
55
+ end
56
+
57
+ it 'returns purity value' do
58
+ result = engine.decompose(beam_id)
59
+ expect(result[:purity]).to be_between(0.0, 1.0)
60
+ end
61
+
62
+ it 'returns error when beam not found' do
63
+ result = engine.decompose('nonexistent-id')
64
+ expect(result[:success]).to be false
65
+ expect(result[:error]).to include('not found')
66
+ end
67
+ end
68
+
69
+ describe '#recompose' do
70
+ before do
71
+ @id = engine.create_beam(domain: :philosophy, content: 'consciousness and qualia')[:beam_id]
72
+ engine.decompose(@id)
73
+ end
74
+
75
+ it 'returns success with synthesis string' do
76
+ beam = engine.get_beam(@id)
77
+ non_faded = beam.components.reject(&:faded?)
78
+ ids = non_faded.map { |c| "#{@id}:#{c.band}" }
79
+ result = engine.recompose(ids)
80
+ expect(result[:success]).to be true
81
+ end
82
+
83
+ it 'returns empty synthesis for empty component_ids' do
84
+ result = engine.recompose([])
85
+ expect(result[:success]).to be true
86
+ expect(result[:synthesis]).to eq('')
87
+ end
88
+
89
+ it 'returns empty synthesis for unknown component ids' do
90
+ result = engine.recompose(['fake:red', 'fake:blue'])
91
+ expect(result[:success]).to be true
92
+ expect(result[:active_count]).to eq(0)
93
+ end
94
+ end
95
+
96
+ describe '#attenuate_all!' do
97
+ before do
98
+ id1 = engine.create_beam(domain: :d, content: 'idea one')[:beam_id]
99
+ id2 = engine.create_beam(domain: :d, content: 'idea two')[:beam_id]
100
+ engine.decompose(id1)
101
+ engine.decompose(id2)
102
+ end
103
+
104
+ it 'returns success with count of attenuated components' do
105
+ result = engine.attenuate_all!
106
+ expect(result[:success]).to be true
107
+ expect(result[:attenuated]).to eq(16)
108
+ end
109
+
110
+ it 'returns the rate used' do
111
+ result = engine.attenuate_all!(rate: 0.05)
112
+ expect(result[:rate]).to eq(0.05)
113
+ end
114
+
115
+ it 'reduces intensities of all components' do
116
+ id = engine.create_beam(domain: :test, content: 'bright idea')[:beam_id]
117
+ engine.decompose(id)
118
+ beam = engine.get_beam(id)
119
+ before_intensities = beam.components.map(&:intensity).dup
120
+ engine.attenuate_all!(rate: 0.2)
121
+ after_intensities = beam.components.map(&:intensity)
122
+ before_intensities.zip(after_intensities).each do |before, after|
123
+ expect(after).to be <= before
124
+ end
125
+ end
126
+
127
+ it 'works when no beams have been decomposed' do
128
+ fresh = described_class.new
129
+ fresh.create_beam(domain: :d, content: 'x')
130
+ result = fresh.attenuate_all!
131
+ expect(result[:success]).to be true
132
+ expect(result[:attenuated]).to eq(0)
133
+ end
134
+ end
135
+
136
+ describe '#dominant_bands' do
137
+ it 'returns empty hash when no beams' do
138
+ expect(engine.dominant_bands).to eq({})
139
+ end
140
+
141
+ it 'returns a hash with band counts after decomposition' do
142
+ id = engine.create_beam(domain: :test, content: 'a complex idea about systems')[:beam_id]
143
+ engine.decompose(id)
144
+ bands = engine.dominant_bands
145
+ expect(bands).to be_a(Hash)
146
+ end
147
+
148
+ it 'counts multiple beams correctly' do
149
+ 2.times do |i|
150
+ id = engine.create_beam(domain: :test, content: "idea #{i}" * 20)[:beam_id]
151
+ engine.decompose(id)
152
+ end
153
+ bands = engine.dominant_bands
154
+ expect(bands.values.sum).to eq(2)
155
+ end
156
+ end
157
+
158
+ describe '#most_intense' do
159
+ before do
160
+ 3.times do |i|
161
+ id = engine.create_beam(domain: :test, content: "concept #{i} with depth")[:beam_id]
162
+ engine.decompose(id)
163
+ end
164
+ end
165
+
166
+ it 'returns up to limit components' do
167
+ result = engine.most_intense(limit: 5)
168
+ expect(result.size).to be <= 5
169
+ end
170
+
171
+ it 'returns component hashes' do
172
+ result = engine.most_intense(limit: 3)
173
+ result.each do |item|
174
+ expect(item).to have_key(:band)
175
+ expect(item).to have_key(:intensity)
176
+ end
177
+ end
178
+
179
+ it 'returns fewer items than limit when not enough components' do
180
+ fresh = described_class.new
181
+ id = fresh.create_beam(domain: :d, content: 'x')[:beam_id]
182
+ fresh.decompose(id)
183
+ result = fresh.most_intense(limit: 100)
184
+ expect(result.size).to eq(8)
185
+ end
186
+
187
+ it 'returns components sorted by descending intensity' do
188
+ result = engine.most_intense(limit: 10)
189
+ intensities = result.map { |c| c[:intensity] }
190
+ expect(intensities).to eq(intensities.sort.reverse)
191
+ end
192
+ end
193
+
194
+ describe '#spectral_report' do
195
+ it 'returns expected keys' do
196
+ report = engine.spectral_report
197
+ expect(report).to have_key(:total_beams)
198
+ expect(report).to have_key(:decomposed_beams)
199
+ expect(report).to have_key(:total_components)
200
+ expect(report).to have_key(:dominant_bands)
201
+ expect(report).to have_key(:avg_purity)
202
+ expect(report).to have_key(:most_intense)
203
+ end
204
+
205
+ it 'reports 0 beams on fresh engine' do
206
+ expect(engine.spectral_report[:total_beams]).to eq(0)
207
+ end
208
+
209
+ it 'reports correct beam counts after creation and decomposition' do
210
+ 2.times { |i| engine.create_beam(domain: :d, content: "idea #{i}") }
211
+ id = engine.create_beam(domain: :d, content: 'decomposed')[:beam_id]
212
+ engine.decompose(id)
213
+ report = engine.spectral_report
214
+ expect(report[:total_beams]).to eq(3)
215
+ expect(report[:decomposed_beams]).to eq(1)
216
+ end
217
+
218
+ it 'avg_purity is 0.0 when no decomposed beams' do
219
+ engine.create_beam(domain: :d, content: 'not decomposed')
220
+ expect(engine.spectral_report[:avg_purity]).to eq(0.0)
221
+ end
222
+
223
+ it 'avg_purity is between 0 and 1 after decomposition' do
224
+ id = engine.create_beam(domain: :d, content: 'will decompose')[:beam_id]
225
+ engine.decompose(id)
226
+ expect(engine.spectral_report[:avg_purity]).to be_between(0.0, 1.0)
227
+ end
228
+ end
229
+
230
+ describe '#clear!' do
231
+ it 'removes all beams' do
232
+ engine.create_beam(domain: :d, content: 'a')
233
+ engine.create_beam(domain: :d, content: 'b')
234
+ engine.clear!
235
+ expect(engine.beam_count).to eq(0)
236
+ end
237
+
238
+ it 'returns self' do
239
+ expect(engine.clear!).to be(engine)
240
+ end
241
+ end
242
+
243
+ describe '#get_beam' do
244
+ it 'returns nil for unknown id' do
245
+ expect(engine.get_beam('nope')).to be_nil
246
+ end
247
+
248
+ it 'returns the beam for a known id' do
249
+ id = engine.create_beam(domain: :d, content: 'x')[:beam_id]
250
+ expect(engine.get_beam(id)).to be_a(Legion::Extensions::Agentic::Attention::Prism::Helpers::Beam)
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Attention::Prism::Helpers::SpectralComponent do
4
+ let(:valid_args) { { band: :green, wavelength: 520, intensity: 0.75, content: 'relational structure' } }
5
+ subject(:component) { described_class.new(**valid_args) }
6
+
7
+ describe '#initialize' do
8
+ it 'creates a component with valid attributes' do
9
+ expect(component.band).to eq(:green)
10
+ expect(component.wavelength).to eq(520)
11
+ expect(component.intensity).to eq(0.75)
12
+ expect(component.content).to eq('relational structure')
13
+ end
14
+
15
+ it 'raises ArgumentError for unknown band' do
16
+ expect { described_class.new(band: :gamma, wavelength: 520, intensity: 0.5, content: 'x') }
17
+ .to raise_error(ArgumentError, /Unknown band/)
18
+ end
19
+
20
+ it 'raises ArgumentError when wavelength out of range for band' do
21
+ expect { described_class.new(band: :red, wavelength: 200, intensity: 0.5, content: 'x') }
22
+ .to raise_error(ArgumentError, /out of range/)
23
+ end
24
+
25
+ it 'clamps intensity above 1.0 to 1.0' do
26
+ c = described_class.new(band: :blue, wavelength: 470, intensity: 1.5, content: 'test')
27
+ expect(c.intensity).to eq(1.0)
28
+ end
29
+
30
+ it 'clamps intensity below 0.0 to 0.0' do
31
+ c = described_class.new(band: :blue, wavelength: 470, intensity: -0.3, content: 'test')
32
+ expect(c.intensity).to eq(0.0)
33
+ end
34
+
35
+ it 'accepts intensity of exactly 0.0' do
36
+ c = described_class.new(band: :violet, wavelength: 420, intensity: 0.0, content: 'x')
37
+ expect(c.intensity).to eq(0.0)
38
+ end
39
+
40
+ it 'accepts intensity of exactly 1.0' do
41
+ c = described_class.new(band: :red, wavelength: 650, intensity: 1.0, content: 'x')
42
+ expect(c.intensity).to eq(1.0)
43
+ end
44
+ end
45
+
46
+ describe '#attenuate!' do
47
+ it 'reduces intensity by the default rate' do
48
+ original = component.intensity
49
+ component.attenuate!
50
+ expect(component.intensity).to be < original
51
+ end
52
+
53
+ it 'reduces intensity by the specified rate' do
54
+ component.attenuate!(rate: 0.3)
55
+ expect(component.intensity).to be_within(0.001).of(0.45)
56
+ end
57
+
58
+ it 'clamps intensity at 0.0' do
59
+ component.attenuate!(rate: 2.0)
60
+ expect(component.intensity).to eq(0.0)
61
+ end
62
+
63
+ it 'returns self for chaining' do
64
+ expect(component.attenuate!).to be(component)
65
+ end
66
+
67
+ it 'takes absolute value of rate (negative rate still attenuates)' do
68
+ original = component.intensity
69
+ component.attenuate!(rate: -0.1)
70
+ expect(component.intensity).to be < original
71
+ end
72
+ end
73
+
74
+ describe '#amplify!' do
75
+ let(:low_component) { described_class.new(band: :green, wavelength: 520, intensity: 0.3, content: 'low') }
76
+
77
+ it 'increases intensity by the default boost' do
78
+ original = low_component.intensity
79
+ low_component.amplify!
80
+ expect(low_component.intensity).to be > original
81
+ end
82
+
83
+ it 'increases intensity by specified boost' do
84
+ low_component.amplify!(boost: 0.4)
85
+ expect(low_component.intensity).to be_within(0.001).of(0.7)
86
+ end
87
+
88
+ it 'clamps intensity at 1.0' do
89
+ low_component.amplify!(boost: 5.0)
90
+ expect(low_component.intensity).to eq(1.0)
91
+ end
92
+
93
+ it 'returns self for chaining' do
94
+ expect(low_component.amplify!).to be(low_component)
95
+ end
96
+ end
97
+
98
+ describe '#dominant?' do
99
+ it 'returns true when intensity >= 0.7' do
100
+ c = described_class.new(band: :blue, wavelength: 470, intensity: 0.8, content: 'x')
101
+ expect(c.dominant?).to be true
102
+ end
103
+
104
+ it 'returns true at exactly 0.7' do
105
+ c = described_class.new(band: :blue, wavelength: 470, intensity: 0.7, content: 'x')
106
+ expect(c.dominant?).to be true
107
+ end
108
+
109
+ it 'returns false when intensity < 0.7' do
110
+ c = described_class.new(band: :blue, wavelength: 470, intensity: 0.69, content: 'x')
111
+ expect(c.dominant?).to be false
112
+ end
113
+ end
114
+
115
+ describe '#faded?' do
116
+ it 'returns true when intensity <= 0.1' do
117
+ c = described_class.new(band: :orange, wavelength: 600, intensity: 0.05, content: 'x')
118
+ expect(c.faded?).to be true
119
+ end
120
+
121
+ it 'returns true at exactly 0.1' do
122
+ c = described_class.new(band: :orange, wavelength: 600, intensity: 0.1, content: 'x')
123
+ expect(c.faded?).to be true
124
+ end
125
+
126
+ it 'returns false when intensity > 0.1' do
127
+ c = described_class.new(band: :orange, wavelength: 600, intensity: 0.11, content: 'x')
128
+ expect(c.faded?).to be false
129
+ end
130
+ end
131
+
132
+ describe '#intensity_label' do
133
+ it 'returns :trace for intensity 0.05' do
134
+ c = described_class.new(band: :green, wavelength: 520, intensity: 0.05, content: 'x')
135
+ expect(c.intensity_label).to eq(:trace)
136
+ end
137
+
138
+ it 'returns :brilliant for intensity 0.9' do
139
+ c = described_class.new(band: :green, wavelength: 520, intensity: 0.9, content: 'x')
140
+ expect(c.intensity_label).to eq(:brilliant)
141
+ end
142
+
143
+ it 'returns :strong for intensity 0.65' do
144
+ c = described_class.new(band: :green, wavelength: 520, intensity: 0.65, content: 'x')
145
+ expect(c.intensity_label).to eq(:strong)
146
+ end
147
+ end
148
+
149
+ describe '#to_h' do
150
+ it 'returns a hash with all expected keys' do
151
+ h = component.to_h
152
+ expect(h.keys).to contain_exactly(:band, :wavelength, :intensity, :intensity_label, :content, :dominant, :faded)
153
+ end
154
+
155
+ it 'includes correct band' do
156
+ expect(component.to_h[:band]).to eq(:green)
157
+ end
158
+
159
+ it 'includes dominant flag' do
160
+ expect(component.to_h[:dominant]).to be(component.dominant?)
161
+ end
162
+
163
+ it 'includes faded flag' do
164
+ expect(component.to_h[:faded]).to be(component.faded?)
165
+ end
166
+
167
+ it 'includes intensity rounded to 10 decimal places' do
168
+ expect(component.to_h[:intensity]).to eq(0.75)
169
+ end
170
+ end
171
+ end