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,262 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Inference::Prediction::Helpers::PredictionStore do
6
+ subject(:store) { described_class.new }
7
+
8
+ let(:basic_prediction) do
9
+ {
10
+ mode: :fault_localization,
11
+ confidence: 0.75,
12
+ description: 'disk latency spike incoming',
13
+ status: :pending
14
+ }
15
+ end
16
+
17
+ describe '#initialize' do
18
+ it 'starts with empty predictions hash' do
19
+ expect(store.predictions).to eq({})
20
+ end
21
+
22
+ it 'starts with empty outcomes array' do
23
+ expect(store.outcomes).to eq([])
24
+ end
25
+ end
26
+
27
+ describe '#store' do
28
+ it 'returns a UUID string' do
29
+ id = store.store(basic_prediction.dup)
30
+ expect(id).to match(/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/)
31
+ end
32
+
33
+ it 'stores the prediction under the returned id' do
34
+ id = store.store(basic_prediction.dup)
35
+ expect(store.predictions[id]).not_to be_nil
36
+ end
37
+
38
+ it 'sets prediction_id on the prediction hash' do
39
+ prediction = basic_prediction.dup
40
+ id = store.store(prediction)
41
+ expect(prediction[:prediction_id]).to eq(id)
42
+ end
43
+
44
+ it 'preserves a caller-supplied prediction_id' do
45
+ prediction = basic_prediction.merge(prediction_id: 'my-custom-id')
46
+ returned_id = store.store(prediction)
47
+ expect(returned_id).to eq('my-custom-id')
48
+ expect(store.predictions['my-custom-id']).not_to be_nil
49
+ end
50
+
51
+ it 'sets created_at when not supplied' do
52
+ prediction = basic_prediction.dup
53
+ before = Time.now.utc
54
+ store.store(prediction)
55
+ expect(prediction[:created_at]).to be >= before
56
+ end
57
+
58
+ it 'preserves a caller-supplied created_at' do
59
+ custom_time = Time.now.utc - 3600
60
+ prediction = basic_prediction.merge(created_at: custom_time)
61
+ store.store(prediction)
62
+ expect(prediction[:created_at]).to eq(custom_time)
63
+ end
64
+
65
+ it 'sets default status to :pending' do
66
+ prediction = { mode: :counterfactual, confidence: 0.5 }
67
+ store.store(prediction)
68
+ expect(prediction[:status]).to eq(:pending)
69
+ end
70
+
71
+ it 'preserves a caller-supplied status' do
72
+ prediction = basic_prediction.merge(status: :expired)
73
+ store.store(prediction)
74
+ expect(prediction[:status]).to eq(:expired)
75
+ end
76
+
77
+ it 'increments count with each stored prediction' do
78
+ 3.times { store.store(basic_prediction.dup) }
79
+ expect(store.count).to eq(3)
80
+ end
81
+ end
82
+
83
+ describe '#get' do
84
+ it 'retrieves a stored prediction by id' do
85
+ id = store.store(basic_prediction.dup)
86
+ result = store.get(id)
87
+ expect(result[:mode]).to eq(:fault_localization)
88
+ end
89
+
90
+ it 'returns nil for an unknown id' do
91
+ expect(store.get('no-such-id')).to be_nil
92
+ end
93
+ end
94
+
95
+ describe '#resolve' do
96
+ let!(:prediction_id) { store.store(basic_prediction.dup) }
97
+
98
+ it 'returns the updated prediction' do
99
+ result = store.resolve(prediction_id, outcome: :correct)
100
+ expect(result).to be_a(Hash)
101
+ expect(result[:prediction_id]).to eq(prediction_id)
102
+ end
103
+
104
+ it 'sets status to the given outcome' do
105
+ store.resolve(prediction_id, outcome: :incorrect)
106
+ expect(store.get(prediction_id)[:status]).to eq(:incorrect)
107
+ end
108
+
109
+ it 'sets resolved_at timestamp' do
110
+ before = Time.now.utc
111
+ store.resolve(prediction_id, outcome: :correct)
112
+ expect(store.get(prediction_id)[:resolved_at]).to be >= before
113
+ end
114
+
115
+ it 'stores actual value when provided' do
116
+ store.resolve(prediction_id, outcome: :partial, actual: 'disk io at 80%')
117
+ expect(store.get(prediction_id)[:actual]).to eq('disk io at 80%')
118
+ end
119
+
120
+ it 'stores nil actual when not provided' do
121
+ store.resolve(prediction_id, outcome: :correct)
122
+ expect(store.get(prediction_id)[:actual]).to be_nil
123
+ end
124
+
125
+ it 'appends to outcomes array' do
126
+ store.resolve(prediction_id, outcome: :correct)
127
+ expect(store.outcomes.size).to eq(1)
128
+ end
129
+
130
+ it 'records prediction_id in the outcome entry' do
131
+ store.resolve(prediction_id, outcome: :correct)
132
+ expect(store.outcomes.last[:prediction_id]).to eq(prediction_id)
133
+ end
134
+
135
+ it 'records outcome in the outcome entry' do
136
+ store.resolve(prediction_id, outcome: :incorrect)
137
+ expect(store.outcomes.last[:outcome]).to eq(:incorrect)
138
+ end
139
+
140
+ it 'returns nil for a non-existent prediction_id' do
141
+ result = store.resolve('ghost-id', outcome: :correct)
142
+ expect(result).to be_nil
143
+ end
144
+
145
+ it 'caps outcomes array at 500 entries' do
146
+ 501.times do
147
+ id = store.store(basic_prediction.dup)
148
+ store.resolve(id, outcome: :correct)
149
+ end
150
+ expect(store.outcomes.size).to eq(500)
151
+ end
152
+ end
153
+
154
+ describe '#pending' do
155
+ it 'returns only predictions with status :pending' do
156
+ id1 = store.store(basic_prediction.dup)
157
+ id2 = store.store(basic_prediction.dup)
158
+ store.resolve(id1, outcome: :correct)
159
+
160
+ result = store.pending
161
+ expect(result.size).to eq(1)
162
+ expect(result.first[:prediction_id]).to eq(id2)
163
+ end
164
+
165
+ it 'returns empty array when no pending predictions' do
166
+ id = store.store(basic_prediction.dup)
167
+ store.resolve(id, outcome: :correct)
168
+ expect(store.pending).to be_empty
169
+ end
170
+
171
+ it 'returns all stored predictions when none are resolved' do
172
+ 3.times { store.store(basic_prediction.dup) }
173
+ expect(store.pending.size).to eq(3)
174
+ end
175
+ end
176
+
177
+ describe '#accuracy' do
178
+ it 'returns 0.0 when no outcomes exist' do
179
+ expect(store.accuracy).to eq(0.0)
180
+ end
181
+
182
+ it 'returns 1.0 when all outcomes are :correct' do
183
+ 3.times do
184
+ id = store.store(basic_prediction.dup)
185
+ store.resolve(id, outcome: :correct)
186
+ end
187
+ expect(store.accuracy).to eq(1.0)
188
+ end
189
+
190
+ it 'returns 0.0 when all outcomes are :incorrect' do
191
+ 3.times do
192
+ id = store.store(basic_prediction.dup)
193
+ store.resolve(id, outcome: :incorrect)
194
+ end
195
+ expect(store.accuracy).to eq(0.0)
196
+ end
197
+
198
+ it 'computes fractional accuracy correctly' do
199
+ 3.times do
200
+ id = store.store(basic_prediction.dup)
201
+ store.resolve(id, outcome: :correct)
202
+ end
203
+ id = store.store(basic_prediction.dup)
204
+ store.resolve(id, outcome: :incorrect)
205
+ expect(store.accuracy).to eq(0.75)
206
+ end
207
+
208
+ it 'defaults window to 100' do
209
+ 102.times do
210
+ id = store.store(basic_prediction.dup)
211
+ store.resolve(id, outcome: :incorrect)
212
+ end
213
+ 2.times do
214
+ id = store.store(basic_prediction.dup)
215
+ store.resolve(id, outcome: :correct)
216
+ end
217
+ # window=100: last 100 contain 2 correct out of 100 = 0.02
218
+ expect(store.accuracy(window: 100)).to eq(0.02)
219
+ end
220
+
221
+ it 'accepts a custom window parameter' do
222
+ 5.times do
223
+ id = store.store(basic_prediction.dup)
224
+ store.resolve(id, outcome: :incorrect)
225
+ end
226
+ 5.times do
227
+ id = store.store(basic_prediction.dup)
228
+ store.resolve(id, outcome: :correct)
229
+ end
230
+ # window=5: last 5 are all :correct
231
+ expect(store.accuracy(window: 5)).to eq(1.0)
232
+ end
233
+
234
+ it 'ignores non-:correct outcomes in numerator' do
235
+ id = store.store(basic_prediction.dup)
236
+ store.resolve(id, outcome: :partial)
237
+ id = store.store(basic_prediction.dup)
238
+ store.resolve(id, outcome: :expired)
239
+ id = store.store(basic_prediction.dup)
240
+ store.resolve(id, outcome: :correct)
241
+ expect(store.accuracy).to be_within(0.001).of(1.0 / 3.0)
242
+ end
243
+ end
244
+
245
+ describe '#count' do
246
+ it 'returns 0 for a new store' do
247
+ expect(store.count).to eq(0)
248
+ end
249
+
250
+ it 'returns the total number of stored predictions' do
251
+ 5.times { store.store(basic_prediction.dup) }
252
+ expect(store.count).to eq(5)
253
+ end
254
+
255
+ it 'counts resolved predictions as well as pending ones' do
256
+ id = store.store(basic_prediction.dup)
257
+ store.resolve(id, outcome: :correct)
258
+ store.store(basic_prediction.dup)
259
+ expect(store.count).to eq(2)
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/inference/prediction/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Inference::Prediction::Runners::Prediction do
6
+ let(:client) { Legion::Extensions::Agentic::Inference::Prediction::Client.new }
7
+
8
+ describe '#predict' do
9
+ it 'creates a prediction with valid mode' do
10
+ result = client.predict(mode: :fault_localization, description: 'test')
11
+ expect(result[:prediction_id]).to match(/\A[0-9a-f-]{36}\z/)
12
+ expect(result[:mode]).to eq(:fault_localization)
13
+ end
14
+
15
+ it 'rejects invalid mode' do
16
+ result = client.predict(mode: :invalid)
17
+ expect(result[:error]).to eq(:invalid_mode)
18
+ end
19
+
20
+ it 'marks actionable predictions above confidence threshold' do
21
+ result = client.predict(mode: :fault_localization, confidence: 0.9)
22
+ expect(result[:actionable]).to be true
23
+ end
24
+
25
+ it 'marks non-actionable predictions below threshold' do
26
+ result = client.predict(mode: :counterfactual, confidence: 0.3)
27
+ expect(result[:actionable]).to be false
28
+ end
29
+
30
+ it 'estimates confidence based on mode' do
31
+ fault = client.predict(mode: :fault_localization)
32
+ counterfactual = client.predict(mode: :counterfactual)
33
+ expect(fault[:confidence]).to be > counterfactual[:confidence]
34
+ end
35
+ end
36
+
37
+ describe '#resolve_prediction' do
38
+ it 'resolves a pending prediction' do
39
+ pred = client.predict(mode: :functional_mapping)
40
+ result = client.resolve_prediction(prediction_id: pred[:prediction_id], outcome: :correct)
41
+ expect(result[:resolved]).to be true
42
+ end
43
+
44
+ it 'returns not_found for missing prediction' do
45
+ result = client.resolve_prediction(prediction_id: 'nonexistent', outcome: :correct)
46
+ expect(result[:resolved]).to be false
47
+ end
48
+ end
49
+
50
+ describe '#pending_predictions' do
51
+ it 'lists pending predictions' do
52
+ client.predict(mode: :fault_localization)
53
+ client.predict(mode: :boundary_testing)
54
+ result = client.pending_predictions
55
+ expect(result[:count]).to eq(2)
56
+ end
57
+ end
58
+
59
+ describe '#expire_stale_predictions' do
60
+ it 'returns zero expired when no pending predictions' do
61
+ result = client.expire_stale_predictions
62
+ expect(result[:expired_count]).to eq(0)
63
+ expect(result[:remaining_pending]).to eq(0)
64
+ end
65
+
66
+ it 'expires predictions older than their horizon' do
67
+ client.predict(mode: :fault_localization)
68
+ client.predict(mode: :boundary_testing)
69
+
70
+ # Simulate staleness by back-dating created_at beyond the horizon
71
+ store = client.send(:prediction_store)
72
+ store.predictions.each_value do |pred|
73
+ pred[:created_at] = Time.now.utc - pred[:horizon] - 1
74
+ end
75
+
76
+ result = client.expire_stale_predictions
77
+ expect(result[:expired_count]).to eq(2)
78
+ expect(result[:remaining_pending]).to eq(0)
79
+ end
80
+
81
+ it 'preserves predictions that have not exceeded their horizon' do
82
+ client.predict(mode: :fault_localization)
83
+ # created_at is just now, horizon is 3600s — not stale
84
+ result = client.expire_stale_predictions
85
+ expect(result[:expired_count]).to eq(0)
86
+ expect(result[:remaining_pending]).to eq(1)
87
+ end
88
+
89
+ it 'only expires stale predictions when mixed with fresh ones' do
90
+ client.predict(mode: :fault_localization)
91
+ stale = client.predict(mode: :boundary_testing)
92
+
93
+ store = client.send(:prediction_store)
94
+ stale_pred = store.predictions[stale[:prediction_id]]
95
+ stale_pred[:created_at] = Time.now.utc - stale_pred[:horizon] - 1
96
+
97
+ result = client.expire_stale_predictions
98
+ expect(result[:expired_count]).to eq(1)
99
+ expect(result[:remaining_pending]).to eq(1)
100
+ end
101
+ end
102
+
103
+ describe '#prediction_accuracy' do
104
+ it 'computes accuracy' do
105
+ 3.times do
106
+ pred = client.predict(mode: :fault_localization)
107
+ client.resolve_prediction(prediction_id: pred[:prediction_id], outcome: :correct)
108
+ end
109
+ pred = client.predict(mode: :fault_localization)
110
+ client.resolve_prediction(prediction_id: pred[:prediction_id], outcome: :incorrect)
111
+
112
+ result = client.prediction_accuracy
113
+ expect(result[:accuracy]).to eq(0.75)
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/inference/predictive_coding/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Inference::PredictiveCoding::Client do
6
+ subject(:client) { described_class.new }
7
+
8
+ it 'responds to all runner methods' do
9
+ expect(client).to respond_to(:generate_prediction)
10
+ expect(client).to respond_to(:report_outcome)
11
+ expect(client).to respond_to(:precision_for)
12
+ expect(client).to respond_to(:surprising_errors)
13
+ expect(client).to respond_to(:free_energy_status)
14
+ expect(client).to respond_to(:active_inference_candidates)
15
+ expect(client).to respond_to(:register_active_inference)
16
+ expect(client).to respond_to(:resolve_active_inference)
17
+ expect(client).to respond_to(:update_predictive_coding)
18
+ expect(client).to respond_to(:predictive_coding_stats)
19
+ end
20
+
21
+ it 'accepts an injected generative_model' do
22
+ model = Legion::Extensions::Agentic::Inference::PredictiveCoding::Helpers::GenerativeModel.new
23
+ custom_client = described_class.new(generative_model: model)
24
+ expect(custom_client).to respond_to(:generate_prediction)
25
+ end
26
+
27
+ it 'isolates state between separate client instances' do
28
+ client_a = described_class.new
29
+ client_b = described_class.new
30
+
31
+ client_a.report_outcome(domain: :x, predicted: 0.0, actual: 1.0)
32
+ result_b = client_b.surprising_errors
33
+
34
+ expect(result_b[:count]).to eq(0)
35
+ end
36
+
37
+ describe 'full predictive coding lifecycle' do
38
+ it 'predicts, reports outcome, then updates stats correctly' do
39
+ prediction = client.generate_prediction(domain: :proprioception, context: { expected: 0.6 })
40
+ expect(prediction[:success]).to be true
41
+
42
+ outcome = client.report_outcome(domain: :proprioception, predicted: prediction[:predicted], actual: 0.65)
43
+ expect(outcome[:success]).to be true
44
+
45
+ status = client.free_energy_status
46
+ expect(status[:free_energy]).to be_a(Float)
47
+
48
+ stats = client.predictive_coding_stats
49
+ expect(stats[:model][:domain_count]).to eq(1)
50
+ end
51
+
52
+ it 'runs a full active inference cycle' do
53
+ reg = client.register_active_inference(
54
+ domain: :motor_cortex,
55
+ action: :amplify_signal,
56
+ expected_outcome: 0.75
57
+ )
58
+
59
+ expect(reg[:status]).to eq(:pending)
60
+
61
+ resolved = client.resolve_active_inference(
62
+ domain: :motor_cortex,
63
+ action: :amplify_signal,
64
+ actual_outcome: 0.78,
65
+ inference_id: reg[:inference_id]
66
+ )
67
+
68
+ expect(resolved[:success]).to be true
69
+
70
+ after_update = client.update_predictive_coding
71
+ expect(after_update[:pruned_inferences]).to eq(1)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Inference::PredictiveCoding::Helpers::GenerativeModel do
4
+ let(:model) { described_class.new }
5
+ let(:constants) { Legion::Extensions::Agentic::Inference::PredictiveCoding::Helpers::Constants }
6
+
7
+ describe '#initialize' do
8
+ it 'assigns a model_id' do
9
+ expect(model.model_id).to match(/\A[0-9a-f-]{36}\z/)
10
+ end
11
+
12
+ it 'starts with zero domain models' do
13
+ expect(model.domain_count).to eq(0)
14
+ end
15
+
16
+ it 'starts with zero errors' do
17
+ expect(model.error_count).to eq(0)
18
+ end
19
+
20
+ it 'accepts an explicit model_id' do
21
+ m = described_class.new(model_id: 'custom-id')
22
+ expect(m.model_id).to eq('custom-id')
23
+ end
24
+ end
25
+
26
+ describe '#predict' do
27
+ it 'returns a prediction hash with domain and confidence' do
28
+ result = model.predict(domain: :vision)
29
+ expect(result[:domain]).to eq(:vision)
30
+ expect(result[:predicted]).to be_a(Numeric)
31
+ expect(result[:confidence]).to be_a(Float)
32
+ end
33
+
34
+ it 'uses DEFAULT_PRECISION for an unknown domain' do
35
+ result = model.predict(domain: :new_domain)
36
+ expect(result[:confidence]).to eq(constants::DEFAULT_PRECISION)
37
+ end
38
+
39
+ it 'uses context[:expected] as initial value for unknown domain' do
40
+ result = model.predict(domain: :touch, context: { expected: 0.9 })
41
+ expect(result[:predicted]).to be_within(0.001).of(0.9)
42
+ end
43
+
44
+ it 'improves prediction after learning from updates' do
45
+ 5.times { model.update(domain: :sensor, predicted: 0.5, actual: 0.8) }
46
+ result = model.predict(domain: :sensor)
47
+ expect(result[:predicted]).to be > 0.5
48
+ end
49
+ end
50
+
51
+ describe '#update' do
52
+ it 'returns a PredictionError object' do
53
+ error = model.update(domain: :vision, predicted: 0.5, actual: 0.9)
54
+ expect(error).to be_a(Legion::Extensions::Agentic::Inference::PredictiveCoding::Helpers::PredictionError)
55
+ end
56
+
57
+ it 'increments error count' do
58
+ model.update(domain: :vision, predicted: 0.5, actual: 0.9)
59
+ expect(model.error_count).to eq(1)
60
+ end
61
+
62
+ it 'creates a domain model entry' do
63
+ model.update(domain: :vision, predicted: 0.5, actual: 0.9)
64
+ expect(model.domain_count).to eq(1)
65
+ end
66
+
67
+ it 'adjusts precision downward on high error' do
68
+ initial = model.precision_for(domain: :vision)
69
+ model.update(domain: :vision, predicted: 0.0, actual: 1.0)
70
+ expect(model.precision_for(domain: :vision)).to be < initial
71
+ end
72
+
73
+ it 'adjusts precision upward on zero error' do
74
+ # First update to initialize the domain
75
+ model.update(domain: :vision, predicted: 0.5, actual: 0.5)
76
+ # Second perfect prediction should raise precision
77
+ after_init = model.precision_for(domain: :vision)
78
+ model.update(domain: :vision, predicted: 0.5, actual: 0.5)
79
+ expect(model.precision_for(domain: :vision)).to be >= after_init
80
+ end
81
+ end
82
+
83
+ describe '#precision_for' do
84
+ it 'returns DEFAULT_PRECISION for unknown domain' do
85
+ expect(model.precision_for(domain: :unknown)).to eq(constants::DEFAULT_PRECISION)
86
+ end
87
+
88
+ it 'returns updated precision after updates' do
89
+ model.update(domain: :motor, predicted: 0.5, actual: 0.5)
90
+ expect(model.precision_for(domain: :motor)).to be_a(Float)
91
+ end
92
+ end
93
+
94
+ describe '#free_energy' do
95
+ it 'returns a float' do
96
+ expect(model.free_energy).to be_a(Float)
97
+ end
98
+
99
+ it 'increases after surprising errors' do
100
+ initial = model.free_energy
101
+ 5.times { model.update(domain: :x, predicted: 0.0, actual: 1.0) }
102
+ expect(model.free_energy).to be > initial
103
+ end
104
+ end
105
+
106
+ describe '#free_energy_level' do
107
+ it 'returns a symbol' do
108
+ expect(model.free_energy_level).to be_a(Symbol)
109
+ end
110
+
111
+ it 'returns :minimal for a fresh model' do
112
+ expect(model.free_energy_level).to eq(:minimal)
113
+ end
114
+ end
115
+
116
+ describe '#active_inference_candidates' do
117
+ it 'returns an empty array for a fresh model' do
118
+ expect(model.active_inference_candidates).to eq([])
119
+ end
120
+
121
+ it 'returns domains with high error and low precision' do
122
+ 10.times { model.update(domain: :faulty, predicted: 0.0, actual: 1.0) }
123
+ candidates = model.active_inference_candidates
124
+ expect(candidates).to include(:faulty)
125
+ end
126
+ end
127
+
128
+ describe '#surprising_errors' do
129
+ it 'returns an empty array when no surprising errors' do
130
+ model.update(domain: :x, predicted: 0.5, actual: 0.5)
131
+ expect(model.surprising_errors).to be_empty
132
+ end
133
+
134
+ it 'returns errors above the surprise threshold' do
135
+ model.update(domain: :x, predicted: 0.0, actual: 1.0)
136
+ expect(model.surprising_errors).not_to be_empty
137
+ end
138
+ end
139
+
140
+ describe '#decay_all' do
141
+ it 'decreases precision for all known domains' do
142
+ model.update(domain: :vision, predicted: 0.8, actual: 0.9)
143
+ before = model.precision_for(domain: :vision)
144
+ model.decay_all
145
+ expect(model.precision_for(domain: :vision)).to be <= before
146
+ end
147
+
148
+ it 'does not drop precision below PRECISION_FLOOR' do
149
+ 50.times { model.decay_all }
150
+ model.update(domain: :x, predicted: 0.5, actual: 0.5)
151
+ 50.times { model.decay_all }
152
+ expect(model.precision_for(domain: :x)).to be >= constants::PRECISION_FLOOR
153
+ end
154
+ end
155
+
156
+ describe '#to_h' do
157
+ it 'returns a summary hash' do
158
+ h = model.to_h
159
+ expect(h[:model_id]).to eq(model.model_id)
160
+ expect(h[:domain_count]).to be_a(Integer)
161
+ expect(h[:error_count]).to be_a(Integer)
162
+ expect(h[:free_energy]).to be_a(Float)
163
+ expect(h[:free_energy_level]).to be_a(Symbol)
164
+ expect(h[:domains]).to be_an(Array)
165
+ end
166
+
167
+ it 'includes domain stats after updates' do
168
+ model.update(domain: :vision, predicted: 0.5, actual: 0.7)
169
+ h = model.to_h
170
+ expect(h[:domain_count]).to eq(1)
171
+ vision_stat = h[:domains].find { |d| d[:domain] == :vision }
172
+ expect(vision_stat).not_to be_nil
173
+ expect(vision_stat[:mean]).to be_a(Float)
174
+ end
175
+ end
176
+
177
+ describe 'MAX_MODELS eviction' do
178
+ it 'does not exceed MAX_MODELS domains' do
179
+ (constants::MAX_MODELS + 5).times do |i|
180
+ model.update(domain: :"domain_#{i}", predicted: 0.5, actual: 0.5)
181
+ end
182
+ expect(model.domain_count).to be <= constants::MAX_MODELS
183
+ end
184
+ end
185
+
186
+ describe 'MAX_ERROR_HISTORY cap' do
187
+ it 'caps error history at MAX_ERROR_HISTORY' do
188
+ (constants::MAX_ERROR_HISTORY + 10).times do
189
+ model.update(domain: :x, predicted: 0.5, actual: 0.5)
190
+ end
191
+ expect(model.error_count).to be <= constants::MAX_ERROR_HISTORY
192
+ end
193
+ end
194
+ end