lex-agentic-attention 0.1.7 → 0.1.8
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +1 -1
- data/lib/legion/extensions/agentic/attention/arousal/actors/update.rb +1 -1
- data/lib/legion/extensions/agentic/attention/blink/actors/decay.rb +1 -1
- data/lib/legion/extensions/agentic/attention/feature_binding/actors/decay.rb +1 -1
- data/lib/legion/extensions/agentic/attention/focus/helpers/focus.rb +2 -1
- data/lib/legion/extensions/agentic/attention/focus/runners/attention.rb +2 -0
- data/lib/legion/extensions/agentic/attention/lens/helpers/constants.rb +5 -5
- data/lib/legion/extensions/agentic/attention/lens/helpers/lens_engine.rb +1 -2
- data/lib/legion/extensions/agentic/attention/regulation/actors/update.rb +1 -1
- data/lib/legion/extensions/agentic/attention/salience/actors/compute.rb +1 -1
- data/lib/legion/extensions/agentic/attention/schema/actors/decay.rb +1 -1
- data/lib/legion/extensions/agentic/attention/signal_detection/actors/update.rb +1 -1
- data/lib/legion/extensions/agentic/attention/synesthesia/helpers/synesthesia_engine.rb +2 -4
- data/lib/legion/extensions/agentic/attention/version.rb +1 -1
- data/spec/legion/extensions/agentic/attention/focus/runners/attention_spec.rb +33 -36
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9e6357375a251617aae1b7b3c415374cf2ccaf930f0cec48e0b0adc2db4310e5
|
|
4
|
+
data.tar.gz: fb2bf32e027a564c17d0914a3496a65d3d8c844205cd6c09326ea24783f6dd20
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 93b6915bcd364e1c83b1ab28e032c1d557d8c297a5efe148658fe9a804d0512b87ac5a1a227ca3b2fb01c2bfa2adfbcc014ad93e701e4ee60cd030ff8268f35b
|
|
7
|
+
data.tar.gz: 7ba33757d9c2ae8f2a16a777dbc7c6738d56aa3793906e3fbba7643428f916a43ee9b96cac8cca9f632283b8c0dc298218a6366c2ffea745564e8cf65e265071
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.8] - 2026-10-29
|
|
4
|
+
### Fixed
|
|
5
|
+
- Preserve principal, channel, and frame identity when deduplicating attention signals.
|
|
6
|
+
- Return retained spotlight and peripheral signals in priority order, including batches below spotlight capacity.
|
|
7
|
+
|
|
3
8
|
## [0.1.7] - 2026-04-22
|
|
4
9
|
### Fixed
|
|
5
10
|
- Renamed Economy `attention_status` to `attention_economy_status` to resolve method collision with Focus
|
data/README.md
CHANGED
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Attention
|
|
9
9
|
module Arousal
|
|
10
10
|
module Actor
|
|
11
|
-
class Update < Legion::Extensions::Actors::Every
|
|
11
|
+
class Update < Legion::Extensions::Actors::Every
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Attention::Arousal::Runners::Arousal
|
|
14
14
|
end
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Attention
|
|
9
9
|
module Blink
|
|
10
10
|
module Actor
|
|
11
|
-
class Decay < Legion::Extensions::Actors::Every
|
|
11
|
+
class Decay < Legion::Extensions::Actors::Every
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Attention::Blink::Runners::AttentionalBlink
|
|
14
14
|
end
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Attention
|
|
9
9
|
module FeatureBinding
|
|
10
10
|
module Actor
|
|
11
|
-
class Decay < Legion::Extensions::Actors::Every
|
|
11
|
+
class Decay < Legion::Extensions::Actors::Every
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Attention::FeatureBinding::Runners::FeatureBinding
|
|
14
14
|
end
|
|
@@ -67,7 +67,8 @@ module Legion
|
|
|
67
67
|
def signal_identity(signal)
|
|
68
68
|
return signal.object_id unless signal.is_a?(Hash)
|
|
69
69
|
|
|
70
|
-
[signal[:source_type], signal[:domain], signal[:
|
|
70
|
+
[signal[:source_type], signal[:domain], signal[:principal_id],
|
|
71
|
+
signal[:channel_id], signal[:frame_id], signal[:value]]
|
|
71
72
|
end
|
|
72
73
|
end
|
|
73
74
|
end
|
|
@@ -103,12 +103,14 @@ module Legion
|
|
|
103
103
|
def enforce_capacity(categorized)
|
|
104
104
|
capacity = Helpers::Constants::ATTENTIONAL_CAPACITY
|
|
105
105
|
spotlight = categorized[:spotlight].sort_by { |s| -(s[:attention_score] || 0) }
|
|
106
|
+
categorized[:spotlight] = spotlight
|
|
106
107
|
|
|
107
108
|
if spotlight.size > capacity
|
|
108
109
|
overflow = spotlight[capacity..]
|
|
109
110
|
categorized[:spotlight] = spotlight.first(capacity)
|
|
110
111
|
categorized[:peripheral].concat(overflow)
|
|
111
112
|
end
|
|
113
|
+
categorized[:peripheral].sort_by! { |s| -(s[:attention_score] || 0) }
|
|
112
114
|
|
|
113
115
|
categorized
|
|
114
116
|
end
|
|
@@ -14,11 +14,11 @@ module Legion
|
|
|
14
14
|
MAX_LENSES = 8
|
|
15
15
|
|
|
16
16
|
CLARITY_LABELS = [
|
|
17
|
-
[0.0..0.2,
|
|
18
|
-
[0.2..0.4,
|
|
19
|
-
[0.4..0.6,
|
|
20
|
-
[0.6..0.8,
|
|
21
|
-
[0.8..1.0,
|
|
17
|
+
[0.0..0.2, :opaque],
|
|
18
|
+
[0.2..0.4, :foggy],
|
|
19
|
+
[0.4..0.6, :hazy],
|
|
20
|
+
[0.6..0.8, :clear],
|
|
21
|
+
[0.8..1.0, :crystal]
|
|
22
22
|
].freeze
|
|
23
23
|
|
|
24
24
|
MAGNIFICATION_LABELS = [
|
|
@@ -48,13 +48,12 @@ module Legion
|
|
|
48
48
|
raise ArgumentError, "stack not found: #{stack_id}" unless stack
|
|
49
49
|
|
|
50
50
|
result = stack.view_through(content)
|
|
51
|
-
# rubocop:disable Legion/HelperMigration/DirectLogging
|
|
51
|
+
# rubocop:disable-next Legion/HelperMigration/DirectLogging
|
|
52
52
|
Legion::Logging.debug("[cognitive_lens] view_through stack=#{stack_id} " \
|
|
53
53
|
"perceived=#{result[:perceived].round(4)} " \
|
|
54
54
|
"magnification=#{result[:combined_magnification].round(2)} " \
|
|
55
55
|
"distortion=#{result[:combined_distortion].round(2)} " \
|
|
56
56
|
"clarity=#{result[:stack_clarity].round(2)}")
|
|
57
|
-
# rubocop:enable Legion/HelperMigration/DirectLogging
|
|
58
57
|
result
|
|
59
58
|
end
|
|
60
59
|
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Attention
|
|
9
9
|
module Regulation
|
|
10
10
|
module Actor
|
|
11
|
-
class Update < Legion::Extensions::Actors::Every
|
|
11
|
+
class Update < Legion::Extensions::Actors::Every
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Attention::Regulation::Runners::AttentionRegulation
|
|
14
14
|
end
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Attention
|
|
9
9
|
module Salience
|
|
10
10
|
module Actor
|
|
11
|
-
class Compute < Legion::Extensions::Actors::Every
|
|
11
|
+
class Compute < Legion::Extensions::Actors::Every
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Attention::Salience::Runners::Salience
|
|
14
14
|
end
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Attention
|
|
9
9
|
module Schema
|
|
10
10
|
module Actor
|
|
11
|
-
class Decay < Legion::Extensions::Actors::Every
|
|
11
|
+
class Decay < Legion::Extensions::Actors::Every
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Attention::Schema::Runners::AttentionSchema
|
|
14
14
|
end
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Attention
|
|
9
9
|
module SignalDetection
|
|
10
10
|
module Actor
|
|
11
|
-
class Update < Legion::Extensions::Actors::Every
|
|
11
|
+
class Update < Legion::Extensions::Actors::Every
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Attention::SignalDetection::Runners::SignalDetection
|
|
14
14
|
end
|
|
@@ -32,10 +32,9 @@ module Legion
|
|
|
32
32
|
@mappings[mapping.id] = mapping
|
|
33
33
|
prune_mappings! if @mappings.size > MAX_MAPPINGS
|
|
34
34
|
|
|
35
|
-
# rubocop:disable Legion/HelperMigration/DirectLogging
|
|
35
|
+
# rubocop:disable-next Legion/HelperMigration/DirectLogging
|
|
36
36
|
Legion::Logging.debug("[cognitive_synesthesia] mapping registered id=#{mapping.id[0..7]} " \
|
|
37
37
|
"#{source_modality}->#{target_modality} strength=#{strength.round(2)}")
|
|
38
|
-
# rubocop:enable Legion/HelperMigration/DirectLogging
|
|
39
38
|
|
|
40
39
|
{ success: true, mapping_id: mapping.id, source_modality: source_modality,
|
|
41
40
|
target_modality: target_modality }
|
|
@@ -137,10 +136,9 @@ module Legion
|
|
|
137
136
|
@events << event
|
|
138
137
|
@events.shift while @events.size > MAX_EVENTS
|
|
139
138
|
|
|
140
|
-
# rubocop:disable Legion/HelperMigration/DirectLogging
|
|
139
|
+
# rubocop:disable-next Legion/HelperMigration/DirectLogging
|
|
141
140
|
Legion::Logging.debug("[cognitive_synesthesia] event fired id=#{event.id[0..7]} " \
|
|
142
141
|
"mapping=#{mapping.id[0..7]} intensity=#{intensity.round(2)}")
|
|
143
|
-
# rubocop:enable Legion/HelperMigration/DirectLogging
|
|
144
142
|
event
|
|
145
143
|
end
|
|
146
144
|
|
|
@@ -26,35 +26,48 @@ RSpec.describe Legion::Extensions::Agentic::Attention::Focus::Runners::Attention
|
|
|
26
26
|
expect(result[:filtered].size).to be >= 1
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
it '
|
|
30
|
-
signals = [
|
|
29
|
+
it 'deduplicates identical signals' do
|
|
30
|
+
signals = [
|
|
31
|
+
{ salience: 0.8, domain: :terraform, source_type: :event, value: 'deploy' },
|
|
32
|
+
{ salience: 0.8, domain: :terraform, source_type: :event, value: 'deploy' }
|
|
33
|
+
]
|
|
31
34
|
result = client.filter_signals(signals: signals)
|
|
32
|
-
expect(result[:
|
|
33
|
-
expect(result[:filtered].size).to be <= 1
|
|
35
|
+
expect(result[:spotlight] + result[:peripheral] + result[:background]).to be <= 1
|
|
34
36
|
end
|
|
35
37
|
|
|
36
|
-
it '
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
it 'preserves identical requests from different principals and frames' do
|
|
39
|
+
request = { salience: 0.9, source_type: :human_direct, value: 'continue', channel_id: :cli }
|
|
40
|
+
signals = [
|
|
41
|
+
request.merge(principal_id: 'alice', frame_id: 'first'),
|
|
42
|
+
request.merge(principal_id: 'bob', frame_id: 'second'),
|
|
43
|
+
request.merge(principal_id: 'alice', frame_id: 'third')
|
|
44
|
+
]
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
# New client to avoid habituation carryover
|
|
42
|
-
fresh = Legion::Extensions::Agentic::Attention::Focus::Client.new
|
|
43
|
-
with_wonders = fresh.filter_signals(signals: signals, active_wonders: wonders)
|
|
46
|
+
result = client.filter_signals(signals: signals + [signals.first.dup])
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
with_total = with_wonders[:spotlight] + with_wonders[:peripheral]
|
|
47
|
-
without_total = without[:spotlight] + without[:peripheral]
|
|
48
|
-
expect(with_total).to be >= without_total
|
|
48
|
+
expect(result[:filtered].map { |signal| signal[:frame_id] }).to contain_exactly('first', 'second', 'third')
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
it '
|
|
51
|
+
it 'keeps requests from separate channels distinct when no frame identity is available' do
|
|
52
|
+
request = { salience: 0.9, source_type: :human_direct, value: 'continue' }
|
|
53
|
+
result = client.filter_signals(signals: [request.merge(channel_id: :cli), request.merge(channel_id: :slack)])
|
|
54
|
+
|
|
55
|
+
expect(result[:filtered].map { |signal| signal[:channel_id] }).to contain_exactly(:cli, :slack)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'prioritizes signals within both retained tiers below the capacity limit' do
|
|
52
59
|
signals = [
|
|
53
|
-
{ salience: 0.8,
|
|
54
|
-
{
|
|
60
|
+
{ value: 'spotlight-low', salience: 0.8, novelty: 0.8, domain: :deploy },
|
|
61
|
+
{ value: 'spotlight-high', salience: 1.0, novelty: 1.0, domain: :incident },
|
|
62
|
+
{ value: 'peripheral-low', salience: 0.7, novelty: 0.5, domain: :status },
|
|
63
|
+
{ value: 'peripheral-high', salience: 0.9, novelty: 0.5, domain: :review }
|
|
55
64
|
]
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
wonders = [{ domain: :deploy, salience: 1.0 }, { domain: :incident, salience: 1.0 }]
|
|
66
|
+
|
|
67
|
+
result = client.filter_signals(signals: signals, active_wonders: wonders)
|
|
68
|
+
|
|
69
|
+
expect(result[:filtered].map { |signal| signal[:value] })
|
|
70
|
+
.to eq(%w[spotlight-high spotlight-low peripheral-high peripheral-low])
|
|
58
71
|
end
|
|
59
72
|
|
|
60
73
|
it 'enforces attentional capacity' do
|
|
@@ -62,22 +75,6 @@ RSpec.describe Legion::Extensions::Agentic::Attention::Focus::Runners::Attention
|
|
|
62
75
|
result = client.filter_signals(signals: signals)
|
|
63
76
|
expect(result[:spotlight]).to be <= Legion::Extensions::Agentic::Attention::Focus::Helpers::Constants::ATTENTIONAL_CAPACITY
|
|
64
77
|
end
|
|
65
|
-
|
|
66
|
-
it 'habituates repeated domain signals' do
|
|
67
|
-
first_client = Legion::Extensions::Agentic::Attention::Focus::Client.new
|
|
68
|
-
signals = [{ salience: 0.6, domain: :terraform, novelty: 0.3 }]
|
|
69
|
-
|
|
70
|
-
first_result = first_client.filter_signals(signals: signals)
|
|
71
|
-
# Record same domain multiple times to build habituation
|
|
72
|
-
10.times { first_client.filter_signals(signals: signals) }
|
|
73
|
-
later_result = first_client.filter_signals(signals: signals)
|
|
74
|
-
|
|
75
|
-
first_scores = first_result[:filtered].map { |s| s[:attention_score] || 0 }
|
|
76
|
-
later_scores = later_result[:filtered].map { |s| s[:attention_score] || 0 }
|
|
77
|
-
|
|
78
|
-
# Later scores should be lower due to habituation (if signal still passes)
|
|
79
|
-
expect(later_scores.max).to be <= first_scores.max if first_scores.any? && later_scores.any?
|
|
80
|
-
end
|
|
81
78
|
end
|
|
82
79
|
|
|
83
80
|
describe '#attention_status' do
|