lex-agentic-executive 0.1.12 → 0.2.1

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 (25) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/lib/legion/extensions/agentic/executive/goal_management/client.rb +23 -0
  4. data/lib/legion/extensions/agentic/executive/goal_management/helpers/decomposer.rb +126 -0
  5. data/lib/legion/extensions/agentic/executive/goal_management/helpers/feedback_listener.rb +63 -0
  6. data/lib/legion/extensions/agentic/executive/goal_management/helpers/goal.rb +41 -12
  7. data/lib/legion/extensions/agentic/executive/goal_management/helpers/goal_engine.rb +99 -10
  8. data/lib/legion/extensions/agentic/executive/goal_management/helpers/goal_persistence.rb +145 -0
  9. data/lib/legion/extensions/agentic/executive/goal_management/helpers/task_dispatcher.rb +109 -0
  10. data/lib/legion/extensions/agentic/executive/goal_management/runners/goal_management.rb +96 -36
  11. data/lib/legion/extensions/agentic/executive/goal_management.rb +3 -0
  12. data/lib/legion/extensions/agentic/executive/version.rb +1 -1
  13. data/lib/legion/extensions/agentic/executive/volition/client.rb +3 -1
  14. data/lib/legion/extensions/agentic/executive/volition/helpers/goal_bridge.rb +86 -0
  15. data/lib/legion/extensions/agentic/executive/volition/runners/volition.rb +13 -6
  16. data/lib/legion/extensions/agentic/executive/volition.rb +1 -0
  17. data/spec/integration/autonomous_goal_pipeline_spec.rb +107 -0
  18. data/spec/legion/extensions/agentic/executive/goal_management/helpers/decomposer_spec.rb +167 -0
  19. data/spec/legion/extensions/agentic/executive/goal_management/helpers/feedback_listener_spec.rb +104 -0
  20. data/spec/legion/extensions/agentic/executive/goal_management/helpers/goal_engine_spec.rb +32 -0
  21. data/spec/legion/extensions/agentic/executive/goal_management/helpers/goal_persistence_spec.rb +119 -0
  22. data/spec/legion/extensions/agentic/executive/goal_management/helpers/task_dispatcher_spec.rb +184 -0
  23. data/spec/legion/extensions/agentic/executive/volition/helpers/goal_bridge_spec.rb +58 -0
  24. data/spec/legion/extensions/agentic/executive/volition/runners/volition_spec.rb +26 -0
  25. metadata +12 -1
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/executive/goal_management/helpers/constants'
4
+ require 'legion/extensions/agentic/executive/goal_management/helpers/goal'
5
+ require 'legion/extensions/agentic/executive/goal_management/helpers/task_dispatcher'
6
+
7
+ RSpec.describe Legion::Extensions::Agentic::Executive::GoalManagement::Helpers::TaskDispatcher do
8
+ subject(:dispatcher) { described_class.new }
9
+
10
+ let(:goal_hash) do
11
+ {
12
+ id: 'goal-123',
13
+ content: 'ensure safety monitors are healthy',
14
+ domain: :safety,
15
+ status: :active
16
+ }
17
+ end
18
+
19
+ let(:unknown_domain_goal) do
20
+ { id: 'goal-999', content: 'do something', domain: :unknown_domain, status: :active }
21
+ end
22
+
23
+ let(:nil_domain_goal) do
24
+ { id: 'goal-nil', content: 'no domain', domain: nil, status: :active }
25
+ end
26
+
27
+ describe '#dispatch_goal' do
28
+ context 'when the domain has no runner mapping' do
29
+ it 'returns dispatched: false with reason :no_runner' do
30
+ result = dispatcher.dispatch_goal(goal: unknown_domain_goal)
31
+ expect(result[:dispatched]).to be false
32
+ expect(result[:reason]).to eq(:no_runner)
33
+ end
34
+
35
+ it 'includes the domain in the response' do
36
+ result = dispatcher.dispatch_goal(goal: unknown_domain_goal)
37
+ expect(result[:domain]).to eq(:unknown_domain)
38
+ end
39
+
40
+ it 'includes goal_id in the response' do
41
+ result = dispatcher.dispatch_goal(goal: unknown_domain_goal)
42
+ expect(result[:goal_id]).to eq('goal-999')
43
+ end
44
+ end
45
+
46
+ context 'when domain is nil' do
47
+ it 'returns dispatched: false' do
48
+ result = dispatcher.dispatch_goal(goal: nil_domain_goal)
49
+ expect(result[:dispatched]).to be false
50
+ end
51
+ end
52
+
53
+ context 'when the runner class is not loaded' do
54
+ it 'returns dispatched: false' do
55
+ result = dispatcher.dispatch_goal(goal: goal_hash)
56
+ expect(result[:dispatched]).to be false
57
+ end
58
+ end
59
+
60
+ context 'when Legion::Runner is available' do
61
+ before do
62
+ stub_const('Legion::Runner', Class.new do
63
+ def self.run(**_opts)
64
+ { success: true, status: 'task.completed', task_id: 'task-abc', result: {} }
65
+ end
66
+ end)
67
+
68
+ stub_const('Legion::Extensions::MindGrowth::Runners::Monitor', Module.new)
69
+ end
70
+
71
+ it 'dispatches a leaf goal and returns task_id' do
72
+ result = dispatcher.dispatch_goal(goal: goal_hash)
73
+ expect(result[:success]).to be true
74
+ expect(result[:task_id]).to eq('task-abc')
75
+ expect(result[:dispatched]).to be true
76
+ end
77
+
78
+ it 'includes runner_mapping in the response' do
79
+ result = dispatcher.dispatch_goal(goal: goal_hash)
80
+ expect(result[:runner_mapping]).to eq('Legion::Extensions::MindGrowth::Runners::Monitor')
81
+ end
82
+
83
+ it 'dispatches cognition goals to the current MindGrowth analyzer runner' do
84
+ stub_const('Legion::Extensions::MindGrowth::Runners::Analyzer', Module.new)
85
+ result = dispatcher.dispatch_goal(goal: goal_hash.merge(domain: :cognition))
86
+
87
+ expect(result[:dispatched]).to be true
88
+ expect(result[:runner_mapping]).to eq('Legion::Extensions::MindGrowth::Runners::Analyzer')
89
+ end
90
+
91
+ it 'includes goal_id in the response' do
92
+ result = dispatcher.dispatch_goal(goal: goal_hash)
93
+ expect(result[:goal_id]).to eq('goal-123')
94
+ end
95
+
96
+ it 'sets success: false when runner does not return task.completed status' do
97
+ stub_const('Legion::Runner', Class.new do
98
+ def self.run(**_opts)
99
+ { success: false, status: 'task.failed', task_id: nil, result: {} }
100
+ end
101
+ end)
102
+
103
+ result = dispatcher.dispatch_goal(goal: goal_hash)
104
+ expect(result[:dispatched]).to be true
105
+ expect(result[:success]).to be false
106
+ end
107
+ end
108
+
109
+ context 'when a client_class domain is used (introspection)' do
110
+ let(:introspection_goal) do
111
+ { id: 'goal-456', content: 'check volition', domain: :introspection, status: :active }
112
+ end
113
+
114
+ context 'when client class is not available' do
115
+ before do
116
+ hide_const('Legion::Extensions::Agentic::Executive::Volition::Client')
117
+ end
118
+
119
+ it 'returns dispatched: false' do
120
+ result = dispatcher.dispatch_goal(goal: introspection_goal)
121
+ expect(result[:dispatched]).to be false
122
+ end
123
+ end
124
+
125
+ context 'when client class is available' do
126
+ before do
127
+ client_double = instance_double('VolitionClient',
128
+ volition_status: { status: 'task.completed', task_id: 'task-xyz' })
129
+ client_class = class_double('Legion::Extensions::Agentic::Executive::Volition::Client',
130
+ new: client_double)
131
+ stub_const('Legion::Extensions::Agentic::Executive::Volition::Client', client_class)
132
+ end
133
+
134
+ it 'dispatches via client and returns dispatched: true' do
135
+ result = dispatcher.dispatch_goal(goal: introspection_goal)
136
+ expect(result[:dispatched]).to be true
137
+ expect(result[:task_id]).to eq('task-xyz')
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ describe 'DOMAIN_RUNNERS constant' do
144
+ it 'defines a safety mapping' do
145
+ expect(described_class::DOMAIN_RUNNERS).to have_key(:safety)
146
+ end
147
+
148
+ it 'defines a cognition mapping' do
149
+ expect(described_class::DOMAIN_RUNNERS).to have_key(:cognition)
150
+ end
151
+
152
+ it 'defines a perception mapping' do
153
+ expect(described_class::DOMAIN_RUNNERS).to have_key(:perception)
154
+ end
155
+
156
+ it 'defines an introspection mapping' do
157
+ expect(described_class::DOMAIN_RUNNERS).to have_key(:introspection)
158
+ end
159
+
160
+ it 'is frozen' do
161
+ expect(described_class::DOMAIN_RUNNERS).to be_frozen
162
+ end
163
+
164
+ it 'safety mapping has a runner_class' do
165
+ expect(described_class::DOMAIN_RUNNERS[:safety]).to have_key(:runner_class)
166
+ end
167
+
168
+ it 'introspection mapping has a client_class' do
169
+ expect(described_class::DOMAIN_RUNNERS[:introspection]).to have_key(:client_class)
170
+ end
171
+
172
+ it 'all mappings have a function' do
173
+ described_class::DOMAIN_RUNNERS.each_value do |mapping|
174
+ expect(mapping).to have_key(:function)
175
+ end
176
+ end
177
+
178
+ it 'all mappings have an args_builder callable' do
179
+ described_class::DOMAIN_RUNNERS.each_value do |mapping|
180
+ expect(mapping[:args_builder]).to respond_to(:call)
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/executive/goal_management/client'
4
+ require 'legion/extensions/agentic/executive/volition/helpers/goal_bridge'
5
+
6
+ RSpec.describe Legion::Extensions::Agentic::Executive::Volition::Helpers::GoalBridge do
7
+ let(:goal_client) { Legion::Extensions::Agentic::Executive::GoalManagement::Client.new }
8
+ let(:bridge) { described_class.new(goal_client: goal_client) }
9
+
10
+ describe '#bridge_intentions' do
11
+ let(:intentions) do
12
+ [
13
+ { intention_id: 'int-001', drive: :curiosity, domain: :cognition,
14
+ goal: 'explore knowledge gap in perception', salience: 0.8,
15
+ state: :active, context: {} },
16
+ { intention_id: 'int-002', drive: :corrective, domain: :safety,
17
+ goal: 'fix degraded safety monitor', salience: 0.6,
18
+ state: :active, context: {} }
19
+ ]
20
+ end
21
+
22
+ it 'creates a goal for each active intention' do
23
+ result = bridge.bridge_intentions(intentions)
24
+ expect(result[:bridged]).to eq(2)
25
+ expect(result[:goal_ids].size).to eq(2)
26
+ expect(goal_client.list_active_goals[:goals]).to be_empty
27
+ proposed = goal_client.goal_status[:statuses][:proposed]
28
+ expect(proposed).to eq(2)
29
+ end
30
+
31
+ it 'maps salience to goal priority' do
32
+ result = bridge.bridge_intentions(intentions)
33
+ goals = result[:goal_ids].map { |id| goal_client.get_goal_tree(goal_id: id) }
34
+ priorities = goals.map { |g| g[:tree][:priority] }
35
+ expect(priorities.first).to be > priorities.last
36
+ end
37
+
38
+ it 'skips non-active intentions' do
39
+ intentions[1][:state] = :suspended
40
+ result = bridge.bridge_intentions(intentions)
41
+ expect(result[:bridged]).to eq(1)
42
+ expect(result[:skipped]).to eq(1)
43
+ end
44
+
45
+ it 'skips duplicate intentions already bridged' do
46
+ bridge.bridge_intentions(intentions)
47
+ result = bridge.bridge_intentions(intentions)
48
+ expect(result[:bridged]).to eq(0)
49
+ expect(result[:duplicates]).to eq(2)
50
+ end
51
+
52
+ it 'returns empty result for empty input' do
53
+ result = bridge.bridge_intentions([])
54
+ expect(result[:bridged]).to eq(0)
55
+ expect(result[:goal_ids]).to be_empty
56
+ end
57
+ end
58
+ end
@@ -289,4 +289,30 @@ RSpec.describe Legion::Extensions::Agentic::Executive::Volition::Runners::Voliti
289
289
  expect(%i[pushed duplicate]).to include(second[:result])
290
290
  end
291
291
  end
292
+
293
+ describe '.form_intentions with goal bridging' do
294
+ let(:goal_client) { Legion::Extensions::Agentic::Executive::GoalManagement::Client.new }
295
+ let(:bridge) { Legion::Extensions::Agentic::Executive::Volition::Helpers::GoalBridge.new(goal_client: goal_client) }
296
+ let(:client) { Legion::Extensions::Agentic::Executive::Volition::Client.new(goal_bridge: bridge) }
297
+
298
+ let(:tick_results) do
299
+ { working_memory_integration: { curiosity_intensity: 0.7, active_wonders: 3 } }
300
+ end
301
+ let(:cognitive_state) do
302
+ { curiosity: { intensity: 0.7, active_count: 3, top_question: 'Why?' } }
303
+ end
304
+
305
+ it 'bridges new intentions to goals' do
306
+ result = client.form_intentions(tick_results: tick_results, cognitive_state: cognitive_state)
307
+ expect(result).to have_key(:bridge_result)
308
+ expect(result[:bridge_result][:bridged]).to be >= 0
309
+ end
310
+
311
+ it 'works without a goal bridge configured' do
312
+ client_no_bridge = Legion::Extensions::Agentic::Executive::Volition::Client.new
313
+ result = client_no_bridge.form_intentions(tick_results: tick_results, cognitive_state: cognitive_state)
314
+ expect(result).to have_key(:drives)
315
+ expect(result).not_to have_key(:bridge_result)
316
+ end
317
+ end
292
318
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-agentic-executive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -263,8 +263,12 @@ files:
263
263
  - lib/legion/extensions/agentic/executive/goal_management.rb
264
264
  - lib/legion/extensions/agentic/executive/goal_management/client.rb
265
265
  - lib/legion/extensions/agentic/executive/goal_management/helpers/constants.rb
266
+ - lib/legion/extensions/agentic/executive/goal_management/helpers/decomposer.rb
267
+ - lib/legion/extensions/agentic/executive/goal_management/helpers/feedback_listener.rb
266
268
  - lib/legion/extensions/agentic/executive/goal_management/helpers/goal.rb
267
269
  - lib/legion/extensions/agentic/executive/goal_management/helpers/goal_engine.rb
270
+ - lib/legion/extensions/agentic/executive/goal_management/helpers/goal_persistence.rb
271
+ - lib/legion/extensions/agentic/executive/goal_management/helpers/task_dispatcher.rb
268
272
  - lib/legion/extensions/agentic/executive/goal_management/runners/goal_management.rb
269
273
  - lib/legion/extensions/agentic/executive/goal_management/version.rb
270
274
  - lib/legion/extensions/agentic/executive/inertia.rb
@@ -322,6 +326,7 @@ files:
322
326
  - lib/legion/extensions/agentic/executive/volition/client.rb
323
327
  - lib/legion/extensions/agentic/executive/volition/helpers/constants.rb
324
328
  - lib/legion/extensions/agentic/executive/volition/helpers/drive_synthesizer.rb
329
+ - lib/legion/extensions/agentic/executive/volition/helpers/goal_bridge.rb
325
330
  - lib/legion/extensions/agentic/executive/volition/helpers/intention.rb
326
331
  - lib/legion/extensions/agentic/executive/volition/helpers/intention_stack.rb
327
332
  - lib/legion/extensions/agentic/executive/volition/runners/volition.rb
@@ -333,6 +338,7 @@ files:
333
338
  - lib/legion/extensions/agentic/executive/working_memory/helpers/constants.rb
334
339
  - lib/legion/extensions/agentic/executive/working_memory/runners/working_memory.rb
335
340
  - lib/legion/extensions/agentic/executive/working_memory/version.rb
341
+ - spec/integration/autonomous_goal_pipeline_spec.rb
336
342
  - spec/legion/extensions/agentic/executive/autopilot/client_spec.rb
337
343
  - spec/legion/extensions/agentic/executive/autopilot/cognitive_autopilot_spec.rb
338
344
  - spec/legion/extensions/agentic/executive/autopilot/helpers/autopilot_engine_spec.rb
@@ -402,8 +408,12 @@ files:
402
408
  - spec/legion/extensions/agentic/executive/goal_management/client_spec.rb
403
409
  - spec/legion/extensions/agentic/executive/goal_management/goal_management_spec.rb
404
410
  - spec/legion/extensions/agentic/executive/goal_management/helpers/constants_spec.rb
411
+ - spec/legion/extensions/agentic/executive/goal_management/helpers/decomposer_spec.rb
412
+ - spec/legion/extensions/agentic/executive/goal_management/helpers/feedback_listener_spec.rb
405
413
  - spec/legion/extensions/agentic/executive/goal_management/helpers/goal_engine_spec.rb
414
+ - spec/legion/extensions/agentic/executive/goal_management/helpers/goal_persistence_spec.rb
406
415
  - spec/legion/extensions/agentic/executive/goal_management/helpers/goal_spec.rb
416
+ - spec/legion/extensions/agentic/executive/goal_management/helpers/task_dispatcher_spec.rb
407
417
  - spec/legion/extensions/agentic/executive/goal_management/runners/goal_management_spec.rb
408
418
  - spec/legion/extensions/agentic/executive/inertia/helpers/belief_spec.rb
409
419
  - spec/legion/extensions/agentic/executive/inertia/helpers/inertia_engine_spec.rb
@@ -442,6 +452,7 @@ files:
442
452
  - spec/legion/extensions/agentic/executive/volition/client_spec.rb
443
453
  - spec/legion/extensions/agentic/executive/volition/helpers/constants_spec.rb
444
454
  - spec/legion/extensions/agentic/executive/volition/helpers/drive_synthesizer_spec.rb
455
+ - spec/legion/extensions/agentic/executive/volition/helpers/goal_bridge_spec.rb
445
456
  - spec/legion/extensions/agentic/executive/volition/helpers/intention_spec.rb
446
457
  - spec/legion/extensions/agentic/executive/volition/helpers/intention_stack_spec.rb
447
458
  - spec/legion/extensions/agentic/executive/volition/runners/volition_spec.rb