lex-agentic-executive 0.1.0 → 0.1.4
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 +15 -0
- data/README.md +50 -3
- data/lib/legion/extensions/agentic/executive/chunking/helpers/constants.rb +1 -1
- data/lib/legion/extensions/agentic/executive/disengagement/helpers/disengagement_engine.rb +5 -0
- data/lib/legion/extensions/agentic/executive/disengagement/version.rb +1 -1
- data/lib/legion/extensions/agentic/executive/dissonance_resolution/helpers/resolution_engine.rb +2 -0
- data/lib/legion/extensions/agentic/executive/dissonance_resolution/version.rb +1 -1
- data/lib/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine.rb +2 -0
- data/lib/legion/extensions/agentic/executive/dual_process/version.rb +1 -1
- data/lib/legion/extensions/agentic/executive/inhibition/helpers/inhibition_store.rb +2 -0
- data/lib/legion/extensions/agentic/executive/inhibition/version.rb +1 -1
- data/lib/legion/extensions/agentic/executive/version.rb +1 -1
- data/lib/legion/extensions/agentic/executive/volition/runners/volition.rb +32 -0
- data/lib/legion/extensions/agentic/executive/working_memory/helpers/constants.rb +1 -1
- data/lib/legion/extensions/agentic/executive/working_memory/version.rb +1 -1
- data/spec/legion/extensions/agentic/executive/chunking/helpers/chunking_engine_spec.rb +1 -1
- data/spec/legion/extensions/agentic/executive/chunking/helpers/constants_spec.rb +2 -2
- data/spec/legion/extensions/agentic/executive/chunking/runners/cognitive_chunking_spec.rb +1 -1
- data/spec/legion/extensions/agentic/executive/disengagement/helpers/disengagement_engine_spec.rb +13 -0
- data/spec/legion/extensions/agentic/executive/dissonance_resolution/helpers/resolution_engine_spec.rb +13 -0
- data/spec/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine_spec.rb +15 -0
- data/spec/legion/extensions/agentic/executive/inhibition/helpers/inhibition_store_spec.rb +12 -0
- data/spec/legion/extensions/agentic/executive/volition/runners/volition_spec.rb +55 -0
- data/spec/legion/extensions/agentic/executive/working_memory/client_spec.rb +3 -3
- data/spec/legion/extensions/agentic/executive/working_memory/helpers/constants_spec.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 23b732c1b95a31e26ca8ac967dc4c6902ab7164afdd5756f8e61ddb9306c86b8
|
|
4
|
+
data.tar.gz: 2c0de464889108f22b0602433f7d1903a9f46523733e1dc3a644126a34ba70f3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e5f64ae22b38be241957bfc1fe828ec2060ab4241765e8927353123bfb6af4042997f885ee8a831ffce3680a0f29715859a8509c96d8a853461acc18892c18bd
|
|
7
|
+
data.tar.gz: 5bc0e25e7e2c76c4ff513337288d47a88b2ef02bc5a5ccdee24f4b2569700b3555b6c1c19a4024656cccfac9d1ceceaa1adccef5fe976f379c69c2dd5a3e62d9
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.1.3] - 2026-03-21
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- Working memory CAPACITY reduced from 7 to 4 (Cowan 2001)
|
|
9
|
+
- Chunking WORKING_MEMORY_CAPACITY updated from 7 to 4
|
|
10
|
+
- Effective max remains 7 via CHUNK_BONUS (4 base + 3 bonus)
|
|
11
|
+
|
|
12
|
+
## [0.1.1] - 2026-03-18
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Enforce IMPULSE_TYPES validation in InhibitionStore#create_impulse (returns nil for invalid type)
|
|
16
|
+
- Enforce STRATEGIES validation in ResolutionEngine#apply_strategy (returns nil for invalid strategy)
|
|
17
|
+
- Enforce DISENGAGE_REASONS validation in DisengagementEngine#disengage_goal (raises ArgumentError)
|
|
18
|
+
- Enforce DECISION_OUTCOMES validation in DualProcessEngine#record_outcome (returns failure hash)
|
|
19
|
+
|
|
5
20
|
## [0.1.0] - 2026-03-18
|
|
6
21
|
|
|
7
22
|
### Added
|
data/README.md
CHANGED
|
@@ -1,13 +1,60 @@
|
|
|
1
1
|
# lex-agentic-executive
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Domain consolidation gem for executive function, goal management, planning, and cognitive control. Bundles 23 source extensions into one loadable unit under `Legion::Extensions::Agentic::Executive`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Gem**: `lex-agentic-executive`
|
|
8
|
+
**Version**: 0.1.1
|
|
9
|
+
**Namespace**: `Legion::Extensions::Agentic::Executive`
|
|
10
|
+
|
|
11
|
+
## Sub-Modules
|
|
12
|
+
|
|
13
|
+
| Sub-Module | Source Gem | Purpose |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `Executive::Control` | `lex-cognitive-control` | Conflict monitoring, error detection, adaptive control signals |
|
|
16
|
+
| `Executive::ExecutiveFunction` | `lex-executive-function` | Miyake three-factor model: updating, flexibility, inhibition |
|
|
17
|
+
| `Executive::GoalManagement` | `lex-goal-management` | Hierarchical goal registry — decomposition, priority, lifecycle |
|
|
18
|
+
| `Executive::Inhibition` | `lex-inhibition` | Stop-signal model, prepotent response suppression |
|
|
19
|
+
| `Executive::Planning` | `lex-planning` | Goal-directed plan management — dependency graphs, replan limit |
|
|
20
|
+
| `Executive::Volition` | `lex-volition` | Five drives synthesized into intention stack — maps to `action_selection` tick phase |
|
|
21
|
+
| `Executive::WorkingMemory` | `lex-working-memory` | Baddeley & Hitch — capacity-limited buffer, verbal/spatial/episodic channels |
|
|
22
|
+
| `Executive::Flexibility` | `lex-cognitive-flexibility` | Cognitive flexibility — task switching, mental set shifting |
|
|
23
|
+
| `Executive::FlexibilityTraining` | `lex-cognitive-flexibility-training` | Structured training for cognitive flexibility improvement |
|
|
24
|
+
| `Executive::Load` | `lex-cognitive-load` | Sweller three-component model — intrinsic/extraneous/germane load |
|
|
25
|
+
| `Executive::LoadBalancing` | `lex-cognitive-load-balancing` | Load distribution across cognitive resources |
|
|
26
|
+
| `Executive::Disengagement` | `lex-cognitive-disengagement` | Controlled disengagement from tasks or mental sets |
|
|
27
|
+
| `Executive::Triage` | `lex-cognitive-triage` | Priority-based task selection under resource constraints |
|
|
28
|
+
| `Executive::Chunking` | `lex-cognitive-chunking` | Information compression into manageable units |
|
|
29
|
+
| `Executive::Inertia` | `lex-cognitive-inertia` | Resistance to switching — persistence in current cognitive mode |
|
|
30
|
+
| `Executive::Dwell` | `lex-cognitive-dwell` | Sustained focus on a single topic or problem |
|
|
31
|
+
| `Executive::Autopilot` | `lex-cognitive-autopilot` | Habitual/automatic processing mode |
|
|
32
|
+
| `Executive::DissonanceResolution` | `lex-cognitive-dissonance-resolution` | Resolution strategies for cognitive dissonance |
|
|
33
|
+
| `Executive::Compass` | `lex-cognitive-compass` | Goal-direction and navigation toward targets |
|
|
34
|
+
| `Executive::DecisionFatigue` | `lex-decision-fatigue` | Decision quality degradation after sustained choices |
|
|
35
|
+
| `Executive::DualProcess` | `lex-dual-process` | Kahneman System 1/System 2 routing |
|
|
36
|
+
| `Executive::ProspectiveMemory` | `lex-prospective-memory` | Memory for future intentions — reminder management |
|
|
37
|
+
| `Executive::CognitiveDebt` | `lex-cognitive-debt` | Accumulated cognitive obligations and deferred processing |
|
|
38
|
+
|
|
39
|
+
## Actors
|
|
40
|
+
|
|
41
|
+
- `Executive::ExecutiveFunction::Actors::Recovery` — interval actor, runs executive function recovery cycle
|
|
42
|
+
- `Executive::Flexibility::Actors::Tick` — interval actor, processes cognitive flexibility tick
|
|
8
43
|
|
|
9
44
|
## Installation
|
|
10
45
|
|
|
11
46
|
```ruby
|
|
12
47
|
gem 'lex-agentic-executive'
|
|
13
48
|
```
|
|
49
|
+
|
|
50
|
+
## Development
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
bundle install
|
|
54
|
+
bundle exec rspec # 2067 examples, 0 failures
|
|
55
|
+
bundle exec rubocop # 0 offenses
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
MIT
|
|
@@ -9,7 +9,7 @@ module Legion
|
|
|
9
9
|
module Constants
|
|
10
10
|
MAX_ITEMS = 500
|
|
11
11
|
MAX_CHUNKS = 200
|
|
12
|
-
WORKING_MEMORY_CAPACITY =
|
|
12
|
+
WORKING_MEMORY_CAPACITY = 4 # Cowan (2001) core capacity
|
|
13
13
|
CAPACITY_VARIANCE = 2 # +/- 2
|
|
14
14
|
DEFAULT_COHERENCE = 0.5
|
|
15
15
|
COHERENCE_BOOST = 0.08
|
|
@@ -42,6 +42,11 @@ module Legion
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def disengage_goal(goal_id:, reason:)
|
|
45
|
+
unless Constants::DISENGAGE_REASONS.include?(reason.to_sym)
|
|
46
|
+
raise ArgumentError,
|
|
47
|
+
"invalid reason: #{reason.inspect}, must be one of #{Constants::DISENGAGE_REASONS}"
|
|
48
|
+
end
|
|
49
|
+
|
|
45
50
|
goal = fetch_goal!(goal_id)
|
|
46
51
|
goal.disengage!(reason: reason)
|
|
47
52
|
goal
|
data/lib/legion/extensions/agentic/executive/dissonance_resolution/helpers/resolution_engine.rb
CHANGED
|
@@ -32,6 +32,8 @@ module Legion
|
|
|
32
32
|
return nil unless conflict
|
|
33
33
|
|
|
34
34
|
strat = strategy.to_sym
|
|
35
|
+
return nil unless STRATEGIES.include?(strat)
|
|
36
|
+
|
|
35
37
|
@strategy_history[strat] += 1
|
|
36
38
|
conflict.apply_strategy!(strategy: strat, effectiveness: effectiveness)
|
|
37
39
|
@strategy_successes[strat] += 1 if conflict.resolved?
|
|
@@ -92,6 +92,8 @@ module Legion
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
def record_outcome(decision_id:, outcome:)
|
|
95
|
+
return { success: false, reason: :invalid_outcome } unless Constants::DECISION_OUTCOMES.include?(outcome)
|
|
96
|
+
|
|
95
97
|
decision = @decisions.find { |d| d.id == decision_id }
|
|
96
98
|
return { success: false, reason: :not_found } unless decision
|
|
97
99
|
|
|
@@ -76,6 +76,38 @@ module Legion
|
|
|
76
76
|
{ status: result, intention_id: intention_id }
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
+
def form_absorption_intention(domains_at_risk:, neighboring_agents: [], severity: :warning, **)
|
|
80
|
+
domains = Array(domains_at_risk)
|
|
81
|
+
neighbors = Array(neighboring_agents)
|
|
82
|
+
|
|
83
|
+
return { success: false, reason: :no_domains } if domains.empty?
|
|
84
|
+
|
|
85
|
+
base_salience = severity.to_sym == :critical ? 0.85 : 0.55
|
|
86
|
+
salience = [base_salience + (domains.size * 0.05), 1.0].min
|
|
87
|
+
|
|
88
|
+
intention = Helpers::Intention.new_intention(
|
|
89
|
+
drive: :epistemic,
|
|
90
|
+
domain: :knowledge,
|
|
91
|
+
goal: "absorb knowledge for domains: #{domains.join(', ')}",
|
|
92
|
+
salience: salience,
|
|
93
|
+
context: { domains_at_risk: domains, target_agents: neighbors, severity: severity,
|
|
94
|
+
triggered_by: :knowledge_vulnerability }
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
result = intention_stack.push(intention)
|
|
98
|
+
Legion::Logging.info "[volition] absorption intention formed: domains=#{domains.join(',')} " \
|
|
99
|
+
"neighbors=#{neighbors.size} salience=#{salience.round(2)} result=#{result}"
|
|
100
|
+
|
|
101
|
+
{
|
|
102
|
+
success: %i[pushed duplicate].include?(result),
|
|
103
|
+
result: result,
|
|
104
|
+
intention_id: intention[:intention_id],
|
|
105
|
+
salience: salience,
|
|
106
|
+
domains: domains,
|
|
107
|
+
targets: neighbors
|
|
108
|
+
}
|
|
109
|
+
end
|
|
110
|
+
|
|
79
111
|
def volition_status(**)
|
|
80
112
|
stats = intention_stack.stats
|
|
81
113
|
drives = Helpers::DriveSynthesizer.synthesize(tick_results: {}, cognitive_state: {})
|
|
@@ -174,7 +174,7 @@ RSpec.describe Legion::Extensions::Agentic::Executive::Chunking::Helpers::Chunki
|
|
|
174
174
|
id = engine.add_item(content: 'x')[:item_id]
|
|
175
175
|
cid = engine.create_chunk(label: 'x', item_ids: [id])[:chunk_id]
|
|
176
176
|
engine.load_to_working_memory(chunk_id: cid)
|
|
177
|
-
expected = (1.0 /
|
|
177
|
+
expected = (1.0 / 4).round(10)
|
|
178
178
|
expect(engine.working_memory_load).to be_within(0.0001).of(expected)
|
|
179
179
|
end
|
|
180
180
|
end
|
|
@@ -10,8 +10,8 @@ RSpec.describe Legion::Extensions::Agentic::Executive::Chunking::Helpers::Consta
|
|
|
10
10
|
expect(described_class::MAX_CHUNKS).to eq(200)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
it 'defines WORKING_MEMORY_CAPACITY as
|
|
14
|
-
expect(described_class::WORKING_MEMORY_CAPACITY).to eq(
|
|
13
|
+
it 'defines WORKING_MEMORY_CAPACITY as 4' do
|
|
14
|
+
expect(described_class::WORKING_MEMORY_CAPACITY).to eq(4)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it 'defines CAPACITY_VARIANCE as 2' do
|
|
@@ -97,7 +97,7 @@ RSpec.describe Legion::Extensions::Agentic::Executive::Chunking::Runners::Cognit
|
|
|
97
97
|
it 'returns success with capacity info' do
|
|
98
98
|
result = client.working_memory_status(engine: engine)
|
|
99
99
|
expect(result[:success]).to be true
|
|
100
|
-
expect(result[:capacity]).to eq(
|
|
100
|
+
expect(result[:capacity]).to eq(4)
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
it 'returns a capacity label' do
|
data/spec/legion/extensions/agentic/executive/disengagement/helpers/disengagement_engine_spec.rb
CHANGED
|
@@ -77,6 +77,19 @@ RSpec.describe Legion::Extensions::Agentic::Executive::Disengagement::Helpers::D
|
|
|
77
77
|
expect { engine.disengage_goal(goal_id: 'nope', reason: :sunk_cost) }
|
|
78
78
|
.to raise_error(ArgumentError)
|
|
79
79
|
end
|
|
80
|
+
|
|
81
|
+
it 'raises ArgumentError for invalid reason' do
|
|
82
|
+
expect { engine.disengage_goal(goal_id: goal.id, reason: :boredom) }
|
|
83
|
+
.to raise_error(ArgumentError, /invalid reason/)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'accepts all valid DISENGAGE_REASONS' do
|
|
87
|
+
constants = Legion::Extensions::Agentic::Executive::Disengagement::Helpers::Constants
|
|
88
|
+
constants::DISENGAGE_REASONS.each do |reason|
|
|
89
|
+
g = engine.create_goal(label: "goal_#{reason}", domain: :test)
|
|
90
|
+
expect { engine.disengage_goal(goal_id: g.id, reason: reason) }.not_to raise_error
|
|
91
|
+
end
|
|
92
|
+
end
|
|
80
93
|
end
|
|
81
94
|
|
|
82
95
|
describe '#stalled_goals' do
|
|
@@ -29,6 +29,19 @@ RSpec.describe Legion::Extensions::Agentic::Executive::DissonanceResolution::Hel
|
|
|
29
29
|
reframe = report.find { |s| s[:strategy] == :reframe }
|
|
30
30
|
expect(reframe[:uses]).to eq(1)
|
|
31
31
|
end
|
|
32
|
+
|
|
33
|
+
it 'rejects invalid strategy' do
|
|
34
|
+
expect(engine.apply_strategy(conflict_id: conflict.id, strategy: :magic)).to be_nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'accepts all valid STRATEGIES' do
|
|
38
|
+
constants = Legion::Extensions::Agentic::Executive::DissonanceResolution::Helpers::Constants
|
|
39
|
+
constants::STRATEGIES.each do |strat|
|
|
40
|
+
c = engine.create_conflict(belief_a: 'a', belief_b: 'b')
|
|
41
|
+
result = engine.apply_strategy(conflict_id: c.id, strategy: strat)
|
|
42
|
+
expect(result).not_to be_nil
|
|
43
|
+
end
|
|
44
|
+
end
|
|
32
45
|
end
|
|
33
46
|
|
|
34
47
|
describe '#escalate_conflict' do
|
data/spec/legion/extensions/agentic/executive/dual_process/helpers/dual_process_engine_spec.rb
CHANGED
|
@@ -165,6 +165,21 @@ RSpec.describe Legion::Extensions::Agentic::Executive::DualProcess::Helpers::Dua
|
|
|
165
165
|
expect(result[:success]).to be false
|
|
166
166
|
expect(result[:reason]).to eq(:not_found)
|
|
167
167
|
end
|
|
168
|
+
|
|
169
|
+
it 'rejects invalid outcome' do
|
|
170
|
+
result = engine.record_outcome(decision_id: decision_id, outcome: :maybe)
|
|
171
|
+
expect(result[:success]).to be false
|
|
172
|
+
expect(result[:reason]).to eq(:invalid_outcome)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it 'accepts all valid DECISION_OUTCOMES' do
|
|
176
|
+
constants = Legion::Extensions::Agentic::Executive::DualProcess::Helpers::Constants
|
|
177
|
+
constants::DECISION_OUTCOMES.each do |out|
|
|
178
|
+
did = engine.execute_system_one(query: "test_#{out}", domain: :work)[:decision_id]
|
|
179
|
+
result = engine.record_outcome(decision_id: did, outcome: out)
|
|
180
|
+
expect(result[:success]).to be true
|
|
181
|
+
end
|
|
182
|
+
end
|
|
168
183
|
end
|
|
169
184
|
|
|
170
185
|
describe '#effort_level' do
|
|
@@ -55,6 +55,18 @@ RSpec.describe Legion::Extensions::Agentic::Executive::Inhibition::Helpers::Inhi
|
|
|
55
55
|
impulse = store.create_impulse(type: :reactive, action: :act, strength: :unknown_level)
|
|
56
56
|
expect(impulse.strength).to eq(Legion::Extensions::Agentic::Executive::Inhibition::Helpers::Constants::IMPULSE_STRENGTHS[:moderate])
|
|
57
57
|
end
|
|
58
|
+
|
|
59
|
+
it 'rejects invalid impulse type' do
|
|
60
|
+
expect(store.create_impulse(type: :telepathic, action: :act, strength: :moderate)).to be_nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'accepts all valid IMPULSE_TYPES' do
|
|
64
|
+
constants = Legion::Extensions::Agentic::Executive::Inhibition::Helpers::Constants
|
|
65
|
+
constants::IMPULSE_TYPES.each do |itype|
|
|
66
|
+
result = store.create_impulse(type: itype, action: :act, strength: :moderate)
|
|
67
|
+
expect(result).not_to be_nil
|
|
68
|
+
end
|
|
69
|
+
end
|
|
58
70
|
end
|
|
59
71
|
|
|
60
72
|
describe '#evaluate_and_apply' do
|
|
@@ -132,4 +132,59 @@ RSpec.describe Legion::Extensions::Agentic::Executive::Volition::Runners::Voliti
|
|
|
132
132
|
expect(result[:count]).to be >= 1
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
|
+
|
|
136
|
+
describe '#form_absorption_intention' do
|
|
137
|
+
it 'returns success false when no domains provided' do
|
|
138
|
+
result = client.form_absorption_intention(domains_at_risk: [])
|
|
139
|
+
expect(result[:success]).to be false
|
|
140
|
+
expect(result[:reason]).to eq(:no_domains)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it 'pushes an epistemic absorption intention onto the stack' do
|
|
144
|
+
result = client.form_absorption_intention(
|
|
145
|
+
domains_at_risk: %w[pki dns],
|
|
146
|
+
neighboring_agents: %w[agent-b agent-c]
|
|
147
|
+
)
|
|
148
|
+
expect(result[:success]).to be true
|
|
149
|
+
expect(result[:result]).to eq(:pushed)
|
|
150
|
+
expect(result[:domains]).to eq(%w[pki dns])
|
|
151
|
+
expect(result[:targets]).to eq(%w[agent-b agent-c])
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'returns the intention_id' do
|
|
155
|
+
result = client.form_absorption_intention(domains_at_risk: ['vault'])
|
|
156
|
+
expect(result[:intention_id]).to be_a(String)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'assigns higher salience for critical severity' do
|
|
160
|
+
warning = client.form_absorption_intention(
|
|
161
|
+
domains_at_risk: ['pki'], severity: :warning
|
|
162
|
+
)
|
|
163
|
+
critical_client = Legion::Extensions::Agentic::Executive::Volition::Client.new
|
|
164
|
+
critical = critical_client.form_absorption_intention(
|
|
165
|
+
domains_at_risk: ['pki'], severity: :critical
|
|
166
|
+
)
|
|
167
|
+
expect(critical[:salience]).to be > warning[:salience]
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'scales salience with number of at-risk domains' do
|
|
171
|
+
few = client.form_absorption_intention(domains_at_risk: ['pki'])
|
|
172
|
+
many_client = Legion::Extensions::Agentic::Executive::Volition::Client.new
|
|
173
|
+
many = many_client.form_absorption_intention(domains_at_risk: %w[pki dns vault ssh consul nomad])
|
|
174
|
+
expect(many[:salience]).to be >= few[:salience]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it 'stores knowledge_vulnerability trigger context' do
|
|
178
|
+
result = client.form_absorption_intention(domains_at_risk: ['pki'])
|
|
179
|
+
intention = client.intention_stack.find(result[:intention_id])
|
|
180
|
+
expect(intention[:context][:triggered_by]).to eq(:knowledge_vulnerability)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it 'returns :duplicate on second call for same domains (capacity protection)' do
|
|
184
|
+
client.form_absorption_intention(domains_at_risk: ['pki'])
|
|
185
|
+
second = client.form_absorption_intention(domains_at_risk: ['pki'])
|
|
186
|
+
# Either duplicate (same drive/domain/goal match) or pushed — both acceptable
|
|
187
|
+
expect(%i[pushed duplicate]).to include(second[:result])
|
|
188
|
+
end
|
|
189
|
+
end
|
|
135
190
|
end
|
|
@@ -71,10 +71,10 @@ RSpec.describe Legion::Extensions::Agentic::Executive::WorkingMemory::Client do
|
|
|
71
71
|
expect(client.working_memory_stats[:size]).to eq(0)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
it 'models the
|
|
74
|
+
it 'models the 4 plus-or-minus 2 capacity limit' do
|
|
75
75
|
# Fill to base capacity
|
|
76
|
-
|
|
77
|
-
expect(client.buffer.size).to eq(
|
|
76
|
+
4.times { |i| client.store_item(content: "item #{i}", priority: :normal) }
|
|
77
|
+
expect(client.buffer.size).to eq(4)
|
|
78
78
|
|
|
79
79
|
# Without chunking, adding more evicts lowest activation
|
|
80
80
|
3.times { |i| client.store_item(content: "overflow #{i}", priority: :high) }
|
|
@@ -4,8 +4,8 @@ require 'spec_helper'
|
|
|
4
4
|
|
|
5
5
|
RSpec.describe Legion::Extensions::Agentic::Executive::WorkingMemory::Helpers::Constants do
|
|
6
6
|
describe 'CAPACITY' do
|
|
7
|
-
it 'is
|
|
8
|
-
expect(described_class::CAPACITY).to eq(
|
|
7
|
+
it 'is 4 (Cowan 2001)' do
|
|
8
|
+
expect(described_class::CAPACITY).to eq(4)
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|