lex-agentic-defense 0.1.9 → 0.1.10
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 +6 -0
- data/lib/legion/extensions/agentic/defense/extinction/helpers/protocol_state.rb +34 -8
- data/lib/legion/extensions/agentic/defense/extinction/runners/extinction.rb +10 -0
- data/lib/legion/extensions/agentic/defense/version.rb +1 -1
- data/spec/legion/extensions/agentic/defense/extinction/helpers/protocol_state_spec.rb +32 -0
- data/spec/legion/extensions/agentic/defense/extinction/runners/extinction_spec.rb +19 -0
- 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: 6d53484c4b3d4cc379b79f42e2a94fe6929f139c503399d10e07ed496c6afbe7
|
|
4
|
+
data.tar.gz: 7bdfe4bc6a78893edbbe26c3f5176a0f38dd1fcefbc0ff55df0336509b3e7486
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37a236ec79ba72b1e31b2188bf5fc8b961b3c24950091b0119b0174abdac0ff2d21d52e77988ee1f0d2175999e9408ef2826ae782a50831bd87889f1c9cbef5c
|
|
7
|
+
data.tar.gz: 19afa627d4177d22c0820d98e025dcae485eb0fc0972d87fcf1cf2f1893ee44e3e1b4029361ab7e48fe5c988bc27de89cf4b6f27dacc8ec1ac4d5b5159aa0c7b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.10] - 2026-05-07
|
|
4
|
+
### Fixed
|
|
5
|
+
- Extinction protocol authority checks now accept string authorities from JSON/API callers.
|
|
6
|
+
- Extinction state persistence failures are logged and return false below level 4, while level 4 erasure state failures raise instead of being swallowed.
|
|
7
|
+
- Level 4 Apollo erasure propagation now prefers the Apollo client when available.
|
|
8
|
+
|
|
3
9
|
## [0.1.9] - 2026-04-22
|
|
4
10
|
### Fixed
|
|
5
11
|
- Confabulation decay actor now calls `decay_claims` instead of read-only `confabulation_report`; added `decay_claims` method to age out stale unverified claims
|
|
@@ -21,6 +21,7 @@ module Legion
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def escalate(level, authority:, reason:)
|
|
24
|
+
authority = authority.to_sym if authority.respond_to?(:to_sym)
|
|
24
25
|
return :invalid_level unless Levels.valid_level?(level)
|
|
25
26
|
return :already_at_or_above if level <= @current_level
|
|
26
27
|
return :insufficient_authority unless authority == Levels.required_authority(level)
|
|
@@ -37,6 +38,7 @@ module Legion
|
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
def deescalate(target_level, authority:, reason:)
|
|
41
|
+
authority = authority.to_sym if authority.respond_to?(:to_sym)
|
|
40
42
|
return :not_active unless @active
|
|
41
43
|
return :invalid_target if target_level >= @current_level
|
|
42
44
|
return :irreversible unless Levels.reversible?(@current_level)
|
|
@@ -63,7 +65,7 @@ module Legion
|
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
def save_to_local
|
|
66
|
-
return unless
|
|
68
|
+
return unless local_persistence_connected?
|
|
67
69
|
|
|
68
70
|
row = {
|
|
69
71
|
id: 1,
|
|
@@ -72,14 +74,18 @@ module Legion
|
|
|
72
74
|
history: ::JSON.dump(@history.map { |h| h.merge(at: h[:at].to_s) }),
|
|
73
75
|
updated_at: Time.now.utc
|
|
74
76
|
}
|
|
75
|
-
db =
|
|
77
|
+
db = local_persistence_connection
|
|
76
78
|
if db[:extinction_state].where(id: 1).any?
|
|
77
79
|
db[:extinction_state].where(id: 1).update(row.except(:id))
|
|
78
80
|
else
|
|
79
81
|
db[:extinction_state].insert(row)
|
|
80
82
|
end
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
true
|
|
84
|
+
rescue StandardError => e
|
|
85
|
+
log.error("lex-extinction: save_to_local failed: #{e.message}")
|
|
86
|
+
raise if @current_level >= 4
|
|
87
|
+
|
|
88
|
+
false
|
|
83
89
|
end
|
|
84
90
|
|
|
85
91
|
private
|
|
@@ -89,17 +95,19 @@ module Legion
|
|
|
89
95
|
end
|
|
90
96
|
|
|
91
97
|
def load_from_local
|
|
92
|
-
return unless
|
|
98
|
+
return unless local_persistence_connected?
|
|
93
99
|
|
|
94
|
-
row =
|
|
100
|
+
row = local_persistence_connection[:extinction_state].where(id: 1).first
|
|
95
101
|
return unless row
|
|
96
102
|
|
|
97
103
|
db_level = row[:current_level].to_i
|
|
98
104
|
@current_level = [db_level, @current_level].max
|
|
99
105
|
@active = [true, 1].include?(row[:active])
|
|
100
106
|
@history = parse_history(row[:history])
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
true
|
|
108
|
+
rescue StandardError => e
|
|
109
|
+
log.error("lex-extinction: load_from_local failed: #{e.message}")
|
|
110
|
+
false
|
|
103
111
|
end
|
|
104
112
|
|
|
105
113
|
def parse_history(raw)
|
|
@@ -116,6 +124,24 @@ module Legion
|
|
|
116
124
|
rescue StandardError => _e
|
|
117
125
|
[]
|
|
118
126
|
end
|
|
127
|
+
|
|
128
|
+
def local_persistence_connected?
|
|
129
|
+
local_data_connected?
|
|
130
|
+
rescue NoMethodError => e
|
|
131
|
+
log.debug("lex-extinction: local persistence availability unavailable: #{e.message}")
|
|
132
|
+
false
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def local_persistence_connection
|
|
136
|
+
local_data_connection
|
|
137
|
+
rescue NoMethodError => e
|
|
138
|
+
log.debug("lex-extinction: local persistence connection unavailable: #{e.message}")
|
|
139
|
+
raise
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def log
|
|
143
|
+
Legion::Logging
|
|
144
|
+
end
|
|
119
145
|
end
|
|
120
146
|
end
|
|
121
147
|
end
|
|
@@ -103,6 +103,16 @@ module Legion
|
|
|
103
103
|
end
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
+
if defined?(Legion::Extensions::Apollo::Client)
|
|
107
|
+
begin
|
|
108
|
+
Legion::Extensions::Apollo::Client.new.handle_erasure_request(agent_id: 'system:extinction')
|
|
109
|
+
log.warn('[extinction] apollo erasure propagated')
|
|
110
|
+
return
|
|
111
|
+
rescue StandardError => e
|
|
112
|
+
log.error("[extinction] apollo erasure failed: #{e.message}")
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
106
116
|
return unless defined?(Legion::Extensions::Apollo::Runners::Knowledge)
|
|
107
117
|
|
|
108
118
|
begin
|
|
@@ -78,6 +78,13 @@ RSpec.describe Legion::Extensions::Agentic::Defense::Extinction::Helpers::Protoc
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
context 'with valid escalation' do
|
|
81
|
+
it 'accepts string authorities from JSON/API callers' do
|
|
82
|
+
result = state.escalate(1, authority: 'governance_council', reason: 'threat')
|
|
83
|
+
|
|
84
|
+
expect(result).to eq(:escalated)
|
|
85
|
+
expect(state.history.last[:authority]).to eq(:governance_council)
|
|
86
|
+
end
|
|
87
|
+
|
|
81
88
|
it 'returns :escalated for level 1 with governance_council' do
|
|
82
89
|
expect(state.escalate(1, authority: :governance_council, reason: 'threat')).to eq(:escalated)
|
|
83
90
|
end
|
|
@@ -207,6 +214,11 @@ RSpec.describe Legion::Extensions::Agentic::Defense::Extinction::Helpers::Protoc
|
|
|
207
214
|
result = state.deescalate(0, authority: :council_plus_executive, reason: 'test')
|
|
208
215
|
expect(result).to eq(:deescalated)
|
|
209
216
|
end
|
|
217
|
+
|
|
218
|
+
it 'accepts string authority for deescalation' do
|
|
219
|
+
result = state.deescalate(0, authority: 'council_plus_executive', reason: 'test')
|
|
220
|
+
expect(result).to eq(:deescalated)
|
|
221
|
+
end
|
|
210
222
|
end
|
|
211
223
|
|
|
212
224
|
context 'with valid de-escalation' do
|
|
@@ -288,4 +300,24 @@ RSpec.describe Legion::Extensions::Agentic::Defense::Extinction::Helpers::Protoc
|
|
|
288
300
|
expect(state.to_h[:history_size]).to eq(1)
|
|
289
301
|
end
|
|
290
302
|
end
|
|
303
|
+
|
|
304
|
+
describe '#save_to_local' do
|
|
305
|
+
it 'logs and returns false when persistence fails below level 4' do
|
|
306
|
+
state.instance_variable_set(:@current_level, 2)
|
|
307
|
+
allow(state).to receive(:local_data_connected?).and_return(true)
|
|
308
|
+
allow(state).to receive(:local_data_connection).and_raise(StandardError, 'disk full')
|
|
309
|
+
|
|
310
|
+
expect(Legion::Logging).to receive(:error).with(/save_to_local failed/)
|
|
311
|
+
expect(state.save_to_local).to be false
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it 'raises when persistence fails for level 4 erasure state' do
|
|
315
|
+
state.instance_variable_set(:@current_level, 4)
|
|
316
|
+
allow(state).to receive(:local_data_connected?).and_return(true)
|
|
317
|
+
allow(state).to receive(:local_data_connection).and_raise(StandardError, 'disk full')
|
|
318
|
+
allow(Legion::Logging).to receive(:error)
|
|
319
|
+
|
|
320
|
+
expect { state.save_to_local }.to raise_error(StandardError, /disk full/)
|
|
321
|
+
end
|
|
322
|
+
end
|
|
291
323
|
end
|
|
@@ -100,6 +100,25 @@ RSpec.describe Legion::Extensions::Agentic::Defense::Extinction::Runners::Extinc
|
|
|
100
100
|
result = client.escalate(level: 4, authority: :physical_keyholders, reason: 'final')
|
|
101
101
|
expect(result[:escalated]).to be true
|
|
102
102
|
end
|
|
103
|
+
|
|
104
|
+
it 'uses Apollo client when it is available for level 4 erasure' do
|
|
105
|
+
events = Module.new { def self.emit(*, **); end }
|
|
106
|
+
stub_const('Legion::Events', events)
|
|
107
|
+
pc_mod = Module.new { def self.erase_all; end }
|
|
108
|
+
stub_const('Legion::Extensions::Privatecore::Runners::Privatecore', pc_mod)
|
|
109
|
+
|
|
110
|
+
apollo_client = instance_double('Legion::Extensions::Apollo::Client')
|
|
111
|
+
apollo_class = class_double('Legion::Extensions::Apollo::Client', new: apollo_client)
|
|
112
|
+
stub_const('Legion::Extensions::Apollo::Client', apollo_class)
|
|
113
|
+
allow(apollo_client).to receive(:handle_erasure_request).and_return({ deleted: 1 })
|
|
114
|
+
|
|
115
|
+
client.escalate(level: 1, authority: :governance_council, reason: 's1')
|
|
116
|
+
client.escalate(level: 2, authority: :governance_council, reason: 's2')
|
|
117
|
+
client.escalate(level: 3, authority: :council_plus_executive, reason: 's3')
|
|
118
|
+
client.escalate(level: 4, authority: :physical_keyholders, reason: 'final')
|
|
119
|
+
|
|
120
|
+
expect(apollo_client).to have_received(:handle_erasure_request).with(agent_id: 'system:extinction')
|
|
121
|
+
end
|
|
103
122
|
end
|
|
104
123
|
|
|
105
124
|
describe '#monitor_protocol' do
|