lex-extinction 0.2.0

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.
@@ -0,0 +1,291 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/extinction/helpers/levels'
4
+ require 'legion/extensions/extinction/helpers/protocol_state'
5
+
6
+ RSpec.describe Legion::Extensions::Extinction::Helpers::ProtocolState do
7
+ subject(:state) { described_class.new }
8
+
9
+ describe '#initialize' do
10
+ it 'starts at level 0' do
11
+ expect(state.current_level).to eq(0)
12
+ end
13
+
14
+ it 'starts as inactive' do
15
+ expect(state.active).to be false
16
+ end
17
+
18
+ it 'starts with an empty history' do
19
+ expect(state.history).to eq([])
20
+ end
21
+ end
22
+
23
+ describe '#escalate' do
24
+ context 'with an invalid level' do
25
+ it 'returns :invalid_level for level 0' do
26
+ expect(state.escalate(0, authority: :governance_council, reason: 'test')).to eq(:invalid_level)
27
+ end
28
+
29
+ it 'returns :invalid_level for level 5' do
30
+ expect(state.escalate(5, authority: :governance_council, reason: 'test')).to eq(:invalid_level)
31
+ end
32
+
33
+ it 'does not change current_level on invalid level' do
34
+ state.escalate(99, authority: :governance_council, reason: 'test')
35
+ expect(state.current_level).to eq(0)
36
+ end
37
+
38
+ it 'does not add to history on invalid level' do
39
+ state.escalate(99, authority: :governance_council, reason: 'test')
40
+ expect(state.history).to be_empty
41
+ end
42
+ end
43
+
44
+ context 'when already at or above the requested level' do
45
+ before { state.escalate(2, authority: :governance_council, reason: 'setup') }
46
+
47
+ it 'returns :already_at_or_above for same level' do
48
+ expect(state.escalate(2, authority: :governance_council, reason: 'test')).to eq(:already_at_or_above)
49
+ end
50
+
51
+ it 'returns :already_at_or_above for lower level' do
52
+ expect(state.escalate(1, authority: :governance_council, reason: 'test')).to eq(:already_at_or_above)
53
+ end
54
+ end
55
+
56
+ context 'with insufficient authority' do
57
+ it 'returns :insufficient_authority for level 1 with wrong authority' do
58
+ result = state.escalate(1, authority: :physical_keyholders, reason: 'test')
59
+ expect(result).to eq(:insufficient_authority)
60
+ end
61
+
62
+ it 'returns :insufficient_authority for level 3 with governance_council' do
63
+ state.escalate(1, authority: :governance_council, reason: 'step1')
64
+ state.escalate(2, authority: :governance_council, reason: 'step2')
65
+ result = state.escalate(3, authority: :governance_council, reason: 'test')
66
+ expect(result).to eq(:insufficient_authority)
67
+ end
68
+
69
+ it 'returns :insufficient_authority for level 4 with governance_council' do
70
+ result = state.escalate(4, authority: :governance_council, reason: 'test')
71
+ expect(result).to eq(:insufficient_authority)
72
+ end
73
+
74
+ it 'does not change level on insufficient authority' do
75
+ state.escalate(1, authority: :physical_keyholders, reason: 'test')
76
+ expect(state.current_level).to eq(0)
77
+ end
78
+ end
79
+
80
+ context 'with valid escalation' do
81
+ it 'returns :escalated for level 1 with governance_council' do
82
+ expect(state.escalate(1, authority: :governance_council, reason: 'threat')).to eq(:escalated)
83
+ end
84
+
85
+ it 'updates current_level to 1' do
86
+ state.escalate(1, authority: :governance_council, reason: 'threat')
87
+ expect(state.current_level).to eq(1)
88
+ end
89
+
90
+ it 'sets active to true' do
91
+ state.escalate(1, authority: :governance_council, reason: 'threat')
92
+ expect(state.active).to be true
93
+ end
94
+
95
+ it 'appends an entry to history' do
96
+ state.escalate(1, authority: :governance_council, reason: 'threat')
97
+ expect(state.history.size).to eq(1)
98
+ end
99
+
100
+ it 'records the correct action in history' do
101
+ state.escalate(1, authority: :governance_council, reason: 'threat')
102
+ expect(state.history.last[:action]).to eq(:escalate)
103
+ end
104
+
105
+ it 'records the level in history' do
106
+ state.escalate(1, authority: :governance_council, reason: 'threat')
107
+ expect(state.history.last[:level]).to eq(1)
108
+ end
109
+
110
+ it 'records the authority in history' do
111
+ state.escalate(1, authority: :governance_council, reason: 'threat')
112
+ expect(state.history.last[:authority]).to eq(:governance_council)
113
+ end
114
+
115
+ it 'records the reason in history' do
116
+ state.escalate(1, authority: :governance_council, reason: 'threat')
117
+ expect(state.history.last[:reason]).to eq('threat')
118
+ end
119
+
120
+ it 'records a Time in history' do
121
+ state.escalate(1, authority: :governance_council, reason: 'threat')
122
+ expect(state.history.last[:at]).to be_a(Time)
123
+ end
124
+
125
+ it 'escalates to level 4 with physical_keyholders after reaching level 3' do
126
+ state.escalate(1, authority: :governance_council, reason: 's1')
127
+ state.escalate(2, authority: :governance_council, reason: 's2')
128
+ state.escalate(3, authority: :council_plus_executive, reason: 's3')
129
+ result = state.escalate(4, authority: :physical_keyholders, reason: 's4')
130
+ expect(result).to eq(:escalated)
131
+ expect(state.current_level).to eq(4)
132
+ end
133
+
134
+ it 'accumulates history across multiple escalations' do
135
+ state.escalate(1, authority: :governance_council, reason: 'r1')
136
+ state.escalate(2, authority: :governance_council, reason: 'r2')
137
+ expect(state.history.size).to eq(2)
138
+ end
139
+
140
+ it 'calls save_to_local after escalation' do
141
+ expect(state).to receive(:save_to_local)
142
+ state.escalate(1, authority: :governance_council, reason: 'test')
143
+ end
144
+
145
+ it 'trims history beyond MAX_HISTORY' do
146
+ s = described_class.new
147
+ s.instance_variable_set(:@history, Array.new(510) { { action: :escalate, at: Time.now } })
148
+ s.send(:trim_history)
149
+ expect(s.history.size).to eq(500)
150
+ end
151
+ end
152
+ end
153
+
154
+ describe '#deescalate' do
155
+ context 'when protocol is not active' do
156
+ it 'returns :not_active' do
157
+ expect(state.deescalate(0, authority: :governance_council, reason: 'test')).to eq(:not_active)
158
+ end
159
+ end
160
+
161
+ context 'when target_level is invalid (not lower than current)' do
162
+ before { state.escalate(2, authority: :governance_council, reason: 'setup') }
163
+
164
+ it 'returns :invalid_target when target equals current' do
165
+ result = state.deescalate(2, authority: :governance_council, reason: 'test')
166
+ expect(result).to eq(:invalid_target)
167
+ end
168
+
169
+ it 'returns :invalid_target when target is above current' do
170
+ result = state.deescalate(3, authority: :governance_council, reason: 'test')
171
+ expect(result).to eq(:invalid_target)
172
+ end
173
+ end
174
+
175
+ context 'when current level is irreversible (level 4)' do
176
+ before do
177
+ state.escalate(1, authority: :governance_council, reason: 's1')
178
+ state.escalate(2, authority: :governance_council, reason: 's2')
179
+ state.escalate(3, authority: :council_plus_executive, reason: 's3')
180
+ state.escalate(4, authority: :physical_keyholders, reason: 's4')
181
+ end
182
+
183
+ it 'returns :irreversible' do
184
+ result = state.deescalate(0, authority: :physical_keyholders, reason: 'try')
185
+ expect(result).to eq(:irreversible)
186
+ end
187
+
188
+ it 'does not change current_level' do
189
+ state.deescalate(0, authority: :physical_keyholders, reason: 'try')
190
+ expect(state.current_level).to eq(4)
191
+ end
192
+ end
193
+
194
+ context 'with insufficient authority for deescalation' do
195
+ before do
196
+ state.escalate(1, authority: :governance_council, reason: 's1')
197
+ state.escalate(2, authority: :governance_council, reason: 's2')
198
+ state.escalate(3, authority: :council_plus_executive, reason: 's3')
199
+ end
200
+
201
+ it 'rejects wrong authority for level 3' do
202
+ result = state.deescalate(0, authority: :governance_council, reason: 'test')
203
+ expect(result).to eq(:insufficient_authority)
204
+ end
205
+
206
+ it 'accepts correct authority for level 3' do
207
+ result = state.deescalate(0, authority: :council_plus_executive, reason: 'test')
208
+ expect(result).to eq(:deescalated)
209
+ end
210
+ end
211
+
212
+ context 'with valid de-escalation' do
213
+ before { state.escalate(2, authority: :governance_council, reason: 'setup') }
214
+
215
+ it 'returns :deescalated' do
216
+ result = state.deescalate(1, authority: :governance_council, reason: 'resolved')
217
+ expect(result).to eq(:deescalated)
218
+ end
219
+
220
+ it 'updates current_level to the target' do
221
+ state.deescalate(1, authority: :governance_council, reason: 'resolved')
222
+ expect(state.current_level).to eq(1)
223
+ end
224
+
225
+ it 'remains active when target_level is positive' do
226
+ state.deescalate(1, authority: :governance_council, reason: 'resolved')
227
+ expect(state.active).to be true
228
+ end
229
+
230
+ it 'becomes inactive when target_level is 0' do
231
+ state.deescalate(0, authority: :governance_council, reason: 'fully resolved')
232
+ expect(state.active).to be false
233
+ end
234
+
235
+ it 'appends a deescalate entry to history' do
236
+ state.deescalate(0, authority: :governance_council, reason: 'resolved')
237
+ last = state.history.last
238
+ expect(last[:action]).to eq(:deescalate)
239
+ expect(last[:level]).to eq(0)
240
+ end
241
+
242
+ it 'records the reason in history' do
243
+ state.deescalate(0, authority: :governance_council, reason: 'resolved')
244
+ expect(state.history.last[:reason]).to eq('resolved')
245
+ end
246
+
247
+ it 'records a Time in the deescalate history entry' do
248
+ state.deescalate(0, authority: :governance_council, reason: 'resolved')
249
+ expect(state.history.last[:at]).to be_a(Time)
250
+ end
251
+
252
+ it 'calls save_to_local after deescalation' do
253
+ expect(state).to receive(:save_to_local)
254
+ state.deescalate(0, authority: :governance_council, reason: 'test')
255
+ end
256
+ end
257
+ end
258
+
259
+ describe '#to_h' do
260
+ it 'returns a hash' do
261
+ expect(state.to_h).to be_a(Hash)
262
+ end
263
+
264
+ it 'includes current_level' do
265
+ expect(state.to_h[:current_level]).to eq(0)
266
+ end
267
+
268
+ it 'includes active' do
269
+ expect(state.to_h[:active]).to be false
270
+ end
271
+
272
+ it 'includes history_size' do
273
+ expect(state.to_h[:history_size]).to eq(0)
274
+ end
275
+
276
+ it 'includes level_info as nil when at level 0' do
277
+ expect(state.to_h[:level_info]).to be_nil
278
+ end
279
+
280
+ it 'includes non-nil level_info when escalated' do
281
+ state.escalate(1, authority: :governance_council, reason: 'test')
282
+ expect(state.to_h[:level_info]).not_to be_nil
283
+ expect(state.to_h[:level_info][:name]).to eq(:mesh_isolation)
284
+ end
285
+
286
+ it 'reflects updated history_size after escalation' do
287
+ state.escalate(1, authority: :governance_council, reason: 'test')
288
+ expect(state.to_h[:history_size]).to eq(1)
289
+ end
290
+ end
291
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/extinction/client'
4
+
5
+ RSpec.describe Legion::Extensions::Extinction::Runners::Extinction do
6
+ let(:client) { Legion::Extensions::Extinction::Client.new }
7
+
8
+ describe '#escalate' do
9
+ it 'escalates to level 1' do
10
+ result = client.escalate(level: 1, authority: :governance_council, reason: 'threat detected')
11
+ expect(result[:escalated]).to be true
12
+ expect(result[:level]).to eq(1)
13
+ end
14
+
15
+ it 'rejects wrong authority' do
16
+ result = client.escalate(level: 4, authority: :governance_council, reason: 'test')
17
+ expect(result[:escalated]).to be false
18
+ expect(result[:reason]).to eq(:insufficient_authority)
19
+ end
20
+
21
+ it 'rejects escalation to same or lower level' do
22
+ client.escalate(level: 2, authority: :governance_council, reason: 'test')
23
+ result = client.escalate(level: 1, authority: :governance_council, reason: 'test')
24
+ expect(result[:escalated]).to be false
25
+ end
26
+
27
+ it 'escalates to level 4 with physical keyholders' do
28
+ client.escalate(level: 1, authority: :governance_council, reason: 'step 1')
29
+ client.escalate(level: 2, authority: :governance_council, reason: 'step 2')
30
+ client.escalate(level: 3, authority: :council_plus_executive, reason: 'step 3')
31
+ result = client.escalate(level: 4, authority: :physical_keyholders, reason: 'final')
32
+ expect(result[:escalated]).to be true
33
+ expect(result[:info][:reversible]).to be false
34
+ end
35
+ end
36
+
37
+ describe '#deescalate' do
38
+ it 'deescalates from reversible level' do
39
+ client.escalate(level: 2, authority: :governance_council, reason: 'test')
40
+ result = client.deescalate(target_level: 0, authority: :governance_council, reason: 'resolved')
41
+ expect(result[:deescalated]).to be true
42
+ end
43
+
44
+ it 'cannot deescalate level 4 (irreversible)' do
45
+ client.escalate(level: 1, authority: :governance_council, reason: 's1')
46
+ client.escalate(level: 2, authority: :governance_council, reason: 's2')
47
+ client.escalate(level: 3, authority: :council_plus_executive, reason: 's3')
48
+ client.escalate(level: 4, authority: :physical_keyholders, reason: 's4')
49
+ result = client.deescalate(target_level: 0, authority: :physical_keyholders, reason: 'try')
50
+ expect(result[:deescalated]).to be false
51
+ expect(result[:reason]).to eq(:irreversible)
52
+ end
53
+ end
54
+
55
+ describe '#extinction_status' do
56
+ it 'returns current state' do
57
+ status = client.extinction_status
58
+ expect(status[:current_level]).to eq(0)
59
+ expect(status[:active]).to be false
60
+ end
61
+ end
62
+
63
+ describe '#escalate side effects' do
64
+ it 'emits escalation event when Legion::Events is defined' do
65
+ events = Module.new { def self.emit(*, **); end }
66
+ stub_const('Legion::Events', events)
67
+ expect(events).to receive(:emit).with('extinction.mesh_isolation', hash_including(level: 1))
68
+ client.escalate(level: 1, authority: :governance_council, reason: 'test')
69
+ end
70
+
71
+ it 'triggers cryptographic erasure at level 4' do
72
+ events = Module.new { def self.emit(*, **); end }
73
+ stub_const('Legion::Events', events)
74
+ pc_mod = Module.new { def self.erase_all; end }
75
+ stub_const('Legion::Extensions::Privatecore::Runners::Privatecore', pc_mod)
76
+
77
+ client.escalate(level: 1, authority: :governance_council, reason: 's1')
78
+ client.escalate(level: 2, authority: :governance_council, reason: 's2')
79
+ client.escalate(level: 3, authority: :council_plus_executive, reason: 's3')
80
+ expect(pc_mod).to receive(:erase_all)
81
+ client.escalate(level: 4, authority: :physical_keyholders, reason: 'final')
82
+ end
83
+ end
84
+
85
+ describe '#monitor_protocol' do
86
+ it 'returns status hash at level 0' do
87
+ result = client.monitor_protocol
88
+ expect(result[:current_level]).to eq(0)
89
+ end
90
+
91
+ it 'detects stale escalation' do
92
+ client.escalate(level: 1, authority: :governance_council, reason: 'test')
93
+ state = client.send(:protocol_state)
94
+ state.history.last[:at] = Time.now.utc - 100_000
95
+
96
+ events = Module.new { def self.emit(*, **); end }
97
+ stub_const('Legion::Events', events)
98
+ expect(events).to receive(:emit).with('extinction.stale_escalation', anything)
99
+ client.monitor_protocol
100
+ end
101
+ end
102
+
103
+ describe '#check_reversibility' do
104
+ it 'reports levels 1-3 as reversible' do
105
+ [1, 2, 3].each do |level|
106
+ expect(client.check_reversibility(level: level)[:reversible]).to be true
107
+ end
108
+ end
109
+
110
+ it 'reports level 4 as irreversible' do
111
+ expect(client.check_reversibility(level: 4)[:reversible]).to be false
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+ require 'sequel/extensions/migration'
5
+
6
+ require 'legion/extensions/extinction/helpers/levels'
7
+ require 'legion/extensions/extinction/helpers/protocol_state'
8
+
9
+ MIGRATIONS_PATH = File.expand_path(
10
+ '../lib/legion/extensions/extinction/local_migrations',
11
+ __dir__
12
+ ).freeze
13
+
14
+ # Minimal stub for Legion::Data::Local used only within this spec file.
15
+ module Legion
16
+ module Data
17
+ module Local
18
+ class << self
19
+ attr_accessor :_connection, :_connected
20
+
21
+ def connection
22
+ _connection
23
+ end
24
+
25
+ def connected?
26
+ _connected == true
27
+ end
28
+
29
+ def reset_test!
30
+ self._connection = nil
31
+ self._connected = false
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ RSpec.describe Legion::Extensions::Extinction::Helpers::ProtocolState do
39
+ let(:db) do
40
+ conn = Sequel.sqlite
41
+ Sequel::TimestampMigrator.new(conn, MIGRATIONS_PATH).run
42
+ conn
43
+ end
44
+
45
+ before do
46
+ Legion::Data::Local._connection = db
47
+ Legion::Data::Local._connected = true
48
+ end
49
+
50
+ after do
51
+ Legion::Data::Local.reset_test!
52
+ end
53
+
54
+ describe 'save and load round-trip' do
55
+ it 'persists current_level via save_to_local and restores it on a new instance' do
56
+ state = described_class.new
57
+ state.escalate(1, authority: :governance_council, reason: 'test threat')
58
+ state.save_to_local
59
+
60
+ restored = described_class.new
61
+ expect(restored.current_level).to eq(1)
62
+ end
63
+
64
+ it 'persists active flag' do
65
+ state = described_class.new
66
+ state.escalate(1, authority: :governance_council, reason: 'threat')
67
+ state.save_to_local
68
+
69
+ restored = described_class.new
70
+ expect(restored.active).to be true
71
+ end
72
+
73
+ it 'persists history entries' do
74
+ state = described_class.new
75
+ state.escalate(1, authority: :governance_council, reason: 'threat')
76
+ state.save_to_local
77
+
78
+ restored = described_class.new
79
+ expect(restored.history.size).to eq(1)
80
+ expect(restored.history.first[:action]).to eq(:escalate)
81
+ expect(restored.history.first[:level]).to eq(1)
82
+ expect(restored.history.first[:reason]).to eq('threat')
83
+ end
84
+
85
+ it 'restores history :at as a Time object' do
86
+ state = described_class.new
87
+ state.escalate(1, authority: :governance_council, reason: 'threat')
88
+ state.save_to_local
89
+
90
+ restored = described_class.new
91
+ expect(restored.history.first[:at]).to be_a(Time)
92
+ end
93
+
94
+ it 'saves and loads an inactive protocol at level 0' do
95
+ state = described_class.new
96
+ # state is at level 0, no escalation
97
+ state.save_to_local
98
+
99
+ restored = described_class.new
100
+ expect(restored.current_level).to eq(0)
101
+ expect(restored.active).to be false
102
+ end
103
+
104
+ it 'updates the existing row on a second save rather than inserting a duplicate' do
105
+ state = described_class.new
106
+ state.escalate(1, authority: :governance_council, reason: 'first')
107
+ state.save_to_local
108
+
109
+ state.escalate(2, authority: :governance_council, reason: 'second')
110
+ state.save_to_local
111
+
112
+ expect(db[:extinction_state].count).to eq(1)
113
+
114
+ restored = described_class.new
115
+ expect(restored.current_level).to eq(2)
116
+ end
117
+ end
118
+
119
+ describe 'level-4 irreversibility across restarts' do
120
+ it 'starts at level 4 when DB contains level 4' do
121
+ # Directly insert a level-4 row to simulate a previous escalation
122
+ db[:extinction_state].insert(
123
+ id: 1,
124
+ current_level: 4,
125
+ active: true,
126
+ history: '[]',
127
+ updated_at: Time.now.utc
128
+ )
129
+
130
+ state = described_class.new
131
+ expect(state.current_level).to eq(4)
132
+ end
133
+
134
+ it 'cannot be de-escalated after reloading level 4 from DB' do
135
+ db[:extinction_state].insert(
136
+ id: 1,
137
+ current_level: 4,
138
+ active: true,
139
+ history: '[]',
140
+ updated_at: Time.now.utc
141
+ )
142
+
143
+ state = described_class.new
144
+ result = state.deescalate(0, authority: :physical_keyholders, reason: 'trying to escape')
145
+ expect(result).to eq(:irreversible)
146
+ end
147
+
148
+ it 'uses max(db_level, in-memory level) so a fresh instance never drops below DB level' do
149
+ db[:extinction_state].insert(
150
+ id: 1,
151
+ current_level: 3,
152
+ active: true,
153
+ history: '[]',
154
+ updated_at: Time.now.utc
155
+ )
156
+
157
+ state = described_class.new
158
+ # In-memory starts at 0, DB has 3, so max(3, 0) = 3
159
+ expect(state.current_level).to eq(3)
160
+ end
161
+ end
162
+
163
+ describe 'graceful no-op when Local is not connected' do
164
+ before do
165
+ Legion::Data::Local._connected = false
166
+ Legion::Data::Local._connection = nil
167
+ end
168
+
169
+ it 'initializes normally when Local is disconnected' do
170
+ state = described_class.new
171
+ expect(state.current_level).to eq(0)
172
+ expect(state.active).to be false
173
+ expect(state.history).to eq([])
174
+ end
175
+
176
+ it 'save_to_local returns nil without raising when disconnected' do
177
+ state = described_class.new
178
+ expect { state.save_to_local }.not_to raise_error
179
+ end
180
+
181
+ it 'does not mutate state during save_to_local when disconnected' do
182
+ state = described_class.new
183
+ state.escalate(1, authority: :governance_council, reason: 'test')
184
+ state.save_to_local
185
+ expect(state.current_level).to eq(1)
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+
5
+ module Legion
6
+ module Logging
7
+ def self.debug(_msg); end
8
+ def self.info(_msg); end
9
+ def self.warn(_msg); end
10
+ def self.error(_msg); end
11
+ end
12
+ end
13
+
14
+ require 'legion/extensions/extinction'
15
+
16
+ RSpec.configure do |config|
17
+ config.example_status_persistence_file_path = '.rspec_status'
18
+ config.disable_monkey_patching!
19
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
20
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lex-extinction
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Esity
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Escalation and extinction protocol (4 levels) for brain-modeled agentic
13
+ AI
14
+ email:
15
+ - matthewdiverson@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - Gemfile
21
+ - lex-extinction.gemspec
22
+ - lib/legion/extensions/extinction.rb
23
+ - lib/legion/extensions/extinction/actors/protocol_monitor.rb
24
+ - lib/legion/extensions/extinction/client.rb
25
+ - lib/legion/extensions/extinction/helpers/levels.rb
26
+ - lib/legion/extensions/extinction/helpers/protocol_state.rb
27
+ - lib/legion/extensions/extinction/local_migrations/20260316000040_create_extinction_state.rb
28
+ - lib/legion/extensions/extinction/runners/extinction.rb
29
+ - lib/legion/extensions/extinction/version.rb
30
+ - spec/legion/extensions/extinction/actors/protocol_monitor_spec.rb
31
+ - spec/legion/extensions/extinction/client_spec.rb
32
+ - spec/legion/extensions/extinction/helpers/levels_spec.rb
33
+ - spec/legion/extensions/extinction/helpers/protocol_state_spec.rb
34
+ - spec/legion/extensions/extinction/runners/extinction_spec.rb
35
+ - spec/local_persistence_spec.rb
36
+ - spec/spec_helper.rb
37
+ homepage: https://github.com/LegionIO/lex-extinction
38
+ licenses:
39
+ - MIT
40
+ metadata:
41
+ homepage_uri: https://github.com/LegionIO/lex-extinction
42
+ source_code_uri: https://github.com/LegionIO/lex-extinction
43
+ documentation_uri: https://github.com/LegionIO/lex-extinction
44
+ changelog_uri: https://github.com/LegionIO/lex-extinction
45
+ bug_tracker_uri: https://github.com/LegionIO/lex-extinction/issues
46
+ rubygems_mfa_required: 'true'
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '3.4'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubygems_version: 3.6.9
62
+ specification_version: 4
63
+ summary: LEX Extinction
64
+ test_files: []