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,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Social
7
+ module Social
8
+ module Helpers
9
+ class SocialGraph
10
+ attr_reader :groups, :reputation_scores, :reciprocity_ledger
11
+
12
+ def initialize
13
+ @groups = {}
14
+ @reputation_scores = {}
15
+ @reciprocity_ledger = []
16
+ end
17
+
18
+ def join_group(group_id:, role: :contributor, members: [])
19
+ @groups[group_id] ||= {
20
+ role: role,
21
+ members: members.dup,
22
+ joined_at: Time.now.utc,
23
+ norms: [],
24
+ cohesion: 0.5,
25
+ violations: []
26
+ }
27
+ trim_groups
28
+ @groups[group_id]
29
+ end
30
+
31
+ def leave_group(group_id)
32
+ @groups.delete(group_id)
33
+ end
34
+
35
+ def update_role(group_id:, role:)
36
+ return nil unless @groups.key?(group_id)
37
+ return nil unless Constants::ROLES.include?(role)
38
+
39
+ @groups[group_id][:role] = role
40
+ end
41
+
42
+ def update_reputation(agent_id:, dimension:, signal:)
43
+ return nil unless Constants::REPUTATION_DIMENSIONS.key?(dimension)
44
+
45
+ @reputation_scores[agent_id] ||= Constants::REPUTATION_DIMENSIONS.keys.to_h { |d| [d, 0.5] }
46
+ current = @reputation_scores[agent_id][dimension]
47
+ @reputation_scores[agent_id][dimension] = ema(current, signal.clamp(0.0, 1.0), Constants::REPUTATION_ALPHA)
48
+ end
49
+
50
+ def reputation_for(agent_id)
51
+ scores = @reputation_scores[agent_id]
52
+ return nil unless scores
53
+
54
+ composite = 0.0
55
+ Constants::REPUTATION_DIMENSIONS.each do |dim, config|
56
+ composite += scores[dim] * config[:weight]
57
+ end
58
+
59
+ {
60
+ agent_id: agent_id,
61
+ scores: scores.transform_values { |v| v.round(4) },
62
+ composite: composite.round(4),
63
+ standing: classify_standing(composite)
64
+ }
65
+ end
66
+
67
+ def social_standing
68
+ return :neutral if @reputation_scores.empty?
69
+
70
+ all_composites = @reputation_scores.map { |id, _| reputation_for(id)[:composite] }
71
+ avg = all_composites.sum / all_composites.size.to_f
72
+ classify_standing(avg)
73
+ end
74
+
75
+ def record_reciprocity(agent_id:, action:, direction:)
76
+ @reciprocity_ledger << {
77
+ agent_id: agent_id,
78
+ action: action,
79
+ direction: direction,
80
+ at: Time.now.utc
81
+ }
82
+ @reciprocity_ledger.shift while @reciprocity_ledger.size > Constants::RECIPROCITY_WINDOW
83
+ end
84
+
85
+ def reciprocity_balance(agent_id)
86
+ entries = @reciprocity_ledger.select { |e| e[:agent_id] == agent_id }
87
+ given = entries.count { |e| e[:direction] == :given }
88
+ received = entries.count { |e| e[:direction] == :received }
89
+
90
+ { given: given, received: received, balance: given - received }
91
+ end
92
+
93
+ def record_violation(group_id:, type:, agent_id:)
94
+ return nil unless @groups.key?(group_id)
95
+ return nil unless Constants::NORM_VIOLATIONS.include?(type)
96
+
97
+ violation = { type: type, agent_id: agent_id, at: Time.now.utc }
98
+ @groups[group_id][:violations] << violation
99
+ reduce_cohesion(group_id, 0.1)
100
+ violation
101
+ end
102
+
103
+ def group_cohesion(group_id)
104
+ return nil unless @groups.key?(group_id)
105
+
106
+ @groups[group_id][:cohesion]
107
+ end
108
+
109
+ def update_cohesion(group_id:, signal:)
110
+ return nil unless @groups.key?(group_id)
111
+
112
+ current = @groups[group_id][:cohesion]
113
+ @groups[group_id][:cohesion] = ema(current, signal.clamp(0.0, 1.0), Constants::REPUTATION_ALPHA)
114
+ end
115
+
116
+ def classify_cohesion(group_id)
117
+ cohesion = group_cohesion(group_id)
118
+ return nil unless cohesion
119
+
120
+ Constants::COHESION_LEVELS.each do |level, threshold|
121
+ return level if cohesion >= threshold
122
+ end
123
+ :fractured
124
+ end
125
+
126
+ def group_count
127
+ @groups.size
128
+ end
129
+
130
+ def agents_tracked
131
+ @reputation_scores.keys.size
132
+ end
133
+
134
+ def to_h
135
+ {
136
+ groups: @groups.keys,
137
+ group_count: @groups.size,
138
+ agents_tracked: agents_tracked,
139
+ social_standing: social_standing,
140
+ ledger_size: @reciprocity_ledger.size
141
+ }
142
+ end
143
+
144
+ private
145
+
146
+ def ema(current, observed, alpha)
147
+ (current * (1.0 - alpha)) + (observed * alpha)
148
+ end
149
+
150
+ def classify_standing(composite)
151
+ Constants::STANDING_LEVELS.each do |level, threshold|
152
+ return level if composite >= threshold
153
+ end
154
+ :ostracized
155
+ end
156
+
157
+ def reduce_cohesion(group_id, amount)
158
+ current = @groups[group_id][:cohesion]
159
+ @groups[group_id][:cohesion] = [current - amount, 0.0].max
160
+ end
161
+
162
+ def trim_groups
163
+ oldest = @groups.keys.sort_by { |k| @groups[k][:joined_at] }
164
+ oldest.first([@groups.size - Constants::MAX_GROUPS, 0].max).each { |k| @groups.delete(k) }
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Social
7
+ module Social
8
+ module Runners
9
+ module Social
10
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
11
+ Legion::Extensions::Helpers.const_defined?(:Lex)
12
+
13
+ def update_social(tick_results: {}, **)
14
+ extract_social_signals(tick_results)
15
+
16
+ Legion::Logging.debug "[social] groups=#{social_graph.group_count} " \
17
+ "agents=#{social_graph.agents_tracked} standing=#{social_graph.social_standing}"
18
+
19
+ {
20
+ groups: social_graph.group_count,
21
+ agents_tracked: social_graph.agents_tracked,
22
+ standing: social_graph.social_standing,
23
+ ledger_size: social_graph.reciprocity_ledger.size
24
+ }
25
+ end
26
+
27
+ def join_group(group_id:, role: :contributor, members: [], **)
28
+ group = social_graph.join_group(group_id: group_id, role: role, members: members)
29
+ Legion::Logging.info "[social] joined group=#{group_id} role=#{role}"
30
+ { success: true, group_id: group_id, role: role, group: group }
31
+ end
32
+
33
+ def leave_group(group_id:, **)
34
+ social_graph.leave_group(group_id)
35
+ Legion::Logging.info "[social] left group=#{group_id}"
36
+ { success: true, group_id: group_id }
37
+ end
38
+
39
+ def update_reputation(agent_id:, dimension:, signal:, **)
40
+ result = social_graph.update_reputation(agent_id: agent_id, dimension: dimension.to_sym, signal: signal)
41
+ return { success: false, error: 'invalid dimension' } unless result
42
+
43
+ rep = social_graph.reputation_for(agent_id)
44
+ Legion::Logging.debug "[social] reputation updated agent=#{agent_id} dim=#{dimension}"
45
+ { success: true, reputation: rep }
46
+ end
47
+
48
+ def agent_reputation(agent_id:, **)
49
+ rep = social_graph.reputation_for(agent_id)
50
+ return { error: 'unknown agent' } unless rep
51
+
52
+ Legion::Logging.debug "[social] reputation for #{agent_id}: #{rep[:composite]}"
53
+ rep
54
+ end
55
+
56
+ def reciprocity_status(agent_id:, **)
57
+ balance = social_graph.reciprocity_balance(agent_id)
58
+ Legion::Logging.debug "[social] reciprocity #{agent_id}: #{balance}"
59
+ balance
60
+ end
61
+
62
+ def record_exchange(agent_id:, action:, direction:, **)
63
+ social_graph.record_reciprocity(agent_id: agent_id, action: action, direction: direction.to_sym)
64
+ Legion::Logging.debug "[social] exchange agent=#{agent_id} dir=#{direction}"
65
+ { success: true }
66
+ end
67
+
68
+ def report_violation(group_id:, type:, agent_id:, **)
69
+ violation = social_graph.record_violation(group_id: group_id, type: type.to_sym, agent_id: agent_id)
70
+ return { success: false, error: 'invalid group or violation type' } unless violation
71
+
72
+ Legion::Logging.warn "[social] violation: #{type} by #{agent_id} in #{group_id}"
73
+ { success: true, violation: violation, cohesion: social_graph.group_cohesion(group_id)&.round(4) }
74
+ end
75
+
76
+ def group_status(group_id:, **)
77
+ return { error: 'unknown group' } unless social_graph.groups.key?(group_id)
78
+
79
+ group = social_graph.groups[group_id]
80
+ {
81
+ group_id: group_id,
82
+ role: group[:role],
83
+ members: group[:members].size,
84
+ cohesion: group[:cohesion].round(4),
85
+ cohesion_level: social_graph.classify_cohesion(group_id),
86
+ violations: group[:violations].size
87
+ }
88
+ end
89
+
90
+ def social_status(**)
91
+ state = social_graph.to_h
92
+ Legion::Logging.debug "[social] status: #{state[:social_standing]}"
93
+ state
94
+ end
95
+
96
+ def social_stats(**)
97
+ Legion::Logging.debug '[social] stats'
98
+
99
+ {
100
+ groups: social_graph.group_count,
101
+ agents_tracked: social_graph.agents_tracked,
102
+ standing: social_graph.social_standing,
103
+ ledger_size: social_graph.reciprocity_ledger.size,
104
+ group_roles: social_graph.groups.transform_values { |g| g[:role] }
105
+ }
106
+ end
107
+
108
+ private
109
+
110
+ def social_graph
111
+ @social_graph ||= Helpers::SocialGraph.new
112
+ end
113
+
114
+ def extract_social_signals(tick_results)
115
+ extract_trust_signals(tick_results)
116
+ extract_mesh_signals(tick_results)
117
+ end
118
+
119
+ def extract_trust_signals(tick_results)
120
+ trust_updates = tick_results.dig(:trust, :updates)
121
+ return unless trust_updates.is_a?(Array)
122
+
123
+ trust_updates.each do |update|
124
+ social_graph.update_reputation(
125
+ agent_id: update[:agent_id],
126
+ dimension: :reliability,
127
+ signal: update[:score] || 0.5
128
+ )
129
+ end
130
+ end
131
+
132
+ def extract_mesh_signals(tick_results)
133
+ peer_count = tick_results.dig(:mesh_interface, :peer_count) || 0
134
+ return if peer_count.zero?
135
+
136
+ social_graph.groups.each_key do |group_id|
137
+ social_graph.update_cohesion(group_id: group_id, signal: [peer_count * 0.1, 1.0].min)
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Social
7
+ module Social
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/social/social/version'
4
+ require 'legion/extensions/agentic/social/social/helpers/constants'
5
+ require 'legion/extensions/agentic/social/social/helpers/social_graph'
6
+ require 'legion/extensions/agentic/social/social/runners/social'
7
+ require 'legion/extensions/agentic/social/social/client'
8
+
9
+ module Legion
10
+ module Extensions
11
+ module Agentic
12
+ module Social
13
+ module Social
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/social/social_learning/helpers/constants'
4
+ require 'legion/extensions/agentic/social/social_learning/helpers/observed_behavior'
5
+ require 'legion/extensions/agentic/social/social_learning/helpers/model_agent'
6
+ require 'legion/extensions/agentic/social/social_learning/helpers/social_learning_engine'
7
+ require 'legion/extensions/agentic/social/social_learning/runners/social_learning'
8
+
9
+ module Legion
10
+ module Extensions
11
+ module Agentic
12
+ module Social
13
+ module SocialLearning
14
+ class Client
15
+ include Runners::SocialLearning
16
+
17
+ def initialize(engine: nil)
18
+ @engine = engine || Helpers::SocialLearningEngine.new
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Social
7
+ module SocialLearning
8
+ module Helpers
9
+ module Constants
10
+ MAX_MODELS = 200
11
+ MAX_BEHAVIORS = 500
12
+ MAX_OBSERVATIONS = 1000
13
+ MAX_HISTORY = 300
14
+
15
+ DEFAULT_PRESTIGE = 0.5
16
+ PRESTIGE_FLOOR = 0.0
17
+ PRESTIGE_CEILING = 1.0
18
+ ATTENTION_THRESHOLD = 0.3
19
+ RETENTION_DECAY = 0.02
20
+ REPRODUCTION_CONFIDENCE = 0.5
21
+ REINFORCEMENT_BOOST = 0.15
22
+ PUNISHMENT_PENALTY = 0.2
23
+ PRESTIGE_LEARNING_RATE = 0.1
24
+ STALE_THRESHOLD = 120
25
+
26
+ OUTCOME_TYPES = %i[positive negative neutral].freeze
27
+ LEARNING_STAGES = %i[attention retention reproduction motivation].freeze
28
+
29
+ MODEL_LABELS = {
30
+ (0.8..) => :expert,
31
+ (0.6...0.8) => :proficient,
32
+ (0.4...0.6) => :peer,
33
+ (0.2...0.4) => :novice,
34
+ (..0.2) => :unreliable
35
+ }.freeze
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Social
9
+ module SocialLearning
10
+ module Helpers
11
+ class ModelAgent
12
+ include Constants
13
+
14
+ attr_reader :id, :agent_id, :domain, :observation_count,
15
+ :success_count, :created_at, :last_observed_at,
16
+ :observed_behaviors
17
+ attr_accessor :prestige
18
+
19
+ def initialize(agent_id:, domain:, prestige: Constants::DEFAULT_PRESTIGE)
20
+ @id = SecureRandom.uuid
21
+ @agent_id = agent_id
22
+ @domain = domain
23
+ @prestige = prestige.clamp(Constants::PRESTIGE_FLOOR, Constants::PRESTIGE_CEILING)
24
+ @observed_behaviors = []
25
+ @observation_count = 0
26
+ @success_count = 0
27
+ @created_at = Time.now.utc
28
+ @last_observed_at = nil
29
+ end
30
+
31
+ def observe!(behavior:, outcome:)
32
+ @observation_count += 1
33
+ @last_observed_at = Time.now.utc
34
+
35
+ if outcome == :positive
36
+ @success_count += 1
37
+ @prestige = (@prestige + Constants::PRESTIGE_LEARNING_RATE).clamp(
38
+ Constants::PRESTIGE_FLOOR,
39
+ Constants::PRESTIGE_CEILING
40
+ )
41
+ elsif outcome == :negative
42
+ @prestige = (@prestige - Constants::PRESTIGE_LEARNING_RATE).clamp(
43
+ Constants::PRESTIGE_FLOOR,
44
+ Constants::PRESTIGE_CEILING
45
+ )
46
+ end
47
+
48
+ behavior
49
+ end
50
+
51
+ def prestige_label
52
+ Constants::MODEL_LABELS.find { |range, _label| range.include?(@prestige) }&.last || :unknown
53
+ end
54
+
55
+ def success_rate
56
+ return 0.0 if @observation_count.zero?
57
+
58
+ (@success_count.to_f / @observation_count).round(4)
59
+ end
60
+
61
+ def to_h
62
+ {
63
+ id: @id,
64
+ agent_id: @agent_id,
65
+ domain: @domain,
66
+ prestige: @prestige.round(4),
67
+ prestige_label: prestige_label,
68
+ observation_count: @observation_count,
69
+ success_count: @success_count,
70
+ success_rate: success_rate,
71
+ behavior_count: @observed_behaviors.size,
72
+ created_at: @created_at,
73
+ last_observed_at: @last_observed_at
74
+ }
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Social
9
+ module SocialLearning
10
+ module Helpers
11
+ class ObservedBehavior
12
+ include Constants
13
+
14
+ attr_reader :id, :model_agent_id, :action, :domain, :context,
15
+ :outcome, :created_at
16
+ attr_accessor :retention, :reproduced
17
+
18
+ def initialize(model_agent_id:, action:, domain:, outcome:, context: {})
19
+ @id = SecureRandom.uuid
20
+ @model_agent_id = model_agent_id
21
+ @action = action
22
+ @domain = domain
23
+ @context = context
24
+ @outcome = outcome
25
+ @retention = 1.0
26
+ @reproduced = false
27
+ @created_at = Time.now.utc
28
+ end
29
+
30
+ def decay_retention!
31
+ @retention = (@retention - Constants::RETENTION_DECAY).clamp(
32
+ Constants::PRESTIGE_FLOOR,
33
+ Constants::PRESTIGE_CEILING
34
+ )
35
+ end
36
+
37
+ def retained?
38
+ @retention >= Constants::REPRODUCTION_CONFIDENCE
39
+ end
40
+
41
+ def to_h
42
+ {
43
+ id: @id,
44
+ model_agent_id: @model_agent_id,
45
+ action: @action,
46
+ domain: @domain,
47
+ context: @context,
48
+ outcome: @outcome,
49
+ retention: @retention.round(4),
50
+ reproduced: @reproduced,
51
+ retained: retained?,
52
+ created_at: @created_at
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Social
7
+ module SocialLearning
8
+ module Helpers
9
+ class SocialLearningEngine
10
+ include Constants
11
+
12
+ def initialize
13
+ @models = {} # id -> ModelAgent
14
+ @behaviors = {} # id -> ObservedBehavior
15
+ end
16
+
17
+ def register_model(agent_id:, domain:, prestige: Constants::DEFAULT_PRESTIGE)
18
+ prune_models if @models.size >= Constants::MAX_MODELS
19
+
20
+ model = ModelAgent.new(agent_id: agent_id, domain: domain, prestige: prestige)
21
+ @models[model.id] = model
22
+ model
23
+ end
24
+
25
+ def observe_behavior(model_id:, action:, domain:, outcome:, context: {})
26
+ model = @models.fetch(model_id, nil)
27
+ return nil unless model
28
+ return nil if model.prestige < Constants::ATTENTION_THRESHOLD
29
+
30
+ prune_behaviors if @behaviors.size >= Constants::MAX_BEHAVIORS
31
+
32
+ behavior = ObservedBehavior.new(
33
+ model_agent_id: model_id,
34
+ action: action,
35
+ domain: domain,
36
+ outcome: outcome,
37
+ context: context
38
+ )
39
+
40
+ model.observe!(behavior: behavior, outcome: outcome)
41
+ model.observed_behaviors << behavior
42
+ @behaviors[behavior.id] = behavior
43
+ behavior
44
+ end
45
+
46
+ def retained_behaviors(domain: nil)
47
+ behaviors = @behaviors.values.select(&:retained?)
48
+ return behaviors unless domain
49
+
50
+ behaviors.select { |beh| beh.domain == domain }
51
+ end
52
+
53
+ def reproducible_behaviors(domain: nil)
54
+ behaviors = retained_behaviors(domain: domain)
55
+ behaviors.select { |beh| beh.retention >= Constants::REPRODUCTION_CONFIDENCE }
56
+ end
57
+
58
+ def reproduce_behavior(behavior_id:)
59
+ behavior = @behaviors.fetch(behavior_id, nil)
60
+ return nil unless behavior
61
+ return nil unless behavior.retained?
62
+
63
+ behavior.reproduced = true
64
+ behavior
65
+ end
66
+
67
+ def reinforce_reproduction(behavior_id:, outcome:)
68
+ behavior = @behaviors.fetch(behavior_id, nil)
69
+ return nil unless behavior
70
+
71
+ model = @models.fetch(behavior.model_agent_id, nil)
72
+ return nil unless model
73
+
74
+ case outcome
75
+ when :positive
76
+ model.prestige = (model.prestige + Constants::REINFORCEMENT_BOOST).clamp(
77
+ Constants::PRESTIGE_FLOOR,
78
+ Constants::PRESTIGE_CEILING
79
+ )
80
+ when :negative
81
+ model.prestige = (model.prestige - Constants::PUNISHMENT_PENALTY).clamp(
82
+ Constants::PRESTIGE_FLOOR,
83
+ Constants::PRESTIGE_CEILING
84
+ )
85
+ end
86
+
87
+ { behavior: behavior.to_h, model_prestige: model.prestige.round(4) }
88
+ end
89
+
90
+ def best_models(limit: 5)
91
+ @models.values
92
+ .sort_by { |mod| -mod.prestige }
93
+ .first(limit)
94
+ end
95
+
96
+ def by_domain(domain:)
97
+ @models.values.select { |mod| mod.domain == domain }
98
+ end
99
+
100
+ def decay_all
101
+ @behaviors.each_value(&:decay_retention!)
102
+ end
103
+
104
+ def prune_forgotten
105
+ @behaviors.delete_if { |_id, beh| beh.retention < 0.05 }
106
+ end
107
+
108
+ def to_h
109
+ {
110
+ model_count: @models.size,
111
+ behavior_count: @behaviors.size,
112
+ retained_count: retained_behaviors.size,
113
+ reproducible_count: reproducible_behaviors.size
114
+ }
115
+ end
116
+
117
+ private
118
+
119
+ def prune_models
120
+ oldest = @models.values.min_by(&:created_at)
121
+ @models.delete(oldest.id) if oldest
122
+ end
123
+
124
+ def prune_behaviors
125
+ oldest = @behaviors.values.min_by(&:created_at)
126
+ @behaviors.delete(oldest.id) if oldest
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end