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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9b428be29ef5df316acb3e4b9d6a01b826168046e1133e50c293e1ecc1a1186
4
- data.tar.gz: 7a38b04f5d93dea41f294cb0011a9f74511cd24bfe9687af792edc1940dcfd03
3
+ metadata.gz: 48176d28730ab5f2b56d9717240975b2c212c789afd5328ab45ebeae470c7c5d
4
+ data.tar.gz: 160ccb0ab88b31b5a946d776556ba3e0926231674747c278283a3356742f583c
5
5
  SHA512:
6
- metadata.gz: 33078449b48cf7cae04ceabd91690ae4900f47bc89275aab55005a2f1cb28242e5ef0780ef6321166b09e7b89a79b34b34afbd2d293243807a64c366c5303323
7
- data.tar.gz: 6d77136475fc7cde737949355135e60fa90891559f29f02ee71aa522e80d5be82cbbda09e41b16fc4293070eae6c9b0466acd564e1441700c326112905035ef6
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
- result = callable.call
61
- pipeline.advance!(result)
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&.instance_variable_set(:@origin, :dream)
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.instance_variable_set(:@rationale, new_rationale)
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
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module MindGrowth
6
- VERSION = '0.3.1'
6
+ VERSION = '0.3.2'
7
7
  end
8
8
  end
9
9
  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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-mind-growth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity