lex-synapse 0.4.7 → 0.4.8
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 +11 -0
- data/lib/legion/extensions/synapse/actors/blast_radius.rb +41 -0
- data/lib/legion/extensions/synapse/client.rb +2 -0
- data/lib/legion/extensions/synapse/data/migrations/007_add_blast_radius.rb +21 -0
- data/lib/legion/extensions/synapse/runners/blast_radius.rb +138 -0
- data/lib/legion/extensions/synapse/runners/challenge.rb +16 -3
- data/lib/legion/extensions/synapse/runners/gaia_report.rb +19 -1
- data/lib/legion/extensions/synapse/version.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84bfe76b9dd10227586c084c8005ad9824ee092ba47d9c8dcf71f2756de07b12
|
|
4
|
+
data.tar.gz: 2d7f842ce4b07913213051c3a3bdf80dbdbeca2bad3b4613d873856a22f41cf0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c2a5c3ce4e8d4d4b86743234efc513a7b5540548331080b5a06db22ca6a018b1ea0abfdb4598496b29dae1ca67bc6553020ec880dc6cf66e3f58ebeee41f6be
|
|
7
|
+
data.tar.gz: 8853c5d3b0b8f814e49df2de326ad8d5070823b7210535d1d4a3d643b32a029aadc8add1bf9f879e99c11a4465eb7770522f473943095e2851cb04270ddc0911
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.8] - 2026-03-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Migration 007: add blast radius columns to synapses (`blast_radius`, `propagation_depth`, `downstream_count`, `blast_radius_updated_at`)
|
|
7
|
+
- `Runners::BlastRadius`: BFS graph traversal computing propagation depth and downstream count per synapse; tier classification (LOW/MED/HIGH/CRITICAL) based on depth, downstream count, and throughput
|
|
8
|
+
- `Actor::BlastRadius`: periodic interval actor (every 30 minutes) calling `Runners::BlastRadius#compute`
|
|
9
|
+
- Blast radius multiplier wired into `Challenge#calculate_impact_score` (1.0x LOW, 1.5x MED, 2.0x HIGH, 3.0x CRITICAL)
|
|
10
|
+
- HIGH and CRITICAL synapses require LLM challenge review regardless of impact threshold
|
|
11
|
+
- `estimated_confidence_impact` on proposals now populated during challenge phase
|
|
12
|
+
- `GaiaReport#gaia_summary` includes `blast_distribution` breakdown (LOW/MED/HIGH/CRITICAL/unknown counts)
|
|
13
|
+
|
|
3
14
|
## [0.4.7] - 2026-03-30
|
|
4
15
|
|
|
5
16
|
### Changed
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../runners/blast_radius'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Synapse
|
|
8
|
+
module Actor
|
|
9
|
+
class BlastRadius < Legion::Extensions::Actors::Every
|
|
10
|
+
include Legion::Extensions::Synapse::Runners::BlastRadius
|
|
11
|
+
|
|
12
|
+
def runner_class = self.class
|
|
13
|
+
|
|
14
|
+
def runner_function
|
|
15
|
+
'compute'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def time
|
|
19
|
+
1800
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def use_runner?
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def check_subtask?
|
|
27
|
+
false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def generate_task?
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def action(**_opts)
|
|
35
|
+
compute
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -11,6 +11,7 @@ require_relative 'runners/dream'
|
|
|
11
11
|
require_relative 'runners/promote'
|
|
12
12
|
require_relative 'runners/retrieve'
|
|
13
13
|
require_relative 'runners/propose'
|
|
14
|
+
require_relative 'runners/blast_radius'
|
|
14
15
|
require_relative 'runners/challenge'
|
|
15
16
|
require_relative 'data/models/synapse_proposal'
|
|
16
17
|
require_relative 'helpers/proposals'
|
|
@@ -30,6 +31,7 @@ module Legion
|
|
|
30
31
|
include Runners::Promote
|
|
31
32
|
include Runners::Retrieve
|
|
32
33
|
include Runners::Propose
|
|
34
|
+
include Runners::BlastRadius
|
|
33
35
|
include Runners::Challenge
|
|
34
36
|
|
|
35
37
|
attr_reader :conditioner_client, :transformer_client
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
up do
|
|
5
|
+
alter_table(:synapses) do
|
|
6
|
+
add_column :blast_radius, String, size: 10
|
|
7
|
+
add_column :propagation_depth, Integer, default: 0
|
|
8
|
+
add_column :downstream_count, Integer, default: 0
|
|
9
|
+
add_column :blast_radius_updated_at, DateTime
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
down do
|
|
14
|
+
alter_table(:synapses) do
|
|
15
|
+
drop_column :blast_radius
|
|
16
|
+
drop_column :propagation_depth
|
|
17
|
+
drop_column :downstream_count
|
|
18
|
+
drop_column :blast_radius_updated_at
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../data/models/synapse'
|
|
4
|
+
require_relative '../data/models/synapse_proposal'
|
|
5
|
+
|
|
6
|
+
module Legion
|
|
7
|
+
module Extensions
|
|
8
|
+
module Synapse
|
|
9
|
+
module Runners
|
|
10
|
+
module BlastRadius
|
|
11
|
+
TIER_CRITICAL = 'CRITICAL'
|
|
12
|
+
TIER_HIGH = 'HIGH'
|
|
13
|
+
TIER_MED = 'MED'
|
|
14
|
+
TIER_LOW = 'LOW'
|
|
15
|
+
|
|
16
|
+
BLAST_MULTIPLIERS = {
|
|
17
|
+
TIER_LOW => 1.0,
|
|
18
|
+
TIER_MED => 1.5,
|
|
19
|
+
TIER_HIGH => 2.0,
|
|
20
|
+
TIER_CRITICAL => 3.0
|
|
21
|
+
}.freeze
|
|
22
|
+
|
|
23
|
+
def compute(**_opts)
|
|
24
|
+
Data::Model.define_synapse_model
|
|
25
|
+
return { success: false, error: 'data unavailable' } unless data_available?
|
|
26
|
+
|
|
27
|
+
synapses = Data::Model::Synapse.where(status: 'active').all
|
|
28
|
+
return { success: true, updated: 0, skipped: 0 } if synapses.empty?
|
|
29
|
+
|
|
30
|
+
graph = build_graph(synapses)
|
|
31
|
+
updated = 0
|
|
32
|
+
skipped = 0
|
|
33
|
+
|
|
34
|
+
synapses.each do |synapse|
|
|
35
|
+
depth, count = bfs_reachable(synapse.id, graph)
|
|
36
|
+
tier = classify_tier(
|
|
37
|
+
depth: depth,
|
|
38
|
+
downstream: count,
|
|
39
|
+
throughput: synapse.baseline_throughput.to_f
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
synapse.update(
|
|
43
|
+
propagation_depth: depth,
|
|
44
|
+
downstream_count: count,
|
|
45
|
+
blast_radius: tier,
|
|
46
|
+
blast_radius_updated_at: Time.now
|
|
47
|
+
)
|
|
48
|
+
updated += 1
|
|
49
|
+
rescue StandardError => e
|
|
50
|
+
log.warn("blast_radius update failed for synapse #{synapse.id}: #{e.message}")
|
|
51
|
+
skipped += 1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
{ success: true, updated: updated, skipped: skipped }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def blast_tier(synapse_id:)
|
|
58
|
+
Data::Model.define_synapse_model
|
|
59
|
+
synapse = Data::Model::Synapse[synapse_id]
|
|
60
|
+
return nil unless synapse
|
|
61
|
+
|
|
62
|
+
synapse.blast_radius
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def blast_multiplier_for(blast_radius_tier)
|
|
66
|
+
BLAST_MULTIPLIERS.fetch(blast_radius_tier.to_s.upcase, 1.0)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def requires_llm_review?(blast_radius_tier)
|
|
70
|
+
tier = blast_radius_tier.to_s.upcase
|
|
71
|
+
[TIER_HIGH, TIER_CRITICAL].include?(tier)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def data_available?
|
|
77
|
+
defined?(Legion::Data) && Legion::Settings.dig(:data, :connected)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def build_graph(synapses)
|
|
81
|
+
graph = Hash.new { |h, k| h[k] = [] }
|
|
82
|
+
synapses.each do |s|
|
|
83
|
+
next unless s.source_function_id && s.target_function_id
|
|
84
|
+
|
|
85
|
+
graph[s.source_function_id] << s.target_function_id
|
|
86
|
+
end
|
|
87
|
+
graph
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def bfs_reachable(synapse_id, graph)
|
|
91
|
+
synapse = Data::Model::Synapse[synapse_id]
|
|
92
|
+
return [0, 0] unless synapse&.source_function_id && synapse.target_function_id
|
|
93
|
+
|
|
94
|
+
start = synapse.source_function_id
|
|
95
|
+
visited = {}
|
|
96
|
+
queue = [[start, 0]]
|
|
97
|
+
max_depth = 0
|
|
98
|
+
reachable = 0
|
|
99
|
+
|
|
100
|
+
until queue.empty?
|
|
101
|
+
node, depth = queue.shift
|
|
102
|
+
next if visited[node]
|
|
103
|
+
|
|
104
|
+
visited[node] = true
|
|
105
|
+
|
|
106
|
+
if depth.positive?
|
|
107
|
+
reachable += 1
|
|
108
|
+
max_depth = depth if depth > max_depth
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
graph[node].each do |neighbor|
|
|
112
|
+
queue << [neighbor, depth + 1] unless visited[neighbor]
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
[max_depth, reachable]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def classify_tier(depth:, downstream:, throughput:)
|
|
120
|
+
if depth > 5 || downstream > 25 || throughput > 500
|
|
121
|
+
TIER_CRITICAL
|
|
122
|
+
elsif depth > 3 || downstream > 10 || throughput > 100
|
|
123
|
+
TIER_HIGH
|
|
124
|
+
elsif depth > 1 || downstream > 3
|
|
125
|
+
TIER_MED
|
|
126
|
+
else
|
|
127
|
+
TIER_LOW
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def log_warn(message)
|
|
132
|
+
log.warn(message)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -6,12 +6,15 @@ require_relative '../data/models/synapse'
|
|
|
6
6
|
require_relative '../data/models/synapse_proposal'
|
|
7
7
|
require_relative '../data/models/synapse_challenge'
|
|
8
8
|
require_relative '../data/models/synapse_signal'
|
|
9
|
+
require_relative 'blast_radius'
|
|
9
10
|
|
|
10
11
|
module Legion
|
|
11
12
|
module Extensions
|
|
12
13
|
module Synapse
|
|
13
14
|
module Runners
|
|
14
15
|
module Challenge
|
|
16
|
+
include BlastRadius
|
|
17
|
+
|
|
15
18
|
def pending_challenges
|
|
16
19
|
Data::Model.define_synapse_proposal_model
|
|
17
20
|
Data::Model::SynapseProposal.where(status: 'pending', challenge_state: nil)
|
|
@@ -36,11 +39,14 @@ module Legion
|
|
|
36
39
|
proposal.update(challenge_state: 'challenging')
|
|
37
40
|
|
|
38
41
|
impact = calculate_impact_score(proposal, synapse)
|
|
39
|
-
proposal
|
|
42
|
+
confidence_impact = estimate_confidence_impact(proposal, synapse)
|
|
43
|
+
proposal.update(impact_score: impact, estimated_confidence_impact: confidence_impact)
|
|
40
44
|
|
|
41
45
|
conflict_check(proposal)
|
|
42
46
|
|
|
43
|
-
|
|
47
|
+
needs_llm = Helpers::Challenge.above_impact_threshold?(impact) ||
|
|
48
|
+
requires_llm_review?(synapse.blast_radius.to_s)
|
|
49
|
+
llm_challenge(proposal, synapse, transformer_client) if needs_llm && transformer_client
|
|
44
50
|
|
|
45
51
|
aggregate_challenges(proposal)
|
|
46
52
|
end
|
|
@@ -201,7 +207,14 @@ module Legion
|
|
|
201
207
|
baseline = [synapse.respond_to?(:baseline_throughput) && synapse.baseline_throughput ? synapse.baseline_throughput : 1.0, 1.0].max
|
|
202
208
|
throughput_factor = [recent_signals.to_f / baseline, 2.0].min
|
|
203
209
|
|
|
204
|
-
|
|
210
|
+
multiplier = blast_multiplier_for(synapse.blast_radius.to_s)
|
|
211
|
+
(base * synapse.confidence * throughput_factor * multiplier).clamp(0.0, 1.0)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def estimate_confidence_impact(proposal, synapse)
|
|
215
|
+
base = Helpers::Challenge::IMPACT_WEIGHTS.fetch(proposal.proposal_type, 0.5)
|
|
216
|
+
multiplier = blast_multiplier_for(synapse.blast_radius.to_s)
|
|
217
|
+
(base * multiplier * 0.1).clamp(0.0, 1.0)
|
|
205
218
|
end
|
|
206
219
|
|
|
207
220
|
def build_challenge_prompt(proposal, synapse)
|
|
@@ -29,7 +29,8 @@ module Legion
|
|
|
29
29
|
elevated_pain_count: elevated_pain.size,
|
|
30
30
|
avg_confidence: avg_confidence(active),
|
|
31
31
|
emergent_candidates: observing.size,
|
|
32
|
-
health_score: compute_health_score(active, dampened, elevated_pain)
|
|
32
|
+
health_score: compute_health_score(active, dampened, elevated_pain),
|
|
33
|
+
blast_distribution: blast_distribution(synapses)
|
|
33
34
|
}
|
|
34
35
|
end
|
|
35
36
|
|
|
@@ -64,6 +65,23 @@ module Legion
|
|
|
64
65
|
healthy = active.size - elevated_pain.size
|
|
65
66
|
(healthy.to_f / total).round(4).clamp(0.0, 1.0)
|
|
66
67
|
end
|
|
68
|
+
|
|
69
|
+
def blast_distribution(synapses)
|
|
70
|
+
tiers = %w[LOW MED HIGH CRITICAL]
|
|
71
|
+
dist = tiers.to_h { |t| [t, 0] }
|
|
72
|
+
dist['unknown'] = 0
|
|
73
|
+
|
|
74
|
+
synapses.each do |s|
|
|
75
|
+
tier = s.respond_to?(:blast_radius) && s.blast_radius ? s.blast_radius.upcase : 'unknown'
|
|
76
|
+
if dist.key?(tier)
|
|
77
|
+
dist[tier] += 1
|
|
78
|
+
else
|
|
79
|
+
dist['unknown'] += 1
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
dist
|
|
84
|
+
end
|
|
67
85
|
end
|
|
68
86
|
end
|
|
69
87
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-synapse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -157,6 +157,7 @@ files:
|
|
|
157
157
|
- Rakefile
|
|
158
158
|
- lex-synapse.gemspec
|
|
159
159
|
- lib/legion/extensions/synapse.rb
|
|
160
|
+
- lib/legion/extensions/synapse/actors/blast_radius.rb
|
|
160
161
|
- lib/legion/extensions/synapse/actors/challenge.rb
|
|
161
162
|
- lib/legion/extensions/synapse/actors/crystallize.rb
|
|
162
163
|
- lib/legion/extensions/synapse/actors/decay.rb
|
|
@@ -171,6 +172,7 @@ files:
|
|
|
171
172
|
- lib/legion/extensions/synapse/data/migrations/004_create_synapse_proposals.rb
|
|
172
173
|
- lib/legion/extensions/synapse/data/migrations/005_add_synapse_challenges.rb
|
|
173
174
|
- lib/legion/extensions/synapse/data/migrations/006_add_slow_query_indexes.rb
|
|
175
|
+
- lib/legion/extensions/synapse/data/migrations/007_add_blast_radius.rb
|
|
174
176
|
- lib/legion/extensions/synapse/data/models/synapse.rb
|
|
175
177
|
- lib/legion/extensions/synapse/data/models/synapse_challenge.rb
|
|
176
178
|
- lib/legion/extensions/synapse/data/models/synapse_mutation.rb
|
|
@@ -181,6 +183,7 @@ files:
|
|
|
181
183
|
- lib/legion/extensions/synapse/helpers/homeostasis.rb
|
|
182
184
|
- lib/legion/extensions/synapse/helpers/proposals.rb
|
|
183
185
|
- lib/legion/extensions/synapse/helpers/relationship_wrapper.rb
|
|
186
|
+
- lib/legion/extensions/synapse/runners/blast_radius.rb
|
|
184
187
|
- lib/legion/extensions/synapse/runners/challenge.rb
|
|
185
188
|
- lib/legion/extensions/synapse/runners/crystallize.rb
|
|
186
189
|
- lib/legion/extensions/synapse/runners/dream.rb
|