lex-agentic-memory 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 (267) 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-memory.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/memory/archaeology/client.rb +19 -0
  8. data/lib/legion/extensions/agentic/memory/archaeology/helpers/archaeology_engine.rb +184 -0
  9. data/lib/legion/extensions/agentic/memory/archaeology/helpers/artifact.rb +146 -0
  10. data/lib/legion/extensions/agentic/memory/archaeology/helpers/constants.rb +95 -0
  11. data/lib/legion/extensions/agentic/memory/archaeology/helpers/excavation_site.rb +97 -0
  12. data/lib/legion/extensions/agentic/memory/archaeology/runners/cognitive_archaeology.rb +86 -0
  13. data/lib/legion/extensions/agentic/memory/archaeology/version.rb +13 -0
  14. data/lib/legion/extensions/agentic/memory/archaeology.rb +22 -0
  15. data/lib/legion/extensions/agentic/memory/compression/client.rb +15 -0
  16. data/lib/legion/extensions/agentic/memory/compression/helpers/compression_engine.rb +145 -0
  17. data/lib/legion/extensions/agentic/memory/compression/helpers/constants.rb +44 -0
  18. data/lib/legion/extensions/agentic/memory/compression/helpers/information_chunk.rb +81 -0
  19. data/lib/legion/extensions/agentic/memory/compression/runners/cognitive_compression.rb +76 -0
  20. data/lib/legion/extensions/agentic/memory/compression/version.rb +13 -0
  21. data/lib/legion/extensions/agentic/memory/compression.rb +19 -0
  22. data/lib/legion/extensions/agentic/memory/echo/client.rb +19 -0
  23. data/lib/legion/extensions/agentic/memory/echo/helpers/constants.rb +57 -0
  24. data/lib/legion/extensions/agentic/memory/echo/helpers/echo.rb +95 -0
  25. data/lib/legion/extensions/agentic/memory/echo/helpers/echo_engine.rb +136 -0
  26. data/lib/legion/extensions/agentic/memory/echo/runners/cognitive_echo.rb +81 -0
  27. data/lib/legion/extensions/agentic/memory/echo/version.rb +13 -0
  28. data/lib/legion/extensions/agentic/memory/echo.rb +19 -0
  29. data/lib/legion/extensions/agentic/memory/echo_chamber/client.rb +19 -0
  30. data/lib/legion/extensions/agentic/memory/echo_chamber/helpers/chamber.rb +134 -0
  31. data/lib/legion/extensions/agentic/memory/echo_chamber/helpers/chamber_engine.rb +156 -0
  32. data/lib/legion/extensions/agentic/memory/echo_chamber/helpers/constants.rb +60 -0
  33. data/lib/legion/extensions/agentic/memory/echo_chamber/helpers/echo.rb +96 -0
  34. data/lib/legion/extensions/agentic/memory/echo_chamber/runners/cognitive_echo_chamber.rb +84 -0
  35. data/lib/legion/extensions/agentic/memory/echo_chamber/version.rb +13 -0
  36. data/lib/legion/extensions/agentic/memory/echo_chamber.rb +21 -0
  37. data/lib/legion/extensions/agentic/memory/episodic/actors/decay.rb +45 -0
  38. data/lib/legion/extensions/agentic/memory/episodic/client.rb +25 -0
  39. data/lib/legion/extensions/agentic/memory/episodic/helpers/constants.rb +36 -0
  40. data/lib/legion/extensions/agentic/memory/episodic/helpers/episode.rb +104 -0
  41. data/lib/legion/extensions/agentic/memory/episodic/helpers/episodic_binding.rb +57 -0
  42. data/lib/legion/extensions/agentic/memory/episodic/helpers/episodic_store.rb +141 -0
  43. data/lib/legion/extensions/agentic/memory/episodic/runners/episodic_buffer.rb +108 -0
  44. data/lib/legion/extensions/agentic/memory/episodic/version.rb +13 -0
  45. data/lib/legion/extensions/agentic/memory/episodic.rb +20 -0
  46. data/lib/legion/extensions/agentic/memory/hologram/client.rb +23 -0
  47. data/lib/legion/extensions/agentic/memory/hologram/helpers/constants.rb +67 -0
  48. data/lib/legion/extensions/agentic/memory/hologram/helpers/hologram.rb +118 -0
  49. data/lib/legion/extensions/agentic/memory/hologram/helpers/hologram_engine.rb +117 -0
  50. data/lib/legion/extensions/agentic/memory/hologram/helpers/holographic_fragment.rb +70 -0
  51. data/lib/legion/extensions/agentic/memory/hologram/runners/cognitive_hologram.rb +110 -0
  52. data/lib/legion/extensions/agentic/memory/hologram/version.rb +13 -0
  53. data/lib/legion/extensions/agentic/memory/hologram.rb +22 -0
  54. data/lib/legion/extensions/agentic/memory/immune_memory/client.rb +19 -0
  55. data/lib/legion/extensions/agentic/memory/immune_memory/helpers/constants.rb +84 -0
  56. data/lib/legion/extensions/agentic/memory/immune_memory/helpers/encounter.rb +54 -0
  57. data/lib/legion/extensions/agentic/memory/immune_memory/helpers/immune_memory_engine.rb +171 -0
  58. data/lib/legion/extensions/agentic/memory/immune_memory/helpers/memory_cell.rb +97 -0
  59. data/lib/legion/extensions/agentic/memory/immune_memory/runners/cognitive_immune_memory.rb +76 -0
  60. data/lib/legion/extensions/agentic/memory/immune_memory/version.rb +13 -0
  61. data/lib/legion/extensions/agentic/memory/immune_memory.rb +20 -0
  62. data/lib/legion/extensions/agentic/memory/nostalgia/client.rb +31 -0
  63. data/lib/legion/extensions/agentic/memory/nostalgia/helpers/constants.rb +68 -0
  64. data/lib/legion/extensions/agentic/memory/nostalgia/helpers/nostalgia_engine.rb +148 -0
  65. data/lib/legion/extensions/agentic/memory/nostalgia/helpers/nostalgia_event.rb +44 -0
  66. data/lib/legion/extensions/agentic/memory/nostalgia/helpers/nostalgic_memory.rb +97 -0
  67. data/lib/legion/extensions/agentic/memory/nostalgia/runners/analysis.rb +61 -0
  68. data/lib/legion/extensions/agentic/memory/nostalgia/runners/recall.rb +60 -0
  69. data/lib/legion/extensions/agentic/memory/nostalgia/version.rb +13 -0
  70. data/lib/legion/extensions/agentic/memory/nostalgia.rb +21 -0
  71. data/lib/legion/extensions/agentic/memory/offloading/client.rb +29 -0
  72. data/lib/legion/extensions/agentic/memory/offloading/helpers/constants.rb +55 -0
  73. data/lib/legion/extensions/agentic/memory/offloading/helpers/external_store.rb +82 -0
  74. data/lib/legion/extensions/agentic/memory/offloading/helpers/offloaded_item.rb +65 -0
  75. data/lib/legion/extensions/agentic/memory/offloading/helpers/offloading_engine.rb +138 -0
  76. data/lib/legion/extensions/agentic/memory/offloading/runners/cognitive_offloading.rb +102 -0
  77. data/lib/legion/extensions/agentic/memory/offloading/version.rb +13 -0
  78. data/lib/legion/extensions/agentic/memory/offloading.rb +20 -0
  79. data/lib/legion/extensions/agentic/memory/paleontology/client.rb +19 -0
  80. data/lib/legion/extensions/agentic/memory/paleontology/helpers/constants.rb +69 -0
  81. data/lib/legion/extensions/agentic/memory/paleontology/helpers/excavation.rb +62 -0
  82. data/lib/legion/extensions/agentic/memory/paleontology/helpers/fossil.rb +125 -0
  83. data/lib/legion/extensions/agentic/memory/paleontology/helpers/paleontology_engine.rb +170 -0
  84. data/lib/legion/extensions/agentic/memory/paleontology/runners/cognitive_paleontology.rb +93 -0
  85. data/lib/legion/extensions/agentic/memory/paleontology/version.rb +13 -0
  86. data/lib/legion/extensions/agentic/memory/paleontology.rb +22 -0
  87. data/lib/legion/extensions/agentic/memory/palimpsest/client.rb +19 -0
  88. data/lib/legion/extensions/agentic/memory/palimpsest/helpers/belief_layer.rb +81 -0
  89. data/lib/legion/extensions/agentic/memory/palimpsest/helpers/constants.rb +56 -0
  90. data/lib/legion/extensions/agentic/memory/palimpsest/helpers/palimpsest.rb +124 -0
  91. data/lib/legion/extensions/agentic/memory/palimpsest/helpers/palimpsest_engine.rb +117 -0
  92. data/lib/legion/extensions/agentic/memory/palimpsest/runners/cognitive_palimpsest.rb +105 -0
  93. data/lib/legion/extensions/agentic/memory/palimpsest/version.rb +13 -0
  94. data/lib/legion/extensions/agentic/memory/palimpsest.rb +21 -0
  95. data/lib/legion/extensions/agentic/memory/reserve/client.rb +19 -0
  96. data/lib/legion/extensions/agentic/memory/reserve/helpers/constants.rb +58 -0
  97. data/lib/legion/extensions/agentic/memory/reserve/helpers/pathway.rb +112 -0
  98. data/lib/legion/extensions/agentic/memory/reserve/helpers/reserve_engine.rb +163 -0
  99. data/lib/legion/extensions/agentic/memory/reserve/runners/cognitive_reserve.rb +92 -0
  100. data/lib/legion/extensions/agentic/memory/reserve/version.rb +13 -0
  101. data/lib/legion/extensions/agentic/memory/reserve.rb +19 -0
  102. data/lib/legion/extensions/agentic/memory/semantic/actors/decay.rb +45 -0
  103. data/lib/legion/extensions/agentic/memory/semantic/client.rb +28 -0
  104. data/lib/legion/extensions/agentic/memory/semantic/helpers/concept.rb +101 -0
  105. data/lib/legion/extensions/agentic/memory/semantic/helpers/constants.rb +51 -0
  106. data/lib/legion/extensions/agentic/memory/semantic/helpers/knowledge_store.rb +145 -0
  107. data/lib/legion/extensions/agentic/memory/semantic/runners/semantic_memory.rb +94 -0
  108. data/lib/legion/extensions/agentic/memory/semantic/version.rb +13 -0
  109. data/lib/legion/extensions/agentic/memory/semantic.rb +20 -0
  110. data/lib/legion/extensions/agentic/memory/semantic_priming/client.rb +19 -0
  111. data/lib/legion/extensions/agentic/memory/semantic_priming/helpers/connection.rb +77 -0
  112. data/lib/legion/extensions/agentic/memory/semantic_priming/helpers/constants.rb +68 -0
  113. data/lib/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network.rb +206 -0
  114. data/lib/legion/extensions/agentic/memory/semantic_priming/helpers/semantic_node.rb +81 -0
  115. data/lib/legion/extensions/agentic/memory/semantic_priming/runners/semantic_priming.rb +120 -0
  116. data/lib/legion/extensions/agentic/memory/semantic_priming/version.rb +13 -0
  117. data/lib/legion/extensions/agentic/memory/semantic_priming.rb +20 -0
  118. data/lib/legion/extensions/agentic/memory/semantic_satiation/client.rb +28 -0
  119. data/lib/legion/extensions/agentic/memory/semantic_satiation/helpers/concept.rb +82 -0
  120. data/lib/legion/extensions/agentic/memory/semantic_satiation/helpers/constants.rb +37 -0
  121. data/lib/legion/extensions/agentic/memory/semantic_satiation/helpers/satiation_engine.rb +103 -0
  122. data/lib/legion/extensions/agentic/memory/semantic_satiation/runners/semantic_satiation.rb +92 -0
  123. data/lib/legion/extensions/agentic/memory/semantic_satiation/version.rb +13 -0
  124. data/lib/legion/extensions/agentic/memory/semantic_satiation.rb +19 -0
  125. data/lib/legion/extensions/agentic/memory/source_monitoring/actors/decay.rb +31 -0
  126. data/lib/legion/extensions/agentic/memory/source_monitoring/client.rb +28 -0
  127. data/lib/legion/extensions/agentic/memory/source_monitoring/helpers/constants.rb +66 -0
  128. data/lib/legion/extensions/agentic/memory/source_monitoring/helpers/source_record.rb +94 -0
  129. data/lib/legion/extensions/agentic/memory/source_monitoring/helpers/source_tracker.rb +119 -0
  130. data/lib/legion/extensions/agentic/memory/source_monitoring/runners/source_monitoring.rb +95 -0
  131. data/lib/legion/extensions/agentic/memory/source_monitoring/version.rb +13 -0
  132. data/lib/legion/extensions/agentic/memory/source_monitoring.rb +19 -0
  133. data/lib/legion/extensions/agentic/memory/trace/actors/decay.rb +45 -0
  134. data/lib/legion/extensions/agentic/memory/trace/actors/tier_migration.rb +45 -0
  135. data/lib/legion/extensions/agentic/memory/trace/batch_decay.rb +44 -0
  136. data/lib/legion/extensions/agentic/memory/trace/client.rb +32 -0
  137. data/lib/legion/extensions/agentic/memory/trace/helpers/cache_store.rb +167 -0
  138. data/lib/legion/extensions/agentic/memory/trace/helpers/decay.rb +68 -0
  139. data/lib/legion/extensions/agentic/memory/trace/helpers/error_tracer.rb +94 -0
  140. data/lib/legion/extensions/agentic/memory/trace/helpers/store.rb +260 -0
  141. data/lib/legion/extensions/agentic/memory/trace/helpers/trace.rb +106 -0
  142. data/lib/legion/extensions/agentic/memory/trace/local_migrations/20260316000001_create_memory_traces.rb +31 -0
  143. data/lib/legion/extensions/agentic/memory/trace/local_migrations/20260316000002_create_memory_associations.rb +13 -0
  144. data/lib/legion/extensions/agentic/memory/trace/persistent_store.rb +94 -0
  145. data/lib/legion/extensions/agentic/memory/trace/quota.rb +55 -0
  146. data/lib/legion/extensions/agentic/memory/trace/runners/consolidation.rb +121 -0
  147. data/lib/legion/extensions/agentic/memory/trace/runners/traces.rb +105 -0
  148. data/lib/legion/extensions/agentic/memory/trace/version.rb +13 -0
  149. data/lib/legion/extensions/agentic/memory/trace.rb +54 -0
  150. data/lib/legion/extensions/agentic/memory/transfer/client.rb +28 -0
  151. data/lib/legion/extensions/agentic/memory/transfer/helpers/constants.rb +34 -0
  152. data/lib/legion/extensions/agentic/memory/transfer/helpers/domain_knowledge.rb +74 -0
  153. data/lib/legion/extensions/agentic/memory/transfer/helpers/transfer_engine.rb +188 -0
  154. data/lib/legion/extensions/agentic/memory/transfer/runners/transfer_learning.rb +77 -0
  155. data/lib/legion/extensions/agentic/memory/transfer/version.rb +13 -0
  156. data/lib/legion/extensions/agentic/memory/transfer.rb +19 -0
  157. data/lib/legion/extensions/agentic/memory/version.rb +11 -0
  158. data/lib/legion/extensions/agentic/memory.rb +35 -0
  159. data/spec/legion/extensions/agentic/memory/archaeology/client_spec.rb +38 -0
  160. data/spec/legion/extensions/agentic/memory/archaeology/cognitive_archaeology_spec.rb +7 -0
  161. data/spec/legion/extensions/agentic/memory/archaeology/helpers/archaeology_engine_spec.rb +165 -0
  162. data/spec/legion/extensions/agentic/memory/archaeology/helpers/artifact_spec.rb +196 -0
  163. data/spec/legion/extensions/agentic/memory/archaeology/helpers/constants_spec.rb +42 -0
  164. data/spec/legion/extensions/agentic/memory/archaeology/helpers/excavation_site_spec.rb +115 -0
  165. data/spec/legion/extensions/agentic/memory/archaeology/runners/cognitive_archaeology_spec.rb +96 -0
  166. data/spec/legion/extensions/agentic/memory/compression/helpers/compression_engine_spec.rb +138 -0
  167. data/spec/legion/extensions/agentic/memory/compression/helpers/constants_spec.rb +50 -0
  168. data/spec/legion/extensions/agentic/memory/compression/helpers/information_chunk_spec.rb +123 -0
  169. data/spec/legion/extensions/agentic/memory/compression/runners/cognitive_compression_spec.rb +80 -0
  170. data/spec/legion/extensions/agentic/memory/echo/client_spec.rb +20 -0
  171. data/spec/legion/extensions/agentic/memory/echo/cognitive_echo_spec.rb +7 -0
  172. data/spec/legion/extensions/agentic/memory/echo/helpers/echo_engine_spec.rb +152 -0
  173. data/spec/legion/extensions/agentic/memory/echo/helpers/echo_spec.rb +128 -0
  174. data/spec/legion/extensions/agentic/memory/echo/runners_spec.rb +80 -0
  175. data/spec/legion/extensions/agentic/memory/echo_chamber/client_spec.rb +84 -0
  176. data/spec/legion/extensions/agentic/memory/echo_chamber/helpers/chamber_engine_spec.rb +266 -0
  177. data/spec/legion/extensions/agentic/memory/echo_chamber/helpers/chamber_spec.rb +249 -0
  178. data/spec/legion/extensions/agentic/memory/echo_chamber/helpers/constants_spec.rb +130 -0
  179. data/spec/legion/extensions/agentic/memory/echo_chamber/helpers/echo_spec.rb +252 -0
  180. data/spec/legion/extensions/agentic/memory/echo_chamber/runners/cognitive_echo_chamber_spec.rb +185 -0
  181. data/spec/legion/extensions/agentic/memory/episodic/client_spec.rb +80 -0
  182. data/spec/legion/extensions/agentic/memory/episodic/episodic_buffer_spec.rb +15 -0
  183. data/spec/legion/extensions/agentic/memory/episodic/helpers/constants_spec.rb +86 -0
  184. data/spec/legion/extensions/agentic/memory/episodic/helpers/episode_spec.rb +188 -0
  185. data/spec/legion/extensions/agentic/memory/episodic/helpers/episodic_binding_spec.rb +114 -0
  186. data/spec/legion/extensions/agentic/memory/episodic/helpers/episodic_store_spec.rb +201 -0
  187. data/spec/legion/extensions/agentic/memory/episodic/runners/episodic_buffer_spec.rb +208 -0
  188. data/spec/legion/extensions/agentic/memory/hologram/client_spec.rb +89 -0
  189. data/spec/legion/extensions/agentic/memory/hologram/cognitive_hologram_spec.rb +39 -0
  190. data/spec/legion/extensions/agentic/memory/hologram/helpers/constants_spec.rb +143 -0
  191. data/spec/legion/extensions/agentic/memory/hologram/helpers/hologram_engine_spec.rb +268 -0
  192. data/spec/legion/extensions/agentic/memory/hologram/helpers/hologram_spec.rb +256 -0
  193. data/spec/legion/extensions/agentic/memory/hologram/helpers/holographic_fragment_spec.rb +213 -0
  194. data/spec/legion/extensions/agentic/memory/hologram/runners/cognitive_hologram_spec.rb +239 -0
  195. data/spec/legion/extensions/agentic/memory/immune_memory/client_spec.rb +18 -0
  196. data/spec/legion/extensions/agentic/memory/immune_memory/cognitive_immune_memory_spec.rb +7 -0
  197. data/spec/legion/extensions/agentic/memory/immune_memory/helpers/encounter_spec.rb +85 -0
  198. data/spec/legion/extensions/agentic/memory/immune_memory/helpers/immune_memory_engine_spec.rb +203 -0
  199. data/spec/legion/extensions/agentic/memory/immune_memory/helpers/memory_cell_spec.rb +190 -0
  200. data/spec/legion/extensions/agentic/memory/immune_memory/runners_spec.rb +83 -0
  201. data/spec/legion/extensions/agentic/memory/nostalgia/client_spec.rb +71 -0
  202. data/spec/legion/extensions/agentic/memory/nostalgia/helpers/constants_spec.rb +65 -0
  203. data/spec/legion/extensions/agentic/memory/nostalgia/helpers/nostalgia_engine_spec.rb +191 -0
  204. data/spec/legion/extensions/agentic/memory/nostalgia/helpers/nostalgia_event_spec.rb +59 -0
  205. data/spec/legion/extensions/agentic/memory/nostalgia/helpers/nostalgic_memory_spec.rb +134 -0
  206. data/spec/legion/extensions/agentic/memory/nostalgia/runners/analysis_spec.rb +97 -0
  207. data/spec/legion/extensions/agentic/memory/nostalgia/runners/recall_spec.rb +81 -0
  208. data/spec/legion/extensions/agentic/memory/offloading/client_spec.rb +30 -0
  209. data/spec/legion/extensions/agentic/memory/offloading/helpers/constants_spec.rb +71 -0
  210. data/spec/legion/extensions/agentic/memory/offloading/helpers/external_store_spec.rb +158 -0
  211. data/spec/legion/extensions/agentic/memory/offloading/helpers/offloaded_item_spec.rb +123 -0
  212. data/spec/legion/extensions/agentic/memory/offloading/helpers/offloading_engine_spec.rb +250 -0
  213. data/spec/legion/extensions/agentic/memory/offloading/runners/cognitive_offloading_spec.rb +194 -0
  214. data/spec/legion/extensions/agentic/memory/paleontology/client_spec.rb +27 -0
  215. data/spec/legion/extensions/agentic/memory/paleontology/cognitive_paleontology_spec.rb +7 -0
  216. data/spec/legion/extensions/agentic/memory/paleontology/helpers/constants_spec.rb +33 -0
  217. data/spec/legion/extensions/agentic/memory/paleontology/helpers/excavation_spec.rb +71 -0
  218. data/spec/legion/extensions/agentic/memory/paleontology/helpers/fossil_spec.rb +134 -0
  219. data/spec/legion/extensions/agentic/memory/paleontology/helpers/paleontology_engine_spec.rb +148 -0
  220. data/spec/legion/extensions/agentic/memory/paleontology/runners/cognitive_paleontology_spec.rb +89 -0
  221. data/spec/legion/extensions/agentic/memory/palimpsest/client_spec.rb +58 -0
  222. data/spec/legion/extensions/agentic/memory/palimpsest/helpers/belief_layer_spec.rb +150 -0
  223. data/spec/legion/extensions/agentic/memory/palimpsest/helpers/constants_spec.rb +63 -0
  224. data/spec/legion/extensions/agentic/memory/palimpsest/helpers/palimpsest_engine_spec.rb +164 -0
  225. data/spec/legion/extensions/agentic/memory/palimpsest/helpers/palimpsest_spec.rb +172 -0
  226. data/spec/legion/extensions/agentic/memory/palimpsest/runners/cognitive_palimpsest_spec.rb +165 -0
  227. data/spec/legion/extensions/agentic/memory/reserve/client_spec.rb +37 -0
  228. data/spec/legion/extensions/agentic/memory/reserve/helpers/pathway_spec.rb +165 -0
  229. data/spec/legion/extensions/agentic/memory/reserve/helpers/reserve_engine_spec.rb +196 -0
  230. data/spec/legion/extensions/agentic/memory/reserve/runners/cognitive_reserve_spec.rb +96 -0
  231. data/spec/legion/extensions/agentic/memory/semantic/client_spec.rb +35 -0
  232. data/spec/legion/extensions/agentic/memory/semantic/helpers/concept_spec.rb +119 -0
  233. data/spec/legion/extensions/agentic/memory/semantic/helpers/knowledge_store_spec.rb +140 -0
  234. data/spec/legion/extensions/agentic/memory/semantic/runners/semantic_memory_spec.rb +103 -0
  235. data/spec/legion/extensions/agentic/memory/semantic_priming/helpers/connection_spec.rb +98 -0
  236. data/spec/legion/extensions/agentic/memory/semantic_priming/helpers/priming_network_spec.rb +208 -0
  237. data/spec/legion/extensions/agentic/memory/semantic_priming/helpers/semantic_node_spec.rb +125 -0
  238. data/spec/legion/extensions/agentic/memory/semantic_priming/semantic_priming_spec.rb +7 -0
  239. data/spec/legion/extensions/agentic/memory/semantic_satiation/client_spec.rb +19 -0
  240. data/spec/legion/extensions/agentic/memory/semantic_satiation/helpers/concept_spec.rb +167 -0
  241. data/spec/legion/extensions/agentic/memory/semantic_satiation/helpers/constants_spec.rb +81 -0
  242. data/spec/legion/extensions/agentic/memory/semantic_satiation/helpers/satiation_engine_spec.rb +189 -0
  243. data/spec/legion/extensions/agentic/memory/semantic_satiation/runners/semantic_satiation_spec.rb +176 -0
  244. data/spec/legion/extensions/agentic/memory/source_monitoring/client_spec.rb +25 -0
  245. data/spec/legion/extensions/agentic/memory/source_monitoring/helpers/source_record_spec.rb +152 -0
  246. data/spec/legion/extensions/agentic/memory/source_monitoring/helpers/source_tracker_spec.rb +139 -0
  247. data/spec/legion/extensions/agentic/memory/source_monitoring/runners/source_monitoring_spec.rb +102 -0
  248. data/spec/legion/extensions/agentic/memory/trace/actors/decay_spec.rb +62 -0
  249. data/spec/legion/extensions/agentic/memory/trace/actors/tier_migration_spec.rb +62 -0
  250. data/spec/legion/extensions/agentic/memory/trace/batch_decay_spec.rb +26 -0
  251. data/spec/legion/extensions/agentic/memory/trace/client_spec.rb +62 -0
  252. data/spec/legion/extensions/agentic/memory/trace/helpers/decay_spec.rb +134 -0
  253. data/spec/legion/extensions/agentic/memory/trace/helpers/store_spec.rb +217 -0
  254. data/spec/legion/extensions/agentic/memory/trace/helpers/trace_spec.rb +120 -0
  255. data/spec/legion/extensions/agentic/memory/trace/local_persistence_spec.rb +255 -0
  256. data/spec/legion/extensions/agentic/memory/trace/memory_spec.rb +11 -0
  257. data/spec/legion/extensions/agentic/memory/trace/persistent_store_spec.rb +50 -0
  258. data/spec/legion/extensions/agentic/memory/trace/quota_spec.rb +56 -0
  259. data/spec/legion/extensions/agentic/memory/trace/runners/consolidation_spec.rb +118 -0
  260. data/spec/legion/extensions/agentic/memory/trace/runners/traces_spec.rb +69 -0
  261. data/spec/legion/extensions/agentic/memory/transfer/client_spec.rb +18 -0
  262. data/spec/legion/extensions/agentic/memory/transfer/helpers/constants_spec.rb +41 -0
  263. data/spec/legion/extensions/agentic/memory/transfer/helpers/domain_knowledge_spec.rb +134 -0
  264. data/spec/legion/extensions/agentic/memory/transfer/helpers/transfer_engine_spec.rb +299 -0
  265. data/spec/legion/extensions/agentic/memory/transfer/runners/transfer_learning_spec.rb +144 -0
  266. data/spec/spec_helper.rb +46 -0
  267. metadata +351 -0
@@ -0,0 +1,266 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Memory::EchoChamber::Helpers::ChamberEngine do
4
+ subject(:engine) { described_class.new }
5
+
6
+ describe '#create_echo' do
7
+ it 'creates an echo with default parameters' do
8
+ echo = engine.create_echo(content: 'test belief')
9
+ expect(echo.content).to eq('test belief')
10
+ end
11
+
12
+ it 'creates an echo with custom echo_type' do
13
+ echo = engine.create_echo(content: 'test', echo_type: :bias)
14
+ expect(echo.echo_type).to eq(:bias)
15
+ end
16
+
17
+ it 'creates an echo with custom domain' do
18
+ echo = engine.create_echo(content: 'test', domain: :science)
19
+ expect(echo.domain).to eq(:science)
20
+ end
21
+
22
+ it 'creates an echo with custom source_agent' do
23
+ echo = engine.create_echo(content: 'test', source_agent: 'agent-1')
24
+ expect(echo.source_agent).to eq('agent-1')
25
+ end
26
+
27
+ it 'creates an echo with custom amplitude' do
28
+ echo = engine.create_echo(content: 'test', amplitude: 0.8)
29
+ expect(echo.amplitude).to eq(0.8)
30
+ end
31
+
32
+ it 'returns an Echo instance' do
33
+ echo = engine.create_echo(content: 'test')
34
+ expect(echo).to be_a(Legion::Extensions::Agentic::Memory::EchoChamber::Helpers::Echo)
35
+ end
36
+ end
37
+
38
+ describe '#create_chamber' do
39
+ it 'creates a chamber with label' do
40
+ chamber = engine.create_chamber(label: 'ideology chamber')
41
+ expect(chamber.label).to eq('ideology chamber')
42
+ end
43
+
44
+ it 'creates a chamber with custom domain' do
45
+ chamber = engine.create_chamber(label: 'x', domain: :politics)
46
+ expect(chamber.domain).to eq(:politics)
47
+ end
48
+
49
+ it 'creates a chamber with custom wall_thickness' do
50
+ chamber = engine.create_chamber(label: 'x', wall_thickness: 0.8)
51
+ expect(chamber.wall_thickness).to eq(0.8)
52
+ end
53
+
54
+ it 'returns a Chamber instance' do
55
+ chamber = engine.create_chamber(label: 'test')
56
+ expect(chamber).to be_a(Legion::Extensions::Agentic::Memory::EchoChamber::Helpers::Chamber)
57
+ end
58
+ end
59
+
60
+ describe '#amplify_echo' do
61
+ it 'increases echo amplitude' do
62
+ echo = engine.create_echo(content: 'test', amplitude: 0.5)
63
+ engine.amplify_echo(echo_id: echo.id)
64
+ expect(echo.amplitude).to be > 0.5
65
+ end
66
+
67
+ it 'returns nil for unknown echo_id' do
68
+ expect(engine.amplify_echo(echo_id: 'nonexistent')).to be_nil
69
+ end
70
+
71
+ it 'accepts custom rate' do
72
+ echo = engine.create_echo(content: 'test', amplitude: 0.5)
73
+ engine.amplify_echo(echo_id: echo.id, rate: 0.2)
74
+ expect(echo.amplitude).to be_within(0.001).of(0.7)
75
+ end
76
+ end
77
+
78
+ describe '#disrupt_chamber' do
79
+ let(:chamber) { engine.create_chamber(label: 'test', wall_thickness: 0.4) }
80
+
81
+ it 'returns error for unknown chamber_id' do
82
+ result = engine.disrupt_chamber(chamber_id: 'nonexistent', force: 0.9)
83
+ expect(result[:success]).to be false
84
+ expect(result[:error]).to eq('chamber not found')
85
+ end
86
+
87
+ it 'succeeds with sufficient force' do
88
+ result = engine.disrupt_chamber(chamber_id: chamber.id, force: 0.9)
89
+ expect(result[:success]).to be true
90
+ end
91
+
92
+ it 'fails with insufficient force' do
93
+ result = engine.disrupt_chamber(chamber_id: chamber.id, force: 0.2)
94
+ expect(result[:success]).to be false
95
+ end
96
+
97
+ it 'records disruption in history on success' do
98
+ engine.disrupt_chamber(chamber_id: chamber.id, force: 0.9)
99
+ expect(engine.disruption_history).not_to be_empty
100
+ end
101
+
102
+ it 'does not record failed disruption in history' do
103
+ engine.disrupt_chamber(chamber_id: chamber.id, force: 0.1)
104
+ expect(engine.disruption_history).to be_empty
105
+ end
106
+ end
107
+
108
+ describe '#decay_all!' do
109
+ it 'reduces amplitude of all echoes' do
110
+ echo = engine.create_echo(content: 'test', amplitude: 0.8)
111
+ original = echo.amplitude
112
+ engine.decay_all!
113
+ expect(echo.amplitude).to be < original
114
+ end
115
+
116
+ it 'returns a hash with decay stats' do
117
+ engine.create_echo(content: 'test')
118
+ result = engine.decay_all!
119
+ expect(result).to include(:decayed, :remaining, :pruned)
120
+ end
121
+
122
+ it 'prunes silent echoes after decay' do
123
+ engine.create_echo(content: 'faint', amplitude: 0.02)
124
+ engine.decay_all!
125
+ expect(engine.active_echoes).to be_empty
126
+ end
127
+ end
128
+
129
+ describe '#echoes_by_type' do
130
+ it 'filters echoes by type' do
131
+ engine.create_echo(content: 'a', echo_type: :bias)
132
+ engine.create_echo(content: 'b', echo_type: :conviction)
133
+ expect(engine.echoes_by_type(echo_type: :bias).size).to eq(1)
134
+ end
135
+
136
+ it 'returns empty array when no matching type' do
137
+ engine.create_echo(content: 'a', echo_type: :belief)
138
+ expect(engine.echoes_by_type(echo_type: :hypothesis)).to be_empty
139
+ end
140
+ end
141
+
142
+ describe '#loudest_echoes' do
143
+ it 'returns echoes sorted by amplitude descending' do
144
+ engine.create_echo(content: 'quiet', amplitude: 0.3)
145
+ loud = engine.create_echo(content: 'loud', amplitude: 0.9)
146
+ expect(engine.loudest_echoes(limit: 1).first.id).to eq(loud.id)
147
+ end
148
+
149
+ it 'respects limit parameter' do
150
+ 3.times { |i| engine.create_echo(content: "echo #{i}") }
151
+ expect(engine.loudest_echoes(limit: 2).size).to eq(2)
152
+ end
153
+ end
154
+
155
+ describe '#most_sealed_chambers' do
156
+ it 'returns chambers sorted by wall_thickness descending' do
157
+ engine.create_chamber(label: 'thin', wall_thickness: 0.2)
158
+ thick = engine.create_chamber(label: 'thick', wall_thickness: 0.9)
159
+ expect(engine.most_sealed_chambers(limit: 1).first.id).to eq(thick.id)
160
+ end
161
+
162
+ it 'respects limit parameter' do
163
+ 3.times { |i| engine.create_chamber(label: "chamber #{i}") }
164
+ expect(engine.most_sealed_chambers(limit: 2).size).to eq(2)
165
+ end
166
+ end
167
+
168
+ describe '#disruption_history' do
169
+ it 'returns empty initially' do
170
+ expect(engine.disruption_history).to be_empty
171
+ end
172
+
173
+ it 'returns a copy, not the internal array' do
174
+ chamber = engine.create_chamber(label: 'test', wall_thickness: 0.2)
175
+ engine.disrupt_chamber(chamber_id: chamber.id, force: 0.9)
176
+ history = engine.disruption_history
177
+ expect(history).not_to equal(engine.disruption_history)
178
+ end
179
+ end
180
+
181
+ describe '#add_echo_to_chamber' do
182
+ it 'adds echo to chamber successfully' do
183
+ echo = engine.create_echo(content: 'test')
184
+ chamber = engine.create_chamber(label: 'test chamber')
185
+ result = engine.add_echo_to_chamber(echo_id: echo.id, chamber_id: chamber.id)
186
+ expect(result[:success]).to be true
187
+ end
188
+
189
+ it 'returns error for unknown echo' do
190
+ chamber = engine.create_chamber(label: 'test')
191
+ result = engine.add_echo_to_chamber(echo_id: 'bad', chamber_id: chamber.id)
192
+ expect(result[:error]).to eq('echo not found')
193
+ end
194
+
195
+ it 'returns error for unknown chamber' do
196
+ echo = engine.create_echo(content: 'test')
197
+ result = engine.add_echo_to_chamber(echo_id: echo.id, chamber_id: 'bad')
198
+ expect(result[:error]).to eq('chamber not found')
199
+ end
200
+ end
201
+
202
+ describe '#active_echoes' do
203
+ it 'returns non-silent echoes' do
204
+ engine.create_echo(content: 'active', amplitude: 0.5)
205
+ engine.create_echo(content: 'silent', amplitude: 0.01)
206
+ expect(engine.active_echoes.size).to eq(1)
207
+ end
208
+ end
209
+
210
+ describe '#resonating_echoes' do
211
+ it 'returns echoes above disruption threshold' do
212
+ engine.create_echo(content: 'resonating', amplitude: 0.8)
213
+ engine.create_echo(content: 'quiet', amplitude: 0.3)
214
+ expect(engine.resonating_echoes.size).to eq(1)
215
+ end
216
+ end
217
+
218
+ describe '#echo_report' do
219
+ it 'includes expected keys' do
220
+ report = engine.echo_report
221
+ expect(report).to include(
222
+ :total_echoes, :active_echoes, :resonating_echoes,
223
+ :total_chambers, :sealed_chambers, :porous_chambers,
224
+ :disruption_count, :loudest
225
+ )
226
+ end
227
+
228
+ it 'counts sealed chambers correctly' do
229
+ engine.create_chamber(label: 'sealed', wall_thickness: 0.9)
230
+ engine.create_chamber(label: 'open', wall_thickness: 0.2)
231
+ expect(engine.echo_report[:sealed_chambers]).to eq(1)
232
+ end
233
+
234
+ it 'counts porous chambers correctly' do
235
+ engine.create_chamber(label: 'porous', wall_thickness: 0.1)
236
+ expect(engine.echo_report[:porous_chambers]).to eq(1)
237
+ end
238
+
239
+ it 'includes loudest echoes array' do
240
+ engine.create_echo(content: 'loud', amplitude: 0.9)
241
+ expect(engine.echo_report[:loudest]).not_to be_empty
242
+ end
243
+ end
244
+
245
+ describe '#echo_by_id' do
246
+ it 'returns the echo if found' do
247
+ echo = engine.create_echo(content: 'find me')
248
+ expect(engine.echo_by_id(echo.id)).to eq(echo)
249
+ end
250
+
251
+ it 'returns nil if not found' do
252
+ expect(engine.echo_by_id('missing')).to be_nil
253
+ end
254
+ end
255
+
256
+ describe '#chamber_by_id' do
257
+ it 'returns the chamber if found' do
258
+ chamber = engine.create_chamber(label: 'find me')
259
+ expect(engine.chamber_by_id(chamber.id)).to eq(chamber)
260
+ end
261
+
262
+ it 'returns nil if not found' do
263
+ expect(engine.chamber_by_id('missing')).to be_nil
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,249 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Memory::EchoChamber::Helpers::Chamber do
4
+ subject(:chamber) { described_class.new(label: 'political beliefs', domain: :politics) }
5
+
6
+ let(:echo) do
7
+ Legion::Extensions::Agentic::Memory::EchoChamber::Helpers::Echo.new(
8
+ content: 'my side is always right',
9
+ domain: :politics
10
+ )
11
+ end
12
+
13
+ let(:strong_echo) do
14
+ Legion::Extensions::Agentic::Memory::EchoChamber::Helpers::Echo.new(
15
+ content: 'opponents are always wrong',
16
+ domain: :politics,
17
+ amplitude: 0.9
18
+ )
19
+ end
20
+
21
+ describe '#initialize' do
22
+ it 'assigns a UUID id' do
23
+ expect(chamber.id).to match(/\A[0-9a-f-]{36}\z/)
24
+ end
25
+
26
+ it 'stores label' do
27
+ expect(chamber.label).to eq('political beliefs')
28
+ end
29
+
30
+ it 'stores domain' do
31
+ expect(chamber.domain).to eq(:politics)
32
+ end
33
+
34
+ it 'initializes state as :forming' do
35
+ expect(chamber.state).to eq(:forming)
36
+ end
37
+
38
+ it 'defaults wall_thickness to 0.5' do
39
+ expect(chamber.wall_thickness).to eq(0.5)
40
+ end
41
+
42
+ it 'initializes resonance_frequency to 0.0' do
43
+ expect(chamber.resonance_frequency).to eq(0.0)
44
+ end
45
+
46
+ it 'initializes disruption_count to 0' do
47
+ expect(chamber.disruption_count).to eq(0)
48
+ end
49
+
50
+ it 'records created_at' do
51
+ expect(chamber.created_at).to be_a(Time)
52
+ end
53
+
54
+ it 'clamps wall_thickness above 1.0' do
55
+ thick = described_class.new(label: 'x', wall_thickness: 2.0)
56
+ expect(thick.wall_thickness).to eq(1.0)
57
+ end
58
+
59
+ it 'clamps wall_thickness below 0.0' do
60
+ thin = described_class.new(label: 'x', wall_thickness: -1.0)
61
+ expect(thin.wall_thickness).to eq(0.0)
62
+ end
63
+ end
64
+
65
+ describe '#add_echo' do
66
+ it 'returns true on success' do
67
+ expect(chamber.add_echo(echo)).to be true
68
+ end
69
+
70
+ it 'increases echo_count' do
71
+ chamber.add_echo(echo)
72
+ expect(chamber.echo_count).to eq(1)
73
+ end
74
+
75
+ it 'updates resonance_frequency' do
76
+ chamber.add_echo(strong_echo)
77
+ expect(chamber.resonance_frequency).to be > 0.0
78
+ end
79
+ end
80
+
81
+ describe '#remove_echo' do
82
+ before { chamber.add_echo(echo) }
83
+
84
+ it 'returns true when echo exists' do
85
+ expect(chamber.remove_echo(echo.id)).to be true
86
+ end
87
+
88
+ it 'decreases echo_count' do
89
+ chamber.remove_echo(echo.id)
90
+ expect(chamber.echo_count).to eq(0)
91
+ end
92
+
93
+ it 'returns false when echo does not exist' do
94
+ expect(chamber.remove_echo('nonexistent-id')).to be false
95
+ end
96
+ end
97
+
98
+ describe '#amplify_all!' do
99
+ before do
100
+ chamber.add_echo(echo)
101
+ chamber.add_echo(strong_echo)
102
+ end
103
+
104
+ it 'returns a hash with amplified count' do
105
+ result = chamber.amplify_all!
106
+ expect(result[:amplified]).to eq(2)
107
+ end
108
+
109
+ it 'returns updated resonance_frequency' do
110
+ result = chamber.amplify_all!
111
+ expect(result[:resonance_frequency]).to be_a(Float)
112
+ end
113
+
114
+ it 'increases amplitudes of echoes' do
115
+ original = echo.amplitude
116
+ chamber.amplify_all!
117
+ expect(echo.amplitude).to be > original
118
+ end
119
+ end
120
+
121
+ describe '#disrupt!' do
122
+ context 'with insufficient force' do
123
+ it 'returns success: false' do
124
+ result = chamber.disrupt!(0.3)
125
+ expect(result[:success]).to be false
126
+ end
127
+
128
+ it 'includes reason in result' do
129
+ result = chamber.disrupt!(0.3)
130
+ expect(result[:reason]).to eq('insufficient_force')
131
+ end
132
+ end
133
+
134
+ context 'with sufficient force' do
135
+ subject(:thick_chamber) { described_class.new(label: 'ideology', wall_thickness: 0.4) }
136
+
137
+ before { thick_chamber.add_echo(strong_echo) }
138
+
139
+ it 'returns success: true' do
140
+ result = thick_chamber.disrupt!(0.9)
141
+ expect(result[:success]).to be true
142
+ end
143
+
144
+ it 'includes breakthrough value' do
145
+ result = thick_chamber.disrupt!(0.9)
146
+ expect(result[:breakthrough]).to be > 0.0
147
+ end
148
+
149
+ it 'reduces wall_thickness' do
150
+ original = thick_chamber.wall_thickness
151
+ thick_chamber.disrupt!(0.9)
152
+ expect(thick_chamber.wall_thickness).to be < original
153
+ end
154
+
155
+ it 'increments disruption_count' do
156
+ thick_chamber.disrupt!(0.9)
157
+ expect(thick_chamber.disruption_count).to eq(1)
158
+ end
159
+
160
+ it 'transitions state to :disrupted' do
161
+ thick_chamber.disrupt!(0.9)
162
+ expect(thick_chamber.state).to eq(:disrupted)
163
+ end
164
+
165
+ it 'dampens echoes in the chamber' do
166
+ original = strong_echo.amplitude
167
+ thick_chamber.disrupt!(0.9)
168
+ expect(strong_echo.amplitude).to be < original
169
+ end
170
+ end
171
+ end
172
+
173
+ describe '#sealed?' do
174
+ it 'is false at default wall_thickness (0.5)' do
175
+ expect(chamber.sealed?).to be false
176
+ end
177
+
178
+ it 'is true when wall_thickness >= 0.8' do
179
+ thick = described_class.new(label: 'x', wall_thickness: 0.85)
180
+ expect(thick.sealed?).to be true
181
+ end
182
+ end
183
+
184
+ describe '#porous?' do
185
+ it 'is false at default wall_thickness (0.5)' do
186
+ expect(chamber.porous?).to be false
187
+ end
188
+
189
+ it 'is true when wall_thickness <= 0.3' do
190
+ thin = described_class.new(label: 'x', wall_thickness: 0.2)
191
+ expect(thin.porous?).to be true
192
+ end
193
+ end
194
+
195
+ describe '#resonance_level' do
196
+ it 'returns :silent with no echoes' do
197
+ expect(chamber.resonance_level).to eq(:silent)
198
+ end
199
+
200
+ it 'returns a symbol after adding resonating echoes' do
201
+ resonating = Legion::Extensions::Agentic::Memory::EchoChamber::Helpers::Echo.new(
202
+ content: 'strong belief',
203
+ amplitude: 0.9
204
+ )
205
+ chamber.add_echo(resonating)
206
+ expect(chamber.resonance_level).to be_a(Symbol)
207
+ end
208
+ end
209
+
210
+ describe '#active_echoes' do
211
+ it 'returns empty array initially' do
212
+ expect(chamber.active_echoes).to be_empty
213
+ end
214
+
215
+ it 'returns echoes that are not silent' do
216
+ chamber.add_echo(echo)
217
+ expect(chamber.active_echoes.size).to eq(1)
218
+ end
219
+ end
220
+
221
+ describe '#resonating_echoes' do
222
+ it 'returns empty when no high-amplitude echoes' do
223
+ chamber.add_echo(echo)
224
+ expect(chamber.resonating_echoes).to be_empty
225
+ end
226
+
227
+ it 'returns echoes above disruption threshold' do
228
+ chamber.add_echo(strong_echo)
229
+ expect(chamber.resonating_echoes.size).to eq(1)
230
+ end
231
+ end
232
+
233
+ describe '#to_h' do
234
+ let(:hash) { chamber.to_h }
235
+
236
+ it 'includes all expected keys' do
237
+ expect(hash).to include(
238
+ :id, :label, :domain, :state, :wall_thickness,
239
+ :resonance_frequency, :resonance_level, :sealed, :porous,
240
+ :echo_count, :active_echo_count, :disruption_count, :created_at
241
+ )
242
+ end
243
+
244
+ it 'reflects current echo_count' do
245
+ chamber.add_echo(echo)
246
+ expect(chamber.to_h[:echo_count]).to eq(1)
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Memory::EchoChamber::Helpers::Constants do
4
+ describe 'numeric constants' do
5
+ it 'defines MAX_ECHOES as 500' do
6
+ expect(described_class::MAX_ECHOES).to eq(500)
7
+ end
8
+
9
+ it 'defines MAX_CHAMBERS as 50' do
10
+ expect(described_class::MAX_CHAMBERS).to eq(50)
11
+ end
12
+
13
+ it 'defines AMPLIFICATION_RATE as 0.1' do
14
+ expect(described_class::AMPLIFICATION_RATE).to eq(0.1)
15
+ end
16
+
17
+ it 'defines DECAY_RATE as 0.02' do
18
+ expect(described_class::DECAY_RATE).to eq(0.02)
19
+ end
20
+
21
+ it 'defines DISRUPTION_THRESHOLD as 0.7' do
22
+ expect(described_class::DISRUPTION_THRESHOLD).to eq(0.7)
23
+ end
24
+
25
+ it 'defines SEALED_THRESHOLD as 0.8' do
26
+ expect(described_class::SEALED_THRESHOLD).to eq(0.8)
27
+ end
28
+
29
+ it 'defines POROUS_THRESHOLD as 0.3' do
30
+ expect(described_class::POROUS_THRESHOLD).to eq(0.3)
31
+ end
32
+ end
33
+
34
+ describe 'ECHO_TYPES' do
35
+ it 'contains belief' do
36
+ expect(described_class::ECHO_TYPES).to include(:belief)
37
+ end
38
+
39
+ it 'contains assumption' do
40
+ expect(described_class::ECHO_TYPES).to include(:assumption)
41
+ end
42
+
43
+ it 'contains bias' do
44
+ expect(described_class::ECHO_TYPES).to include(:bias)
45
+ end
46
+
47
+ it 'contains hypothesis' do
48
+ expect(described_class::ECHO_TYPES).to include(:hypothesis)
49
+ end
50
+
51
+ it 'contains conviction' do
52
+ expect(described_class::ECHO_TYPES).to include(:conviction)
53
+ end
54
+
55
+ it 'is frozen' do
56
+ expect(described_class::ECHO_TYPES).to be_frozen
57
+ end
58
+ end
59
+
60
+ describe 'CHAMBER_STATES' do
61
+ it 'contains all expected states' do
62
+ expect(described_class::CHAMBER_STATES).to contain_exactly(
63
+ :forming, :resonating, :saturated, :disrupted, :collapsed
64
+ )
65
+ end
66
+
67
+ it 'is frozen' do
68
+ expect(described_class::CHAMBER_STATES).to be_frozen
69
+ end
70
+ end
71
+
72
+ describe 'RESONANCE_LABELS' do
73
+ it 'maps high values to :thunderous' do
74
+ expect(described_class::RESONANCE_LABELS.find { |r, _| r.cover?(0.9) }&.last).to eq(:thunderous)
75
+ end
76
+
77
+ it 'maps mid values to :humming' do
78
+ expect(described_class::RESONANCE_LABELS.find { |r, _| r.cover?(0.5) }&.last).to eq(:humming)
79
+ end
80
+
81
+ it 'maps low values to :silent' do
82
+ expect(described_class::RESONANCE_LABELS.find { |r, _| r.cover?(0.1) }&.last).to eq(:silent)
83
+ end
84
+
85
+ it 'is frozen' do
86
+ expect(described_class::RESONANCE_LABELS).to be_frozen
87
+ end
88
+ end
89
+
90
+ describe 'AMPLIFICATION_LABELS' do
91
+ it 'maps high values to :deafening' do
92
+ expect(described_class::AMPLIFICATION_LABELS.find { |r, _| r.cover?(0.9) }&.last).to eq(:deafening)
93
+ end
94
+
95
+ it 'maps mid values to :moderate' do
96
+ expect(described_class::AMPLIFICATION_LABELS.find { |r, _| r.cover?(0.5) }&.last).to eq(:moderate)
97
+ end
98
+
99
+ it 'maps low values to :muted' do
100
+ expect(described_class::AMPLIFICATION_LABELS.find { |r, _| r.cover?(0.1) }&.last).to eq(:muted)
101
+ end
102
+ end
103
+
104
+ describe '.label_for' do
105
+ it 'returns the correct label for a value in range' do
106
+ label = described_class.label_for(described_class::RESONANCE_LABELS, 0.9)
107
+ expect(label).to eq(:thunderous)
108
+ end
109
+
110
+ it 'returns label for boundary value' do
111
+ label = described_class.label_for(described_class::RESONANCE_LABELS, 0.8)
112
+ expect(label).to eq(:thunderous)
113
+ end
114
+
115
+ it 'returns :silent for very low values' do
116
+ label = described_class.label_for(described_class::RESONANCE_LABELS, 0.1)
117
+ expect(label).to eq(:silent)
118
+ end
119
+
120
+ it 'returns nil for no match' do
121
+ label = described_class.label_for({}, 0.5)
122
+ expect(label).to be_nil
123
+ end
124
+
125
+ it 'works with AMPLIFICATION_LABELS' do
126
+ label = described_class.label_for(described_class::AMPLIFICATION_LABELS, 0.75)
127
+ expect(label).to eq(:loud)
128
+ end
129
+ end
130
+ end