lex-cognitive-genesis 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 51c3c248b9445d32001938679a1f261a013b248e3cfc00d6622a695ac78911ed
4
+ data.tar.gz: 8a2d4dd89cbf10fdd33cc35c61df22e384f1c5de3fd96c1c754bab5c42b098df
5
+ SHA512:
6
+ metadata.gz: bc41eb3e37f5d57373c4c4e3369033d22b1daaa95de9e3f324db16eefbe94b2e590c3d1161470ba4cbecc92703f25216f2b4f6d3d731de1ef2fa111d88b2ef6f
7
+ data.tar.gz: b1aa1db38cc13a7d2373b7b0144fc6bd834de39217a4acbbe6b35bad135f4b1cd203588a859649b547fb05df625ad94ff5ad74516dd5a7fabe1a9c654b7eeb31
@@ -0,0 +1,16 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+
7
+ jobs:
8
+ ci:
9
+ uses: LegionIO/.github/.github/workflows/ci.yml@main
10
+
11
+ release:
12
+ needs: ci
13
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
14
+ uses: LegionIO/.github/.github/workflows/release.yml@main
15
+ secrets:
16
+ rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.gem
10
+ .rspec_status
11
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --color
3
+ --format documentation
data/.rubocop.yml ADDED
@@ -0,0 +1,68 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.4
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+
6
+ Layout/LineLength:
7
+ Max: 160
8
+
9
+ Layout/SpaceAroundEqualsInParameterDefault:
10
+ EnforcedStyle: space
11
+
12
+ Layout/HashAlignment:
13
+ EnforcedHashRocketStyle: table
14
+ EnforcedColonStyle: table
15
+
16
+ Metrics/MethodLength:
17
+ Max: 25
18
+
19
+ Metrics/ClassLength:
20
+ Max: 200
21
+
22
+ Metrics/ModuleLength:
23
+ Max: 200
24
+
25
+ Metrics/BlockLength:
26
+ Max: 40
27
+ Exclude:
28
+ - 'spec/**/*'
29
+
30
+ Metrics/AbcSize:
31
+ Max: 30
32
+
33
+ Metrics/CyclomaticComplexity:
34
+ Max: 15
35
+
36
+ Metrics/PerceivedComplexity:
37
+ Max: 17
38
+
39
+ Metrics/ParameterLists:
40
+ Max: 8
41
+ MaxOptionalParameters: 8
42
+
43
+ Style/Documentation:
44
+ Enabled: false
45
+
46
+ Style/SymbolArray:
47
+ Enabled: true
48
+
49
+ Style/FrozenStringLiteralComment:
50
+ Enabled: true
51
+ EnforcedStyle: always
52
+
53
+ Style/OneClassPerFile:
54
+ Exclude:
55
+ - 'spec/spec_helper.rb'
56
+
57
+ Naming/FileName:
58
+ Enabled: false
59
+
60
+ Naming/PredicateMethod:
61
+ Enabled: false
62
+
63
+ Naming/PredicatePrefix:
64
+ Enabled: false
65
+
66
+ Naming/MethodParameterName:
67
+ Exclude:
68
+ - 'spec/**/*'
data/CLAUDE.md ADDED
@@ -0,0 +1,129 @@
1
+ # lex-cognitive-genesis
2
+
3
+ **Level 3 Leaf Documentation**
4
+ - **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
5
+ - **Gem**: `lex-cognitive-genesis`
6
+
7
+ ## Purpose
8
+
9
+ Models the emergence of new cognitive concepts from seeds. Seeds are planted with a germination potential; once potential exceeds the germination threshold they can be germinated. Germinated seeds become concepts only when they meet three simultaneous criteria: viability (fitness >= VIABILITY_THRESHOLD), novelty (novelty >= NOVELTY_THRESHOLD), and readiness (maturity stage). Concepts can be nurtured to increase fitness, pruned if stale, cross-pollinated to produce hybrid seeds, or adopted from external sources. Tracks genesis rate and novelty landscape across domains.
10
+
11
+ ## Gem Info
12
+
13
+ | Field | Value |
14
+ |---|---|
15
+ | Gem name | `lex-cognitive-genesis` |
16
+ | Version | `0.1.0` |
17
+ | Namespace | `Legion::Extensions::CognitiveGenesis` |
18
+ | Ruby | `>= 3.4` |
19
+ | License | MIT |
20
+ | GitHub | https://github.com/LegionIO/lex-cognitive-genesis |
21
+
22
+ ## File Structure
23
+
24
+ ```
25
+ lib/legion/extensions/cognitive_genesis/
26
+ cognitive_genesis.rb # Top-level require
27
+ version.rb # VERSION = '0.1.0'
28
+ client.rb # Client class
29
+ helpers/
30
+ constants.rb # Concept types, domains, stages, thresholds, 6 label hashes
31
+ seed.rb # Seed value object
32
+ concept.rb # Concept value object
33
+ genesis_engine.rb # Engine: seeds, concepts, germination, fitness, novelty
34
+ runners/
35
+ genesis.rb # Runner module
36
+ ```
37
+
38
+ ## Key Constants
39
+
40
+ | Constant | Value | Meaning |
41
+ |---|---|---|
42
+ | `CONCEPT_TYPES` | array | `[:idea, :theory, :hypothesis, :belief, :intention, :memory, :insight, :fantasy, :archetype, :symbol]` |
43
+ | `SOURCE_DOMAINS` | array | `[:experience, :observation, :inference, :intuition, :analogy, :synthesis, :dream, :external]` |
44
+ | `MATURITY_STAGES` | array | `[:nascent, :developing, :mature, :crystallized, :transcendent]` |
45
+ | `SEED_DOMAINS` | array | Various cognitive domains |
46
+ | `GERMINATION_THRESHOLD` | 0.7 | Minimum potential to attempt germination |
47
+ | `NOVELTY_THRESHOLD` | 0.5 | Minimum novelty for concept birth |
48
+ | `VIABILITY_THRESHOLD` | 0.4 | Minimum fitness for concept birth |
49
+ | `GENESIS_RATE_WINDOW` | last N | Rolling window for genesis rate calculation |
50
+
51
+ Label hashes: `MATURITY_LABELS`, `FITNESS_LABELS`, `NOVELTY_LABELS`, `POTENTIAL_LABELS`, `GENESIS_LABELS`, `ADOPTION_LABELS`.
52
+
53
+ ## Helpers
54
+
55
+ ### `Seed`
56
+
57
+ Pre-concept cognitive material awaiting germination.
58
+
59
+ - `initialize(domain:, source:, content:, potential: 0.5, seed_id: nil)`
60
+ - `potential`, `germinated?`, `germinate!` — marks as germinated
61
+ - `boost!(amount)` — increases potential, capped at 1.0
62
+ - `to_h`
63
+
64
+ ### `Concept`
65
+
66
+ A birthed cognitive entity with fitness, novelty, and maturity tracking.
67
+
68
+ - `initialize(concept_type:, domain:, content:, fitness: 0.5, novelty: 0.5, seed_id: nil, concept_id: nil)`
69
+ - `nurture!(amount)` — increases fitness
70
+ - `viable?` — fitness >= `VIABILITY_THRESHOLD`
71
+ - `novel?` — novelty >= `NOVELTY_THRESHOLD`
72
+ - `maturity_label`, `fitness_label`, `novelty_label`
73
+ - `to_h`
74
+
75
+ ### `GenesisEngine`
76
+
77
+ - `plant(domain:, source:, content:, potential: 0.5)` — creates Seed; returns `{ planted:, seed_id:, seed: }`
78
+ - `germinate(seed_id:)` — requires potential >= GERMINATION_THRESHOLD; returns Concept candidate or `{ germinated: false, reason: }`
79
+ - `birth(seed_id:)` — requires viable + novel + ready (germinated); stores in concept map; returns `{ born:, concept_id:, concept: }` or rejection
80
+ - `nurture(concept_id:, amount: 0.1)` — increases concept fitness
81
+ - `prune(seed_id:)` — removes seed from store
82
+ - `cross_pollinate(seed_a_id:, seed_b_id:)` — creates new seed combining domains and averaging potential
83
+ - `adopt_concept(concept_type:, domain:, content:, fitness: 0.5, novelty: 0.5)` — imports concept from external source
84
+ - `concept_fitness(concept_id:)` — returns fitness + label
85
+ - `novelty_landscape` — domain -> mean novelty map
86
+ - `genesis_rate` — concepts born per time window
87
+ - `most_adopted(limit: 10)`, `orphan_concepts(limit: 10)`
88
+ - `genesis_report` — full stats
89
+
90
+ ## Runners
91
+
92
+ **Module**: `Legion::Extensions::CognitiveGenesis::Runners::Genesis`
93
+
94
+ | Method | Key Args | Returns |
95
+ |---|---|---|
96
+ | `plant_seed` | `domain:`, `source:`, `content:`, `potential: 0.5` | `{ success:, seed_id:, seed: }` |
97
+ | `germinate_seed` | `seed_id:` | `{ success:, concept: }` or `{ success: false, reason: }` |
98
+ | `birth_concept` | `seed_id:` | `{ success:, concept_id:, concept: }` |
99
+ | `nurture_concept` | `concept_id:`, `amount: 0.1` | `{ success:, concept: }` |
100
+ | `prune_seed` | `seed_id:` | `{ success:, pruned: }` |
101
+ | `cross_pollinate` | `seed_a_id:`, `seed_b_id:` | `{ success:, seed_id:, seed: }` |
102
+ | `adopt_concept` | `concept_type:`, `domain:`, `content:` | `{ success:, concept_id:, concept: }` |
103
+ | `concept_fitness` | `concept_id:` | `{ success:, fitness:, label: }` |
104
+ | `novelty_landscape` | — | `{ success:, landscape: }` |
105
+ | `genesis_rate` | — | `{ success:, rate: }` |
106
+ | `most_adopted` | `limit: 10` | `{ success:, concepts: }` |
107
+ | `orphan_concepts` | `limit: 10` | `{ success:, concepts: }` |
108
+ | `genesis_report` | — | Full report hash |
109
+
110
+ Private: `genesis_engine` — memoized `GenesisEngine`. Logs via `log_debug` helper.
111
+
112
+ ## Integration Points
113
+
114
+ - **`lex-cognitive-furnace`**: Smelted alloys (insight, wisdom, synthesis) feed genesis as seeds or direct concept inputs. The furnace produces refined material; genesis turns that material into new concepts.
115
+ - **`lex-cognitive-garden`**: Mature, flowering garden plants are candidates for genesis seed planting or cross-pollination.
116
+ - **`lex-memory`**: Born concepts should be stored as semantic traces in lex-memory. `adopt_concept` is the primary path for ingesting concepts from external sources or other agents.
117
+ - **`lex-dream`**: Dream cycle outputs (agenda items, resolved contradictions) can be adopted as concepts via `adopt_concept`.
118
+
119
+ ## Development Notes
120
+
121
+ - `birth` is the gating step: a germinated seed's concept candidate must independently pass both viability (`fitness >= 0.4`) and novelty (`novelty >= 0.5`) checks. Germination alone is not sufficient.
122
+ - `cross_pollinate` does not consume source seeds; both remain in the store after producing a child seed.
123
+ - `orphan_concepts` returns concepts whose originating seed has been pruned.
124
+ - `genesis_rate` uses a rolling window; a cold engine with no births returns 0.0.
125
+ - In-memory only.
126
+
127
+ ---
128
+
129
+ **Maintained By**: Matthew Iverson (@Esity)
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :test do
8
+ gem 'rspec', '~> 3.13'
9
+ gem 'rubocop', '~> 1.75', require: false
10
+ gem 'rubocop-rspec', require: false
11
+ end
12
+
13
+ gem 'legion-gaia', path: '../../legion-gaia'
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # lex-cognitive-genesis
2
+
3
+ Cognitive concept emergence engine for brain-modeled agentic AI in the LegionIO ecosystem.
4
+
5
+ ## What It Does
6
+
7
+ Models how new cognitive concepts emerge from raw seeds. Seeds are planted with a germination potential; once potential exceeds the threshold (0.7), germination produces a concept candidate. That candidate only achieves full birth if it simultaneously passes viability (fitness >= 0.4) and novelty (>= 0.5) checks. Born concepts can be nurtured to increase fitness, cross-pollinated to produce hybrid seeds, or pruned. External concepts can be adopted directly. The engine tracks novelty distribution across domains and genesis rate over time.
8
+
9
+ ## Usage
10
+
11
+ ```ruby
12
+ require 'legion/extensions/cognitive_genesis'
13
+
14
+ client = Legion::Extensions::CognitiveGenesis::Client.new
15
+
16
+ # Plant a seed
17
+ result = client.plant_seed(domain: :engineering, source: :experience, content: 'fault-tolerant retry pattern', potential: 0.8)
18
+ seed_id = result[:seed_id]
19
+
20
+ # Germinate when potential is sufficient
21
+ germination = client.germinate_seed(seed_id: seed_id)
22
+ # => { success: true, concept: { fitness: 0.5, novelty: 0.6, ... } }
23
+
24
+ # Birth the concept if viable and novel
25
+ concept = client.birth_concept(seed_id: seed_id)
26
+ # => { success: true, concept_id: "...", concept: { ... } }
27
+
28
+ # Nurture to increase fitness
29
+ client.nurture_concept(concept_id: concept[:concept_id], amount: 0.15)
30
+
31
+ # Check novelty across domains
32
+ client.novelty_landscape
33
+ # => { success: true, landscape: { engineering: 0.6, ... } }
34
+
35
+ # Full genesis report
36
+ client.genesis_report
37
+ # => { success: true, report: { seed_count: 0, concept_count: 1, genesis_rate: 0.1, ... } }
38
+ ```
39
+
40
+ ## Development
41
+
42
+ ```bash
43
+ bundle install
44
+ bundle exec rspec
45
+ bundle exec rubocop
46
+ ```
47
+
48
+ ## License
49
+
50
+ MIT
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/legion/extensions/cognitive_genesis/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lex-cognitive-genesis'
7
+ spec.version = Legion::Extensions::CognitiveGenesis::VERSION
8
+ spec.authors = ['Esity']
9
+ spec.email = ['matthewdiverson@gmail.com']
10
+
11
+ spec.summary = 'LEX Cognitive Genesis'
12
+ spec.description = 'De novo concept creation for brain-modeled agentic AI — the 200th LegionIO cognitive extension. ' \
13
+ 'Seeds proto-concepts, germinates them into novel cognitive categories, and tracks their adoption.'
14
+ spec.homepage = 'https://github.com/LegionIO/lex-cognitive-genesis'
15
+ spec.license = 'MIT'
16
+ spec.required_ruby_version = '>= 3.4'
17
+
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-cognitive-genesis'
20
+ spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-genesis'
21
+ spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-genesis'
22
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-genesis/issues'
23
+ spec.metadata['rubygems_mfa_required'] = 'true'
24
+
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
+ end
28
+ spec.require_paths = ['lib']
29
+ spec.add_development_dependency 'legion-gaia'
30
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveGenesis
6
+ class Client
7
+ include Runners::Genesis
8
+
9
+ attr_reader :engine
10
+
11
+ def initialize(engine: nil, **)
12
+ @engine = engine || Helpers::GenesisEngine.new
13
+ end
14
+
15
+ private
16
+
17
+ def default_engine
18
+ @engine
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveGenesis
8
+ module Helpers
9
+ class Concept
10
+ attr_reader :concept_id, :name, :definition, :parent_seed_id, :domain, :born_at
11
+ attr_accessor :maturity, :connections, :utility_score, :adoption_count
12
+
13
+ def initialize(name:, definition:, parent_seed_id:, domain:,
14
+ maturity: 0.0, connections: [], utility_score: 0.0, adoption_count: 0)
15
+ unless Constants::SEED_DOMAINS.include?(domain.to_sym)
16
+ raise ArgumentError, "invalid domain: #{domain.inspect}; must be one of #{Constants::SEED_DOMAINS.inspect}"
17
+ end
18
+
19
+ @concept_id = SecureRandom.uuid
20
+ @name = name.to_s.freeze
21
+ @definition = definition.to_s.freeze
22
+ @parent_seed_id = parent_seed_id.to_s.freeze
23
+ @domain = domain.to_sym
24
+ @maturity = maturity.clamp(0.0, 1.0).round(10)
25
+ @connections = Array(connections).dup
26
+ @utility_score = utility_score.clamp(0.0, 1.0).round(10)
27
+ @adoption_count = adoption_count.to_i
28
+ @born_at = Time.now.utc
29
+ end
30
+
31
+ def maturity_label
32
+ Constants.label_for(Constants::MATURITY_LABELS, maturity)
33
+ end
34
+
35
+ def fitness_label
36
+ Constants.label_for(Constants::FITNESS_LABELS, utility_score)
37
+ end
38
+
39
+ def adopt!
40
+ @adoption_count += 1
41
+ @utility_score = (@utility_score + Constants::ADOPTION_BONUS).clamp(0.0, 1.0).round(10)
42
+ @maturity = (@maturity + Constants::MATURITY_BOOST).clamp(0.0, 1.0).round(10)
43
+ end
44
+
45
+ def nurture!(boost: Constants::MATURITY_BOOST)
46
+ @maturity = (@maturity + boost).clamp(0.0, 1.0).round(10)
47
+ end
48
+
49
+ def decay!(rate: Constants::MATURITY_DECAY)
50
+ @maturity = (@maturity - rate).clamp(0.0, 1.0).round(10)
51
+ end
52
+
53
+ def connect_to(concept_id)
54
+ @connections << concept_id unless @connections.include?(concept_id)
55
+ end
56
+
57
+ def orphan?
58
+ adoption_count.zero?
59
+ end
60
+
61
+ def to_h
62
+ {
63
+ concept_id: concept_id,
64
+ name: name,
65
+ definition: definition,
66
+ parent_seed_id: parent_seed_id,
67
+ domain: domain,
68
+ maturity: maturity,
69
+ maturity_label: maturity_label,
70
+ connections: connections,
71
+ utility_score: utility_score,
72
+ fitness_label: fitness_label,
73
+ adoption_count: adoption_count,
74
+ orphan: orphan?,
75
+ born_at: born_at
76
+ }
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveGenesis
6
+ module Helpers
7
+ module Constants
8
+ MAX_SEEDS = 200
9
+ MAX_CONCEPTS = 100
10
+
11
+ DEFAULT_GERMINATION = 0.3
12
+ GERMINATION_BOOST = 0.1
13
+ GERMINATION_THRESHOLD = 0.7
14
+
15
+ DEFAULT_NOVELTY = 0.5
16
+ NOVELTY_THRESHOLD = 0.5
17
+ VIABILITY_THRESHOLD = 0.4
18
+
19
+ MATURATION_RATE = 0.08
20
+ NOVELTY_DECAY = 0.02
21
+ SYNTHESIS_BONUS = 0.15
22
+ MATURITY_BOOST = 0.08
23
+ MATURITY_DECAY = 0.02
24
+ ADOPTION_BONUS = 0.05
25
+
26
+ CONCEPT_TYPES = %i[
27
+ fusion
28
+ abstraction
29
+ analogy
30
+ inversion
31
+ extrapolation
32
+ mutation
33
+ emergence
34
+ transcendence
35
+ ].freeze
36
+
37
+ SOURCE_DOMAINS = %i[
38
+ perception
39
+ memory
40
+ language
41
+ reasoning
42
+ emotion
43
+ social
44
+ embodiment
45
+ imagination
46
+ ].freeze
47
+
48
+ MATURITY_STAGES = %i[
49
+ germinal
50
+ embryonic
51
+ nascent
52
+ developing
53
+ viable
54
+ mature
55
+ crystallized
56
+ ].freeze
57
+
58
+ SEED_DOMAINS = %i[
59
+ linguistic
60
+ spatial
61
+ logical
62
+ interpersonal
63
+ aesthetic
64
+ procedural
65
+ abstract
66
+ emergent
67
+ ].freeze
68
+
69
+ GERMINATION_LABELS = {
70
+ (0.0...0.2) => :dormant,
71
+ (0.2...0.4) => :stirring,
72
+ (0.4...0.6) => :awakening,
73
+ (0.6...0.8) => :developing,
74
+ (0.8..1.0) => :ready
75
+ }.freeze
76
+
77
+ NOVELTY_LABELS = {
78
+ (0.0...0.2) => :derivative,
79
+ (0.2...0.4) => :recombinant,
80
+ (0.4..0.6) => :emergent,
81
+ (0.6...0.8) => :novel,
82
+ (0.8..1.0) => :unprecedented
83
+ }.freeze
84
+
85
+ MATURITY_LABELS = {
86
+ (0.0...0.2) => :nascent,
87
+ (0.2...0.4) => :fragile,
88
+ (0.4...0.6) => :establishing,
89
+ (0.6...0.8) => :stable,
90
+ (0.8..1.0) => :foundational
91
+ }.freeze
92
+
93
+ FITNESS_LABELS = {
94
+ (0.0...0.2) => :untested,
95
+ (0.2...0.4) => :experimental,
96
+ (0.4...0.6) => :promising,
97
+ (0.6...0.8) => :proven,
98
+ (0.8..1.0) => :essential
99
+ }.freeze
100
+
101
+ VIABILITY_LABELS = {
102
+ (0.8..1.0) => :strongly_viable,
103
+ (0.6...0.8) => :viable,
104
+ (0.4...0.6) => :marginal,
105
+ (0.2...0.4) => :tenuous,
106
+ (0.0...0.2) => :non_viable
107
+ }.freeze
108
+
109
+ FERTILITY_LABELS = {
110
+ (0.8..1.0) => :prolific,
111
+ (0.6...0.8) => :fertile,
112
+ (0.4...0.6) => :moderate,
113
+ (0.2...0.4) => :sparse,
114
+ (0.0...0.2) => :barren
115
+ }.freeze
116
+
117
+ def self.label_for(labels_hash, value)
118
+ clamped = value.clamp(0.0, 1.0)
119
+ labels_hash.each do |range, label|
120
+ return label if range.cover?(clamped)
121
+ end
122
+ labels_hash.values.last
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveGenesis
6
+ module Helpers
7
+ class GenesisEngine
8
+ include Constants
9
+
10
+ attr_reader :seeds, :concepts, :genesis_events
11
+
12
+ def initialize
13
+ @seeds = {}
14
+ @concepts = {}
15
+ @genesis_events = []
16
+ end
17
+
18
+ def plant(raw_material:, domain:, germination_potential: DEFAULT_GERMINATION,
19
+ novelty_score: 0.0, viability: 0.0, **)
20
+ return { planted: false, reason: :capacity_exceeded } if @seeds.size >= MAX_SEEDS
21
+
22
+ seed = Seed.new(
23
+ raw_material: raw_material,
24
+ domain: domain,
25
+ germination_potential: germination_potential,
26
+ novelty_score: novelty_score,
27
+ viability: viability
28
+ )
29
+ @seeds[seed.seed_id] = seed
30
+ Legion::Logging.debug "[cognitive_genesis] planted seed #{seed.seed_id[0..7]} " \
31
+ "domain=#{domain} novelty=#{novelty_score.round(3)}"
32
+ { planted: true, seed_id: seed.seed_id, seed: seed.to_h }
33
+ end
34
+
35
+ def germinate(seed_id:, boost: GERMINATION_BOOST, **)
36
+ seed = @seeds[seed_id]
37
+ return { germinated: false, reason: :not_found } unless seed
38
+
39
+ seed.germination_potential = (seed.germination_potential + boost).clamp(0.0, 1.0).round(10)
40
+ seed.viability = compute_viability(seed)
41
+
42
+ Legion::Logging.debug "[cognitive_genesis] germinated #{seed_id[0..7]} " \
43
+ "potential=#{seed.germination_potential.round(3)}"
44
+ { germinated: true, seed_id: seed_id,
45
+ germination_potential: seed.germination_potential,
46
+ viability: seed.viability,
47
+ label: seed.germination_label }
48
+ end
49
+
50
+ def birth(seed_id:, name:, definition:, **)
51
+ seed = @seeds[seed_id]
52
+ return { birthed: false, reason: :not_found } unless seed
53
+ return { birthed: false, reason: :not_viable } unless seed.viable?
54
+ return { birthed: false, reason: :not_novel } unless seed.novel?
55
+ return { birthed: false, reason: :not_ready } unless seed.ready_to_birth?
56
+ return { birthed: false, reason: :concept_capacity_exceeded } if @concepts.size >= MAX_CONCEPTS
57
+
58
+ concept = Concept.new(
59
+ name: name,
60
+ definition: definition,
61
+ parent_seed_id: seed_id,
62
+ domain: seed.domain
63
+ )
64
+ @concepts[concept.concept_id] = concept
65
+ @seeds.delete(seed_id)
66
+ record_genesis_event(concept: concept, seed: seed)
67
+
68
+ Legion::Logging.info "[cognitive_genesis] concept born: \"#{name}\" " \
69
+ "(#{concept.concept_id[0..7]}) domain=#{seed.domain}"
70
+ { birthed: true, concept_id: concept.concept_id, concept: concept.to_h }
71
+ end
72
+
73
+ def nurture(concept_id:, boost: MATURITY_BOOST, **)
74
+ concept = @concepts[concept_id]
75
+ return { nurtured: false, reason: :not_found } unless concept
76
+
77
+ concept.nurture!(boost: boost)
78
+ Legion::Logging.debug "[cognitive_genesis] nurtured #{concept_id[0..7]} " \
79
+ "maturity=#{concept.maturity.round(3)}"
80
+ { nurtured: true, concept_id: concept_id,
81
+ maturity: concept.maturity, label: concept.maturity_label }
82
+ end
83
+
84
+ def prune(seed_id:, **)
85
+ seed = @seeds.delete(seed_id)
86
+ return { pruned: false, reason: :not_found } unless seed
87
+
88
+ Legion::Logging.debug "[cognitive_genesis] pruned seed #{seed_id[0..7]}"
89
+ { pruned: true, seed_id: seed_id }
90
+ end
91
+
92
+ def cross_pollinate(seed_id_a:, seed_id_b:, **)
93
+ guard = cross_pollinate_guard(seed_id_a, seed_id_b)
94
+ return guard if guard
95
+
96
+ seed_a = @seeds[seed_id_a]
97
+ seed_b = @seeds[seed_id_b]
98
+ child_novelty = cross_novelty(seed_a.novelty_score, seed_b.novelty_score)
99
+ result = plant_cross_child(seed_a, seed_b, child_novelty)
100
+
101
+ Legion::Logging.debug '[cognitive_genesis] cross_pollinated ' \
102
+ "#{seed_id_a[0..7]}+#{seed_id_b[0..7]} -> #{result[:seed_id]&.slice(0, 8)}"
103
+ result.merge(cross_pollinated: true, parent_seed_ids: [seed_id_a, seed_id_b])
104
+ end
105
+
106
+ def adopt_concept(concept_id:, **)
107
+ concept = @concepts[concept_id]
108
+ return { adopted: false, reason: :not_found } unless concept
109
+
110
+ concept.adopt!
111
+ Legion::Logging.debug "[cognitive_genesis] adopted #{concept_id[0..7]} " \
112
+ "count=#{concept.adoption_count}"
113
+ { adopted: true, concept_id: concept_id,
114
+ adoption_count: concept.adoption_count,
115
+ utility_score: concept.utility_score,
116
+ maturity: concept.maturity }
117
+ end
118
+
119
+ def concept_fitness(concept_id:, **)
120
+ concept = @concepts[concept_id]
121
+ return { found: false } unless concept
122
+
123
+ { found: true,
124
+ concept_id: concept_id,
125
+ utility_score: concept.utility_score,
126
+ fitness_label: concept.fitness_label,
127
+ adoption_count: concept.adoption_count,
128
+ maturity: concept.maturity }
129
+ end
130
+
131
+ def novelty_landscape(**)
132
+ seeds_map = @seeds.values.map do |s|
133
+ { id: s.seed_id, type: :seed, score: s.novelty_score,
134
+ label: s.novelty_label, domain: s.domain }
135
+ end
136
+ concepts_map = @concepts.values.map do |c|
137
+ { id: c.concept_id, type: :concept, score: 0.0, label: :n_a, domain: c.domain }
138
+ end
139
+ {
140
+ seeds: seeds_map,
141
+ concepts: concepts_map,
142
+ avg_seed_novelty: avg_values(@seeds.values.map(&:novelty_score)),
143
+ high_novelty_seeds: @seeds.values.count(&:novel?)
144
+ }
145
+ end
146
+
147
+ def genesis_rate(**)
148
+ return { rate: 0.0, total_events: 0 } if @genesis_events.empty?
149
+
150
+ oldest = @genesis_events.min_by { |e| e[:born_at] }[:born_at]
151
+ elapsed_hours = [(Time.now.utc - oldest) / 3600.0, 1.0].max
152
+ rate = @genesis_events.size / elapsed_hours
153
+ { rate: rate.round(10),
154
+ total_events: @genesis_events.size,
155
+ elapsed_hours: elapsed_hours.round(4) }
156
+ end
157
+
158
+ def most_adopted(**)
159
+ return nil if @concepts.empty?
160
+
161
+ @concepts.values.max_by(&:adoption_count)&.to_h
162
+ end
163
+
164
+ def orphan_concepts(**)
165
+ @concepts.values.select(&:orphan?).map(&:to_h)
166
+ end
167
+
168
+ def genesis_report(**)
169
+ {
170
+ seeds: @seeds.size,
171
+ concepts: @concepts.size,
172
+ genesis_events: @genesis_events.size,
173
+ genesis_rate: genesis_rate,
174
+ orphan_count: orphan_concepts.size,
175
+ most_adopted: most_adopted,
176
+ avg_seed_novelty: avg_values(@seeds.values.map(&:novelty_score)),
177
+ avg_concept_maturity: avg_values(@concepts.values.map(&:maturity)),
178
+ domains_active: active_domains
179
+ }
180
+ end
181
+
182
+ private
183
+
184
+ def cross_pollinate_guard(seed_id_a, seed_id_b)
185
+ return { cross_pollinated: false, reason: :seed_a_not_found } unless @seeds[seed_id_a]
186
+ return { cross_pollinated: false, reason: :seed_b_not_found } unless @seeds[seed_id_b]
187
+ return { cross_pollinated: false, reason: :capacity_exceeded } if @seeds.size >= MAX_SEEDS
188
+
189
+ nil
190
+ end
191
+
192
+ def plant_cross_child(seed_a, seed_b, child_novelty)
193
+ combined_viability = ((seed_a.viability + seed_b.viability) / 2.0).round(10)
194
+ plant(
195
+ raw_material: (seed_a.raw_material + seed_b.raw_material).uniq,
196
+ domain: pick_domain(seed_a.domain, seed_b.domain, child_novelty),
197
+ germination_potential: DEFAULT_GERMINATION + GERMINATION_BOOST,
198
+ novelty_score: child_novelty,
199
+ viability: combined_viability
200
+ )
201
+ end
202
+
203
+ def compute_viability(seed)
204
+ material_factor = [seed.raw_material.size / 5.0, 1.0].min
205
+ novelty_factor = seed.novelty_score
206
+ potential_factor = seed.germination_potential
207
+ ((material_factor * 0.3) + (novelty_factor * 0.4) + (potential_factor * 0.3)).clamp(0.0, 1.0).round(10)
208
+ end
209
+
210
+ def cross_novelty(score_a, score_b)
211
+ base = [score_a, score_b].max
212
+ synergy = (score_a - score_b).abs * 0.5
213
+ (base + synergy + GERMINATION_BOOST).clamp(0.0, 1.0).round(10)
214
+ end
215
+
216
+ def pick_domain(domain_a, domain_b, novelty)
217
+ return :emergent if novelty >= 0.8
218
+ return domain_a if domain_a == domain_b
219
+
220
+ novelty >= 0.6 ? :abstract : domain_a
221
+ end
222
+
223
+ def avg_values(values)
224
+ return 0.0 if values.empty?
225
+
226
+ (values.sum / values.size.to_f).round(10)
227
+ end
228
+
229
+ def active_domains
230
+ all_domains = @seeds.values.map(&:domain) + @concepts.values.map(&:domain)
231
+ all_domains.tally
232
+ end
233
+
234
+ def record_genesis_event(concept:, seed:)
235
+ @genesis_events << {
236
+ concept_id: concept.concept_id,
237
+ name: concept.name,
238
+ domain: concept.domain,
239
+ seed_id: seed.seed_id,
240
+ born_at: concept.born_at
241
+ }
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveGenesis
8
+ module Helpers
9
+ class Seed
10
+ attr_reader :seed_id, :raw_material, :domain, :created_at
11
+ attr_accessor :germination_potential, :novelty_score, :viability
12
+
13
+ def initialize(raw_material:, domain:, germination_potential: Constants::DEFAULT_GERMINATION,
14
+ novelty_score: 0.0, viability: 0.0)
15
+ unless Constants::SEED_DOMAINS.include?(domain.to_sym)
16
+ raise ArgumentError, "invalid domain: #{domain.inspect}; must be one of #{Constants::SEED_DOMAINS.inspect}"
17
+ end
18
+
19
+ @seed_id = SecureRandom.uuid
20
+ @raw_material = Array(raw_material).freeze
21
+ @domain = domain.to_sym
22
+ @germination_potential = germination_potential.clamp(0.0, 1.0).round(10)
23
+ @novelty_score = novelty_score.clamp(0.0, 1.0).round(10)
24
+ @viability = viability.clamp(0.0, 1.0).round(10)
25
+ @created_at = Time.now.utc
26
+ end
27
+
28
+ def germination_label
29
+ Constants.label_for(Constants::GERMINATION_LABELS, germination_potential)
30
+ end
31
+
32
+ def novelty_label
33
+ Constants.label_for(Constants::NOVELTY_LABELS, novelty_score)
34
+ end
35
+
36
+ def viable?
37
+ viability >= Constants::VIABILITY_THRESHOLD
38
+ end
39
+
40
+ def novel?
41
+ novelty_score >= Constants::NOVELTY_THRESHOLD
42
+ end
43
+
44
+ def ready_to_birth?
45
+ germination_potential >= Constants::GERMINATION_THRESHOLD && viable? && novel?
46
+ end
47
+
48
+ def to_h
49
+ {
50
+ seed_id: seed_id,
51
+ raw_material: raw_material,
52
+ domain: domain,
53
+ germination_potential: germination_potential,
54
+ novelty_score: novelty_score,
55
+ viability: viability,
56
+ germination_label: germination_label,
57
+ novelty_label: novelty_label,
58
+ ready_to_birth: ready_to_birth?,
59
+ created_at: created_at
60
+ }
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveGenesis
6
+ module Runners
7
+ module Genesis
8
+ def plant_seed(raw_material:, domain:, engine: nil,
9
+ germination_potential: Helpers::Constants::DEFAULT_GERMINATION,
10
+ novelty_score: 0.0, viability: 0.0, **)
11
+ e = engine || default_engine
12
+ result = e.plant(raw_material: raw_material, domain: domain,
13
+ germination_potential: germination_potential,
14
+ novelty_score: novelty_score, viability: viability)
15
+ { success: result[:planted], **result }
16
+ end
17
+
18
+ def germinate_seed(seed_id:, engine: nil, boost: Helpers::Constants::GERMINATION_BOOST, **)
19
+ e = engine || default_engine
20
+ result = e.germinate(seed_id: seed_id, boost: boost)
21
+ { success: result[:germinated], **result }
22
+ end
23
+
24
+ def birth_concept(seed_id:, name:, definition:, engine: nil, **)
25
+ e = engine || default_engine
26
+ result = e.birth(seed_id: seed_id, name: name, definition: definition)
27
+ { success: result[:birthed], **result }
28
+ end
29
+
30
+ def nurture_concept(concept_id:, engine: nil, boost: Helpers::Constants::MATURITY_BOOST, **)
31
+ e = engine || default_engine
32
+ result = e.nurture(concept_id: concept_id, boost: boost)
33
+ { success: result[:nurtured], **result }
34
+ end
35
+
36
+ def prune_seed(seed_id:, engine: nil, **)
37
+ e = engine || default_engine
38
+ result = e.prune(seed_id: seed_id)
39
+ { success: result[:pruned], **result }
40
+ end
41
+
42
+ def cross_pollinate(seed_id_a:, seed_id_b:, engine: nil, **)
43
+ e = engine || default_engine
44
+ result = e.cross_pollinate(seed_id_a: seed_id_a, seed_id_b: seed_id_b)
45
+ { success: result[:cross_pollinated], **result }
46
+ end
47
+
48
+ def adopt_concept(concept_id:, engine: nil, **)
49
+ e = engine || default_engine
50
+ result = e.adopt_concept(concept_id: concept_id)
51
+ { success: result[:adopted], **result }
52
+ end
53
+
54
+ def concept_fitness(concept_id:, engine: nil, **)
55
+ e = engine || default_engine
56
+ result = e.concept_fitness(concept_id: concept_id)
57
+ { success: result[:found], **result }
58
+ end
59
+
60
+ def novelty_landscape(engine: nil, **)
61
+ e = engine || default_engine
62
+ landscape = e.novelty_landscape
63
+ { success: true, **landscape }
64
+ end
65
+
66
+ def genesis_rate(engine: nil, **)
67
+ e = engine || default_engine
68
+ result = e.genesis_rate
69
+ { success: true, **result }
70
+ end
71
+
72
+ def most_adopted(engine: nil, **)
73
+ e = engine || default_engine
74
+ concept = e.most_adopted
75
+ { success: true, concept: concept }
76
+ end
77
+
78
+ def orphan_concepts(engine: nil, **)
79
+ e = engine || default_engine
80
+ orphans = e.orphan_concepts
81
+ { success: true, orphans: orphans, count: orphans.size }
82
+ end
83
+
84
+ def genesis_report(engine: nil, **)
85
+ e = engine || default_engine
86
+ report = e.genesis_report
87
+ { success: true, **report }
88
+ end
89
+
90
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
91
+
92
+ private
93
+
94
+ def default_engine
95
+ @default_engine ||= Helpers::GenesisEngine.new
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveGenesis
6
+ VERSION = '0.1.0'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/cognitive_genesis/version'
4
+ require 'legion/extensions/cognitive_genesis/helpers/constants'
5
+ require 'legion/extensions/cognitive_genesis/helpers/seed'
6
+ require 'legion/extensions/cognitive_genesis/helpers/concept'
7
+ require 'legion/extensions/cognitive_genesis/helpers/genesis_engine'
8
+ require 'legion/extensions/cognitive_genesis/runners/genesis'
9
+ require 'legion/extensions/cognitive_genesis/client'
10
+
11
+ module Legion
12
+ module Extensions
13
+ module CognitiveGenesis
14
+ extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
15
+ end
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lex-cognitive-genesis
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.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
+ - !ruby/object:Gem::Dependency
13
+ name: legion-gaia
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ description: De novo concept creation for brain-modeled agentic AI — the 200th LegionIO
27
+ cognitive extension. Seeds proto-concepts, germinates them into novel cognitive
28
+ categories, and tracks their adoption.
29
+ email:
30
+ - matthewdiverson@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".github/workflows/ci.yml"
36
+ - ".gitignore"
37
+ - ".rspec"
38
+ - ".rubocop.yml"
39
+ - CLAUDE.md
40
+ - Gemfile
41
+ - README.md
42
+ - lex-cognitive-genesis.gemspec
43
+ - lib/legion/extensions/cognitive_genesis.rb
44
+ - lib/legion/extensions/cognitive_genesis/client.rb
45
+ - lib/legion/extensions/cognitive_genesis/helpers/concept.rb
46
+ - lib/legion/extensions/cognitive_genesis/helpers/constants.rb
47
+ - lib/legion/extensions/cognitive_genesis/helpers/genesis_engine.rb
48
+ - lib/legion/extensions/cognitive_genesis/helpers/seed.rb
49
+ - lib/legion/extensions/cognitive_genesis/runners/genesis.rb
50
+ - lib/legion/extensions/cognitive_genesis/version.rb
51
+ homepage: https://github.com/LegionIO/lex-cognitive-genesis
52
+ licenses:
53
+ - MIT
54
+ metadata:
55
+ homepage_uri: https://github.com/LegionIO/lex-cognitive-genesis
56
+ source_code_uri: https://github.com/LegionIO/lex-cognitive-genesis
57
+ documentation_uri: https://github.com/LegionIO/lex-cognitive-genesis
58
+ changelog_uri: https://github.com/LegionIO/lex-cognitive-genesis
59
+ bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-genesis/issues
60
+ rubygems_mfa_required: 'true'
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '3.4'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubygems_version: 3.6.9
76
+ specification_version: 4
77
+ summary: LEX Cognitive Genesis
78
+ test_files: []