lex-agentic-social 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 (235) 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-social.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/social/apprenticeship/client.rb +28 -0
  8. data/lib/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship.rb +90 -0
  9. data/lib/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_engine.rb +109 -0
  10. data/lib/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_model.rb +93 -0
  11. data/lib/legion/extensions/agentic/social/apprenticeship/runners/cognitive_apprenticeship.rb +112 -0
  12. data/lib/legion/extensions/agentic/social/apprenticeship/version.rb +13 -0
  13. data/lib/legion/extensions/agentic/social/apprenticeship.rb +19 -0
  14. data/lib/legion/extensions/agentic/social/conflict/actors/stale_check.rb +45 -0
  15. data/lib/legion/extensions/agentic/social/conflict/client.rb +27 -0
  16. data/lib/legion/extensions/agentic/social/conflict/helpers/conflict_log.rb +70 -0
  17. data/lib/legion/extensions/agentic/social/conflict/helpers/llm_enhancer.rb +130 -0
  18. data/lib/legion/extensions/agentic/social/conflict/helpers/severity.rb +47 -0
  19. data/lib/legion/extensions/agentic/social/conflict/runners/conflict.rb +112 -0
  20. data/lib/legion/extensions/agentic/social/conflict/version.rb +13 -0
  21. data/lib/legion/extensions/agentic/social/conflict.rb +19 -0
  22. data/lib/legion/extensions/agentic/social/conscience/client.rb +26 -0
  23. data/lib/legion/extensions/agentic/social/conscience/helpers/constants.rb +53 -0
  24. data/lib/legion/extensions/agentic/social/conscience/helpers/moral_evaluator.rb +178 -0
  25. data/lib/legion/extensions/agentic/social/conscience/helpers/moral_store.rb +116 -0
  26. data/lib/legion/extensions/agentic/social/conscience/runners/conscience.rb +117 -0
  27. data/lib/legion/extensions/agentic/social/conscience/version.rb +13 -0
  28. data/lib/legion/extensions/agentic/social/conscience.rb +19 -0
  29. data/lib/legion/extensions/agentic/social/consent/actors/tier_evaluation.rb +45 -0
  30. data/lib/legion/extensions/agentic/social/consent/client.rb +27 -0
  31. data/lib/legion/extensions/agentic/social/consent/helpers/consent_map.rb +199 -0
  32. data/lib/legion/extensions/agentic/social/consent/helpers/tiers.rb +54 -0
  33. data/lib/legion/extensions/agentic/social/consent/local_migrations/20260316000010_create_consent_domains.rb +16 -0
  34. data/lib/legion/extensions/agentic/social/consent/runners/consent.rb +228 -0
  35. data/lib/legion/extensions/agentic/social/consent/version.rb +13 -0
  36. data/lib/legion/extensions/agentic/social/consent.rb +25 -0
  37. data/lib/legion/extensions/agentic/social/entrainment/client.rb +19 -0
  38. data/lib/legion/extensions/agentic/social/entrainment/helpers/constants.rb +40 -0
  39. data/lib/legion/extensions/agentic/social/entrainment/helpers/entrainment_engine.rb +120 -0
  40. data/lib/legion/extensions/agentic/social/entrainment/helpers/pairing.rb +86 -0
  41. data/lib/legion/extensions/agentic/social/entrainment/runners/cognitive_entrainment.rb +89 -0
  42. data/lib/legion/extensions/agentic/social/entrainment/version.rb +13 -0
  43. data/lib/legion/extensions/agentic/social/entrainment.rb +19 -0
  44. data/lib/legion/extensions/agentic/social/governance/actors/shadow_ai_scan.rb +19 -0
  45. data/lib/legion/extensions/agentic/social/governance/actors/vote_timeout.rb +45 -0
  46. data/lib/legion/extensions/agentic/social/governance/client.rb +27 -0
  47. data/lib/legion/extensions/agentic/social/governance/helpers/layers.rb +40 -0
  48. data/lib/legion/extensions/agentic/social/governance/helpers/proposal.rb +94 -0
  49. data/lib/legion/extensions/agentic/social/governance/runners/governance.rb +87 -0
  50. data/lib/legion/extensions/agentic/social/governance/runners/shadow_ai.rb +93 -0
  51. data/lib/legion/extensions/agentic/social/governance/version.rb +13 -0
  52. data/lib/legion/extensions/agentic/social/governance.rb +20 -0
  53. data/lib/legion/extensions/agentic/social/joint_attention/actors/decay.rb +45 -0
  54. data/lib/legion/extensions/agentic/social/joint_attention/client.rb +28 -0
  55. data/lib/legion/extensions/agentic/social/joint_attention/helpers/attention_target.rb +124 -0
  56. data/lib/legion/extensions/agentic/social/joint_attention/helpers/constants.rb +34 -0
  57. data/lib/legion/extensions/agentic/social/joint_attention/helpers/joint_focus_manager.rb +157 -0
  58. data/lib/legion/extensions/agentic/social/joint_attention/runners/joint_attention.rb +88 -0
  59. data/lib/legion/extensions/agentic/social/joint_attention/version.rb +13 -0
  60. data/lib/legion/extensions/agentic/social/joint_attention.rb +20 -0
  61. data/lib/legion/extensions/agentic/social/mentalizing/actors/decay.rb +45 -0
  62. data/lib/legion/extensions/agentic/social/mentalizing/client.rb +28 -0
  63. data/lib/legion/extensions/agentic/social/mentalizing/helpers/belief_attribution.rb +58 -0
  64. data/lib/legion/extensions/agentic/social/mentalizing/helpers/constants.rb +33 -0
  65. data/lib/legion/extensions/agentic/social/mentalizing/helpers/mental_model.rb +137 -0
  66. data/lib/legion/extensions/agentic/social/mentalizing/runners/mentalizing.rb +93 -0
  67. data/lib/legion/extensions/agentic/social/mentalizing/version.rb +13 -0
  68. data/lib/legion/extensions/agentic/social/mentalizing.rb +20 -0
  69. data/lib/legion/extensions/agentic/social/mirror/client.rb +33 -0
  70. data/lib/legion/extensions/agentic/social/mirror/helpers/constants.rb +65 -0
  71. data/lib/legion/extensions/agentic/social/mirror/helpers/mirror_engine.rb +132 -0
  72. data/lib/legion/extensions/agentic/social/mirror/helpers/mirror_event.rb +46 -0
  73. data/lib/legion/extensions/agentic/social/mirror/helpers/simulation.rb +43 -0
  74. data/lib/legion/extensions/agentic/social/mirror/runners/observe.rb +52 -0
  75. data/lib/legion/extensions/agentic/social/mirror/runners/resonance.rb +79 -0
  76. data/lib/legion/extensions/agentic/social/mirror/runners/simulate.rb +63 -0
  77. data/lib/legion/extensions/agentic/social/mirror/version.rb +13 -0
  78. data/lib/legion/extensions/agentic/social/mirror.rb +22 -0
  79. data/lib/legion/extensions/agentic/social/mirror_system/actors/decay.rb +45 -0
  80. data/lib/legion/extensions/agentic/social/mirror_system/client.rb +28 -0
  81. data/lib/legion/extensions/agentic/social/mirror_system/helpers/constants.rb +62 -0
  82. data/lib/legion/extensions/agentic/social/mirror_system/helpers/mirror_system.rb +162 -0
  83. data/lib/legion/extensions/agentic/social/mirror_system/helpers/observed_behavior.rb +67 -0
  84. data/lib/legion/extensions/agentic/social/mirror_system/runners/mirror.rb +99 -0
  85. data/lib/legion/extensions/agentic/social/mirror_system/version.rb +13 -0
  86. data/lib/legion/extensions/agentic/social/mirror_system.rb +20 -0
  87. data/lib/legion/extensions/agentic/social/moral_reasoning/client.rb +19 -0
  88. data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/constants.rb +49 -0
  89. data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/dilemma.rb +68 -0
  90. data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/llm_enhancer.rb +140 -0
  91. data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb +239 -0
  92. data/lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_foundation.rb +45 -0
  93. data/lib/legion/extensions/agentic/social/moral_reasoning/runners/moral_reasoning.rb +121 -0
  94. data/lib/legion/extensions/agentic/social/moral_reasoning/version.rb +13 -0
  95. data/lib/legion/extensions/agentic/social/moral_reasoning.rb +21 -0
  96. data/lib/legion/extensions/agentic/social/perspective_shifting/client.rb +29 -0
  97. data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/constants.rb +67 -0
  98. data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/perspective.rb +45 -0
  99. data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/perspective_view.rb +57 -0
  100. data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/shifting_engine.rb +166 -0
  101. data/lib/legion/extensions/agentic/social/perspective_shifting/runners/perspective_shifting.rb +167 -0
  102. data/lib/legion/extensions/agentic/social/perspective_shifting/version.rb +13 -0
  103. data/lib/legion/extensions/agentic/social/perspective_shifting.rb +20 -0
  104. data/lib/legion/extensions/agentic/social/social/client.rb +25 -0
  105. data/lib/legion/extensions/agentic/social/social/helpers/constants.rb +84 -0
  106. data/lib/legion/extensions/agentic/social/social/helpers/social_graph.rb +172 -0
  107. data/lib/legion/extensions/agentic/social/social/runners/social.rb +146 -0
  108. data/lib/legion/extensions/agentic/social/social/version.rb +13 -0
  109. data/lib/legion/extensions/agentic/social/social.rb +18 -0
  110. data/lib/legion/extensions/agentic/social/social_learning/client.rb +25 -0
  111. data/lib/legion/extensions/agentic/social/social_learning/helpers/constants.rb +42 -0
  112. data/lib/legion/extensions/agentic/social/social_learning/helpers/model_agent.rb +82 -0
  113. data/lib/legion/extensions/agentic/social/social_learning/helpers/observed_behavior.rb +61 -0
  114. data/lib/legion/extensions/agentic/social/social_learning/helpers/social_learning_engine.rb +134 -0
  115. data/lib/legion/extensions/agentic/social/social_learning/runners/social_learning.rb +105 -0
  116. data/lib/legion/extensions/agentic/social/social_learning/version.rb +13 -0
  117. data/lib/legion/extensions/agentic/social/social_learning.rb +20 -0
  118. data/lib/legion/extensions/agentic/social/symbiosis/client.rb +23 -0
  119. data/lib/legion/extensions/agentic/social/symbiosis/helpers/constants.rb +50 -0
  120. data/lib/legion/extensions/agentic/social/symbiosis/helpers/ecosystem.rb +113 -0
  121. data/lib/legion/extensions/agentic/social/symbiosis/helpers/symbiosis_engine.rb +104 -0
  122. data/lib/legion/extensions/agentic/social/symbiosis/helpers/symbiotic_bond.rb +112 -0
  123. data/lib/legion/extensions/agentic/social/symbiosis/runners/cognitive_symbiosis.rb +101 -0
  124. data/lib/legion/extensions/agentic/social/symbiosis/version.rb +13 -0
  125. data/lib/legion/extensions/agentic/social/symbiosis.rb +22 -0
  126. data/lib/legion/extensions/agentic/social/theory_of_mind/client.rb +26 -0
  127. data/lib/legion/extensions/agentic/social/theory_of_mind/helpers/agent_model.rb +173 -0
  128. data/lib/legion/extensions/agentic/social/theory_of_mind/helpers/constants.rb +70 -0
  129. data/lib/legion/extensions/agentic/social/theory_of_mind/helpers/mental_state_tracker.rb +169 -0
  130. data/lib/legion/extensions/agentic/social/theory_of_mind/runners/theory_of_mind.rb +159 -0
  131. data/lib/legion/extensions/agentic/social/theory_of_mind/version.rb +13 -0
  132. data/lib/legion/extensions/agentic/social/theory_of_mind.rb +19 -0
  133. data/lib/legion/extensions/agentic/social/trust/actors/decay.rb +45 -0
  134. data/lib/legion/extensions/agentic/social/trust/client.rb +27 -0
  135. data/lib/legion/extensions/agentic/social/trust/helpers/trust_map.rb +160 -0
  136. data/lib/legion/extensions/agentic/social/trust/helpers/trust_model.rb +52 -0
  137. data/lib/legion/extensions/agentic/social/trust/local_migrations/20260316000020_create_trust_entries.rb +23 -0
  138. data/lib/legion/extensions/agentic/social/trust/runners/trust.rb +80 -0
  139. data/lib/legion/extensions/agentic/social/trust/version.rb +13 -0
  140. data/lib/legion/extensions/agentic/social/trust.rb +25 -0
  141. data/lib/legion/extensions/agentic/social/version.rb +11 -0
  142. data/lib/legion/extensions/agentic/social.rb +34 -0
  143. data/spec/legion/extensions/agentic/social/apprenticeship/client_spec.rb +20 -0
  144. data/spec/legion/extensions/agentic/social/apprenticeship/cognitive_apprenticeship_spec.rb +11 -0
  145. data/spec/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_engine_spec.rb +146 -0
  146. data/spec/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_model_spec.rb +124 -0
  147. data/spec/legion/extensions/agentic/social/apprenticeship/helpers/apprenticeship_spec.rb +136 -0
  148. data/spec/legion/extensions/agentic/social/apprenticeship/runners/cognitive_apprenticeship_spec.rb +154 -0
  149. data/spec/legion/extensions/agentic/social/conflict/actors/stale_check_spec.rb +45 -0
  150. data/spec/legion/extensions/agentic/social/conflict/client_spec.rb +15 -0
  151. data/spec/legion/extensions/agentic/social/conflict/helpers/conflict_log_spec.rb +232 -0
  152. data/spec/legion/extensions/agentic/social/conflict/helpers/llm_enhancer_spec.rb +189 -0
  153. data/spec/legion/extensions/agentic/social/conflict/helpers/severity_spec.rb +215 -0
  154. data/spec/legion/extensions/agentic/social/conflict/runners/conflict_spec.rb +151 -0
  155. data/spec/legion/extensions/agentic/social/conscience/client_spec.rb +58 -0
  156. data/spec/legion/extensions/agentic/social/conscience/helpers/constants_spec.rb +124 -0
  157. data/spec/legion/extensions/agentic/social/conscience/helpers/moral_evaluator_spec.rb +253 -0
  158. data/spec/legion/extensions/agentic/social/conscience/helpers/moral_store_spec.rb +230 -0
  159. data/spec/legion/extensions/agentic/social/conscience/runners/conscience_spec.rb +239 -0
  160. data/spec/legion/extensions/agentic/social/consent/actors/tier_evaluation_spec.rb +46 -0
  161. data/spec/legion/extensions/agentic/social/consent/client_spec.rb +33 -0
  162. data/spec/legion/extensions/agentic/social/consent/helpers/tiers_spec.rb +49 -0
  163. data/spec/legion/extensions/agentic/social/consent/local_persistence_spec.rb +234 -0
  164. data/spec/legion/extensions/agentic/social/consent/runners/consent_spec.rb +224 -0
  165. data/spec/legion/extensions/agentic/social/entrainment/client_spec.rb +21 -0
  166. data/spec/legion/extensions/agentic/social/entrainment/helpers/entrainment_engine_spec.rb +116 -0
  167. data/spec/legion/extensions/agentic/social/entrainment/helpers/pairing_spec.rb +103 -0
  168. data/spec/legion/extensions/agentic/social/entrainment/runners/cognitive_entrainment_spec.rb +87 -0
  169. data/spec/legion/extensions/agentic/social/governance/actors/vote_timeout_spec.rb +45 -0
  170. data/spec/legion/extensions/agentic/social/governance/client_spec.rb +14 -0
  171. data/spec/legion/extensions/agentic/social/governance/helpers/layers_spec.rb +190 -0
  172. data/spec/legion/extensions/agentic/social/governance/helpers/proposal_spec.rb +188 -0
  173. data/spec/legion/extensions/agentic/social/governance/runners/governance_spec.rb +101 -0
  174. data/spec/legion/extensions/agentic/social/governance/runners/shadow_ai_spec.rb +65 -0
  175. data/spec/legion/extensions/agentic/social/joint_attention/client_spec.rb +36 -0
  176. data/spec/legion/extensions/agentic/social/joint_attention/helpers/attention_target_spec.rb +258 -0
  177. data/spec/legion/extensions/agentic/social/joint_attention/helpers/joint_focus_manager_spec.rb +238 -0
  178. data/spec/legion/extensions/agentic/social/joint_attention/runners/joint_attention_spec.rb +228 -0
  179. data/spec/legion/extensions/agentic/social/mentalizing/client_spec.rb +19 -0
  180. data/spec/legion/extensions/agentic/social/mentalizing/helpers/belief_attribution_spec.rb +108 -0
  181. data/spec/legion/extensions/agentic/social/mentalizing/helpers/mental_model_spec.rb +179 -0
  182. data/spec/legion/extensions/agentic/social/mentalizing/runners/mentalizing_spec.rb +162 -0
  183. data/spec/legion/extensions/agentic/social/mirror/client_spec.rb +92 -0
  184. data/spec/legion/extensions/agentic/social/mirror/helpers/constants_spec.rb +123 -0
  185. data/spec/legion/extensions/agentic/social/mirror/helpers/mirror_engine_spec.rb +217 -0
  186. data/spec/legion/extensions/agentic/social/mirror/helpers/mirror_event_spec.rb +102 -0
  187. data/spec/legion/extensions/agentic/social/mirror/helpers/simulation_spec.rb +100 -0
  188. data/spec/legion/extensions/agentic/social/mirror/runners/observe_spec.rb +77 -0
  189. data/spec/legion/extensions/agentic/social/mirror/runners/resonance_spec.rb +123 -0
  190. data/spec/legion/extensions/agentic/social/mirror/runners/simulate_spec.rb +103 -0
  191. data/spec/legion/extensions/agentic/social/mirror_system/client_spec.rb +40 -0
  192. data/spec/legion/extensions/agentic/social/mirror_system/helpers/mirror_system_spec.rb +144 -0
  193. data/spec/legion/extensions/agentic/social/mirror_system/helpers/observed_behavior_spec.rb +98 -0
  194. data/spec/legion/extensions/agentic/social/mirror_system/runners/mirror_spec.rb +122 -0
  195. data/spec/legion/extensions/agentic/social/moral_reasoning/client_spec.rb +34 -0
  196. data/spec/legion/extensions/agentic/social/moral_reasoning/helpers/dilemma_spec.rb +108 -0
  197. data/spec/legion/extensions/agentic/social/moral_reasoning/helpers/llm_enhancer_spec.rb +232 -0
  198. data/spec/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine_spec.rb +266 -0
  199. data/spec/legion/extensions/agentic/social/moral_reasoning/helpers/moral_foundation_spec.rb +70 -0
  200. data/spec/legion/extensions/agentic/social/moral_reasoning/runners/moral_reasoning_spec.rb +275 -0
  201. data/spec/legion/extensions/agentic/social/perspective_shifting/client_spec.rb +30 -0
  202. data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/constants_spec.rb +99 -0
  203. data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/perspective_spec.rb +77 -0
  204. data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/perspective_view_spec.rb +105 -0
  205. data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/shifting_engine_spec.rb +246 -0
  206. data/spec/legion/extensions/agentic/social/perspective_shifting/runners/perspective_shifting_spec.rb +277 -0
  207. data/spec/legion/extensions/agentic/social/social/client_spec.rb +72 -0
  208. data/spec/legion/extensions/agentic/social/social/helpers/constants_spec.rb +99 -0
  209. data/spec/legion/extensions/agentic/social/social/helpers/social_graph_spec.rb +322 -0
  210. data/spec/legion/extensions/agentic/social/social/runners/social_spec.rb +220 -0
  211. data/spec/legion/extensions/agentic/social/social_learning/client_spec.rb +25 -0
  212. data/spec/legion/extensions/agentic/social/social_learning/helpers/constants_spec.rb +44 -0
  213. data/spec/legion/extensions/agentic/social/social_learning/helpers/model_agent_spec.rb +120 -0
  214. data/spec/legion/extensions/agentic/social/social_learning/helpers/observed_behavior_spec.rb +81 -0
  215. data/spec/legion/extensions/agentic/social/social_learning/helpers/social_learning_engine_spec.rb +196 -0
  216. data/spec/legion/extensions/agentic/social/social_learning/runners/social_learning_spec.rb +150 -0
  217. data/spec/legion/extensions/agentic/social/symbiosis/client_spec.rb +45 -0
  218. data/spec/legion/extensions/agentic/social/symbiosis/helpers/constants_spec.rb +73 -0
  219. data/spec/legion/extensions/agentic/social/symbiosis/helpers/ecosystem_spec.rb +185 -0
  220. data/spec/legion/extensions/agentic/social/symbiosis/helpers/symbiosis_engine_spec.rb +182 -0
  221. data/spec/legion/extensions/agentic/social/symbiosis/helpers/symbiotic_bond_spec.rb +209 -0
  222. data/spec/legion/extensions/agentic/social/symbiosis/runners/cognitive_symbiosis_spec.rb +182 -0
  223. data/spec/legion/extensions/agentic/social/theory_of_mind/client_spec.rb +63 -0
  224. data/spec/legion/extensions/agentic/social/theory_of_mind/helpers/agent_model_spec.rb +244 -0
  225. data/spec/legion/extensions/agentic/social/theory_of_mind/helpers/constants_spec.rb +71 -0
  226. data/spec/legion/extensions/agentic/social/theory_of_mind/helpers/mental_state_tracker_spec.rb +228 -0
  227. data/spec/legion/extensions/agentic/social/theory_of_mind/runners/theory_of_mind_spec.rb +221 -0
  228. data/spec/legion/extensions/agentic/social/trust/actors/decay_spec.rb +62 -0
  229. data/spec/legion/extensions/agentic/social/trust/client_spec.rb +17 -0
  230. data/spec/legion/extensions/agentic/social/trust/helpers/trust_map_spec.rb +299 -0
  231. data/spec/legion/extensions/agentic/social/trust/helpers/trust_model_spec.rb +179 -0
  232. data/spec/legion/extensions/agentic/social/trust/local_persistence_spec.rb +359 -0
  233. data/spec/legion/extensions/agentic/social/trust/runners/trust_spec.rb +84 -0
  234. data/spec/spec_helper.rb +54 -0
  235. metadata +319 -0
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::SocialLearning::Helpers::ModelAgent do
4
+ subject(:model) do
5
+ described_class.new(agent_id: 'agent-abc', domain: :ops, prestige: 0.5)
6
+ end
7
+
8
+ describe '#initialize' do
9
+ it 'assigns a uuid id' do
10
+ expect(model.id).to match(/\A[0-9a-f-]{36}\z/)
11
+ end
12
+
13
+ it 'sets the agent_id' do
14
+ expect(model.agent_id).to eq('agent-abc')
15
+ end
16
+
17
+ it 'sets prestige' do
18
+ expect(model.prestige).to eq(0.5)
19
+ end
20
+
21
+ it 'starts with zero observation_count' do
22
+ expect(model.observation_count).to eq(0)
23
+ end
24
+
25
+ it 'starts with empty observed_behaviors' do
26
+ expect(model.observed_behaviors).to be_empty
27
+ end
28
+
29
+ it 'clamps prestige above ceiling to 1.0' do
30
+ m = described_class.new(agent_id: 'x', domain: :test, prestige: 5.0)
31
+ expect(m.prestige).to eq(1.0)
32
+ end
33
+
34
+ it 'clamps prestige below floor to 0.0' do
35
+ m = described_class.new(agent_id: 'x', domain: :test, prestige: -1.0)
36
+ expect(m.prestige).to eq(0.0)
37
+ end
38
+ end
39
+
40
+ describe '#observe!' do
41
+ let(:fake_behavior) { double('ObservedBehavior') }
42
+
43
+ it 'increments observation_count' do
44
+ expect { model.observe!(behavior: fake_behavior, outcome: :neutral) }
45
+ .to change(model, :observation_count).by(1)
46
+ end
47
+
48
+ it 'increases prestige on positive outcome' do
49
+ before = model.prestige
50
+ model.observe!(behavior: fake_behavior, outcome: :positive)
51
+ expect(model.prestige).to be > before
52
+ end
53
+
54
+ it 'decreases prestige on negative outcome' do
55
+ before = model.prestige
56
+ model.observe!(behavior: fake_behavior, outcome: :negative)
57
+ expect(model.prestige).to be < before
58
+ end
59
+
60
+ it 'does not change prestige on neutral outcome' do
61
+ before = model.prestige
62
+ model.observe!(behavior: fake_behavior, outcome: :neutral)
63
+ expect(model.prestige).to eq(before)
64
+ end
65
+
66
+ it 'tracks success_count for positive outcomes' do
67
+ model.observe!(behavior: fake_behavior, outcome: :positive)
68
+ expect(model.success_count).to eq(1)
69
+ end
70
+ end
71
+
72
+ describe '#prestige_label' do
73
+ it 'returns :expert for prestige >= 0.8' do
74
+ model.prestige = 0.9
75
+ expect(model.prestige_label).to eq(:expert)
76
+ end
77
+
78
+ it 'returns :proficient for prestige in 0.6...0.8' do
79
+ model.prestige = 0.7
80
+ expect(model.prestige_label).to eq(:proficient)
81
+ end
82
+
83
+ it 'returns :peer for prestige in 0.4...0.6' do
84
+ model.prestige = 0.5
85
+ expect(model.prestige_label).to eq(:peer)
86
+ end
87
+
88
+ it 'returns :novice for prestige in 0.2...0.4' do
89
+ model.prestige = 0.3
90
+ expect(model.prestige_label).to eq(:novice)
91
+ end
92
+
93
+ it 'returns :unreliable for prestige below 0.2' do
94
+ model.prestige = 0.1
95
+ expect(model.prestige_label).to eq(:unreliable)
96
+ end
97
+ end
98
+
99
+ describe '#success_rate' do
100
+ it 'returns 0.0 with no observations' do
101
+ expect(model.success_rate).to eq(0.0)
102
+ end
103
+
104
+ it 'returns correct ratio after observations' do
105
+ fake_behavior = double('ObservedBehavior')
106
+ model.observe!(behavior: fake_behavior, outcome: :positive)
107
+ model.observe!(behavior: fake_behavior, outcome: :negative)
108
+ expect(model.success_rate).to eq(0.5)
109
+ end
110
+ end
111
+
112
+ describe '#to_h' do
113
+ it 'returns a hash with expected keys' do
114
+ hash = model.to_h
115
+ expect(hash).to include(:id, :agent_id, :domain, :prestige, :prestige_label,
116
+ :observation_count, :success_count, :success_rate,
117
+ :behavior_count, :created_at)
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::SocialLearning::Helpers::ObservedBehavior do
4
+ subject(:behavior) do
5
+ described_class.new(
6
+ model_agent_id: 'model-123',
7
+ action: 'write_test',
8
+ domain: :coding,
9
+ outcome: :positive,
10
+ context: { language: 'ruby' }
11
+ )
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'assigns a uuid id' do
16
+ expect(behavior.id).to match(/\A[0-9a-f-]{36}\z/)
17
+ end
18
+
19
+ it 'sets retention to 1.0' do
20
+ expect(behavior.retention).to eq(1.0)
21
+ end
22
+
23
+ it 'sets reproduced to false' do
24
+ expect(behavior.reproduced).to be false
25
+ end
26
+
27
+ it 'stores the action' do
28
+ expect(behavior.action).to eq('write_test')
29
+ end
30
+
31
+ it 'stores the domain' do
32
+ expect(behavior.domain).to eq(:coding)
33
+ end
34
+
35
+ it 'stores the outcome' do
36
+ expect(behavior.outcome).to eq(:positive)
37
+ end
38
+
39
+ it 'stores context' do
40
+ expect(behavior.context).to eq({ language: 'ruby' })
41
+ end
42
+ end
43
+
44
+ describe '#decay_retention!' do
45
+ it 'reduces retention by RETENTION_DECAY' do
46
+ before = behavior.retention
47
+ behavior.decay_retention!
48
+ expect(behavior.retention).to be < before
49
+ end
50
+
51
+ it 'does not go below 0.0' do
52
+ 50.times { behavior.decay_retention! }
53
+ expect(behavior.retention).to be >= 0.0
54
+ end
55
+ end
56
+
57
+ describe '#retained?' do
58
+ it 'returns true when retention is above REPRODUCTION_CONFIDENCE' do
59
+ expect(behavior.retained?).to be true
60
+ end
61
+
62
+ it 'returns false when retention has decayed below threshold' do
63
+ behavior.retention = 0.4
64
+ expect(behavior.retained?).to be false
65
+ end
66
+ end
67
+
68
+ describe '#to_h' do
69
+ it 'returns a hash with expected keys' do
70
+ hash = behavior.to_h
71
+ expect(hash).to include(:id, :model_agent_id, :action, :domain, :outcome,
72
+ :retention, :reproduced, :retained, :created_at)
73
+ end
74
+
75
+ it 'rounds retention to 4 decimal places' do
76
+ behavior.decay_retention!
77
+ hash = behavior.to_h
78
+ expect(hash[:retention].to_s.split('.').last.length).to be <= 4
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::SocialLearning::Helpers::SocialLearningEngine do
4
+ subject(:engine) { described_class.new }
5
+
6
+ let(:model) { engine.register_model(agent_id: 'agent-1', domain: :coding) }
7
+
8
+ describe '#register_model' do
9
+ it 'returns a ModelAgent' do
10
+ expect(model).to be_a(Legion::Extensions::Agentic::Social::SocialLearning::Helpers::ModelAgent)
11
+ end
12
+
13
+ it 'assigns agent_id and domain' do
14
+ expect(model.agent_id).to eq('agent-1')
15
+ expect(model.domain).to eq(:coding)
16
+ end
17
+
18
+ it 'uses DEFAULT_PRESTIGE when none given' do
19
+ expect(model.prestige).to eq(Legion::Extensions::Agentic::Social::SocialLearning::Helpers::Constants::DEFAULT_PRESTIGE)
20
+ end
21
+ end
22
+
23
+ describe '#observe_behavior' do
24
+ it 'returns nil for unknown model' do
25
+ result = engine.observe_behavior(
26
+ model_id: 'nonexistent', action: 'do_thing', domain: :coding, outcome: :positive
27
+ )
28
+ expect(result).to be_nil
29
+ end
30
+
31
+ it 'returns nil when model prestige is below ATTENTION_THRESHOLD' do
32
+ low_model = engine.register_model(agent_id: 'low', domain: :coding, prestige: 0.1)
33
+ result = engine.observe_behavior(
34
+ model_id: low_model.id, action: 'do_thing', domain: :coding, outcome: :positive
35
+ )
36
+ expect(result).to be_nil
37
+ end
38
+
39
+ it 'returns an ObservedBehavior when model passes attention threshold' do
40
+ behavior = engine.observe_behavior(
41
+ model_id: model.id, action: 'write_test', domain: :coding, outcome: :positive
42
+ )
43
+ expect(behavior).to be_a(Legion::Extensions::Agentic::Social::SocialLearning::Helpers::ObservedBehavior)
44
+ end
45
+
46
+ it 'updates model prestige on positive outcome' do
47
+ before = model.prestige
48
+ engine.observe_behavior(
49
+ model_id: model.id, action: 'write_test', domain: :coding, outcome: :positive
50
+ )
51
+ expect(model.prestige).to be > before
52
+ end
53
+ end
54
+
55
+ describe '#retained_behaviors' do
56
+ before do
57
+ engine.observe_behavior(
58
+ model_id: model.id, action: 'action_a', domain: :coding, outcome: :positive
59
+ )
60
+ end
61
+
62
+ it 'returns behaviors with retention above REPRODUCTION_CONFIDENCE' do
63
+ result = engine.retained_behaviors
64
+ expect(result).not_to be_empty
65
+ end
66
+
67
+ it 'filters by domain when given' do
68
+ engine.observe_behavior(
69
+ model_id: model.id, action: 'action_b', domain: :ops, outcome: :positive
70
+ )
71
+ result = engine.retained_behaviors(domain: :coding)
72
+ expect(result.all? { |beh| beh.domain == :coding }).to be true
73
+ end
74
+ end
75
+
76
+ describe '#reproducible_behaviors' do
77
+ it 'returns behaviors above REPRODUCTION_CONFIDENCE' do
78
+ engine.observe_behavior(
79
+ model_id: model.id, action: 'write_test', domain: :coding, outcome: :positive
80
+ )
81
+ result = engine.reproducible_behaviors
82
+ expect(result).not_to be_empty
83
+ end
84
+ end
85
+
86
+ describe '#reproduce_behavior' do
87
+ let(:behavior) do
88
+ engine.observe_behavior(
89
+ model_id: model.id, action: 'write_test', domain: :coding, outcome: :positive
90
+ )
91
+ end
92
+
93
+ it 'marks the behavior as reproduced' do
94
+ engine.reproduce_behavior(behavior_id: behavior.id)
95
+ expect(behavior.reproduced).to be true
96
+ end
97
+
98
+ it 'returns nil for unknown behavior_id' do
99
+ result = engine.reproduce_behavior(behavior_id: 'nonexistent')
100
+ expect(result).to be_nil
101
+ end
102
+ end
103
+
104
+ describe '#reinforce_reproduction' do
105
+ let(:behavior) do
106
+ engine.observe_behavior(
107
+ model_id: model.id, action: 'write_test', domain: :coding, outcome: :positive
108
+ )
109
+ end
110
+
111
+ it 'boosts model prestige on positive outcome' do
112
+ before = model.prestige
113
+ engine.reinforce_reproduction(behavior_id: behavior.id, outcome: :positive)
114
+ expect(model.prestige).to be > before
115
+ end
116
+
117
+ it 'penalizes model prestige on negative outcome' do
118
+ before = model.prestige
119
+ engine.reinforce_reproduction(behavior_id: behavior.id, outcome: :negative)
120
+ expect(model.prestige).to be < before
121
+ end
122
+
123
+ it 'returns nil for unknown behavior_id' do
124
+ result = engine.reinforce_reproduction(behavior_id: 'nonexistent', outcome: :positive)
125
+ expect(result).to be_nil
126
+ end
127
+
128
+ it 'returns a hash with behavior and model_prestige' do
129
+ result = engine.reinforce_reproduction(behavior_id: behavior.id, outcome: :positive)
130
+ expect(result).to include(:behavior, :model_prestige)
131
+ end
132
+ end
133
+
134
+ describe '#best_models' do
135
+ before do
136
+ engine.register_model(agent_id: 'agent-2', domain: :ops, prestige: 0.9)
137
+ engine.register_model(agent_id: 'agent-3', domain: :coding, prestige: 0.3)
138
+ end
139
+
140
+ it 'returns models sorted by prestige descending' do
141
+ models = engine.best_models(limit: 3)
142
+ prestiges = models.map(&:prestige)
143
+ expect(prestiges).to eq(prestiges.sort.reverse)
144
+ end
145
+
146
+ it 'respects the limit' do
147
+ models = engine.best_models(limit: 2)
148
+ expect(models.size).to be <= 2
149
+ end
150
+ end
151
+
152
+ describe '#by_domain' do
153
+ before do
154
+ engine.register_model(agent_id: 'agent-ops', domain: :ops)
155
+ end
156
+
157
+ it 'returns only models in the given domain' do
158
+ result = engine.by_domain(domain: :ops)
159
+ expect(result.all? { |mod| mod.domain == :ops }).to be true
160
+ end
161
+
162
+ it 'returns empty array for unknown domain' do
163
+ result = engine.by_domain(domain: :unknown_domain)
164
+ expect(result).to be_empty
165
+ end
166
+ end
167
+
168
+ describe '#decay_all' do
169
+ it 'decays retention on all behaviors' do
170
+ behavior = engine.observe_behavior(
171
+ model_id: model.id, action: 'write_test', domain: :coding, outcome: :positive
172
+ )
173
+ before = behavior.retention
174
+ engine.decay_all
175
+ expect(behavior.retention).to be < before
176
+ end
177
+ end
178
+
179
+ describe '#prune_forgotten' do
180
+ it 'removes behaviors below 0.05 retention' do
181
+ behavior = engine.observe_behavior(
182
+ model_id: model.id, action: 'write_test', domain: :coding, outcome: :positive
183
+ )
184
+ behavior.retention = 0.04
185
+ engine.prune_forgotten
186
+ expect(engine.retained_behaviors).not_to include(behavior)
187
+ end
188
+ end
189
+
190
+ describe '#to_h' do
191
+ it 'returns stats hash' do
192
+ result = engine.to_h
193
+ expect(result).to include(:model_count, :behavior_count, :retained_count, :reproducible_count)
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::SocialLearning::Runners::SocialLearning do
4
+ let(:client) { Legion::Extensions::Agentic::Social::SocialLearning::Client.new }
5
+
6
+ describe '#register_model_agent' do
7
+ it 'returns success with model hash' do
8
+ result = client.register_model_agent(agent_id: 'agent-1', domain: :coding)
9
+ expect(result[:success]).to be true
10
+ expect(result[:model]).to include(:id, :agent_id, :domain, :prestige)
11
+ end
12
+
13
+ it 'accepts custom prestige' do
14
+ result = client.register_model_agent(agent_id: 'agent-1', domain: :coding, prestige: 0.8)
15
+ expect(result[:model][:prestige]).to eq(0.8)
16
+ end
17
+ end
18
+
19
+ describe '#observe_agent_behavior' do
20
+ let(:model_id) do
21
+ client.register_model_agent(agent_id: 'agent-1', domain: :coding)[:model][:id]
22
+ end
23
+
24
+ it 'returns success with behavior hash when model passes attention threshold' do
25
+ result = client.observe_agent_behavior(
26
+ model_id: model_id, action: 'write_test', domain: :coding, outcome: :positive
27
+ )
28
+ expect(result[:success]).to be true
29
+ expect(result[:behavior]).to include(:id, :action, :retention)
30
+ end
31
+
32
+ it 'returns success: false for unknown model_id' do
33
+ result = client.observe_agent_behavior(
34
+ model_id: 'nonexistent', action: 'do_thing', domain: :coding, outcome: :positive
35
+ )
36
+ expect(result[:success]).to be false
37
+ end
38
+ end
39
+
40
+ describe '#retained_behaviors' do
41
+ before do
42
+ model_id = client.register_model_agent(agent_id: 'agent-1', domain: :coding)[:model][:id]
43
+ client.observe_agent_behavior(
44
+ model_id: model_id, action: 'write_test', domain: :coding, outcome: :positive
45
+ )
46
+ end
47
+
48
+ it 'returns behaviors with count' do
49
+ result = client.retained_behaviors
50
+ expect(result[:success]).to be true
51
+ expect(result).to include(:behaviors, :count)
52
+ end
53
+
54
+ it 'filters by domain' do
55
+ result = client.retained_behaviors(domain: :coding)
56
+ expect(result[:behaviors].all? { |beh| beh[:domain] == :coding }).to be true
57
+ end
58
+ end
59
+
60
+ describe '#reproducible_behaviors' do
61
+ it 'returns success: true with behaviors list' do
62
+ result = client.reproducible_behaviors
63
+ expect(result[:success]).to be true
64
+ expect(result).to include(:behaviors, :count)
65
+ end
66
+ end
67
+
68
+ describe '#reproduce_observed_behavior' do
69
+ let(:behavior_id) do
70
+ model_id = client.register_model_agent(agent_id: 'agent-1', domain: :coding)[:model][:id]
71
+ client.observe_agent_behavior(
72
+ model_id: model_id, action: 'write_test', domain: :coding, outcome: :positive
73
+ )[:behavior][:id]
74
+ end
75
+
76
+ it 'returns success with reproduced behavior' do
77
+ result = client.reproduce_observed_behavior(behavior_id: behavior_id)
78
+ expect(result[:success]).to be true
79
+ expect(result[:behavior][:reproduced]).to be true
80
+ end
81
+
82
+ it 'returns success: false for unknown behavior_id' do
83
+ result = client.reproduce_observed_behavior(behavior_id: 'nonexistent')
84
+ expect(result[:success]).to be false
85
+ end
86
+ end
87
+
88
+ describe '#reinforce_reproduction' do
89
+ let(:behavior_id) do
90
+ model_id = client.register_model_agent(agent_id: 'agent-1', domain: :coding)[:model][:id]
91
+ client.observe_agent_behavior(
92
+ model_id: model_id, action: 'write_test', domain: :coding, outcome: :positive
93
+ )[:behavior][:id]
94
+ end
95
+
96
+ it 'returns success with model_prestige on positive outcome' do
97
+ result = client.reinforce_reproduction(behavior_id: behavior_id, outcome: :positive)
98
+ expect(result[:success]).to be true
99
+ expect(result[:model_prestige]).to be_a(Float)
100
+ end
101
+
102
+ it 'returns success: false for unknown behavior_id' do
103
+ result = client.reinforce_reproduction(behavior_id: 'nonexistent', outcome: :positive)
104
+ expect(result[:success]).to be false
105
+ end
106
+ end
107
+
108
+ describe '#best_model_agents' do
109
+ before do
110
+ client.register_model_agent(agent_id: 'agent-1', domain: :coding, prestige: 0.9)
111
+ client.register_model_agent(agent_id: 'agent-2', domain: :ops, prestige: 0.4)
112
+ end
113
+
114
+ it 'returns models sorted by prestige' do
115
+ result = client.best_model_agents(limit: 2)
116
+ expect(result[:success]).to be true
117
+ prestiges = result[:models].map { |mod| mod[:prestige] }
118
+ expect(prestiges).to eq(prestiges.sort.reverse)
119
+ end
120
+ end
121
+
122
+ describe '#domain_models' do
123
+ before do
124
+ client.register_model_agent(agent_id: 'agent-1', domain: :coding)
125
+ client.register_model_agent(agent_id: 'agent-2', domain: :ops)
126
+ end
127
+
128
+ it 'returns only models for the given domain' do
129
+ result = client.domain_models(domain: :coding)
130
+ expect(result[:success]).to be true
131
+ expect(result[:models].all? { |mod| mod[:domain] == :coding }).to be true
132
+ end
133
+ end
134
+
135
+ describe '#update_social_learning' do
136
+ it 'returns success with stats' do
137
+ result = client.update_social_learning
138
+ expect(result[:success]).to be true
139
+ expect(result).to include(:model_count, :behavior_count)
140
+ end
141
+ end
142
+
143
+ describe '#social_learning_stats' do
144
+ it 'returns success with stats hash' do
145
+ result = client.social_learning_stats
146
+ expect(result[:success]).to be true
147
+ expect(result).to include(:model_count, :behavior_count, :retained_count, :reproducible_count)
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/social/symbiosis/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Social::Symbiosis::Client do
6
+ subject(:client) { described_class.new }
7
+
8
+ it 'responds to create_bond' do
9
+ expect(client).to respond_to(:create_bond)
10
+ end
11
+
12
+ it 'responds to activate' do
13
+ expect(client).to respond_to(:activate)
14
+ end
15
+
16
+ it 'responds to health_status' do
17
+ expect(client).to respond_to(:health_status)
18
+ end
19
+
20
+ it 'responds to list_bonds' do
21
+ expect(client).to respond_to(:list_bonds)
22
+ end
23
+
24
+ it 'responds to detect_parasites' do
25
+ expect(client).to respond_to(:detect_parasites)
26
+ end
27
+
28
+ it 'responds to ecosystem_report' do
29
+ expect(client).to respond_to(:ecosystem_report)
30
+ end
31
+
32
+ it 'creates a fresh engine per instance' do
33
+ c1 = described_class.new
34
+ c2 = described_class.new
35
+ c1.create_bond(subsystem_a: 'a', subsystem_b: 'b', relationship_type: :mutualistic)
36
+ expect(c2.list_bonds[:count]).to eq(0)
37
+ end
38
+
39
+ it 'maintains state across calls on same instance' do
40
+ client.create_bond(subsystem_a: 'memory', subsystem_b: 'emotion', relationship_type: :mutualistic)
41
+ expect(client.list_bonds[:count]).to eq(1)
42
+ client.create_bond(subsystem_a: 'trust', subsystem_b: 'consent', relationship_type: :mutualistic)
43
+ expect(client.list_bonds[:count]).to eq(2)
44
+ end
45
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::Symbiosis::Helpers::Constants do
4
+ describe 'RELATIONSHIP_TYPES' do
5
+ it 'contains the three canonical types' do
6
+ expect(described_class::RELATIONSHIP_TYPES).to contain_exactly(:mutualistic, :parasitic, :commensal)
7
+ end
8
+
9
+ it 'is frozen' do
10
+ expect(described_class::RELATIONSHIP_TYPES).to be_frozen
11
+ end
12
+ end
13
+
14
+ describe 'INTERACTION_STRENGTHS' do
15
+ it 'maps range 0.0..0.2 to :dormant' do
16
+ label = described_class::INTERACTION_STRENGTHS.find { |range, _| range.cover?(0.1) }&.last
17
+ expect(label).to eq(:dormant)
18
+ end
19
+
20
+ it 'maps range 0.6..0.8 to :strong' do
21
+ label = described_class::INTERACTION_STRENGTHS.find { |range, _| range.cover?(0.7) }&.last
22
+ expect(label).to eq(:strong)
23
+ end
24
+
25
+ it 'maps range 0.8..1.0 to :dominant' do
26
+ label = described_class::INTERACTION_STRENGTHS.find { |range, _| range.cover?(0.9) }&.last
27
+ expect(label).to eq(:dominant)
28
+ end
29
+ end
30
+
31
+ describe 'MAX_BONDS' do
32
+ it 'is 200' do
33
+ expect(described_class::MAX_BONDS).to eq(200)
34
+ end
35
+ end
36
+
37
+ describe 'BOND_DECAY' do
38
+ it 'is a positive float' do
39
+ expect(described_class::BOND_DECAY).to be > 0
40
+ expect(described_class::BOND_DECAY).to be < 1
41
+ end
42
+ end
43
+
44
+ describe 'BENEFIT_RATIO_RANGES' do
45
+ it 'has positive range for mutualistic' do
46
+ range = described_class::BENEFIT_RATIO_RANGES[:mutualistic]
47
+ expect(range.min).to be > 0
48
+ end
49
+
50
+ it 'has negative range for parasitic' do
51
+ range = described_class::BENEFIT_RATIO_RANGES[:parasitic]
52
+ expect(range.max).to be < 0
53
+ end
54
+
55
+ it 'has near-zero range for commensal' do
56
+ range = described_class::BENEFIT_RATIO_RANGES[:commensal]
57
+ expect(range.min.abs).to be < 0.1
58
+ expect(range.max.abs).to be < 0.1
59
+ end
60
+ end
61
+
62
+ describe 'ECOSYSTEM_HEALTH_LABELS' do
63
+ it 'maps 0.0..0.2 to :critical' do
64
+ label = described_class::ECOSYSTEM_HEALTH_LABELS.find { |range, _| range.cover?(0.1) }&.last
65
+ expect(label).to eq(:critical)
66
+ end
67
+
68
+ it 'maps 0.8..1.0 to :flourishing' do
69
+ label = described_class::ECOSYSTEM_HEALTH_LABELS.find { |range, _| range.cover?(0.9) }&.last
70
+ expect(label).to eq(:flourishing)
71
+ end
72
+ end
73
+ end