lex-schema 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/lib/legion/extensions/schema/client.rb +22 -0
- data/lib/legion/extensions/schema/helpers/causal_relation.rb +66 -0
- data/lib/legion/extensions/schema/helpers/constants.rb +46 -0
- data/lib/legion/extensions/schema/helpers/world_model.rb +169 -0
- data/lib/legion/extensions/schema/runners/schema.rb +97 -0
- data/lib/legion/extensions/schema/version.rb +9 -0
- data/lib/legion/extensions/schema.rb +16 -0
- metadata +63 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 610c292616da34f0d31990db52cd23f1f6144003742f28c5fa10482fbbe8f490
|
|
4
|
+
data.tar.gz: d0d06626d42e4b37bf60ffb78284c4a8cbd04fb5f59bfe1ea2e3835de2b203d9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c4f0d6677c40e2ef05393c4c122bf5072d20115a442275ebd145f857165cf43099383697c942205662bed81afa110e4bbbf02f8ad6441fb3cf0e6b51d623f1e9
|
|
7
|
+
data.tar.gz: ce3fa23aa8352a05e629c9bd045ca24e859e40c62c8a952f522dae0439b985575ebd85980e39823a77acd2643c76342bcf521b7327c4044999a42b4c694e9f1f
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/schema/helpers/constants'
|
|
4
|
+
require 'legion/extensions/schema/helpers/causal_relation'
|
|
5
|
+
require 'legion/extensions/schema/helpers/world_model'
|
|
6
|
+
require 'legion/extensions/schema/runners/schema'
|
|
7
|
+
|
|
8
|
+
module Legion
|
|
9
|
+
module Extensions
|
|
10
|
+
module Schema
|
|
11
|
+
class Client
|
|
12
|
+
include Runners::Schema
|
|
13
|
+
|
|
14
|
+
attr_reader :world_model
|
|
15
|
+
|
|
16
|
+
def initialize(world_model: nil, **)
|
|
17
|
+
@world_model = world_model || Helpers::WorldModel.new
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Schema
|
|
8
|
+
module Helpers
|
|
9
|
+
class CausalRelation
|
|
10
|
+
attr_reader :id, :cause, :effect, :relation_type, :confidence,
|
|
11
|
+
:evidence_count, :created_at, :updated_at
|
|
12
|
+
|
|
13
|
+
def initialize(cause:, effect:, relation_type:, confidence: 0.5)
|
|
14
|
+
@id = SecureRandom.uuid
|
|
15
|
+
@cause = cause
|
|
16
|
+
@effect = effect
|
|
17
|
+
@relation_type = relation_type
|
|
18
|
+
@confidence = confidence.clamp(0.0, 1.0)
|
|
19
|
+
@evidence_count = 1
|
|
20
|
+
@created_at = Time.now.utc
|
|
21
|
+
@updated_at = Time.now.utc
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def reinforce(amount = Constants::REINFORCEMENT_BONUS)
|
|
25
|
+
@confidence = [@confidence + amount, 1.0].min
|
|
26
|
+
@evidence_count += 1
|
|
27
|
+
@updated_at = Time.now.utc
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def weaken(amount = Constants::CONTRADICTION_PENALTY)
|
|
31
|
+
@confidence = [@confidence - amount, 0.0].max
|
|
32
|
+
@updated_at = Time.now.utc
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def decay
|
|
36
|
+
@confidence = [@confidence - Constants::DECAY_RATE, 0.0].max
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def established?
|
|
40
|
+
@confidence >= Constants::CONFIDENCE_LEVELS[:established]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def speculative?
|
|
44
|
+
@confidence <= Constants::CONFIDENCE_LEVELS[:speculative]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def prunable?
|
|
48
|
+
@confidence < Constants::PRUNE_THRESHOLD
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def to_h
|
|
52
|
+
{
|
|
53
|
+
id: @id,
|
|
54
|
+
cause: @cause,
|
|
55
|
+
effect: @effect,
|
|
56
|
+
relation_type: @relation_type,
|
|
57
|
+
confidence: @confidence.round(4),
|
|
58
|
+
evidence_count: @evidence_count,
|
|
59
|
+
established: established?
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Schema
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
RELATION_TYPES = %i[
|
|
9
|
+
causes
|
|
10
|
+
prevents
|
|
11
|
+
enables
|
|
12
|
+
requires
|
|
13
|
+
correlates
|
|
14
|
+
contradicts
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
CONFIDENCE_LEVELS = {
|
|
18
|
+
established: 0.9,
|
|
19
|
+
strong: 0.7,
|
|
20
|
+
moderate: 0.5,
|
|
21
|
+
weak: 0.3,
|
|
22
|
+
speculative: 0.1
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
SCHEMA_ALPHA = 0.12
|
|
26
|
+
|
|
27
|
+
MAX_SCHEMAS = 500
|
|
28
|
+
|
|
29
|
+
MAX_RELATIONS_PER_SCHEMA = 50
|
|
30
|
+
|
|
31
|
+
REINFORCEMENT_BONUS = 0.05
|
|
32
|
+
|
|
33
|
+
CONTRADICTION_PENALTY = 0.15
|
|
34
|
+
|
|
35
|
+
DECAY_RATE = 0.005
|
|
36
|
+
|
|
37
|
+
PRUNE_THRESHOLD = 0.1
|
|
38
|
+
|
|
39
|
+
MAX_COUNTERFACTUAL_DEPTH = 5
|
|
40
|
+
|
|
41
|
+
MAX_EXPLANATION_CHAIN = 10
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Schema
|
|
6
|
+
module Helpers
|
|
7
|
+
class WorldModel
|
|
8
|
+
attr_reader :relations, :domains
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@relations = {}
|
|
12
|
+
@domains = Hash.new { |h, k| h[k] = [] }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def add_relation(cause:, effect:, relation_type:, confidence: 0.5)
|
|
16
|
+
return nil unless Constants::RELATION_TYPES.include?(relation_type)
|
|
17
|
+
|
|
18
|
+
key = relation_key(cause, effect, relation_type)
|
|
19
|
+
if @relations.key?(key)
|
|
20
|
+
@relations[key].reinforce
|
|
21
|
+
else
|
|
22
|
+
@relations[key] = CausalRelation.new(cause: cause, effect: effect, relation_type: relation_type, confidence: confidence)
|
|
23
|
+
index_domains(cause, effect, key)
|
|
24
|
+
trim_relations
|
|
25
|
+
end
|
|
26
|
+
@relations[key]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def weaken_relation(cause:, effect:, relation_type:)
|
|
30
|
+
key = relation_key(cause, effect, relation_type)
|
|
31
|
+
relation = @relations[key]
|
|
32
|
+
return nil unless relation
|
|
33
|
+
|
|
34
|
+
relation.weaken
|
|
35
|
+
prune_if_needed(key)
|
|
36
|
+
relation
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def find_effects(cause)
|
|
40
|
+
keys = @domains[cause] || []
|
|
41
|
+
keys.filter_map { |k| @relations[k] }.select { |r| r.cause == cause }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def find_causes(effect)
|
|
45
|
+
keys = @domains[effect] || []
|
|
46
|
+
keys.filter_map { |k| @relations[k] }.select { |r| r.effect == effect }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def explain(outcome, max_depth: Constants::MAX_EXPLANATION_CHAIN)
|
|
50
|
+
chain = []
|
|
51
|
+
visited = Set.new
|
|
52
|
+
build_explanation_chain(outcome, chain, visited, max_depth)
|
|
53
|
+
chain
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def counterfactual(cause, max_depth: Constants::MAX_COUNTERFACTUAL_DEPTH)
|
|
57
|
+
affected = []
|
|
58
|
+
visited = Set.new
|
|
59
|
+
propagate_counterfactual(cause, affected, visited, max_depth)
|
|
60
|
+
affected
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def contradictions
|
|
64
|
+
@relations.values.each_with_object([]) do |rel, result|
|
|
65
|
+
next unless rel.relation_type == :causes
|
|
66
|
+
|
|
67
|
+
opposite = @relations[relation_key(rel.cause, rel.effect, :prevents)]
|
|
68
|
+
next unless opposite
|
|
69
|
+
|
|
70
|
+
result << {
|
|
71
|
+
cause: rel.cause,
|
|
72
|
+
effect: rel.effect,
|
|
73
|
+
causes_confidence: rel.confidence.round(4),
|
|
74
|
+
prevents_confidence: opposite.confidence.round(4)
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def decay_all
|
|
80
|
+
@relations.each_value(&:decay)
|
|
81
|
+
prune_weak
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def relation_count
|
|
85
|
+
@relations.size
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def domain_count
|
|
89
|
+
all_entities = @relations.values.flat_map { |r| [r.cause, r.effect] }
|
|
90
|
+
all_entities.uniq.size
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def established_relations
|
|
94
|
+
@relations.values.select(&:established?)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def to_h
|
|
98
|
+
{
|
|
99
|
+
relation_count: relation_count,
|
|
100
|
+
domain_count: domain_count,
|
|
101
|
+
established_count: established_relations.size,
|
|
102
|
+
contradiction_count: contradictions.size
|
|
103
|
+
}
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def relation_key(cause, effect, relation_type)
|
|
109
|
+
"#{cause}->#{relation_type}->#{effect}"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def index_domains(cause, effect, key)
|
|
113
|
+
@domains[cause] << key
|
|
114
|
+
@domains[effect] << key
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def build_explanation_chain(outcome, chain, visited, depth)
|
|
118
|
+
return if depth <= 0 || visited.include?(outcome)
|
|
119
|
+
|
|
120
|
+
visited.add(outcome)
|
|
121
|
+
causes = find_causes(outcome).sort_by { |r| -r.confidence }
|
|
122
|
+
causes.first(3).each do |rel|
|
|
123
|
+
chain << rel.to_h
|
|
124
|
+
build_explanation_chain(rel.cause, chain, visited, depth - 1)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def propagate_counterfactual(cause, affected, visited, depth)
|
|
129
|
+
return if depth <= 0 || visited.include?(cause)
|
|
130
|
+
|
|
131
|
+
visited.add(cause)
|
|
132
|
+
effects = find_effects(cause).sort_by { |r| -r.confidence }
|
|
133
|
+
effects.each do |rel|
|
|
134
|
+
affected << { effect: rel.effect, relation: rel.relation_type, confidence: rel.confidence.round(4) }
|
|
135
|
+
propagate_counterfactual(rel.effect, affected, visited, depth - 1)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def prune_if_needed(key)
|
|
140
|
+
relation = @relations[key]
|
|
141
|
+
return unless relation&.prunable?
|
|
142
|
+
|
|
143
|
+
remove_relation(key)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def prune_weak
|
|
147
|
+
prunable = @relations.select { |_, r| r.prunable? }.keys
|
|
148
|
+
prunable.each { |key| remove_relation(key) }
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def remove_relation(key)
|
|
152
|
+
rel = @relations.delete(key)
|
|
153
|
+
return unless rel
|
|
154
|
+
|
|
155
|
+
@domains[rel.cause]&.delete(key)
|
|
156
|
+
@domains[rel.effect]&.delete(key)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def trim_relations
|
|
160
|
+
return if @relations.size <= Constants::MAX_SCHEMAS
|
|
161
|
+
|
|
162
|
+
weakest = @relations.sort_by { |_, r| r.confidence }
|
|
163
|
+
weakest.first(@relations.size - Constants::MAX_SCHEMAS).each { |k, _| remove_relation(k) } # rubocop:disable Style/HashEachMethods
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Schema
|
|
6
|
+
module Runners
|
|
7
|
+
module Schema
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
9
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
|
|
11
|
+
def update_schema(tick_results: {}, **)
|
|
12
|
+
extract_prediction_outcomes(tick_results)
|
|
13
|
+
world_model.decay_all
|
|
14
|
+
|
|
15
|
+
Legion::Logging.debug "[schema] relations=#{world_model.relation_count} " \
|
|
16
|
+
"domains=#{world_model.domain_count} established=#{world_model.established_relations.size}"
|
|
17
|
+
|
|
18
|
+
world_model.to_h
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def learn_relation(cause:, effect:, relation_type:, confidence: 0.5, **)
|
|
22
|
+
relation_sym = relation_type.to_sym
|
|
23
|
+
result = world_model.add_relation(cause: cause, effect: effect, relation_type: relation_sym, confidence: confidence)
|
|
24
|
+
return { success: false, error: 'invalid relation type' } unless result
|
|
25
|
+
|
|
26
|
+
Legion::Logging.info "[schema] learned: #{cause} #{relation_sym} #{effect} (#{result.confidence.round(2)})"
|
|
27
|
+
{ success: true, relation: result.to_h }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def weaken_relation(cause:, effect:, relation_type:, **)
|
|
31
|
+
result = world_model.weaken_relation(cause: cause, effect: effect, relation_type: relation_type.to_sym)
|
|
32
|
+
return { success: false, error: 'relation not found' } unless result
|
|
33
|
+
|
|
34
|
+
Legion::Logging.debug "[schema] weakened: #{cause} #{relation_type} #{effect}"
|
|
35
|
+
{ success: true, relation: result.to_h }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def explain(outcome:, **)
|
|
39
|
+
chain = world_model.explain(outcome)
|
|
40
|
+
Legion::Logging.debug "[schema] explanation for #{outcome}: #{chain.size} links"
|
|
41
|
+
{ outcome: outcome, chain: chain, depth: chain.size }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def counterfactual(cause:, **)
|
|
45
|
+
affected = world_model.counterfactual(cause)
|
|
46
|
+
Legion::Logging.debug "[schema] counterfactual for #{cause}: #{affected.size} effects"
|
|
47
|
+
{ cause: cause, affected: affected, impact: affected.size }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def find_effects(cause:, **)
|
|
51
|
+
effects = world_model.find_effects(cause).map(&:to_h)
|
|
52
|
+
{ cause: cause, effects: effects, count: effects.size }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def find_causes(effect:, **)
|
|
56
|
+
causes = world_model.find_causes(effect).map(&:to_h)
|
|
57
|
+
{ effect: effect, causes: causes, count: causes.size }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def contradictions(**)
|
|
61
|
+
result = world_model.contradictions
|
|
62
|
+
Legion::Logging.debug "[schema] contradictions: #{result.size}"
|
|
63
|
+
{ contradictions: result, count: result.size }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def schema_stats(**)
|
|
67
|
+
Legion::Logging.debug '[schema] stats'
|
|
68
|
+
world_model.to_h.merge(
|
|
69
|
+
top_relations: world_model.established_relations.first(10).map(&:to_h)
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def world_model
|
|
76
|
+
@world_model ||= Helpers::WorldModel.new
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def extract_prediction_outcomes(tick_results)
|
|
80
|
+
predictions = tick_results.dig(:prediction_engine, :resolved)
|
|
81
|
+
return unless predictions.is_a?(Array)
|
|
82
|
+
|
|
83
|
+
predictions.each do |pred|
|
|
84
|
+
next unless pred[:domain] && pred[:outcome_domain]
|
|
85
|
+
|
|
86
|
+
if pred[:accurate]
|
|
87
|
+
world_model.add_relation(cause: pred[:domain], effect: pred[:outcome_domain], relation_type: :causes, confidence: 0.6)
|
|
88
|
+
else
|
|
89
|
+
world_model.weaken_relation(cause: pred[:domain], effect: pred[:outcome_domain], relation_type: :causes)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/schema/version'
|
|
4
|
+
require 'legion/extensions/schema/helpers/constants'
|
|
5
|
+
require 'legion/extensions/schema/helpers/causal_relation'
|
|
6
|
+
require 'legion/extensions/schema/helpers/world_model'
|
|
7
|
+
require 'legion/extensions/schema/runners/schema'
|
|
8
|
+
require 'legion/extensions/schema/client'
|
|
9
|
+
|
|
10
|
+
module Legion
|
|
11
|
+
module Extensions
|
|
12
|
+
module Schema
|
|
13
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined?(:Core)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-schema
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Matthew Iverson
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: legion-gaia
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: Builds and maintains causal schemas — structured models of how things
|
|
27
|
+
work, enabling explanation and counterfactual reasoning
|
|
28
|
+
email:
|
|
29
|
+
- matt@legionIO.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- lib/legion/extensions/schema.rb
|
|
35
|
+
- lib/legion/extensions/schema/client.rb
|
|
36
|
+
- lib/legion/extensions/schema/helpers/causal_relation.rb
|
|
37
|
+
- lib/legion/extensions/schema/helpers/constants.rb
|
|
38
|
+
- lib/legion/extensions/schema/helpers/world_model.rb
|
|
39
|
+
- lib/legion/extensions/schema/runners/schema.rb
|
|
40
|
+
- lib/legion/extensions/schema/version.rb
|
|
41
|
+
homepage: https://github.com/LegionIO/lex-schema
|
|
42
|
+
licenses:
|
|
43
|
+
- MIT
|
|
44
|
+
metadata:
|
|
45
|
+
rubygems_mfa_required: 'true'
|
|
46
|
+
rdoc_options: []
|
|
47
|
+
require_paths:
|
|
48
|
+
- lib
|
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.4'
|
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '0'
|
|
59
|
+
requirements: []
|
|
60
|
+
rubygems_version: 3.6.9
|
|
61
|
+
specification_version: 4
|
|
62
|
+
summary: Internal world model and causal reasoning for LegionIO cognitive agents
|
|
63
|
+
test_files: []
|