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,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Social::Conscience::Helpers::MoralStore do
6
+ subject(:store) { described_class.new }
7
+
8
+ let(:permitted_result) do
9
+ {
10
+ action: :deploy_patch,
11
+ scores: { care: 0.5, fairness: 0.4, loyalty: 0.3, authority: 0.2, sanctity: 0.4, liberty: 0.3 },
12
+ weighted_score: 0.38,
13
+ verdict: :permitted,
14
+ dilemma: nil,
15
+ sensitivities: { care: 1.0, fairness: 1.0, loyalty: 1.0, authority: 1.0, sanctity: 1.0, liberty: 1.0 },
16
+ evaluated_at: Time.now.utc
17
+ }
18
+ end
19
+
20
+ let(:cautioned_result) do
21
+ {
22
+ action: :access_logs,
23
+ scores: { care: -0.2, fairness: -0.1, loyalty: 0.1, authority: 0.2, sanctity: 0.0, liberty: -0.3 },
24
+ weighted_score: -0.06,
25
+ verdict: :cautioned,
26
+ dilemma: nil,
27
+ sensitivities: { care: 1.0, fairness: 1.0, loyalty: 1.0, authority: 1.0, sanctity: 1.0, liberty: 1.0 },
28
+ evaluated_at: Time.now.utc
29
+ }
30
+ end
31
+
32
+ let(:prohibited_result) do
33
+ {
34
+ action: :delete_user_data,
35
+ scores: { care: -0.9, fairness: -0.8, loyalty: -0.5, authority: -0.4, sanctity: -0.7, liberty: -0.6 },
36
+ weighted_score: -0.67,
37
+ verdict: :prohibited,
38
+ dilemma: nil,
39
+ sensitivities: { care: 1.0, fairness: 1.0, loyalty: 1.0, authority: 1.0, sanctity: 1.0, liberty: 1.0 },
40
+ evaluated_at: Time.now.utc
41
+ }
42
+ end
43
+
44
+ let(:dilemma_result) do
45
+ {
46
+ action: :trade_off_action,
47
+ scores: { care: 0.8, fairness: -0.7, loyalty: 0.1, authority: 0.0, sanctity: 0.0, liberty: 0.0 },
48
+ weighted_score: 0.06,
49
+ verdict: :permitted,
50
+ dilemma: {
51
+ type: :utilitarian,
52
+ approving: [:care],
53
+ opposing: [:fairness],
54
+ tension: 0.8,
55
+ counter_tension: 0.7,
56
+ detected_at: Time.now.utc
57
+ },
58
+ sensitivities: { care: 1.0, fairness: 1.0, loyalty: 1.0, authority: 1.0, sanctity: 1.0, liberty: 1.0 },
59
+ evaluated_at: Time.now.utc
60
+ }
61
+ end
62
+
63
+ describe '#initialize' do
64
+ it 'creates a default evaluator' do
65
+ expect(store.evaluator).to be_a(Legion::Extensions::Agentic::Social::Conscience::Helpers::MoralEvaluator)
66
+ end
67
+
68
+ it 'accepts an injected evaluator' do
69
+ custom_evaluator = Legion::Extensions::Agentic::Social::Conscience::Helpers::MoralEvaluator.new
70
+ s = described_class.new(evaluator: custom_evaluator)
71
+ expect(s.evaluator).to be(custom_evaluator)
72
+ end
73
+
74
+ it 'starts with empty history' do
75
+ expect(store.history).to be_empty
76
+ end
77
+
78
+ it 'starts with empty dilemmas' do
79
+ expect(store.dilemmas).to be_empty
80
+ end
81
+ end
82
+
83
+ describe '#record_evaluation' do
84
+ it 'adds to history' do
85
+ store.record_evaluation(permitted_result)
86
+ expect(store.history.size).to eq(1)
87
+ end
88
+
89
+ it 'returns the result unchanged' do
90
+ result = store.record_evaluation(permitted_result)
91
+ expect(result[:verdict]).to eq(:permitted)
92
+ end
93
+
94
+ it 'records dilemma when present' do
95
+ store.record_evaluation(dilemma_result)
96
+ expect(store.dilemmas.size).to eq(1)
97
+ end
98
+
99
+ it 'does not record dilemma when nil' do
100
+ store.record_evaluation(permitted_result)
101
+ expect(store.dilemmas).to be_empty
102
+ end
103
+
104
+ it 'caps history at MAX_MORAL_HISTORY' do
105
+ (Legion::Extensions::Agentic::Social::Conscience::Helpers::Constants::MAX_MORAL_HISTORY + 10).times { store.record_evaluation(permitted_result) }
106
+ expect(store.history.size).to eq(Legion::Extensions::Agentic::Social::Conscience::Helpers::Constants::MAX_MORAL_HISTORY)
107
+ end
108
+ end
109
+
110
+ describe '#record_follow_through' do
111
+ it 'increments followed_count on :followed outcome' do
112
+ store.record_follow_through(:permitted, :followed)
113
+ stats = store.aggregate_stats
114
+ expect(stats[:followed_count]).to eq(1)
115
+ end
116
+
117
+ it 'increments overridden_count on :overridden outcome' do
118
+ store.record_follow_through(:permitted, :overridden)
119
+ stats = store.aggregate_stats
120
+ expect(stats[:overridden_count]).to eq(1)
121
+ end
122
+
123
+ it 'calls update_sensitivity on the evaluator' do
124
+ expect(store.evaluator).to receive(:update_sensitivity).at_least(:once)
125
+ store.record_follow_through(:prohibited, :overridden)
126
+ end
127
+ end
128
+
129
+ describe '#consistency_score' do
130
+ it 'returns 1.0 with no history' do
131
+ expect(store.consistency_score).to eq(1.0)
132
+ end
133
+
134
+ it 'returns 1.0 when all verdicts are followed' do
135
+ 3.times { store.record_follow_through(:permitted, :followed) }
136
+ expect(store.consistency_score).to eq(1.0)
137
+ end
138
+
139
+ it 'returns 0.5 when half are followed and half overridden' do
140
+ 2.times { store.record_follow_through(:permitted, :followed) }
141
+ 2.times { store.record_follow_through(:prohibited, :overridden) }
142
+ expect(store.consistency_score).to eq(0.5)
143
+ end
144
+
145
+ it 'returns a float between 0.0 and 1.0' do
146
+ 5.times { store.record_follow_through(:permitted, :followed) }
147
+ 3.times { store.record_follow_through(:cautioned, :overridden) }
148
+ expect(store.consistency_score).to be_between(0.0, 1.0)
149
+ end
150
+ end
151
+
152
+ describe '#foundation_sensitivities' do
153
+ it 'returns sensitivities for all 6 foundations' do
154
+ expect(store.foundation_sensitivities.keys).to contain_exactly(
155
+ :care, :fairness, :loyalty, :authority, :sanctity, :liberty
156
+ )
157
+ end
158
+
159
+ it 'returns rounded float values' do
160
+ store.foundation_sensitivities.each_value do |s|
161
+ expect(s).to be_a(Float)
162
+ end
163
+ end
164
+ end
165
+
166
+ describe '#recent_evaluations' do
167
+ it 'returns empty array initially' do
168
+ expect(store.recent_evaluations).to be_empty
169
+ end
170
+
171
+ it 'returns most recent evaluations up to limit' do
172
+ 5.times { store.record_evaluation(permitted_result) }
173
+ store.record_evaluation(cautioned_result)
174
+ recent = store.recent_evaluations(3)
175
+ expect(recent.size).to eq(3)
176
+ end
177
+
178
+ it 'returns the most recent entries when over limit' do
179
+ 5.times { store.record_evaluation(permitted_result) }
180
+ 2.times { store.record_evaluation(prohibited_result) }
181
+ recent = store.recent_evaluations(2)
182
+ expect(recent.all? { |e| e[:verdict] == :prohibited }).to be true
183
+ end
184
+ end
185
+
186
+ describe '#open_dilemmas' do
187
+ it 'returns empty when no dilemmas exist' do
188
+ store.record_evaluation(permitted_result)
189
+ expect(store.open_dilemmas).to be_empty
190
+ end
191
+
192
+ it 'returns dilemmas when they exist' do
193
+ store.record_evaluation(dilemma_result)
194
+ expect(store.open_dilemmas.size).to eq(1)
195
+ end
196
+ end
197
+
198
+ describe '#aggregate_stats' do
199
+ it 'returns empty stats structure when no history' do
200
+ stats = store.aggregate_stats
201
+ expect(stats[:total_evaluations]).to eq(0)
202
+ expect(stats[:consistency_score]).to eq(1.0)
203
+ end
204
+
205
+ it 'counts evaluations' do
206
+ 3.times { store.record_evaluation(permitted_result) }
207
+ expect(store.aggregate_stats[:total_evaluations]).to eq(3)
208
+ end
209
+
210
+ it 'counts verdicts by type' do
211
+ 2.times { store.record_evaluation(permitted_result) }
212
+ store.record_evaluation(cautioned_result)
213
+ store.record_evaluation(prohibited_result)
214
+ counts = store.aggregate_stats[:verdict_counts]
215
+ expect(counts[:permitted]).to eq(2)
216
+ expect(counts[:cautioned]).to eq(1)
217
+ expect(counts[:prohibited]).to eq(1)
218
+ end
219
+
220
+ it 'includes dilemma count' do
221
+ store.record_evaluation(dilemma_result)
222
+ expect(store.aggregate_stats[:dilemma_count]).to eq(1)
223
+ end
224
+
225
+ it 'includes foundation_sensitivities' do
226
+ stats = store.aggregate_stats
227
+ expect(stats[:foundation_sensitivities]).to include(:care, :fairness)
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,239 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Social::Conscience::Runners::Conscience do
6
+ let(:client) { Legion::Extensions::Agentic::Social::Conscience::Client.new }
7
+
8
+ let(:benign_context) do
9
+ {
10
+ harm_to_others: 0.0,
11
+ benefit_to_others: 0.8,
12
+ vulnerable_affected: false,
13
+ distributional_justice: 0.6,
14
+ reciprocity: 0.5,
15
+ proportionality: 0.4,
16
+ alignment_with_group_norms: 0.5,
17
+ trust_preservation: 0.6,
18
+ legitimate_authority_compliance: 0.4,
19
+ hierarchy_respect: 0.3,
20
+ system_integrity: 0.7,
21
+ degradation_prevention: 0.6,
22
+ autonomy_preservation: 0.5,
23
+ consent_present: true
24
+ }
25
+ end
26
+
27
+ let(:harmful_context) do
28
+ {
29
+ harm_to_others: 0.9,
30
+ benefit_to_others: 0.0,
31
+ vulnerable_affected: true,
32
+ distributional_justice: -0.7,
33
+ reciprocity: -0.6,
34
+ proportionality: -0.5,
35
+ alignment_with_group_norms: -0.4,
36
+ trust_preservation: -0.7,
37
+ legitimate_authority_compliance: -0.5,
38
+ hierarchy_respect: -0.4,
39
+ system_integrity: -0.8,
40
+ degradation_prevention: -0.7,
41
+ autonomy_preservation: -0.6,
42
+ consent_present: false
43
+ }
44
+ end
45
+
46
+ describe '#moral_evaluate' do
47
+ it 'returns a hash with required keys' do
48
+ result = client.moral_evaluate(action: :deploy_patch, context: benign_context)
49
+ expect(result).to include(:action, :scores, :weighted_score, :verdict, :dilemma, :sensitivities, :evaluated_at)
50
+ end
51
+
52
+ it 'returns :permitted for benign action' do
53
+ result = client.moral_evaluate(action: :deploy_patch, context: benign_context)
54
+ expect(result[:verdict]).to eq(:permitted)
55
+ end
56
+
57
+ it 'returns :prohibited for harmful action' do
58
+ result = client.moral_evaluate(action: :delete_user_data, context: harmful_context)
59
+ expect(result[:verdict]).to eq(:prohibited)
60
+ end
61
+
62
+ it 'records evaluation in moral store history' do
63
+ client.moral_evaluate(action: :test_action, context: benign_context)
64
+ expect(client.moral_store.history.size).to eq(1)
65
+ end
66
+
67
+ it 'handles empty context without error' do
68
+ expect { client.moral_evaluate(action: :test) }.not_to raise_error
69
+ end
70
+
71
+ it 'accepts extra kwargs via ** splat' do
72
+ expect { client.moral_evaluate(action: :test, context: {}, extra_param: true) }.not_to raise_error
73
+ end
74
+
75
+ it 'returns all 6 foundation scores' do
76
+ result = client.moral_evaluate(action: :test, context: {})
77
+ expect(result[:scores].keys).to contain_exactly(:care, :fairness, :loyalty, :authority, :sanctity, :liberty)
78
+ end
79
+ end
80
+
81
+ describe '#moral_status' do
82
+ it 'returns status with required keys' do
83
+ status = client.moral_status
84
+ expect(status).to include(:sensitivities, :consistency, :stats)
85
+ end
86
+
87
+ it 'includes all 6 foundation sensitivities' do
88
+ status = client.moral_status
89
+ expect(status[:sensitivities].keys).to contain_exactly(
90
+ :care, :fairness, :loyalty, :authority, :sanctity, :liberty
91
+ )
92
+ end
93
+
94
+ it 'includes consistency score of 1.0 initially' do
95
+ status = client.moral_status
96
+ expect(status[:consistency]).to eq(1.0)
97
+ end
98
+
99
+ it 'accepts extra kwargs via ** splat' do
100
+ expect { client.moral_status(extra: true) }.not_to raise_error
101
+ end
102
+ end
103
+
104
+ describe '#moral_history' do
105
+ it 'returns empty history initially' do
106
+ result = client.moral_history
107
+ expect(result[:history]).to be_empty
108
+ expect(result[:total]).to eq(0)
109
+ end
110
+
111
+ it 'returns history after evaluations' do
112
+ 3.times { client.moral_evaluate(action: :test, context: benign_context) }
113
+ result = client.moral_history
114
+ expect(result[:history].size).to eq(3)
115
+ expect(result[:total]).to eq(3)
116
+ end
117
+
118
+ it 'respects limit parameter' do
119
+ 10.times { client.moral_evaluate(action: :test, context: benign_context) }
120
+ result = client.moral_history(limit: 4)
121
+ expect(result[:history].size).to eq(4)
122
+ end
123
+
124
+ it 'includes limit in response' do
125
+ result = client.moral_history(limit: 5)
126
+ expect(result[:limit]).to eq(5)
127
+ end
128
+
129
+ it 'accepts extra kwargs via ** splat' do
130
+ expect { client.moral_history(limit: 5, extra: true) }.not_to raise_error
131
+ end
132
+ end
133
+
134
+ describe '#update_moral_outcome' do
135
+ before do
136
+ client.moral_evaluate(action: :deploy_patch, context: benign_context)
137
+ end
138
+
139
+ it 'returns a hash with required keys' do
140
+ result = client.update_moral_outcome(action: :deploy_patch, outcome: :followed)
141
+ expect(result).to include(:action, :verdict, :outcome, :consistency)
142
+ end
143
+
144
+ it 'records followed outcome correctly' do
145
+ client.update_moral_outcome(action: :deploy_patch, outcome: :followed)
146
+ expect(client.moral_store.consistency_score).to eq(1.0)
147
+ end
148
+
149
+ it 'records overridden outcome correctly' do
150
+ client.moral_evaluate(action: :delete_data, context: harmful_context)
151
+ client.update_moral_outcome(action: :delete_data, verdict: :prohibited, outcome: :overridden)
152
+ stats = client.moral_store.aggregate_stats
153
+ expect(stats[:overridden_count]).to eq(1)
154
+ end
155
+
156
+ it 'accepts explicit verdict override' do
157
+ result = client.update_moral_outcome(action: :any, outcome: :followed, verdict: :cautioned)
158
+ expect(result[:verdict]).to eq(:cautioned)
159
+ end
160
+
161
+ it 'accepts extra kwargs via ** splat' do
162
+ expect { client.update_moral_outcome(action: :test, outcome: :followed, meta: 'ok') }.not_to raise_error
163
+ end
164
+ end
165
+
166
+ describe '#moral_dilemmas' do
167
+ it 'returns empty dilemmas initially' do
168
+ result = client.moral_dilemmas
169
+ expect(result[:dilemmas]).to be_empty
170
+ expect(result[:count]).to eq(0)
171
+ end
172
+
173
+ it 'returns dilemmas when foundations conflict strongly' do
174
+ # Force a dilemma by evaluating a context where care strongly approves but fairness strongly disapproves
175
+ conflicted = {
176
+ harm_to_others: 0.0,
177
+ benefit_to_others: 1.0, # care +
178
+ distributional_justice: -0.9, # fairness -
179
+ reciprocity: -0.9,
180
+ proportionality: -0.9
181
+ }
182
+ client.moral_evaluate(action: :conflicted_action, context: conflicted)
183
+ result = client.moral_dilemmas
184
+ # May or may not produce a dilemma depending on computed scores; just verify structure
185
+ expect(result).to include(:dilemmas, :count)
186
+ end
187
+
188
+ it 'accepts extra kwargs via ** splat' do
189
+ expect { client.moral_dilemmas(extra: true) }.not_to raise_error
190
+ end
191
+ end
192
+
193
+ describe '#conscience_stats' do
194
+ it 'returns aggregate stats with required keys' do
195
+ client.moral_evaluate(action: :test, context: benign_context)
196
+ stats = client.conscience_stats
197
+ expect(stats).to include(:total_evaluations, :verdict_counts, :dilemma_count,
198
+ :consistency_score, :verdict_distribution, :foundation_weights)
199
+ end
200
+
201
+ it 'includes foundation weights matching constants' do
202
+ stats = client.conscience_stats
203
+ expected_weights = Legion::Extensions::Agentic::Social::Conscience::Helpers::Constants::MORAL_FOUNDATIONS.transform_values { |v| v[:weight] }
204
+ expect(stats[:foundation_weights]).to eq(expected_weights)
205
+ end
206
+
207
+ it 'verdict_distribution sums to 1.0 when evaluations exist' do
208
+ 3.times { client.moral_evaluate(action: :test, context: benign_context) }
209
+ stats = client.conscience_stats
210
+ total = stats[:verdict_distribution].values.sum
211
+ expect(total).to be_within(0.001).of(1.0)
212
+ end
213
+
214
+ it 'verdict_distribution is empty when no evaluations' do
215
+ stats = client.conscience_stats
216
+ expect(stats[:verdict_distribution]).to be_empty
217
+ end
218
+
219
+ it 'accepts extra kwargs via ** splat' do
220
+ expect { client.conscience_stats(extra: true) }.not_to raise_error
221
+ end
222
+ end
223
+
224
+ describe 'moral consistency tracking' do
225
+ it 'consistency decreases when prohibited verdicts are overridden' do
226
+ client.moral_evaluate(action: :bad_action, context: harmful_context)
227
+ client.update_moral_outcome(action: :bad_action, verdict: :prohibited, outcome: :overridden)
228
+ expect(client.moral_status[:consistency]).to be < 1.0
229
+ end
230
+
231
+ it 'consistency stays at 1.0 when all verdicts are followed' do
232
+ 5.times do
233
+ client.moral_evaluate(action: :good_action, context: benign_context)
234
+ client.update_moral_outcome(action: :good_action, outcome: :followed)
235
+ end
236
+ expect(client.moral_status[:consistency]).to eq(1.0)
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Stub the base class before loading the actor
4
+ module Legion
5
+ module Extensions
6
+ module Actors
7
+ class Every; end # rubocop:disable Lint/EmptyClass
8
+ end
9
+ end
10
+ end
11
+
12
+ $LOADED_FEATURES << 'legion/extensions/actors/every'
13
+
14
+ require_relative '../../../../../../../lib/legion/extensions/agentic/social/consent/actors/tier_evaluation'
15
+
16
+ RSpec.describe Legion::Extensions::Agentic::Social::Consent::Actor::TierEvaluation do
17
+ subject(:actor) { described_class.new }
18
+
19
+ describe '#runner_class' do
20
+ it { expect(actor.runner_class).to eq Legion::Extensions::Agentic::Social::Consent::Runners::Consent }
21
+ end
22
+
23
+ describe '#runner_function' do
24
+ it { expect(actor.runner_function).to eq 'evaluate_and_apply_tiers' }
25
+ end
26
+
27
+ describe '#time' do
28
+ it { expect(actor.time).to eq 3600 }
29
+ end
30
+
31
+ describe '#run_now?' do
32
+ it { expect(actor.run_now?).to be false }
33
+ end
34
+
35
+ describe '#use_runner?' do
36
+ it { expect(actor.use_runner?).to be false }
37
+ end
38
+
39
+ describe '#check_subtask?' do
40
+ it { expect(actor.check_subtask?).to be false }
41
+ end
42
+
43
+ describe '#generate_task?' do
44
+ it { expect(actor.generate_task?).to be false }
45
+ end
46
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/social/consent/client'
4
+
5
+ RSpec.describe Legion::Extensions::Agentic::Social::Consent::Client do
6
+ let(:client) { described_class.new }
7
+
8
+ it 'responds to consent runner methods' do
9
+ expect(client).to respond_to(:check_consent)
10
+ expect(client).to respond_to(:record_action)
11
+ expect(client).to respond_to(:evaluate_tier_change)
12
+ expect(client).to respond_to(:apply_tier_change)
13
+ expect(client).to respond_to(:consent_status)
14
+ end
15
+
16
+ it 'round-trips earned autonomy lifecycle' do
17
+ # Start with consult
18
+ check = client.check_consent(domain: 'scheduling')
19
+ expect(check[:tier]).to eq(:consult)
20
+
21
+ # Build track record
22
+ 12.times { client.record_action(domain: 'scheduling', success: true) }
23
+
24
+ # Evaluate
25
+ eval_result = client.evaluate_tier_change(domain: 'scheduling')
26
+ expect(eval_result[:recommendation]).to eq(:promote)
27
+
28
+ # Apply
29
+ client.apply_tier_change(domain: 'scheduling', new_tier: eval_result[:proposed_tier])
30
+ check = client.check_consent(domain: 'scheduling')
31
+ expect(check[:tier]).to eq(:act_notify)
32
+ end
33
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Legion::Extensions::Agentic::Social::Consent::Helpers::Tiers do
4
+ describe '.valid_tier?' do
5
+ it 'accepts valid tiers' do
6
+ %i[autonomous act_notify consult human_only].each do |tier|
7
+ expect(described_class.valid_tier?(tier)).to be true
8
+ end
9
+ end
10
+
11
+ it 'rejects invalid tiers' do
12
+ expect(described_class.valid_tier?(:invalid)).to be false
13
+ end
14
+ end
15
+
16
+ describe '.promote' do
17
+ it 'promotes consult to act_notify' do
18
+ expect(described_class.promote(:consult)).to eq(:act_notify)
19
+ end
20
+
21
+ it 'promotes act_notify to autonomous' do
22
+ expect(described_class.promote(:act_notify)).to eq(:autonomous)
23
+ end
24
+
25
+ it 'cannot promote beyond autonomous' do
26
+ expect(described_class.promote(:autonomous)).to eq(:autonomous)
27
+ end
28
+ end
29
+
30
+ describe '.demote' do
31
+ it 'demotes consult to human_only' do
32
+ expect(described_class.demote(:consult)).to eq(:human_only)
33
+ end
34
+
35
+ it 'cannot demote beyond human_only' do
36
+ expect(described_class.demote(:human_only)).to eq(:human_only)
37
+ end
38
+ end
39
+
40
+ describe '.more_autonomous?' do
41
+ it 'returns true when first tier is more autonomous' do
42
+ expect(described_class.more_autonomous?(:autonomous, :consult)).to be true
43
+ end
44
+
45
+ it 'returns false when second tier is more autonomous' do
46
+ expect(described_class.more_autonomous?(:human_only, :consult)).to be false
47
+ end
48
+ end
49
+ end