lex-synapse 0.4.11 → 0.4.12
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 868277c8084e7cd4e50c660e65cf93d3bd3554c183f8c7852bddf7ae28ff91dd
|
|
4
|
+
data.tar.gz: c588730afaa91b1842f35eb3e20584445ebb6f62d2e1042831de6942f9b712e7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 63aa10dd7948c59e7f3f603748a2bfa5bca217aad2dd99d05e898cdf9b102358c21f66b73d4eb258f81fed54b1c90dca23ce6569f942fa9db632fd269c564a8b
|
|
7
|
+
data.tar.gz: dc9a028d79dca386c03672a46237d1190c8001ee35c9704630ed9b8f310ba38322983176d02d178ab979b2695699cbd0178addb4f890d5fe03b498bce4c1008b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.12] - 2026-05-07
|
|
4
|
+
### Fixed
|
|
5
|
+
- Added challenge proposal application through the mutate runner so auto-accepted proposals can advance to `applied` and later resolve challenger outcomes.
|
|
6
|
+
- Averaged resolved LLM challenger confidence, auto-accepted all-abstain challenges, and ensured proactive proposals store a non-empty candidate output.
|
|
7
|
+
- Look up target function schemas through extension discovery when building transform proposals.
|
|
8
|
+
|
|
3
9
|
## [0.4.11] - 2026-04-22
|
|
4
10
|
### Fixed
|
|
5
11
|
- `handle_pain` now actually calls `revert` when consecutive failures reach threshold (was only setting a flag)
|
|
@@ -7,6 +7,7 @@ require_relative '../data/models/synapse_proposal'
|
|
|
7
7
|
require_relative '../data/models/synapse_challenge'
|
|
8
8
|
require_relative '../data/models/synapse_signal'
|
|
9
9
|
require_relative 'blast_radius'
|
|
10
|
+
require_relative 'mutate'
|
|
10
11
|
|
|
11
12
|
module Legion
|
|
12
13
|
module Extensions
|
|
@@ -87,10 +88,37 @@ module Legion
|
|
|
87
88
|
{ success: true, proposal_id: proposal_id, success_rate: success_rate, resolved: challenges.size }
|
|
88
89
|
end
|
|
89
90
|
|
|
91
|
+
def apply_proposal(proposal_id:)
|
|
92
|
+
Data::Model.define_synapse_proposal_model
|
|
93
|
+
Data::Model.define_synapse_model
|
|
94
|
+
|
|
95
|
+
proposal = Data::Model::SynapseProposal[proposal_id]
|
|
96
|
+
return { success: false, error: 'proposal not found' } unless proposal
|
|
97
|
+
return { success: false, error: 'proposal not approved' } unless %w[approved auto_accepted].include?(proposal.status)
|
|
98
|
+
return { success: false, error: 'proposal output missing' } if proposal.output.nil? || proposal.output.to_s.strip.empty?
|
|
99
|
+
|
|
100
|
+
synapse = Data::Model::Synapse[proposal.synapse_id]
|
|
101
|
+
return { success: false, error: 'synapse not found' } unless synapse
|
|
102
|
+
|
|
103
|
+
mutation = mutation_for_proposal(proposal)
|
|
104
|
+
return { success: false, error: "unsupported proposal_type: #{proposal.proposal_type}" } unless mutation
|
|
105
|
+
|
|
106
|
+
result = Object.new.extend(Mutate).mutate(
|
|
107
|
+
synapse_id: proposal.synapse_id,
|
|
108
|
+
mutation_type: mutation[:mutation_type],
|
|
109
|
+
changes: mutation[:changes],
|
|
110
|
+
trigger: 'gaia'
|
|
111
|
+
)
|
|
112
|
+
return result unless result[:success]
|
|
113
|
+
|
|
114
|
+
proposal.update(status: 'applied', reviewed_at: Time.now)
|
|
115
|
+
result.merge(proposal_id: proposal.id, status: 'applied', decision: 'applied')
|
|
116
|
+
end
|
|
117
|
+
|
|
90
118
|
def run_challenge_cycle(transformer_client: nil)
|
|
91
119
|
Data::Model.define_synapse_proposal_model
|
|
92
120
|
Data::Model.define_synapse_challenge_model
|
|
93
|
-
return { challenged: 0, resolved: 0 } unless Helpers::Challenge.enabled?
|
|
121
|
+
return { challenged: 0, applied: 0, resolved: 0 } unless Helpers::Challenge.enabled?
|
|
94
122
|
|
|
95
123
|
settings = Helpers::Challenge.settings
|
|
96
124
|
max = settings[:max_per_cycle] || 5
|
|
@@ -101,6 +129,12 @@ module Legion
|
|
|
101
129
|
challenged += 1
|
|
102
130
|
end
|
|
103
131
|
|
|
132
|
+
applied = 0
|
|
133
|
+
Data::Model::SynapseProposal.where(status: 'auto_accepted').order(Sequel.asc(:id)).limit(max).each do |proposal|
|
|
134
|
+
result = apply_proposal(proposal_id: proposal.id)
|
|
135
|
+
applied += 1 if result[:success]
|
|
136
|
+
end
|
|
137
|
+
|
|
104
138
|
resolved = 0
|
|
105
139
|
window = settings[:outcome_observation_window] || 50
|
|
106
140
|
Data::Model.define_synapse_signal_model
|
|
@@ -118,11 +152,22 @@ module Legion
|
|
|
118
152
|
resolved += 1
|
|
119
153
|
end
|
|
120
154
|
|
|
121
|
-
{ challenged: challenged, resolved: resolved }
|
|
155
|
+
{ challenged: challenged, applied: applied, resolved: resolved }
|
|
122
156
|
end
|
|
123
157
|
|
|
124
158
|
private
|
|
125
159
|
|
|
160
|
+
def mutation_for_proposal(proposal)
|
|
161
|
+
case proposal.proposal_type
|
|
162
|
+
when 'llm_transform', 'transform_mutation'
|
|
163
|
+
{ mutation_type: 'transform_adjusted', changes: { transform: proposal.output } }
|
|
164
|
+
when 'attention_mutation'
|
|
165
|
+
{ mutation_type: 'attention_adjusted', changes: { attention: proposal.output } }
|
|
166
|
+
when 'route_change'
|
|
167
|
+
{ mutation_type: 'route_changed', changes: { routing_strategy: proposal.output } }
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
126
171
|
def conflict_check(proposal)
|
|
127
172
|
conflicts = Data::Model::SynapseProposal.where(
|
|
128
173
|
synapse_id: proposal.synapse_id,
|
|
@@ -176,8 +221,8 @@ module Legion
|
|
|
176
221
|
.exclude(verdict: 'abstain').all
|
|
177
222
|
|
|
178
223
|
if challenges.empty?
|
|
179
|
-
proposal.update(challenge_state: 'challenged', challenge_score: 0.
|
|
180
|
-
return { success: true, challenge_score: 0.
|
|
224
|
+
proposal.update(status: 'auto_accepted', challenge_state: 'challenged', challenge_score: 0.0)
|
|
225
|
+
return { success: true, challenge_score: 0.0, decision: 'auto_accepted' }
|
|
181
226
|
end
|
|
182
227
|
|
|
183
228
|
support_weight = challenges.select { |c| c.verdict == 'support' }.sum(&:challenger_confidence)
|
|
@@ -253,7 +298,7 @@ module Legion
|
|
|
253
298
|
.order(Sequel.desc(:id)).limit(20).all
|
|
254
299
|
return Helpers::Challenge.settings[:challenger_starting_confidence] if recent.empty?
|
|
255
300
|
|
|
256
|
-
recent.
|
|
301
|
+
recent.sum(&:challenger_confidence).to_f / recent.size
|
|
257
302
|
end
|
|
258
303
|
|
|
259
304
|
include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
|
|
@@ -135,7 +135,7 @@ module Legion
|
|
|
135
135
|
synapse: synapse, signal_id: nil, proposal_type: 'transform_mutation',
|
|
136
136
|
trigger: 'proactive',
|
|
137
137
|
inputs: Legion::JSON.dump({ success_rate: rate.round(3), sample_size: signals.size, threshold: threshold }),
|
|
138
|
-
output:
|
|
138
|
+
output: proactive_transform_output(synapse, success_rate: rate.round(3), sample_size: signals.size),
|
|
139
139
|
rationale: "success rate #{(rate * 100).round(1)}% below threshold #{(threshold * 100).round(1)}%"
|
|
140
140
|
)
|
|
141
141
|
end
|
|
@@ -156,7 +156,7 @@ module Legion
|
|
|
156
156
|
synapse: synapse, signal_id: nil, proposal_type: 'transform_mutation',
|
|
157
157
|
trigger: 'proactive',
|
|
158
158
|
inputs: Legion::JSON.dump({ drift_rate: drift_rate.round(3), sample_size: signals.size }),
|
|
159
|
-
output:
|
|
159
|
+
output: proactive_transform_output(synapse, drift_rate: drift_rate.round(3), sample_size: signals.size),
|
|
160
160
|
rationale: "payload drift detected: #{(drift_rate * 100).round(1)}% transform failures in recent signals"
|
|
161
161
|
)
|
|
162
162
|
end
|
|
@@ -226,9 +226,25 @@ module Legion
|
|
|
226
226
|
|
|
227
227
|
def lookup_target_schema(synapse)
|
|
228
228
|
return {} unless synapse.target_function_id
|
|
229
|
-
return {} unless defined?(Legion::Extensions::Lex)
|
|
230
229
|
|
|
231
|
-
{}
|
|
230
|
+
discovery_schema(synapse.target_function_id) || {}
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def discovery_schema(function_id)
|
|
234
|
+
discovery = defined?(Legion::Extensions::Discovery) && Legion::Extensions::Discovery
|
|
235
|
+
return unless discovery.respond_to?(:function_schema)
|
|
236
|
+
|
|
237
|
+
discovery.function_schema(function_id)
|
|
238
|
+
rescue StandardError => e
|
|
239
|
+
log.debug("lookup_target_schema failed for #{function_id}: #{e.message}")
|
|
240
|
+
nil
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def proactive_transform_output(synapse, **metadata)
|
|
244
|
+
existing = synapse.transform.to_s.strip
|
|
245
|
+
return existing unless existing.empty?
|
|
246
|
+
|
|
247
|
+
Legion::JSON.dump(metadata.merge(action: 'review_transform', synapse_id: synapse.id))
|
|
232
248
|
end
|
|
233
249
|
|
|
234
250
|
def build_transform_prompt(source_schema, target_schema)
|