lex-cognitive-map 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 +11 -0
- data/lex-cognitive-map.gemspec +29 -0
- data/lib/legion/extensions/cognitive_map/actors/decay.rb +41 -0
- data/lib/legion/extensions/cognitive_map/client.rb +25 -0
- data/lib/legion/extensions/cognitive_map/helpers/cognitive_map_store.rb +175 -0
- data/lib/legion/extensions/cognitive_map/helpers/constants.rb +67 -0
- data/lib/legion/extensions/cognitive_map/helpers/graph_traversal.rb +120 -0
- data/lib/legion/extensions/cognitive_map/helpers/location.rb +67 -0
- data/lib/legion/extensions/cognitive_map/runners/cognitive_map.rb +91 -0
- data/lib/legion/extensions/cognitive_map/version.rb +9 -0
- data/lib/legion/extensions/cognitive_map.rb +16 -0
- data/spec/legion/extensions/cognitive_map/client_spec.rb +89 -0
- data/spec/legion/extensions/cognitive_map/helpers/cognitive_map_store_spec.rb +321 -0
- data/spec/legion/extensions/cognitive_map/helpers/location_spec.rb +165 -0
- data/spec/legion/extensions/cognitive_map/runners/cognitive_map_spec.rb +190 -0
- data/spec/spec_helper.rb +20 -0
- metadata +77 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/cognitive_map/client'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Legion::Extensions::CognitiveMap::Runners::CognitiveMap do
|
|
6
|
+
let(:client) { Legion::Extensions::CognitiveMap::Client.new }
|
|
7
|
+
|
|
8
|
+
def setup_two_locations
|
|
9
|
+
client.add_location(id: 'a', domain: :test)
|
|
10
|
+
client.add_location(id: 'b', domain: :test)
|
|
11
|
+
client.connect_locations(from: 'a', to: 'b', distance: 1.0)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '#add_location' do
|
|
15
|
+
it 'returns success: true for new location' do
|
|
16
|
+
result = client.add_location(id: 'concept:ruby')
|
|
17
|
+
expect(result[:success]).to be true
|
|
18
|
+
expect(result[:id]).to eq('concept:ruby')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns success: true for duplicate (idempotent)' do
|
|
22
|
+
client.add_location(id: 'concept:ruby')
|
|
23
|
+
result = client.add_location(id: 'concept:ruby')
|
|
24
|
+
expect(result[:success]).to be true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'passes domain through' do
|
|
28
|
+
result = client.add_location(id: 'loc1', domain: :science)
|
|
29
|
+
expect(result[:domain]).to eq(:science)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe '#connect_locations' do
|
|
34
|
+
before { setup_two_locations }
|
|
35
|
+
|
|
36
|
+
it 'returns success: true' do
|
|
37
|
+
client.add_location(id: 'c')
|
|
38
|
+
result = client.connect_locations(from: 'a', to: 'c')
|
|
39
|
+
expect(result[:success]).to be true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'returns success: false for missing location' do
|
|
43
|
+
result = client.connect_locations(from: 'a', to: 'ghost')
|
|
44
|
+
expect(result[:success]).to be false
|
|
45
|
+
expect(result[:reason]).to eq(:missing_location)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'passes distance through' do
|
|
49
|
+
client.add_location(id: 'c')
|
|
50
|
+
result = client.connect_locations(from: 'a', to: 'c', distance: 2.5)
|
|
51
|
+
expect(result[:distance]).to eq(2.5)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe '#visit_location' do
|
|
56
|
+
it 'returns success: true for existing location' do
|
|
57
|
+
client.add_location(id: 'loc1')
|
|
58
|
+
result = client.visit_location(id: 'loc1')
|
|
59
|
+
expect(result[:success]).to be true
|
|
60
|
+
expect(result[:visit_count]).to eq(1)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'returns success: false for missing location' do
|
|
64
|
+
result = client.visit_location(id: 'ghost')
|
|
65
|
+
expect(result[:success]).to be false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'increments visit count on repeated visits' do
|
|
69
|
+
client.add_location(id: 'loc1')
|
|
70
|
+
3.times { client.visit_location(id: 'loc1') }
|
|
71
|
+
result = client.visit_location(id: 'loc1')
|
|
72
|
+
expect(result[:visit_count]).to eq(4)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe '#find_path' do
|
|
77
|
+
before { setup_two_locations }
|
|
78
|
+
|
|
79
|
+
it 'finds path between connected locations' do
|
|
80
|
+
result = client.find_path(from: 'a', to: 'b')
|
|
81
|
+
expect(result[:success]).to be true
|
|
82
|
+
expect(result[:path]).to eq(%w[a b])
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'returns success: false for disconnected locations' do
|
|
86
|
+
client.add_location(id: 'island')
|
|
87
|
+
result = client.find_path(from: 'a', to: 'island')
|
|
88
|
+
expect(result[:success]).to be false
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'returns trivial path for same start and end' do
|
|
92
|
+
result = client.find_path(from: 'a', to: 'a')
|
|
93
|
+
expect(result[:success]).to be true
|
|
94
|
+
expect(result[:distance]).to eq(0.0)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe '#explore_neighborhood' do
|
|
99
|
+
before { setup_two_locations }
|
|
100
|
+
|
|
101
|
+
it 'returns reachable locations' do
|
|
102
|
+
result = client.explore_neighborhood(id: 'a', max_distance: 2.0)
|
|
103
|
+
expect(result[:success]).to be true
|
|
104
|
+
expect(result[:count]).to be >= 1
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'respects max_distance' do
|
|
108
|
+
result = client.explore_neighborhood(id: 'a', max_distance: 0.5)
|
|
109
|
+
expect(result[:count]).to eq(0)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'returns success: true even for isolated location' do
|
|
113
|
+
client.add_location(id: 'island')
|
|
114
|
+
result = client.explore_neighborhood(id: 'island', max_distance: 5.0)
|
|
115
|
+
expect(result[:success]).to be true
|
|
116
|
+
expect(result[:count]).to eq(0)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
describe '#map_clusters' do
|
|
121
|
+
it 'returns cluster information' do
|
|
122
|
+
client.add_location(id: 'a')
|
|
123
|
+
client.add_location(id: 'b')
|
|
124
|
+
client.connect_locations(from: 'a', to: 'b')
|
|
125
|
+
result = client.map_clusters
|
|
126
|
+
expect(result[:success]).to be true
|
|
127
|
+
expect(result[:count]).to eq(1)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'returns zero clusters for empty map' do
|
|
131
|
+
result = client.map_clusters
|
|
132
|
+
expect(result[:count]).to eq(0)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
describe '#familiar_locations' do
|
|
137
|
+
it 'returns locations sorted by familiarity' do
|
|
138
|
+
3.times { |i| client.add_location(id: "loc_#{i}") }
|
|
139
|
+
5.times { client.visit_location(id: 'loc_0') }
|
|
140
|
+
result = client.familiar_locations(limit: 3)
|
|
141
|
+
expect(result[:success]).to be true
|
|
142
|
+
expect(result[:locations].first[:id]).to eq('loc_0')
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'respects limit' do
|
|
146
|
+
5.times { |i| client.add_location(id: "loc_#{i}") }
|
|
147
|
+
result = client.familiar_locations(limit: 2)
|
|
148
|
+
expect(result[:count]).to be <= 2
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
describe '#switch_context' do
|
|
153
|
+
it 'switches to a new context' do
|
|
154
|
+
result = client.switch_context(context_id: :work)
|
|
155
|
+
expect(result[:success]).to be true
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it 'new context has empty map' do
|
|
159
|
+
client.add_location(id: 'loc1')
|
|
160
|
+
client.switch_context(context_id: :empty_context)
|
|
161
|
+
stats = client.cognitive_map_stats
|
|
162
|
+
expect(stats[:location_count]).to eq(0)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
describe '#update_cognitive_map' do
|
|
167
|
+
it 'runs decay cycle and returns counts' do
|
|
168
|
+
client.add_location(id: 'a')
|
|
169
|
+
client.visit_location(id: 'a')
|
|
170
|
+
result = client.update_cognitive_map
|
|
171
|
+
expect(result[:success]).to be true
|
|
172
|
+
expect(result).to include(:decayed, :pruned)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
describe '#cognitive_map_stats' do
|
|
177
|
+
it 'returns stats with success: true' do
|
|
178
|
+
result = client.cognitive_map_stats
|
|
179
|
+
expect(result[:success]).to be true
|
|
180
|
+
expect(result).to include(:context, :location_count, :edge_count)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it 'reflects added locations' do
|
|
184
|
+
client.add_location(id: 'a')
|
|
185
|
+
client.add_location(id: 'b')
|
|
186
|
+
result = client.cognitive_map_stats
|
|
187
|
+
expect(result[:location_count]).to eq(2)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Logging
|
|
7
|
+
def self.debug(_msg); end
|
|
8
|
+
def self.info(_msg); end
|
|
9
|
+
def self.warn(_msg); end
|
|
10
|
+
def self.error(_msg); end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
require 'legion/extensions/cognitive_map'
|
|
15
|
+
|
|
16
|
+
RSpec.configure do |config|
|
|
17
|
+
config.example_status_persistence_file_path = '.rspec_status'
|
|
18
|
+
config.disable_monkey_patching!
|
|
19
|
+
config.expect_with(:rspec) { |c| c.syntax = :expect }
|
|
20
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-cognitive-map
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
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: Tolman's cognitive map + O'Keefe/Moser place and grid cell theory for
|
|
27
|
+
brain-modeled agentic AI
|
|
28
|
+
email:
|
|
29
|
+
- matthewdiverson@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- Gemfile
|
|
35
|
+
- lex-cognitive-map.gemspec
|
|
36
|
+
- lib/legion/extensions/cognitive_map.rb
|
|
37
|
+
- lib/legion/extensions/cognitive_map/actors/decay.rb
|
|
38
|
+
- lib/legion/extensions/cognitive_map/client.rb
|
|
39
|
+
- lib/legion/extensions/cognitive_map/helpers/cognitive_map_store.rb
|
|
40
|
+
- lib/legion/extensions/cognitive_map/helpers/constants.rb
|
|
41
|
+
- lib/legion/extensions/cognitive_map/helpers/graph_traversal.rb
|
|
42
|
+
- lib/legion/extensions/cognitive_map/helpers/location.rb
|
|
43
|
+
- lib/legion/extensions/cognitive_map/runners/cognitive_map.rb
|
|
44
|
+
- lib/legion/extensions/cognitive_map/version.rb
|
|
45
|
+
- spec/legion/extensions/cognitive_map/client_spec.rb
|
|
46
|
+
- spec/legion/extensions/cognitive_map/helpers/cognitive_map_store_spec.rb
|
|
47
|
+
- spec/legion/extensions/cognitive_map/helpers/location_spec.rb
|
|
48
|
+
- spec/legion/extensions/cognitive_map/runners/cognitive_map_spec.rb
|
|
49
|
+
- spec/spec_helper.rb
|
|
50
|
+
homepage: https://github.com/LegionIO/lex-cognitive-map
|
|
51
|
+
licenses:
|
|
52
|
+
- MIT
|
|
53
|
+
metadata:
|
|
54
|
+
homepage_uri: https://github.com/LegionIO/lex-cognitive-map
|
|
55
|
+
source_code_uri: https://github.com/LegionIO/lex-cognitive-map
|
|
56
|
+
documentation_uri: https://github.com/LegionIO/lex-cognitive-map
|
|
57
|
+
changelog_uri: https://github.com/LegionIO/lex-cognitive-map
|
|
58
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-map/issues
|
|
59
|
+
rubygems_mfa_required: 'true'
|
|
60
|
+
rdoc_options: []
|
|
61
|
+
require_paths:
|
|
62
|
+
- lib
|
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.4'
|
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '0'
|
|
73
|
+
requirements: []
|
|
74
|
+
rubygems_version: 3.6.9
|
|
75
|
+
specification_version: 4
|
|
76
|
+
summary: LEX Cognitive Map
|
|
77
|
+
test_files: []
|