lex-cognitive-volcano 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: f79db54f8bbca323744fbb95f9efc778521d66e01ef25f9301eb8ec173374cb7
4
+ data.tar.gz: ed15b25b8ac357b18b2a7aa8d1ac76aa3201661cb3b3ad3bfde77caa43044037
5
+ SHA512:
6
+ metadata.gz: 828961a9d272b16adf514121b9599b10c2d52e343091a1a3ddeb5780563c0127a6e1639019a2d4c822ebb016fee231262cdc54e30f50ff700e58f48754cc7f39
7
+ data.tar.gz: d16173b4a14f96d9a5957d31ea775392aa8da6d495a9be6b0824a8cdff01811f6cc2e394e8266f5ddf94f41ee968e341eec01a109971ea551c2780b2e2ee5c52
@@ -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,2 @@
1
+ .rspec_status
2
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,64 @@
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: 150
21
+
22
+ Metrics/ModuleLength:
23
+ Max: 150
24
+
25
+ Metrics/BlockLength:
26
+ Max: 40
27
+ Exclude:
28
+ - 'spec/**/*'
29
+
30
+ Metrics/AbcSize:
31
+ Max: 25
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/OneClassPerFile:
47
+ Exclude:
48
+ - 'spec/spec_helper.rb'
49
+
50
+ Style/SymbolArray:
51
+ Enabled: true
52
+
53
+ Style/FrozenStringLiteralComment:
54
+ Enabled: true
55
+ EnforcedStyle: always
56
+
57
+ Naming/FileName:
58
+ Enabled: false
59
+
60
+ Naming/PredicateMethod:
61
+ Enabled: false
62
+
63
+ Naming/PredicatePrefix:
64
+ Enabled: false
data/CLAUDE.md ADDED
@@ -0,0 +1,121 @@
1
+ # lex-cognitive-volcano
2
+
3
+ **Level 3 Leaf Documentation**
4
+ - **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
5
+ - **Gem**: `lex-cognitive-volcano`
6
+ - **Version**: 0.1.0
7
+ - **Namespace**: `Legion::Extensions::CognitiveVolcano`
8
+
9
+ ## Purpose
10
+
11
+ Models cognitive pressure accumulation and eruption as a volcanic system. Magma units represent suppressed or building cognitive content (suppression, creativity, emotion, memory, frustration) that accumulate pressure over time. Chambers hold magma deposits and can erupt when critical-pressure magma is present. Eruption type is determined by the dominant magma type: suppression -> breakthrough, creativity -> insight, emotion/frustration -> outburst, memory -> catharsis.
12
+
13
+ ## Gem Info
14
+
15
+ - **Gemspec**: `lex-cognitive-volcano.gemspec`
16
+ - **Require**: `lex-cognitive-volcano`
17
+ - **Ruby**: >= 3.4
18
+ - **License**: MIT
19
+ - **Homepage**: https://github.com/LegionIO/lex-cognitive-volcano
20
+
21
+ ## File Structure
22
+
23
+ ```
24
+ lib/legion/extensions/cognitive_volcano/
25
+ version.rb
26
+ helpers/
27
+ constants.rb # Magma/eruption types, pressure/intensity label tables, thresholds
28
+ magma.rb # Magma class — one pressurizable cognitive deposit
29
+ chamber.rb # Chamber class — holds magma, can erupt
30
+ volcano_engine.rb # VolcanoEngine — registry for chambers and magma
31
+ runners/
32
+ cognitive_volcano.rb # Runner module — public API (extend self)
33
+ client.rb
34
+ ```
35
+
36
+ ## Key Constants
37
+
38
+ | Constant | Value | Meaning |
39
+ |---|---|---|
40
+ | `MAX_CHAMBERS` | 100 | Hard cap on chambers (raises if exceeded) |
41
+ | `PRESSURE_RATE` | 0.08 | Default pressure increase per `pressurize!` call |
42
+ | `ERUPTION_THRESHOLD` | 0.85 | Pressure >= this = critical magma |
43
+ | `COOLDOWN_RATE` | 0.03 | Pressure released per `cool_all!` tick |
44
+
45
+ `MAGMA_TYPES`: `[:suppression, :creativity, :emotion, :memory, :frustration]`
46
+
47
+ `ERUPTION_TYPES`: `[:breakthrough, :outburst, :insight, :catharsis]`
48
+
49
+ Eruption type mapping (by dominant magma): `suppression -> :breakthrough`, `creativity -> :insight`, `emotion -> :outburst`, `frustration -> :outburst`, `memory -> :catharsis`
50
+
51
+ Pressure labels: `0.0..0.2` = `:dormant`, `0.2..0.4` = `:building`, `0.4..0.6` = `:active`, `0.6..0.8` = `:elevated`, `0.8..1.0` = `:critical`
52
+
53
+ Intensity labels: `0.0..0.2` = `:minor`, `0.2..0.4` = `:moderate`, `0.4..0.6` = `:significant`, `0.6..0.8` = `:major`, `0.8..1.0` = `:cataclysmic`
54
+
55
+ ## Key Classes
56
+
57
+ ### `Helpers::Magma`
58
+
59
+ One pressurizable cognitive deposit.
60
+
61
+ - `pressurize!(rate:)` — increases pressure by rate (default `PRESSURE_RATE`)
62
+ - `release!(amount:)` — reduces pressure by at most `amount`; returns released amount
63
+ - `critical?` — pressure >= `ERUPTION_THRESHOLD`
64
+ - `dormant?` — pressure < 0.2
65
+ - `pressure_label` — label from `PRESSURE_LABELS`
66
+ - Invalid `magma_type` raises `ArgumentError`
67
+
68
+ ### `Helpers::Chamber`
69
+
70
+ A volcanic chamber holding magma deposits.
71
+
72
+ - `add_magma(magma)` — appends magma; raises temperature by 0.05 (capped at 1.0)
73
+ - `erupt!` — if no critical magma, returns `{ erupted: false, reason: :no_critical_magma }`; otherwise releases all critical magma, removes dormant deposits, lowers temperature by 0.2, lowers structural_integrity by 0.1, increments `eruption_count`; returns eruption event hash
74
+ - `reinforce!(amount:)` / `degrade!(amount:)` — adjust structural integrity
75
+ - `volatile?` — any critical magma OR structural_integrity < 0.3
76
+ - `stable?` — not volatile AND structural_integrity >= 0.7
77
+ - `average_pressure` — mean pressure across all magma deposits
78
+ - Eruption type determined by dominant magma type count via `ERUPTION_TYPE_MAP`
79
+
80
+ ### `Helpers::VolcanoEngine`
81
+
82
+ Registry for chambers and magma.
83
+
84
+ - `create_magma(magma_type:, domain:, content:, source:, pressure:)` — stores in `@magma_registry`
85
+ - `create_chamber(name:, temperature:, structural_integrity:)` — raises if at `MAX_CHAMBERS`
86
+ - `pressurize_magma(magma_id:, rate:)` — delegates to magma
87
+ - `trigger_eruption(chamber_id:)` — delegates to chamber's `erupt!`; records in `@eruption_history` (ring buffer, 500 max)
88
+ - `cool_all!(rate:)` — releases `rate` pressure from all non-dormant magma; returns count cooled
89
+ - `most_volatile` — chamber with highest `average_pressure`
90
+ - `pressure_report` — aggregate with critical count, volatile chamber count, eruption history size
91
+
92
+ Note: magma is stored in `@magma_registry` independently; chambers maintain `@magma_deposits` separately. Adding magma to the registry does NOT automatically add it to a chamber — that requires `chamber.add_magma(magma)`.
93
+
94
+ ## Runners
95
+
96
+ Module: `Legion::Extensions::CognitiveVolcano::Runners::CognitiveVolcano` (uses `extend self`)
97
+
98
+ | Runner | Key Args | Returns |
99
+ |---|---|---|
100
+ | `create_magma` | `magma_type:`, `domain:`, `content:`, `source:`, `pressure:` | `{ success:, magma: }` or `{ success: false, error: :invalid_magma_type }` |
101
+ | `create_chamber` | `name:`, `temperature:`, `structural_integrity:` | `{ success:, chamber: }` |
102
+ | `pressurize` | `magma_id:`, `rate:` | `{ success:, magma: }` or `{ success: false, error: :magma_not_found }` |
103
+ | `trigger_eruption` | `chamber_id:` | `{ success:, erupted:, eruption_type:, intensity:, ... }` |
104
+ | `list_chambers` | — | `{ success:, chambers:, count: }` |
105
+ | `pressure_status` | — | `{ success:, total_chambers:, critical_count:, average_pressure:, ... }` |
106
+
107
+ All runners accept optional `engine:` keyword for test injection.
108
+
109
+ ## Integration Points
110
+
111
+ - No actors defined; `cool_all!` and `pressurize_magma` must be triggered externally
112
+ - Can model emotional pressure build-up alongside `lex-emotion` for a complementary pressure+valence model
113
+ - `trigger_eruption` is the culminating action — represents sudden expressive release
114
+ - All state is in-memory per `VolcanoEngine` instance
115
+
116
+ ## Development Notes
117
+
118
+ - Magma and chambers are separate: magma must be explicitly added to a chamber via `chamber.add_magma(magma)` — the engine runners do not perform this linking automatically
119
+ - The runner's `trigger_eruption` merges `success:` after the fact: `result.merge(success: result[:erupted])`
120
+ - `erupt!` removes dormant deposits (pressure < 0.2) after releasing critical ones — slight behavior to be aware of in tests
121
+ - `VolcanoEngine#cool_all!` releases from `@magma_registry` (the flat registry), not from chamber deposits
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/Gemfile.lock ADDED
@@ -0,0 +1,78 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lex-cognitive-volcano (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ addressable (2.8.9)
10
+ public_suffix (>= 2.0.2, < 8.0)
11
+ ast (2.4.3)
12
+ bigdecimal (4.0.1)
13
+ diff-lcs (1.6.2)
14
+ json (2.19.1)
15
+ json-schema (6.2.0)
16
+ addressable (~> 2.8)
17
+ bigdecimal (>= 3.1, < 5)
18
+ language_server-protocol (3.17.0.5)
19
+ lint_roller (1.1.0)
20
+ mcp (0.8.0)
21
+ json-schema (>= 4.1)
22
+ parallel (1.27.0)
23
+ parser (3.3.10.2)
24
+ ast (~> 2.4.1)
25
+ racc
26
+ prism (1.9.0)
27
+ public_suffix (7.0.5)
28
+ racc (1.8.1)
29
+ rainbow (3.1.1)
30
+ regexp_parser (2.11.3)
31
+ rspec (3.13.2)
32
+ rspec-core (~> 3.13.0)
33
+ rspec-expectations (~> 3.13.0)
34
+ rspec-mocks (~> 3.13.0)
35
+ rspec-core (3.13.6)
36
+ rspec-support (~> 3.13.0)
37
+ rspec-expectations (3.13.5)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.13.0)
40
+ rspec-mocks (3.13.8)
41
+ diff-lcs (>= 1.2.0, < 2.0)
42
+ rspec-support (~> 3.13.0)
43
+ rspec-support (3.13.7)
44
+ rubocop (1.85.1)
45
+ json (~> 2.3)
46
+ language_server-protocol (~> 3.17.0.2)
47
+ lint_roller (~> 1.1.0)
48
+ mcp (~> 0.6)
49
+ parallel (~> 1.10)
50
+ parser (>= 3.3.0.2)
51
+ rainbow (>= 2.2.2, < 4.0)
52
+ regexp_parser (>= 2.9.3, < 3.0)
53
+ rubocop-ast (>= 1.49.0, < 2.0)
54
+ ruby-progressbar (~> 1.7)
55
+ unicode-display_width (>= 2.4.0, < 4.0)
56
+ rubocop-ast (1.49.1)
57
+ parser (>= 3.3.7.2)
58
+ prism (~> 1.7)
59
+ rubocop-rspec (3.9.0)
60
+ lint_roller (~> 1.1)
61
+ rubocop (~> 1.81)
62
+ ruby-progressbar (1.13.0)
63
+ unicode-display_width (3.2.0)
64
+ unicode-emoji (~> 4.1)
65
+ unicode-emoji (4.2.0)
66
+
67
+ PLATFORMS
68
+ arm64-darwin-25
69
+ ruby
70
+
71
+ DEPENDENCIES
72
+ lex-cognitive-volcano!
73
+ rspec (~> 3.13)
74
+ rubocop (~> 1.75)
75
+ rubocop-rspec
76
+
77
+ BUNDLED WITH
78
+ 2.6.9
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # lex-cognitive-volcano
2
+
3
+ A LegionIO cognitive architecture extension that models cognitive pressure accumulation and release as a volcanic system. Suppressed thoughts, creative impulses, and emotional energy accumulate as magma that pressurizes until a chamber erupts.
4
+
5
+ ## What It Does
6
+
7
+ Tracks **magma** — cognitive content of five types:
8
+
9
+ `suppression`, `creativity`, `emotion`, `memory`, `frustration`
10
+
11
+ Magma pressurizes over time. Once pressure reaches 0.85 (critical), it becomes eligible for eruption. **Chambers** hold magma deposits; when a chamber erupts, all critical magma releases and the eruption type is determined by the dominant magma:
12
+
13
+ - Suppression -> `:breakthrough`
14
+ - Creativity -> `:insight`
15
+ - Emotion/Frustration -> `:outburst`
16
+ - Memory -> `:catharsis`
17
+
18
+ ## Usage
19
+
20
+ ```ruby
21
+ require 'lex-cognitive-volcano'
22
+
23
+ client = Legion::Extensions::CognitiveVolcano::Client.new
24
+
25
+ # Create a volcanic chamber
26
+ chamber = client.create_chamber(name: 'emotional_pressure_chamber', temperature: 0.4)
27
+ # => { success: true, chamber: { chamber_id: "uuid...", volatile: false, stable: true, ... } }
28
+
29
+ chamber_id = chamber[:chamber][:chamber_id]
30
+
31
+ # Create magma units
32
+ m1 = client.create_magma(magma_type: :emotion, domain: :social, content: 'unresolved conflict', source: :interaction, pressure: 0.5)
33
+ # => { success: true, magma: { magma_id: "uuid...", pressure: 0.5, label: :active, critical: false, ... } }
34
+
35
+ # Pressurize magma
36
+ client.pressurize(magma_id: m1[:magma][:magma_id])
37
+ # => { success: true, magma: { pressure: 0.58, label: :active, critical: false, ... } }
38
+
39
+ # Pressurize repeatedly until critical
40
+ 8.times { client.pressurize(magma_id: m1[:magma][:magma_id]) }
41
+ client.pressurize(magma_id: m1[:magma][:magma_id])
42
+ # => { success: true, magma: { pressure: 0.86+, label: :critical, critical: true, ... } }
43
+
44
+ # Check system pressure
45
+ client.pressure_status
46
+ # => { success: true, critical_count: 1, average_pressure: 0.86, pressure_label: :critical, volatile_chambers: 0, ... }
47
+
48
+ # Trigger eruption from a chamber (requires magma added to chamber directly via Chamber#add_magma)
49
+ client.trigger_eruption(chamber_id: chamber_id)
50
+ # => { success: false, erupted: false, reason: :no_critical_magma }
51
+ # (Note: magma must be added to the chamber object to trigger eruption)
52
+
53
+ # List all chambers
54
+ client.list_chambers
55
+ # => { success: true, chambers: [...], count: 1 }
56
+ ```
57
+
58
+ ## Development
59
+
60
+ ```bash
61
+ bundle install
62
+ bundle exec rspec
63
+ bundle exec rubocop
64
+ ```
65
+
66
+ ## License
67
+
68
+ MIT
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/legion/extensions/cognitive_volcano/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lex-cognitive-volcano'
7
+ spec.version = Legion::Extensions::CognitiveVolcano::VERSION
8
+ spec.authors = ['Esity']
9
+ spec.email = ['matthewdiverson@gmail.com']
10
+
11
+ spec.summary = 'LEX Cognitive Volcano'
12
+ spec.description = 'Models cognitive pressure buildup and eruption cycles — suppressed thoughts accumulate ' \
13
+ 'pressure (like magma) until they erupt as breakthroughs, emotional outbursts, or creative explosions'
14
+ spec.homepage = 'https://github.com/LegionIO/lex-cognitive-volcano'
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-volcano'
20
+ spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-volcano'
21
+ spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-volcano'
22
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-volcano/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,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveVolcano
6
+ class Client
7
+ include Runners::CognitiveVolcano
8
+
9
+ attr_reader :engine
10
+
11
+ def initialize(engine: nil, **)
12
+ @engine = engine || Helpers::VolcanoEngine.new
13
+ end
14
+
15
+ def create_magma(magma_type:, domain:, content:, source:, pressure: 0.0, **)
16
+ super(magma_type: magma_type, domain: domain, content: content,
17
+ source: source, pressure: pressure, engine: @engine)
18
+ end
19
+
20
+ def create_chamber(name:, temperature: 0.5, structural_integrity: 1.0, **)
21
+ super(name: name, temperature: temperature,
22
+ structural_integrity: structural_integrity, engine: @engine)
23
+ end
24
+
25
+ def pressurize(magma_id:, rate: Helpers::Constants::PRESSURE_RATE, **)
26
+ super(magma_id: magma_id, rate: rate, engine: @engine)
27
+ end
28
+
29
+ def trigger_eruption(chamber_id:, **)
30
+ super(chamber_id: chamber_id, engine: @engine)
31
+ end
32
+
33
+ def list_chambers(**)
34
+ super(engine: @engine)
35
+ end
36
+
37
+ def pressure_status(**)
38
+ super(engine: @engine)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveVolcano
8
+ module Helpers
9
+ class Chamber
10
+ attr_reader :chamber_id, :name, :temperature, :structural_integrity, :magma_deposits, :eruption_count
11
+
12
+ def initialize(name:, temperature: 0.5, structural_integrity: 1.0)
13
+ @chamber_id = SecureRandom.uuid
14
+ @name = name
15
+ @temperature = temperature.clamp(0.0, 1.0)
16
+ @structural_integrity = structural_integrity.clamp(0.0, 1.0)
17
+ @magma_deposits = []
18
+ @eruption_count = 0
19
+ @created_at = Time.now.utc
20
+ end
21
+
22
+ def add_magma(magma)
23
+ raise ArgumentError, 'magma must be a Magma instance' unless magma.is_a?(Magma)
24
+
25
+ @magma_deposits << magma
26
+ @temperature = [@temperature + 0.05, 1.0].min
27
+ magma
28
+ end
29
+
30
+ def erupt!
31
+ critical = @magma_deposits.select(&:critical?)
32
+ return { erupted: false, reason: :no_critical_magma } if critical.empty?
33
+
34
+ eruption_type = determine_eruption_type(critical)
35
+ total_pressure = critical.sum(&:pressure)
36
+ avg_pressure = total_pressure / critical.size
37
+ intensity = avg_pressure.clamp(0.0, 1.0)
38
+
39
+ critical.each { |m| m.release!(amount: m.pressure) }
40
+ @magma_deposits.reject!(&:dormant?)
41
+
42
+ @temperature = [@temperature - 0.2, 0.0].max
43
+ @structural_integrity = [@structural_integrity - 0.1, 0.0].max
44
+ @eruption_count += 1
45
+
46
+ {
47
+ erupted: true,
48
+ chamber_id: @chamber_id,
49
+ eruption_type: eruption_type,
50
+ intensity: intensity.round(10),
51
+ intensity_label: Constants.label_for(Constants::INTENSITY_LABELS, intensity),
52
+ magma_count: critical.size,
53
+ domains: critical.map(&:domain).uniq,
54
+ erupted_at: Time.now.utc
55
+ }
56
+ end
57
+
58
+ def reinforce!(amount: 0.1)
59
+ @structural_integrity = [@structural_integrity + amount, 1.0].min
60
+ @structural_integrity
61
+ end
62
+
63
+ def degrade!(amount: 0.05)
64
+ @structural_integrity = [@structural_integrity - amount, 0.0].max
65
+ @structural_integrity
66
+ end
67
+
68
+ def volatile?
69
+ @magma_deposits.any?(&:critical?) || @structural_integrity < 0.3
70
+ end
71
+
72
+ def stable?
73
+ !volatile? && @structural_integrity >= 0.7
74
+ end
75
+
76
+ def average_pressure
77
+ return 0.0 if @magma_deposits.empty?
78
+
79
+ @magma_deposits.sum(&:pressure) / @magma_deposits.size
80
+ end
81
+
82
+ ERUPTION_TYPE_MAP = {
83
+ suppression: :breakthrough,
84
+ creativity: :insight,
85
+ emotion: :outburst,
86
+ memory: :catharsis,
87
+ frustration: :outburst
88
+ }.freeze
89
+
90
+ def to_h
91
+ {
92
+ chamber_id: @chamber_id,
93
+ name: @name,
94
+ temperature: @temperature.round(10),
95
+ structural_integrity: @structural_integrity.round(10),
96
+ magma_count: @magma_deposits.size,
97
+ average_pressure: average_pressure.round(10),
98
+ volatile: volatile?,
99
+ stable: stable?,
100
+ eruption_count: @eruption_count,
101
+ created_at: @created_at
102
+ }
103
+ end
104
+
105
+ private
106
+
107
+ def determine_eruption_type(critical_deposits)
108
+ type_counts = critical_deposits.each_with_object(Hash.new(0)) do |m, counts|
109
+ counts[m.magma_type] += 1
110
+ end
111
+
112
+ dominant = type_counts.max_by { |_type, count| count }&.first
113
+ ERUPTION_TYPE_MAP.fetch(dominant, :breakthrough)
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveVolcano
6
+ module Helpers
7
+ module Constants
8
+ MAGMA_TYPES = %i[suppression creativity emotion memory frustration].freeze
9
+ ERUPTION_TYPES = %i[breakthrough outburst insight catharsis].freeze
10
+
11
+ MAX_CHAMBERS = 100
12
+ PRESSURE_RATE = 0.08
13
+ ERUPTION_THRESHOLD = 0.85
14
+ COOLDOWN_RATE = 0.03
15
+
16
+ PRESSURE_LABELS = [
17
+ [0.0..0.2, :dormant],
18
+ [0.2..0.4, :building],
19
+ [0.4..0.6, :active],
20
+ [0.6..0.8, :elevated],
21
+ [0.8..1.0, :critical]
22
+ ].freeze
23
+
24
+ INTENSITY_LABELS = [
25
+ [0.0..0.2, :minor],
26
+ [0.2..0.4, :moderate],
27
+ [0.4..0.6, :significant],
28
+ [0.6..0.8, :major],
29
+ [0.8..1.0, :cataclysmic]
30
+ ].freeze
31
+
32
+ def self.label_for(table, value)
33
+ clamped = value.clamp(0.0, 1.0)
34
+ entry = table.find { |range, _label| range.cover?(clamped) }
35
+ entry ? entry[1] : table.last[1]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveVolcano
8
+ module Helpers
9
+ class Magma
10
+ attr_reader :magma_id, :magma_type, :domain, :content, :source, :created_at, :pressure
11
+
12
+ def initialize(magma_type:, domain:, content:, source:, pressure: 0.0)
13
+ unless Constants::MAGMA_TYPES.include?(magma_type)
14
+ raise ArgumentError, "unknown magma_type: #{magma_type.inspect}; " \
15
+ "must be one of #{Constants::MAGMA_TYPES.inspect}"
16
+ end
17
+
18
+ @magma_id = SecureRandom.uuid
19
+ @magma_type = magma_type
20
+ @domain = domain
21
+ @content = content
22
+ @source = source
23
+ @pressure = pressure.clamp(0.0, 1.0)
24
+ @created_at = Time.now.utc
25
+ end
26
+
27
+ def pressurize!(rate: Constants::PRESSURE_RATE)
28
+ @pressure = (@pressure + rate).clamp(0.0, 1.0)
29
+ @pressure
30
+ end
31
+
32
+ def release!(amount:)
33
+ released = [amount, @pressure].min
34
+ @pressure = (@pressure - released).clamp(0.0, 1.0)
35
+ released
36
+ end
37
+
38
+ def critical?
39
+ @pressure >= Constants::ERUPTION_THRESHOLD
40
+ end
41
+
42
+ def dormant?
43
+ @pressure < 0.2
44
+ end
45
+
46
+ def pressure_label
47
+ Constants.label_for(Constants::PRESSURE_LABELS, @pressure)
48
+ end
49
+
50
+ def to_h
51
+ {
52
+ magma_id: @magma_id,
53
+ magma_type: @magma_type,
54
+ domain: @domain,
55
+ content: @content,
56
+ source: @source,
57
+ pressure: @pressure.round(10),
58
+ label: pressure_label,
59
+ critical: critical?,
60
+ dormant: dormant?,
61
+ created_at: @created_at
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveVolcano
8
+ module Helpers
9
+ class VolcanoEngine
10
+ attr_reader :eruption_history
11
+
12
+ def initialize
13
+ @chambers = {}
14
+ @magma_registry = {}
15
+ @eruption_history = []
16
+ end
17
+
18
+ def create_magma(magma_type:, domain:, content:, source:, pressure: 0.0)
19
+ magma = Magma.new(
20
+ magma_type: magma_type,
21
+ domain: domain,
22
+ content: content,
23
+ source: source,
24
+ pressure: pressure
25
+ )
26
+ @magma_registry[magma.magma_id] = magma
27
+ magma
28
+ end
29
+
30
+ def create_chamber(name:, temperature: 0.5, structural_integrity: 1.0)
31
+ raise ArgumentError, "chamber limit of #{Constants::MAX_CHAMBERS} reached" if @chambers.size >= Constants::MAX_CHAMBERS
32
+
33
+ chamber = Chamber.new(
34
+ name: name,
35
+ temperature: temperature,
36
+ structural_integrity: structural_integrity
37
+ )
38
+ @chambers[chamber.chamber_id] = chamber
39
+ chamber
40
+ end
41
+
42
+ def pressurize_magma(magma_id:, rate: Constants::PRESSURE_RATE)
43
+ magma = @magma_registry.fetch(magma_id, nil)
44
+ return nil unless magma
45
+
46
+ magma.pressurize!(rate: rate)
47
+ magma
48
+ end
49
+
50
+ def trigger_eruption(chamber_id:)
51
+ chamber = @chambers.fetch(chamber_id, nil)
52
+ return { erupted: false, reason: :chamber_not_found } unless chamber
53
+
54
+ result = chamber.erupt!
55
+ if result[:erupted]
56
+ @eruption_history << result
57
+ @eruption_history.shift while @eruption_history.size > 500
58
+ end
59
+ result
60
+ end
61
+
62
+ def cool_all!(rate: Constants::COOLDOWN_RATE)
63
+ cooled = 0
64
+ @magma_registry.each_value do |magma|
65
+ next if magma.dormant?
66
+
67
+ magma.release!(amount: rate)
68
+ cooled += 1
69
+ end
70
+ cooled
71
+ end
72
+
73
+ def most_volatile
74
+ return nil if @chambers.empty?
75
+
76
+ @chambers.values.max_by(&:average_pressure)
77
+ end
78
+
79
+ def pressure_report
80
+ chambers_data = @chambers.values.map(&:to_h)
81
+ critical_magma = @magma_registry.values.select(&:critical?)
82
+ total_pressure = @magma_registry.values.sum(&:pressure)
83
+ avg_pressure = @magma_registry.empty? ? 0.0 : total_pressure / @magma_registry.size
84
+
85
+ {
86
+ total_chambers: @chambers.size,
87
+ total_magma: @magma_registry.size,
88
+ critical_count: critical_magma.size,
89
+ average_pressure: avg_pressure.round(10),
90
+ pressure_label: Constants.label_for(Constants::PRESSURE_LABELS, avg_pressure),
91
+ volatile_chambers: @chambers.values.count(&:volatile?),
92
+ eruption_count: @eruption_history.size,
93
+ chambers: chambers_data
94
+ }
95
+ end
96
+
97
+ def get_chamber(chamber_id)
98
+ @chambers[chamber_id]
99
+ end
100
+
101
+ def get_magma(magma_id)
102
+ @magma_registry[magma_id]
103
+ end
104
+
105
+ def all_chambers
106
+ @chambers.values
107
+ end
108
+
109
+ def all_magma
110
+ @magma_registry.values
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveVolcano
6
+ module Runners
7
+ module CognitiveVolcano
8
+ extend self
9
+
10
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
11
+
12
+ def create_magma(magma_type:, domain:, content:, source:, pressure: 0.0, engine: nil, **)
13
+ unless Helpers::Constants::MAGMA_TYPES.include?(magma_type)
14
+ return { success: false, error: :invalid_magma_type, valid_types: Helpers::Constants::MAGMA_TYPES }
15
+ end
16
+
17
+ magma = resolve_engine(engine).create_magma(
18
+ magma_type: magma_type,
19
+ domain: domain,
20
+ content: content,
21
+ source: source,
22
+ pressure: pressure
23
+ )
24
+
25
+ Legion::Logging.debug "[cognitive_volcano] created magma type=#{magma_type} domain=#{domain} " \
26
+ "pressure=#{magma.pressure.round(2)} id=#{magma.magma_id[0..7]}"
27
+
28
+ { success: true, magma: magma.to_h }
29
+ rescue ArgumentError => e
30
+ { success: false, error: e.message }
31
+ end
32
+
33
+ def create_chamber(name:, temperature: 0.5, structural_integrity: 1.0, engine: nil, **)
34
+ chamber = resolve_engine(engine).create_chamber(
35
+ name: name,
36
+ temperature: temperature,
37
+ structural_integrity: structural_integrity
38
+ )
39
+
40
+ Legion::Logging.debug "[cognitive_volcano] created chamber name=#{name} id=#{chamber.chamber_id[0..7]}"
41
+
42
+ { success: true, chamber: chamber.to_h }
43
+ rescue ArgumentError => e
44
+ { success: false, error: e.message }
45
+ end
46
+
47
+ def pressurize(magma_id:, rate: Helpers::Constants::PRESSURE_RATE, engine: nil, **)
48
+ magma = resolve_engine(engine).pressurize_magma(magma_id: magma_id, rate: rate)
49
+ return { success: false, error: :magma_not_found, magma_id: magma_id } unless magma
50
+
51
+ Legion::Logging.debug "[cognitive_volcano] pressurized magma=#{magma_id[0..7]} " \
52
+ "pressure=#{magma.pressure.round(2)} critical=#{magma.critical?}"
53
+
54
+ { success: true, magma: magma.to_h }
55
+ rescue ArgumentError => e
56
+ { success: false, error: e.message }
57
+ end
58
+
59
+ def trigger_eruption(chamber_id:, engine: nil, **)
60
+ result = resolve_engine(engine).trigger_eruption(chamber_id: chamber_id)
61
+
62
+ if result[:erupted]
63
+ Legion::Logging.info "[cognitive_volcano] eruption! chamber=#{chamber_id[0..7]} " \
64
+ "type=#{result[:eruption_type]} intensity=#{result[:intensity_label]}"
65
+ else
66
+ Legion::Logging.debug "[cognitive_volcano] no eruption chamber=#{chamber_id[0..7]} reason=#{result[:reason]}"
67
+ end
68
+
69
+ result.merge(success: result[:erupted])
70
+ rescue ArgumentError => e
71
+ { success: false, error: e.message }
72
+ end
73
+
74
+ def list_chambers(engine: nil, **)
75
+ chambers = resolve_engine(engine).all_chambers.map(&:to_h)
76
+ Legion::Logging.debug "[cognitive_volcano] list_chambers count=#{chambers.size}"
77
+ { success: true, chambers: chambers, count: chambers.size }
78
+ rescue ArgumentError => e
79
+ { success: false, error: e.message }
80
+ end
81
+
82
+ def pressure_status(engine: nil, **)
83
+ report = resolve_engine(engine).pressure_report
84
+ Legion::Logging.debug "[cognitive_volcano] pressure_status avg=#{report[:pressure_label]} " \
85
+ "critical=#{report[:critical_count]}"
86
+ report.merge(success: true)
87
+ rescue ArgumentError => e
88
+ { success: false, error: e.message }
89
+ end
90
+
91
+ private
92
+
93
+ def resolve_engine(engine)
94
+ engine || volcano_engine
95
+ end
96
+
97
+ def volcano_engine
98
+ @volcano_engine ||= Helpers::VolcanoEngine.new
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveVolcano
6
+ VERSION = '0.1.0'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require_relative 'cognitive_volcano/version'
5
+ require_relative 'cognitive_volcano/helpers/constants'
6
+ require_relative 'cognitive_volcano/helpers/magma'
7
+ require_relative 'cognitive_volcano/helpers/chamber'
8
+ require_relative 'cognitive_volcano/helpers/volcano_engine'
9
+ require_relative 'cognitive_volcano/runners/cognitive_volcano'
10
+ require_relative 'cognitive_volcano/client'
11
+
12
+ module Legion
13
+ module Extensions
14
+ module CognitiveVolcano
15
+ extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lex-cognitive-volcano
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: Models cognitive pressure buildup and eruption cycles — suppressed thoughts
27
+ accumulate pressure (like magma) until they erupt as breakthroughs, emotional outbursts,
28
+ or creative explosions
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
+ - Gemfile.lock
42
+ - README.md
43
+ - lex-cognitive-volcano.gemspec
44
+ - lib/legion/extensions/cognitive_volcano.rb
45
+ - lib/legion/extensions/cognitive_volcano/client.rb
46
+ - lib/legion/extensions/cognitive_volcano/helpers/chamber.rb
47
+ - lib/legion/extensions/cognitive_volcano/helpers/constants.rb
48
+ - lib/legion/extensions/cognitive_volcano/helpers/magma.rb
49
+ - lib/legion/extensions/cognitive_volcano/helpers/volcano_engine.rb
50
+ - lib/legion/extensions/cognitive_volcano/runners/cognitive_volcano.rb
51
+ - lib/legion/extensions/cognitive_volcano/version.rb
52
+ homepage: https://github.com/LegionIO/lex-cognitive-volcano
53
+ licenses:
54
+ - MIT
55
+ metadata:
56
+ homepage_uri: https://github.com/LegionIO/lex-cognitive-volcano
57
+ source_code_uri: https://github.com/LegionIO/lex-cognitive-volcano
58
+ documentation_uri: https://github.com/LegionIO/lex-cognitive-volcano
59
+ changelog_uri: https://github.com/LegionIO/lex-cognitive-volcano
60
+ bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-volcano/issues
61
+ rubygems_mfa_required: 'true'
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '3.4'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubygems_version: 3.6.9
77
+ specification_version: 4
78
+ summary: LEX Cognitive Volcano
79
+ test_files: []