lex-agentic-integration 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 (236) 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-integration.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/integration/boundary/client.rb +15 -0
  8. data/lib/legion/extensions/agentic/integration/boundary/helpers/boundary.rb +90 -0
  9. data/lib/legion/extensions/agentic/integration/boundary/helpers/boundary_engine.rb +123 -0
  10. data/lib/legion/extensions/agentic/integration/boundary/helpers/constants.rb +44 -0
  11. data/lib/legion/extensions/agentic/integration/boundary/runners/cognitive_boundary.rb +100 -0
  12. data/lib/legion/extensions/agentic/integration/boundary/version.rb +13 -0
  13. data/lib/legion/extensions/agentic/integration/boundary.rb +19 -0
  14. data/lib/legion/extensions/agentic/integration/context/client.rb +26 -0
  15. data/lib/legion/extensions/agentic/integration/context/helpers/constants.rb +34 -0
  16. data/lib/legion/extensions/agentic/integration/context/helpers/context_manager.rb +150 -0
  17. data/lib/legion/extensions/agentic/integration/context/helpers/frame.rb +99 -0
  18. data/lib/legion/extensions/agentic/integration/context/runners/context.rb +94 -0
  19. data/lib/legion/extensions/agentic/integration/context/version.rb +13 -0
  20. data/lib/legion/extensions/agentic/integration/context.rb +19 -0
  21. data/lib/legion/extensions/agentic/integration/distributed_cognition/client.rb +19 -0
  22. data/lib/legion/extensions/agentic/integration/distributed_cognition/helpers/constants.rb +51 -0
  23. data/lib/legion/extensions/agentic/integration/distributed_cognition/helpers/distribution_engine.rb +159 -0
  24. data/lib/legion/extensions/agentic/integration/distributed_cognition/helpers/participant.rb +100 -0
  25. data/lib/legion/extensions/agentic/integration/distributed_cognition/runners/distributed_cognition.rb +107 -0
  26. data/lib/legion/extensions/agentic/integration/distributed_cognition/version.rb +13 -0
  27. data/lib/legion/extensions/agentic/integration/distributed_cognition.rb +19 -0
  28. data/lib/legion/extensions/agentic/integration/gestalt/client.rb +21 -0
  29. data/lib/legion/extensions/agentic/integration/gestalt/helpers/constants.rb +51 -0
  30. data/lib/legion/extensions/agentic/integration/gestalt/helpers/pattern.rb +90 -0
  31. data/lib/legion/extensions/agentic/integration/gestalt/helpers/pattern_store.rb +123 -0
  32. data/lib/legion/extensions/agentic/integration/gestalt/runners/gestalt.rb +82 -0
  33. data/lib/legion/extensions/agentic/integration/gestalt/version.rb +13 -0
  34. data/lib/legion/extensions/agentic/integration/gestalt.rb +19 -0
  35. data/lib/legion/extensions/agentic/integration/global_workspace/actors/competition.rb +45 -0
  36. data/lib/legion/extensions/agentic/integration/global_workspace/client.rb +29 -0
  37. data/lib/legion/extensions/agentic/integration/global_workspace/helpers/broadcast.rb +62 -0
  38. data/lib/legion/extensions/agentic/integration/global_workspace/helpers/competitor.rb +59 -0
  39. data/lib/legion/extensions/agentic/integration/global_workspace/helpers/constants.rb +65 -0
  40. data/lib/legion/extensions/agentic/integration/global_workspace/helpers/workspace.rb +188 -0
  41. data/lib/legion/extensions/agentic/integration/global_workspace/runners/global_workspace.rb +104 -0
  42. data/lib/legion/extensions/agentic/integration/global_workspace/version.rb +13 -0
  43. data/lib/legion/extensions/agentic/integration/global_workspace.rb +20 -0
  44. data/lib/legion/extensions/agentic/integration/integration/client.rb +19 -0
  45. data/lib/legion/extensions/agentic/integration/integration/helpers/constants.rb +62 -0
  46. data/lib/legion/extensions/agentic/integration/integration/helpers/integrated_representation.rb +106 -0
  47. data/lib/legion/extensions/agentic/integration/integration/helpers/integration_engine.rb +163 -0
  48. data/lib/legion/extensions/agentic/integration/integration/helpers/modal_signal.rb +62 -0
  49. data/lib/legion/extensions/agentic/integration/integration/runners/cognitive_integration.rb +105 -0
  50. data/lib/legion/extensions/agentic/integration/integration/version.rb +13 -0
  51. data/lib/legion/extensions/agentic/integration/integration.rb +20 -0
  52. data/lib/legion/extensions/agentic/integration/labyrinth/actors/thread_walker.rb +45 -0
  53. data/lib/legion/extensions/agentic/integration/labyrinth/client.rb +23 -0
  54. data/lib/legion/extensions/agentic/integration/labyrinth/helpers/constants.rb +39 -0
  55. data/lib/legion/extensions/agentic/integration/labyrinth/helpers/labyrinth.rb +138 -0
  56. data/lib/legion/extensions/agentic/integration/labyrinth/helpers/labyrinth_engine.rb +177 -0
  57. data/lib/legion/extensions/agentic/integration/labyrinth/helpers/node.rb +64 -0
  58. data/lib/legion/extensions/agentic/integration/labyrinth/runners/cognitive_labyrinth.rb +128 -0
  59. data/lib/legion/extensions/agentic/integration/labyrinth/version.rb +13 -0
  60. data/lib/legion/extensions/agentic/integration/labyrinth.rb +22 -0
  61. data/lib/legion/extensions/agentic/integration/map/actors/decay.rb +45 -0
  62. data/lib/legion/extensions/agentic/integration/map/client.rb +29 -0
  63. data/lib/legion/extensions/agentic/integration/map/helpers/cognitive_map_store.rb +179 -0
  64. data/lib/legion/extensions/agentic/integration/map/helpers/constants.rb +71 -0
  65. data/lib/legion/extensions/agentic/integration/map/helpers/graph_traversal.rb +124 -0
  66. data/lib/legion/extensions/agentic/integration/map/helpers/location.rb +71 -0
  67. data/lib/legion/extensions/agentic/integration/map/runners/cognitive_map.rb +95 -0
  68. data/lib/legion/extensions/agentic/integration/map/version.rb +13 -0
  69. data/lib/legion/extensions/agentic/integration/map.rb +20 -0
  70. data/lib/legion/extensions/agentic/integration/mosaic/client.rb +15 -0
  71. data/lib/legion/extensions/agentic/integration/mosaic/helpers/constants.rb +55 -0
  72. data/lib/legion/extensions/agentic/integration/mosaic/helpers/mosaic.rb +111 -0
  73. data/lib/legion/extensions/agentic/integration/mosaic/helpers/mosaic_engine.rb +124 -0
  74. data/lib/legion/extensions/agentic/integration/mosaic/helpers/tessera.rb +86 -0
  75. data/lib/legion/extensions/agentic/integration/mosaic/runners/cognitive_mosaic.rb +76 -0
  76. data/lib/legion/extensions/agentic/integration/mosaic/version.rb +13 -0
  77. data/lib/legion/extensions/agentic/integration/mosaic.rb +22 -0
  78. data/lib/legion/extensions/agentic/integration/mycelium/client.rb +19 -0
  79. data/lib/legion/extensions/agentic/integration/mycelium/helpers/constants.rb +52 -0
  80. data/lib/legion/extensions/agentic/integration/mycelium/helpers/fruiting_body.rb +50 -0
  81. data/lib/legion/extensions/agentic/integration/mycelium/helpers/hypha.rb +76 -0
  82. data/lib/legion/extensions/agentic/integration/mycelium/helpers/mycelial_node.rb +72 -0
  83. data/lib/legion/extensions/agentic/integration/mycelium/helpers/mycelium_engine.rb +151 -0
  84. data/lib/legion/extensions/agentic/integration/mycelium/runners/cognitive_mycelium.rb +73 -0
  85. data/lib/legion/extensions/agentic/integration/mycelium/version.rb +13 -0
  86. data/lib/legion/extensions/agentic/integration/mycelium.rb +23 -0
  87. data/lib/legion/extensions/agentic/integration/phenomenal_binding/client.rb +25 -0
  88. data/lib/legion/extensions/agentic/integration/phenomenal_binding/helpers/binding_engine.rb +156 -0
  89. data/lib/legion/extensions/agentic/integration/phenomenal_binding/helpers/binding_unit.rb +72 -0
  90. data/lib/legion/extensions/agentic/integration/phenomenal_binding/helpers/constants.rb +35 -0
  91. data/lib/legion/extensions/agentic/integration/phenomenal_binding/helpers/stream.rb +51 -0
  92. data/lib/legion/extensions/agentic/integration/phenomenal_binding/runners/phenomenal_binding.rb +110 -0
  93. data/lib/legion/extensions/agentic/integration/phenomenal_binding/version.rb +13 -0
  94. data/lib/legion/extensions/agentic/integration/phenomenal_binding.rb +20 -0
  95. data/lib/legion/extensions/agentic/integration/qualia/client.rb +19 -0
  96. data/lib/legion/extensions/agentic/integration/qualia/helpers/constants.rb +74 -0
  97. data/lib/legion/extensions/agentic/integration/qualia/helpers/quale.rb +103 -0
  98. data/lib/legion/extensions/agentic/integration/qualia/helpers/qualia_engine.rb +142 -0
  99. data/lib/legion/extensions/agentic/integration/qualia/runners/qualia.rb +67 -0
  100. data/lib/legion/extensions/agentic/integration/qualia/version.rb +13 -0
  101. data/lib/legion/extensions/agentic/integration/qualia.rb +19 -0
  102. data/lib/legion/extensions/agentic/integration/situation_model/client.rb +28 -0
  103. data/lib/legion/extensions/agentic/integration/situation_model/helpers/client.rb +23 -0
  104. data/lib/legion/extensions/agentic/integration/situation_model/helpers/constants.rb +40 -0
  105. data/lib/legion/extensions/agentic/integration/situation_model/helpers/situation_engine.rb +73 -0
  106. data/lib/legion/extensions/agentic/integration/situation_model/helpers/situation_event.rb +56 -0
  107. data/lib/legion/extensions/agentic/integration/situation_model/helpers/situation_model.rb +90 -0
  108. data/lib/legion/extensions/agentic/integration/situation_model/runners/situation_model.rb +99 -0
  109. data/lib/legion/extensions/agentic/integration/situation_model/version.rb +13 -0
  110. data/lib/legion/extensions/agentic/integration/situation_model.rb +21 -0
  111. data/lib/legion/extensions/agentic/integration/synthesis/client.rb +29 -0
  112. data/lib/legion/extensions/agentic/integration/synthesis/helpers/constants.rb +41 -0
  113. data/lib/legion/extensions/agentic/integration/synthesis/helpers/synthesis.rb +63 -0
  114. data/lib/legion/extensions/agentic/integration/synthesis/helpers/synthesis_engine.rb +213 -0
  115. data/lib/legion/extensions/agentic/integration/synthesis/helpers/synthesis_stream.rb +67 -0
  116. data/lib/legion/extensions/agentic/integration/synthesis/runners/cognitive_synthesis.rb +82 -0
  117. data/lib/legion/extensions/agentic/integration/synthesis/version.rb +13 -0
  118. data/lib/legion/extensions/agentic/integration/synthesis.rb +20 -0
  119. data/lib/legion/extensions/agentic/integration/tapestry/client.rb +15 -0
  120. data/lib/legion/extensions/agentic/integration/tapestry/helpers/constants.rb +46 -0
  121. data/lib/legion/extensions/agentic/integration/tapestry/helpers/loom_engine.rb +125 -0
  122. data/lib/legion/extensions/agentic/integration/tapestry/helpers/tapestry.rb +144 -0
  123. data/lib/legion/extensions/agentic/integration/tapestry/helpers/thread.rb +112 -0
  124. data/lib/legion/extensions/agentic/integration/tapestry/runners/cognitive_tapestry.rb +81 -0
  125. data/lib/legion/extensions/agentic/integration/tapestry/version.rb +13 -0
  126. data/lib/legion/extensions/agentic/integration/tapestry.rb +22 -0
  127. data/lib/legion/extensions/agentic/integration/tessellation/client.rb +19 -0
  128. data/lib/legion/extensions/agentic/integration/tessellation/helpers/constants.rb +72 -0
  129. data/lib/legion/extensions/agentic/integration/tessellation/helpers/mosaic.rb +99 -0
  130. data/lib/legion/extensions/agentic/integration/tessellation/helpers/tessellation_engine.rb +141 -0
  131. data/lib/legion/extensions/agentic/integration/tessellation/helpers/tile.rb +76 -0
  132. data/lib/legion/extensions/agentic/integration/tessellation/runners/cognitive_tessellation.rb +58 -0
  133. data/lib/legion/extensions/agentic/integration/tessellation/version.rb +13 -0
  134. data/lib/legion/extensions/agentic/integration/tessellation.rb +22 -0
  135. data/lib/legion/extensions/agentic/integration/version.rb +11 -0
  136. data/lib/legion/extensions/agentic/integration/zeitgeist/helpers/client.rb +17 -0
  137. data/lib/legion/extensions/agentic/integration/zeitgeist/helpers/cognitive_signal.rb +38 -0
  138. data/lib/legion/extensions/agentic/integration/zeitgeist/helpers/constants.rb +64 -0
  139. data/lib/legion/extensions/agentic/integration/zeitgeist/helpers/trend_window.rb +80 -0
  140. data/lib/legion/extensions/agentic/integration/zeitgeist/helpers/zeitgeist_engine.rb +157 -0
  141. data/lib/legion/extensions/agentic/integration/zeitgeist/runners/cognitive_zeitgeist.rb +99 -0
  142. data/lib/legion/extensions/agentic/integration/zeitgeist/version.rb +13 -0
  143. data/lib/legion/extensions/agentic/integration/zeitgeist.rb +22 -0
  144. data/lib/legion/extensions/agentic/integration.rb +34 -0
  145. data/spec/legion/extensions/agentic/integration/boundary/helpers/boundary_engine_spec.rb +165 -0
  146. data/spec/legion/extensions/agentic/integration/boundary/helpers/boundary_spec.rb +168 -0
  147. data/spec/legion/extensions/agentic/integration/boundary/helpers/constants_spec.rb +65 -0
  148. data/spec/legion/extensions/agentic/integration/boundary/runners/cognitive_boundary_spec.rb +111 -0
  149. data/spec/legion/extensions/agentic/integration/context/client_spec.rb +58 -0
  150. data/spec/legion/extensions/agentic/integration/context/helpers/constants_spec.rb +32 -0
  151. data/spec/legion/extensions/agentic/integration/context/helpers/context_manager_spec.rb +190 -0
  152. data/spec/legion/extensions/agentic/integration/context/helpers/frame_spec.rb +164 -0
  153. data/spec/legion/extensions/agentic/integration/context/runners/context_spec.rb +142 -0
  154. data/spec/legion/extensions/agentic/integration/distributed_cognition/client_spec.rb +21 -0
  155. data/spec/legion/extensions/agentic/integration/distributed_cognition/helpers/distribution_engine_spec.rb +149 -0
  156. data/spec/legion/extensions/agentic/integration/distributed_cognition/helpers/participant_spec.rb +116 -0
  157. data/spec/legion/extensions/agentic/integration/distributed_cognition/runners/distributed_cognition_spec.rb +102 -0
  158. data/spec/legion/extensions/agentic/integration/gestalt/client_spec.rb +53 -0
  159. data/spec/legion/extensions/agentic/integration/gestalt/helpers/constants_spec.rb +27 -0
  160. data/spec/legion/extensions/agentic/integration/gestalt/helpers/pattern_spec.rb +128 -0
  161. data/spec/legion/extensions/agentic/integration/gestalt/helpers/pattern_store_spec.rb +155 -0
  162. data/spec/legion/extensions/agentic/integration/gestalt/runners/gestalt_spec.rb +114 -0
  163. data/spec/legion/extensions/agentic/integration/global_workspace/client_spec.rb +49 -0
  164. data/spec/legion/extensions/agentic/integration/global_workspace/helpers/broadcast_spec.rb +83 -0
  165. data/spec/legion/extensions/agentic/integration/global_workspace/helpers/competitor_spec.rb +84 -0
  166. data/spec/legion/extensions/agentic/integration/global_workspace/helpers/workspace_spec.rb +174 -0
  167. data/spec/legion/extensions/agentic/integration/global_workspace/runners/global_workspace_spec.rb +118 -0
  168. data/spec/legion/extensions/agentic/integration/integration/cognitive_integration_spec.rb +7 -0
  169. data/spec/legion/extensions/agentic/integration/integration/helpers/integrated_representation_spec.rb +149 -0
  170. data/spec/legion/extensions/agentic/integration/integration/helpers/integration_engine_spec.rb +191 -0
  171. data/spec/legion/extensions/agentic/integration/integration/helpers/modal_signal_spec.rb +81 -0
  172. data/spec/legion/extensions/agentic/integration/labyrinth/client_spec.rb +122 -0
  173. data/spec/legion/extensions/agentic/integration/labyrinth/cognitive_labyrinth_spec.rb +19 -0
  174. data/spec/legion/extensions/agentic/integration/labyrinth/helpers/constants_spec.rb +72 -0
  175. data/spec/legion/extensions/agentic/integration/labyrinth/helpers/labyrinth_engine_spec.rb +222 -0
  176. data/spec/legion/extensions/agentic/integration/labyrinth/helpers/labyrinth_spec.rb +235 -0
  177. data/spec/legion/extensions/agentic/integration/labyrinth/helpers/node_spec.rb +157 -0
  178. data/spec/legion/extensions/agentic/integration/labyrinth/runners/cognitive_labyrinth_spec.rb +209 -0
  179. data/spec/legion/extensions/agentic/integration/map/client_spec.rb +89 -0
  180. data/spec/legion/extensions/agentic/integration/map/helpers/cognitive_map_store_spec.rb +321 -0
  181. data/spec/legion/extensions/agentic/integration/map/helpers/location_spec.rb +165 -0
  182. data/spec/legion/extensions/agentic/integration/map/runners/cognitive_map_spec.rb +190 -0
  183. data/spec/legion/extensions/agentic/integration/mosaic/client_spec.rb +16 -0
  184. data/spec/legion/extensions/agentic/integration/mosaic/helpers/constants_spec.rb +37 -0
  185. data/spec/legion/extensions/agentic/integration/mosaic/helpers/mosaic_engine_spec.rb +108 -0
  186. data/spec/legion/extensions/agentic/integration/mosaic/helpers/mosaic_spec.rb +120 -0
  187. data/spec/legion/extensions/agentic/integration/mosaic/helpers/tessera_spec.rb +92 -0
  188. data/spec/legion/extensions/agentic/integration/mosaic/runners/cognitive_mosaic_spec.rb +88 -0
  189. data/spec/legion/extensions/agentic/integration/mycelium/client_spec.rb +25 -0
  190. data/spec/legion/extensions/agentic/integration/mycelium/cognitive_mycelium_spec.rb +7 -0
  191. data/spec/legion/extensions/agentic/integration/mycelium/helpers/constants_spec.rb +28 -0
  192. data/spec/legion/extensions/agentic/integration/mycelium/helpers/fruiting_body_spec.rb +33 -0
  193. data/spec/legion/extensions/agentic/integration/mycelium/helpers/hypha_spec.rb +69 -0
  194. data/spec/legion/extensions/agentic/integration/mycelium/helpers/mycelial_node_spec.rb +79 -0
  195. data/spec/legion/extensions/agentic/integration/mycelium/helpers/mycelium_engine_spec.rb +136 -0
  196. data/spec/legion/extensions/agentic/integration/mycelium/runners/cognitive_mycelium_spec.rb +61 -0
  197. data/spec/legion/extensions/agentic/integration/phenomenal_binding/client_spec.rb +52 -0
  198. data/spec/legion/extensions/agentic/integration/phenomenal_binding/helpers/binding_engine_spec.rb +290 -0
  199. data/spec/legion/extensions/agentic/integration/phenomenal_binding/helpers/binding_unit_spec.rb +195 -0
  200. data/spec/legion/extensions/agentic/integration/phenomenal_binding/helpers/constants_spec.rb +92 -0
  201. data/spec/legion/extensions/agentic/integration/phenomenal_binding/helpers/stream_spec.rb +128 -0
  202. data/spec/legion/extensions/agentic/integration/phenomenal_binding/runners/phenomenal_binding_spec.rb +174 -0
  203. data/spec/legion/extensions/agentic/integration/qualia/client_spec.rb +21 -0
  204. data/spec/legion/extensions/agentic/integration/qualia/helpers/quale_spec.rb +168 -0
  205. data/spec/legion/extensions/agentic/integration/qualia/helpers/qualia_engine_spec.rb +174 -0
  206. data/spec/legion/extensions/agentic/integration/qualia/qualia_spec.rb +7 -0
  207. data/spec/legion/extensions/agentic/integration/qualia/runners_spec.rb +70 -0
  208. data/spec/legion/extensions/agentic/integration/situation_model/client_spec.rb +51 -0
  209. data/spec/legion/extensions/agentic/integration/situation_model/helpers/constants_spec.rb +56 -0
  210. data/spec/legion/extensions/agentic/integration/situation_model/helpers/situation_engine_spec.rb +203 -0
  211. data/spec/legion/extensions/agentic/integration/situation_model/helpers/situation_event_spec.rb +94 -0
  212. data/spec/legion/extensions/agentic/integration/situation_model/helpers/situation_model_spec.rb +235 -0
  213. data/spec/legion/extensions/agentic/integration/situation_model/runners/situation_model_spec.rb +204 -0
  214. data/spec/legion/extensions/agentic/integration/synthesis/client_spec.rb +26 -0
  215. data/spec/legion/extensions/agentic/integration/synthesis/helpers/constants_spec.rb +87 -0
  216. data/spec/legion/extensions/agentic/integration/synthesis/helpers/synthesis_engine_spec.rb +233 -0
  217. data/spec/legion/extensions/agentic/integration/synthesis/helpers/synthesis_spec.rb +101 -0
  218. data/spec/legion/extensions/agentic/integration/synthesis/helpers/synthesis_stream_spec.rb +116 -0
  219. data/spec/legion/extensions/agentic/integration/synthesis/runners/cognitive_synthesis_spec.rb +181 -0
  220. data/spec/legion/extensions/agentic/integration/tapestry/client_spec.rb +55 -0
  221. data/spec/legion/extensions/agentic/integration/tapestry/helpers/constants_spec.rb +88 -0
  222. data/spec/legion/extensions/agentic/integration/tapestry/helpers/loom_engine_spec.rb +225 -0
  223. data/spec/legion/extensions/agentic/integration/tapestry/helpers/tapestry_spec.rb +229 -0
  224. data/spec/legion/extensions/agentic/integration/tapestry/helpers/thread_spec.rb +211 -0
  225. data/spec/legion/extensions/agentic/integration/tapestry/runners/cognitive_tapestry_spec.rb +171 -0
  226. data/spec/legion/extensions/agentic/integration/tessellation/client_spec.rb +40 -0
  227. data/spec/legion/extensions/agentic/integration/tessellation/helpers/mosaic_spec.rb +99 -0
  228. data/spec/legion/extensions/agentic/integration/tessellation/helpers/tessellation_engine_spec.rb +145 -0
  229. data/spec/legion/extensions/agentic/integration/tessellation/helpers/tile_spec.rb +138 -0
  230. data/spec/legion/extensions/agentic/integration/zeitgeist/helpers/cognitive_signal_spec.rb +62 -0
  231. data/spec/legion/extensions/agentic/integration/zeitgeist/helpers/constants_spec.rb +73 -0
  232. data/spec/legion/extensions/agentic/integration/zeitgeist/helpers/trend_window_spec.rb +100 -0
  233. data/spec/legion/extensions/agentic/integration/zeitgeist/helpers/zeitgeist_engine_spec.rb +163 -0
  234. data/spec/legion/extensions/agentic/integration/zeitgeist/runners/cognitive_zeitgeist_spec.rb +165 -0
  235. data/spec/spec_helper.rb +46 -0
  236. metadata +320 -0
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Integration::Tessellation::Helpers::Mosaic do
4
+ subject(:mosaic) { described_class.new(domain: :cognitive) }
5
+
6
+ let(:tile_class) { Legion::Extensions::Agentic::Integration::Tessellation::Helpers::Tile }
7
+
8
+ describe '#initialize' do
9
+ it 'assigns a uuid id' do
10
+ expect(mosaic.id).to match(/\A[0-9a-f-]{36}\z/)
11
+ end
12
+
13
+ it 'stores domain as symbol' do
14
+ expect(mosaic.domain).to eq(:cognitive)
15
+ end
16
+
17
+ it 'starts with empty tiles' do
18
+ expect(mosaic.tiles).to be_empty
19
+ end
20
+ end
21
+
22
+ describe '#add_tile' do
23
+ it 'adds a tile to the mosaic' do
24
+ tile = tile_class.new(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
25
+ mosaic.add_tile(tile)
26
+ expect(mosaic.tiles.size).to eq(1)
27
+ end
28
+
29
+ it 'auto-connects tiles of the same domain' do
30
+ t1 = tile_class.new(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
31
+ t2 = tile_class.new(tile_type: :skill, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
32
+ mosaic.add_tile(t1)
33
+ mosaic.add_tile(t2)
34
+ expect(t2.adjacent_ids).to include(t1.id)
35
+ end
36
+ end
37
+
38
+ describe '#total_coverage' do
39
+ it 'returns 0.0 for empty mosaic' do
40
+ expect(mosaic.total_coverage).to eq(0.0)
41
+ end
42
+
43
+ it 'returns average effective coverage' do
44
+ t1 = tile_class.new(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.6)
45
+ t2 = tile_class.new(tile_type: :skill, shape: :square, domain: :cognitive, coverage: 0.4)
46
+ mosaic.add_tile(t1)
47
+ mosaic.add_tile(t2)
48
+ expect(mosaic.total_coverage).to be_between(0.0, 1.0)
49
+ end
50
+ end
51
+
52
+ describe '#average_fit' do
53
+ it 'returns 0.0 for empty mosaic' do
54
+ expect(mosaic.average_fit).to eq(0.0)
55
+ end
56
+
57
+ it 'computes average fit score' do
58
+ t1 = tile_class.new(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, fit_score: 0.8)
59
+ mosaic.add_tile(t1)
60
+ expect(mosaic.average_fit).to be > 0.0
61
+ end
62
+ end
63
+
64
+ describe '#coherence' do
65
+ it 'returns 0.0 for empty mosaic' do
66
+ expect(mosaic.coherence).to eq(0.0)
67
+ end
68
+ end
69
+
70
+ describe '#uniformity' do
71
+ it 'returns 1.0 for single tile' do
72
+ t = tile_class.new(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
73
+ mosaic.add_tile(t)
74
+ expect(mosaic.uniformity).to eq(1.0)
75
+ end
76
+
77
+ it 'returns high uniformity for similar coverages' do
78
+ t1 = tile_class.new(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
79
+ t2 = tile_class.new(tile_type: :skill, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
80
+ mosaic.add_tile(t1)
81
+ mosaic.add_tile(t2)
82
+ expect(mosaic.uniformity).to be > 0.9
83
+ end
84
+ end
85
+
86
+ describe '#complete?' do
87
+ it 'returns false for low coverage' do
88
+ expect(mosaic).not_to be_complete
89
+ end
90
+ end
91
+
92
+ describe '#to_h' do
93
+ it 'returns hash with mosaic stats' do
94
+ h = mosaic.to_h
95
+ expect(h).to include(:id, :domain, :tile_count, :total_coverage, :average_fit,
96
+ :coherence, :uniformity, :gaps, :seamless, :complete)
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Integration::Tessellation::Helpers::TessellationEngine do
4
+ subject(:engine) { described_class.new }
5
+
6
+ describe '#create_tile' do
7
+ it 'creates a tile and returns it' do
8
+ tile = engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
9
+ expect(tile).to be_a(Legion::Extensions::Agentic::Integration::Tessellation::Helpers::Tile)
10
+ end
11
+
12
+ it 'adds tile to a mosaic for its domain' do
13
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
14
+ report = engine.tessellation_report
15
+ expect(report[:total_mosaics]).to eq(1)
16
+ end
17
+
18
+ it 'reuses existing mosaic for same domain' do
19
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
20
+ engine.create_tile(tile_type: :skill, shape: :square, domain: :cognitive)
21
+ report = engine.tessellation_report
22
+ expect(report[:total_mosaics]).to eq(1)
23
+ end
24
+
25
+ it 'creates separate mosaics for different domains' do
26
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
27
+ engine.create_tile(tile_type: :skill, shape: :square, domain: :emotional)
28
+ report = engine.tessellation_report
29
+ expect(report[:total_mosaics]).to eq(2)
30
+ end
31
+ end
32
+
33
+ describe '#expand_tile' do
34
+ it 'expands an existing tile' do
35
+ tile = engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
36
+ result = engine.expand_tile(tile_id: tile.id)
37
+ expect(result.coverage).to be > 0.0
38
+ end
39
+
40
+ it 'returns nil for unknown tile' do
41
+ expect(engine.expand_tile(tile_id: 'nonexistent')).to be_nil
42
+ end
43
+ end
44
+
45
+ describe '#shrink_all!' do
46
+ it 'reduces coverage of all tiles' do
47
+ tile = engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
48
+ engine.shrink_all!
49
+ expect(tile.coverage).to be < 0.5
50
+ end
51
+ end
52
+
53
+ describe '#connect_tiles' do
54
+ it 'connects two tiles' do
55
+ t1 = engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
56
+ t2 = engine.create_tile(tile_type: :skill, shape: :square, domain: :emotional)
57
+ result = engine.connect_tiles(tile_a_id: t1.id, tile_b_id: t2.id)
58
+ expect(result[:connected]).to be true
59
+ end
60
+
61
+ it 'returns nil for missing tiles' do
62
+ t1 = engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
63
+ expect(engine.connect_tiles(tile_a_id: t1.id, tile_b_id: 'missing')).to be_nil
64
+ end
65
+ end
66
+
67
+ describe 'query methods' do
68
+ before do
69
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
70
+ engine.create_tile(tile_type: :skill, shape: :square, domain: :emotional, coverage: 0.3)
71
+ engine.create_tile(tile_type: :pattern, shape: :hexagonal, domain: :cognitive, coverage: 0.8)
72
+ end
73
+
74
+ it 'filters tiles_by_domain' do
75
+ expect(engine.tiles_by_domain(domain: :cognitive).size).to eq(2)
76
+ end
77
+
78
+ it 'filters tiles_by_type' do
79
+ expect(engine.tiles_by_type(tile_type: :knowledge).size).to eq(1)
80
+ end
81
+
82
+ it 'filters tiles_by_shape' do
83
+ expect(engine.tiles_by_shape(shape: :hexagonal).size).to eq(2)
84
+ end
85
+
86
+ it 'returns most_covered tiles' do
87
+ results = engine.most_covered(limit: 2)
88
+ expect(results.size).to eq(2)
89
+ expect(results.first.coverage).to be >= results.last.coverage
90
+ end
91
+
92
+ it 'returns least_covered tiles' do
93
+ results = engine.least_covered(limit: 1)
94
+ expect(results.size).to eq(1)
95
+ end
96
+ end
97
+
98
+ describe 'aggregate metrics' do
99
+ it 'returns 0.0 overall_coverage for empty engine' do
100
+ expect(engine.overall_coverage).to eq(0.0)
101
+ end
102
+
103
+ it 'returns 0.0 overall_fit for empty engine' do
104
+ expect(engine.overall_fit).to eq(0.0)
105
+ end
106
+
107
+ it 'computes overall_coverage from mosaics' do
108
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.6)
109
+ expect(engine.overall_coverage).to be > 0.0
110
+ end
111
+
112
+ it 'computes overall_fit from tiles' do
113
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive)
114
+ expect(engine.overall_fit).to be > 0.0
115
+ end
116
+
117
+ it 'computes gap_density' do
118
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, fit_score: 0.1)
119
+ expect(engine.gap_density).to be > 0.0
120
+ end
121
+ end
122
+
123
+ describe '#tessellation_report' do
124
+ it 'returns comprehensive report' do
125
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
126
+ report = engine.tessellation_report
127
+ expect(report).to include(:total_tiles, :total_mosaics, :overall_coverage,
128
+ :coverage_label, :overall_fit, :fit_label,
129
+ :overall_coherence, :gap_density, :domain_coverage, :mosaics)
130
+ end
131
+
132
+ it 'includes coverage_label' do
133
+ engine.create_tile(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive, coverage: 0.5)
134
+ report = engine.tessellation_report
135
+ expect(report[:coverage_label]).to be_a(Symbol)
136
+ end
137
+ end
138
+
139
+ describe '#to_h' do
140
+ it 'returns summary hash' do
141
+ h = engine.to_h
142
+ expect(h).to include(:total_tiles, :total_mosaics, :coverage, :fit, :coherence)
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Integration::Tessellation::Helpers::Tile do
4
+ subject(:tile) { described_class.new(tile_type: :knowledge, shape: :hexagonal, domain: :cognitive) }
5
+
6
+ describe '#initialize' do
7
+ it 'assigns a uuid id' do
8
+ expect(tile.id).to match(/\A[0-9a-f-]{36}\z/)
9
+ end
10
+
11
+ it 'stores tile_type as symbol' do
12
+ expect(tile.tile_type).to eq(:knowledge)
13
+ end
14
+
15
+ it 'stores shape as symbol' do
16
+ expect(tile.shape).to eq(:hexagonal)
17
+ end
18
+
19
+ it 'stores domain as symbol' do
20
+ expect(tile.domain).to eq(:cognitive)
21
+ end
22
+
23
+ it 'defaults coverage to 0.0' do
24
+ expect(tile.coverage).to eq(0.0)
25
+ end
26
+
27
+ it 'defaults fit_score to 0.5' do
28
+ expect(tile.fit_score).to eq(0.5)
29
+ end
30
+
31
+ it 'starts with empty adjacent_ids' do
32
+ expect(tile.adjacent_ids).to be_empty
33
+ end
34
+
35
+ it 'accepts explicit coverage' do
36
+ t = described_class.new(tile_type: :skill, shape: :square, domain: :emotional, coverage: 0.8)
37
+ expect(t.coverage).to eq(0.8)
38
+ end
39
+
40
+ it 'clamps coverage to 0..1' do
41
+ t = described_class.new(tile_type: :skill, shape: :square, domain: :emotional, coverage: 1.5)
42
+ expect(t.coverage).to eq(1.0)
43
+ end
44
+ end
45
+
46
+ describe '#expand!' do
47
+ it 'increases coverage' do
48
+ tile.expand!
49
+ expect(tile.coverage).to be > 0.0
50
+ end
51
+
52
+ it 'clamps coverage at 1.0' do
53
+ t = described_class.new(tile_type: :skill, shape: :square, domain: :cognitive, coverage: 0.98)
54
+ t.expand!(0.1)
55
+ expect(t.coverage).to eq(1.0)
56
+ end
57
+ end
58
+
59
+ describe '#shrink!' do
60
+ it 'decreases coverage' do
61
+ t = described_class.new(tile_type: :skill, shape: :square, domain: :cognitive, coverage: 0.5)
62
+ t.shrink!
63
+ expect(t.coverage).to be < 0.5
64
+ end
65
+
66
+ it 'clamps coverage at 0.0' do
67
+ t = described_class.new(tile_type: :skill, shape: :square, domain: :cognitive, coverage: 0.01)
68
+ t.shrink!(0.1)
69
+ expect(t.coverage).to eq(0.0)
70
+ end
71
+ end
72
+
73
+ describe '#adjust_fit!' do
74
+ it 'updates fit_score' do
75
+ tile.adjust_fit!(0.9)
76
+ expect(tile.fit_score).to eq(0.9)
77
+ end
78
+
79
+ it 'clamps fit_score' do
80
+ tile.adjust_fit!(1.5)
81
+ expect(tile.fit_score).to eq(1.0)
82
+ end
83
+ end
84
+
85
+ describe '#connect!' do
86
+ it 'adds adjacent id' do
87
+ tile.connect!('other-id')
88
+ expect(tile.adjacent_ids).to include('other-id')
89
+ end
90
+
91
+ it 'does not duplicate adjacent ids' do
92
+ tile.connect!('other-id')
93
+ tile.connect!('other-id')
94
+ expect(tile.adjacent_ids.size).to eq(1)
95
+ end
96
+ end
97
+
98
+ describe 'predicate methods' do
99
+ it 'reports full_coverage when coverage >= 0.95' do
100
+ t = described_class.new(tile_type: :skill, shape: :square, domain: :cognitive, coverage: 0.96)
101
+ expect(t).to be_full_coverage
102
+ end
103
+
104
+ it 'reports gapped when fit_score < 0.3' do
105
+ t = described_class.new(tile_type: :skill, shape: :square, domain: :cognitive, fit_score: 0.2)
106
+ expect(t).to be_gapped
107
+ end
108
+
109
+ it 'reports isolated when no adjacent tiles' do
110
+ expect(tile).to be_isolated
111
+ end
112
+
113
+ it 'reports well_connected with 3+ adjacent' do
114
+ 3.times { |i| tile.connect!("id-#{i}") }
115
+ expect(tile).to be_well_connected
116
+ end
117
+
118
+ it 'reports seamless when fit >= 0.8' do
119
+ tile.adjust_fit!(0.85)
120
+ expect(tile).to be_seamless
121
+ end
122
+ end
123
+
124
+ describe '#effective_coverage' do
125
+ it 'equals coverage for non-overlapping tiles' do
126
+ t = described_class.new(tile_type: :skill, shape: :square, domain: :cognitive, coverage: 0.5)
127
+ expect(t.effective_coverage).to eq(0.5)
128
+ end
129
+ end
130
+
131
+ describe '#to_h' do
132
+ it 'returns a hash with all fields' do
133
+ h = tile.to_h
134
+ expect(h).to include(:id, :tile_type, :shape, :domain, :coverage, :fit_score,
135
+ :effective_coverage, :adjacent_count, :created_at)
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Integration::Zeitgeist::Helpers::CognitiveSignal do
4
+ subject(:signal) do
5
+ described_class.new(source_subsystem: :emotion, domain: :threat, intensity: 0.8, valence: -0.5)
6
+ end
7
+
8
+ describe '#initialize' do
9
+ it 'assigns a uuid id' do
10
+ expect(signal.id).to match(/\A[0-9a-f-]{36}\z/)
11
+ end
12
+
13
+ it 'stores source_subsystem as symbol' do
14
+ expect(signal.source_subsystem).to eq(:emotion)
15
+ end
16
+
17
+ it 'stores domain as symbol' do
18
+ expect(signal.domain).to eq(:threat)
19
+ end
20
+
21
+ it 'clamps intensity to 0..1' do
22
+ s = described_class.new(source_subsystem: :x, domain: :y, intensity: 5.0)
23
+ expect(s.intensity).to eq(1.0)
24
+ end
25
+
26
+ it 'clamps valence to -1..1' do
27
+ s = described_class.new(source_subsystem: :x, domain: :y, valence: -9.0)
28
+ expect(s.valence).to eq(-1.0)
29
+ end
30
+
31
+ it 'uses default intensity when not provided' do
32
+ s = described_class.new(source_subsystem: :x, domain: :y)
33
+ expect(s.intensity).to eq(Legion::Extensions::Agentic::Integration::Zeitgeist::Helpers::Constants::DEFAULT_INTENSITY)
34
+ end
35
+
36
+ it 'defaults timestamp to now' do
37
+ expect(signal.timestamp).to be_a(Time)
38
+ end
39
+
40
+ it 'accepts explicit timestamp' do
41
+ t = Time.now.utc - 3600
42
+ s = described_class.new(source_subsystem: :x, domain: :y, timestamp: t)
43
+ expect(s.timestamp).to eq(t)
44
+ end
45
+ end
46
+
47
+ describe '#to_h' do
48
+ it 'returns a hash with all fields' do
49
+ h = signal.to_h
50
+ expect(h.keys).to contain_exactly(:id, :source_subsystem, :domain, :intensity, :valence, :timestamp)
51
+ end
52
+
53
+ it 'rounds intensity to 10 decimal places' do
54
+ h = signal.to_h
55
+ expect(h[:intensity]).to be_a(Float)
56
+ end
57
+
58
+ it 'includes timestamp as iso8601 string' do
59
+ expect(signal.to_h[:timestamp]).to match(/\d{4}-\d{2}-\d{2}/)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Integration::Zeitgeist::Helpers::Constants do
4
+ describe '.label_for' do
5
+ it 'returns correct mood label for high value' do
6
+ label = described_class.label_for(described_class::MOOD_LABELS, 0.9)
7
+ expect(label).to eq(:euphoric)
8
+ end
9
+
10
+ it 'returns correct mood label for mid value' do
11
+ label = described_class.label_for(described_class::MOOD_LABELS, 0.5)
12
+ expect(label).to eq(:neutral)
13
+ end
14
+
15
+ it 'returns correct mood label for low value' do
16
+ label = described_class.label_for(described_class::MOOD_LABELS, 0.1)
17
+ expect(label).to eq(:suppressed)
18
+ end
19
+
20
+ it 'returns correct convergence label for unified' do
21
+ label = described_class.label_for(described_class::CONVERGENCE_LABELS, 0.95)
22
+ expect(label).to eq(:unified)
23
+ end
24
+
25
+ it 'returns correct convergence label for divergent' do
26
+ label = described_class.label_for(described_class::CONVERGENCE_LABELS, 0.1)
27
+ expect(label).to eq(:divergent)
28
+ end
29
+
30
+ it 'returns correct momentum label for surging' do
31
+ label = described_class.label_for(described_class::MOMENTUM_LABELS, 0.8)
32
+ expect(label).to eq(:surging)
33
+ end
34
+
35
+ it 'returns correct momentum label for collapsing' do
36
+ label = described_class.label_for(described_class::MOMENTUM_LABELS, -0.5)
37
+ expect(label).to eq(:collapsing)
38
+ end
39
+
40
+ it 'returns nil for unmatched value when no range covers it' do
41
+ custom = { (0.5..1.0) => :high }.freeze
42
+ expect(described_class.label_for(custom, 0.2)).to be_nil
43
+ end
44
+ end
45
+
46
+ describe 'SIGNAL_DOMAINS' do
47
+ it 'contains 8 domains' do
48
+ expect(described_class::SIGNAL_DOMAINS.size).to eq(8)
49
+ end
50
+
51
+ it 'includes expected domains' do
52
+ expect(described_class::SIGNAL_DOMAINS).to include(:threat, :curiosity, :creativity, :social)
53
+ end
54
+ end
55
+
56
+ describe 'constants' do
57
+ it 'MAX_SIGNALS is 1000' do
58
+ expect(described_class::MAX_SIGNALS).to eq(1000)
59
+ end
60
+
61
+ it 'WINDOW_SIZE is 100' do
62
+ expect(described_class::WINDOW_SIZE).to eq(100)
63
+ end
64
+
65
+ it 'CONVERGENCE_THRESHOLD is 0.7' do
66
+ expect(described_class::CONVERGENCE_THRESHOLD).to eq(0.7)
67
+ end
68
+
69
+ it 'DIVERGENCE_THRESHOLD is 0.3' do
70
+ expect(described_class::DIVERGENCE_THRESHOLD).to eq(0.3)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Integration::Zeitgeist::Helpers::TrendWindow do
4
+ subject(:window) { described_class.new }
5
+
6
+ let(:signal_class) { Legion::Extensions::Agentic::Integration::Zeitgeist::Helpers::CognitiveSignal }
7
+
8
+ def make_signal(domain: :curiosity, intensity: 0.5, valence: 0.0)
9
+ signal_class.new(source_subsystem: :emotion, domain: domain, intensity: intensity, valence: valence)
10
+ end
11
+
12
+ describe '#add' do
13
+ it 'adds a signal and returns self' do
14
+ result = window.add(make_signal)
15
+ expect(result).to be(window)
16
+ expect(window.signals.size).to eq(1)
17
+ end
18
+
19
+ it 'evicts oldest signal when at capacity' do
20
+ small_window = described_class.new(window_size: 3)
21
+ 4.times { small_window.add(make_signal) }
22
+ expect(small_window.signals.size).to eq(3)
23
+ end
24
+ end
25
+
26
+ describe '#dominant_domain' do
27
+ it 'returns nil for empty window' do
28
+ expect(window.dominant_domain).to be_nil
29
+ end
30
+
31
+ it 'returns the domain with highest weighted intensity' do
32
+ window.add(make_signal(domain: :threat, intensity: 0.9))
33
+ window.add(make_signal(domain: :threat, intensity: 0.8))
34
+ window.add(make_signal(domain: :curiosity, intensity: 0.3))
35
+ expect(window.dominant_domain).to eq(:threat)
36
+ end
37
+ end
38
+
39
+ describe '#dominant_valence' do
40
+ it 'returns 0.0 for empty window' do
41
+ expect(window.dominant_valence).to eq(0.0)
42
+ end
43
+
44
+ it 'computes intensity-weighted valence' do
45
+ window.add(make_signal(domain: :threat, intensity: 1.0, valence: -1.0))
46
+ window.add(make_signal(domain: :opportunity, intensity: 1.0, valence: 1.0))
47
+ expect(window.dominant_valence).to be_within(0.001).of(0.0)
48
+ end
49
+
50
+ it 'is positive when positive signals dominate' do
51
+ window.add(make_signal(intensity: 0.8, valence: 0.9))
52
+ window.add(make_signal(intensity: 0.1, valence: -0.5))
53
+ expect(window.dominant_valence).to be > 0.0
54
+ end
55
+ end
56
+
57
+ describe '#momentum' do
58
+ it 'returns 0.0 with fewer than 2 signals' do
59
+ window.add(make_signal)
60
+ expect(window.momentum).to eq(0.0)
61
+ end
62
+
63
+ it 'returns positive momentum when second half more intense' do
64
+ 4.times { window.add(make_signal(intensity: 0.2)) }
65
+ 4.times { window.add(make_signal(intensity: 0.9)) }
66
+ expect(window.momentum).to be > 0.0
67
+ end
68
+
69
+ it 'returns negative momentum when second half less intense' do
70
+ 4.times { window.add(make_signal(intensity: 0.9)) }
71
+ 4.times { window.add(make_signal(intensity: 0.2)) }
72
+ expect(window.momentum).to be < 0.0
73
+ end
74
+ end
75
+
76
+ describe '#accelerating? and #decelerating?' do
77
+ it 'is accelerating when momentum exceeds threshold' do
78
+ 4.times { window.add(make_signal(intensity: 0.1)) }
79
+ 4.times { window.add(make_signal(intensity: 1.0)) }
80
+ expect(window.accelerating?).to be true
81
+ expect(window.decelerating?).to be false
82
+ end
83
+
84
+ it 'is decelerating when momentum is strongly negative' do
85
+ 4.times { window.add(make_signal(intensity: 1.0)) }
86
+ 4.times { window.add(make_signal(intensity: 0.0)) }
87
+ expect(window.decelerating?).to be true
88
+ expect(window.accelerating?).to be false
89
+ end
90
+ end
91
+
92
+ describe '#to_h' do
93
+ it 'returns a complete hash' do
94
+ window.add(make_signal)
95
+ h = window.to_h
96
+ expect(h.keys).to include(:size, :window_size, :dominant_domain, :dominant_valence, :momentum,
97
+ :accelerating, :decelerating)
98
+ end
99
+ end
100
+ end