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,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Social
9
+ module PerspectiveShifting
10
+ module Helpers
11
+ class Perspective
12
+ attr_reader :id, :name, :perspective_type, :priorities,
13
+ :expertise_domains, :empathy_level, :bias_toward, :created_at
14
+
15
+ def initialize(name:, perspective_type:, priorities: [], expertise_domains: [],
16
+ empathy_level: Constants::DEFAULT_EMPATHY, bias_toward: nil)
17
+ @id = SecureRandom.uuid
18
+ @name = name
19
+ @perspective_type = perspective_type
20
+ @priorities = Array(priorities)
21
+ @expertise_domains = Array(expertise_domains)
22
+ @empathy_level = empathy_level.clamp(0.0, 1.0)
23
+ @bias_toward = bias_toward
24
+ @created_at = Time.now.utc
25
+ end
26
+
27
+ def to_h
28
+ {
29
+ id: @id,
30
+ name: @name,
31
+ perspective_type: @perspective_type,
32
+ priorities: @priorities,
33
+ expertise_domains: @expertise_domains,
34
+ empathy_level: @empathy_level.round(10),
35
+ bias_toward: @bias_toward,
36
+ created_at: @created_at
37
+ }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Social
9
+ module PerspectiveShifting
10
+ module Helpers
11
+ class PerspectiveView
12
+ attr_reader :id, :situation_id, :perspective_id, :valence,
13
+ :concerns, :opportunities, :confidence, :created_at
14
+
15
+ def initialize(situation_id:, perspective_id:, valence: 0.0,
16
+ concerns: [], opportunities: [], confidence: 0.5)
17
+ @id = SecureRandom.uuid
18
+ @situation_id = situation_id
19
+ @perspective_id = perspective_id
20
+ @valence = valence.clamp(-1.0, 1.0).round(10)
21
+ @concerns = Array(concerns)
22
+ @opportunities = Array(opportunities)
23
+ @confidence = confidence.clamp(0.0, 1.0).round(10)
24
+ @created_at = Time.now.utc
25
+ end
26
+
27
+ def positive?
28
+ @valence > 0.1
29
+ end
30
+
31
+ def negative?
32
+ @valence < -0.1
33
+ end
34
+
35
+ def neutral?
36
+ !positive? && !negative?
37
+ end
38
+
39
+ def to_h
40
+ {
41
+ id: @id,
42
+ situation_id: @situation_id,
43
+ perspective_id: @perspective_id,
44
+ valence: @valence,
45
+ concerns: @concerns,
46
+ opportunities: @opportunities,
47
+ confidence: @confidence,
48
+ created_at: @created_at
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Social
9
+ module PerspectiveShifting
10
+ module Helpers
11
+ class ShiftingEngine
12
+ attr_reader :perspectives, :situations
13
+
14
+ def initialize
15
+ @perspectives = {}
16
+ @situations = {}
17
+ end
18
+
19
+ def add_perspective(name:, type: :stakeholder, priorities: [], empathy: Constants::DEFAULT_EMPATHY,
20
+ bias: nil, expertise_domains: [])
21
+ return { error: :too_many_perspectives } if @perspectives.size >= Constants::MAX_PERSPECTIVES
22
+ return { error: :invalid_type } unless Constants::PERSPECTIVE_TYPES.include?(type)
23
+
24
+ p = Perspective.new(
25
+ name: name,
26
+ perspective_type: type,
27
+ priorities: priorities,
28
+ expertise_domains: expertise_domains,
29
+ empathy_level: empathy,
30
+ bias_toward: bias
31
+ )
32
+ @perspectives[p.id] = p
33
+ p
34
+ end
35
+
36
+ def add_situation(content:)
37
+ return { error: :too_many_situations } if @situations.size >= Constants::MAX_SITUATIONS
38
+
39
+ id = SecureRandom.uuid
40
+ @situations[id] = { id: id, content: content, views: [], created_at: Time.now.utc }
41
+ @situations[id]
42
+ end
43
+
44
+ def generate_view(situation_id:, perspective_id:, valence: 0.0,
45
+ concerns: [], opportunities: [], confidence: 0.5)
46
+ situation = @situations[situation_id]
47
+ perspective = @perspectives[perspective_id]
48
+
49
+ return { error: :situation_not_found } unless situation
50
+ return { error: :perspective_not_found } unless perspective
51
+ return { error: :too_many_views } if situation[:views].size >= Constants::MAX_VIEWS_PER_SITUATION
52
+
53
+ view = PerspectiveView.new(
54
+ situation_id: situation_id,
55
+ perspective_id: perspective_id,
56
+ valence: valence,
57
+ concerns: concerns,
58
+ opportunities: opportunities,
59
+ confidence: confidence
60
+ )
61
+ situation[:views] << view
62
+ view
63
+ end
64
+
65
+ def views_for_situation(situation_id:)
66
+ situation = @situations[situation_id]
67
+ return [] unless situation
68
+
69
+ situation[:views]
70
+ end
71
+
72
+ def perspective_agreement(situation_id:)
73
+ views = views_for_situation(situation_id: situation_id)
74
+ return 0.0 if views.size < Constants::MIN_PERSPECTIVES_FOR_SYNTHESIS
75
+
76
+ valences = views.map(&:valence)
77
+ mean = valences.sum / valences.size.to_f
78
+ variance = valences.sum { |v| (v - mean)**2 } / valences.size.to_f
79
+ std_dev = Math.sqrt(variance)
80
+
81
+ # Agreement is inverse of normalized std_dev (max std_dev is 1.0 for symmetric ±1 distribution)
82
+ (1.0 - std_dev).clamp(0.0, 1.0).round(10)
83
+ end
84
+
85
+ def blind_spots(situation_id:)
86
+ views = views_for_situation(situation_id: situation_id)
87
+ applied_ids = views.map(&:perspective_id).uniq
88
+ applied_types = applied_ids.filter_map { |pid| @perspectives[pid]&.perspective_type }.uniq
89
+ Constants::PERSPECTIVE_TYPES - applied_types
90
+ end
91
+
92
+ def coverage_score(situation_id:)
93
+ views = views_for_situation(situation_id: situation_id)
94
+ return 0.0 if @perspectives.empty?
95
+
96
+ applied_count = views.map(&:perspective_id).uniq.size
97
+ (applied_count.to_f / @perspectives.size).clamp(0.0, 1.0).round(10)
98
+ end
99
+
100
+ def dominant_view(situation_id:)
101
+ views = views_for_situation(situation_id: situation_id)
102
+ return nil if views.empty?
103
+
104
+ views.max_by(&:confidence)
105
+ end
106
+
107
+ def synthesize(situation_id:)
108
+ views = views_for_situation(situation_id: situation_id)
109
+ return { error: :insufficient_views } if views.size < Constants::MIN_PERSPECTIVES_FOR_SYNTHESIS
110
+
111
+ total_confidence = views.sum(&:confidence)
112
+ return { error: :zero_confidence } if total_confidence.zero?
113
+
114
+ weighted_valence = views.sum { |v| v.valence * v.confidence } / total_confidence
115
+ all_concerns = views.flat_map(&:concerns).uniq
116
+ all_opportunities = views.flat_map(&:opportunities).uniq
117
+ agreement = perspective_agreement(situation_id: situation_id)
118
+
119
+ {
120
+ situation_id: situation_id,
121
+ weighted_valence: weighted_valence.round(10),
122
+ concerns: all_concerns,
123
+ opportunities: all_opportunities,
124
+ agreement: agreement.round(10),
125
+ agreement_label: Constants.agreement_label(agreement),
126
+ view_count: views.size,
127
+ coverage_score: coverage_score(situation_id: situation_id),
128
+ coverage_label: Constants.coverage_label(coverage_score(situation_id: situation_id))
129
+ }
130
+ end
131
+
132
+ def most_divergent_pair(situation_id:)
133
+ views = views_for_situation(situation_id: situation_id)
134
+ return nil if views.size < 2
135
+
136
+ max_diff = -1.0
137
+ pair = nil
138
+
139
+ views.combination(2) do |a, b|
140
+ diff = (a.valence - b.valence).abs
141
+ if diff > max_diff
142
+ max_diff = diff
143
+ pair = [a, b]
144
+ end
145
+ end
146
+
147
+ pair
148
+ end
149
+
150
+ def to_h
151
+ {
152
+ perspective_count: @perspectives.size,
153
+ situation_count: @situations.size,
154
+ perspectives: @perspectives.values.map(&:to_h),
155
+ situations: @situations.values.map do |s|
156
+ s.merge(views: s[:views].map(&:to_h))
157
+ end
158
+ }
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Social
9
+ module PerspectiveShifting
10
+ module Runners
11
+ module PerspectiveShifting
12
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
13
+ Legion::Extensions::Helpers.const_defined?(:Lex)
14
+
15
+ # --- Perspective management ---
16
+
17
+ def add_perspective(name:, type: :stakeholder, priorities: [], empathy: Helpers::Constants::DEFAULT_EMPATHY,
18
+ bias: nil, expertise_domains: [], engine: nil, **)
19
+ eng = engine || shifting_engine
20
+ result = eng.add_perspective(name: name, type: type, priorities: priorities,
21
+ empathy: empathy, bias: bias, expertise_domains: expertise_domains)
22
+ return { success: false, error: result[:error] } if result.is_a?(Hash) && result[:error]
23
+
24
+ Legion::Logging.debug "[perspective_shifting] added perspective name=#{name} type=#{type} id=#{result.id[0..7]}"
25
+ { success: true, perspective: result.to_h }
26
+ end
27
+
28
+ def list_perspectives(engine: nil, **)
29
+ eng = engine || shifting_engine
30
+ persp = eng.perspectives.values.map(&:to_h)
31
+ Legion::Logging.debug "[perspective_shifting] list_perspectives count=#{persp.size}"
32
+ { success: true, perspectives: persp, count: persp.size }
33
+ end
34
+
35
+ def get_perspective(perspective_id:, engine: nil, **)
36
+ eng = engine || shifting_engine
37
+ persp = eng.perspectives[perspective_id]
38
+ if persp
39
+ { success: true, found: true, perspective: persp.to_h }
40
+ else
41
+ Legion::Logging.debug "[perspective_shifting] perspective not found id=#{perspective_id[0..7]}"
42
+ { success: false, found: false }
43
+ end
44
+ end
45
+
46
+ # --- Situation management ---
47
+
48
+ def add_situation(content:, engine: nil, **)
49
+ eng = engine || shifting_engine
50
+ result = eng.add_situation(content: content)
51
+ return { success: false, error: result[:error] } if result.is_a?(Hash) && result[:error]
52
+
53
+ Legion::Logging.debug "[perspective_shifting] added situation id=#{result[:id][0..7]}"
54
+ { success: true, situation_id: result[:id], content: result[:content] }
55
+ end
56
+
57
+ def list_situations(engine: nil, **)
58
+ eng = engine || shifting_engine
59
+ sits = eng.situations.values.map { |s| s.merge(views: s[:views].map(&:to_h)) }
60
+ Legion::Logging.debug "[perspective_shifting] list_situations count=#{sits.size}"
61
+ { success: true, situations: sits, count: sits.size }
62
+ end
63
+
64
+ # --- View generation and retrieval ---
65
+
66
+ def generate_view(situation_id:, perspective_id:, valence: 0.0,
67
+ concerns: [], opportunities: [], confidence: 0.5, engine: nil, **)
68
+ eng = engine || shifting_engine
69
+ result = eng.generate_view(
70
+ situation_id: situation_id,
71
+ perspective_id: perspective_id,
72
+ valence: valence,
73
+ concerns: concerns,
74
+ opportunities: opportunities,
75
+ confidence: confidence
76
+ )
77
+ return { success: false, error: result[:error] } if result.is_a?(Hash) && result[:error]
78
+
79
+ Legion::Logging.debug "[perspective_shifting] generated view id=#{result.id[0..7]} " \
80
+ "valence=#{result.valence.round(2)}"
81
+ { success: true, view: result.to_h }
82
+ end
83
+
84
+ def views_for_situation(situation_id:, engine: nil, **)
85
+ eng = engine || shifting_engine
86
+ views = eng.views_for_situation(situation_id: situation_id)
87
+ Legion::Logging.debug "[perspective_shifting] views_for_situation id=#{situation_id[0..7]} count=#{views.size}"
88
+ { success: true, views: views.map(&:to_h), count: views.size }
89
+ end
90
+
91
+ # --- Analysis ---
92
+
93
+ def perspective_agreement(situation_id:, engine: nil, **)
94
+ eng = engine || shifting_engine
95
+ score = eng.perspective_agreement(situation_id: situation_id)
96
+ label = Helpers::Constants.agreement_label(score)
97
+ Legion::Logging.debug "[perspective_shifting] agreement situation=#{situation_id[0..7]} score=#{score.round(2)} label=#{label}"
98
+ { success: true, situation_id: situation_id, agreement: score, label: label }
99
+ end
100
+
101
+ def blind_spots(situation_id:, engine: nil, **)
102
+ eng = engine || shifting_engine
103
+ spots = eng.blind_spots(situation_id: situation_id)
104
+ Legion::Logging.debug "[perspective_shifting] blind_spots situation=#{situation_id[0..7]} count=#{spots.size}"
105
+ { success: true, situation_id: situation_id, blind_spots: spots, count: spots.size }
106
+ end
107
+
108
+ def coverage_score(situation_id:, engine: nil, **)
109
+ eng = engine || shifting_engine
110
+ score = eng.coverage_score(situation_id: situation_id)
111
+ label = Helpers::Constants.coverage_label(score)
112
+ Legion::Logging.debug "[perspective_shifting] coverage situation=#{situation_id[0..7]} score=#{score.round(2)} label=#{label}"
113
+ { success: true, situation_id: situation_id, coverage: score, label: label }
114
+ end
115
+
116
+ def dominant_view(situation_id:, engine: nil, **)
117
+ eng = engine || shifting_engine
118
+ view = eng.dominant_view(situation_id: situation_id)
119
+ if view
120
+ Legion::Logging.debug "[perspective_shifting] dominant_view situation=#{situation_id[0..7]} confidence=#{view.confidence.round(2)}"
121
+ { success: true, found: true, view: view.to_h }
122
+ else
123
+ { success: true, found: false }
124
+ end
125
+ end
126
+
127
+ def synthesize(situation_id:, engine: nil, **)
128
+ eng = engine || shifting_engine
129
+ result = eng.synthesize(situation_id: situation_id)
130
+ return { success: false, error: result[:error] } if result[:error]
131
+
132
+ Legion::Logging.info "[perspective_shifting] synthesized situation=#{situation_id[0..7]} " \
133
+ "valence=#{result[:weighted_valence].round(2)} views=#{result[:view_count]}"
134
+ result.merge(success: true)
135
+ end
136
+
137
+ def most_divergent_pair(situation_id:, engine: nil, **)
138
+ eng = engine || shifting_engine
139
+ pair = eng.most_divergent_pair(situation_id: situation_id)
140
+ unless pair
141
+ Legion::Logging.debug '[perspective_shifting] most_divergent_pair: not enough views'
142
+ return { success: true, found: false }
143
+ end
144
+
145
+ divergence = (pair[0].valence - pair[1].valence).abs.round(10)
146
+ Legion::Logging.debug "[perspective_shifting] most_divergent_pair divergence=#{divergence.round(2)}"
147
+ { success: true, found: true, views: pair.map(&:to_h), divergence: divergence }
148
+ end
149
+
150
+ def engine_status(engine: nil, **)
151
+ eng = engine || shifting_engine
152
+ Legion::Logging.debug '[perspective_shifting] engine_status'
153
+ { success: true }.merge(eng.to_h)
154
+ end
155
+
156
+ private
157
+
158
+ def shifting_engine
159
+ @shifting_engine ||= Helpers::ShiftingEngine.new
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ 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 PerspectiveShifting
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/social/perspective_shifting/version'
4
+ require 'legion/extensions/agentic/social/perspective_shifting/helpers/constants'
5
+ require 'legion/extensions/agentic/social/perspective_shifting/helpers/perspective'
6
+ require 'legion/extensions/agentic/social/perspective_shifting/helpers/perspective_view'
7
+ require 'legion/extensions/agentic/social/perspective_shifting/helpers/shifting_engine'
8
+ require 'legion/extensions/agentic/social/perspective_shifting/runners/perspective_shifting'
9
+ require 'legion/extensions/agentic/social/perspective_shifting/client'
10
+
11
+ module Legion
12
+ module Extensions
13
+ module Agentic
14
+ module Social
15
+ module PerspectiveShifting
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/social/social/helpers/constants'
4
+ require 'legion/extensions/agentic/social/social/helpers/social_graph'
5
+ require 'legion/extensions/agentic/social/social/runners/social'
6
+
7
+ module Legion
8
+ module Extensions
9
+ module Agentic
10
+ module Social
11
+ module Social
12
+ class Client
13
+ include Runners::Social
14
+
15
+ attr_reader :social_graph
16
+
17
+ def initialize(social_graph: nil, **)
18
+ @social_graph = social_graph || Helpers::SocialGraph.new
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,84 @@
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
+ module Constants
10
+ # Social roles an agent can hold in a group
11
+ ROLES = %i[
12
+ leader
13
+ contributor
14
+ specialist
15
+ observer
16
+ mentor
17
+ newcomer
18
+ ].freeze
19
+
20
+ # Group relationship types
21
+ RELATIONSHIP_TYPES = %i[
22
+ ally
23
+ collaborator
24
+ neutral
25
+ competitor
26
+ adversary
27
+ ].freeze
28
+
29
+ # Reputation dimensions
30
+ REPUTATION_DIMENSIONS = {
31
+ reliability: { weight: 0.25, description: 'Follows through on commitments' },
32
+ competence: { weight: 0.25, description: 'Quality of work output' },
33
+ benevolence: { weight: 0.20, description: 'Acts in others interests' },
34
+ integrity: { weight: 0.15, description: 'Consistency between words and actions' },
35
+ influence: { weight: 0.15, description: 'Ability to shape group direction' }
36
+ }.freeze
37
+
38
+ # EMA alpha for reputation updates
39
+ REPUTATION_ALPHA = 0.1
40
+
41
+ # Social standing thresholds
42
+ STANDING_LEVELS = {
43
+ exemplary: 0.8,
44
+ respected: 0.6,
45
+ neutral: 0.4,
46
+ marginal: 0.2,
47
+ ostracized: 0.0
48
+ }.freeze
49
+
50
+ # Group cohesion thresholds
51
+ COHESION_LEVELS = {
52
+ tight: 0.7,
53
+ moderate: 0.5,
54
+ loose: 0.3,
55
+ fractured: 0.0
56
+ }.freeze
57
+
58
+ # Maximum tracked groups
59
+ MAX_GROUPS = 20
60
+
61
+ # Maximum members per group
62
+ MAX_GROUP_MEMBERS = 50
63
+
64
+ # Social norms violation types
65
+ NORM_VIOLATIONS = %i[
66
+ free_riding
67
+ defection
68
+ deception
69
+ dominance_abuse
70
+ exclusion
71
+ ].freeze
72
+
73
+ # Reciprocity tracking window
74
+ RECIPROCITY_WINDOW = 50
75
+
76
+ # Social influence decay rate
77
+ INFLUENCE_DECAY = 0.02
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end