lex-agentic-inference 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 (328) 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-inference.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/inference/abductive/client.rb +25 -0
  8. data/lib/legion/extensions/agentic/inference/abductive/helpers/abduction_engine.rb +164 -0
  9. data/lib/legion/extensions/agentic/inference/abductive/helpers/constants.rb +39 -0
  10. data/lib/legion/extensions/agentic/inference/abductive/helpers/hypothesis.rb +106 -0
  11. data/lib/legion/extensions/agentic/inference/abductive/helpers/observation.rb +39 -0
  12. data/lib/legion/extensions/agentic/inference/abductive/runners/abductive_reasoning.rb +129 -0
  13. data/lib/legion/extensions/agentic/inference/abductive/version.rb +13 -0
  14. data/lib/legion/extensions/agentic/inference/abductive.rb +20 -0
  15. data/lib/legion/extensions/agentic/inference/affordance/actors/scan.rb +31 -0
  16. data/lib/legion/extensions/agentic/inference/affordance/client.rb +28 -0
  17. data/lib/legion/extensions/agentic/inference/affordance/helpers/affordance_field.rb +123 -0
  18. data/lib/legion/extensions/agentic/inference/affordance/helpers/affordance_item.rb +75 -0
  19. data/lib/legion/extensions/agentic/inference/affordance/helpers/constants.rb +42 -0
  20. data/lib/legion/extensions/agentic/inference/affordance/runners/affordance.rb +90 -0
  21. data/lib/legion/extensions/agentic/inference/affordance/version.rb +13 -0
  22. data/lib/legion/extensions/agentic/inference/affordance.rb +19 -0
  23. data/lib/legion/extensions/agentic/inference/analogical/client.rb +28 -0
  24. data/lib/legion/extensions/agentic/inference/analogical/helpers/analogy_engine.rb +209 -0
  25. data/lib/legion/extensions/agentic/inference/analogical/helpers/constants.rb +38 -0
  26. data/lib/legion/extensions/agentic/inference/analogical/helpers/structure_map.rb +113 -0
  27. data/lib/legion/extensions/agentic/inference/analogical/runners/analogical_reasoning.rb +106 -0
  28. data/lib/legion/extensions/agentic/inference/analogical/version.rb +13 -0
  29. data/lib/legion/extensions/agentic/inference/analogical.rb +19 -0
  30. data/lib/legion/extensions/agentic/inference/argument_mapping/client.rb +19 -0
  31. data/lib/legion/extensions/agentic/inference/argument_mapping/helpers/argument.rb +102 -0
  32. data/lib/legion/extensions/agentic/inference/argument_mapping/helpers/argument_engine.rb +131 -0
  33. data/lib/legion/extensions/agentic/inference/argument_mapping/helpers/constants.rb +44 -0
  34. data/lib/legion/extensions/agentic/inference/argument_mapping/runners/argument_mapping.rb +78 -0
  35. data/lib/legion/extensions/agentic/inference/argument_mapping/version.rb +13 -0
  36. data/lib/legion/extensions/agentic/inference/argument_mapping.rb +19 -0
  37. data/lib/legion/extensions/agentic/inference/bayesian/client.rb +28 -0
  38. data/lib/legion/extensions/agentic/inference/bayesian/helpers/belief.rb +96 -0
  39. data/lib/legion/extensions/agentic/inference/bayesian/helpers/belief_network.rb +147 -0
  40. data/lib/legion/extensions/agentic/inference/bayesian/helpers/constants.rb +36 -0
  41. data/lib/legion/extensions/agentic/inference/bayesian/runners/bayesian_belief.rb +125 -0
  42. data/lib/legion/extensions/agentic/inference/bayesian/version.rb +13 -0
  43. data/lib/legion/extensions/agentic/inference/bayesian.rb +19 -0
  44. data/lib/legion/extensions/agentic/inference/belief_revision/client.rb +19 -0
  45. data/lib/legion/extensions/agentic/inference/belief_revision/helpers/belief.rb +155 -0
  46. data/lib/legion/extensions/agentic/inference/belief_revision/helpers/belief_network.rb +193 -0
  47. data/lib/legion/extensions/agentic/inference/belief_revision/helpers/constants.rb +54 -0
  48. data/lib/legion/extensions/agentic/inference/belief_revision/helpers/evidence.rb +49 -0
  49. data/lib/legion/extensions/agentic/inference/belief_revision/runners/belief_revision.rb +89 -0
  50. data/lib/legion/extensions/agentic/inference/belief_revision/version.rb +13 -0
  51. data/lib/legion/extensions/agentic/inference/belief_revision.rb +21 -0
  52. data/lib/legion/extensions/agentic/inference/causal_attribution/client.rb +27 -0
  53. data/lib/legion/extensions/agentic/inference/causal_attribution/helpers/attribution.rb +92 -0
  54. data/lib/legion/extensions/agentic/inference/causal_attribution/helpers/attribution_engine.rb +159 -0
  55. data/lib/legion/extensions/agentic/inference/causal_attribution/runners/causal_attribution.rb +111 -0
  56. data/lib/legion/extensions/agentic/inference/causal_attribution/version.rb +13 -0
  57. data/lib/legion/extensions/agentic/inference/causal_attribution.rb +18 -0
  58. data/lib/legion/extensions/agentic/inference/causal_reasoning/client.rb +24 -0
  59. data/lib/legion/extensions/agentic/inference/causal_reasoning/helpers/causal_edge.rb +101 -0
  60. data/lib/legion/extensions/agentic/inference/causal_reasoning/helpers/causal_graph.rb +184 -0
  61. data/lib/legion/extensions/agentic/inference/causal_reasoning/helpers/constants.rb +40 -0
  62. data/lib/legion/extensions/agentic/inference/causal_reasoning/runners/causal_reasoning.rb +111 -0
  63. data/lib/legion/extensions/agentic/inference/causal_reasoning/version.rb +13 -0
  64. data/lib/legion/extensions/agentic/inference/causal_reasoning.rb +19 -0
  65. data/lib/legion/extensions/agentic/inference/coherence/client.rb +28 -0
  66. data/lib/legion/extensions/agentic/inference/coherence/helpers/coherence_engine.rb +170 -0
  67. data/lib/legion/extensions/agentic/inference/coherence/helpers/constants.rb +35 -0
  68. data/lib/legion/extensions/agentic/inference/coherence/helpers/proposition.rb +100 -0
  69. data/lib/legion/extensions/agentic/inference/coherence/runners/cognitive_coherence.rb +123 -0
  70. data/lib/legion/extensions/agentic/inference/coherence/version.rb +13 -0
  71. data/lib/legion/extensions/agentic/inference/coherence.rb +19 -0
  72. data/lib/legion/extensions/agentic/inference/counterfactual/client.rb +19 -0
  73. data/lib/legion/extensions/agentic/inference/counterfactual/helpers/constants.rb +40 -0
  74. data/lib/legion/extensions/agentic/inference/counterfactual/helpers/counterfactual_engine.rb +157 -0
  75. data/lib/legion/extensions/agentic/inference/counterfactual/helpers/scenario.rb +98 -0
  76. data/lib/legion/extensions/agentic/inference/counterfactual/runners/counterfactual.rb +106 -0
  77. data/lib/legion/extensions/agentic/inference/counterfactual/version.rb +13 -0
  78. data/lib/legion/extensions/agentic/inference/counterfactual.rb +19 -0
  79. data/lib/legion/extensions/agentic/inference/debugging/client.rb +30 -0
  80. data/lib/legion/extensions/agentic/inference/debugging/helpers/causal_trace.rb +51 -0
  81. data/lib/legion/extensions/agentic/inference/debugging/helpers/constants.rb +58 -0
  82. data/lib/legion/extensions/agentic/inference/debugging/helpers/correction.rb +56 -0
  83. data/lib/legion/extensions/agentic/inference/debugging/helpers/debugging_engine.rb +156 -0
  84. data/lib/legion/extensions/agentic/inference/debugging/helpers/reasoning_error.rb +97 -0
  85. data/lib/legion/extensions/agentic/inference/debugging/runners/cognitive_debugging.rb +178 -0
  86. data/lib/legion/extensions/agentic/inference/debugging/version.rb +13 -0
  87. data/lib/legion/extensions/agentic/inference/debugging.rb +21 -0
  88. data/lib/legion/extensions/agentic/inference/enactive_cognition/client.rb +27 -0
  89. data/lib/legion/extensions/agentic/inference/enactive_cognition/helpers/enaction_engine.rb +120 -0
  90. data/lib/legion/extensions/agentic/inference/enactive_cognition/helpers/sensorimotor_loop.rb +122 -0
  91. data/lib/legion/extensions/agentic/inference/enactive_cognition/runners/enactive_cognition.rb +124 -0
  92. data/lib/legion/extensions/agentic/inference/enactive_cognition/version.rb +13 -0
  93. data/lib/legion/extensions/agentic/inference/enactive_cognition.rb +18 -0
  94. data/lib/legion/extensions/agentic/inference/expectation_violation/helpers/client.rb +17 -0
  95. data/lib/legion/extensions/agentic/inference/expectation_violation/helpers/constants.rb +47 -0
  96. data/lib/legion/extensions/agentic/inference/expectation_violation/helpers/expectation.rb +82 -0
  97. data/lib/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine.rb +126 -0
  98. data/lib/legion/extensions/agentic/inference/expectation_violation/runners/expectation_violation.rb +76 -0
  99. data/lib/legion/extensions/agentic/inference/expectation_violation/version.rb +13 -0
  100. data/lib/legion/extensions/agentic/inference/expectation_violation.rb +19 -0
  101. data/lib/legion/extensions/agentic/inference/free_energy/client.rb +19 -0
  102. data/lib/legion/extensions/agentic/inference/free_energy/helpers/belief.rb +127 -0
  103. data/lib/legion/extensions/agentic/inference/free_energy/helpers/constants.rb +58 -0
  104. data/lib/legion/extensions/agentic/inference/free_energy/helpers/free_energy_engine.rb +156 -0
  105. data/lib/legion/extensions/agentic/inference/free_energy/runners/free_energy.rb +97 -0
  106. data/lib/legion/extensions/agentic/inference/free_energy/version.rb +13 -0
  107. data/lib/legion/extensions/agentic/inference/free_energy.rb +19 -0
  108. data/lib/legion/extensions/agentic/inference/gravity/client.rb +29 -0
  109. data/lib/legion/extensions/agentic/inference/gravity/helpers/attractor.rb +77 -0
  110. data/lib/legion/extensions/agentic/inference/gravity/helpers/constants.rb +76 -0
  111. data/lib/legion/extensions/agentic/inference/gravity/helpers/gravity_engine.rb +164 -0
  112. data/lib/legion/extensions/agentic/inference/gravity/helpers/orbiting_thought.rb +64 -0
  113. data/lib/legion/extensions/agentic/inference/gravity/runners/gravity.rb +132 -0
  114. data/lib/legion/extensions/agentic/inference/gravity/version.rb +13 -0
  115. data/lib/legion/extensions/agentic/inference/gravity.rb +20 -0
  116. data/lib/legion/extensions/agentic/inference/horizon/actors/adjust.rb +45 -0
  117. data/lib/legion/extensions/agentic/inference/horizon/client.rb +28 -0
  118. data/lib/legion/extensions/agentic/inference/horizon/helpers/constants.rb +43 -0
  119. data/lib/legion/extensions/agentic/inference/horizon/helpers/horizon_engine.rb +110 -0
  120. data/lib/legion/extensions/agentic/inference/horizon/helpers/projection.rb +59 -0
  121. data/lib/legion/extensions/agentic/inference/horizon/runners/cognitive_horizon.rb +107 -0
  122. data/lib/legion/extensions/agentic/inference/horizon/version.rb +13 -0
  123. data/lib/legion/extensions/agentic/inference/horizon.rb +19 -0
  124. data/lib/legion/extensions/agentic/inference/hypothesis_testing/client.rb +28 -0
  125. data/lib/legion/extensions/agentic/inference/hypothesis_testing/helpers/constants.rb +37 -0
  126. data/lib/legion/extensions/agentic/inference/hypothesis_testing/helpers/hypothesis.rb +83 -0
  127. data/lib/legion/extensions/agentic/inference/hypothesis_testing/helpers/hypothesis_engine.rb +97 -0
  128. data/lib/legion/extensions/agentic/inference/hypothesis_testing/runners/hypothesis_testing.rb +115 -0
  129. data/lib/legion/extensions/agentic/inference/hypothesis_testing/version.rb +13 -0
  130. data/lib/legion/extensions/agentic/inference/hypothesis_testing.rb +19 -0
  131. data/lib/legion/extensions/agentic/inference/intuition/client.rb +19 -0
  132. data/lib/legion/extensions/agentic/inference/intuition/helpers/constants.rb +60 -0
  133. data/lib/legion/extensions/agentic/inference/intuition/helpers/heuristic.rb +66 -0
  134. data/lib/legion/extensions/agentic/inference/intuition/helpers/intuition_engine.rb +157 -0
  135. data/lib/legion/extensions/agentic/inference/intuition/helpers/pattern.rb +105 -0
  136. data/lib/legion/extensions/agentic/inference/intuition/runners/intuition.rb +87 -0
  137. data/lib/legion/extensions/agentic/inference/intuition/version.rb +13 -0
  138. data/lib/legion/extensions/agentic/inference/intuition.rb +20 -0
  139. data/lib/legion/extensions/agentic/inference/magnet/client.rb +29 -0
  140. data/lib/legion/extensions/agentic/inference/magnet/helpers/constants.rb +57 -0
  141. data/lib/legion/extensions/agentic/inference/magnet/helpers/field.rb +105 -0
  142. data/lib/legion/extensions/agentic/inference/magnet/helpers/magnet_engine.rb +179 -0
  143. data/lib/legion/extensions/agentic/inference/magnet/helpers/pole.rb +80 -0
  144. data/lib/legion/extensions/agentic/inference/magnet/runners/cognitive_magnet.rb +124 -0
  145. data/lib/legion/extensions/agentic/inference/magnet/version.rb +13 -0
  146. data/lib/legion/extensions/agentic/inference/magnet.rb +21 -0
  147. data/lib/legion/extensions/agentic/inference/momentum/helpers/client.rb +17 -0
  148. data/lib/legion/extensions/agentic/inference/momentum/helpers/constants.rb +65 -0
  149. data/lib/legion/extensions/agentic/inference/momentum/helpers/idea.rb +112 -0
  150. data/lib/legion/extensions/agentic/inference/momentum/helpers/momentum_engine.rb +127 -0
  151. data/lib/legion/extensions/agentic/inference/momentum/runners/cognitive_momentum.rb +101 -0
  152. data/lib/legion/extensions/agentic/inference/momentum/version.rb +13 -0
  153. data/lib/legion/extensions/agentic/inference/momentum.rb +19 -0
  154. data/lib/legion/extensions/agentic/inference/perceptual_inference/client.rb +28 -0
  155. data/lib/legion/extensions/agentic/inference/perceptual_inference/helpers/constants.rb +34 -0
  156. data/lib/legion/extensions/agentic/inference/perceptual_inference/helpers/perceptual_field.rb +154 -0
  157. data/lib/legion/extensions/agentic/inference/perceptual_inference/helpers/perceptual_hypothesis.rb +100 -0
  158. data/lib/legion/extensions/agentic/inference/perceptual_inference/runners/perceptual_inference.rb +120 -0
  159. data/lib/legion/extensions/agentic/inference/perceptual_inference/version.rb +13 -0
  160. data/lib/legion/extensions/agentic/inference/perceptual_inference.rb +19 -0
  161. data/lib/legion/extensions/agentic/inference/prediction/actors/expire_predictions.rb +45 -0
  162. data/lib/legion/extensions/agentic/inference/prediction/client.rb +27 -0
  163. data/lib/legion/extensions/agentic/inference/prediction/helpers/modes.rb +28 -0
  164. data/lib/legion/extensions/agentic/inference/prediction/helpers/prediction_store.rb +66 -0
  165. data/lib/legion/extensions/agentic/inference/prediction/runners/prediction.rb +146 -0
  166. data/lib/legion/extensions/agentic/inference/prediction/version.rb +13 -0
  167. data/lib/legion/extensions/agentic/inference/prediction.rb +18 -0
  168. data/lib/legion/extensions/agentic/inference/predictive_coding/actors/decay.rb +45 -0
  169. data/lib/legion/extensions/agentic/inference/predictive_coding/client.rb +28 -0
  170. data/lib/legion/extensions/agentic/inference/predictive_coding/helpers/constants.rb +46 -0
  171. data/lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb +187 -0
  172. data/lib/legion/extensions/agentic/inference/predictive_coding/helpers/prediction_error.rb +59 -0
  173. data/lib/legion/extensions/agentic/inference/predictive_coding/runners/predictive_coding.rb +171 -0
  174. data/lib/legion/extensions/agentic/inference/predictive_coding/version.rb +13 -0
  175. data/lib/legion/extensions/agentic/inference/predictive_coding.rb +20 -0
  176. data/lib/legion/extensions/agentic/inference/predictive_processing/client.rb +28 -0
  177. data/lib/legion/extensions/agentic/inference/predictive_processing/helpers/constants.rb +35 -0
  178. data/lib/legion/extensions/agentic/inference/predictive_processing/helpers/generative_model.rb +142 -0
  179. data/lib/legion/extensions/agentic/inference/predictive_processing/helpers/predictive_processor.rb +129 -0
  180. data/lib/legion/extensions/agentic/inference/predictive_processing/runners/predictive_processing.rb +104 -0
  181. data/lib/legion/extensions/agentic/inference/predictive_processing/version.rb +13 -0
  182. data/lib/legion/extensions/agentic/inference/predictive_processing.rb +19 -0
  183. data/lib/legion/extensions/agentic/inference/reality_testing/client.rb +28 -0
  184. data/lib/legion/extensions/agentic/inference/reality_testing/helpers/belief.rb +98 -0
  185. data/lib/legion/extensions/agentic/inference/reality_testing/helpers/constants.rb +41 -0
  186. data/lib/legion/extensions/agentic/inference/reality_testing/helpers/reality_engine.rb +104 -0
  187. data/lib/legion/extensions/agentic/inference/reality_testing/runners/reality_testing.rb +94 -0
  188. data/lib/legion/extensions/agentic/inference/reality_testing/version.rb +13 -0
  189. data/lib/legion/extensions/agentic/inference/reality_testing.rb +19 -0
  190. data/lib/legion/extensions/agentic/inference/schema/client.rb +26 -0
  191. data/lib/legion/extensions/agentic/inference/schema/helpers/causal_relation.rb +70 -0
  192. data/lib/legion/extensions/agentic/inference/schema/helpers/constants.rb +50 -0
  193. data/lib/legion/extensions/agentic/inference/schema/helpers/world_model.rb +173 -0
  194. data/lib/legion/extensions/agentic/inference/schema/runners/schema.rb +101 -0
  195. data/lib/legion/extensions/agentic/inference/schema/version.rb +13 -0
  196. data/lib/legion/extensions/agentic/inference/schema.rb +19 -0
  197. data/lib/legion/extensions/agentic/inference/uncertainty_tolerance/client.rb +28 -0
  198. data/lib/legion/extensions/agentic/inference/uncertainty_tolerance/helpers/constants.rb +42 -0
  199. data/lib/legion/extensions/agentic/inference/uncertainty_tolerance/helpers/decision.rb +66 -0
  200. data/lib/legion/extensions/agentic/inference/uncertainty_tolerance/helpers/tolerance_engine.rb +139 -0
  201. data/lib/legion/extensions/agentic/inference/uncertainty_tolerance/runners/uncertainty_tolerance.rb +129 -0
  202. data/lib/legion/extensions/agentic/inference/uncertainty_tolerance/version.rb +13 -0
  203. data/lib/legion/extensions/agentic/inference/uncertainty_tolerance.rb +19 -0
  204. data/lib/legion/extensions/agentic/inference/version.rb +11 -0
  205. data/lib/legion/extensions/agentic/inference.rb +44 -0
  206. data/spec/legion/extensions/agentic/inference/abductive/client_spec.rb +25 -0
  207. data/spec/legion/extensions/agentic/inference/abductive/runners/abductive_reasoning_spec.rb +349 -0
  208. data/spec/legion/extensions/agentic/inference/affordance/client_spec.rb +26 -0
  209. data/spec/legion/extensions/agentic/inference/affordance/helpers/affordance_field_spec.rb +131 -0
  210. data/spec/legion/extensions/agentic/inference/affordance/helpers/affordance_item_spec.rb +107 -0
  211. data/spec/legion/extensions/agentic/inference/affordance/runners/affordance_spec.rb +78 -0
  212. data/spec/legion/extensions/agentic/inference/analogical/client_spec.rb +31 -0
  213. data/spec/legion/extensions/agentic/inference/analogical/helpers/analogy_engine_spec.rb +276 -0
  214. data/spec/legion/extensions/agentic/inference/analogical/helpers/structure_map_spec.rb +255 -0
  215. data/spec/legion/extensions/agentic/inference/analogical/runners/analogical_reasoning_spec.rb +213 -0
  216. data/spec/legion/extensions/agentic/inference/argument_mapping/client_spec.rb +18 -0
  217. data/spec/legion/extensions/agentic/inference/argument_mapping/helpers/argument_engine_spec.rb +218 -0
  218. data/spec/legion/extensions/agentic/inference/argument_mapping/helpers/argument_spec.rb +231 -0
  219. data/spec/legion/extensions/agentic/inference/argument_mapping/runners/argument_mapping_spec.rb +171 -0
  220. data/spec/legion/extensions/agentic/inference/bayesian/client_spec.rb +20 -0
  221. data/spec/legion/extensions/agentic/inference/bayesian/helpers/belief_network_spec.rb +178 -0
  222. data/spec/legion/extensions/agentic/inference/bayesian/helpers/belief_spec.rb +137 -0
  223. data/spec/legion/extensions/agentic/inference/bayesian/runners/bayesian_belief_spec.rb +176 -0
  224. data/spec/legion/extensions/agentic/inference/belief_revision/client_spec.rb +31 -0
  225. data/spec/legion/extensions/agentic/inference/belief_revision/helpers/belief_network_spec.rb +176 -0
  226. data/spec/legion/extensions/agentic/inference/belief_revision/helpers/belief_spec.rb +153 -0
  227. data/spec/legion/extensions/agentic/inference/belief_revision/helpers/evidence_spec.rb +51 -0
  228. data/spec/legion/extensions/agentic/inference/belief_revision/runners/belief_revision_spec.rb +106 -0
  229. data/spec/legion/extensions/agentic/inference/causal_attribution/client_spec.rb +24 -0
  230. data/spec/legion/extensions/agentic/inference/causal_attribution/helpers/attribution_engine_spec.rb +181 -0
  231. data/spec/legion/extensions/agentic/inference/causal_attribution/helpers/attribution_spec.rb +108 -0
  232. data/spec/legion/extensions/agentic/inference/causal_attribution/runners/causal_attribution_spec.rb +142 -0
  233. data/spec/legion/extensions/agentic/inference/causal_reasoning/client_spec.rb +35 -0
  234. data/spec/legion/extensions/agentic/inference/causal_reasoning/helpers/causal_edge_spec.rb +158 -0
  235. data/spec/legion/extensions/agentic/inference/causal_reasoning/helpers/causal_graph_spec.rb +259 -0
  236. data/spec/legion/extensions/agentic/inference/causal_reasoning/runners/causal_reasoning_spec.rb +161 -0
  237. data/spec/legion/extensions/agentic/inference/coherence/client_spec.rb +17 -0
  238. data/spec/legion/extensions/agentic/inference/coherence/runners/cognitive_coherence_spec.rb +267 -0
  239. data/spec/legion/extensions/agentic/inference/counterfactual/client_spec.rb +48 -0
  240. data/spec/legion/extensions/agentic/inference/counterfactual/helpers/constants_spec.rb +55 -0
  241. data/spec/legion/extensions/agentic/inference/counterfactual/helpers/counterfactual_engine_spec.rb +234 -0
  242. data/spec/legion/extensions/agentic/inference/counterfactual/helpers/scenario_spec.rb +193 -0
  243. data/spec/legion/extensions/agentic/inference/counterfactual/runners/counterfactual_spec.rb +179 -0
  244. data/spec/legion/extensions/agentic/inference/debugging/client_spec.rb +46 -0
  245. data/spec/legion/extensions/agentic/inference/debugging/helpers/causal_trace_spec.rb +84 -0
  246. data/spec/legion/extensions/agentic/inference/debugging/helpers/constants_spec.rb +97 -0
  247. data/spec/legion/extensions/agentic/inference/debugging/helpers/correction_spec.rb +98 -0
  248. data/spec/legion/extensions/agentic/inference/debugging/helpers/debugging_engine_spec.rb +290 -0
  249. data/spec/legion/extensions/agentic/inference/debugging/helpers/reasoning_error_spec.rb +164 -0
  250. data/spec/legion/extensions/agentic/inference/debugging/runners/cognitive_debugging_spec.rb +301 -0
  251. data/spec/legion/extensions/agentic/inference/enactive_cognition/client_spec.rb +19 -0
  252. data/spec/legion/extensions/agentic/inference/enactive_cognition/helpers/enaction_engine_spec.rb +181 -0
  253. data/spec/legion/extensions/agentic/inference/enactive_cognition/helpers/sensorimotor_loop_spec.rb +184 -0
  254. data/spec/legion/extensions/agentic/inference/enactive_cognition/runners/enactive_cognition_spec.rb +214 -0
  255. data/spec/legion/extensions/agentic/inference/expectation_violation/expectation_violation_spec.rb +11 -0
  256. data/spec/legion/extensions/agentic/inference/expectation_violation/helpers/expectation_spec.rb +102 -0
  257. data/spec/legion/extensions/agentic/inference/expectation_violation/helpers/violation_engine_spec.rb +121 -0
  258. data/spec/legion/extensions/agentic/inference/expectation_violation/runners/expectation_violation_spec.rb +59 -0
  259. data/spec/legion/extensions/agentic/inference/free_energy/client_spec.rb +46 -0
  260. data/spec/legion/extensions/agentic/inference/free_energy/helpers/belief_spec.rb +183 -0
  261. data/spec/legion/extensions/agentic/inference/free_energy/helpers/free_energy_engine_spec.rb +211 -0
  262. data/spec/legion/extensions/agentic/inference/free_energy/runners/free_energy_spec.rb +118 -0
  263. data/spec/legion/extensions/agentic/inference/gravity/client_spec.rb +24 -0
  264. data/spec/legion/extensions/agentic/inference/gravity/helpers/attractor_spec.rb +143 -0
  265. data/spec/legion/extensions/agentic/inference/gravity/helpers/constants_spec.rb +107 -0
  266. data/spec/legion/extensions/agentic/inference/gravity/helpers/gravity_engine_spec.rb +193 -0
  267. data/spec/legion/extensions/agentic/inference/gravity/helpers/orbiting_thought_spec.rb +103 -0
  268. data/spec/legion/extensions/agentic/inference/gravity/runners/gravity_spec.rb +159 -0
  269. data/spec/legion/extensions/agentic/inference/horizon/client_spec.rb +58 -0
  270. data/spec/legion/extensions/agentic/inference/horizon/helpers/constants_spec.rb +98 -0
  271. data/spec/legion/extensions/agentic/inference/horizon/helpers/horizon_engine_spec.rb +325 -0
  272. data/spec/legion/extensions/agentic/inference/horizon/helpers/projection_spec.rb +155 -0
  273. data/spec/legion/extensions/agentic/inference/horizon/runners/cognitive_horizon_spec.rb +269 -0
  274. data/spec/legion/extensions/agentic/inference/hypothesis_testing/helpers/constants_spec.rb +38 -0
  275. data/spec/legion/extensions/agentic/inference/hypothesis_testing/helpers/hypothesis_engine_spec.rb +182 -0
  276. data/spec/legion/extensions/agentic/inference/hypothesis_testing/helpers/hypothesis_spec.rb +172 -0
  277. data/spec/legion/extensions/agentic/inference/hypothesis_testing/hypothesis_testing_spec.rb +16 -0
  278. data/spec/legion/extensions/agentic/inference/hypothesis_testing/runners/hypothesis_testing_spec.rb +159 -0
  279. data/spec/legion/extensions/agentic/inference/intuition/client_spec.rb +33 -0
  280. data/spec/legion/extensions/agentic/inference/intuition/helpers/heuristic_spec.rb +82 -0
  281. data/spec/legion/extensions/agentic/inference/intuition/helpers/intuition_engine_spec.rb +163 -0
  282. data/spec/legion/extensions/agentic/inference/intuition/helpers/pattern_spec.rb +160 -0
  283. data/spec/legion/extensions/agentic/inference/intuition/runners/intuition_spec.rb +107 -0
  284. data/spec/legion/extensions/agentic/inference/magnet/client_spec.rb +30 -0
  285. data/spec/legion/extensions/agentic/inference/magnet/helpers/constants_spec.rb +120 -0
  286. data/spec/legion/extensions/agentic/inference/magnet/helpers/field_spec.rb +193 -0
  287. data/spec/legion/extensions/agentic/inference/magnet/helpers/magnet_engine_spec.rb +281 -0
  288. data/spec/legion/extensions/agentic/inference/magnet/helpers/pole_spec.rb +211 -0
  289. data/spec/legion/extensions/agentic/inference/magnet/runners/cognitive_magnet_spec.rb +201 -0
  290. data/spec/legion/extensions/agentic/inference/momentum/cognitive_momentum_spec.rb +11 -0
  291. data/spec/legion/extensions/agentic/inference/momentum/helpers/idea_spec.rb +152 -0
  292. data/spec/legion/extensions/agentic/inference/momentum/helpers/momentum_engine_spec.rb +154 -0
  293. data/spec/legion/extensions/agentic/inference/momentum/runners/cognitive_momentum_spec.rb +97 -0
  294. data/spec/legion/extensions/agentic/inference/perceptual_inference/client_spec.rb +39 -0
  295. data/spec/legion/extensions/agentic/inference/perceptual_inference/helpers/constants_spec.rb +97 -0
  296. data/spec/legion/extensions/agentic/inference/perceptual_inference/helpers/perceptual_field_spec.rb +270 -0
  297. data/spec/legion/extensions/agentic/inference/perceptual_inference/helpers/perceptual_hypothesis_spec.rb +206 -0
  298. data/spec/legion/extensions/agentic/inference/perceptual_inference/runners/perceptual_inference_spec.rb +305 -0
  299. data/spec/legion/extensions/agentic/inference/prediction/actors/expire_predictions_spec.rb +46 -0
  300. data/spec/legion/extensions/agentic/inference/prediction/client_spec.rb +14 -0
  301. data/spec/legion/extensions/agentic/inference/prediction/helpers/modes_spec.rb +118 -0
  302. data/spec/legion/extensions/agentic/inference/prediction/helpers/prediction_store_spec.rb +262 -0
  303. data/spec/legion/extensions/agentic/inference/prediction/runners/prediction_spec.rb +116 -0
  304. data/spec/legion/extensions/agentic/inference/predictive_coding/client_spec.rb +74 -0
  305. data/spec/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model_spec.rb +194 -0
  306. data/spec/legion/extensions/agentic/inference/predictive_coding/helpers/prediction_error_spec.rb +109 -0
  307. data/spec/legion/extensions/agentic/inference/predictive_coding/runners/predictive_coding_spec.rb +210 -0
  308. data/spec/legion/extensions/agentic/inference/predictive_processing/client_spec.rb +82 -0
  309. data/spec/legion/extensions/agentic/inference/predictive_processing/helpers/generative_model_spec.rb +220 -0
  310. data/spec/legion/extensions/agentic/inference/predictive_processing/helpers/predictive_processor_spec.rb +206 -0
  311. data/spec/legion/extensions/agentic/inference/predictive_processing/runners/predictive_processing_spec.rb +213 -0
  312. data/spec/legion/extensions/agentic/inference/reality_testing/client_spec.rb +29 -0
  313. data/spec/legion/extensions/agentic/inference/reality_testing/helpers/belief_spec.rb +197 -0
  314. data/spec/legion/extensions/agentic/inference/reality_testing/helpers/constants_spec.rb +78 -0
  315. data/spec/legion/extensions/agentic/inference/reality_testing/helpers/reality_engine_spec.rb +191 -0
  316. data/spec/legion/extensions/agentic/inference/reality_testing/runners/reality_testing_spec.rb +154 -0
  317. data/spec/legion/extensions/agentic/inference/schema/client_spec.rb +53 -0
  318. data/spec/legion/extensions/agentic/inference/schema/helpers/causal_relation_spec.rb +108 -0
  319. data/spec/legion/extensions/agentic/inference/schema/helpers/constants_spec.rb +54 -0
  320. data/spec/legion/extensions/agentic/inference/schema/helpers/world_model_spec.rb +179 -0
  321. data/spec/legion/extensions/agentic/inference/schema/runners/schema_spec.rb +146 -0
  322. data/spec/legion/extensions/agentic/inference/uncertainty_tolerance/client_spec.rb +18 -0
  323. data/spec/legion/extensions/agentic/inference/uncertainty_tolerance/helpers/constants_spec.rb +62 -0
  324. data/spec/legion/extensions/agentic/inference/uncertainty_tolerance/helpers/decision_spec.rb +125 -0
  325. data/spec/legion/extensions/agentic/inference/uncertainty_tolerance/helpers/tolerance_engine_spec.rb +184 -0
  326. data/spec/legion/extensions/agentic/inference/uncertainty_tolerance/runners/uncertainty_tolerance_spec.rb +157 -0
  327. data/spec/spec_helper.rb +46 -0
  328. metadata +412 -0
@@ -0,0 +1,301 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/inference/debugging/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Inference::Debugging::Runners::CognitiveDebugging do
6
+ subject(:client) { Legion::Extensions::Agentic::Inference::Debugging::Client.new }
7
+
8
+ let(:base_error_kwargs) do
9
+ {
10
+ error_type: :inconsistency,
11
+ description: 'Claim X contradicts Claim Y',
12
+ severity: 0.6,
13
+ source_phase: :prediction_engine,
14
+ confidence_at_detection: 0.85
15
+ }
16
+ end
17
+
18
+ def detect_one(overrides = {})
19
+ client.detect_error(**base_error_kwargs, **overrides)
20
+ end
21
+
22
+ describe '#detect_error' do
23
+ it 'returns success: true with an error_id' do
24
+ result = detect_one
25
+ expect(result[:success]).to be true
26
+ expect(result[:error_id]).to match(/\A[0-9a-f-]{36}\z/)
27
+ end
28
+
29
+ it 'returns the error_type' do
30
+ result = detect_one
31
+ expect(result[:error_type]).to eq(:inconsistency)
32
+ end
33
+
34
+ it 'includes severity_label' do
35
+ result = detect_one
36
+ expect(result[:severity_label]).to be_a(Symbol)
37
+ end
38
+
39
+ it 'returns success: false for invalid error_type' do
40
+ result = client.detect_error(**base_error_kwargs, error_type: :not_real)
41
+ expect(result[:success]).to be false
42
+ expect(result[:error]).to eq(:invalid_error_type)
43
+ end
44
+
45
+ it 'returns valid error types on failure' do
46
+ result = client.detect_error(**base_error_kwargs, error_type: :bogus)
47
+ expect(result[:valid]).to include(:inconsistency)
48
+ end
49
+
50
+ it 'uses default confidence_at_detection of 0.5 when omitted' do
51
+ result = client.detect_error(error_type: :overconfidence, description: 'x',
52
+ severity: 0.5, source_phase: :tick)
53
+ expect(result[:success]).to be true
54
+ end
55
+ end
56
+
57
+ describe '#trace_error' do
58
+ let(:error_id) { detect_one[:error_id] }
59
+ let(:steps) do
60
+ [
61
+ { phase: :emotional_evaluation, description: 'Urgency spike' },
62
+ { phase: :prediction_engine, description: 'Premature conclusion' }
63
+ ]
64
+ end
65
+
66
+ it 'returns success: true with trace_id and depth' do
67
+ result = client.trace_error(error_id: error_id, steps: steps, root_cause: :bad_prior, confidence: 0.7)
68
+ expect(result[:success]).to be true
69
+ expect(result[:trace_id]).to match(/\A[0-9a-f-]{36}\z/)
70
+ expect(result[:depth]).to eq(2)
71
+ end
72
+
73
+ it 'returns root_cause in response' do
74
+ result = client.trace_error(error_id: error_id, steps: steps, root_cause: :bad_prior, confidence: 0.7)
75
+ expect(result[:root_cause]).to eq(:bad_prior)
76
+ end
77
+
78
+ it 'returns success: false for unknown error_id' do
79
+ result = client.trace_error(error_id: 'nope', steps: steps, root_cause: :x, confidence: 0.5)
80
+ expect(result[:success]).to be false
81
+ expect(result[:error]).to eq(:not_found_or_cap)
82
+ end
83
+
84
+ it 'uses default confidence of 0.5 when omitted' do
85
+ result = client.trace_error(error_id: error_id, steps: steps, root_cause: :x)
86
+ expect(result[:success]).to be true
87
+ end
88
+ end
89
+
90
+ describe '#propose_correction' do
91
+ let(:error_id) { detect_one[:error_id] }
92
+
93
+ it 'returns success: true with correction_id and strategy' do
94
+ result = client.propose_correction(error_id: error_id, strategy: :retrace,
95
+ description: 'Re-examine from start')
96
+ expect(result[:success]).to be true
97
+ expect(result[:correction_id]).to match(/\A[0-9a-f-]{36}\z/)
98
+ expect(result[:strategy]).to eq(:retrace)
99
+ end
100
+
101
+ it 'returns success: false for invalid strategy' do
102
+ result = client.propose_correction(error_id: error_id, strategy: :invalid_strat, description: 'x')
103
+ expect(result[:success]).to be false
104
+ expect(result[:error]).to eq(:invalid_strategy)
105
+ end
106
+
107
+ it 'returns valid strategies on failure' do
108
+ result = client.propose_correction(error_id: error_id, strategy: :bad, description: 'x')
109
+ expect(result[:valid]).to include(:retrace, :devil_advocate)
110
+ end
111
+
112
+ it 'returns success: false for unknown error_id' do
113
+ result = client.propose_correction(error_id: 'nope', strategy: :retrace, description: 'x')
114
+ expect(result[:success]).to be false
115
+ expect(result[:error]).to eq(:not_found)
116
+ end
117
+ end
118
+
119
+ describe '#apply_correction' do
120
+ let(:correction_id) do
121
+ error_id = detect_one[:error_id]
122
+ client.propose_correction(error_id: error_id, strategy: :retrace, description: 'x')[:correction_id]
123
+ end
124
+
125
+ it 'returns success: true and applied: true' do
126
+ result = client.apply_correction(correction_id: correction_id)
127
+ expect(result[:success]).to be true
128
+ expect(result[:applied]).to be true
129
+ end
130
+
131
+ it 'returns success: false for unknown correction_id' do
132
+ result = client.apply_correction(correction_id: 'nope')
133
+ expect(result[:success]).to be false
134
+ expect(result[:error]).to eq(:not_found)
135
+ end
136
+ end
137
+
138
+ describe '#measure_correction' do
139
+ let(:correction_id) do
140
+ error_id = detect_one[:error_id]
141
+ client.propose_correction(error_id: error_id, strategy: :reframe, description: 'x')[:correction_id]
142
+ end
143
+
144
+ it 'returns effectiveness and effective flag' do
145
+ result = client.measure_correction(correction_id: correction_id, effectiveness: 0.8)
146
+ expect(result[:success]).to be true
147
+ expect(result[:effectiveness]).to eq(0.8)
148
+ expect(result[:effective]).to be true
149
+ end
150
+
151
+ it 'returns effective: false for low score' do
152
+ result = client.measure_correction(correction_id: correction_id, effectiveness: 0.4)
153
+ expect(result[:effective]).to be false
154
+ end
155
+
156
+ it 'returns success: false for unknown correction_id' do
157
+ result = client.measure_correction(correction_id: 'nope', effectiveness: 0.5)
158
+ expect(result[:success]).to be false
159
+ end
160
+ end
161
+
162
+ describe '#resolve_error' do
163
+ let(:error_id) { detect_one[:error_id] }
164
+
165
+ it 'returns success: true and resolved: true' do
166
+ result = client.resolve_error(error_id: error_id)
167
+ expect(result[:success]).to be true
168
+ expect(result[:resolved]).to be true
169
+ end
170
+
171
+ it 'returns success: false for unknown error_id' do
172
+ result = client.resolve_error(error_id: 'nope')
173
+ expect(result[:success]).to be false
174
+ end
175
+ end
176
+
177
+ describe '#active_errors' do
178
+ it 'returns a list of active errors' do
179
+ detect_one
180
+ result = client.active_errors
181
+ expect(result[:success]).to be true
182
+ expect(result[:count]).to be >= 1
183
+ expect(result[:errors]).to be_an(Array)
184
+ end
185
+
186
+ it 'does not include resolved errors' do
187
+ eid = detect_one[:error_id]
188
+ client.resolve_error(error_id: eid)
189
+ result = client.active_errors
190
+ ids = result[:errors].map { |e| e[:id] }
191
+ expect(ids).not_to include(eid)
192
+ end
193
+ end
194
+
195
+ describe '#resolved_errors' do
196
+ it 'returns empty list when nothing resolved' do
197
+ result = client.resolved_errors
198
+ expect(result[:success]).to be true
199
+ expect(result[:count]).to eq(0)
200
+ end
201
+
202
+ it 'includes resolved errors' do
203
+ eid = detect_one[:error_id]
204
+ client.resolve_error(error_id: eid)
205
+ result = client.resolved_errors
206
+ ids = result[:errors].map { |e| e[:id] }
207
+ expect(ids).to include(eid)
208
+ end
209
+ end
210
+
211
+ describe '#errors_by_type' do
212
+ it 'returns a tally hash' do
213
+ detect_one(error_type: :overconfidence)
214
+ detect_one(error_type: :overconfidence)
215
+ result = client.errors_by_type
216
+ expect(result[:success]).to be true
217
+ expect(result[:tally][:overconfidence]).to eq(2)
218
+ end
219
+ end
220
+
221
+ describe '#errors_by_phase' do
222
+ it 'returns a tally by source_phase' do
223
+ detect_one(source_phase: :emotional_evaluation)
224
+ result = client.errors_by_phase
225
+ expect(result[:success]).to be true
226
+ expect(result[:tally][:emotional_evaluation]).to be >= 1
227
+ end
228
+ end
229
+
230
+ describe '#most_common_error_type' do
231
+ it 'returns nil when no errors' do
232
+ result = client.most_common_error_type
233
+ expect(result[:success]).to be true
234
+ expect(result[:error_type]).to be_nil
235
+ end
236
+
237
+ it 'returns the most frequent type' do
238
+ detect_one(error_type: :circular_logic)
239
+ detect_one(error_type: :circular_logic)
240
+ detect_one(error_type: :missing_evidence)
241
+ result = client.most_common_error_type
242
+ expect(result[:error_type]).to eq(:circular_logic)
243
+ end
244
+ end
245
+
246
+ describe '#most_effective_strategy' do
247
+ it 'returns nil when no measured corrections' do
248
+ result = client.most_effective_strategy
249
+ expect(result[:success]).to be true
250
+ expect(result[:strategy]).to be_nil
251
+ end
252
+
253
+ it 'returns the best-performing strategy' do
254
+ eid = detect_one[:error_id]
255
+ c1 = client.propose_correction(error_id: eid, strategy: :retrace, description: 'x')
256
+ c2 = client.propose_correction(error_id: eid, strategy: :seek_evidence, description: 'y')
257
+ client.measure_correction(correction_id: c1[:correction_id], effectiveness: 0.3)
258
+ client.measure_correction(correction_id: c2[:correction_id], effectiveness: 0.95)
259
+ result = client.most_effective_strategy
260
+ expect(result[:strategy]).to eq(:seek_evidence)
261
+ end
262
+ end
263
+
264
+ describe '#correction_success_rate' do
265
+ it 'returns 0.0 when no corrections' do
266
+ result = client.correction_success_rate
267
+ expect(result[:success]).to be true
268
+ expect(result[:rate]).to eq(0.0)
269
+ end
270
+
271
+ it 'calculates correct rate after measuring' do
272
+ eid = detect_one[:error_id]
273
+ c1 = client.propose_correction(error_id: eid, strategy: :retrace, description: 'a')
274
+ c2 = client.propose_correction(error_id: eid, strategy: :reframe, description: 'b')
275
+ client.apply_correction(correction_id: c1[:correction_id])
276
+ client.apply_correction(correction_id: c2[:correction_id])
277
+ client.measure_correction(correction_id: c1[:correction_id], effectiveness: 0.9)
278
+ client.measure_correction(correction_id: c2[:correction_id], effectiveness: 0.9)
279
+ result = client.correction_success_rate
280
+ expect(result[:rate]).to eq(1.0)
281
+ end
282
+ end
283
+
284
+ describe '#debugging_report' do
285
+ it 'returns success: true with a complete report' do
286
+ detect_one
287
+ result = client.debugging_report
288
+ expect(result[:success]).to be true
289
+ expect(result[:report]).to include(:total_errors, :active_errors, :correction_success_rate)
290
+ end
291
+ end
292
+
293
+ describe '#snapshot' do
294
+ it 'returns success: true with snapshot data' do
295
+ detect_one
296
+ result = client.snapshot
297
+ expect(result[:success]).to be true
298
+ expect(result[:snapshot]).to include(:errors, :traces, :corrections)
299
+ end
300
+ end
301
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/inference/enactive_cognition/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Inference::EnactiveCognition::Client do
6
+ it 'responds to all runner methods' do
7
+ client = described_class.new
8
+ expect(client).to respond_to(:create_sensorimotor_coupling)
9
+ expect(client).to respond_to(:execute_enactive_action)
10
+ expect(client).to respond_to(:adapt_sensorimotor_coupling)
11
+ expect(client).to respond_to(:find_action_for_perception)
12
+ expect(client).to respond_to(:coupled_sensorimotor_loops)
13
+ expect(client).to respond_to(:domain_couplings)
14
+ expect(client).to respond_to(:strongest_couplings)
15
+ expect(client).to respond_to(:overall_enactive_coupling)
16
+ expect(client).to respond_to(:update_enactive_cognition)
17
+ expect(client).to respond_to(:enactive_cognition_stats)
18
+ end
19
+ end
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/inference/enactive_cognition/helpers/sensorimotor_loop'
4
+ require 'legion/extensions/agentic/inference/enactive_cognition/helpers/enaction_engine'
5
+
6
+ RSpec.describe Legion::Extensions::Agentic::Inference::EnactiveCognition::Helpers::EnactionEngine do
7
+ subject(:engine) { described_class.new }
8
+
9
+ let(:coupling) do
10
+ engine.create_coupling(action: 'grasp', perception: 'grip', domain: 'motor')
11
+ end
12
+
13
+ describe '#create_coupling' do
14
+ it 'returns a SensorimotorLoop instance' do
15
+ expect(coupling).to be_a(Legion::Extensions::Agentic::Inference::EnactiveCognition::Helpers::SensorimotorLoop)
16
+ end
17
+
18
+ it 'stores the coupling by id' do
19
+ expect(engine.couplings[coupling.id]).to eq(coupling)
20
+ end
21
+
22
+ it 'increments coupling count' do
23
+ engine.create_coupling(action: 'push', perception: 'moved', domain: 'motor')
24
+ expect(engine.count).to eq(1)
25
+ end
26
+
27
+ it 'defaults loop_type to :sensorimotor' do
28
+ expect(coupling.loop_type).to eq(:sensorimotor)
29
+ end
30
+
31
+ it 'accepts explicit loop_type' do
32
+ lp = engine.create_coupling(action: 'think', perception: 'clarity', domain: 'cog', loop_type: :cognitive)
33
+ expect(lp.loop_type).to eq(:cognitive)
34
+ end
35
+ end
36
+
37
+ describe '#execute_action' do
38
+ it 'returns success: true on match' do
39
+ result = engine.execute_action(coupling_id: coupling.id, actual_perception: 'grip')
40
+ expect(result[:success]).to be true
41
+ expect(result[:match]).to be true
42
+ end
43
+
44
+ it 'returns success: true on mismatch' do
45
+ result = engine.execute_action(coupling_id: coupling.id, actual_perception: 'slip')
46
+ expect(result[:success]).to be true
47
+ expect(result[:match]).to be false
48
+ end
49
+
50
+ it 'returns success: false for missing coupling' do
51
+ result = engine.execute_action(coupling_id: 'nonexistent', actual_perception: 'grip')
52
+ expect(result[:success]).to be false
53
+ expect(result[:reason]).to eq(:not_found)
54
+ end
55
+
56
+ it 'includes coupling_label in result' do
57
+ result = engine.execute_action(coupling_id: coupling.id, actual_perception: 'grip')
58
+ expect(result[:coupling_label]).to be_a(Symbol)
59
+ end
60
+ end
61
+
62
+ describe '#adapt_coupling' do
63
+ it 'updates the coupling perception' do
64
+ engine.adapt_coupling(coupling_id: coupling.id, new_perception: 'firm_grip')
65
+ expect(engine.couplings[coupling.id].perception).to eq('firm_grip')
66
+ end
67
+
68
+ it 'returns success: true' do
69
+ result = engine.adapt_coupling(coupling_id: coupling.id, new_perception: 'firm_grip')
70
+ expect(result[:success]).to be true
71
+ end
72
+
73
+ it 'returns success: false for missing coupling' do
74
+ result = engine.adapt_coupling(coupling_id: 'bad', new_perception: 'x')
75
+ expect(result[:success]).to be false
76
+ end
77
+ end
78
+
79
+ describe '#find_action_for' do
80
+ before do
81
+ 5.times { engine.execute_action(coupling_id: coupling.id, actual_perception: 'grip') }
82
+ end
83
+
84
+ it 'returns the loop when it is coupled and perception matches' do
85
+ result = engine.find_action_for(perception: 'grip')
86
+ if coupling.coupled?
87
+ expect(result).not_to be_nil
88
+ expect(result.action).to eq('grasp')
89
+ else
90
+ expect(result).to be_nil
91
+ end
92
+ end
93
+
94
+ it 'returns nil when perception does not match any coupled loop' do
95
+ result = engine.find_action_for(perception: 'unknown_perception')
96
+ expect(result).to be_nil
97
+ end
98
+ end
99
+
100
+ describe '#coupled_loops' do
101
+ it 'returns empty when nothing is coupled' do
102
+ engine.create_coupling(action: 'act', perception: 'per', domain: 'dom')
103
+ expect(engine.coupled_loops).to be_empty
104
+ end
105
+
106
+ it 'returns loops above coupling threshold' do
107
+ c2 = engine.create_coupling(action: 'act2', perception: 'per2', domain: 'dom2')
108
+ allow(c2).to receive(:coupled?).and_return(true)
109
+ expect(engine.coupled_loops).to include(c2)
110
+ end
111
+ end
112
+
113
+ describe '#by_domain' do
114
+ it 'returns loops in the specified domain' do
115
+ engine.create_coupling(action: 'act', perception: 'per', domain: 'motor')
116
+ engine.create_coupling(action: 'speak', perception: 'heard', domain: 'social')
117
+ expect(engine.by_domain(domain: 'motor').size).to eq(1)
118
+ end
119
+ end
120
+
121
+ describe '#by_type' do
122
+ it 'returns loops of the specified type' do
123
+ engine.create_coupling(action: 'act', perception: 'per', domain: 'dom', loop_type: :cognitive)
124
+ engine.create_coupling(action: 'act2', perception: 'per2', domain: 'dom2', loop_type: :social)
125
+ expect(engine.by_type(loop_type: :cognitive).size).to eq(1)
126
+ end
127
+ end
128
+
129
+ describe '#strongest_couplings' do
130
+ it 'returns at most limit couplings sorted by strength desc' do
131
+ 3.times { |i| engine.create_coupling(action: "a#{i}", perception: "p#{i}", domain: 'dom') }
132
+ result = engine.strongest_couplings(limit: 2)
133
+ expect(result.size).to be <= 2
134
+ end
135
+ end
136
+
137
+ describe '#overall_coupling' do
138
+ it 'returns 0.0 when no couplings exist' do
139
+ expect(engine.overall_coupling).to eq(0.0)
140
+ end
141
+
142
+ it 'returns mean coupling strength' do
143
+ engine.create_coupling(action: 'a', perception: 'p', domain: 'd')
144
+ expect(engine.overall_coupling).to eq(
145
+ Legion::Extensions::Agentic::Inference::EnactiveCognition::Helpers::SensorimotorLoop::DEFAULT_COUPLING_STRENGTH
146
+ )
147
+ end
148
+ end
149
+
150
+ describe '#decay_all' do
151
+ it 'reduces coupling strength of all loops' do
152
+ lp = engine.create_coupling(action: 'a', perception: 'p', domain: 'd')
153
+ before = lp.coupling_strength
154
+ engine.decay_all
155
+ expect(lp.coupling_strength).to be < before
156
+ end
157
+ end
158
+
159
+ describe '#prune_decoupled' do
160
+ it 'removes very weak couplings' do
161
+ lp = engine.create_coupling(action: 'a', perception: 'p', domain: 'd')
162
+ 100.times { lp.execute!(actual_perception: 'miss') }
163
+ count_before = engine.count
164
+ engine.prune_decoupled
165
+ expect(engine.count).to be <= count_before
166
+ end
167
+ end
168
+
169
+ describe '#to_h' do
170
+ it 'includes expected keys' do
171
+ result = engine.to_h
172
+ expect(result).to include(:coupling_count, :coupled_count, :overall_coupling, :strongest)
173
+ end
174
+
175
+ it 'rounds overall_coupling to 4 decimal places' do
176
+ engine.create_coupling(action: 'a', perception: 'p', domain: 'd')
177
+ result = engine.to_h
178
+ expect(result[:overall_coupling]).to be_a(Float)
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/inference/enactive_cognition/helpers/sensorimotor_loop'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Inference::EnactiveCognition::Helpers::SensorimotorLoop do
6
+ subject(:loop_obj) do
7
+ described_class.new(action: 'reach', perception: 'contact', domain: 'motor')
8
+ end
9
+
10
+ describe '#initialize' do
11
+ it 'assigns a uuid id' do
12
+ expect(loop_obj.id).to match(/\A[0-9a-f-]{36}\z/)
13
+ end
14
+
15
+ it 'sets default coupling strength' do
16
+ expect(loop_obj.coupling_strength).to eq(described_class::DEFAULT_COUPLING_STRENGTH)
17
+ end
18
+
19
+ it 'defaults loop_type to :sensorimotor' do
20
+ expect(loop_obj.loop_type).to eq(:sensorimotor)
21
+ end
22
+
23
+ it 'accepts valid loop types' do
24
+ cognitive = described_class.new(action: 'think', perception: 'insight', domain: 'cog', loop_type: :cognitive)
25
+ expect(cognitive.loop_type).to eq(:cognitive)
26
+ end
27
+
28
+ it 'falls back to :sensorimotor for invalid loop_type' do
29
+ bad = described_class.new(action: 'x', perception: 'y', domain: 'z', loop_type: :invalid)
30
+ expect(bad.loop_type).to eq(:sensorimotor)
31
+ end
32
+
33
+ it 'starts with zero execution count' do
34
+ expect(loop_obj.execution_count).to eq(0)
35
+ end
36
+
37
+ it 'starts with zero accurate_predictions' do
38
+ expect(loop_obj.accurate_predictions).to eq(0)
39
+ end
40
+ end
41
+
42
+ describe '#execute!' do
43
+ context 'when actual matches expected perception' do
44
+ it 'increments execution_count' do
45
+ loop_obj.execute!(actual_perception: 'contact')
46
+ expect(loop_obj.execution_count).to eq(1)
47
+ end
48
+
49
+ it 'increments accurate_predictions' do
50
+ loop_obj.execute!(actual_perception: 'contact')
51
+ expect(loop_obj.accurate_predictions).to eq(1)
52
+ end
53
+
54
+ it 'strengthens coupling' do
55
+ before = loop_obj.coupling_strength
56
+ loop_obj.execute!(actual_perception: 'contact')
57
+ expect(loop_obj.coupling_strength).to be > before
58
+ end
59
+
60
+ it 'returns match: true' do
61
+ result = loop_obj.execute!(actual_perception: 'contact')
62
+ expect(result[:match]).to be true
63
+ end
64
+
65
+ it 'does not exceed COUPLING_CEILING' do
66
+ 20.times { loop_obj.execute!(actual_perception: 'contact') }
67
+ expect(loop_obj.coupling_strength).to be <= described_class::COUPLING_CEILING
68
+ end
69
+ end
70
+
71
+ context 'when actual does not match expected perception' do
72
+ it 'weakens coupling' do
73
+ before = loop_obj.coupling_strength
74
+ loop_obj.execute!(actual_perception: 'no_contact')
75
+ expect(loop_obj.coupling_strength).to be < before
76
+ end
77
+
78
+ it 'returns match: false' do
79
+ result = loop_obj.execute!(actual_perception: 'no_contact')
80
+ expect(result[:match]).to be false
81
+ end
82
+
83
+ it 'does not fall below COUPLING_FLOOR' do
84
+ 20.times { loop_obj.execute!(actual_perception: 'no_contact') }
85
+ expect(loop_obj.coupling_strength).to be >= described_class::COUPLING_FLOOR
86
+ end
87
+
88
+ it 'does not increment accurate_predictions' do
89
+ loop_obj.execute!(actual_perception: 'no_contact')
90
+ expect(loop_obj.accurate_predictions).to eq(0)
91
+ end
92
+ end
93
+
94
+ it 'updates prediction_accuracy' do
95
+ 3.times { loop_obj.execute!(actual_perception: 'contact') }
96
+ loop_obj.execute!(actual_perception: 'miss')
97
+ expect(loop_obj.prediction_accuracy).to eq(0.75)
98
+ end
99
+
100
+ it 'sets last_executed_at' do
101
+ loop_obj.execute!(actual_perception: 'contact')
102
+ expect(loop_obj.last_executed_at).not_to be_nil
103
+ end
104
+ end
105
+
106
+ describe '#coupled?' do
107
+ it 'returns false at default strength (0.5)' do
108
+ expect(loop_obj.coupled?).to be false
109
+ end
110
+
111
+ it 'returns true when strength reaches 0.6' do
112
+ loop_obj.execute!(actual_perception: 'contact')
113
+ loop_obj.execute!(actual_perception: 'contact')
114
+ if loop_obj.coupling_strength >= 0.6
115
+ expect(loop_obj.coupled?).to be true
116
+ else
117
+ expect(loop_obj.coupled?).to be false
118
+ end
119
+ end
120
+ end
121
+
122
+ describe '#coupling_label' do
123
+ it 'returns :forming at default strength 0.5' do
124
+ expect(loop_obj.coupling_label).to eq(:forming)
125
+ end
126
+
127
+ it 'returns :entrained at strength 0.9' do
128
+ allow(loop_obj).to receive(:coupling_strength).and_return(0.9)
129
+ expect(loop_obj.coupling_label).to eq(:entrained)
130
+ end
131
+
132
+ it 'returns :decoupled at strength 0.1' do
133
+ allow(loop_obj).to receive(:coupling_strength).and_return(0.1)
134
+ expect(loop_obj.coupling_label).to eq(:decoupled)
135
+ end
136
+
137
+ it 'returns :weak at strength 0.25' do
138
+ allow(loop_obj).to receive(:coupling_strength).and_return(0.25)
139
+ expect(loop_obj.coupling_label).to eq(:weak)
140
+ end
141
+
142
+ it 'returns :coupled at strength 0.7' do
143
+ allow(loop_obj).to receive(:coupling_strength).and_return(0.7)
144
+ expect(loop_obj.coupling_label).to eq(:coupled)
145
+ end
146
+ end
147
+
148
+ describe '#adapt_perception!' do
149
+ it 'updates the expected perception' do
150
+ loop_obj.adapt_perception!(new_perception: 'soft_contact')
151
+ expect(loop_obj.perception).to eq('soft_contact')
152
+ end
153
+ end
154
+
155
+ describe '#decay!' do
156
+ it 'reduces coupling_strength by COUPLING_DECAY' do
157
+ before = loop_obj.coupling_strength
158
+ loop_obj.decay!
159
+ expect(loop_obj.coupling_strength).to eq((before - described_class::COUPLING_DECAY).clamp(0.0, 1.0))
160
+ end
161
+
162
+ it 'does not fall below COUPLING_FLOOR' do
163
+ 100.times { loop_obj.decay! }
164
+ expect(loop_obj.coupling_strength).to be >= described_class::COUPLING_FLOOR
165
+ end
166
+ end
167
+
168
+ describe '#to_h' do
169
+ it 'includes all expected keys' do
170
+ hash = loop_obj.to_h
171
+ expect(hash).to include(
172
+ :id, :action, :perception, :domain, :loop_type,
173
+ :coupling_strength, :coupling_label, :prediction_accuracy,
174
+ :execution_count, :accurate_predictions, :coupled,
175
+ :created_at, :last_executed_at
176
+ )
177
+ end
178
+
179
+ it 'reflects current coupling_label' do
180
+ hash = loop_obj.to_h
181
+ expect(hash[:coupling_label]).to eq(loop_obj.coupling_label)
182
+ end
183
+ end
184
+ end