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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/lib/legion/extensions/agentic/executive/goal_management/client.rb +23 -0
- data/lib/legion/extensions/agentic/executive/goal_management/helpers/decomposer.rb +126 -0
- data/lib/legion/extensions/agentic/executive/goal_management/helpers/feedback_listener.rb +63 -0
- data/lib/legion/extensions/agentic/executive/goal_management/helpers/goal.rb +41 -12
- data/lib/legion/extensions/agentic/executive/goal_management/helpers/goal_engine.rb +99 -10
- data/lib/legion/extensions/agentic/executive/goal_management/helpers/goal_persistence.rb +145 -0
- data/lib/legion/extensions/agentic/executive/goal_management/helpers/task_dispatcher.rb +109 -0
- data/lib/legion/extensions/agentic/executive/goal_management/runners/goal_management.rb +96 -36
- data/lib/legion/extensions/agentic/executive/goal_management.rb +3 -0
- data/lib/legion/extensions/agentic/executive/version.rb +1 -1
- data/lib/legion/extensions/agentic/executive/volition/client.rb +3 -1
- data/lib/legion/extensions/agentic/executive/volition/helpers/goal_bridge.rb +86 -0
- data/lib/legion/extensions/agentic/executive/volition/runners/volition.rb +13 -6
- data/lib/legion/extensions/agentic/executive/volition.rb +1 -0
- data/spec/integration/autonomous_goal_pipeline_spec.rb +107 -0
- data/spec/legion/extensions/agentic/executive/goal_management/helpers/decomposer_spec.rb +167 -0
- data/spec/legion/extensions/agentic/executive/goal_management/helpers/feedback_listener_spec.rb +104 -0
- data/spec/legion/extensions/agentic/executive/goal_management/helpers/goal_engine_spec.rb +32 -0
- data/spec/legion/extensions/agentic/executive/goal_management/helpers/goal_persistence_spec.rb +119 -0
- data/spec/legion/extensions/agentic/executive/goal_management/helpers/task_dispatcher_spec.rb +184 -0
- data/spec/legion/extensions/agentic/executive/volition/helpers/goal_bridge_spec.rb +58 -0
- data/spec/legion/extensions/agentic/executive/volition/runners/volition_spec.rb +26 -0
- 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
|
|
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
|