superinstance-equipment-consensus-engine 1.0.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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +448 -0
- data/lib/equipment/consensus_engine/conflict_resolution.rb +507 -0
- data/lib/equipment/consensus_engine/consensus_engine.rb +451 -0
- data/lib/equipment/consensus_engine/tripartite_deliberation.rb +645 -0
- data/lib/equipment/consensus_engine/types.rb +229 -0
- data/lib/equipment/consensus_engine/version.rb +9 -0
- data/lib/equipment/consensus_engine/weight_calculator.rb +438 -0
- data/lib/equipment/consensus_engine.rb +17 -0
- metadata +65 -0
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'types'
|
|
4
|
+
|
|
5
|
+
module SuperInstance
|
|
6
|
+
module Equipment
|
|
7
|
+
module ConsensusEngine
|
|
8
|
+
# TripartiteDeliberation - Pathos/Logos/Ethos 3-agent deliberation
|
|
9
|
+
#
|
|
10
|
+
# Implements the classical rhetorical framework for argumentation
|
|
11
|
+
# through three fundamental modes of persuasion.
|
|
12
|
+
#
|
|
13
|
+
# The tripartite framework originates from Aristotle's Rhetoric and provides
|
|
14
|
+
# a comprehensive approach to argumentation:
|
|
15
|
+
#
|
|
16
|
+
# - **Pathos**: Appeals to emotion, intent, and human experience
|
|
17
|
+
# - **Logos**: Appeals to logic, reason, and rational argument
|
|
18
|
+
# - **Ethos**: Appeals to ethics, credibility, and moral character
|
|
19
|
+
#
|
|
20
|
+
# @example
|
|
21
|
+
# deliberation = SuperInstance::Equipment::ConsensusEngine::TripartiteDeliberation.new
|
|
22
|
+
#
|
|
23
|
+
# pathos_analysis = deliberation.analyze(
|
|
24
|
+
# :pathos,
|
|
25
|
+
# 'Should we reduce work hours?',
|
|
26
|
+
# 'A company is considering a 4-day work week'
|
|
27
|
+
# )
|
|
28
|
+
class TripartiteDeliberation
|
|
29
|
+
# Creates a new TripartiteDeliberation instance
|
|
30
|
+
def initialize
|
|
31
|
+
@perspective_configs = {
|
|
32
|
+
pathos: { threshold: 0.6, style: :collaborative },
|
|
33
|
+
logos: { threshold: 0.7, style: :inquisitive },
|
|
34
|
+
ethos: { threshold: 0.75, style: :adversarial }
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Analyzes a proposition from a specific perspective
|
|
39
|
+
# @param perspective [Symbol] The perspective to analyze from
|
|
40
|
+
# @param proposition [String] The proposition to analyze
|
|
41
|
+
# @param context [String] The context for deliberation
|
|
42
|
+
# @param previous_opinions [Array<Hash>] Opinions from previous rounds
|
|
43
|
+
# @return [Hash] The perspective's analysis
|
|
44
|
+
def analyze(perspective, proposition, context, previous_opinions = [])
|
|
45
|
+
case perspective
|
|
46
|
+
when :pathos
|
|
47
|
+
analyze_from_pathos(proposition, context, previous_opinions)
|
|
48
|
+
when :logos
|
|
49
|
+
analyze_from_logos(proposition, context, previous_opinions)
|
|
50
|
+
when :ethos
|
|
51
|
+
analyze_from_ethos(proposition, context, previous_opinions)
|
|
52
|
+
else
|
|
53
|
+
raise ArgumentError, "Unknown perspective: #{perspective}"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Sets the configuration for a perspective
|
|
58
|
+
# @param perspective [Symbol] The perspective to configure
|
|
59
|
+
# @param config [Hash] Configuration options { threshold: Float, style: Symbol }
|
|
60
|
+
def set_perspective_config(perspective, config)
|
|
61
|
+
current = @perspective_configs[perspective]
|
|
62
|
+
return unless current
|
|
63
|
+
|
|
64
|
+
@perspective_configs[perspective] = {
|
|
65
|
+
threshold: config[:threshold] || current[:threshold],
|
|
66
|
+
style: config[:style] || current[:style]
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Gets the configuration for a perspective
|
|
71
|
+
# @param perspective [Symbol] The perspective to get config for
|
|
72
|
+
# @return [Hash] Configuration { threshold: Float, style: Symbol }
|
|
73
|
+
def get_perspective_config(perspective)
|
|
74
|
+
config = @perspective_configs[perspective]
|
|
75
|
+
raise ArgumentError, "Unknown perspective: #{perspective}" unless config
|
|
76
|
+
config.dup
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
# Analyzes from the Pathos perspective (emotion/intent)
|
|
82
|
+
def analyze_from_pathos(proposition, context, previous_opinions)
|
|
83
|
+
# Extract emotional dimensions
|
|
84
|
+
characteristics = extract_pathos_characteristics(proposition, context)
|
|
85
|
+
|
|
86
|
+
# Consider previous emotional arguments
|
|
87
|
+
previous_pathos = previous_opinions.find { |op| op[:perspective] == :pathos }
|
|
88
|
+
|
|
89
|
+
# Generate emotional analysis
|
|
90
|
+
verdict = generate_pathos_verdict(proposition, characteristics, previous_pathos)
|
|
91
|
+
confidence = calculate_pathos_confidence(characteristics, previous_opinions)
|
|
92
|
+
arguments = generate_pathos_arguments(characteristics)
|
|
93
|
+
concerns = identify_pathos_concerns(characteristics)
|
|
94
|
+
|
|
95
|
+
{
|
|
96
|
+
perspective: :pathos,
|
|
97
|
+
verdict: verdict,
|
|
98
|
+
confidence: confidence,
|
|
99
|
+
arguments: arguments,
|
|
100
|
+
concerns: concerns,
|
|
101
|
+
emotional_tone: characteristics[:primary_emotion],
|
|
102
|
+
suggestions: generate_pathos_suggestions(characteristics)
|
|
103
|
+
}
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Analyzes from the Logos perspective (logic/reason)
|
|
107
|
+
def analyze_from_logos(proposition, context, previous_opinions)
|
|
108
|
+
# Extract logical structure
|
|
109
|
+
characteristics = extract_logos_characteristics(proposition, context)
|
|
110
|
+
|
|
111
|
+
# Consider previous logical arguments
|
|
112
|
+
previous_logos = previous_opinions.find { |op| op[:perspective] == :logos }
|
|
113
|
+
|
|
114
|
+
# Generate logical analysis
|
|
115
|
+
verdict = generate_logos_verdict(proposition, characteristics, previous_logos)
|
|
116
|
+
confidence = calculate_logos_confidence(characteristics, previous_opinions)
|
|
117
|
+
arguments = generate_logos_arguments(characteristics)
|
|
118
|
+
concerns = identify_logos_concerns(characteristics)
|
|
119
|
+
logical_validity = assess_logical_validity(characteristics)
|
|
120
|
+
|
|
121
|
+
{
|
|
122
|
+
perspective: :logos,
|
|
123
|
+
verdict: verdict,
|
|
124
|
+
confidence: confidence,
|
|
125
|
+
arguments: arguments,
|
|
126
|
+
concerns: concerns,
|
|
127
|
+
logical_validity: logical_validity,
|
|
128
|
+
suggestions: generate_logos_suggestions(characteristics)
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Analyzes from the Ethos perspective (ethics/truth)
|
|
133
|
+
def analyze_from_ethos(proposition, context, previous_opinions)
|
|
134
|
+
# Extract ethical dimensions
|
|
135
|
+
characteristics = extract_ethos_characteristics(proposition, context)
|
|
136
|
+
|
|
137
|
+
# Consider previous ethical arguments
|
|
138
|
+
previous_ethos = previous_opinions.find { |op| op[:perspective] == :ethos }
|
|
139
|
+
|
|
140
|
+
# Generate ethical analysis
|
|
141
|
+
verdict = generate_ethos_verdict(proposition, characteristics, previous_ethos)
|
|
142
|
+
confidence = calculate_ethos_confidence(characteristics, previous_opinions)
|
|
143
|
+
arguments = generate_ethos_arguments(characteristics)
|
|
144
|
+
concerns = identify_ethos_concerns(characteristics)
|
|
145
|
+
ethical_alignment = assess_ethical_alignment(characteristics)
|
|
146
|
+
|
|
147
|
+
{
|
|
148
|
+
perspective: :ethos,
|
|
149
|
+
verdict: verdict,
|
|
150
|
+
confidence: confidence,
|
|
151
|
+
arguments: arguments,
|
|
152
|
+
concerns: concerns,
|
|
153
|
+
ethical_alignment: ethical_alignment,
|
|
154
|
+
suggestions: generate_ethos_suggestions(characteristics)
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Extracts pathos characteristics from proposition and context
|
|
159
|
+
def extract_pathos_characteristics(proposition, context)
|
|
160
|
+
combined = "#{proposition} #{context}".downcase
|
|
161
|
+
|
|
162
|
+
# Detect primary emotion
|
|
163
|
+
emotions = %w[hope fear joy anger sadness surprise trust anticipation]
|
|
164
|
+
detected_emotions = emotions.select { |e| combined.include?(e) }
|
|
165
|
+
primary_emotion = detected_emotions[0] || 'neutral'
|
|
166
|
+
|
|
167
|
+
# Calculate emotional intensity based on emotional words
|
|
168
|
+
emotional_words = %w[urgent critical important essential vital crucial]
|
|
169
|
+
intensity = emotional_words.sum do |word|
|
|
170
|
+
combined.include?(word) ? 0.15 : 0
|
|
171
|
+
end
|
|
172
|
+
intensity = [intensity + 0.3, 1.0].min
|
|
173
|
+
|
|
174
|
+
# Identify stakeholders
|
|
175
|
+
stakeholders = identify_stakeholders(combined)
|
|
176
|
+
|
|
177
|
+
# Identify emotional risks
|
|
178
|
+
emotional_risks = identify_emotional_risks(combined)
|
|
179
|
+
|
|
180
|
+
{
|
|
181
|
+
primary_emotion: primary_emotion,
|
|
182
|
+
intensity: intensity,
|
|
183
|
+
stakeholders: stakeholders,
|
|
184
|
+
emotional_risks: emotional_risks
|
|
185
|
+
}
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Extracts logos characteristics from proposition and context
|
|
189
|
+
def extract_logos_characteristics(proposition, context)
|
|
190
|
+
combined = "#{proposition} #{context}".downcase
|
|
191
|
+
|
|
192
|
+
# Determine logical structure
|
|
193
|
+
logical_structure = :inductive
|
|
194
|
+
if combined.include?('therefore') || combined.include?('thus') || combined.include?('must')
|
|
195
|
+
logical_structure = :deductive
|
|
196
|
+
elsif combined.include?('likely') || combined.include?('probably') || combined.include?('suggests')
|
|
197
|
+
logical_structure = :abductive
|
|
198
|
+
elsif combined.include?('like') || combined.include?('similar') || combined.include?('comparable')
|
|
199
|
+
logical_structure = :analogical
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Extract premises
|
|
203
|
+
premises = extract_premises(combined)
|
|
204
|
+
|
|
205
|
+
# Identify assumptions
|
|
206
|
+
assumptions = identify_assumptions(combined)
|
|
207
|
+
|
|
208
|
+
# Identify logical risks
|
|
209
|
+
logical_risks = identify_logical_risks(combined)
|
|
210
|
+
|
|
211
|
+
{
|
|
212
|
+
logical_structure: logical_structure,
|
|
213
|
+
premises: premises,
|
|
214
|
+
assumptions: assumptions,
|
|
215
|
+
logical_risks: logical_risks
|
|
216
|
+
}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Extracts ethos characteristics from proposition and context
|
|
220
|
+
def extract_ethos_characteristics(proposition, context)
|
|
221
|
+
combined = "#{proposition} #{context}".downcase
|
|
222
|
+
|
|
223
|
+
# Determine ethical framework
|
|
224
|
+
ethical_framework = :utilitarian
|
|
225
|
+
if combined.include?('rights') || combined.include?('duty') || combined.include?('obligation')
|
|
226
|
+
ethical_framework = :deontological
|
|
227
|
+
elsif combined.include?('virtue') || combined.include?('character') || combined.include?('integrity')
|
|
228
|
+
ethical_framework = :virtue_ethics
|
|
229
|
+
elsif combined.include?('care') || combined.include?('relationship') || combined.include?('empathy')
|
|
230
|
+
ethical_framework = :care_ethics
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Identify principles
|
|
234
|
+
principles = identify_principles(combined)
|
|
235
|
+
|
|
236
|
+
# Identify values at stake
|
|
237
|
+
values_at_stake = identify_values_at_stake(combined)
|
|
238
|
+
|
|
239
|
+
# Identify ethical risks
|
|
240
|
+
ethical_risks = identify_ethical_risks(combined)
|
|
241
|
+
|
|
242
|
+
{
|
|
243
|
+
ethical_framework: ethical_framework,
|
|
244
|
+
principles: principles,
|
|
245
|
+
values_at_stake: values_at_stake,
|
|
246
|
+
ethical_risks: ethical_risks
|
|
247
|
+
}
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Helper methods for pathos analysis
|
|
251
|
+
def identify_stakeholders(text)
|
|
252
|
+
stakeholders = []
|
|
253
|
+
if text.include?('employee') || text.include?('worker') || text.include?('staff')
|
|
254
|
+
stakeholders << 'employees'
|
|
255
|
+
end
|
|
256
|
+
if text.include?('customer') || text.include?('client') || text.include?('user')
|
|
257
|
+
stakeholders << 'customers'
|
|
258
|
+
end
|
|
259
|
+
if text.include?('community') || text.include?('society') || text.include?('public')
|
|
260
|
+
stakeholders << 'community'
|
|
261
|
+
end
|
|
262
|
+
if text.include?('environment') || text.include?('nature') || text.include?('ecosystem')
|
|
263
|
+
stakeholders << 'environment'
|
|
264
|
+
end
|
|
265
|
+
stakeholders.any? ? stakeholders : ['affected parties']
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def identify_emotional_risks(text)
|
|
269
|
+
risks = []
|
|
270
|
+
if text.include?('change') || text.include?('transform')
|
|
271
|
+
risks << 'Resistance to change'
|
|
272
|
+
end
|
|
273
|
+
if text.include?('reduce') || text.include?('cut') || text.include?('decrease')
|
|
274
|
+
risks << 'Anxiety about loss'
|
|
275
|
+
end
|
|
276
|
+
if text.include?('increase') || text.include?('expand') || text.include?('grow')
|
|
277
|
+
risks << 'Fear of overwhelm'
|
|
278
|
+
end
|
|
279
|
+
risks.any? ? risks : ['Unknown emotional impact']
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def generate_pathos_verdict(proposition, characteristics, previous_pathos)
|
|
283
|
+
emotional_appeal = characteristics[:intensity] > 0.6 ? 'strong' : 'moderate'
|
|
284
|
+
stakeholder_count = characteristics[:stakeholders].length
|
|
285
|
+
|
|
286
|
+
if previous_pathos
|
|
287
|
+
return "After reconsideration, the emotional impact on #{characteristics[:stakeholders].join(', ')} remains a key factor. The proposition has #{emotional_appeal} emotional appeal with #{characteristics[:primary_emotion]} as the primary emotion. Proceeding with caution is advised."
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
"From an emotional standpoint, this proposition affects #{stakeholder_count} stakeholder groups: #{characteristics[:stakeholders].join(', ')}. The primary emotion of #{characteristics[:primary_emotion]} with #{emotional_appeal} intensity suggests #{characteristics[:intensity] > 0.5 ? 'proceeding with empathetic consideration' : 'the emotional impact may be manageable'}."
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def calculate_pathos_confidence(characteristics, previous_opinions)
|
|
294
|
+
confidence = 0.5
|
|
295
|
+
|
|
296
|
+
# Higher confidence with more identified stakeholders
|
|
297
|
+
confidence += [0.2, characteristics[:stakeholders].length * 0.05].min
|
|
298
|
+
|
|
299
|
+
# Higher confidence with clear emotional signal
|
|
300
|
+
if characteristics[:primary_emotion] != 'neutral'
|
|
301
|
+
confidence += 0.1
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Consider previous logos agreement
|
|
305
|
+
previous_logos = previous_opinions.find { |op| op[:perspective] == :logos }
|
|
306
|
+
if previous_logos && previous_logos[:confidence] > 0.6
|
|
307
|
+
confidence += 0.05
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
[confidence, 1.0].min
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def generate_pathos_arguments(characteristics)
|
|
314
|
+
args = []
|
|
315
|
+
|
|
316
|
+
args << "Addresses emotional needs of #{characteristics[:stakeholders].join(' and ')}"
|
|
317
|
+
|
|
318
|
+
if characteristics[:intensity] > 0.6
|
|
319
|
+
args << "Strong emotional engagement through #{characteristics[:primary_emotion]}"
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
if characteristics[:emotional_risks].any?
|
|
323
|
+
args << "Requires managing: #{characteristics[:emotional_risks].join(', ')}"
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
args
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def identify_pathos_concerns(characteristics)
|
|
330
|
+
concerns = []
|
|
331
|
+
|
|
332
|
+
if characteristics[:intensity] > 0.7
|
|
333
|
+
concerns << 'High emotional intensity may cloud rational judgment'
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
if characteristics[:stakeholders].length > 3
|
|
337
|
+
concerns << 'Multiple stakeholder groups may have conflicting emotional needs'
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
if characteristics[:emotional_risks].any? { |r| r.include?('Resistance') || r.include?('Anxiety') }
|
|
341
|
+
concerns << 'Potential for emotional resistance that needs addressing'
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
concerns.any? ? concerns : ['Emotional impact appears manageable']
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def generate_pathos_suggestions(characteristics)
|
|
348
|
+
suggestions = []
|
|
349
|
+
|
|
350
|
+
suggestions << "Consider communication strategy for #{characteristics[:stakeholders].join(' and ')}"
|
|
351
|
+
|
|
352
|
+
if characteristics[:primary_emotion] != 'neutral'
|
|
353
|
+
suggestions << "Address the #{characteristics[:primary_emotion]} emotion directly in implementation"
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
suggestions
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# Helper methods for logos analysis
|
|
360
|
+
def extract_premises(text)
|
|
361
|
+
premises = []
|
|
362
|
+
|
|
363
|
+
if text.include?('because') || text.include?('since')
|
|
364
|
+
premises << 'Causal reasoning detected in argument'
|
|
365
|
+
end
|
|
366
|
+
if text.include?('data') || text.include?('evidence') || text.include?('research')
|
|
367
|
+
premises << 'Empirical evidence cited'
|
|
368
|
+
end
|
|
369
|
+
if text.include?('experience') || text.include?('history') || text.include?('track record')
|
|
370
|
+
premises << 'Historical precedent referenced'
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
premises.any? ? premises : ['Implicit premises require examination']
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def identify_assumptions(text)
|
|
377
|
+
assumptions = []
|
|
378
|
+
|
|
379
|
+
if text.include?('will') || text.include?('going to')
|
|
380
|
+
assumptions << 'Future prediction assumed certain'
|
|
381
|
+
end
|
|
382
|
+
if text.include?('always') || text.include?('never')
|
|
383
|
+
assumptions << 'Absolute statements may oversimplify'
|
|
384
|
+
end
|
|
385
|
+
if text.include?('everyone') || text.include?('nobody')
|
|
386
|
+
assumptions << 'Universal claims need verification'
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
assumptions.any? ? assumptions : ['Standard assumptions apply']
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def identify_logical_risks(text)
|
|
393
|
+
risks = []
|
|
394
|
+
|
|
395
|
+
if text.include?('all') && text.include?('must')
|
|
396
|
+
risks << 'Potential hasty generalization'
|
|
397
|
+
end
|
|
398
|
+
if text.include?('either') && text.include?('or')
|
|
399
|
+
risks << 'Possible false dichotomy'
|
|
400
|
+
end
|
|
401
|
+
if text.include?('because') && text.include?('popular')
|
|
402
|
+
risks << 'Potential appeal to popularity'
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
risks.any? ? risks : ['Logical structure appears sound']
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def generate_logos_verdict(proposition, characteristics, previous_logos)
|
|
409
|
+
structure_desc = {
|
|
410
|
+
deductive: 'following a deductive structure from general principles',
|
|
411
|
+
inductive: 'building from specific observations to general conclusions',
|
|
412
|
+
abductive: 'inferring the most likely explanation',
|
|
413
|
+
analogical: 'drawing parallels from comparable situations'
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if previous_logos
|
|
417
|
+
return "Upon re-examination, the #{characteristics[:logical_structure]} reasoning remains valid with #{characteristics[:premises].length} supporting premises. The logical risks (#{characteristics[:logical_risks].join(', ')}) should be monitored."
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
"The proposition presents #{structure_desc[characteristics[:logical_structure]]}. #{characteristics[:premises].length} premises have been identified. The argument's logical foundation is #{characteristics[:assumptions].length > 1 ? 'subject to several assumptions that warrant scrutiny' : 'relatively straightforward'}."
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def calculate_logos_confidence(characteristics, previous_opinions)
|
|
424
|
+
confidence = 0.5
|
|
425
|
+
|
|
426
|
+
# More premises increase confidence
|
|
427
|
+
confidence += [0.2, characteristics[:premises].length * 0.05].min
|
|
428
|
+
|
|
429
|
+
# Fewer assumptions is better
|
|
430
|
+
confidence -= [0.15, characteristics[:assumptions].length * 0.03].min
|
|
431
|
+
|
|
432
|
+
# Fewer logical risks is better
|
|
433
|
+
confidence -= [0.1, characteristics[:logical_risks].length * 0.02].min
|
|
434
|
+
|
|
435
|
+
# Consider previous ethos agreement
|
|
436
|
+
previous_ethos = previous_opinions.find { |op| op[:perspective] == :ethos }
|
|
437
|
+
if previous_ethos && previous_ethos[:confidence] > 0.6
|
|
438
|
+
confidence += 0.05
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
[[confidence, 1.0].min, 0.0].max
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def generate_logos_arguments(characteristics)
|
|
445
|
+
args = []
|
|
446
|
+
|
|
447
|
+
args << "Reasoning follows #{characteristics[:logical_structure]} structure"
|
|
448
|
+
|
|
449
|
+
characteristics[:premises].each do |premise|
|
|
450
|
+
args << "Premise: #{premise}"
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
if characteristics[:assumptions].any?
|
|
454
|
+
args << "Assumptions to verify: #{characteristics[:assumptions].join(', ')}"
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
args
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def identify_logos_concerns(characteristics)
|
|
461
|
+
concerns = []
|
|
462
|
+
|
|
463
|
+
if characteristics[:assumptions].length > 2
|
|
464
|
+
concerns << 'Multiple unverified assumptions in the argument'
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
characteristics[:logical_risks].each do |risk|
|
|
468
|
+
concerns << risk unless risk.include?('appears sound')
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
if characteristics[:premises].any? { |p| p.include?('Implicit') }
|
|
472
|
+
concerns << 'Implicit premises need explicit articulation'
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
concerns.any? ? concerns : ['Logical structure is sound']
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def assess_logical_validity(characteristics)
|
|
479
|
+
validity = 0.7
|
|
480
|
+
|
|
481
|
+
validity -= [0.2, characteristics[:logical_risks].length * 0.05].min
|
|
482
|
+
validity -= [0.1, characteristics[:assumptions].length * 0.02].min
|
|
483
|
+
|
|
484
|
+
[[validity, 0.3].max, 1.0].min
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def generate_logos_suggestions(characteristics)
|
|
488
|
+
suggestions = []
|
|
489
|
+
|
|
490
|
+
characteristics[:assumptions].slice(0, 2).each do |assumption|
|
|
491
|
+
suggestions << "Verify assumption: #{assumption}"
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
if characteristics[:premises].any? { |p| p.include?('Implicit') }
|
|
495
|
+
suggestions << 'Make implicit premises explicit for clarity'
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
suggestions
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
# Helper methods for ethos analysis
|
|
502
|
+
def identify_principles(text)
|
|
503
|
+
principles = []
|
|
504
|
+
|
|
505
|
+
if text.include?('fair') || text.include?('equitable') || text.include?('just')
|
|
506
|
+
principles << 'Fairness and justice'
|
|
507
|
+
end
|
|
508
|
+
if text.include?('honest') || text.include?('transparent') || text.include?('truthful')
|
|
509
|
+
principles << 'Honesty and transparency'
|
|
510
|
+
end
|
|
511
|
+
if text.include?('respect') || text.include?('dignity') || text.include?('worth')
|
|
512
|
+
principles << 'Respect for dignity'
|
|
513
|
+
end
|
|
514
|
+
if text.include?('responsibility') || text.include?('accountable') || text.include?('liable')
|
|
515
|
+
principles << 'Accountability and responsibility'
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
principles.any? ? principles : ['General ethical principles apply']
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def identify_values_at_stake(text)
|
|
522
|
+
values = []
|
|
523
|
+
|
|
524
|
+
if text.include?('privacy') || text.include?('confidential') || text.include?('secret')
|
|
525
|
+
values << 'Privacy rights'
|
|
526
|
+
end
|
|
527
|
+
if text.include?('safety') || text.include?('security') || text.include?('protection')
|
|
528
|
+
values << 'Safety and security'
|
|
529
|
+
end
|
|
530
|
+
if text.include?('freedom') || text.include?('autonomy') || text.include?('choice')
|
|
531
|
+
values << 'Autonomy and freedom'
|
|
532
|
+
end
|
|
533
|
+
if text.include?('equality') || text.include?('equal') || text.include?('discriminat')
|
|
534
|
+
values << 'Equality and non-discrimination'
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
values.any? ? values : ['Standard ethical values']
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def identify_ethical_risks(text)
|
|
541
|
+
risks = []
|
|
542
|
+
|
|
543
|
+
if text.include?('profit') && !text.include?('people')
|
|
544
|
+
risks << 'Potential prioritization of profit over people'
|
|
545
|
+
end
|
|
546
|
+
if text.include?('secret') || text.include?('hidden') || text.include?('undisclosed')
|
|
547
|
+
risks << 'Transparency concerns'
|
|
548
|
+
end
|
|
549
|
+
if text.include?('minority') || text.include?('vulnerable') || text.include?('disadvantaged')
|
|
550
|
+
risks << 'Impact on vulnerable populations needs assessment'
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
risks.any? ? risks : ['No significant ethical risks identified']
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
def generate_ethos_verdict(proposition, characteristics, previous_ethos)
|
|
557
|
+
if previous_ethos
|
|
558
|
+
significant_risks = characteristics[:ethical_risks].none? { |r| r.include?('No significant') }
|
|
559
|
+
return "Upon ethical re-evaluation using #{characteristics[:ethical_framework]} framework, the proposition's alignment with #{characteristics[:principles].join(', ')} #{significant_risks ? 'requires attention to identified risks' : 'remains acceptable'}."
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
"From an ethical perspective informed by #{characteristics[:ethical_framework]} principles, this proposition #{characteristics[:values_at_stake].length > 2 ? 'implicates multiple values' : 'has limited ethical implications'}. The key principles at stake are #{characteristics[:principles].slice(0, 2).join(' and ')}."
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
def calculate_ethos_confidence(characteristics, previous_opinions)
|
|
566
|
+
confidence = 0.6
|
|
567
|
+
|
|
568
|
+
# More principles = clearer ethical framework
|
|
569
|
+
confidence += [0.1, characteristics[:principles].length * 0.02].min
|
|
570
|
+
|
|
571
|
+
# Fewer risks = higher confidence
|
|
572
|
+
if characteristics[:ethical_risks].any? { |r| r.include?('No significant') }
|
|
573
|
+
confidence += 0.1
|
|
574
|
+
else
|
|
575
|
+
confidence -= [0.15, characteristics[:ethical_risks].length * 0.03].min
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
# Consider previous pathos alignment
|
|
579
|
+
previous_pathos = previous_opinions.find { |op| op[:perspective] == :pathos }
|
|
580
|
+
if previous_pathos && previous_pathos[:confidence] > 0.6
|
|
581
|
+
confidence += 0.05
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
[[confidence, 1.0].min, 0.0].max
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
def generate_ethos_arguments(characteristics)
|
|
588
|
+
args = []
|
|
589
|
+
|
|
590
|
+
args << "Ethical framework: #{characteristics[:ethical_framework]}"
|
|
591
|
+
|
|
592
|
+
characteristics[:principles].slice(0, 2).each do |principle|
|
|
593
|
+
args << "Principle invoked: #{principle}"
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
if characteristics[:values_at_stake].any?
|
|
597
|
+
args << "Values at stake: #{characteristics[:values_at_stake].join(', ')}"
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
args
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
def identify_ethos_concerns(characteristics)
|
|
604
|
+
concerns = []
|
|
605
|
+
|
|
606
|
+
characteristics[:ethical_risks].each do |risk|
|
|
607
|
+
concerns << risk unless risk.include?('No significant')
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
if characteristics[:values_at_stake].length > 3
|
|
611
|
+
concerns << 'Multiple values may create ethical tensions'
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
concerns.any? ? concerns : ['Ethical considerations appear manageable']
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
def assess_ethical_alignment(characteristics)
|
|
618
|
+
alignment = 0.7
|
|
619
|
+
|
|
620
|
+
# Reduce for identified risks
|
|
621
|
+
significant_risks = characteristics[:ethical_risks].count { |r| !r.include?('No significant') }
|
|
622
|
+
alignment -= [0.2, significant_risks * 0.05].min
|
|
623
|
+
|
|
624
|
+
[[alignment, 0.3].max, 1.0].min
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def generate_ethos_suggestions(characteristics)
|
|
628
|
+
suggestions = []
|
|
629
|
+
|
|
630
|
+
if characteristics[:ethical_risks].any? { |r| !r.include?('No significant') }
|
|
631
|
+
suggestions << 'Address identified ethical risks before implementation'
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
if characteristics[:values_at_stake].length > 2
|
|
635
|
+
suggestions << 'Consider ethical trade-offs between competing values'
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
suggestions << "Apply #{characteristics[:ethical_framework]} framework consistently"
|
|
639
|
+
|
|
640
|
+
suggestions
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
end
|