lex-agentic-learning 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 (192) 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-learning.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/learning/anchoring/client.rb +26 -0
  8. data/lib/legion/extensions/agentic/learning/anchoring/helpers/anchor.rb +65 -0
  9. data/lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb +132 -0
  10. data/lib/legion/extensions/agentic/learning/anchoring/helpers/constants.rb +31 -0
  11. data/lib/legion/extensions/agentic/learning/anchoring/runners/anchoring.rb +100 -0
  12. data/lib/legion/extensions/agentic/learning/anchoring/version.rb +13 -0
  13. data/lib/legion/extensions/agentic/learning/anchoring.rb +19 -0
  14. data/lib/legion/extensions/agentic/learning/catalyst/client.rb +15 -0
  15. data/lib/legion/extensions/agentic/learning/catalyst/helpers/catalyst.rb +87 -0
  16. data/lib/legion/extensions/agentic/learning/catalyst/helpers/catalyst_engine.rb +153 -0
  17. data/lib/legion/extensions/agentic/learning/catalyst/helpers/constants.rb +55 -0
  18. data/lib/legion/extensions/agentic/learning/catalyst/helpers/reaction.rb +87 -0
  19. data/lib/legion/extensions/agentic/learning/catalyst/runners/cognitive_catalyst.rb +103 -0
  20. data/lib/legion/extensions/agentic/learning/catalyst/version.rb +13 -0
  21. data/lib/legion/extensions/agentic/learning/catalyst.rb +22 -0
  22. data/lib/legion/extensions/agentic/learning/chrysalis/client.rb +22 -0
  23. data/lib/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis.rb +137 -0
  24. data/lib/legion/extensions/agentic/learning/chrysalis/helpers/cocoon.rb +89 -0
  25. data/lib/legion/extensions/agentic/learning/chrysalis/helpers/constants.rb +49 -0
  26. data/lib/legion/extensions/agentic/learning/chrysalis/helpers/metamorphosis_engine.rb +157 -0
  27. data/lib/legion/extensions/agentic/learning/chrysalis/runners/cognitive_chrysalis.rb +129 -0
  28. data/lib/legion/extensions/agentic/learning/chrysalis/version.rb +13 -0
  29. data/lib/legion/extensions/agentic/learning/chrysalis.rb +21 -0
  30. data/lib/legion/extensions/agentic/learning/curiosity/client.rb +28 -0
  31. data/lib/legion/extensions/agentic/learning/curiosity/helpers/constants.rb +30 -0
  32. data/lib/legion/extensions/agentic/learning/curiosity/helpers/gap_detector.rb +167 -0
  33. data/lib/legion/extensions/agentic/learning/curiosity/helpers/wonder.rb +73 -0
  34. data/lib/legion/extensions/agentic/learning/curiosity/helpers/wonder_store.rb +149 -0
  35. data/lib/legion/extensions/agentic/learning/curiosity/runners/curiosity.rb +163 -0
  36. data/lib/legion/extensions/agentic/learning/curiosity/version.rb +13 -0
  37. data/lib/legion/extensions/agentic/learning/curiosity.rb +21 -0
  38. data/lib/legion/extensions/agentic/learning/epistemic_curiosity/client.rb +28 -0
  39. data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/constants.rb +31 -0
  40. data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/curiosity_engine.rb +122 -0
  41. data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/knowledge_gap.rb +70 -0
  42. data/lib/legion/extensions/agentic/learning/epistemic_curiosity/runners/epistemic_curiosity.rb +106 -0
  43. data/lib/legion/extensions/agentic/learning/epistemic_curiosity/version.rb +13 -0
  44. data/lib/legion/extensions/agentic/learning/epistemic_curiosity.rb +19 -0
  45. data/lib/legion/extensions/agentic/learning/fermentation/client.rb +19 -0
  46. data/lib/legion/extensions/agentic/learning/fermentation/helpers/batch.rb +75 -0
  47. data/lib/legion/extensions/agentic/learning/fermentation/helpers/constants.rb +78 -0
  48. data/lib/legion/extensions/agentic/learning/fermentation/helpers/fermentation_engine.rb +147 -0
  49. data/lib/legion/extensions/agentic/learning/fermentation/helpers/substrate.rb +108 -0
  50. data/lib/legion/extensions/agentic/learning/fermentation/runners/cognitive_fermentation.rb +60 -0
  51. data/lib/legion/extensions/agentic/learning/fermentation/version.rb +13 -0
  52. data/lib/legion/extensions/agentic/learning/fermentation.rb +22 -0
  53. data/lib/legion/extensions/agentic/learning/habit/client.rb +26 -0
  54. data/lib/legion/extensions/agentic/learning/habit/helpers/action_sequence.rb +120 -0
  55. data/lib/legion/extensions/agentic/learning/habit/helpers/constants.rb +44 -0
  56. data/lib/legion/extensions/agentic/learning/habit/helpers/habit_store.rb +148 -0
  57. data/lib/legion/extensions/agentic/learning/habit/runners/habit.rb +86 -0
  58. data/lib/legion/extensions/agentic/learning/habit/version.rb +13 -0
  59. data/lib/legion/extensions/agentic/learning/habit.rb +19 -0
  60. data/lib/legion/extensions/agentic/learning/hebbian/actors/decay.rb +45 -0
  61. data/lib/legion/extensions/agentic/learning/hebbian/client.rb +29 -0
  62. data/lib/legion/extensions/agentic/learning/hebbian/helpers/assembly.rb +82 -0
  63. data/lib/legion/extensions/agentic/learning/hebbian/helpers/assembly_network.rb +190 -0
  64. data/lib/legion/extensions/agentic/learning/hebbian/helpers/constants.rb +50 -0
  65. data/lib/legion/extensions/agentic/learning/hebbian/helpers/unit.rb +94 -0
  66. data/lib/legion/extensions/agentic/learning/hebbian/runners/hebbian_assembly.rb +94 -0
  67. data/lib/legion/extensions/agentic/learning/hebbian/version.rb +13 -0
  68. data/lib/legion/extensions/agentic/learning/hebbian.rb +20 -0
  69. data/lib/legion/extensions/agentic/learning/learning_rate/client.rb +25 -0
  70. data/lib/legion/extensions/agentic/learning/learning_rate/helpers/constants.rb +35 -0
  71. data/lib/legion/extensions/agentic/learning/learning_rate/helpers/rate_model.rb +133 -0
  72. data/lib/legion/extensions/agentic/learning/learning_rate/runners/learning_rate.rb +85 -0
  73. data/lib/legion/extensions/agentic/learning/learning_rate/version.rb +13 -0
  74. data/lib/legion/extensions/agentic/learning/learning_rate.rb +18 -0
  75. data/lib/legion/extensions/agentic/learning/meta_learning/client.rb +27 -0
  76. data/lib/legion/extensions/agentic/learning/meta_learning/helpers/constants.rb +46 -0
  77. data/lib/legion/extensions/agentic/learning/meta_learning/helpers/learning_domain.rb +85 -0
  78. data/lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb +202 -0
  79. data/lib/legion/extensions/agentic/learning/meta_learning/helpers/strategy.rb +62 -0
  80. data/lib/legion/extensions/agentic/learning/meta_learning/runners/meta_learning.rb +118 -0
  81. data/lib/legion/extensions/agentic/learning/meta_learning/version.rb +13 -0
  82. data/lib/legion/extensions/agentic/learning/meta_learning.rb +20 -0
  83. data/lib/legion/extensions/agentic/learning/plasticity/client.rb +15 -0
  84. data/lib/legion/extensions/agentic/learning/plasticity/helpers/constants.rb +45 -0
  85. data/lib/legion/extensions/agentic/learning/plasticity/helpers/neural_pathway.rb +85 -0
  86. data/lib/legion/extensions/agentic/learning/plasticity/helpers/plasticity_engine.rb +130 -0
  87. data/lib/legion/extensions/agentic/learning/plasticity/runners/cognitive_plasticity.rb +85 -0
  88. data/lib/legion/extensions/agentic/learning/plasticity/version.rb +13 -0
  89. data/lib/legion/extensions/agentic/learning/plasticity.rb +19 -0
  90. data/lib/legion/extensions/agentic/learning/preference_learning/actors/decay.rb +45 -0
  91. data/lib/legion/extensions/agentic/learning/preference_learning/client.rb +28 -0
  92. data/lib/legion/extensions/agentic/learning/preference_learning/helpers/constants.rb +35 -0
  93. data/lib/legion/extensions/agentic/learning/preference_learning/helpers/option.rb +78 -0
  94. data/lib/legion/extensions/agentic/learning/preference_learning/helpers/preference_engine.rb +121 -0
  95. data/lib/legion/extensions/agentic/learning/preference_learning/runners/preference_learning.rb +84 -0
  96. data/lib/legion/extensions/agentic/learning/preference_learning/version.rb +13 -0
  97. data/lib/legion/extensions/agentic/learning/preference_learning.rb +19 -0
  98. data/lib/legion/extensions/agentic/learning/procedural/client.rb +19 -0
  99. data/lib/legion/extensions/agentic/learning/procedural/helpers/constants.rb +46 -0
  100. data/lib/legion/extensions/agentic/learning/procedural/helpers/learning_engine.rb +160 -0
  101. data/lib/legion/extensions/agentic/learning/procedural/helpers/production.rb +66 -0
  102. data/lib/legion/extensions/agentic/learning/procedural/helpers/skill.rb +101 -0
  103. data/lib/legion/extensions/agentic/learning/procedural/runners/procedural_learning.rb +96 -0
  104. data/lib/legion/extensions/agentic/learning/procedural/version.rb +13 -0
  105. data/lib/legion/extensions/agentic/learning/procedural.rb +20 -0
  106. data/lib/legion/extensions/agentic/learning/scaffolding/client.rb +26 -0
  107. data/lib/legion/extensions/agentic/learning/scaffolding/helpers/constants.rb +42 -0
  108. data/lib/legion/extensions/agentic/learning/scaffolding/helpers/scaffold.rb +136 -0
  109. data/lib/legion/extensions/agentic/learning/scaffolding/helpers/scaffolding_engine.rb +112 -0
  110. data/lib/legion/extensions/agentic/learning/scaffolding/runners/cognitive_scaffolding.rb +107 -0
  111. data/lib/legion/extensions/agentic/learning/scaffolding/version.rb +13 -0
  112. data/lib/legion/extensions/agentic/learning/scaffolding.rb +19 -0
  113. data/lib/legion/extensions/agentic/learning/version.rb +11 -0
  114. data/lib/legion/extensions/agentic/learning.rb +31 -0
  115. data/spec/legion/extensions/agentic/learning/anchoring/client_spec.rb +32 -0
  116. data/spec/legion/extensions/agentic/learning/anchoring/helpers/anchor_spec.rb +130 -0
  117. data/spec/legion/extensions/agentic/learning/anchoring/helpers/anchor_store_spec.rb +201 -0
  118. data/spec/legion/extensions/agentic/learning/anchoring/helpers/constants_spec.rb +63 -0
  119. data/spec/legion/extensions/agentic/learning/anchoring/runners/anchoring_spec.rb +199 -0
  120. data/spec/legion/extensions/agentic/learning/catalyst/client_spec.rb +58 -0
  121. data/spec/legion/extensions/agentic/learning/catalyst/cognitive_catalyst_spec.rb +49 -0
  122. data/spec/legion/extensions/agentic/learning/catalyst/helpers/catalyst_engine_spec.rb +263 -0
  123. data/spec/legion/extensions/agentic/learning/catalyst/helpers/catalyst_spec.rb +214 -0
  124. data/spec/legion/extensions/agentic/learning/catalyst/helpers/reaction_spec.rb +223 -0
  125. data/spec/legion/extensions/agentic/learning/catalyst/runners/cognitive_catalyst_spec.rb +217 -0
  126. data/spec/legion/extensions/agentic/learning/chrysalis/client_spec.rb +83 -0
  127. data/spec/legion/extensions/agentic/learning/chrysalis/cognitive_chrysalis_spec.rb +15 -0
  128. data/spec/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis_engine_spec.rb +57 -0
  129. data/spec/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis_spec.rb +305 -0
  130. data/spec/legion/extensions/agentic/learning/chrysalis/helpers/cocoon_spec.rb +206 -0
  131. data/spec/legion/extensions/agentic/learning/chrysalis/helpers/constants_spec.rb +109 -0
  132. data/spec/legion/extensions/agentic/learning/chrysalis/helpers/metamorphic_cycle_spec.rb +76 -0
  133. data/spec/legion/extensions/agentic/learning/chrysalis/helpers/metamorphosis_engine_spec.rb +247 -0
  134. data/spec/legion/extensions/agentic/learning/chrysalis/helpers/transformation_phase_spec.rb +98 -0
  135. data/spec/legion/extensions/agentic/learning/chrysalis/runners/cognitive_chrysalis_spec.rb +180 -0
  136. data/spec/legion/extensions/agentic/learning/chrysalis/runners/reporting_spec.rb +81 -0
  137. data/spec/legion/extensions/agentic/learning/chrysalis/runners/transformation_spec.rb +74 -0
  138. data/spec/legion/extensions/agentic/learning/curiosity/client_spec.rb +27 -0
  139. data/spec/legion/extensions/agentic/learning/curiosity/helpers/gap_detector_spec.rb +118 -0
  140. data/spec/legion/extensions/agentic/learning/curiosity/helpers/wonder_spec.rb +130 -0
  141. data/spec/legion/extensions/agentic/learning/curiosity/helpers/wonder_store_spec.rb +136 -0
  142. data/spec/legion/extensions/agentic/learning/curiosity/runners/curiosity_spec.rb +159 -0
  143. data/spec/legion/extensions/agentic/learning/epistemic_curiosity/client_spec.rb +47 -0
  144. data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/constants_spec.rb +45 -0
  145. data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/curiosity_engine_spec.rb +229 -0
  146. data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/knowledge_gap_spec.rb +188 -0
  147. data/spec/legion/extensions/agentic/learning/epistemic_curiosity/runners/epistemic_curiosity_spec.rb +175 -0
  148. data/spec/legion/extensions/agentic/learning/fermentation/client_spec.rb +36 -0
  149. data/spec/legion/extensions/agentic/learning/fermentation/helpers/batch_spec.rb +72 -0
  150. data/spec/legion/extensions/agentic/learning/fermentation/helpers/fermentation_engine_spec.rb +138 -0
  151. data/spec/legion/extensions/agentic/learning/fermentation/helpers/substrate_spec.rb +146 -0
  152. data/spec/legion/extensions/agentic/learning/habit/client_spec.rb +50 -0
  153. data/spec/legion/extensions/agentic/learning/habit/helpers/action_sequence_spec.rb +276 -0
  154. data/spec/legion/extensions/agentic/learning/habit/helpers/constants_spec.rb +115 -0
  155. data/spec/legion/extensions/agentic/learning/habit/helpers/habit_store_spec.rb +274 -0
  156. data/spec/legion/extensions/agentic/learning/habit/runners/habit_spec.rb +228 -0
  157. data/spec/legion/extensions/agentic/learning/hebbian/client_spec.rb +38 -0
  158. data/spec/legion/extensions/agentic/learning/hebbian/helpers/assembly_network_spec.rb +142 -0
  159. data/spec/legion/extensions/agentic/learning/hebbian/helpers/assembly_spec.rb +89 -0
  160. data/spec/legion/extensions/agentic/learning/hebbian/helpers/unit_spec.rb +119 -0
  161. data/spec/legion/extensions/agentic/learning/hebbian/runners/hebbian_assembly_spec.rb +109 -0
  162. data/spec/legion/extensions/agentic/learning/learning_rate/client_spec.rb +51 -0
  163. data/spec/legion/extensions/agentic/learning/learning_rate/helpers/constants_spec.rb +29 -0
  164. data/spec/legion/extensions/agentic/learning/learning_rate/helpers/rate_model_spec.rb +151 -0
  165. data/spec/legion/extensions/agentic/learning/learning_rate/runners/learning_rate_spec.rb +92 -0
  166. data/spec/legion/extensions/agentic/learning/meta_learning/client_spec.rb +27 -0
  167. data/spec/legion/extensions/agentic/learning/meta_learning/helpers/constants_spec.rb +43 -0
  168. data/spec/legion/extensions/agentic/learning/meta_learning/helpers/learning_domain_spec.rb +146 -0
  169. data/spec/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine_spec.rb +309 -0
  170. data/spec/legion/extensions/agentic/learning/meta_learning/helpers/strategy_spec.rb +82 -0
  171. data/spec/legion/extensions/agentic/learning/meta_learning/runners/meta_learning_spec.rb +185 -0
  172. data/spec/legion/extensions/agentic/learning/plasticity/helpers/constants_spec.rb +54 -0
  173. data/spec/legion/extensions/agentic/learning/plasticity/helpers/neural_pathway_spec.rb +136 -0
  174. data/spec/legion/extensions/agentic/learning/plasticity/helpers/plasticity_engine_spec.rb +157 -0
  175. data/spec/legion/extensions/agentic/learning/plasticity/runners/cognitive_plasticity_spec.rb +83 -0
  176. data/spec/legion/extensions/agentic/learning/preference_learning/client_spec.rb +17 -0
  177. data/spec/legion/extensions/agentic/learning/preference_learning/helpers/constants_spec.rb +67 -0
  178. data/spec/legion/extensions/agentic/learning/preference_learning/helpers/option_spec.rb +104 -0
  179. data/spec/legion/extensions/agentic/learning/preference_learning/helpers/preference_engine_spec.rb +151 -0
  180. data/spec/legion/extensions/agentic/learning/preference_learning/runners/preference_learning_spec.rb +86 -0
  181. data/spec/legion/extensions/agentic/learning/procedural/client_spec.rb +22 -0
  182. data/spec/legion/extensions/agentic/learning/procedural/helpers/learning_engine_spec.rb +135 -0
  183. data/spec/legion/extensions/agentic/learning/procedural/helpers/production_spec.rb +66 -0
  184. data/spec/legion/extensions/agentic/learning/procedural/helpers/skill_spec.rb +102 -0
  185. data/spec/legion/extensions/agentic/learning/procedural/runners/procedural_learning_spec.rb +94 -0
  186. data/spec/legion/extensions/agentic/learning/scaffolding/client_spec.rb +20 -0
  187. data/spec/legion/extensions/agentic/learning/scaffolding/helpers/constants_spec.rb +36 -0
  188. data/spec/legion/extensions/agentic/learning/scaffolding/helpers/scaffold_spec.rb +187 -0
  189. data/spec/legion/extensions/agentic/learning/scaffolding/helpers/scaffolding_engine_spec.rb +159 -0
  190. data/spec/legion/extensions/agentic/learning/scaffolding/runners/cognitive_scaffolding_spec.rb +163 -0
  191. data/spec/spec_helper.rb +46 -0
  192. metadata +277 -0
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Learning
7
+ module Procedural
8
+ module Runners
9
+ module ProceduralLearning
10
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
11
+ Legion::Extensions::Helpers.const_defined?(:Lex)
12
+
13
+ def create_skill(name:, domain:, **)
14
+ skill = engine.create_skill(name: name, domain: domain)
15
+ Legion::Logging.debug "[procedural_learning] created skill=#{name} " \
16
+ "domain=#{domain} id=#{skill.id[0..7]}"
17
+ { success: true, skill_id: skill.id, name: name, domain: domain,
18
+ proficiency: skill.proficiency, stage: skill.stage }
19
+ end
20
+
21
+ def add_skill_production(skill_id:, condition:, action:, domain:, **)
22
+ result = engine.add_production(
23
+ skill_id: skill_id, condition: condition,
24
+ action: action, domain: domain
25
+ )
26
+
27
+ return result unless result.is_a?(Helpers::Production)
28
+
29
+ Legion::Logging.debug '[procedural_learning] production added ' \
30
+ "skill=#{skill_id[0..7]} condition=#{condition}"
31
+ { success: true, production_id: result.id, skill_id: skill_id }
32
+ end
33
+
34
+ def practice_skill(skill_id:, success:, **)
35
+ result = engine.practice_skill(skill_id: skill_id, success: success)
36
+ Legion::Logging.debug "[procedural_learning] practice skill=#{skill_id[0..7]} " \
37
+ "success=#{success} proficiency=#{result[:proficiency]&.round(3)}"
38
+ result
39
+ end
40
+
41
+ def execute_production(production_id:, success:, **)
42
+ result = engine.execute_production(production_id: production_id, success: success)
43
+ Legion::Logging.debug "[procedural_learning] execute production=#{production_id[0..7]} " \
44
+ "success=#{success}"
45
+ result
46
+ end
47
+
48
+ def skill_assessment(skill_id:, **)
49
+ result = engine.skill_assessment(skill_id: skill_id)
50
+ Legion::Logging.debug "[procedural_learning] assessment skill=#{skill_id[0..7]}"
51
+ result
52
+ end
53
+
54
+ def compiled_skills(**)
55
+ skills = engine.compiled_skills
56
+ Legion::Logging.debug "[procedural_learning] compiled count=#{skills.size}"
57
+ { success: true, skills: skills.map(&:to_h), count: skills.size }
58
+ end
59
+
60
+ def autonomous_skills(**)
61
+ skills = engine.autonomous_skills
62
+ Legion::Logging.debug "[procedural_learning] autonomous count=#{skills.size}"
63
+ { success: true, skills: skills.map(&:to_h), count: skills.size }
64
+ end
65
+
66
+ def most_practiced_skills(limit: 5, **)
67
+ skills = engine.most_practiced(limit: limit)
68
+ Legion::Logging.debug "[procedural_learning] most_practiced limit=#{limit}"
69
+ { success: true, skills: skills.map(&:to_h), count: skills.size }
70
+ end
71
+
72
+ def update_procedural_learning(**)
73
+ engine.decay_all
74
+ pruned = engine.prune_stale
75
+ Legion::Logging.debug "[procedural_learning] decay+prune pruned=#{pruned}"
76
+ { success: true, pruned: pruned }
77
+ end
78
+
79
+ def procedural_learning_stats(**)
80
+ stats = engine.to_h
81
+ Legion::Logging.debug "[procedural_learning] stats total=#{stats[:total_skills]}"
82
+ { success: true }.merge(stats)
83
+ end
84
+
85
+ private
86
+
87
+ def engine
88
+ @engine ||= Helpers::LearningEngine.new
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Learning
7
+ module Procedural
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/learning/procedural/version'
4
+ require 'legion/extensions/agentic/learning/procedural/helpers/constants'
5
+ require 'legion/extensions/agentic/learning/procedural/helpers/production'
6
+ require 'legion/extensions/agentic/learning/procedural/helpers/skill'
7
+ require 'legion/extensions/agentic/learning/procedural/helpers/learning_engine'
8
+ require 'legion/extensions/agentic/learning/procedural/runners/procedural_learning'
9
+ require 'legion/extensions/agentic/learning/procedural/client'
10
+
11
+ module Legion
12
+ module Extensions
13
+ module Agentic
14
+ module Learning
15
+ module Procedural
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/learning/scaffolding/helpers/constants'
4
+ require 'legion/extensions/agentic/learning/scaffolding/helpers/scaffold'
5
+ require 'legion/extensions/agentic/learning/scaffolding/helpers/scaffolding_engine'
6
+ require 'legion/extensions/agentic/learning/scaffolding/runners/cognitive_scaffolding'
7
+
8
+ module Legion
9
+ module Extensions
10
+ module Agentic
11
+ module Learning
12
+ module Scaffolding
13
+ class Client
14
+ include Runners::CognitiveScaffolding
15
+
16
+ attr_reader :engine
17
+
18
+ def initialize(engine: nil, **)
19
+ @engine = engine || Helpers::ScaffoldingEngine.new
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Learning
7
+ module Scaffolding
8
+ module Helpers
9
+ module Constants
10
+ MAX_SCAFFOLDS = 100
11
+ MAX_TASKS = 500
12
+ MAX_HISTORY = 300
13
+
14
+ DEFAULT_COMPETENCE = 0.3
15
+ COMPETENCE_FLOOR = 0.0
16
+ COMPETENCE_CEILING = 1.0
17
+
18
+ ZPD_LOWER = 0.3
19
+ ZPD_UPPER = 0.8
20
+
21
+ SUPPORT_LEVELS = %i[full guided prompted independent].freeze
22
+
23
+ FADING_RATE = 0.1
24
+ MASTERY_THRESHOLD = 0.85
25
+ FRUSTRATION_THRESHOLD = 0.15
26
+
27
+ LEARNING_GAIN = 0.08
28
+ FAILURE_SETBACK = 0.03
29
+ DECAY_RATE = 0.01
30
+
31
+ ZONE_LABELS = {
32
+ (0.85..) => :mastered,
33
+ (0.3...0.85) => :zpd,
34
+ (..0.3) => :beyond_reach
35
+ }.freeze
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Learning
9
+ module Scaffolding
10
+ module Helpers
11
+ class Scaffold
12
+ include Constants
13
+
14
+ attr_reader :id, :skill_name, :domain, :competence, :support_level,
15
+ :task_history, :practice_count, :created_at, :last_practiced_at
16
+
17
+ def initialize(skill_name:, domain:, competence: DEFAULT_COMPETENCE)
18
+ @id = SecureRandom.uuid
19
+ @skill_name = skill_name
20
+ @domain = domain
21
+ @competence = competence.to_f.clamp(COMPETENCE_FLOOR, COMPETENCE_CEILING)
22
+ @support_level = initial_support_level
23
+ @task_history = []
24
+ @practice_count = 0
25
+ @created_at = Time.now.utc
26
+ @last_practiced_at = nil
27
+ end
28
+
29
+ def attempt_task(difficulty:, success:)
30
+ diff = difficulty.to_f.clamp(COMPETENCE_FLOOR, COMPETENCE_CEILING)
31
+ delta = compute_delta(difficulty: diff, success: success)
32
+ @competence = (@competence + delta).clamp(COMPETENCE_FLOOR, COMPETENCE_CEILING)
33
+ @practice_count += 1
34
+ @last_practiced_at = Time.now.utc
35
+
36
+ record_task(difficulty: diff, success: success)
37
+ adjust_support(success)
38
+ @competence
39
+ end
40
+
41
+ def current_zone
42
+ ZONE_LABELS.each do |range, label|
43
+ return label if range.cover?(@competence)
44
+ end
45
+ :beyond_reach
46
+ end
47
+
48
+ def recommended_difficulty
49
+ (@competence + ((ZPD_UPPER - @competence) * 0.5)).clamp(COMPETENCE_FLOOR, COMPETENCE_CEILING)
50
+ end
51
+
52
+ def fade_support!
53
+ idx = SUPPORT_LEVELS.index(@support_level) || 0
54
+ return if idx >= SUPPORT_LEVELS.size - 1
55
+
56
+ @support_level = SUPPORT_LEVELS[idx + 1]
57
+ end
58
+
59
+ def increase_support!
60
+ idx = SUPPORT_LEVELS.index(@support_level) || (SUPPORT_LEVELS.size - 1)
61
+ return if idx <= 0
62
+
63
+ @support_level = SUPPORT_LEVELS[idx - 1]
64
+ end
65
+
66
+ def mastered?
67
+ @competence >= MASTERY_THRESHOLD
68
+ end
69
+
70
+ def in_zpd?
71
+ @competence >= ZPD_LOWER && @competence < ZPD_UPPER
72
+ end
73
+
74
+ def to_h
75
+ {
76
+ id: @id,
77
+ skill_name: @skill_name,
78
+ domain: @domain,
79
+ competence: @competence.round(4),
80
+ support_level: @support_level,
81
+ current_zone: current_zone,
82
+ practice_count: @practice_count,
83
+ mastered: mastered?,
84
+ in_zpd: in_zpd?,
85
+ created_at: @created_at,
86
+ last_practiced_at: @last_practiced_at,
87
+ task_history_size: @task_history.size
88
+ }
89
+ end
90
+
91
+ private
92
+
93
+ def compute_delta(difficulty:, success:)
94
+ if success
95
+ in_active_zpd = difficulty >= ZPD_LOWER && difficulty < ZPD_UPPER
96
+ in_active_zpd ? LEARNING_GAIN : LEARNING_GAIN / 2.0
97
+ else
98
+ -FAILURE_SETBACK
99
+ end
100
+ end
101
+
102
+ def adjust_support(success)
103
+ if success
104
+ fade_support!
105
+ else
106
+ increase_support!
107
+ end
108
+ end
109
+
110
+ def initial_support_level
111
+ if @competence >= ZPD_UPPER
112
+ :independent
113
+ elsif @competence >= ZPD_LOWER
114
+ :prompted
115
+ else
116
+ :full
117
+ end
118
+ end
119
+
120
+ def record_task(difficulty:, success:)
121
+ @task_history << {
122
+ task_id: SecureRandom.uuid,
123
+ difficulty: difficulty,
124
+ success: success,
125
+ support: @support_level,
126
+ at: Time.now.utc
127
+ }
128
+ @task_history.shift while @task_history.size > MAX_HISTORY
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Learning
7
+ module Scaffolding
8
+ module Helpers
9
+ class ScaffoldingEngine
10
+ include Constants
11
+
12
+ attr_reader :scaffolds
13
+
14
+ def initialize
15
+ @scaffolds = {}
16
+ end
17
+
18
+ def create_scaffold(skill_name:, domain:, competence: nil)
19
+ trim_scaffolds if @scaffolds.size >= MAX_SCAFFOLDS
20
+ comp = competence.nil? ? DEFAULT_COMPETENCE : competence
21
+ scaffold = Scaffold.new(skill_name: skill_name, domain: domain, competence: comp)
22
+ @scaffolds[scaffold.id] = scaffold
23
+ scaffold
24
+ end
25
+
26
+ def attempt_scaffolded_task(scaffold_id:, difficulty:, success:)
27
+ scaffold = find(scaffold_id)
28
+ return nil unless scaffold
29
+
30
+ scaffold.attempt_task(difficulty: difficulty, success: success)
31
+ scaffold
32
+ end
33
+
34
+ def recommend_task(scaffold_id:)
35
+ scaffold = find(scaffold_id)
36
+ return nil unless scaffold
37
+
38
+ {
39
+ difficulty: scaffold.recommended_difficulty,
40
+ support_level: scaffold.support_level,
41
+ zone: scaffold.current_zone
42
+ }
43
+ end
44
+
45
+ def mastered_skills
46
+ @scaffolds.values.select(&:mastered?)
47
+ end
48
+
49
+ def zpd_skills
50
+ @scaffolds.values.select(&:in_zpd?)
51
+ end
52
+
53
+ def by_domain(domain:)
54
+ @scaffolds.values.select { |s| s.domain == domain }
55
+ end
56
+
57
+ def adjust_support(scaffold_id:, direction:)
58
+ scaffold = find(scaffold_id)
59
+ return nil unless scaffold
60
+
61
+ case direction
62
+ when :increase then scaffold.increase_support!
63
+ when :decrease then scaffold.fade_support!
64
+ end
65
+
66
+ scaffold
67
+ end
68
+
69
+ def overall_competence
70
+ return DEFAULT_COMPETENCE if @scaffolds.empty?
71
+
72
+ @scaffolds.values.sum(&:competence) / @scaffolds.size
73
+ end
74
+
75
+ def decay_all
76
+ @scaffolds.each_value do |scaffold|
77
+ next if scaffold.mastered?
78
+
79
+ decayed = (scaffold.competence - DECAY_RATE).clamp(COMPETENCE_FLOOR, COMPETENCE_CEILING)
80
+ scaffold.instance_variable_set(:@competence, decayed)
81
+ end
82
+ @scaffolds.size
83
+ end
84
+
85
+ def to_h
86
+ {
87
+ total_scaffolds: @scaffolds.size,
88
+ mastered_count: mastered_skills.size,
89
+ zpd_count: zpd_skills.size,
90
+ overall_competence: overall_competence.round(4)
91
+ }
92
+ end
93
+
94
+ private
95
+
96
+ def find(scaffold_id)
97
+ @scaffolds[scaffold_id]
98
+ end
99
+
100
+ def trim_scaffolds
101
+ mastered = mastered_skills.sort_by(&:last_practiced_at)
102
+ candidates = mastered.any? ? mastered : @scaffolds.values.sort_by(&:last_practiced_at)
103
+ remove = candidates.first
104
+ @scaffolds.delete(remove.id) if remove
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Learning
7
+ module Scaffolding
8
+ module Runners
9
+ module CognitiveScaffolding
10
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
11
+ Legion::Extensions::Helpers.const_defined?(:Lex)
12
+
13
+ def create_scaffold(skill_name:, domain:, competence: nil, **)
14
+ comp = competence || Helpers::Constants::DEFAULT_COMPETENCE
15
+ scaffold = engine.create_scaffold(skill_name: skill_name, domain: domain, competence: comp)
16
+ Legion::Logging.debug "[cognitive_scaffolding] created: skill=#{skill_name} domain=#{domain} " \
17
+ "competence=#{scaffold.competence.round(2)} zone=#{scaffold.current_zone}"
18
+ { success: true, scaffold: scaffold.to_h }
19
+ end
20
+
21
+ def attempt_scaffolded_task(scaffold_id:, difficulty:, success:, **)
22
+ scaffold = engine.attempt_scaffolded_task(scaffold_id: scaffold_id, difficulty: difficulty, success: success)
23
+ unless scaffold
24
+ Legion::Logging.debug "[cognitive_scaffolding] attempt: scaffold_id=#{scaffold_id} not found"
25
+ return { success: false, reason: :not_found, scaffold_id: scaffold_id }
26
+ end
27
+
28
+ Legion::Logging.debug "[cognitive_scaffolding] attempt: skill=#{scaffold.skill_name} " \
29
+ "difficulty=#{difficulty.round(2)} success=#{success} " \
30
+ "competence=#{scaffold.competence.round(2)} zone=#{scaffold.current_zone}"
31
+ { success: true, scaffold: scaffold.to_h }
32
+ end
33
+
34
+ def recommend_scaffolded_task(scaffold_id:, **)
35
+ recommendation = engine.recommend_task(scaffold_id: scaffold_id)
36
+ unless recommendation
37
+ Legion::Logging.debug "[cognitive_scaffolding] recommend: scaffold_id=#{scaffold_id} not found"
38
+ return { success: false, reason: :not_found, scaffold_id: scaffold_id }
39
+ end
40
+
41
+ Legion::Logging.debug "[cognitive_scaffolding] recommend: difficulty=#{recommendation[:difficulty].round(2)} " \
42
+ "support=#{recommendation[:support_level]} zone=#{recommendation[:zone]}"
43
+ { success: true, recommendation: recommendation }
44
+ end
45
+
46
+ def mastered_scaffolded_skills(**)
47
+ skills = engine.mastered_skills
48
+ Legion::Logging.debug "[cognitive_scaffolding] mastered: count=#{skills.size}"
49
+ { success: true, skills: skills.map(&:to_h), count: skills.size }
50
+ end
51
+
52
+ def zpd_skills(**)
53
+ skills = engine.zpd_skills
54
+ Legion::Logging.debug "[cognitive_scaffolding] zpd: count=#{skills.size}"
55
+ { success: true, skills: skills.map(&:to_h), count: skills.size }
56
+ end
57
+
58
+ def domain_scaffolds(domain:, **)
59
+ scaffolds = engine.by_domain(domain: domain)
60
+ Legion::Logging.debug "[cognitive_scaffolding] domain: domain=#{domain} count=#{scaffolds.size}"
61
+ { success: true, domain: domain, scaffolds: scaffolds.map(&:to_h), count: scaffolds.size }
62
+ end
63
+
64
+ def adjust_scaffold_support(scaffold_id:, direction:, **)
65
+ scaffold = engine.adjust_support(scaffold_id: scaffold_id, direction: direction)
66
+ unless scaffold
67
+ Legion::Logging.debug "[cognitive_scaffolding] adjust_support: scaffold_id=#{scaffold_id} not found"
68
+ return { success: false, reason: :not_found, scaffold_id: scaffold_id }
69
+ end
70
+
71
+ Legion::Logging.debug "[cognitive_scaffolding] adjust_support: skill=#{scaffold.skill_name} " \
72
+ "direction=#{direction} support=#{scaffold.support_level}"
73
+ { success: true, scaffold: scaffold.to_h }
74
+ end
75
+
76
+ def overall_scaffolded_competence(**)
77
+ overall = engine.overall_competence
78
+ Legion::Logging.debug "[cognitive_scaffolding] overall_competence: #{overall.round(3)}"
79
+ { success: true, overall_competence: overall.round(4) }
80
+ end
81
+
82
+ def update_cognitive_scaffolding(**)
83
+ count = engine.decay_all
84
+ overall = engine.overall_competence
85
+ Legion::Logging.debug "[cognitive_scaffolding] decay: scaffolds=#{count} overall=#{overall.round(3)}"
86
+ { success: true, action: :decay, scaffold_count: count, overall_competence: overall.round(4) }
87
+ end
88
+
89
+ def cognitive_scaffolding_stats(**)
90
+ stats = engine.to_h
91
+ Legion::Logging.debug "[cognitive_scaffolding] stats: total=#{stats[:total_scaffolds]} " \
92
+ "mastered=#{stats[:mastered_count]} zpd=#{stats[:zpd_count]}"
93
+ { success: true, stats: stats }
94
+ end
95
+
96
+ private
97
+
98
+ def engine
99
+ @engine ||= Helpers::ScaffoldingEngine.new
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Learning
7
+ module Scaffolding
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/learning/scaffolding/version'
4
+ require 'legion/extensions/agentic/learning/scaffolding/helpers/constants'
5
+ require 'legion/extensions/agentic/learning/scaffolding/helpers/scaffold'
6
+ require 'legion/extensions/agentic/learning/scaffolding/helpers/scaffolding_engine'
7
+ require 'legion/extensions/agentic/learning/scaffolding/runners/cognitive_scaffolding'
8
+ require 'legion/extensions/agentic/learning/scaffolding/client'
9
+
10
+ module Legion
11
+ module Extensions
12
+ module Agentic
13
+ module Learning
14
+ module Scaffolding
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Learning
7
+ VERSION = '0.1.0'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'learning/version'
4
+ require_relative 'learning/plasticity'
5
+ require_relative 'learning/scaffolding'
6
+ require_relative 'learning/fermentation'
7
+ require_relative 'learning/chrysalis'
8
+ require_relative 'learning/catalyst'
9
+ require_relative 'learning/curiosity'
10
+ require_relative 'learning/epistemic_curiosity'
11
+ require_relative 'learning/habit'
12
+ require_relative 'learning/hebbian'
13
+ require_relative 'learning/learning_rate'
14
+ require_relative 'learning/meta_learning'
15
+ require_relative 'learning/preference_learning'
16
+ require_relative 'learning/procedural'
17
+ require_relative 'learning/anchoring'
18
+
19
+ module Legion
20
+ module Extensions
21
+ module Agentic
22
+ module Learning
23
+ extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
24
+
25
+ def remote_invocable?
26
+ false
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/learning/anchoring/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Learning::Anchoring::Client do
6
+ let(:client) { described_class.new }
7
+
8
+ it 'responds to all runner methods' do
9
+ expect(client).to respond_to(:record_anchor)
10
+ expect(client).to respond_to(:evaluate_estimate)
11
+ expect(client).to respond_to(:reference_frame)
12
+ expect(client).to respond_to(:de_anchor)
13
+ expect(client).to respond_to(:shift_reference)
14
+ expect(client).to respond_to(:update_anchoring)
15
+ expect(client).to respond_to(:domain_anchors)
16
+ expect(client).to respond_to(:anchoring_stats)
17
+ end
18
+
19
+ it 'exposes anchor_store' do
20
+ expect(client.anchor_store).to be_a(Legion::Extensions::Agentic::Learning::Anchoring::Helpers::AnchorStore)
21
+ end
22
+
23
+ it 'accepts an external anchor_store' do
24
+ custom_store = Legion::Extensions::Agentic::Learning::Anchoring::Helpers::AnchorStore.new
25
+ c = described_class.new(anchor_store: custom_store)
26
+ expect(c.anchor_store).to be(custom_store)
27
+ end
28
+
29
+ it 'accepts keyword splat arguments' do
30
+ expect { described_class.new(extra: :ignored) }.not_to raise_error
31
+ end
32
+ end