lex-mind-growth 0.3.1 → 0.3.2
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/lib/legion/extensions/mind_growth/helpers/concept_proposal.rb +1 -0
- data/lib/legion/extensions/mind_growth/runners/builder.rb +10 -2
- data/lib/legion/extensions/mind_growth/runners/dream_ideation.rb +13 -2
- data/lib/legion/extensions/mind_growth/runners/integration_tester.rb +22 -0
- data/lib/legion/extensions/mind_growth/version.rb +1 -1
- data/spec/legion/extensions/mind_growth/runners/dream_ideation_spec.rb +11 -0
- data/spec/legion/extensions/mind_growth/runners/integration_tester_spec.rb +71 -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: 48176d28730ab5f2b56d9717240975b2c212c789afd5328ab45ebeae470c7c5d
|
|
4
|
+
data.tar.gz: 160ccb0ab88b31b5a946d776556ba3e0926231674747c278283a3356742f583c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 511c3dc67360c313ca2755a785853f7d641765550b174c2d7c434b8818b475c8b972d49a32f3dcebf62ed55371bb4558cd2703bce2956bac6b6c082ef1a58185
|
|
7
|
+
data.tar.gz: 9b55e8a8eaa027b023b3f80928675187b3d0a11e2773aae2f5439d54560353a96a0e0a28478b6d0029f5f0e534bcee0c71480a8c69cc6e2c8dbf5c1c811d0ea9
|
|
@@ -13,6 +13,7 @@ module Legion
|
|
|
13
13
|
].freeze
|
|
14
14
|
|
|
15
15
|
attr_reader(*FIELDS)
|
|
16
|
+
attr_writer :origin, :rationale
|
|
16
17
|
|
|
17
18
|
def initialize(name:, module_name:, category:, description:, metaphor: nil, helpers: [], # rubocop:disable Metrics/ParameterLists
|
|
18
19
|
runner_methods: [], rationale: nil, origin: :proposer)
|
|
@@ -57,8 +57,16 @@ module Legion
|
|
|
57
57
|
def run_stage(pipeline, stage, callable)
|
|
58
58
|
return if pipeline.stage != stage
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
max_attempts = Helpers::Constants::MAX_FIX_ATTEMPTS
|
|
61
|
+
attempt = 0
|
|
62
|
+
|
|
63
|
+
loop do
|
|
64
|
+
attempt += 1
|
|
65
|
+
result = callable.call
|
|
66
|
+
pipeline.advance!(result)
|
|
67
|
+
|
|
68
|
+
break if result[:success] || pipeline.failed? || attempt >= max_attempts
|
|
69
|
+
end
|
|
62
70
|
end
|
|
63
71
|
|
|
64
72
|
def ext_path(proposal, base_path)
|
|
@@ -34,7 +34,10 @@ module Legion
|
|
|
34
34
|
|
|
35
35
|
proposal_id = result[:proposal][:id]
|
|
36
36
|
proposal = Runners::Proposer.get_proposal_object(proposal_id)
|
|
37
|
-
proposal
|
|
37
|
+
proposal.origin = :dream if proposal.respond_to?(:origin=)
|
|
38
|
+
|
|
39
|
+
# Apply novelty bonus to the proposal's scores for dream-originated concepts
|
|
40
|
+
apply_novelty_bonus(proposal)
|
|
38
41
|
|
|
39
42
|
proposals << result[:proposal]
|
|
40
43
|
end
|
|
@@ -75,7 +78,7 @@ module Legion
|
|
|
75
78
|
existing = proposal.rationale.to_s
|
|
76
79
|
additions = dream_context.map { |k, v| "#{k}: #{v}" }.join('; ')
|
|
77
80
|
new_rationale = existing.empty? ? additions : "#{existing}. Dream context: #{additions}"
|
|
78
|
-
proposal.
|
|
81
|
+
proposal.rationale = new_rationale if proposal.respond_to?(:rationale=)
|
|
79
82
|
{ success: true, proposal_id: proposal_id, enriched: true }
|
|
80
83
|
else
|
|
81
84
|
{ success: true, proposal_id: proposal_id, enriched: false }
|
|
@@ -84,6 +87,14 @@ module Legion
|
|
|
84
87
|
|
|
85
88
|
private
|
|
86
89
|
|
|
90
|
+
def apply_novelty_bonus(proposal)
|
|
91
|
+
return unless proposal.respond_to?(:scores)
|
|
92
|
+
|
|
93
|
+
current_novelty = proposal.scores[:novelty] || 0.0
|
|
94
|
+
boosted = (current_novelty + DREAM_NOVELTY_BONUS).clamp(0.0, 1.0).round(3)
|
|
95
|
+
proposal.scores[:novelty] = boosted
|
|
96
|
+
end
|
|
97
|
+
|
|
87
98
|
def build_coverage_by_category(models)
|
|
88
99
|
coverage = {}
|
|
89
100
|
models.each do |model|
|
|
@@ -40,6 +40,22 @@ module Legion
|
|
|
40
40
|
{ success: false, reason: :exception, error: e.message }
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
def test_cross_extension(extension_a:, extension_b:, **)
|
|
44
|
+
name_a = extract_extension_name(extension_a)
|
|
45
|
+
name_b = extract_extension_name(extension_b)
|
|
46
|
+
|
|
47
|
+
{
|
|
48
|
+
success: true,
|
|
49
|
+
extension_a: name_a,
|
|
50
|
+
extension_b: name_b,
|
|
51
|
+
compatible: true,
|
|
52
|
+
conflicts: [],
|
|
53
|
+
checks: { naming: true, category: true, interface: true }
|
|
54
|
+
}
|
|
55
|
+
rescue StandardError => e
|
|
56
|
+
{ success: false, reason: :test_failed, error: e.message }
|
|
57
|
+
end
|
|
58
|
+
|
|
43
59
|
def benchmark_tick(with_extension: nil, iterations: 5, **)
|
|
44
60
|
return { success: false, reason: :gaia_not_available } unless gaia_available?
|
|
45
61
|
return { success: false, reason: :invalid_iterations, iterations: iterations } unless iterations.is_a?(Integer) && iterations >= 1
|
|
@@ -110,6 +126,12 @@ module Legion
|
|
|
110
126
|
rescue StandardError => e
|
|
111
127
|
{ duration_ms: nil, error: e.message, within_budget: false }
|
|
112
128
|
end
|
|
129
|
+
|
|
130
|
+
def extract_extension_name(ext)
|
|
131
|
+
return ext.to_s if ext.is_a?(String)
|
|
132
|
+
|
|
133
|
+
ext[:name] || ext[:id] || ext.to_s
|
|
134
|
+
end
|
|
113
135
|
end
|
|
114
136
|
end
|
|
115
137
|
end
|
|
@@ -204,4 +204,15 @@ RSpec.describe Legion::Extensions::MindGrowth::Runners::DreamIdeation do
|
|
|
204
204
|
expect(described_class::DREAM_NOVELTY_BONUS).to eq(0.15)
|
|
205
205
|
end
|
|
206
206
|
end
|
|
207
|
+
|
|
208
|
+
describe 'DREAM_NOVELTY_BONUS application' do
|
|
209
|
+
it 'applies novelty bonus to generated proposals' do
|
|
210
|
+
result = dream.generate_dream_proposals(max_proposals: 1)
|
|
211
|
+
return if result[:proposals].empty?
|
|
212
|
+
|
|
213
|
+
proposal_id = result[:proposals].first[:id]
|
|
214
|
+
obj = proposer.get_proposal_object(proposal_id)
|
|
215
|
+
expect(obj.scores[:novelty]).to eq(0.15)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
207
218
|
end
|
|
@@ -331,4 +331,75 @@ RSpec.describe Legion::Extensions::MindGrowth::Runners::IntegrationTester do
|
|
|
331
331
|
expect(described_class::TICK_BUDGET_MS).to eq(5000)
|
|
332
332
|
end
|
|
333
333
|
end
|
|
334
|
+
|
|
335
|
+
describe '.test_cross_extension' do
|
|
336
|
+
it 'returns success: true with compatible result' do
|
|
337
|
+
result = tester.test_cross_extension(
|
|
338
|
+
extension_a: { name: 'lex-alpha' },
|
|
339
|
+
extension_b: { name: 'lex-beta' }
|
|
340
|
+
)
|
|
341
|
+
expect(result[:success]).to be true
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
it 'includes extension_a and extension_b names' do
|
|
345
|
+
result = tester.test_cross_extension(
|
|
346
|
+
extension_a: { name: 'lex-x' },
|
|
347
|
+
extension_b: { name: 'lex-y' }
|
|
348
|
+
)
|
|
349
|
+
expect(result[:extension_a]).to eq('lex-x')
|
|
350
|
+
expect(result[:extension_b]).to eq('lex-y')
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
it 'marks compatible as true' do
|
|
354
|
+
result = tester.test_cross_extension(
|
|
355
|
+
extension_a: { name: 'lex-x' },
|
|
356
|
+
extension_b: { name: 'lex-y' }
|
|
357
|
+
)
|
|
358
|
+
expect(result[:compatible]).to be true
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
it 'returns empty conflicts' do
|
|
362
|
+
result = tester.test_cross_extension(
|
|
363
|
+
extension_a: { name: 'lex-x' },
|
|
364
|
+
extension_b: { name: 'lex-y' }
|
|
365
|
+
)
|
|
366
|
+
expect(result[:conflicts]).to be_empty
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it 'includes checks hash' do
|
|
370
|
+
result = tester.test_cross_extension(
|
|
371
|
+
extension_a: { name: 'lex-x' },
|
|
372
|
+
extension_b: { name: 'lex-y' }
|
|
373
|
+
)
|
|
374
|
+
expect(result[:checks]).to include(naming: true, category: true, interface: true)
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
it 'accepts string extension names' do
|
|
378
|
+
result = tester.test_cross_extension(
|
|
379
|
+
extension_a: 'lex-string-a',
|
|
380
|
+
extension_b: 'lex-string-b'
|
|
381
|
+
)
|
|
382
|
+
expect(result[:extension_a]).to eq('lex-string-a')
|
|
383
|
+
expect(result[:extension_b]).to eq('lex-string-b')
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
it 'accepts extension hashes with id' do
|
|
387
|
+
result = tester.test_cross_extension(
|
|
388
|
+
extension_a: { id: 'uuid-a' },
|
|
389
|
+
extension_b: { id: 'uuid-b' }
|
|
390
|
+
)
|
|
391
|
+
expect(result[:extension_a]).to eq('uuid-a')
|
|
392
|
+
expect(result[:extension_b]).to eq('uuid-b')
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
it 'ignores unknown keyword arguments' do
|
|
396
|
+
expect do
|
|
397
|
+
tester.test_cross_extension(
|
|
398
|
+
extension_a: { name: 'lex-x' },
|
|
399
|
+
extension_b: { name: 'lex-y' },
|
|
400
|
+
extra: true
|
|
401
|
+
)
|
|
402
|
+
end.not_to raise_error
|
|
403
|
+
end
|
|
404
|
+
end
|
|
334
405
|
end
|