lex-agentic-executive 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 (296) 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-executive.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/executive/autopilot/client.rb +19 -0
  8. data/lib/legion/extensions/agentic/executive/autopilot/helpers/autopilot_engine.rb +161 -0
  9. data/lib/legion/extensions/agentic/executive/autopilot/helpers/constants.rb +62 -0
  10. data/lib/legion/extensions/agentic/executive/autopilot/helpers/mode_event.rb +51 -0
  11. data/lib/legion/extensions/agentic/executive/autopilot/helpers/routine.rb +91 -0
  12. data/lib/legion/extensions/agentic/executive/autopilot/runners/cognitive_autopilot.rb +93 -0
  13. data/lib/legion/extensions/agentic/executive/autopilot/version.rb +13 -0
  14. data/lib/legion/extensions/agentic/executive/autopilot.rb +20 -0
  15. data/lib/legion/extensions/agentic/executive/chunking/client.rb +21 -0
  16. data/lib/legion/extensions/agentic/executive/chunking/helpers/chunk.rb +92 -0
  17. data/lib/legion/extensions/agentic/executive/chunking/helpers/chunking_engine.rb +147 -0
  18. data/lib/legion/extensions/agentic/executive/chunking/helpers/constants.rb +56 -0
  19. data/lib/legion/extensions/agentic/executive/chunking/helpers/information_item.rb +51 -0
  20. data/lib/legion/extensions/agentic/executive/chunking/runners/cognitive_chunking.rb +111 -0
  21. data/lib/legion/extensions/agentic/executive/chunking/version.rb +13 -0
  22. data/lib/legion/extensions/agentic/executive/chunking.rb +21 -0
  23. data/lib/legion/extensions/agentic/executive/cognitive_debt/client.rb +28 -0
  24. data/lib/legion/extensions/agentic/executive/cognitive_debt/helpers/constants.rb +36 -0
  25. data/lib/legion/extensions/agentic/executive/cognitive_debt/helpers/debt_engine.rb +118 -0
  26. data/lib/legion/extensions/agentic/executive/cognitive_debt/helpers/debt_item.rb +83 -0
  27. data/lib/legion/extensions/agentic/executive/cognitive_debt/runners/cognitive_debt.rb +84 -0
  28. data/lib/legion/extensions/agentic/executive/cognitive_debt/version.rb +13 -0
  29. data/lib/legion/extensions/agentic/executive/cognitive_debt.rb +19 -0
  30. data/lib/legion/extensions/agentic/executive/compass/client.rb +15 -0
  31. data/lib/legion/extensions/agentic/executive/compass/helpers/bearing.rb +79 -0
  32. data/lib/legion/extensions/agentic/executive/compass/helpers/compass_engine.rb +108 -0
  33. data/lib/legion/extensions/agentic/executive/compass/helpers/constants.rb +65 -0
  34. data/lib/legion/extensions/agentic/executive/compass/helpers/magnetic_bias.rb +81 -0
  35. data/lib/legion/extensions/agentic/executive/compass/runners/cognitive_compass.rb +76 -0
  36. data/lib/legion/extensions/agentic/executive/compass/version.rb +13 -0
  37. data/lib/legion/extensions/agentic/executive/compass.rb +22 -0
  38. data/lib/legion/extensions/agentic/executive/control/client.rb +19 -0
  39. data/lib/legion/extensions/agentic/executive/control/helpers/constants.rb +45 -0
  40. data/lib/legion/extensions/agentic/executive/control/helpers/control_signal.rb +79 -0
  41. data/lib/legion/extensions/agentic/executive/control/helpers/controller.rb +140 -0
  42. data/lib/legion/extensions/agentic/executive/control/helpers/goal.rb +72 -0
  43. data/lib/legion/extensions/agentic/executive/control/runners/cognitive_control.rb +74 -0
  44. data/lib/legion/extensions/agentic/executive/control/version.rb +13 -0
  45. data/lib/legion/extensions/agentic/executive/control.rb +21 -0
  46. data/lib/legion/extensions/agentic/executive/decision_fatigue/client.rb +28 -0
  47. data/lib/legion/extensions/agentic/executive/decision_fatigue/helpers/constants.rb +51 -0
  48. data/lib/legion/extensions/agentic/executive/decision_fatigue/helpers/decision_record.rb +50 -0
  49. data/lib/legion/extensions/agentic/executive/decision_fatigue/helpers/fatigue_engine.rb +114 -0
  50. data/lib/legion/extensions/agentic/executive/decision_fatigue/runners/decision_fatigue.rb +94 -0
  51. data/lib/legion/extensions/agentic/executive/decision_fatigue/version.rb +13 -0
  52. data/lib/legion/extensions/agentic/executive/decision_fatigue.rb +19 -0
  53. data/lib/legion/extensions/agentic/executive/disengagement/client.rb +24 -0
  54. data/lib/legion/extensions/agentic/executive/disengagement/helpers/constants.rb +48 -0
  55. data/lib/legion/extensions/agentic/executive/disengagement/helpers/disengagement_engine.rb +101 -0
  56. data/lib/legion/extensions/agentic/executive/disengagement/helpers/goal.rb +105 -0
  57. data/lib/legion/extensions/agentic/executive/disengagement/runners/cognitive_disengagement.rb +90 -0
  58. data/lib/legion/extensions/agentic/executive/disengagement/version.rb +13 -0
  59. data/lib/legion/extensions/agentic/executive/disengagement.rb +19 -0
  60. data/lib/legion/extensions/agentic/executive/dissonance_resolution/client.rb +19 -0
  61. data/lib/legion/extensions/agentic/executive/dissonance_resolution/helpers/constants.rb +38 -0
  62. data/lib/legion/extensions/agentic/executive/dissonance_resolution/helpers/dissonance_conflict.rb +90 -0
  63. data/lib/legion/extensions/agentic/executive/dissonance_resolution/helpers/resolution_engine.rb +155 -0
  64. data/lib/legion/extensions/agentic/executive/dissonance_resolution/runners/cognitive_dissonance_resolution.rb +74 -0
  65. data/lib/legion/extensions/agentic/executive/dissonance_resolution/version.rb +13 -0
  66. data/lib/legion/extensions/agentic/executive/dissonance_resolution.rb +19 -0
  67. data/lib/legion/extensions/agentic/executive/dual_process/client.rb +25 -0
  68. data/lib/legion/extensions/agentic/executive/dual_process/helpers/constants.rb +44 -0
  69. data/lib/legion/extensions/agentic/executive/dual_process/helpers/decision.rb +50 -0
  70. data/lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb +200 -0
  71. data/lib/legion/extensions/agentic/executive/dual_process/helpers/heuristic.rb +67 -0
  72. data/lib/legion/extensions/agentic/executive/dual_process/runners/dual_process.rb +87 -0
  73. data/lib/legion/extensions/agentic/executive/dual_process/version.rb +13 -0
  74. data/lib/legion/extensions/agentic/executive/dual_process.rb +20 -0
  75. data/lib/legion/extensions/agentic/executive/dwell/client.rb +19 -0
  76. data/lib/legion/extensions/agentic/executive/dwell/helpers/constants.rb +65 -0
  77. data/lib/legion/extensions/agentic/executive/dwell/helpers/dwell_engine.rb +126 -0
  78. data/lib/legion/extensions/agentic/executive/dwell/helpers/dwell_topic.rb +119 -0
  79. data/lib/legion/extensions/agentic/executive/dwell/runners/cognitive_dwell.rb +87 -0
  80. data/lib/legion/extensions/agentic/executive/dwell/version.rb +13 -0
  81. data/lib/legion/extensions/agentic/executive/dwell.rb +19 -0
  82. data/lib/legion/extensions/agentic/executive/executive_function/actors/recovery.rb +45 -0
  83. data/lib/legion/extensions/agentic/executive/executive_function/client.rb +27 -0
  84. data/lib/legion/extensions/agentic/executive/executive_function/helpers/ef_component.rb +58 -0
  85. data/lib/legion/extensions/agentic/executive/executive_function/helpers/executive_controller.rb +129 -0
  86. data/lib/legion/extensions/agentic/executive/executive_function/runners/executive_function.rb +104 -0
  87. data/lib/legion/extensions/agentic/executive/executive_function/version.rb +13 -0
  88. data/lib/legion/extensions/agentic/executive/executive_function.rb +18 -0
  89. data/lib/legion/extensions/agentic/executive/flexibility/actors/tick.rb +31 -0
  90. data/lib/legion/extensions/agentic/executive/flexibility/client.rb +28 -0
  91. data/lib/legion/extensions/agentic/executive/flexibility/helpers/constants.rb +39 -0
  92. data/lib/legion/extensions/agentic/executive/flexibility/helpers/flexibility_engine.rb +109 -0
  93. data/lib/legion/extensions/agentic/executive/flexibility/helpers/task_set.rb +69 -0
  94. data/lib/legion/extensions/agentic/executive/flexibility/runners/cognitive_flexibility.rb +77 -0
  95. data/lib/legion/extensions/agentic/executive/flexibility/version.rb +13 -0
  96. data/lib/legion/extensions/agentic/executive/flexibility.rb +19 -0
  97. data/lib/legion/extensions/agentic/executive/flexibility_training/client.rb +29 -0
  98. data/lib/legion/extensions/agentic/executive/flexibility_training/helpers/constants.rb +57 -0
  99. data/lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb +178 -0
  100. data/lib/legion/extensions/agentic/executive/flexibility_training/helpers/switch_trial.rb +54 -0
  101. data/lib/legion/extensions/agentic/executive/flexibility_training/helpers/training_task.rb +54 -0
  102. data/lib/legion/extensions/agentic/executive/flexibility_training/runners/cognitive_flexibility_training.rb +134 -0
  103. data/lib/legion/extensions/agentic/executive/flexibility_training/version.rb +13 -0
  104. data/lib/legion/extensions/agentic/executive/flexibility_training.rb +20 -0
  105. data/lib/legion/extensions/agentic/executive/goal_management/client.rb +28 -0
  106. data/lib/legion/extensions/agentic/executive/goal_management/helpers/constants.rb +49 -0
  107. data/lib/legion/extensions/agentic/executive/goal_management/helpers/goal.rb +153 -0
  108. data/lib/legion/extensions/agentic/executive/goal_management/helpers/goal_engine.rb +265 -0
  109. data/lib/legion/extensions/agentic/executive/goal_management/runners/goal_management.rb +169 -0
  110. data/lib/legion/extensions/agentic/executive/goal_management/version.rb +13 -0
  111. data/lib/legion/extensions/agentic/executive/goal_management.rb +19 -0
  112. data/lib/legion/extensions/agentic/executive/inertia/client.rb +15 -0
  113. data/lib/legion/extensions/agentic/executive/inertia/helpers/belief.rb +99 -0
  114. data/lib/legion/extensions/agentic/executive/inertia/helpers/constants.rb +45 -0
  115. data/lib/legion/extensions/agentic/executive/inertia/helpers/inertia_engine.rb +111 -0
  116. data/lib/legion/extensions/agentic/executive/inertia/runners/cognitive_inertia.rb +74 -0
  117. data/lib/legion/extensions/agentic/executive/inertia/version.rb +13 -0
  118. data/lib/legion/extensions/agentic/executive/inertia.rb +19 -0
  119. data/lib/legion/extensions/agentic/executive/inhibition/client.rb +27 -0
  120. data/lib/legion/extensions/agentic/executive/inhibition/helpers/constants.rb +36 -0
  121. data/lib/legion/extensions/agentic/executive/inhibition/helpers/impulse.rb +37 -0
  122. data/lib/legion/extensions/agentic/executive/inhibition/helpers/inhibition_model.rb +122 -0
  123. data/lib/legion/extensions/agentic/executive/inhibition/helpers/inhibition_store.rb +72 -0
  124. data/lib/legion/extensions/agentic/executive/inhibition/runners/inhibition.rb +155 -0
  125. data/lib/legion/extensions/agentic/executive/inhibition/version.rb +13 -0
  126. data/lib/legion/extensions/agentic/executive/inhibition.rb +20 -0
  127. data/lib/legion/extensions/agentic/executive/load/client.rb +25 -0
  128. data/lib/legion/extensions/agentic/executive/load/helpers/constants.rb +36 -0
  129. data/lib/legion/extensions/agentic/executive/load/helpers/load_model.rb +146 -0
  130. data/lib/legion/extensions/agentic/executive/load/runners/cognitive_load.rb +120 -0
  131. data/lib/legion/extensions/agentic/executive/load/version.rb +13 -0
  132. data/lib/legion/extensions/agentic/executive/load.rb +18 -0
  133. data/lib/legion/extensions/agentic/executive/load_balancing/client.rb +19 -0
  134. data/lib/legion/extensions/agentic/executive/load_balancing/helpers/constants.rb +44 -0
  135. data/lib/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer.rb +137 -0
  136. data/lib/legion/extensions/agentic/executive/load_balancing/helpers/subsystem.rb +101 -0
  137. data/lib/legion/extensions/agentic/executive/load_balancing/runners/cognitive_load_balancing.rb +69 -0
  138. data/lib/legion/extensions/agentic/executive/load_balancing/version.rb +13 -0
  139. data/lib/legion/extensions/agentic/executive/load_balancing.rb +19 -0
  140. data/lib/legion/extensions/agentic/executive/planning/client.rb +27 -0
  141. data/lib/legion/extensions/agentic/executive/planning/helpers/constants.rb +26 -0
  142. data/lib/legion/extensions/agentic/executive/planning/helpers/plan.rb +110 -0
  143. data/lib/legion/extensions/agentic/executive/planning/helpers/plan_step.rb +82 -0
  144. data/lib/legion/extensions/agentic/executive/planning/helpers/plan_store.rb +161 -0
  145. data/lib/legion/extensions/agentic/executive/planning/runners/planning.rb +123 -0
  146. data/lib/legion/extensions/agentic/executive/planning/version.rb +13 -0
  147. data/lib/legion/extensions/agentic/executive/planning.rb +20 -0
  148. data/lib/legion/extensions/agentic/executive/prospective_memory/client.rb +28 -0
  149. data/lib/legion/extensions/agentic/executive/prospective_memory/helpers/constants.rb +32 -0
  150. data/lib/legion/extensions/agentic/executive/prospective_memory/helpers/intention.rb +94 -0
  151. data/lib/legion/extensions/agentic/executive/prospective_memory/helpers/prospective_engine.rb +157 -0
  152. data/lib/legion/extensions/agentic/executive/prospective_memory/runners/prospective_memory.rb +146 -0
  153. data/lib/legion/extensions/agentic/executive/prospective_memory/version.rb +13 -0
  154. data/lib/legion/extensions/agentic/executive/prospective_memory.rb +19 -0
  155. data/lib/legion/extensions/agentic/executive/triage/client.rb +19 -0
  156. data/lib/legion/extensions/agentic/executive/triage/helpers/constants.rb +70 -0
  157. data/lib/legion/extensions/agentic/executive/triage/helpers/demand.rb +101 -0
  158. data/lib/legion/extensions/agentic/executive/triage/helpers/triage_engine.rb +150 -0
  159. data/lib/legion/extensions/agentic/executive/triage/runners/cognitive_triage.rb +110 -0
  160. data/lib/legion/extensions/agentic/executive/triage/version.rb +13 -0
  161. data/lib/legion/extensions/agentic/executive/triage.rb +19 -0
  162. data/lib/legion/extensions/agentic/executive/version.rb +11 -0
  163. data/lib/legion/extensions/agentic/executive/volition/client.rb +27 -0
  164. data/lib/legion/extensions/agentic/executive/volition/helpers/constants.rb +51 -0
  165. data/lib/legion/extensions/agentic/executive/volition/helpers/drive_synthesizer.rb +158 -0
  166. data/lib/legion/extensions/agentic/executive/volition/helpers/intention.rb +56 -0
  167. data/lib/legion/extensions/agentic/executive/volition/helpers/intention_stack.rb +140 -0
  168. data/lib/legion/extensions/agentic/executive/volition/runners/volition.rb +129 -0
  169. data/lib/legion/extensions/agentic/executive/volition/version.rb +13 -0
  170. data/lib/legion/extensions/agentic/executive/volition.rb +20 -0
  171. data/lib/legion/extensions/agentic/executive/working_memory/client.rb +21 -0
  172. data/lib/legion/extensions/agentic/executive/working_memory/helpers/buffer.rb +124 -0
  173. data/lib/legion/extensions/agentic/executive/working_memory/helpers/buffer_item.rb +72 -0
  174. data/lib/legion/extensions/agentic/executive/working_memory/helpers/constants.rb +47 -0
  175. data/lib/legion/extensions/agentic/executive/working_memory/runners/working_memory.rb +102 -0
  176. data/lib/legion/extensions/agentic/executive/working_memory/version.rb +13 -0
  177. data/lib/legion/extensions/agentic/executive/working_memory.rb +19 -0
  178. data/lib/legion/extensions/agentic/executive.rb +40 -0
  179. data/spec/legion/extensions/agentic/executive/autopilot/client_spec.rb +21 -0
  180. data/spec/legion/extensions/agentic/executive/autopilot/cognitive_autopilot_spec.rb +7 -0
  181. data/spec/legion/extensions/agentic/executive/autopilot/helpers/autopilot_engine_spec.rb +166 -0
  182. data/spec/legion/extensions/agentic/executive/autopilot/helpers/constants_spec.rb +37 -0
  183. data/spec/legion/extensions/agentic/executive/autopilot/helpers/mode_event_spec.rb +30 -0
  184. data/spec/legion/extensions/agentic/executive/autopilot/helpers/routine_spec.rb +133 -0
  185. data/spec/legion/extensions/agentic/executive/autopilot/runners_spec.rb +108 -0
  186. data/spec/legion/extensions/agentic/executive/chunking/client_spec.rb +67 -0
  187. data/spec/legion/extensions/agentic/executive/chunking/helpers/chunk_spec.rb +187 -0
  188. data/spec/legion/extensions/agentic/executive/chunking/helpers/chunking_engine_spec.rb +290 -0
  189. data/spec/legion/extensions/agentic/executive/chunking/helpers/constants_spec.rb +116 -0
  190. data/spec/legion/extensions/agentic/executive/chunking/helpers/information_item_spec.rb +75 -0
  191. data/spec/legion/extensions/agentic/executive/chunking/runners/cognitive_chunking_spec.rb +169 -0
  192. data/spec/legion/extensions/agentic/executive/cognitive_debt/client_spec.rb +73 -0
  193. data/spec/legion/extensions/agentic/executive/cognitive_debt/cognitive_debt_spec.rb +15 -0
  194. data/spec/legion/extensions/agentic/executive/cognitive_debt/helpers/constants_spec.rb +78 -0
  195. data/spec/legion/extensions/agentic/executive/cognitive_debt/helpers/debt_engine_spec.rb +297 -0
  196. data/spec/legion/extensions/agentic/executive/cognitive_debt/helpers/debt_item_spec.rb +233 -0
  197. data/spec/legion/extensions/agentic/executive/cognitive_debt/runners/cognitive_debt_spec.rb +196 -0
  198. data/spec/legion/extensions/agentic/executive/compass/client_spec.rb +16 -0
  199. data/spec/legion/extensions/agentic/executive/compass/helpers/bearing_spec.rb +93 -0
  200. data/spec/legion/extensions/agentic/executive/compass/helpers/compass_engine_spec.rb +113 -0
  201. data/spec/legion/extensions/agentic/executive/compass/helpers/constants_spec.rb +45 -0
  202. data/spec/legion/extensions/agentic/executive/compass/helpers/magnetic_bias_spec.rb +103 -0
  203. data/spec/legion/extensions/agentic/executive/compass/runners/cognitive_compass_spec.rb +80 -0
  204. data/spec/legion/extensions/agentic/executive/control/client_spec.rb +23 -0
  205. data/spec/legion/extensions/agentic/executive/control/helpers/control_signal_spec.rb +118 -0
  206. data/spec/legion/extensions/agentic/executive/control/helpers/controller_spec.rb +167 -0
  207. data/spec/legion/extensions/agentic/executive/control/helpers/goal_spec.rb +99 -0
  208. data/spec/legion/extensions/agentic/executive/control/runners/cognitive_control_spec.rb +107 -0
  209. data/spec/legion/extensions/agentic/executive/decision_fatigue/client_spec.rb +24 -0
  210. data/spec/legion/extensions/agentic/executive/decision_fatigue/helpers/constants_spec.rb +93 -0
  211. data/spec/legion/extensions/agentic/executive/decision_fatigue/helpers/decision_record_spec.rb +89 -0
  212. data/spec/legion/extensions/agentic/executive/decision_fatigue/helpers/fatigue_engine_spec.rb +216 -0
  213. data/spec/legion/extensions/agentic/executive/decision_fatigue/runners/decision_fatigue_spec.rb +180 -0
  214. data/spec/legion/extensions/agentic/executive/disengagement/helpers/constants_spec.rb +81 -0
  215. data/spec/legion/extensions/agentic/executive/disengagement/helpers/disengagement_engine_spec.rb +213 -0
  216. data/spec/legion/extensions/agentic/executive/disengagement/helpers/goal_spec.rb +289 -0
  217. data/spec/legion/extensions/agentic/executive/disengagement/runners/cognitive_disengagement_spec.rb +215 -0
  218. data/spec/legion/extensions/agentic/executive/dissonance_resolution/client_spec.rb +20 -0
  219. data/spec/legion/extensions/agentic/executive/dissonance_resolution/helpers/dissonance_conflict_spec.rb +107 -0
  220. data/spec/legion/extensions/agentic/executive/dissonance_resolution/helpers/resolution_engine_spec.rb +122 -0
  221. data/spec/legion/extensions/agentic/executive/dissonance_resolution/runners/cognitive_dissonance_resolution_spec.rb +49 -0
  222. data/spec/legion/extensions/agentic/executive/dual_process/client_spec.rb +74 -0
  223. data/spec/legion/extensions/agentic/executive/dual_process/helpers/constants_spec.rb +55 -0
  224. data/spec/legion/extensions/agentic/executive/dual_process/helpers/decision_spec.rb +76 -0
  225. data/spec/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine_spec.rb +274 -0
  226. data/spec/legion/extensions/agentic/executive/dual_process/helpers/heuristic_spec.rb +144 -0
  227. data/spec/legion/extensions/agentic/executive/dual_process/runners/dual_process_spec.rb +188 -0
  228. data/spec/legion/extensions/agentic/executive/dwell/cognitive_dwell_spec.rb +7 -0
  229. data/spec/legion/extensions/agentic/executive/dwell/helpers/dwell_engine_spec.rb +136 -0
  230. data/spec/legion/extensions/agentic/executive/dwell/helpers/dwell_topic_spec.rb +152 -0
  231. data/spec/legion/extensions/agentic/executive/executive_function/client_spec.rb +40 -0
  232. data/spec/legion/extensions/agentic/executive/executive_function/helpers/ef_component_spec.rb +108 -0
  233. data/spec/legion/extensions/agentic/executive/executive_function/helpers/executive_controller_spec.rb +136 -0
  234. data/spec/legion/extensions/agentic/executive/executive_function/runners/executive_function_spec.rb +191 -0
  235. data/spec/legion/extensions/agentic/executive/flexibility/client_spec.rb +20 -0
  236. data/spec/legion/extensions/agentic/executive/flexibility/helpers/flexibility_engine_spec.rb +119 -0
  237. data/spec/legion/extensions/agentic/executive/flexibility/helpers/task_set_spec.rb +87 -0
  238. data/spec/legion/extensions/agentic/executive/flexibility/runners/cognitive_flexibility_spec.rb +69 -0
  239. data/spec/legion/extensions/agentic/executive/flexibility_training/client_spec.rb +39 -0
  240. data/spec/legion/extensions/agentic/executive/flexibility_training/helpers/constants_spec.rb +67 -0
  241. data/spec/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine_spec.rb +209 -0
  242. data/spec/legion/extensions/agentic/executive/flexibility_training/helpers/switch_trial_spec.rb +77 -0
  243. data/spec/legion/extensions/agentic/executive/flexibility_training/helpers/training_task_spec.rb +97 -0
  244. data/spec/legion/extensions/agentic/executive/flexibility_training/runners/cognitive_flexibility_training_spec.rb +171 -0
  245. data/spec/legion/extensions/agentic/executive/goal_management/client_spec.rb +34 -0
  246. data/spec/legion/extensions/agentic/executive/goal_management/goal_management_spec.rb +11 -0
  247. data/spec/legion/extensions/agentic/executive/goal_management/helpers/constants_spec.rb +94 -0
  248. data/spec/legion/extensions/agentic/executive/goal_management/helpers/goal_engine_spec.rb +358 -0
  249. data/spec/legion/extensions/agentic/executive/goal_management/helpers/goal_spec.rb +283 -0
  250. data/spec/legion/extensions/agentic/executive/goal_management/runners/goal_management_spec.rb +244 -0
  251. data/spec/legion/extensions/agentic/executive/inertia/helpers/belief_spec.rb +128 -0
  252. data/spec/legion/extensions/agentic/executive/inertia/helpers/inertia_engine_spec.rb +104 -0
  253. data/spec/legion/extensions/agentic/executive/inertia/runners/cognitive_inertia_spec.rb +59 -0
  254. data/spec/legion/extensions/agentic/executive/inhibition/client_spec.rb +43 -0
  255. data/spec/legion/extensions/agentic/executive/inhibition/helpers/constants_spec.rb +108 -0
  256. data/spec/legion/extensions/agentic/executive/inhibition/helpers/impulse_spec.rb +101 -0
  257. data/spec/legion/extensions/agentic/executive/inhibition/helpers/inhibition_model_spec.rb +245 -0
  258. data/spec/legion/extensions/agentic/executive/inhibition/helpers/inhibition_store_spec.rb +126 -0
  259. data/spec/legion/extensions/agentic/executive/inhibition/runners/inhibition_spec.rb +242 -0
  260. data/spec/legion/extensions/agentic/executive/load/client_spec.rb +94 -0
  261. data/spec/legion/extensions/agentic/executive/load/helpers/constants_spec.rb +62 -0
  262. data/spec/legion/extensions/agentic/executive/load/helpers/load_model_spec.rb +314 -0
  263. data/spec/legion/extensions/agentic/executive/load/runners/cognitive_load_spec.rb +231 -0
  264. data/spec/legion/extensions/agentic/executive/load_balancing/client_spec.rb +20 -0
  265. data/spec/legion/extensions/agentic/executive/load_balancing/helpers/load_balancer_spec.rb +106 -0
  266. data/spec/legion/extensions/agentic/executive/load_balancing/helpers/subsystem_spec.rb +106 -0
  267. data/spec/legion/extensions/agentic/executive/load_balancing/runners/cognitive_load_balancing_spec.rb +52 -0
  268. data/spec/legion/extensions/agentic/executive/planning/client_spec.rb +91 -0
  269. data/spec/legion/extensions/agentic/executive/planning/helpers/constants_spec.rb +91 -0
  270. data/spec/legion/extensions/agentic/executive/planning/helpers/plan_spec.rb +230 -0
  271. data/spec/legion/extensions/agentic/executive/planning/helpers/plan_step_spec.rb +159 -0
  272. data/spec/legion/extensions/agentic/executive/planning/helpers/plan_store_spec.rb +317 -0
  273. data/spec/legion/extensions/agentic/executive/planning/runners/planning_spec.rb +217 -0
  274. data/spec/legion/extensions/agentic/executive/prospective_memory/client_spec.rb +24 -0
  275. data/spec/legion/extensions/agentic/executive/prospective_memory/helpers/constants_spec.rb +84 -0
  276. data/spec/legion/extensions/agentic/executive/prospective_memory/helpers/intention_spec.rb +194 -0
  277. data/spec/legion/extensions/agentic/executive/prospective_memory/helpers/prospective_engine_spec.rb +255 -0
  278. data/spec/legion/extensions/agentic/executive/prospective_memory/runners/prospective_memory_spec.rb +220 -0
  279. data/spec/legion/extensions/agentic/executive/triage/client_spec.rb +28 -0
  280. data/spec/legion/extensions/agentic/executive/triage/cognitive_triage_spec.rb +7 -0
  281. data/spec/legion/extensions/agentic/executive/triage/helpers/constants_spec.rb +41 -0
  282. data/spec/legion/extensions/agentic/executive/triage/helpers/demand_spec.rb +139 -0
  283. data/spec/legion/extensions/agentic/executive/triage/helpers/triage_engine_spec.rb +183 -0
  284. data/spec/legion/extensions/agentic/executive/triage/runners_spec.rb +127 -0
  285. data/spec/legion/extensions/agentic/executive/volition/client_spec.rb +25 -0
  286. data/spec/legion/extensions/agentic/executive/volition/helpers/drive_synthesizer_spec.rb +99 -0
  287. data/spec/legion/extensions/agentic/executive/volition/helpers/intention_spec.rb +93 -0
  288. data/spec/legion/extensions/agentic/executive/volition/helpers/intention_stack_spec.rb +129 -0
  289. data/spec/legion/extensions/agentic/executive/volition/runners/volition_spec.rb +135 -0
  290. data/spec/legion/extensions/agentic/executive/working_memory/client_spec.rb +93 -0
  291. data/spec/legion/extensions/agentic/executive/working_memory/helpers/buffer_item_spec.rb +185 -0
  292. data/spec/legion/extensions/agentic/executive/working_memory/helpers/buffer_spec.rb +232 -0
  293. data/spec/legion/extensions/agentic/executive/working_memory/helpers/constants_spec.rb +99 -0
  294. data/spec/legion/extensions/agentic/executive/working_memory/runners/working_memory_spec.rb +191 -0
  295. data/spec/spec_helper.rb +46 -0
  296. metadata +380 -0
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module Control
8
+ module Helpers
9
+ module Constants
10
+ MAX_GOALS = 20
11
+ MAX_POLICIES = 50
12
+ MAX_HISTORY = 200
13
+
14
+ DEFAULT_EFFORT = 0.5
15
+ EFFORT_FLOOR = 0.1
16
+ EFFORT_CEILING = 1.0
17
+ EFFORT_DECAY = 0.02
18
+ EFFORT_RECOVERY = 0.03
19
+
20
+ AUTOMATIC_THRESHOLD = 0.3
21
+ CONTROLLED_THRESHOLD = 0.6
22
+ OVERRIDE_THRESHOLD = 0.8
23
+
24
+ CONFLICT_BOOST = 0.2
25
+ ERROR_BOOST = 0.15
26
+ NOVELTY_BOOST = 0.1
27
+ ADAPTATION_ALPHA = 0.1
28
+
29
+ CONTROL_MODES = %i[automatic controlled override].freeze
30
+ GOAL_STATES = %i[active suspended completed abandoned].freeze
31
+
32
+ EFFORT_LABELS = {
33
+ (0.8..) => :maximal,
34
+ (0.6...0.8) => :effortful,
35
+ (0.4...0.6) => :moderate,
36
+ (0.2...0.4) => :low,
37
+ (..0.2) => :automatic
38
+ }.freeze
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module Control
8
+ module Helpers
9
+ class ControlSignal
10
+ include Constants
11
+
12
+ attr_reader :effort_level, :conflict_detected, :error_detected,
13
+ :novelty_detected
14
+
15
+ def initialize
16
+ @effort_level = DEFAULT_EFFORT
17
+ @conflict_detected = false
18
+ @error_detected = false
19
+ @novelty_detected = false
20
+ end
21
+
22
+ def detect_conflict
23
+ @conflict_detected = true
24
+ @effort_level = [@effort_level + CONFLICT_BOOST, EFFORT_CEILING].min
25
+ end
26
+
27
+ def detect_error
28
+ @error_detected = true
29
+ @effort_level = [@effort_level + ERROR_BOOST, EFFORT_CEILING].min
30
+ end
31
+
32
+ def detect_novelty
33
+ @novelty_detected = true
34
+ @effort_level = [@effort_level + NOVELTY_BOOST, EFFORT_CEILING].min
35
+ end
36
+
37
+ def reset_detections
38
+ @conflict_detected = false
39
+ @error_detected = false
40
+ @novelty_detected = false
41
+ end
42
+
43
+ def mode
44
+ return :override if @effort_level >= OVERRIDE_THRESHOLD
45
+ return :controlled if @effort_level >= CONTROLLED_THRESHOLD
46
+
47
+ :automatic
48
+ end
49
+
50
+ def effort_label
51
+ EFFORT_LABELS.each { |range, lbl| return lbl if range.cover?(@effort_level) }
52
+ :automatic
53
+ end
54
+
55
+ def decay
56
+ @effort_level = [@effort_level - EFFORT_DECAY, EFFORT_FLOOR].max
57
+ end
58
+
59
+ def recover(amount: EFFORT_RECOVERY)
60
+ @effort_level = [@effort_level + amount, EFFORT_CEILING].min
61
+ end
62
+
63
+ def to_h
64
+ {
65
+ effort_level: @effort_level.round(4),
66
+ mode: mode,
67
+ effort_label: effort_label,
68
+ conflict_detected: @conflict_detected,
69
+ error_detected: @error_detected,
70
+ novelty_detected: @novelty_detected
71
+ }
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module Control
8
+ module Helpers
9
+ class Controller
10
+ include Constants
11
+
12
+ attr_reader :goals, :signal, :history
13
+
14
+ def initialize
15
+ @goals = {}
16
+ @counter = 0
17
+ @signal = ControlSignal.new
18
+ @history = []
19
+ end
20
+
21
+ def set_goal(description:, domain: :general, priority: 0.5)
22
+ return nil if @goals.size >= MAX_GOALS
23
+
24
+ @counter += 1
25
+ goal_id = :"goal_#{@counter}"
26
+ goal = Goal.new(id: goal_id, description: description, domain: domain, priority: priority)
27
+ @goals[goal_id] = goal
28
+ goal
29
+ end
30
+
31
+ def advance_goal(goal_id:, amount: 0.1)
32
+ goal = @goals[goal_id]
33
+ return nil unless goal
34
+
35
+ goal.advance(amount: amount)
36
+ end
37
+
38
+ def suspend_goal(goal_id:)
39
+ goal = @goals[goal_id]
40
+ return nil unless goal
41
+
42
+ goal.suspend!
43
+ end
44
+
45
+ def resume_goal(goal_id:)
46
+ goal = @goals[goal_id]
47
+ return nil unless goal
48
+
49
+ goal.resume!
50
+ end
51
+
52
+ def abandon_goal(goal_id:)
53
+ goal = @goals[goal_id]
54
+ return nil unless goal
55
+
56
+ goal.abandon!
57
+ end
58
+
59
+ def evaluate_control_demand(conflict: false, error: false, novelty: false)
60
+ @signal.reset_detections
61
+ @signal.detect_conflict if conflict
62
+ @signal.detect_error if error
63
+ @signal.detect_novelty if novelty
64
+ record_evaluation
65
+ @signal.to_h
66
+ end
67
+
68
+ def current_mode
69
+ @signal.mode
70
+ end
71
+
72
+ def should_override?
73
+ @signal.mode == :override
74
+ end
75
+
76
+ def should_control?
77
+ %i[controlled override].include?(@signal.mode)
78
+ end
79
+
80
+ def active_goals
81
+ @goals.values.select(&:active?).sort_by { |g| -g.priority }.map(&:to_h)
82
+ end
83
+
84
+ def top_goal
85
+ active = @goals.values.select(&:active?)
86
+ return nil if active.empty?
87
+
88
+ active.max_by(&:priority).to_h
89
+ end
90
+
91
+ def goal_conflict?
92
+ active = @goals.values.select(&:active?)
93
+ return false if active.size < 2
94
+
95
+ priorities = active.map(&:priority)
96
+ (priorities.max - priorities.min) < 0.2 && active.size > 1
97
+ end
98
+
99
+ def tick
100
+ @signal.decay
101
+ check_goal_conflicts
102
+ @signal.to_h
103
+ end
104
+
105
+ def to_h
106
+ {
107
+ goal_count: @goals.size,
108
+ active_goals: @goals.values.count(&:active?),
109
+ effort_level: @signal.effort_level.round(4),
110
+ mode: current_mode,
111
+ effort_label: @signal.effort_label,
112
+ goal_conflict: goal_conflict?,
113
+ history_size: @history.size
114
+ }
115
+ end
116
+
117
+ private
118
+
119
+ def check_goal_conflicts
120
+ @signal.detect_conflict if goal_conflict?
121
+ end
122
+
123
+ def record_evaluation
124
+ @history << {
125
+ mode: @signal.mode,
126
+ effort: @signal.effort_level.round(4),
127
+ conflict: @signal.conflict_detected,
128
+ error: @signal.error_detected,
129
+ novelty: @signal.novelty_detected,
130
+ at: Time.now.utc
131
+ }
132
+ @history.shift while @history.size > MAX_HISTORY
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module Control
8
+ module Helpers
9
+ class Goal
10
+ include Constants
11
+
12
+ attr_reader :id, :description, :domain, :priority, :state, :progress, :created_at
13
+
14
+ def initialize(id:, description:, domain: :general, priority: 0.5)
15
+ @id = id
16
+ @description = description
17
+ @domain = domain
18
+ @priority = priority.to_f.clamp(0.0, 1.0)
19
+ @state = :active
20
+ @progress = 0.0
21
+ @created_at = Time.now.utc
22
+ end
23
+
24
+ def advance(amount: 0.1)
25
+ return nil unless @state == :active
26
+
27
+ @progress = [@progress + amount, 1.0].min
28
+ complete! if @progress >= 1.0
29
+ @progress
30
+ end
31
+
32
+ def complete!
33
+ @state = :completed
34
+ end
35
+
36
+ def suspend!
37
+ @state = :suspended if @state == :active
38
+ end
39
+
40
+ def resume!
41
+ @state = :active if @state == :suspended
42
+ end
43
+
44
+ def abandon!
45
+ @state = :abandoned unless @state == :completed
46
+ end
47
+
48
+ def active?
49
+ @state == :active
50
+ end
51
+
52
+ def completed?
53
+ @state == :completed
54
+ end
55
+
56
+ def to_h
57
+ {
58
+ id: @id,
59
+ description: @description,
60
+ domain: @domain,
61
+ priority: @priority.round(4),
62
+ state: @state,
63
+ progress: @progress.round(4)
64
+ }
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module Control
8
+ module Runners
9
+ module CognitiveControl
10
+ include Helpers::Constants
11
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
12
+
13
+ def set_control_goal(description:, domain: :general, priority: 0.5, **)
14
+ goal = controller.set_goal(description: description, domain: domain, priority: priority)
15
+ return { success: false, reason: :limit_reached } unless goal
16
+
17
+ { success: true, goal_id: goal.id, priority: goal.priority }
18
+ end
19
+
20
+ def advance_control_goal(goal_id:, amount: 0.1, **)
21
+ result = controller.advance_goal(goal_id: goal_id, amount: amount)
22
+ return { success: false, reason: :not_found } unless result
23
+
24
+ { success: true, goal_id: goal_id, progress: result.round(4) }
25
+ end
26
+
27
+ def suspend_control_goal(goal_id:, **)
28
+ controller.suspend_goal(goal_id: goal_id)
29
+ { success: true, goal_id: goal_id }
30
+ end
31
+
32
+ def evaluate_control(conflict: false, error: false, novelty: false, **)
33
+ result = controller.evaluate_control_demand(conflict: conflict, error: error, novelty: novelty)
34
+ { success: true }.merge(result)
35
+ end
36
+
37
+ def current_control_mode(**)
38
+ { success: true, mode: controller.current_mode, should_override: controller.should_override?,
39
+ should_control: controller.should_control? }
40
+ end
41
+
42
+ def active_control_goals(**)
43
+ goals = controller.active_goals
44
+ { success: true, goals: goals, count: goals.size }
45
+ end
46
+
47
+ def top_control_goal(**)
48
+ goal = controller.top_goal
49
+ return { success: false, reason: :no_active_goals } unless goal
50
+
51
+ { success: true }.merge(goal)
52
+ end
53
+
54
+ def update_cognitive_control(**)
55
+ result = controller.tick
56
+ { success: true }.merge(result)
57
+ end
58
+
59
+ def cognitive_control_stats(**)
60
+ { success: true }.merge(controller.to_h)
61
+ end
62
+
63
+ private
64
+
65
+ def controller
66
+ @controller ||= Helpers::Controller.new
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module Control
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'control/version'
4
+ require_relative 'control/helpers/constants'
5
+ require_relative 'control/helpers/control_signal'
6
+ require_relative 'control/helpers/controller'
7
+ require_relative 'control/helpers/goal'
8
+ require_relative 'control/runners/cognitive_control'
9
+ require_relative 'control/client'
10
+
11
+ module Legion
12
+ module Extensions
13
+ module Agentic
14
+ module Executive
15
+ module Control
16
+ # Sub-module for cognitive control: conflict monitoring and adaptive control signals
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/executive/decision_fatigue/helpers/constants'
4
+ require 'legion/extensions/agentic/executive/decision_fatigue/helpers/decision_record'
5
+ require 'legion/extensions/agentic/executive/decision_fatigue/helpers/fatigue_engine'
6
+ require 'legion/extensions/agentic/executive/decision_fatigue/runners/decision_fatigue'
7
+
8
+ module Legion
9
+ module Extensions
10
+ module Agentic
11
+ module Executive
12
+ module DecisionFatigue
13
+ class Client
14
+ include Runners::DecisionFatigue
15
+
16
+ def initialize(**)
17
+ @fatigue_engine = Helpers::FatigueEngine.new
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :fatigue_engine
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module DecisionFatigue
8
+ module Helpers
9
+ module Constants
10
+ MAX_DECISIONS = 500
11
+ DEFAULT_WILLPOWER = 1.0
12
+ DEPLETION_RATE = 0.05
13
+ RECOVERY_RATE = 0.08
14
+ QUALITY_FLOOR = 0.2
15
+
16
+ QUALITY_LABELS = [
17
+ { range: (0.85..1.0), label: :optimal },
18
+ { range: (0.65..0.85), label: :good },
19
+ { range: (0.45..0.65), label: :adequate },
20
+ { range: (0.25..0.45), label: :compromised },
21
+ { range: (0.0..0.25), label: :depleted }
22
+ ].freeze
23
+
24
+ DECISION_TYPES = %i[analytical evaluative creative routine social moral].freeze
25
+
26
+ COMPLEXITY_LABELS = [
27
+ { range: (0.0..0.2), label: :trivial },
28
+ { range: (0.2..0.4), label: :simple },
29
+ { range: (0.4..0.6), label: :moderate },
30
+ { range: (0.6..0.8), label: :complex },
31
+ { range: (0.8..1.0), label: :overwhelming }
32
+ ].freeze
33
+
34
+ module_function
35
+
36
+ def quality_label_for(value)
37
+ entry = QUALITY_LABELS.find { |e| e[:range].cover?(value) }
38
+ entry ? entry[:label] : :depleted
39
+ end
40
+
41
+ def complexity_label_for(value)
42
+ entry = COMPLEXITY_LABELS.find { |e| e[:range].cover?(value) }
43
+ entry ? entry[:label] : :overwhelming
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module DecisionFatigue
8
+ module Helpers
9
+ class DecisionRecord
10
+ attr_reader :id, :label, :decision_type, :complexity,
11
+ :quality_at_time, :willpower_cost, :created_at
12
+
13
+ def initialize(id:, label:, decision_type:, complexity:, quality_at_time:, willpower_cost:)
14
+ @id = id
15
+ @label = label
16
+ @decision_type = decision_type
17
+ @complexity = complexity.clamp(0.0, 1.0)
18
+ @quality_at_time = quality_at_time.clamp(Constants::QUALITY_FLOOR, 1.0)
19
+ @willpower_cost = willpower_cost
20
+ @created_at = Time.now.utc
21
+ end
22
+
23
+ def complexity_label
24
+ Constants.complexity_label_for(@complexity)
25
+ end
26
+
27
+ def quality_label
28
+ Constants.quality_label_for(@quality_at_time)
29
+ end
30
+
31
+ def to_h
32
+ {
33
+ id: @id,
34
+ label: @label,
35
+ decision_type: @decision_type,
36
+ complexity: @complexity,
37
+ complexity_label: complexity_label,
38
+ quality_at_time: @quality_at_time,
39
+ quality_label: quality_label,
40
+ willpower_cost: @willpower_cost,
41
+ created_at: @created_at
42
+ }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Executive
7
+ module DecisionFatigue
8
+ module Helpers
9
+ class FatigueEngine
10
+ attr_reader :willpower, :total_decisions, :session_start
11
+
12
+ def initialize
13
+ @decisions = []
14
+ @willpower = Constants::DEFAULT_WILLPOWER
15
+ @total_decisions = 0
16
+ @session_start = Time.now.utc
17
+ @next_id = 1
18
+ end
19
+
20
+ def make_decision(label:, decision_type: :routine, complexity: 0.5)
21
+ complexity = complexity.clamp(0.0, 1.0)
22
+ cost = complexity * Constants::DEPLETION_RATE
23
+ @willpower = [@willpower - cost, Constants::QUALITY_FLOOR].max
24
+
25
+ record = DecisionRecord.new(
26
+ id: @next_id,
27
+ label: label,
28
+ decision_type: decision_type,
29
+ complexity: complexity,
30
+ quality_at_time: current_quality,
31
+ willpower_cost: cost
32
+ )
33
+
34
+ @next_id += 1
35
+ @total_decisions += 1
36
+ @decisions << record
37
+ @decisions.shift while @decisions.size > Constants::MAX_DECISIONS
38
+
39
+ record
40
+ end
41
+
42
+ def current_quality
43
+ @willpower.clamp(Constants::QUALITY_FLOOR, 1.0)
44
+ end
45
+
46
+ def quality_label
47
+ Constants.quality_label_for(current_quality)
48
+ end
49
+
50
+ def rest!(amount: Constants::RECOVERY_RATE)
51
+ @willpower = [@willpower + amount, 1.0].min
52
+ end
53
+
54
+ def full_rest!
55
+ @willpower = Constants::DEFAULT_WILLPOWER
56
+ end
57
+
58
+ def decisions_since_rest
59
+ @decisions.size
60
+ end
61
+
62
+ def decision_rate
63
+ elapsed = [(Time.now.utc - @session_start) / 60.0, 1.0].max
64
+ @total_decisions / elapsed
65
+ end
66
+
67
+ def should_rest?
68
+ @willpower < 0.3
69
+ end
70
+
71
+ def recent_decisions(limit: 10)
72
+ @decisions.last(limit)
73
+ end
74
+
75
+ def decisions_by_type(decision_type:)
76
+ @decisions.select { |d| d.decision_type == decision_type }
77
+ end
78
+
79
+ def quality_trend(window: 10)
80
+ recent = @decisions.last(window)
81
+ return current_quality if recent.empty?
82
+
83
+ recent.sum(&:quality_at_time) / recent.size
84
+ end
85
+
86
+ def fatigue_report
87
+ {
88
+ willpower: @willpower.round(4),
89
+ current_quality: current_quality.round(4),
90
+ quality_label: quality_label,
91
+ total_decisions: @total_decisions,
92
+ session_decisions: @decisions.size,
93
+ decision_rate: decision_rate.round(4),
94
+ should_rest: should_rest?,
95
+ quality_trend: quality_trend.round(4),
96
+ session_start: @session_start
97
+ }
98
+ end
99
+
100
+ def to_h
101
+ {
102
+ willpower: @willpower,
103
+ total_decisions: @total_decisions,
104
+ session_start: @session_start,
105
+ decisions: @decisions.map(&:to_h)
106
+ }
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end