Class: Legion::Extensions::Agentic::Social::MoralReasoning::Helpers::MoralEngine
- Inherits:
-
Object
- Object
- Legion::Extensions::Agentic::Social::MoralReasoning::Helpers::MoralEngine
show all
- Includes:
- Constants, FrameworkEvaluators
- Defined in:
- lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb
Constant Summary
collapse
- KOHLBERG_STAGE_DESCRIPTIONS =
{
obedience: 'Avoid punishment; obey authority unconditionally',
self_interest: 'Act for direct reward; reciprocal exchange',
conformity: 'Conform to social norms; be a good person',
law_and_order: 'Follow rules, laws, and authority to maintain social order',
social_contract: 'Uphold democratic principles; greatest good for greatest number',
universal_ethics: 'Follow self-chosen universal ethical principles'
}.freeze
- FRAMEWORK_STRATEGIES =
{
utilitarian: :evaluate_by_utility,
deontological: :evaluate_by_duty,
virtue: :evaluate_by_virtue,
care: :evaluate_by_care,
justice: :evaluate_by_justice,
rights: :evaluate_by_rights
}.freeze
FrameworkEvaluators::CARE_FOUNDATIONS, FrameworkEvaluators::DUTY_FOUNDATIONS, FrameworkEvaluators::JUSTICE_FOUNDATIONS, FrameworkEvaluators::RIGHTS_FOUNDATIONS
Constants included
from Constants
Constants::DECAY_RATE, Constants::DEFAULT_WEIGHT, Constants::ETHICAL_FRAMEWORKS, Constants::KOHLBERG_LEVELS, Constants::KOHLBERG_STAGES, Constants::MAX_DILEMMAS, Constants::MAX_HISTORY, Constants::MAX_PRINCIPLES, Constants::MORAL_FOUNDATIONS, Constants::REINFORCEMENT_RATE, Constants::SEVERITY_LABELS, Constants::WEIGHT_CEILING, Constants::WEIGHT_FLOOR
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#add_principle(name:, description:, foundation:, weight: DEFAULT_WEIGHT) ⇒ Object
-
#apply_framework(dilemma_id:, framework:) ⇒ Object
-
#decay_all ⇒ Object
-
#evaluate_action(action:, affected_foundations:, domain: :general) ⇒ Object
-
#foundation_profile ⇒ Object
-
#initialize ⇒ MoralEngine
constructor
A new instance of MoralEngine.
-
#moral_development ⇒ Object
-
#pose_dilemma(description:, options:, domain: :general, severity: 0.5) ⇒ Object
-
#resolve_dilemma(dilemma_id:, option_id:, reasoning:, framework:) ⇒ Object
-
#resolved_dilemmas ⇒ Object
-
#stage_info ⇒ Object
-
#to_h ⇒ Object
-
#unresolved_dilemmas ⇒ Object
Constructor Details
Returns a new instance of MoralEngine.
86
87
88
89
90
91
92
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 86
def initialize
@foundations = MORAL_FOUNDATIONS.to_h { |f| [f, MoralFoundation.new(id: f)] }
@principles = []
@dilemmas = {}
@stage = :social_contract
@history = []
end
|
Instance Attribute Details
#dilemmas ⇒ Object
Returns the value of attribute dilemmas.
84
85
86
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 84
def dilemmas
@dilemmas
end
|
#history ⇒ Object
Returns the value of attribute history.
84
85
86
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 84
def history
@history
end
|
#principles ⇒ Object
Returns the value of attribute principles.
84
85
86
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 84
def principles
@principles
end
|
#stage ⇒ Object
Returns the value of attribute stage.
84
85
86
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 84
def stage
@stage
end
|
Instance Method Details
#add_principle(name:, description:, foundation:, weight: DEFAULT_WEIGHT) ⇒ Object
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 137
def add_principle(name:, description:, foundation:, weight: DEFAULT_WEIGHT)
return { success: false, reason: :max_principles_reached } if @principles.size >= MAX_PRINCIPLES
return { success: false, reason: :unknown_foundation } unless MORAL_FOUNDATIONS.include?(foundation)
principle = {
id: generate_id('principle'),
name: name,
description: description,
foundation: foundation,
weight: weight.clamp(WEIGHT_FLOOR, WEIGHT_CEILING),
created_at: Time.now.utc
}
@principles << principle
{ success: true, principle: principle }
end
|
#apply_framework(dilemma_id:, framework:) ⇒ Object
127
128
129
130
131
132
133
134
135
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 127
def apply_framework(dilemma_id:, framework:)
dilemma = @dilemmas[dilemma_id]
return { success: false, reason: :not_found } unless dilemma
return { success: false, reason: :unknown_framework } unless ETHICAL_FRAMEWORKS.include?(framework)
strategy = FRAMEWORK_STRATEGIES.fetch(framework)
rankings = send(strategy, dilemma)
{ success: true, dilemma_id: dilemma_id, framework: framework, rankings: rankings }
end
|
#decay_all ⇒ Object
186
187
188
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 186
def decay_all
@foundations.each_value(&:decay)
end
|
#evaluate_action(action:, affected_foundations:, domain: :general) ⇒ Object
94
95
96
97
98
99
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 94
def evaluate_action(action:, affected_foundations:, domain: :general)
score = score_foundations(affected_foundations)
normalized = affected_foundations.empty? ? 0.0 : score / affected_foundations.size
add_history(type: :evaluation, action: action, domain: domain, score: normalized)
{ action: action, domain: domain, score: normalized, foundations: affected_foundations }
end
|
#foundation_profile ⇒ Object
169
170
171
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 169
def foundation_profile
@foundations.transform_values(&:to_h)
end
|
#moral_development ⇒ Object
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 153
def moral_development
resolved = resolved_dilemmas
return { advanced: false, stage: @stage, reason: :insufficient_resolutions } if resolved.size < 3
avg_severity = resolved.sum(&:severity) / resolved.size.to_f
complexity_met = avg_severity >= 0.4 && resolved.size >= 5
current_idx = KOHLBERG_STAGES.index(@stage)
if complexity_met && current_idx < KOHLBERG_STAGES.size - 1
@stage = KOHLBERG_STAGES[current_idx + 1]
{ advanced: true, stage: @stage, previous_stage: KOHLBERG_STAGES[current_idx] }
else
{ advanced: false, stage: @stage, reason: :complexity_threshold_not_met }
end
end
|
#pose_dilemma(description:, options:, domain: :general, severity: 0.5) ⇒ Object
101
102
103
104
105
106
107
108
109
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 101
def pose_dilemma(description:, options:, domain: :general, severity: 0.5)
return { success: false, reason: :max_dilemmas_reached } if @dilemmas.size >= MAX_DILEMMAS
id = generate_id('dilemma')
dilemma = Dilemma.new(id: id, description: description, options: options,
domain: domain, severity: severity)
@dilemmas[id] = dilemma
{ success: true, dilemma: dilemma.to_h }
end
|
#resolve_dilemma(dilemma_id:, option_id:, reasoning:, framework:) ⇒ Object
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 111
def resolve_dilemma(dilemma_id:, option_id:, reasoning:, framework:)
dilemma = @dilemmas[dilemma_id]
return { success: false, reason: :not_found } unless dilemma
return { success: false, reason: :already_resolved } if dilemma.resolved?
chosen = dilemma.options.find { |o| o[:id] == option_id }
return { success: false, reason: :invalid_option } unless chosen
dilemma.resolve(option_id: option_id, reasoning: reasoning, framework: framework)
reinforce_chosen_foundations(chosen)
weaken_unchosen_foundations(dilemma.options, option_id)
add_history(type: :resolution, dilemma_id: dilemma_id, option_id: option_id,
framework: framework, severity: dilemma.severity)
{ success: true, dilemma: dilemma.to_h }
end
|
#resolved_dilemmas ⇒ Object
182
183
184
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 182
def resolved_dilemmas
@dilemmas.values.select(&:resolved?)
end
|
#stage_info ⇒ Object
173
174
175
176
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 173
def stage_info
level = KOHLBERG_LEVELS.find { |_, stages| stages.include?(@stage) }&.first
{ stage: @stage, level: level, description: KOHLBERG_STAGE_DESCRIPTIONS.fetch(@stage, 'Unknown') }
end
|
#to_h ⇒ Object
190
191
192
193
194
195
196
197
198
199
200
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 190
def to_h
{
stage: @stage,
total_dilemmas: @dilemmas.size,
resolved_dilemmas: resolved_dilemmas.size,
unresolved_dilemmas: unresolved_dilemmas.size,
principles: @principles.size,
history_entries: @history.size,
foundation_profile: foundation_profile
}
end
|
#unresolved_dilemmas ⇒ Object
178
179
180
|
# File 'lib/legion/extensions/agentic/social/moral_reasoning/helpers/moral_engine.rb', line 178
def unresolved_dilemmas
@dilemmas.values.reject(&:resolved?)
end
|