lex-trust 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.
- checksums.yaml +7 -0
- data/Gemfile +12 -0
- data/lex-trust.gemspec +30 -0
- data/lib/legion/extensions/trust/actors/decay.rb +41 -0
- data/lib/legion/extensions/trust/client.rb +23 -0
- data/lib/legion/extensions/trust/helpers/trust_map.rb +156 -0
- data/lib/legion/extensions/trust/helpers/trust_model.rb +48 -0
- data/lib/legion/extensions/trust/local_migrations/20260316000020_create_trust_entries.rb +23 -0
- data/lib/legion/extensions/trust/runners/trust.rb +76 -0
- data/lib/legion/extensions/trust/version.rb +9 -0
- data/lib/legion/extensions/trust.rb +21 -0
- data/spec/legion/extensions/trust/actors/decay_spec.rb +62 -0
- data/spec/legion/extensions/trust/client_spec.rb +17 -0
- data/spec/legion/extensions/trust/helpers/trust_map_spec.rb +299 -0
- data/spec/legion/extensions/trust/helpers/trust_model_spec.rb +179 -0
- data/spec/legion/extensions/trust/runners/trust_spec.rb +84 -0
- data/spec/local_persistence_spec.rb +359 -0
- data/spec/spec_helper.rb +20 -0
- metadata +91 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: ee93b725a6f165775e614f7dff64a7fe24d9ed596ca3782b22710df86895e763
|
|
4
|
+
data.tar.gz: bdab508af3b14b60d6821c572bbaaefa6ba59c18f79fd460ab90630319101710
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 34b5000f12abe1eba146fca0bdb2dfd3badf793330e2d488111ceef7f238bd67a0d0f5a216c935e9abd7bb3e4458090c0e3403fad651dac266e094cc2849859b
|
|
7
|
+
data.tar.gz: 6c93059d3e4685de0d9607831104a58ca71ca3bf8aa1e339336ec5cc9133e557b97e2e5351ecb28e06fc93e01f99b2c371f3fc9f5c3ae1863cad36ee433df6e7
|
data/Gemfile
ADDED
data/lex-trust.gemspec
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/trust/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-trust'
|
|
7
|
+
spec.version = Legion::Extensions::Trust::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'LEX Trust'
|
|
12
|
+
spec.description = 'Emergent domain-specific trust modeling for brain-modeled agentic AI'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-trust'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-trust'
|
|
19
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-trust'
|
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-trust'
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-trust/issues'
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
|
+
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
25
|
+
Dir.glob('{lib,spec}/**/*') + %w[lex-trust.gemspec Gemfile]
|
|
26
|
+
end
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
|
+
spec.add_development_dependency 'sequel', '>= 5.70'
|
|
29
|
+
spec.add_development_dependency 'sqlite3', '>= 2.0'
|
|
30
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/actors/every'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Trust
|
|
8
|
+
module Actor
|
|
9
|
+
class Decay < Legion::Extensions::Actors::Every
|
|
10
|
+
def runner_class
|
|
11
|
+
Legion::Extensions::Trust::Runners::Trust
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def runner_function
|
|
15
|
+
'decay_trust'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def time
|
|
19
|
+
300
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def run_now?
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def use_runner?
|
|
27
|
+
false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def check_subtask?
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def generate_task?
|
|
35
|
+
false
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/trust/helpers/trust_model'
|
|
4
|
+
require 'legion/extensions/trust/helpers/trust_map'
|
|
5
|
+
require 'legion/extensions/trust/runners/trust'
|
|
6
|
+
|
|
7
|
+
module Legion
|
|
8
|
+
module Extensions
|
|
9
|
+
module Trust
|
|
10
|
+
class Client
|
|
11
|
+
include Runners::Trust
|
|
12
|
+
|
|
13
|
+
def initialize(**)
|
|
14
|
+
@trust_map = Helpers::TrustMap.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
attr_reader :trust_map
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Trust
|
|
6
|
+
module Helpers
|
|
7
|
+
class TrustMap
|
|
8
|
+
attr_reader :entries
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@entries = {} # key: "agent_id:domain"
|
|
12
|
+
load_from_local
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get(agent_id, domain: :general)
|
|
16
|
+
@entries[key(agent_id, domain)]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get_or_create(agent_id, domain: :general)
|
|
20
|
+
@entries[key(agent_id, domain)] ||= TrustModel.new_trust_entry(agent_id: agent_id, domain: domain)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def record_interaction(agent_id, positive:, domain: :general)
|
|
24
|
+
entry = get_or_create(agent_id, domain: domain)
|
|
25
|
+
entry[:interaction_count] += 1
|
|
26
|
+
entry[:last_interaction] = Time.now.utc
|
|
27
|
+
|
|
28
|
+
if positive
|
|
29
|
+
entry[:positive_count] += 1
|
|
30
|
+
TrustModel::TRUST_DIMENSIONS.each do |dim|
|
|
31
|
+
entry[:dimensions][dim] = TrustModel.clamp(entry[:dimensions][dim] + TrustModel::TRUST_REINFORCEMENT)
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
entry[:negative_count] += 1
|
|
35
|
+
TrustModel::TRUST_DIMENSIONS.each do |dim|
|
|
36
|
+
entry[:dimensions][dim] = TrustModel.clamp(entry[:dimensions][dim] - TrustModel::TRUST_PENALTY)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
entry[:composite] = TrustModel.composite_score(entry[:dimensions])
|
|
41
|
+
entry
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def reinforce_dimension(agent_id, dimension:, domain: :general, amount: TrustModel::TRUST_REINFORCEMENT)
|
|
45
|
+
entry = get_or_create(agent_id, domain: domain)
|
|
46
|
+
return unless TrustModel::TRUST_DIMENSIONS.include?(dimension)
|
|
47
|
+
|
|
48
|
+
entry[:dimensions][dimension] = TrustModel.clamp(entry[:dimensions][dimension] + amount)
|
|
49
|
+
entry[:composite] = TrustModel.composite_score(entry[:dimensions])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def decay_all
|
|
53
|
+
decayed = 0
|
|
54
|
+
@entries.each_value do |entry|
|
|
55
|
+
TrustModel::TRUST_DIMENSIONS.each do |dim|
|
|
56
|
+
old = entry[:dimensions][dim]
|
|
57
|
+
entry[:dimensions][dim] = TrustModel.clamp(old - TrustModel::TRUST_DECAY_RATE)
|
|
58
|
+
end
|
|
59
|
+
entry[:composite] = TrustModel.composite_score(entry[:dimensions])
|
|
60
|
+
decayed += 1
|
|
61
|
+
end
|
|
62
|
+
decayed
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def trusted_agents(domain: :general, min_trust: TrustModel::TRUST_CONSIDER_THRESHOLD)
|
|
66
|
+
@entries.values
|
|
67
|
+
.select { |e| e[:domain] == domain && e[:composite] >= min_trust }
|
|
68
|
+
.sort_by { |e| -e[:composite] }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def delegatable_agents(domain: :general)
|
|
72
|
+
trusted_agents(domain: domain, min_trust: TrustModel::TRUST_DELEGATE_THRESHOLD)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def count
|
|
76
|
+
@entries.size
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def save_to_local
|
|
80
|
+
return unless defined?(Legion::Data::Local) && Legion::Data::Local.connected?
|
|
81
|
+
|
|
82
|
+
dataset = Legion::Data::Local.connection[:trust_entries]
|
|
83
|
+
|
|
84
|
+
@entries.each_value do |entry|
|
|
85
|
+
row = {
|
|
86
|
+
agent_id: entry[:agent_id].to_s,
|
|
87
|
+
domain: entry[:domain].to_s,
|
|
88
|
+
reliability: entry[:dimensions][:reliability],
|
|
89
|
+
competence: entry[:dimensions][:competence],
|
|
90
|
+
integrity: entry[:dimensions][:integrity],
|
|
91
|
+
benevolence: entry[:dimensions][:benevolence],
|
|
92
|
+
composite: entry[:composite],
|
|
93
|
+
interaction_count: entry[:interaction_count],
|
|
94
|
+
positive_count: entry[:positive_count],
|
|
95
|
+
negative_count: entry[:negative_count],
|
|
96
|
+
last_interaction: entry[:last_interaction],
|
|
97
|
+
created_at: entry[:created_at]
|
|
98
|
+
}
|
|
99
|
+
existing = dataset.where(agent_id: row[:agent_id], domain: row[:domain]).first
|
|
100
|
+
if existing
|
|
101
|
+
dataset.where(agent_id: row[:agent_id], domain: row[:domain])
|
|
102
|
+
.update(row.except(:agent_id, :domain))
|
|
103
|
+
else
|
|
104
|
+
dataset.insert(row)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Remove DB rows for entries no longer in memory
|
|
109
|
+
memory_pairs = @entries.values.map { |e| [e[:agent_id].to_s, e[:domain].to_s] }
|
|
110
|
+
dataset.each do |row|
|
|
111
|
+
pair = [row[:agent_id], row[:domain]]
|
|
112
|
+
dataset.where(agent_id: pair[0], domain: pair[1]).delete unless memory_pairs.include?(pair)
|
|
113
|
+
end
|
|
114
|
+
rescue StandardError => e
|
|
115
|
+
Legion::Logging.warn "[trust] save_to_local failed: #{e.message}" if defined?(Legion::Logging)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def load_from_local
|
|
119
|
+
return unless defined?(Legion::Data::Local) && Legion::Data::Local.connected?
|
|
120
|
+
|
|
121
|
+
Legion::Data::Local.connection[:trust_entries].each do |row|
|
|
122
|
+
agent_id = row[:agent_id]
|
|
123
|
+
domain_str = row[:domain]
|
|
124
|
+
domain_val = domain_str.to_sym
|
|
125
|
+
entry_key = "#{agent_id}:#{domain_str}"
|
|
126
|
+
@entries[entry_key] = {
|
|
127
|
+
agent_id: agent_id,
|
|
128
|
+
domain: domain_val,
|
|
129
|
+
dimensions: {
|
|
130
|
+
reliability: row[:reliability].to_f,
|
|
131
|
+
competence: row[:competence].to_f,
|
|
132
|
+
integrity: row[:integrity].to_f,
|
|
133
|
+
benevolence: row[:benevolence].to_f
|
|
134
|
+
},
|
|
135
|
+
composite: row[:composite].to_f,
|
|
136
|
+
interaction_count: row[:interaction_count].to_i,
|
|
137
|
+
positive_count: row[:positive_count].to_i,
|
|
138
|
+
negative_count: row[:negative_count].to_i,
|
|
139
|
+
last_interaction: row[:last_interaction],
|
|
140
|
+
created_at: row[:created_at]
|
|
141
|
+
}
|
|
142
|
+
end
|
|
143
|
+
rescue StandardError => e
|
|
144
|
+
Legion::Logging.warn "[trust] load_from_local failed: #{e.message}" if defined?(Legion::Logging)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
|
|
149
|
+
def key(agent_id, domain)
|
|
150
|
+
"#{agent_id}:#{domain}"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Trust
|
|
6
|
+
module Helpers
|
|
7
|
+
module TrustModel
|
|
8
|
+
# Trust is emergent, multidimensional, domain-specific (spec design-decisions-v5 #4)
|
|
9
|
+
TRUST_DIMENSIONS = %i[reliability competence integrity benevolence].freeze
|
|
10
|
+
|
|
11
|
+
# Thresholds
|
|
12
|
+
TRUST_CONSIDER_THRESHOLD = 0.3 # minimum trust to consider agent's input
|
|
13
|
+
TRUST_DELEGATE_THRESHOLD = 0.7 # minimum trust to delegate actions
|
|
14
|
+
TRUST_DECAY_RATE = 0.005 # per-cycle decay
|
|
15
|
+
TRUST_REINFORCEMENT = 0.05 # per positive interaction
|
|
16
|
+
TRUST_PENALTY = 0.15 # per negative interaction (asymmetric)
|
|
17
|
+
NEUTRAL_TRUST = 0.3 # starting trust for new agents
|
|
18
|
+
|
|
19
|
+
module_function
|
|
20
|
+
|
|
21
|
+
def new_trust_entry(agent_id:, domain: :general)
|
|
22
|
+
{
|
|
23
|
+
agent_id: agent_id,
|
|
24
|
+
domain: domain,
|
|
25
|
+
dimensions: TRUST_DIMENSIONS.to_h { |d| [d, NEUTRAL_TRUST] },
|
|
26
|
+
composite: NEUTRAL_TRUST,
|
|
27
|
+
interaction_count: 0,
|
|
28
|
+
positive_count: 0,
|
|
29
|
+
negative_count: 0,
|
|
30
|
+
last_interaction: nil,
|
|
31
|
+
created_at: Time.now.utc
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def composite_score(dimensions)
|
|
36
|
+
return 0.0 if dimensions.empty?
|
|
37
|
+
|
|
38
|
+
dimensions.values.sum / dimensions.size
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def clamp(value, min = 0.0, max = 1.0)
|
|
42
|
+
value.clamp(min, max)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:trust_entries) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :agent_id, null: false
|
|
8
|
+
String :domain, null: false
|
|
9
|
+
Float :reliability, default: 0.3
|
|
10
|
+
Float :competence, default: 0.3
|
|
11
|
+
Float :integrity, default: 0.3
|
|
12
|
+
Float :benevolence, default: 0.3
|
|
13
|
+
Float :composite, default: 0.3
|
|
14
|
+
Integer :interaction_count, default: 0
|
|
15
|
+
Integer :positive_count, default: 0
|
|
16
|
+
Integer :negative_count, default: 0
|
|
17
|
+
DateTime :last_interaction
|
|
18
|
+
DateTime :created_at, null: false
|
|
19
|
+
unique %i[agent_id domain]
|
|
20
|
+
index [:agent_id]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Trust
|
|
6
|
+
module Runners
|
|
7
|
+
module Trust
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
9
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
|
|
11
|
+
def get_trust(agent_id:, domain: :general, **)
|
|
12
|
+
entry = trust_map.get(agent_id, domain: domain)
|
|
13
|
+
if entry
|
|
14
|
+
Legion::Logging.debug "[trust] get agent=#{agent_id} domain=#{domain} composite=#{entry[:composite].round(2)}"
|
|
15
|
+
{ found: true, trust: entry }
|
|
16
|
+
else
|
|
17
|
+
Legion::Logging.debug "[trust] get agent=#{agent_id} domain=#{domain} not found"
|
|
18
|
+
{ found: false, agent_id: agent_id, domain: domain }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def record_trust_interaction(agent_id:, positive:, domain: :general, **)
|
|
23
|
+
entry = trust_map.record_interaction(agent_id, domain: domain, positive: positive)
|
|
24
|
+
msg = "[trust] interaction: agent=#{agent_id} domain=#{domain} positive=#{positive} " \
|
|
25
|
+
"composite=#{entry[:composite].round(2)} total=#{entry[:interaction_count]}"
|
|
26
|
+
Legion::Logging.info msg
|
|
27
|
+
{
|
|
28
|
+
agent_id: agent_id,
|
|
29
|
+
domain: domain,
|
|
30
|
+
positive: positive,
|
|
31
|
+
composite: entry[:composite],
|
|
32
|
+
interactions: entry[:interaction_count]
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def reinforce_trust_dimension(agent_id:, dimension:, domain: :general, amount: nil, **)
|
|
37
|
+
amt = amount || Helpers::TrustModel::TRUST_REINFORCEMENT
|
|
38
|
+
trust_map.reinforce_dimension(agent_id, domain: domain, dimension: dimension, amount: amt)
|
|
39
|
+
entry = trust_map.get(agent_id, domain: domain)
|
|
40
|
+
Legion::Logging.debug "[trust] reinforce: agent=#{agent_id} dimension=#{dimension} amount=#{amt} composite=#{entry[:composite].round(2)}"
|
|
41
|
+
{ agent_id: agent_id, domain: domain, dimension: dimension, composite: entry[:composite] }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def decay_trust(**)
|
|
45
|
+
decayed = trust_map.decay_all
|
|
46
|
+
Legion::Logging.debug "[trust] decay cycle: entries_updated=#{decayed}"
|
|
47
|
+
{ decayed: decayed }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def trusted_agents(domain: :general, min_trust: nil, **)
|
|
51
|
+
min = min_trust || Helpers::TrustModel::TRUST_CONSIDER_THRESHOLD
|
|
52
|
+
agents = trust_map.trusted_agents(domain: domain, min_trust: min)
|
|
53
|
+
Legion::Logging.debug "[trust] trusted agents: domain=#{domain} min=#{min} count=#{agents.size}"
|
|
54
|
+
{ agents: agents, count: agents.size }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def delegatable_agents(domain: :general, **)
|
|
58
|
+
agents = trust_map.delegatable_agents(domain: domain)
|
|
59
|
+
Legion::Logging.debug "[trust] delegatable agents: domain=#{domain} count=#{agents.size}"
|
|
60
|
+
{ agents: agents, count: agents.size }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def trust_status(**)
|
|
64
|
+
{ total_entries: trust_map.count }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def trust_map
|
|
70
|
+
@trust_map ||= Helpers::TrustMap.new
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/trust/version'
|
|
4
|
+
require 'legion/extensions/trust/helpers/trust_model'
|
|
5
|
+
require 'legion/extensions/trust/helpers/trust_map'
|
|
6
|
+
require 'legion/extensions/trust/runners/trust'
|
|
7
|
+
|
|
8
|
+
module Legion
|
|
9
|
+
module Extensions
|
|
10
|
+
module Trust
|
|
11
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if defined?(Legion::Data::Local)
|
|
17
|
+
Legion::Data::Local.register_migrations(
|
|
18
|
+
name: :trust,
|
|
19
|
+
path: File.join(__dir__, 'trust', 'local_migrations')
|
|
20
|
+
)
|
|
21
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Stub the framework actor base class since legionio gem is not available in test
|
|
4
|
+
module Legion
|
|
5
|
+
module Extensions
|
|
6
|
+
module Actors
|
|
7
|
+
class Every # rubocop:disable Lint/EmptyClass
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Intercept the require in the actor file so it doesn't fail
|
|
14
|
+
$LOADED_FEATURES << 'legion/extensions/actors/every'
|
|
15
|
+
|
|
16
|
+
require 'legion/extensions/trust/actors/decay'
|
|
17
|
+
|
|
18
|
+
RSpec.describe Legion::Extensions::Trust::Actor::Decay do
|
|
19
|
+
subject(:actor) { described_class.new }
|
|
20
|
+
|
|
21
|
+
describe '#runner_class' do
|
|
22
|
+
it 'returns the Trust module' do
|
|
23
|
+
expect(actor.runner_class).to eq(Legion::Extensions::Trust::Runners::Trust)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#runner_function' do
|
|
28
|
+
it 'returns decay_trust' do
|
|
29
|
+
expect(actor.runner_function).to eq('decay_trust')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe '#time' do
|
|
34
|
+
it 'returns 300 seconds' do
|
|
35
|
+
expect(actor.time).to eq(300)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe '#run_now?' do
|
|
40
|
+
it 'returns false' do
|
|
41
|
+
expect(actor.run_now?).to be false
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '#use_runner?' do
|
|
46
|
+
it 'returns false' do
|
|
47
|
+
expect(actor.use_runner?).to be false
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#check_subtask?' do
|
|
52
|
+
it 'returns false' do
|
|
53
|
+
expect(actor.check_subtask?).to be false
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#generate_task?' do
|
|
58
|
+
it 'returns false' do
|
|
59
|
+
expect(actor.generate_task?).to be false
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/trust/client'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Legion::Extensions::Trust::Client do
|
|
6
|
+
let(:client) { described_class.new }
|
|
7
|
+
|
|
8
|
+
it 'responds to trust runner methods' do
|
|
9
|
+
expect(client).to respond_to(:get_trust)
|
|
10
|
+
expect(client).to respond_to(:record_trust_interaction)
|
|
11
|
+
expect(client).to respond_to(:reinforce_trust_dimension)
|
|
12
|
+
expect(client).to respond_to(:decay_trust)
|
|
13
|
+
expect(client).to respond_to(:trusted_agents)
|
|
14
|
+
expect(client).to respond_to(:delegatable_agents)
|
|
15
|
+
expect(client).to respond_to(:trust_status)
|
|
16
|
+
end
|
|
17
|
+
end
|