lex-agentic-affect 0.1.12 → 0.1.14

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.
Files changed (22) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +1 -1
  4. data/lib/legion/extensions/agentic/affect/emotion/actors/momentum_decay.rb +1 -1
  5. data/lib/legion/extensions/agentic/affect/emotion/client.rb +1 -2
  6. data/lib/legion/extensions/agentic/affect/emotion/runners/gut.rb +2 -2
  7. data/lib/legion/extensions/agentic/affect/emotion/runners/valence.rb +12 -1
  8. data/lib/legion/extensions/agentic/affect/empathy/actors/decay_models.rb +1 -1
  9. data/lib/legion/extensions/agentic/affect/fatigue/actors/update_fatigue.rb +1 -1
  10. data/lib/legion/extensions/agentic/affect/flow/actors/update_flow.rb +1 -1
  11. data/lib/legion/extensions/agentic/affect/interoception/actors/decay.rb +1 -1
  12. data/lib/legion/extensions/agentic/affect/mood/actors/update_mood.rb +1 -1
  13. data/lib/legion/extensions/agentic/affect/reappraisal/actors/auto_regulate.rb +1 -1
  14. data/lib/legion/extensions/agentic/affect/regulation/actors/regulate_emotion.rb +1 -1
  15. data/lib/legion/extensions/agentic/affect/resilience/actors/update_resilience.rb +1 -1
  16. data/lib/legion/extensions/agentic/affect/resonance/helpers/resonance_engine.rb +2 -4
  17. data/lib/legion/extensions/agentic/affect/somatic_marker/actors/decay.rb +1 -1
  18. data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/body_state.rb +3 -3
  19. data/lib/legion/extensions/agentic/affect/version.rb +1 -1
  20. data/spec/legion/extensions/agentic/affect/emotion/runners/gut_spec.rb +22 -0
  21. data/spec/legion/extensions/agentic/affect/emotion/runners/valence_spec.rb +8 -0
  22. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1451732e09f9aaebe3c833f3e9edf5923d0081c262d5fa3f1d0ad1392bbf660
4
- data.tar.gz: deaa140090d9630d0ca749ed5a180e278f5ae8a0fe76b1bd840d1d949051990b
3
+ metadata.gz: 9223ccb51846d7da0c831d72bc85524df797f98999541719f8ec597a13213b29
4
+ data.tar.gz: a0a68749e8576d34a5770818a67db14c6e1c9aafee1432f0115c809bf3285561
5
5
  SHA512:
6
- metadata.gz: 5a25e9fb7182dbeecc0c9e290ac6f3f7ba8f2be0b1d16d777b4502f63e98fe827b4ec0af60d303bbd83b10c22baabaec3df015e236bce4aa2c0b042a6cf710ed
7
- data.tar.gz: d0c7d9f674583d01790199fa0750b036b64457b7a1a37900cabbad600be4a7e3c01bca43d254466ad848cdfd5a0d6c07aabdf43328d1b083263f59ef52e04e63
6
+ metadata.gz: c18f597848a6ac85c6f85a5d61b6b21cc431d003eddd0b273fa9908410be16941c200a1bc383b7bfca394d2cec444ce898ad3f2795705161cfe2a11fa1a9c7b0
7
+ data.tar.gz: 23f3308edf09101470dc0615b3dd82d9e2a7edd9faa27226f54d065933eae92831c5aa78e0d8f4c47aa1a37d33712d364b9b81213ddf8604094c0d1988e8f081
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.14] - 2026-10-29
4
+ ### Fixed
5
+ - Decay emotional momentum toward rest instead of introducing synthetic valence and arousal during idle maintenance.
6
+
7
+ ## [0.1.13] - 2026-05-07
8
+ ### Fixed
9
+ - Valence evaluation now lazily initializes and updates domain signal counts so familiarity scoring works in runner-host usage.
10
+
3
11
  ## [0.1.12] - 2026-04-22
4
12
  ### Added
5
13
  - 6 new maintenance actors: Mood::Actor::UpdateMood (60s), Flow::Actor::UpdateFlow (30s), Fatigue::Actor::UpdateFatigue (60s), Resilience::Actor::UpdateResilience (120s), Regulation::Actor::RegulateEmotion (60s), Empathy::Actor::DecayModels (300s)
data/README.md CHANGED
@@ -5,7 +5,7 @@ Domain consolidation gem for emotion, affect, and motivational processing. Bundl
5
5
  ## Overview
6
6
 
7
7
  **Gem**: `lex-agentic-affect`
8
- **Version**: 0.1.12
8
+ **Version**: 0.1.14
9
9
  **Namespace**: `Legion::Extensions::Agentic::Affect`
10
10
 
11
11
  ## Sub-Modules
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module Emotion
10
10
  module Actor
11
- class MomentumDecay < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class MomentumDecay < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::Emotion::Runners::Gut
14
14
  end
@@ -19,11 +19,10 @@ module Legion
19
19
  def initialize(**)
20
20
  @emotion_baseline = Helpers::Baseline.new
21
21
  @emotion_momentum = Helpers::Momentum.new
22
- @domain_counts = Hash.new(0)
23
22
  end
24
23
 
25
24
  def track_domain(domain)
26
- @domain_counts[domain] += 1
25
+ domain_counts[domain] += 1
27
26
  end
28
27
 
29
28
  private
@@ -39,9 +39,9 @@ module Legion
39
39
  end
40
40
 
41
41
  def decay_momentum(**)
42
- neutral = { urgency: 0.5, importance: 0.5, novelty: 0.5, familiarity: 0.5 }
42
+ neutral = Helpers::Valence.new_valence
43
43
  momentum = emotion_momentum
44
- momentum.update(neutral, 0.5)
44
+ momentum.update(neutral, 0.0)
45
45
  stability = momentum.stability
46
46
 
47
47
  log.debug("[emotion] momentum decay: stability=#{stability.round(2)}")
@@ -31,6 +31,7 @@ module Legion
31
31
  novelty: novelty_raw, familiarity: familiarity_raw }[dim]
32
32
  baseline.update(dim, raw)
33
33
  end
34
+ record_domain_signal(domain)
34
35
 
35
36
  magnitude = Helpers::Valence.magnitude(valence)
36
37
  dominant = Helpers::Valence.dominant_dimension(valence)
@@ -111,6 +112,16 @@ module Legion
111
112
  @emotion_baseline ||= Helpers::Baseline.new
112
113
  end
113
114
 
115
+ def domain_counts
116
+ @domain_counts ||= Hash.new(0)
117
+ end
118
+
119
+ def record_domain_signal(domain)
120
+ return unless domain
121
+
122
+ domain_counts[domain] += 1
123
+ end
124
+
114
125
  def compute_urgency(signal, source_type, deadline)
115
126
  deadline_urgency = 0.0
116
127
  if deadline
@@ -141,7 +152,7 @@ module Legion
141
152
  end
142
153
 
143
154
  def compute_familiarity(domain)
144
- signal_count = @domain_counts&.fetch(domain, 0) || 0
155
+ signal_count = domain_counts.fetch(domain, 0)
145
156
  Helpers::Valence.clamp(signal_count.to_f / Helpers::Valence::FAMILIARITY_SATURATION)
146
157
  end
147
158
  end
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module Empathy
10
10
  module Actor
11
- class DecayModels < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class DecayModels < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::Empathy::Runners::Empathy
14
14
  end
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module Fatigue
10
10
  module Actor
11
- class UpdateFatigue < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class UpdateFatigue < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::Fatigue::Runners::Fatigue
14
14
  end
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module Flow
10
10
  module Actor
11
- class UpdateFlow < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class UpdateFlow < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::Flow::Runners::Flow
14
14
  end
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module Interoception
10
10
  module Actor
11
- class Decay < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class Decay < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::Interoception::Runners::Interoception
14
14
  end
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module Mood
10
10
  module Actor
11
- class UpdateMood < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class UpdateMood < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::Mood::Runners::Mood
14
14
  end
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module Reappraisal
10
10
  module Actor
11
- class AutoRegulate < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class AutoRegulate < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::Reappraisal::Runners::CognitiveReappraisal
14
14
  end
@@ -12,7 +12,7 @@ module Legion
12
12
  # Calls update_emotional_regulation which performs skill decay — no live emotion
13
13
  # inputs are required. regulate_emotion itself requires emotion_magnitude: and
14
14
  # cannot be safely invoked as a background tick without a signal source.
15
- class RegulateEmotion < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
15
+ class RegulateEmotion < Legion::Extensions::Actors::Every
16
16
  def runner_class
17
17
  Legion::Extensions::Agentic::Affect::Regulation::Runners::EmotionalRegulation
18
18
  end
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module Resilience
10
10
  module Actor
11
- class UpdateResilience < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class UpdateResilience < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::Resilience::Runners::Resilience
14
14
  end
@@ -73,10 +73,9 @@ module Legion
73
73
  def resonate_with(match, normalized)
74
74
  category = @categories[match[:id]]
75
75
  category.update_prototype!(input: normalized)
76
- # rubocop:disable Legion/HelperMigration/DirectLogging
76
+ # rubocop:disable-next Legion/HelperMigration/DirectLogging
77
77
  Legion::Logging.debug("[cognitive_resonance] resonance with category #{match[:id][0..7]} " \
78
78
  "quality=#{match[:quality].round(3)} vigilance=#{@vigilance.round(3)}")
79
- # rubocop:enable Legion/HelperMigration/DirectLogging
80
79
  {
81
80
  outcome: :resonance,
82
81
  category_id: match[:id],
@@ -90,10 +89,9 @@ module Legion
90
89
  prune_if_full!
91
90
  category = Category.new(prototype: normalized)
92
91
  @categories[category.id] = category
93
- # rubocop:disable Legion/HelperMigration/DirectLogging
92
+ # rubocop:disable-next Legion/HelperMigration/DirectLogging
94
93
  Legion::Logging.debug("[cognitive_resonance] new category #{category.id[0..7]} " \
95
94
  "total=#{@categories.size} vigilance=#{@vigilance.round(3)}")
96
- # rubocop:enable Legion/HelperMigration/DirectLogging
97
95
  {
98
96
  outcome: :new_category,
99
97
  category_id: category.id,
@@ -8,7 +8,7 @@ module Legion
8
8
  module Affect
9
9
  module SomaticMarker
10
10
  module Actor
11
- class Decay < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
11
+ class Decay < Legion::Extensions::Actors::Every
12
12
  def runner_class
13
13
  Legion::Extensions::Agentic::Affect::SomaticMarker::Runners::SomaticMarker
14
14
  end
@@ -19,9 +19,9 @@ module Legion
19
19
  end
20
20
 
21
21
  def update(arousal: nil, tension: nil, comfort: nil, gut_signal: nil)
22
- @arousal = arousal.clamp(0.0, 1.0) if arousal
23
- @tension = tension.clamp(0.0, 1.0) if tension
24
- @comfort = comfort.clamp(0.0, 1.0) if comfort
22
+ @arousal = arousal.clamp(0.0, 1.0) if arousal
23
+ @tension = tension.clamp(0.0, 1.0) if tension
24
+ @comfort = comfort.clamp(0.0, 1.0) if comfort
25
25
  @gut_signal = gut_signal.clamp(-1.0, 1.0) if gut_signal
26
26
  end
27
27
 
@@ -4,7 +4,7 @@ module Legion
4
4
  module Extensions
5
5
  module Agentic
6
6
  module Affect
7
- VERSION = '0.1.12'
7
+ VERSION = '0.1.14'
8
8
  end
9
9
  end
10
10
  end
@@ -55,6 +55,28 @@ RSpec.describe Legion::Extensions::Agentic::Affect::Emotion::Runners::Gut do
55
55
  end
56
56
 
57
57
  describe '#decay_momentum' do
58
+ it 'does not generate arousal without an emotional signal' do
59
+ 3.times { client.decay_momentum }
60
+
61
+ state = client.emotional_state[:momentum]
62
+ expect(state[:arousal_ema]).to eq(0.0)
63
+ expect(state[:valence_ema].values).to all(eq(0.0))
64
+ end
65
+
66
+ it 'reduces a low-arousal signal toward rest rather than increasing it' do
67
+ valence = valence_mod.new_valence(urgency: 0.1, importance: 0.1, novelty: 0.1, familiarity: 0.1)
68
+ client.gut_instinct(valences: [valence])
69
+ before = client.emotional_state[:momentum]
70
+
71
+ client.decay_momentum
72
+
73
+ after = client.emotional_state[:momentum]
74
+ expect(after[:arousal_ema]).to be < before[:arousal_ema]
75
+ valence_mod::DIMENSIONS.each do |dimension|
76
+ expect(after[:valence_ema][dimension]).to be < before[:valence_ema][dimension]
77
+ end
78
+ end
79
+
58
80
  it 'returns decayed: true' do
59
81
  result = client.decay_momentum
60
82
  expect(result[:decayed]).to be true
@@ -32,6 +32,14 @@ RSpec.describe Legion::Extensions::Agentic::Affect::Emotion::Runners::Valence do
32
32
  with_deadline = client.evaluate_valence(signal: {}, deadline: Time.now.utc + 60)
33
33
  expect(with_deadline[:valence][:urgency]).to be >= no_deadline[:valence][:urgency]
34
34
  end
35
+
36
+ it 'initializes and updates domain counts in runner-host usage' do
37
+ expect(client.instance_variable_get(:@domain_counts)).to be_nil
38
+
39
+ client.evaluate_valence(signal: {}, domain: :ops)
40
+
41
+ expect(client.instance_variable_get(:@domain_counts)[:ops]).to eq(1)
42
+ end
35
43
  end
36
44
 
37
45
  describe '#aggregate_valences' do
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.12
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity