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,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::MirrorSystem::Runners::Mirror do
4
+ let(:client) { Legion::Extensions::Agentic::Social::MirrorSystem::Client.new }
5
+
6
+ describe '#observe_behavior' do
7
+ it 'creates an observation' do
8
+ result = client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
9
+ expect(result[:success]).to be true
10
+ expect(result[:observation][:agent_id]).to eq('alice')
11
+ expect(result[:observation][:action]).to eq(:deploy)
12
+ end
13
+
14
+ it 'boosts resonance on repeat observation' do
15
+ client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
16
+ result = client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
17
+ expect(result[:observation][:observation_count]).to eq(2)
18
+ end
19
+ end
20
+
21
+ describe '#imitate_behavior' do
22
+ it 'returns imitated: false with no observations' do
23
+ result = client.imitate_behavior(action: :deploy, domain: :infra)
24
+ expect(result[:success]).to be true
25
+ expect(result[:imitated]).to be false
26
+ end
27
+
28
+ it 'imitates observed behavior' do
29
+ client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
30
+ result = client.imitate_behavior(action: :deploy, domain: :infra)
31
+ expect(result[:imitated]).to be true
32
+ expect(result[:source]).to eq('alice')
33
+ expect(result[:fidelity]).to be_a(Float)
34
+ end
35
+
36
+ it 'filters by source_agent' do
37
+ client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
38
+ client.observe_behavior(agent_id: 'bob', action: :deploy, domain: :infra)
39
+ result = client.imitate_behavior(action: :deploy, domain: :infra, source_agent: 'bob')
40
+ expect(result[:source]).to eq('bob')
41
+ end
42
+ end
43
+
44
+ describe '#report_imitation_outcome' do
45
+ it 'updates fidelity on success' do
46
+ result = client.report_imitation_outcome(action: :deploy, domain: :infra, success_flag: true)
47
+ expect(result[:success]).to be true
48
+ expect(result[:fidelity]).to be > Legion::Extensions::Agentic::Social::MirrorSystem::Helpers::Constants::DEFAULT_FIDELITY
49
+ end
50
+
51
+ it 'updates fidelity on failure' do
52
+ result = client.report_imitation_outcome(action: :deploy, domain: :infra, success_flag: false)
53
+ expect(result[:fidelity]).to be < Legion::Extensions::Agentic::Social::MirrorSystem::Helpers::Constants::DEFAULT_FIDELITY
54
+ end
55
+ end
56
+
57
+ describe '#strongest_mirrors' do
58
+ it 'returns top mirrors' do
59
+ client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
60
+ client.observe_behavior(agent_id: 'bob', action: :test, domain: :code)
61
+ result = client.strongest_mirrors(count: 2)
62
+ expect(result[:success]).to be true
63
+ expect(result[:count]).to eq(2)
64
+ end
65
+ end
66
+
67
+ describe '#observations_for' do
68
+ it 'returns observations for agent' do
69
+ client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
70
+ client.observe_behavior(agent_id: 'alice', action: :test, domain: :code)
71
+ result = client.observations_for(agent_id: 'alice')
72
+ expect(result[:count]).to eq(2)
73
+ end
74
+
75
+ it 'returns empty for unknown agent' do
76
+ result = client.observations_for(agent_id: 'nobody')
77
+ expect(result[:count]).to eq(0)
78
+ end
79
+ end
80
+
81
+ describe '#observations_in' do
82
+ it 'returns observations in domain' do
83
+ client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
84
+ client.observe_behavior(agent_id: 'bob', action: :test, domain: :code)
85
+ result = client.observations_in(domain: :infra)
86
+ expect(result[:count]).to eq(1)
87
+ end
88
+ end
89
+
90
+ describe '#repertoire_status' do
91
+ it 'starts empty' do
92
+ result = client.repertoire_status
93
+ expect(result[:size]).to eq(0)
94
+ end
95
+
96
+ it 'grows after imitation' do
97
+ client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
98
+ client.imitate_behavior(action: :deploy, domain: :infra)
99
+ result = client.repertoire_status
100
+ expect(result[:size]).to eq(1)
101
+ end
102
+ end
103
+
104
+ describe '#update_mirror' do
105
+ it 'decays and returns stats' do
106
+ client.observe_behavior(agent_id: 'alice', action: :deploy, domain: :infra)
107
+ result = client.update_mirror
108
+ expect(result[:success]).to be true
109
+ expect(result).to have_key(:observations)
110
+ expect(result).to have_key(:repertoire)
111
+ expect(result).to have_key(:agents)
112
+ end
113
+ end
114
+
115
+ describe '#mirror_stats' do
116
+ it 'returns comprehensive stats' do
117
+ result = client.mirror_stats
118
+ expect(result[:success]).to be true
119
+ expect(result[:stats]).to include(:observations, :repertoire_size, :mirrored_agents)
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::MoralReasoning::Client do
4
+ subject(:client) { described_class.new }
5
+
6
+ it 'responds to all runner methods' do
7
+ expect(client).to respond_to(:evaluate_moral_action)
8
+ expect(client).to respond_to(:pose_moral_dilemma)
9
+ expect(client).to respond_to(:resolve_moral_dilemma)
10
+ expect(client).to respond_to(:apply_ethical_framework)
11
+ expect(client).to respond_to(:add_moral_principle)
12
+ expect(client).to respond_to(:check_moral_development)
13
+ expect(client).to respond_to(:moral_foundation_profile)
14
+ expect(client).to respond_to(:moral_stage_info)
15
+ expect(client).to respond_to(:update_moral_reasoning)
16
+ expect(client).to respond_to(:moral_reasoning_stats)
17
+ end
18
+
19
+ it 'maintains separate engine state per instance' do
20
+ client_a = described_class.new
21
+ client_b = described_class.new
22
+
23
+ client_a.pose_moral_dilemma(
24
+ description: 'Instance A dilemma',
25
+ options: [{ id: 'opt_a', description: 'Option A', foundations: [:care] }]
26
+ )
27
+
28
+ stats_a = client_a.moral_reasoning_stats
29
+ stats_b = client_b.moral_reasoning_stats
30
+
31
+ expect(stats_a[:total_dilemmas]).to eq(1)
32
+ expect(stats_b[:total_dilemmas]).to eq(0)
33
+ end
34
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::MoralReasoning::Helpers::Dilemma do
4
+ let(:options) do
5
+ [
6
+ { id: 'opt_a', description: 'Help the many', foundations: %i[care fairness] },
7
+ { id: 'opt_b', description: 'Follow the rule', foundations: %i[authority loyalty] }
8
+ ]
9
+ end
10
+
11
+ subject(:dilemma) do
12
+ described_class.new(
13
+ id: 'dilemma_1',
14
+ description: 'A trolley problem',
15
+ options: options,
16
+ domain: :ethics,
17
+ severity: 0.9
18
+ )
19
+ end
20
+
21
+ describe '#initialize' do
22
+ it 'sets id, description, domain, severity' do
23
+ expect(dilemma.id).to eq('dilemma_1')
24
+ expect(dilemma.description).to eq('A trolley problem')
25
+ expect(dilemma.domain).to eq(:ethics)
26
+ expect(dilemma.severity).to eq(0.9)
27
+ end
28
+
29
+ it 'is not resolved by default' do
30
+ expect(dilemma.resolved?).to be false
31
+ end
32
+
33
+ it 'has nil chosen_option, reasoning, framework_used' do
34
+ expect(dilemma.chosen_option).to be_nil
35
+ expect(dilemma.reasoning).to be_nil
36
+ expect(dilemma.framework_used).to be_nil
37
+ end
38
+
39
+ it 'clamps severity above 1.0' do
40
+ d = described_class.new(id: 'x', description: 'x', options: [], severity: 1.5)
41
+ expect(d.severity).to eq(1.0)
42
+ end
43
+
44
+ it 'clamps severity below 0.0' do
45
+ d = described_class.new(id: 'x', description: 'x', options: [], severity: -0.5)
46
+ expect(d.severity).to eq(0.0)
47
+ end
48
+ end
49
+
50
+ describe '#severity_label' do
51
+ it 'returns :critical for severity >= 0.8' do
52
+ expect(dilemma.severity_label).to eq(:critical)
53
+ end
54
+
55
+ it 'returns :serious for severity 0.6..0.79' do
56
+ d = described_class.new(id: 'x', description: 'x', options: [], severity: 0.7)
57
+ expect(d.severity_label).to eq(:serious)
58
+ end
59
+
60
+ it 'returns :moderate for severity 0.4..0.59' do
61
+ d = described_class.new(id: 'x', description: 'x', options: [], severity: 0.5)
62
+ expect(d.severity_label).to eq(:moderate)
63
+ end
64
+
65
+ it 'returns :minor for severity 0.2..0.39' do
66
+ d = described_class.new(id: 'x', description: 'x', options: [], severity: 0.3)
67
+ expect(d.severity_label).to eq(:minor)
68
+ end
69
+
70
+ it 'returns :trivial for severity < 0.2' do
71
+ d = described_class.new(id: 'x', description: 'x', options: [], severity: 0.1)
72
+ expect(d.severity_label).to eq(:trivial)
73
+ end
74
+ end
75
+
76
+ describe '#resolve' do
77
+ before { dilemma.resolve(option_id: 'opt_a', reasoning: 'Utilitarian outcome', framework: :utilitarian) }
78
+
79
+ it 'marks dilemma as resolved' do
80
+ expect(dilemma.resolved?).to be true
81
+ end
82
+
83
+ it 'sets chosen_option' do
84
+ expect(dilemma.chosen_option).to eq('opt_a')
85
+ end
86
+
87
+ it 'sets reasoning' do
88
+ expect(dilemma.reasoning).to eq('Utilitarian outcome')
89
+ end
90
+
91
+ it 'sets framework_used' do
92
+ expect(dilemma.framework_used).to eq(:utilitarian)
93
+ end
94
+
95
+ it 'sets resolved_at timestamp' do
96
+ expect(dilemma.resolved_at).not_to be_nil
97
+ end
98
+ end
99
+
100
+ describe '#to_h' do
101
+ it 'returns a hash with all expected keys' do
102
+ h = dilemma.to_h
103
+ expect(h).to include(:id, :description, :domain, :severity, :severity_label,
104
+ :options, :chosen_option, :reasoning, :framework_used,
105
+ :resolved, :created_at, :resolved_at)
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::MoralReasoning::Helpers::LlmEnhancer do
4
+ subject(:enhancer) { described_class }
5
+
6
+ let(:foundations) { { care: 0.5, fairness: 0.6, loyalty: 0.4, authority: 0.5, sanctity: 0.4, liberty: 0.5 } }
7
+
8
+ let(:options) do
9
+ [
10
+ { id: 'opt_a', description: 'Prioritize care', foundations: %i[care fairness] },
11
+ { id: 'opt_b', description: 'Follow rules', foundations: %i[authority loyalty] }
12
+ ]
13
+ end
14
+
15
+ describe '.available?' do
16
+ context 'when Legion::LLM is not defined' do
17
+ it 'returns false' do
18
+ expect(enhancer.available?).to be false
19
+ end
20
+ end
21
+
22
+ context 'when Legion::LLM is defined but not started' do
23
+ before do
24
+ stub_const('Legion::LLM', double(respond_to?: true, started?: false))
25
+ end
26
+
27
+ it 'returns false' do
28
+ expect(enhancer.available?).to be false
29
+ end
30
+ end
31
+
32
+ context 'when Legion::LLM is started' do
33
+ before do
34
+ stub_const('Legion::LLM', double(respond_to?: true, started?: true))
35
+ end
36
+
37
+ it 'returns true' do
38
+ expect(enhancer.available?).to be true
39
+ end
40
+ end
41
+
42
+ context 'when Legion::LLM raises an error' do
43
+ before do
44
+ stub_const('Legion::LLM', double)
45
+ allow(Legion::LLM).to receive(:respond_to?).and_raise(StandardError, 'boom')
46
+ end
47
+
48
+ it 'returns false' do
49
+ expect(enhancer.available?).to be false
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '.evaluate_action' do
55
+ let(:mock_response) do
56
+ content = <<~TEXT
57
+ REASONING: This action demonstrates care for others and promotes fairness. It strengthens the foundational values of justice and compassion.
58
+ IMPACT: care=0.3 | fairness=0.2 | loyalty=-0.1 | authority=0.0 | sanctity=0.1 | liberty=0.15
59
+ TEXT
60
+ double('response', content: content)
61
+ end
62
+
63
+ before do
64
+ stub_const('Legion::LLM', double)
65
+ chat = double('chat')
66
+ allow(Legion::LLM).to receive(:chat).and_return(chat)
67
+ allow(chat).to receive(:with_instructions)
68
+ allow(chat).to receive(:ask).and_return(mock_response)
69
+ end
70
+
71
+ it 'returns reasoning and foundation_impacts' do
72
+ result = enhancer.evaluate_action(
73
+ action: :help_stranger,
74
+ description: 'Helping someone in need',
75
+ foundations: foundations
76
+ )
77
+ expect(result).to be_a(Hash)
78
+ expect(result[:reasoning]).to be_a(String)
79
+ expect(result[:reasoning]).not_to be_empty
80
+ expect(result[:foundation_impacts]).to be_a(Hash)
81
+ end
82
+
83
+ it 'parses all foundation impacts' do
84
+ result = enhancer.evaluate_action(
85
+ action: :help_stranger,
86
+ description: 'Helping someone in need',
87
+ foundations: foundations
88
+ )
89
+ expect(result[:foundation_impacts].keys).to include(:care, :fairness, :loyalty)
90
+ end
91
+
92
+ it 'clamps foundation impact values to -1.0..1.0' do
93
+ result = enhancer.evaluate_action(
94
+ action: :help_stranger,
95
+ description: 'Helping someone in need',
96
+ foundations: foundations
97
+ )
98
+ result[:foundation_impacts].each_value do |val|
99
+ expect(val).to be_between(-1.0, 1.0)
100
+ end
101
+ end
102
+
103
+ context 'when LLM raises an error' do
104
+ before do
105
+ chat = double('chat')
106
+ allow(Legion::LLM).to receive(:chat).and_return(chat)
107
+ allow(chat).to receive(:with_instructions)
108
+ allow(chat).to receive(:ask).and_raise(StandardError, 'API unavailable')
109
+ end
110
+
111
+ it 'returns nil' do
112
+ result = enhancer.evaluate_action(
113
+ action: :help_stranger,
114
+ description: 'test',
115
+ foundations: foundations
116
+ )
117
+ expect(result).to be_nil
118
+ end
119
+ end
120
+
121
+ context 'when response has no content' do
122
+ before do
123
+ chat = double('chat')
124
+ allow(Legion::LLM).to receive(:chat).and_return(chat)
125
+ allow(chat).to receive(:with_instructions)
126
+ allow(chat).to receive(:ask).and_return(double('response', content: nil))
127
+ end
128
+
129
+ it 'returns nil' do
130
+ result = enhancer.evaluate_action(
131
+ action: :test,
132
+ description: 'test',
133
+ foundations: foundations
134
+ )
135
+ expect(result).to be_nil
136
+ end
137
+ end
138
+
139
+ context 'when response has malformed IMPACT line' do
140
+ before do
141
+ bad_response = double('response', content: 'REASONING: some text only, no IMPACT line')
142
+ chat = double('chat')
143
+ allow(Legion::LLM).to receive(:chat).and_return(chat)
144
+ allow(chat).to receive(:with_instructions)
145
+ allow(chat).to receive(:ask).and_return(bad_response)
146
+ end
147
+
148
+ it 'returns nil' do
149
+ result = enhancer.evaluate_action(action: :test, description: 'test', foundations: foundations)
150
+ expect(result).to be_nil
151
+ end
152
+ end
153
+ end
154
+
155
+ describe '.resolve_dilemma' do
156
+ let(:mock_response) do
157
+ content = <<~TEXT
158
+ CHOSEN: opt_a
159
+ CONFIDENCE: 0.82
160
+ REASONING: From a care ethics perspective, prioritizing the wellbeing of those directly affected aligns with the core principle of nurturing relationships and responding to vulnerability.
161
+ TEXT
162
+ double('response', content: content)
163
+ end
164
+
165
+ before do
166
+ stub_const('Legion::LLM', double)
167
+ chat = double('chat')
168
+ allow(Legion::LLM).to receive(:chat).and_return(chat)
169
+ allow(chat).to receive(:with_instructions)
170
+ allow(chat).to receive(:ask).and_return(mock_response)
171
+ end
172
+
173
+ it 'returns chosen_option, confidence, and reasoning' do
174
+ result = enhancer.resolve_dilemma(
175
+ dilemma_description: 'Should the agent reveal sensitive information?',
176
+ options: options,
177
+ framework: :care
178
+ )
179
+ expect(result).to be_a(Hash)
180
+ expect(result[:chosen_option]).to eq('opt_a')
181
+ expect(result[:confidence]).to be_a(Float)
182
+ expect(result[:reasoning]).to be_a(String)
183
+ expect(result[:reasoning]).not_to be_empty
184
+ end
185
+
186
+ it 'clamps confidence to 0.0..1.0' do
187
+ result = enhancer.resolve_dilemma(
188
+ dilemma_description: 'Test',
189
+ options: options,
190
+ framework: :utilitarian
191
+ )
192
+ expect(result[:confidence]).to be_between(0.0, 1.0)
193
+ end
194
+
195
+ context 'when LLM raises an error' do
196
+ before do
197
+ chat = double('chat')
198
+ allow(Legion::LLM).to receive(:chat).and_return(chat)
199
+ allow(chat).to receive(:with_instructions)
200
+ allow(chat).to receive(:ask).and_raise(StandardError, 'timeout')
201
+ end
202
+
203
+ it 'returns nil' do
204
+ result = enhancer.resolve_dilemma(
205
+ dilemma_description: 'test',
206
+ options: options,
207
+ framework: :utilitarian
208
+ )
209
+ expect(result).to be_nil
210
+ end
211
+ end
212
+
213
+ context 'when response is malformed' do
214
+ before do
215
+ bad_response = double('response', content: 'This is just some text without any format markers.')
216
+ chat = double('chat')
217
+ allow(Legion::LLM).to receive(:chat).and_return(chat)
218
+ allow(chat).to receive(:with_instructions)
219
+ allow(chat).to receive(:ask).and_return(bad_response)
220
+ end
221
+
222
+ it 'returns nil' do
223
+ result = enhancer.resolve_dilemma(
224
+ dilemma_description: 'test',
225
+ options: options,
226
+ framework: :deontological
227
+ )
228
+ expect(result).to be_nil
229
+ end
230
+ end
231
+ end
232
+ end