lex-agentic-affect 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 +8 -0
- data/lib/legion/extensions/agentic/affect/emotion/helpers/valence.rb +11 -0
- data/lib/legion/extensions/agentic/affect/emotion/runners/valence.rb +20 -0
- data/lib/legion/extensions/agentic/affect/version.rb +1 -1
- data/spec/legion/extensions/agentic/affect/emotion/helpers/valence_partner_absence_spec.rb +35 -0
- data/spec/legion/extensions/agentic/affect/emotion/runners/valence_partner_absence_spec.rb +62 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 304db292215662c9a10acb7c604d279ff263a747ffa410d4306020a03f2d1d69
|
|
4
|
+
data.tar.gz: dc50e3bcecccdd41ce18855d375576cbd52747634a8d93bd161e00ffb9c3622e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f4f56f2da0be9254ca01595c8d891e8b1f8a846ccc16fa8df485c818fd2ba37fb5e888e5391085c5539fdf10f342c601963ff6a5d37e22749d986e2f16a89401
|
|
7
|
+
data.tar.gz: f8d3e0b229ba3b01749c1a5e5773ffe64ef3f5ac3cb67bdfea1046a2fd7ce984554d4d1af6c4dee729d25b67c14b00e5912678e7245b03c00d6b5212371a255b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.8] - 2026-03-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Valence: `:partner_absence` source urgency 0.2 added to `SOURCE_URGENCY`
|
|
7
|
+
- Valence: `ABSENCE_BASE_IMPORTANCE`, `ABSENCE_IMPORTANCE_SCALE`, `ABSENCE_MAX_IMPORTANCE` constants for logarithmic absence scaling
|
|
8
|
+
- Valence helper: `absence_importance(consecutive_misses)` — logarithmic importance scaling capped at 0.7
|
|
9
|
+
- Valence runner: `evaluate_partner_absence(consecutive_misses:)` — generates absence valence signal (urgency 0.2, novelty 0.1, familiarity 0.8, importance scales with misses)
|
|
10
|
+
|
|
3
11
|
## [0.1.7] - 2026-03-31
|
|
4
12
|
|
|
5
13
|
### Added
|
|
@@ -26,9 +26,15 @@ module Legion
|
|
|
26
26
|
direct_address: 0.8,
|
|
27
27
|
mesh_priority: 0.7,
|
|
28
28
|
scheduled: 0.4,
|
|
29
|
+
partner_absence: 0.2,
|
|
29
30
|
ambient: 0.1
|
|
30
31
|
}.freeze
|
|
31
32
|
|
|
33
|
+
# Partner absence importance scaling
|
|
34
|
+
ABSENCE_BASE_IMPORTANCE = 0.4
|
|
35
|
+
ABSENCE_IMPORTANCE_SCALE = 0.1
|
|
36
|
+
ABSENCE_MAX_IMPORTANCE = 0.7
|
|
37
|
+
|
|
32
38
|
# Familiarity saturation (spec Section 3.5)
|
|
33
39
|
FAMILIARITY_SATURATION = 100
|
|
34
40
|
|
|
@@ -74,6 +80,11 @@ module Legion
|
|
|
74
80
|
clamp(total / (valences.size * MAX_MAGNITUDE))
|
|
75
81
|
end
|
|
76
82
|
|
|
83
|
+
def absence_importance(consecutive_misses)
|
|
84
|
+
raw = ABSENCE_BASE_IMPORTANCE + (ABSENCE_IMPORTANCE_SCALE * Math.log(consecutive_misses + 1))
|
|
85
|
+
clamp(raw, 0.0, ABSENCE_MAX_IMPORTANCE)
|
|
86
|
+
end
|
|
87
|
+
|
|
77
88
|
def modulate_salience(base_salience, valence)
|
|
78
89
|
boost = ((valence[:urgency] * URGENCY_ATTENTION_WEIGHT) +
|
|
79
90
|
(valence[:importance] * IMPORTANCE_ATTENTION_WEIGHT) +
|
|
@@ -72,6 +72,26 @@ module Legion
|
|
|
72
72
|
{ arousal: arousal }
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
def evaluate_partner_absence(consecutive_misses: 1, **)
|
|
76
|
+
importance = Helpers::Valence.absence_importance(consecutive_misses)
|
|
77
|
+
|
|
78
|
+
valence = Helpers::Valence.new_valence(
|
|
79
|
+
urgency: 0.2,
|
|
80
|
+
importance: importance,
|
|
81
|
+
novelty: 0.1,
|
|
82
|
+
familiarity: 0.8
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
magnitude = Helpers::Valence.magnitude(valence)
|
|
86
|
+
dominant = Helpers::Valence.dominant_dimension(valence)
|
|
87
|
+
|
|
88
|
+
log.debug("[emotion] partner_absence: misses=#{consecutive_misses} " \
|
|
89
|
+
"importance=#{importance.round(2)} magnitude=#{magnitude.round(2)}")
|
|
90
|
+
|
|
91
|
+
{ valence: valence, magnitude: magnitude, dominant_dimension: dominant,
|
|
92
|
+
event: :partner_absence, consecutive_misses: consecutive_misses }
|
|
93
|
+
end
|
|
94
|
+
|
|
75
95
|
def raise_urgency_for_knowledge_vulnerability(domains_at_risk:, severity: :warning, urgency_boost: 0.3, **)
|
|
76
96
|
boost = severity.to_sym == :critical ? [urgency_boost * 1.5, 1.0].min : urgency_boost.to_f
|
|
77
97
|
signal = { urgency_hint: boost, domain_weight: 0.6, impact_scope: 0.5,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::Agentic::Affect::Emotion::Helpers::Valence do
|
|
4
|
+
describe 'SOURCE_URGENCY' do
|
|
5
|
+
it 'includes :partner_absence with urgency 0.2' do
|
|
6
|
+
expect(described_class::SOURCE_URGENCY[:partner_absence]).to eq(0.2)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe '.absence_importance' do
|
|
11
|
+
it 'returns base importance for a single miss' do
|
|
12
|
+
result = described_class.absence_importance(1)
|
|
13
|
+
expected = 0.4 + (0.1 * Math.log(2))
|
|
14
|
+
expect(result).to be_within(0.001).of(expected)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'scales logarithmically with consecutive misses' do
|
|
18
|
+
low = described_class.absence_importance(1)
|
|
19
|
+
mid = described_class.absence_importance(10)
|
|
20
|
+
high = described_class.absence_importance(50)
|
|
21
|
+
expect(mid).to be > low
|
|
22
|
+
expect(high).to be > mid
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'caps at ABSENCE_MAX_IMPORTANCE' do
|
|
26
|
+
result = described_class.absence_importance(10_000)
|
|
27
|
+
expect(result).to eq(described_class::ABSENCE_MAX_IMPORTANCE)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'returns base importance for zero misses' do
|
|
31
|
+
result = described_class.absence_importance(0)
|
|
32
|
+
expect(result).to be_within(0.001).of(described_class::ABSENCE_BASE_IMPORTANCE)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/affect/emotion/client'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Legion::Extensions::Agentic::Affect::Emotion::Runners::Valence do
|
|
6
|
+
let(:client) { Legion::Extensions::Agentic::Affect::Emotion::Client.new }
|
|
7
|
+
|
|
8
|
+
describe '#evaluate_partner_absence' do
|
|
9
|
+
it 'returns a valence with all four dimensions' do
|
|
10
|
+
result = client.evaluate_partner_absence(consecutive_misses: 1)
|
|
11
|
+
expect(result[:valence].keys).to contain_exactly(:urgency, :importance, :novelty, :familiarity)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'sets urgency to 0.2' do
|
|
15
|
+
result = client.evaluate_partner_absence(consecutive_misses: 1)
|
|
16
|
+
expect(result[:valence][:urgency]).to eq(0.2)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'sets novelty to 0.1' do
|
|
20
|
+
result = client.evaluate_partner_absence(consecutive_misses: 1)
|
|
21
|
+
expect(result[:valence][:novelty]).to eq(0.1)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'sets familiarity to 0.8' do
|
|
25
|
+
result = client.evaluate_partner_absence(consecutive_misses: 1)
|
|
26
|
+
expect(result[:valence][:familiarity]).to eq(0.8)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'tags the event as :partner_absence' do
|
|
30
|
+
result = client.evaluate_partner_absence(consecutive_misses: 1)
|
|
31
|
+
expect(result[:event]).to eq(:partner_absence)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'includes consecutive_misses in the result' do
|
|
35
|
+
result = client.evaluate_partner_absence(consecutive_misses: 5)
|
|
36
|
+
expect(result[:consecutive_misses]).to eq(5)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'returns magnitude and dominant dimension' do
|
|
40
|
+
result = client.evaluate_partner_absence(consecutive_misses: 1)
|
|
41
|
+
expect(result[:magnitude]).to be > 0.0
|
|
42
|
+
expect(result[:dominant_dimension]).to be_a(Symbol)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'increases importance with consecutive misses' do
|
|
46
|
+
low = client.evaluate_partner_absence(consecutive_misses: 1)
|
|
47
|
+
high = client.evaluate_partner_absence(consecutive_misses: 50)
|
|
48
|
+
expect(high[:valence][:importance]).to be > low[:valence][:importance]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'caps importance at ABSENCE_MAX_IMPORTANCE' do
|
|
52
|
+
helpers = Legion::Extensions::Agentic::Affect::Emotion::Helpers::Valence
|
|
53
|
+
result = client.evaluate_partner_absence(consecutive_misses: 10_000)
|
|
54
|
+
expect(result[:valence][:importance]).to eq(helpers::ABSENCE_MAX_IMPORTANCE)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'defaults to 1 consecutive miss' do
|
|
58
|
+
result = client.evaluate_partner_absence
|
|
59
|
+
expect(result[:consecutive_misses]).to eq(1)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-agentic-affect
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -312,8 +312,10 @@ files:
|
|
|
312
312
|
- spec/legion/extensions/agentic/affect/emotion/helpers/baseline_spec.rb
|
|
313
313
|
- spec/legion/extensions/agentic/affect/emotion/helpers/momentum_spec.rb
|
|
314
314
|
- spec/legion/extensions/agentic/affect/emotion/helpers/valence_direct_address_spec.rb
|
|
315
|
+
- spec/legion/extensions/agentic/affect/emotion/helpers/valence_partner_absence_spec.rb
|
|
315
316
|
- spec/legion/extensions/agentic/affect/emotion/helpers/valence_spec.rb
|
|
316
317
|
- spec/legion/extensions/agentic/affect/emotion/runners/gut_spec.rb
|
|
318
|
+
- spec/legion/extensions/agentic/affect/emotion/runners/valence_partner_absence_spec.rb
|
|
317
319
|
- spec/legion/extensions/agentic/affect/emotion/runners/valence_spec.rb
|
|
318
320
|
- spec/legion/extensions/agentic/affect/empathy/client_spec.rb
|
|
319
321
|
- spec/legion/extensions/agentic/affect/empathy/helpers/constants_spec.rb
|