lex-agentic-attention 0.1.4 → 0.1.6
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 +9 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/lex-agentic-attention.gemspec +2 -2
- data/lib/legion/extensions/agentic/attention/arousal/runners/arousal.rb +8 -8
- data/lib/legion/extensions/agentic/attention/economy/runners/attention_economy.rb +12 -12
- data/lib/legion/extensions/agentic/attention/feature_binding/actors/decay.rb +1 -1
- data/lib/legion/extensions/agentic/attention/feature_binding/runners/feature_binding.rb +13 -13
- data/lib/legion/extensions/agentic/attention/focus/runners/attention.rb +7 -7
- data/lib/legion/extensions/agentic/attention/latent_inhibition/runners/latent_inhibition.rb +14 -14
- data/lib/legion/extensions/agentic/attention/lens/helpers/lens_engine.rb +4 -2
- data/lib/legion/extensions/agentic/attention/lens/runners/cognitive_lens.rb +9 -9
- data/lib/legion/extensions/agentic/attention/lighthouse/runners/cognitive_lighthouse.rb +6 -6
- data/lib/legion/extensions/agentic/attention/priming/runners/priming.rb +3 -3
- data/lib/legion/extensions/agentic/attention/prism/helpers/prism_engine.rb +1 -1
- data/lib/legion/extensions/agentic/attention/prism/runners/cognitive_prism.rb +4 -4
- data/lib/legion/extensions/agentic/attention/relevance_theory/runners/relevance_theory.rb +16 -16
- data/lib/legion/extensions/agentic/attention/salience/runners/salience.rb +6 -6
- data/lib/legion/extensions/agentic/attention/schema/actors/decay.rb +1 -1
- data/lib/legion/extensions/agentic/attention/schema/runners/attention_schema.rb +13 -13
- data/lib/legion/extensions/agentic/attention/signal_detection/runners/signal_detection.rb +20 -20
- data/lib/legion/extensions/agentic/attention/spotlight/runners/attention_spotlight.rb +23 -23
- data/lib/legion/extensions/agentic/attention/surprise/runners/surprise.rb +12 -12
- data/lib/legion/extensions/agentic/attention/synesthesia/helpers/synesthesia_engine.rb +9 -5
- data/lib/legion/extensions/agentic/attention/synesthesia/runners/cognitive_synesthesia.rb +10 -10
- data/lib/legion/extensions/agentic/attention/version.rb +1 -1
- data/lib/legion/extensions/agentic/attention.rb +13 -1
- data/spec/legion/extensions/agentic/attention/focus/runners/attention_spec.rb +1 -1
- data/spec/legion/extensions/agentic/attention/spotlight/helpers/spotlight_engine_spec.rb +1 -1
- data/spec/legion/extensions/agentic/attention/surprise/client_spec.rb +1 -1
- metadata +9 -9
|
@@ -7,8 +7,8 @@ module Legion
|
|
|
7
7
|
module RelevanceTheory
|
|
8
8
|
module Runners
|
|
9
9
|
module RelevanceTheory
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def submit_relevance_input(content:, input_type:, context:, cognitive_effect: nil,
|
|
14
14
|
processing_effort: nil, effect_type: nil, source_id: nil, **)
|
|
@@ -21,66 +21,66 @@ module Legion
|
|
|
21
21
|
effect_type: (effect_type || :new_implication).to_sym,
|
|
22
22
|
source_id: source_id
|
|
23
23
|
)
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
log.debug("[relevance_theory] submit id=#{input.id[0..7]} " \
|
|
25
|
+
"type=#{input_type} relevance=#{input.normalized_relevance.round(3)}")
|
|
26
26
|
{ success: true, input: input.to_h }
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def assess_input_relevance(input_id:, **)
|
|
30
30
|
result = engine.assess_relevance(input_id: input_id)
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
log.debug("[relevance_theory] assess id=#{input_id[0..7]} " \
|
|
32
|
+
"relevance=#{result[:normalized]}")
|
|
33
33
|
result
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def strengthen_relevance(input_id:, amount: 0.1, **)
|
|
37
37
|
result = engine.strengthen_input(input_id: input_id, amount: amount)
|
|
38
|
-
|
|
38
|
+
log.debug("[relevance_theory] strengthen id=#{input_id[0..7]}")
|
|
39
39
|
result
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def weaken_relevance(input_id:, amount: 0.1, **)
|
|
43
43
|
result = engine.weaken_input(input_id: input_id, amount: amount)
|
|
44
|
-
|
|
44
|
+
log.debug("[relevance_theory] weaken id=#{input_id[0..7]}")
|
|
45
45
|
result
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def worth_processing_report(**)
|
|
49
49
|
inputs = engine.worth_processing
|
|
50
|
-
|
|
50
|
+
log.debug("[relevance_theory] worth_processing count=#{inputs.size}")
|
|
51
51
|
{ success: true, inputs: inputs.map(&:to_h), count: inputs.size }
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def most_relevant_inputs(limit: 5, **)
|
|
55
55
|
inputs = engine.most_relevant(limit: limit)
|
|
56
|
-
|
|
56
|
+
log.debug("[relevance_theory] most_relevant count=#{inputs.size}")
|
|
57
57
|
{ success: true, inputs: inputs.map(&:to_h), count: inputs.size }
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def context_relevance_report(context:, **)
|
|
61
61
|
score = engine.context_relevance(context: context.to_sym)
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
log.debug('[relevance_theory] context_relevance ' \
|
|
63
|
+
"ctx=#{context} score=#{score.round(3)}")
|
|
64
64
|
{ success: true, context: context, relevance: score.round(3) }
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def attention_budget_report(**)
|
|
68
68
|
budget = engine.attention_budget
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
log.debug('[relevance_theory] attention_budget ' \
|
|
70
|
+
"ratio=#{budget[:processing_ratio]}")
|
|
71
71
|
{ success: true }.merge(budget)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
def update_relevance_theory(**)
|
|
75
75
|
engine.decay_all
|
|
76
76
|
pruned = engine.prune_irrelevant
|
|
77
|
-
|
|
77
|
+
log.debug("[relevance_theory] decay+prune pruned=#{pruned}")
|
|
78
78
|
{ success: true, pruned: pruned }
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def relevance_theory_stats(**)
|
|
82
82
|
stats = engine.to_h
|
|
83
|
-
|
|
83
|
+
log.debug("[relevance_theory] stats total=#{stats[:total_inputs]}")
|
|
84
84
|
{ success: true }.merge(stats)
|
|
85
85
|
end
|
|
86
86
|
|
|
@@ -7,15 +7,15 @@ module Legion
|
|
|
7
7
|
module Salience
|
|
8
8
|
module Runners
|
|
9
9
|
module Salience
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def compute_salience(tick_results: {}, **)
|
|
14
14
|
integrated = Helpers::SignalIntegrator.integrate(tick_results: tick_results)
|
|
15
15
|
salience_map.update(integrated)
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
log.debug("[salience] compute: overall=#{salience_map.overall_salience.round(3)} " \
|
|
18
|
+
"urgency=#{salience_map.urgency_level} dominant=#{salience_map.dominant_source}")
|
|
19
19
|
|
|
20
20
|
{
|
|
21
21
|
overall: salience_map.overall_salience,
|
|
@@ -29,7 +29,7 @@ module Legion
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def salience_status(**)
|
|
32
|
-
|
|
32
|
+
log.debug("[salience] status: urgency=#{salience_map.urgency_level} trend=#{salience_map.salience_trend}")
|
|
33
33
|
{
|
|
34
34
|
overall: salience_map.overall_salience,
|
|
35
35
|
urgency: salience_map.urgency_level,
|
|
@@ -42,7 +42,7 @@ module Legion
|
|
|
42
42
|
|
|
43
43
|
def salience_for(source:, **)
|
|
44
44
|
data = salience_map.current_map[source]
|
|
45
|
-
|
|
45
|
+
log.debug("[salience] salience_for: source=#{source} salience=#{data || 0.0}")
|
|
46
46
|
{ source: source, salience: data || 0.0, urgency: salience_map.urgency_level }
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -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 # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Attention::Schema::Runners::AttentionSchema
|
|
14
14
|
end
|
|
@@ -7,12 +7,12 @@ module Legion
|
|
|
7
7
|
module Schema
|
|
8
8
|
module Runners
|
|
9
9
|
module AttentionSchema
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
# Focus attention on a target — adds or boosts it in the schema
|
|
14
14
|
def focus_on(target:, domain:, reason:, source: :external, **)
|
|
15
|
-
|
|
15
|
+
log.debug("[attention_schema] focus_on: target=#{target} domain=#{domain} source=#{source}")
|
|
16
16
|
item = schema_model.focus_on(target: target, domain: domain, reason: reason, source: source)
|
|
17
17
|
{
|
|
18
18
|
success: true,
|
|
@@ -26,7 +26,7 @@ module Legion
|
|
|
26
26
|
|
|
27
27
|
# Remove a target from the attention schema
|
|
28
28
|
def defocus(target:, **)
|
|
29
|
-
|
|
29
|
+
log.debug("[attention_schema] defocus: target=#{target}")
|
|
30
30
|
removed = schema_model.defocus(target: target)
|
|
31
31
|
{ success: true, target: target, removed: removed, schema_size: schema_model.schema_size }
|
|
32
32
|
end
|
|
@@ -34,14 +34,14 @@ module Legion
|
|
|
34
34
|
# Core AST query: "am I aware of X?"
|
|
35
35
|
def am_i_aware_of(target:, **)
|
|
36
36
|
result = schema_model.am_i_aware_of(target: target)
|
|
37
|
-
|
|
37
|
+
log.debug("[attention_schema] am_i_aware_of: target=#{target} aware=#{result[:aware]} level=#{result[:awareness_level]}")
|
|
38
38
|
result.merge(success: true)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
# Generate a natural-language attention awareness report
|
|
42
42
|
def report_awareness(**)
|
|
43
43
|
report = schema_model.report_awareness
|
|
44
|
-
|
|
44
|
+
log.debug("[attention_schema] report_awareness: state=#{report[:state]} items=#{report[:items].size}")
|
|
45
45
|
report.merge(success: true)
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -49,13 +49,13 @@ module Legion
|
|
|
49
49
|
def attention_state(**)
|
|
50
50
|
state = schema_model.attention_state
|
|
51
51
|
label = Helpers::Constants::ATTENTION_STATE_LABELS[state]
|
|
52
|
-
|
|
52
|
+
log.debug("[attention_schema] attention_state: state=#{state}")
|
|
53
53
|
{ success: true, state: state, label: label }
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# Model another agent's attention (social attention modeling)
|
|
57
57
|
def model_other_attention(agent_id:, target:, awareness:, **)
|
|
58
|
-
|
|
58
|
+
log.debug("[attention_schema] model_other: agent=#{agent_id} target=#{target} awareness=#{awareness}")
|
|
59
59
|
schema_model.model_other_attention(agent_id: agent_id, target: target, awareness: awareness.to_f)
|
|
60
60
|
{ success: true, agent_id: agent_id, target: target, awareness: awareness.to_f.clamp(0.0, 1.0).round(4) }
|
|
61
61
|
end
|
|
@@ -63,14 +63,14 @@ module Legion
|
|
|
63
63
|
# Query what another agent is modeled as attending to
|
|
64
64
|
def query_other_attention(agent_id:, **)
|
|
65
65
|
model = schema_model.query_other_attention(agent_id: agent_id)
|
|
66
|
-
|
|
66
|
+
log.debug("[attention_schema] query_other: agent=#{agent_id} found=#{!model.nil?}")
|
|
67
67
|
{ success: true, agent_id: agent_id, model: model }
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
# Run meta-attention check: detect drifting, hyper-focus, etc.
|
|
71
71
|
def meta_check(**)
|
|
72
72
|
result = schema_model.meta_check
|
|
73
|
-
|
|
73
|
+
log.debug("[attention_schema] meta_check: state=#{result[:state]} signals=#{result[:signals]}")
|
|
74
74
|
result.merge(success: true)
|
|
75
75
|
end
|
|
76
76
|
|
|
@@ -78,7 +78,7 @@ module Legion
|
|
|
78
78
|
def update_meta_accuracy(was_correct:, **)
|
|
79
79
|
schema_model.update_meta_accuracy(was_correct: was_correct)
|
|
80
80
|
accuracy = schema_model.meta_accuracy
|
|
81
|
-
|
|
81
|
+
log.debug("[attention_schema] meta_accuracy: was_correct=#{was_correct} accuracy=#{accuracy.round(3)}")
|
|
82
82
|
{ success: true, was_correct: was_correct, meta_accuracy: accuracy.round(4) }
|
|
83
83
|
end
|
|
84
84
|
|
|
@@ -87,7 +87,7 @@ module Legion
|
|
|
87
87
|
before = schema_model.schema_size
|
|
88
88
|
schema_model.decay_all
|
|
89
89
|
after = schema_model.schema_size
|
|
90
|
-
|
|
90
|
+
log.debug("[attention_schema] decay: before=#{before} after=#{after} pruned=#{before - after}")
|
|
91
91
|
{
|
|
92
92
|
success: true,
|
|
93
93
|
before: before,
|
|
@@ -99,7 +99,7 @@ module Legion
|
|
|
99
99
|
|
|
100
100
|
# Return full schema stats snapshot
|
|
101
101
|
def schema_stats(**)
|
|
102
|
-
|
|
102
|
+
log.debug("[attention_schema] stats: size=#{schema_model.schema_size}")
|
|
103
103
|
{ success: true, stats: schema_model.to_h }
|
|
104
104
|
end
|
|
105
105
|
|
|
@@ -7,15 +7,15 @@ module Legion
|
|
|
7
7
|
module SignalDetection
|
|
8
8
|
module Runners
|
|
9
9
|
module SignalDetection
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def create_detector(domain:, **)
|
|
14
14
|
detector = detection_engine.create_detector(domain: domain)
|
|
15
|
-
|
|
15
|
+
log.info("[signal_detection] created detector id=#{detector.id[0..7]} domain=#{domain}")
|
|
16
16
|
{ created: true, detector_id: detector.id, domain: domain }
|
|
17
17
|
rescue ArgumentError => e
|
|
18
|
-
|
|
18
|
+
log.warn("[signal_detection] create_detector failed: #{e.message}")
|
|
19
19
|
{ created: false, reason: e.message }
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -25,42 +25,42 @@ module Legion
|
|
|
25
25
|
signal_present: signal_present,
|
|
26
26
|
responded_present: responded_present
|
|
27
27
|
)
|
|
28
|
-
|
|
28
|
+
log.debug("[signal_detection] trial: id=#{detector_id[0..7]} outcome=#{result[:outcome]} count=#{result[:trial_count]}")
|
|
29
29
|
result
|
|
30
30
|
rescue KeyError => e
|
|
31
|
-
|
|
31
|
+
log.warn("[signal_detection] record_trial failed: #{e.message}")
|
|
32
32
|
{ recorded: false, reason: :not_found }
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def compute_detector_sensitivity(detector_id:, **)
|
|
36
36
|
result = detection_engine.compute_sensitivity(detector_id: detector_id)
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
log.debug("[signal_detection] sensitivity: id=#{detector_id[0..7]} " \
|
|
38
|
+
"d_prime=#{result[:d_prime].round(3)} label=#{result[:sensitivity_label]}")
|
|
39
39
|
result
|
|
40
40
|
rescue KeyError => e
|
|
41
|
-
|
|
41
|
+
log.warn("[signal_detection] compute_sensitivity failed: #{e.message}")
|
|
42
42
|
{ found: false, reason: :not_found }
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def adjust_detector_bias(detector_id:, amount:, **)
|
|
46
46
|
result = detection_engine.adjust_bias(detector_id: detector_id, amount: amount)
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
log.debug("[signal_detection] bias adjusted: id=#{detector_id[0..7]} " \
|
|
48
|
+
"criterion=#{result[:criterion].round(3)} label=#{result[:bias_label]}")
|
|
49
49
|
result
|
|
50
50
|
rescue KeyError => e
|
|
51
|
-
|
|
51
|
+
log.warn("[signal_detection] adjust_bias failed: #{e.message}")
|
|
52
52
|
{ adjusted: false, reason: :not_found }
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def best_detectors(limit: 5, **)
|
|
56
56
|
detectors = detection_engine.best_detectors(limit: limit)
|
|
57
|
-
|
|
57
|
+
log.debug("[signal_detection] best detectors: count=#{detectors.size} limit=#{limit}")
|
|
58
58
|
{ detectors: detectors, count: detectors.size }
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def domain_detectors(domain:, **)
|
|
62
62
|
detectors = detection_engine.by_domain(domain: domain)
|
|
63
|
-
|
|
63
|
+
log.debug("[signal_detection] domain detectors: domain=#{domain} count=#{detectors.size}")
|
|
64
64
|
{ detectors: detectors, count: detectors.size, domain: domain }
|
|
65
65
|
end
|
|
66
66
|
|
|
@@ -69,26 +69,26 @@ module Legion
|
|
|
69
69
|
detector_id: detector_id,
|
|
70
70
|
signal_probability: signal_probability
|
|
71
71
|
)
|
|
72
|
-
|
|
72
|
+
log.debug("[signal_detection] optimal criterion: id=#{detector_id[0..7]} optimal=#{result[:optimal_criterion].round(3)}")
|
|
73
73
|
result
|
|
74
74
|
rescue KeyError => e
|
|
75
|
-
|
|
75
|
+
log.warn("[signal_detection] optimal_criterion failed: #{e.message}")
|
|
76
76
|
{ found: false, reason: :not_found }
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def detector_roc_point(detector_id:, **)
|
|
80
80
|
result = detection_engine.roc_point(detector_id: detector_id)
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
log.debug("[signal_detection] roc point: id=#{detector_id[0..7]} " \
|
|
82
|
+
"hr=#{result[:hit_rate].round(3)} far=#{result[:false_alarm_rate].round(3)}")
|
|
83
83
|
result
|
|
84
84
|
rescue KeyError => e
|
|
85
|
-
|
|
85
|
+
log.warn("[signal_detection] roc_point failed: #{e.message}")
|
|
86
86
|
{ found: false, reason: :not_found }
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
def update_signal_detection(**)
|
|
90
90
|
decayed = detection_engine.decay_all
|
|
91
|
-
|
|
91
|
+
log.debug("[signal_detection] decay cycle: detectors_updated=#{decayed}")
|
|
92
92
|
{ decayed: decayed }
|
|
93
93
|
end
|
|
94
94
|
|
|
@@ -7,104 +7,104 @@ module Legion
|
|
|
7
7
|
module Spotlight
|
|
8
8
|
module Runners
|
|
9
9
|
module AttentionSpotlight
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def register_target(label:, domain:, salience: 0.5, relevance: 0.5, **)
|
|
14
|
-
|
|
14
|
+
log.debug("[attention_spotlight] register target label=#{label} domain=#{domain}")
|
|
15
15
|
result = engine.register_target(label: label, domain: domain,
|
|
16
16
|
salience: salience, relevance: relevance)
|
|
17
17
|
{ success: result[:registered], **result }
|
|
18
18
|
rescue StandardError => e
|
|
19
|
-
|
|
19
|
+
log.error("[attention_spotlight] register_target error: #{e.message}")
|
|
20
20
|
{ success: false, error: e.message }
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def focus_spotlight(target_id:, **)
|
|
24
|
-
|
|
24
|
+
log.debug("[attention_spotlight] focus target_id=#{target_id[0..7]}")
|
|
25
25
|
result = engine.focus(target_id: target_id)
|
|
26
26
|
{ success: result[:focused], **result }
|
|
27
27
|
rescue StandardError => e
|
|
28
|
-
|
|
28
|
+
log.error("[attention_spotlight] focus_spotlight error: #{e.message}")
|
|
29
29
|
{ success: false, error: e.message }
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def broaden_spotlight(**)
|
|
33
|
-
|
|
33
|
+
log.debug('[attention_spotlight] broadening spotlight')
|
|
34
34
|
result = engine.broaden
|
|
35
35
|
{ success: true, **result }
|
|
36
36
|
rescue StandardError => e
|
|
37
|
-
|
|
37
|
+
log.error("[attention_spotlight] broaden_spotlight error: #{e.message}")
|
|
38
38
|
{ success: false, error: e.message }
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def narrow_spotlight(**)
|
|
42
|
-
|
|
42
|
+
log.debug('[attention_spotlight] narrowing spotlight')
|
|
43
43
|
result = engine.narrow
|
|
44
44
|
{ success: true, **result }
|
|
45
45
|
rescue StandardError => e
|
|
46
|
-
|
|
46
|
+
log.error("[attention_spotlight] narrow_spotlight error: #{e.message}")
|
|
47
47
|
{ success: false, error: e.message }
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def scan_targets(**)
|
|
51
|
-
|
|
51
|
+
log.debug('[attention_spotlight] initiating scan')
|
|
52
52
|
result = engine.scan
|
|
53
53
|
{ success: true, **result }
|
|
54
54
|
rescue StandardError => e
|
|
55
|
-
|
|
55
|
+
log.error("[attention_spotlight] scan_targets error: #{e.message}")
|
|
56
56
|
{ success: false, error: e.message }
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def check_peripheral(**)
|
|
60
|
-
|
|
60
|
+
log.debug('[attention_spotlight] checking periphery')
|
|
61
61
|
result = engine.check_peripheral
|
|
62
62
|
{ success: true, **result }
|
|
63
63
|
rescue StandardError => e
|
|
64
|
-
|
|
64
|
+
log.error("[attention_spotlight] check_peripheral error: #{e.message}")
|
|
65
65
|
{ success: false, error: e.message }
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def check_capture(**)
|
|
69
|
-
|
|
69
|
+
log.debug('[attention_spotlight] checking for attention capture')
|
|
70
70
|
result = engine.check_capture
|
|
71
71
|
{ success: true, **result }
|
|
72
72
|
rescue StandardError => e
|
|
73
|
-
|
|
73
|
+
log.error("[attention_spotlight] check_capture error: #{e.message}")
|
|
74
74
|
{ success: false, error: e.message }
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def release_focus(**)
|
|
78
|
-
|
|
78
|
+
log.debug('[attention_spotlight] releasing focus')
|
|
79
79
|
result = engine.release_focus
|
|
80
80
|
{ success: true, **result }
|
|
81
81
|
rescue StandardError => e
|
|
82
|
-
|
|
82
|
+
log.error("[attention_spotlight] release_focus error: #{e.message}")
|
|
83
83
|
{ success: false, error: e.message }
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def spotlight_report(**)
|
|
87
|
-
|
|
87
|
+
log.debug('[attention_spotlight] generating report')
|
|
88
88
|
report = engine.spotlight_report
|
|
89
89
|
{ success: true, **report }
|
|
90
90
|
rescue StandardError => e
|
|
91
|
-
|
|
91
|
+
log.error("[attention_spotlight] spotlight_report error: #{e.message}")
|
|
92
92
|
{ success: false, error: e.message }
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def most_salient(limit: 5, **)
|
|
96
|
-
|
|
96
|
+
log.debug("[attention_spotlight] most_salient limit=#{limit}")
|
|
97
97
|
targets = engine.most_salient(limit: limit)
|
|
98
98
|
{ success: true, targets: targets.map(&:to_h), count: targets.size }
|
|
99
99
|
rescue StandardError => e
|
|
100
|
-
|
|
100
|
+
log.error("[attention_spotlight] most_salient error: #{e.message}")
|
|
101
101
|
{ success: false, error: e.message }
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
def spotlight_state(**)
|
|
105
105
|
{ success: true, **engine.to_h }
|
|
106
106
|
rescue StandardError => e
|
|
107
|
-
|
|
107
|
+
log.error("[attention_spotlight] spotlight_state error: #{e.message}")
|
|
108
108
|
{ success: false, error: e.message }
|
|
109
109
|
end
|
|
110
110
|
|
|
@@ -7,8 +7,8 @@ module Legion
|
|
|
7
7
|
module Surprise
|
|
8
8
|
module Runners
|
|
9
9
|
module Surprise
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
# Evaluate a single prediction-outcome pair and compute surprise magnitude.
|
|
14
14
|
# magnitude = |predicted - actual| * sensitivity * valence_weight, clamped to [0,1]
|
|
@@ -35,9 +35,9 @@ module Legion
|
|
|
35
35
|
|
|
36
36
|
if orienting
|
|
37
37
|
record_cooldown(domain)
|
|
38
|
-
|
|
38
|
+
log.debug("[surprise] orienting response triggered: domain=#{domain} magnitude=#{magnitude.round(3)}")
|
|
39
39
|
else
|
|
40
|
-
|
|
40
|
+
log.debug("[surprise] surprise recorded: domain=#{domain} magnitude=#{magnitude.round(3)} orienting=false")
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
{ success: true, surprise_event: event.to_h, orienting_triggered: orienting }
|
|
@@ -65,7 +65,7 @@ module Legion
|
|
|
65
65
|
tick_cooldowns
|
|
66
66
|
|
|
67
67
|
orienting_count = events.count { |e| e[:orienting] }
|
|
68
|
-
|
|
68
|
+
log.debug("[surprise] tick update: evaluated=#{events.size} orienting=#{orienting_count}")
|
|
69
69
|
|
|
70
70
|
{
|
|
71
71
|
success: true,
|
|
@@ -80,7 +80,7 @@ module Legion
|
|
|
80
80
|
top = store.most_surprising(1).first
|
|
81
81
|
avg_mag = stats[:average_magnitude]
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
log.debug("[surprise] stats: total=#{stats[:total_events]} domains=#{stats[:domain_count]}")
|
|
84
84
|
|
|
85
85
|
{
|
|
86
86
|
success: true,
|
|
@@ -97,7 +97,7 @@ module Legion
|
|
|
97
97
|
baseline = store.baseline_for(domain)
|
|
98
98
|
domain_events = store.by_domain(domain)
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
log.debug("[surprise] domain_sensitivity: domain=#{domain} sensitivity=#{sensitivity.round(3)}")
|
|
101
101
|
|
|
102
102
|
{
|
|
103
103
|
success: true,
|
|
@@ -110,7 +110,7 @@ module Legion
|
|
|
110
110
|
|
|
111
111
|
def recent_surprises(count: 10, **)
|
|
112
112
|
events = store.recent(count)
|
|
113
|
-
|
|
113
|
+
log.debug("[surprise] recent_surprises: count=#{events.size}")
|
|
114
114
|
{ success: true, events: events.map(&:to_h), count: events.size }
|
|
115
115
|
end
|
|
116
116
|
|
|
@@ -121,7 +121,7 @@ module Legion
|
|
|
121
121
|
steps.times { habituation_model.sensitize(domain) }
|
|
122
122
|
new_sensitivity = habituation_model.sensitivity_for(domain)
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
log.debug("[surprise] reset_habituation: domain=#{domain} #{old_sensitivity.round(3)} -> #{new_sensitivity.round(3)}")
|
|
125
125
|
|
|
126
126
|
{ success: true, domain: domain, old_sensitivity: old_sensitivity.round(4), new_sensitivity: new_sensitivity.round(4) }
|
|
127
127
|
end
|
|
@@ -154,14 +154,14 @@ module Legion
|
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
def should_orient?(domain, magnitude, threshold)
|
|
157
|
-
return false if magnitude < threshold
|
|
158
|
-
return false if on_cooldown?(domain)
|
|
157
|
+
return false if magnitude < threshold # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
158
|
+
return false if on_cooldown?(domain) # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
159
159
|
|
|
160
160
|
true
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
def extract_predictions(tick_result)
|
|
164
|
-
return [] unless tick_result.is_a?(Hash)
|
|
164
|
+
return [] unless tick_result.is_a?(Hash) # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
165
165
|
|
|
166
166
|
tick_result.fetch(:predictions, [])
|
|
167
167
|
end
|
|
@@ -32,8 +32,10 @@ module Legion
|
|
|
32
32
|
@mappings[mapping.id] = mapping
|
|
33
33
|
prune_mappings! if @mappings.size > MAX_MAPPINGS
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
# rubocop:disable Legion/HelperMigration/DirectLogging
|
|
36
|
+
Legion::Logging.debug("[cognitive_synesthesia] mapping registered id=#{mapping.id[0..7]} " \
|
|
37
|
+
"#{source_modality}->#{target_modality} strength=#{strength.round(2)}")
|
|
38
|
+
# rubocop:enable Legion/HelperMigration/DirectLogging
|
|
37
39
|
|
|
38
40
|
{ success: true, mapping_id: mapping.id, source_modality: source_modality,
|
|
39
41
|
target_modality: target_modality }
|
|
@@ -54,7 +56,7 @@ module Legion
|
|
|
54
56
|
@mappings.each_value(&:decay!)
|
|
55
57
|
removed = prune_weak_mappings!
|
|
56
58
|
|
|
57
|
-
Legion::Logging.debug
|
|
59
|
+
Legion::Logging.debug("[cognitive_synesthesia] decay_mappings! removed=#{removed} remaining=#{@mappings.size}") # rubocop:disable Legion/HelperMigration/DirectLogging
|
|
58
60
|
{ success: true, mappings_removed: removed, mappings_remaining: @mappings.size }
|
|
59
61
|
end
|
|
60
62
|
|
|
@@ -135,8 +137,10 @@ module Legion
|
|
|
135
137
|
@events << event
|
|
136
138
|
@events.shift while @events.size > MAX_EVENTS
|
|
137
139
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
# rubocop:disable Legion/HelperMigration/DirectLogging
|
|
141
|
+
Legion::Logging.debug("[cognitive_synesthesia] event fired id=#{event.id[0..7]} " \
|
|
142
|
+
"mapping=#{mapping.id[0..7]} intensity=#{intensity.round(2)}")
|
|
143
|
+
# rubocop:enable Legion/HelperMigration/DirectLogging
|
|
140
144
|
event
|
|
141
145
|
end
|
|
142
146
|
|