lex-cognitive-metabolism 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: 19eba116503c91b42ca676c5b7a5252973d32f83a8772a52c1c653af91da343b
4
+ data.tar.gz: d0f46b89bb8b79e725f43472ca8df65c30fe2053cefc2376d2d3d2f044631cfc
5
+ SHA512:
6
+ metadata.gz: d574a9365e90c4113e59f6f41663b7acc5329cab7ed0f0557c28b466f70d34fb91fc3f49342bae457104f5bc47349a3b3a862cf1805caf2faced0f693466063a
7
+ data.tar.gz: c8d3ef82f31d6270c0928961d5bf00b5413738ca33d2252148cbb15d3aaf93d19bcb308a6b0975ea890eb5d92136b71c876b6efe1a8031b1fdf21e5cea29f0e2
@@ -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,2 @@
1
+ --require spec_helper
2
+ --format documentation
data/.rubocop.yml ADDED
@@ -0,0 +1,58 @@
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/ParameterLists:
34
+ Max: 8
35
+ MaxOptionalParameters: 8
36
+
37
+ Style/Documentation:
38
+ Enabled: false
39
+
40
+ Style/SymbolArray:
41
+ Enabled: true
42
+
43
+ Style/FrozenStringLiteralComment:
44
+ Enabled: true
45
+ EnforcedStyle: always
46
+
47
+ Style/OneClassPerFile:
48
+ Exclude:
49
+ - 'spec/spec_helper.rb'
50
+
51
+ Naming/FileName:
52
+ Enabled: false
53
+
54
+ Naming/PredicateMethod:
55
+ Enabled: false
56
+
57
+ Naming/PredicatePrefix:
58
+ Enabled: false
data/CLAUDE.md ADDED
@@ -0,0 +1,95 @@
1
+ # lex-cognitive-metabolism
2
+
3
+ **Level 3 Leaf Documentation**
4
+ - **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
5
+
6
+ ## Purpose
7
+
8
+ Energy reserve model for cognitive processing. Inspired by biological metabolism: spending energy on operations depletes reserves and degrades efficiency; recovery restores both. Catabolism converts complex structures into energy (breakdown for fuel); anabolism converts energy into structural value (building). Metabolic cycles track sequences of operations with timing and energy-per-operation metrics. Six operation types with defined costs: `perception` (5), `reasoning` (15), `creativity` (20), and others.
9
+
10
+ ## Gem Info
11
+
12
+ - **Gem name**: `lex-cognitive-metabolism`
13
+ - **Module**: `Legion::Extensions::CognitiveMetabolism`
14
+ - **Version**: `0.1.0`
15
+ - **Ruby**: `>= 3.4`
16
+ - **License**: MIT
17
+
18
+ ## File Structure
19
+
20
+ ```
21
+ lib/legion/extensions/cognitive_metabolism/
22
+ version.rb
23
+ client.rb
24
+ helpers/
25
+ constants.rb
26
+ energy_reserve.rb
27
+ metabolic_cycle.rb
28
+ runners/
29
+ cognitive_metabolism.rb
30
+ ```
31
+
32
+ ## Key Constants
33
+
34
+ | Constant | Value | Purpose |
35
+ |---|---|---|
36
+ | `MAX_ENERGY` | `1000.0` | Maximum energy reserve |
37
+ | `RESTING_METABOLIC_RATE` | `0.5` | Baseline energy consumed per idle cycle |
38
+ | `RECOVERY_RATE` | `2.0` | Energy restored per recovery unit |
39
+ | `EFFICIENCY_DECAY` | `0.01` | Efficiency reduction per energy-spending operation |
40
+ | `OPERATION_COSTS` | hash | Per-type energy costs (perception=5, reasoning=15, creativity=20, etc.) |
41
+ | `METABOLIC_STATES` | symbol array | `%i[hyperactive active resting recovering depleted]` |
42
+ | `STATE_THRESHOLDS` | hash | Energy ratio thresholds for each metabolic state |
43
+
44
+ ## Helpers
45
+
46
+ ### `Helpers::EnergyReserve`
47
+ Core energy tracker with efficiency modulator.
48
+
49
+ - `energy_ratio` — `energy / MAX_ENERGY`
50
+ - `state` — current metabolic state based on `energy_ratio` vs `STATE_THRESHOLDS`
51
+ - `depleted?` — energy at or below zero
52
+ - `spend!(operation_type)` — deducts operation cost divided by current efficiency; degrades efficiency by `EFFICIENCY_DECAY`
53
+ - `recover!(amount)` — restores energy by `amount * RECOVERY_RATE`; partially restores efficiency at `0.5x` rate
54
+ - `catabolize!(complexity)` — converts complexity * 10 into energy (breakdown)
55
+ - `anabolize!(energy_amount)` — converts energy_amount to `structure_value` via efficiency ratio
56
+
57
+ ### `Helpers::MetabolicCycle`
58
+ Records an operational cycle.
59
+
60
+ - `record_operation(type:, cost:)` — appends operation record
61
+ - `complete!` — marks cycle done, sets `completed_at`
62
+ - `duration_seconds` — wall-clock duration
63
+ - `average_energy_per_operation` — total cost / operation count
64
+
65
+ ## Runners
66
+
67
+ Module: `Runners::CognitiveMetabolism`
68
+
69
+ | Runner Method | Description |
70
+ |---|---|
71
+ | `create_reserve(initial_energy:)` | Initialize an energy reserve |
72
+ | `spend_energy(operation_type:)` | Spend energy on an operation |
73
+ | `recover(amount:)` | Restore energy and partial efficiency |
74
+ | `catabolize(complexity:)` | Convert complexity to energy |
75
+ | `anabolize(energy_amount:)` | Convert energy to structural value |
76
+ | `metabolic_status` | Current reserve state |
77
+ | `run_cycle(operations:)` | Execute a sequence of operations as a cycle |
78
+
79
+ All runners return `{success: true/false, ...}` hashes.
80
+
81
+ ## Integration Points
82
+
83
+ - `lex-tick` integration: `metabolic_status` can gate whether full-active mode is available (depleted reserve → fallback to sentinel)
84
+ - `lex-cognitive-load`: extraneous load maps to energy overhead; reducing extraneous load = recovering energy
85
+ - `lex-emotion` arousal correlates with energy level: depleted → low arousal
86
+ - `lex-dream` dormant_active cycle can trigger `recover` operations during idle consolidation
87
+ - Catabolism (breaking down old structures) parallels `lex-memory` decay: pruned traces release conceptual energy
88
+
89
+ ## Development Notes
90
+
91
+ - `Client` instantiates a single `EnergyReserve`; runners operate on it
92
+ - `spend!` cost is divided by efficiency: at `efficiency = 0.5`, operations cost double
93
+ - `recover!` restores efficiency at `0.5x` rate to prevent instant full reset after recovery
94
+ - `OPERATION_COSTS` keys must match the `operation_type:` argument to `spend_energy`; unknown types raise or return error
95
+ - `MetabolicCycle` is a lightweight record object; it does not hold a reference to the reserve
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rspec', '~> 3.13'
8
+ gem 'rubocop', '~> 1.75', require: false
9
+ gem 'rubocop-rspec', require: false
10
+ end
11
+
12
+ gem 'legion-gaia', path: '../../legion-gaia'
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Esity
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # lex-cognitive-metabolism
2
+
3
+ Energy reserve and metabolic cycle model for LegionIO cognitive agents. Operations consume energy and degrade efficiency; recovery restores both. Catabolism breaks down complexity into energy; anabolism converts energy into structural value.
4
+
5
+ ## What It Does
6
+
7
+ - Energy reserve with 5 metabolic states: hyperactive, active, resting, recovering, depleted
8
+ - Six operation types with defined costs (perception=5, reasoning=15, creativity=20)
9
+ - Efficiency modulator: spending energy degrades efficiency; higher operations cost more when efficiency is low
10
+ - Recovery restores energy and partially restores efficiency
11
+ - Catabolism: convert cognitive complexity into energy (useful during restructuring)
12
+ - Anabolism: convert energy into structural value (useful when building new patterns)
13
+ - Metabolic cycles: group sequences of operations with timing and cost metrics
14
+
15
+ ## Usage
16
+
17
+ ```ruby
18
+ # Create a reserve
19
+ runner.create_reserve(initial_energy: 500.0)
20
+
21
+ # Spend energy on operations
22
+ runner.spend_energy(operation_type: :reasoning)
23
+ # => { success: true, spent: 15.0, remaining: 485.0, efficiency: 0.49, state: :active }
24
+
25
+ runner.spend_energy(operation_type: :creativity)
26
+ # => { success: true, spent: 20.0 / efficiency, ... }
27
+
28
+ # Recover
29
+ runner.recover(amount: 10.0)
30
+ # => { success: true, restored: 20.0, efficiency_restored: 10.0, state: :active }
31
+
32
+ # Catabolize to gain energy from complexity
33
+ runner.catabolize(complexity: 5.0)
34
+ # => { success: true, energy_gained: 50.0 }
35
+
36
+ # Current status
37
+ runner.metabolic_status
38
+ # => { success: true, energy: 485.0, energy_ratio: 0.485, state: :active, efficiency: 0.49, ... }
39
+ ```
40
+
41
+ ## Development
42
+
43
+ ```bash
44
+ bundle install
45
+ bundle exec rspec
46
+ bundle exec rubocop
47
+ ```
48
+
49
+ ## License
50
+
51
+ MIT
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/legion/extensions/cognitive_metabolism/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lex-cognitive-metabolism'
7
+ spec.version = Legion::Extensions::CognitiveMetabolism::VERSION
8
+ spec.authors = ['Esity']
9
+ spec.email = ['matthewdiverson@gmail.com']
10
+
11
+ spec.summary = 'LEX Cognitive Metabolism'
12
+ spec.description = 'ATP-like cognitive energy system with metabolic cycles, catabolism, and anabolism for brain-modeled agentic AI'
13
+ spec.homepage = 'https://github.com/LegionIO/lex-cognitive-metabolism'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = '>= 3.4'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-cognitive-metabolism'
19
+ spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-metabolism'
20
+ spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-metabolism'
21
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-metabolism/issues'
22
+ spec.metadata['rubygems_mfa_required'] = 'true'
23
+
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ end
27
+ spec.require_paths = ['lib']
28
+ spec.add_development_dependency 'legion-gaia'
29
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/cognitive_metabolism/helpers/constants'
4
+ require 'legion/extensions/cognitive_metabolism/helpers/energy_reserve'
5
+ require 'legion/extensions/cognitive_metabolism/helpers/metabolic_cycle'
6
+ require 'legion/extensions/cognitive_metabolism/helpers/metabolism_engine'
7
+ require 'legion/extensions/cognitive_metabolism/runners/cognitive_metabolism'
8
+
9
+ module Legion
10
+ module Extensions
11
+ module CognitiveMetabolism
12
+ class Client
13
+ include Runners::CognitiveMetabolism
14
+
15
+ def initialize(**)
16
+ @engine = Helpers::MetabolismEngine.new
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :engine
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveMetabolism
6
+ module Helpers
7
+ module Constants
8
+ MAX_ENERGY = 1000.0
9
+ RESTING_METABOLIC_RATE = 0.5
10
+ RECOVERY_RATE = 2.0
11
+ EFFICIENCY_DECAY = 0.01
12
+
13
+ OPERATION_COSTS = {
14
+ perception: 5.0,
15
+ memory_retrieval: 8.0,
16
+ reasoning: 15.0,
17
+ creativity: 20.0,
18
+ decision: 12.0,
19
+ communication: 10.0
20
+ }.freeze
21
+
22
+ METABOLIC_STATES = %i[optimal efficient normal strained depleted].freeze
23
+
24
+ STATE_THRESHOLDS = {
25
+ optimal: (0.8..),
26
+ efficient: (0.6...0.8),
27
+ normal: (0.4...0.6),
28
+ strained: (0.15...0.4),
29
+ depleted: (..0.15)
30
+ }.freeze
31
+
32
+ module_function
33
+
34
+ def label_for(energy_ratio)
35
+ ratio = energy_ratio.clamp(0.0, 1.0)
36
+ STATE_THRESHOLDS.each do |state, range|
37
+ return state if range.cover?(ratio)
38
+ end
39
+ :depleted
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveMetabolism
8
+ module Helpers
9
+ class EnergyReserve
10
+ include Constants
11
+
12
+ attr_reader :id, :current_energy, :max_energy, :metabolic_rate, :efficiency, :created_at
13
+
14
+ def initialize(max_energy: MAX_ENERGY, metabolic_rate: RESTING_METABOLIC_RATE, efficiency: 1.0)
15
+ @id = SecureRandom.uuid
16
+ @max_energy = max_energy.clamp(1.0, Float::INFINITY)
17
+ @current_energy = @max_energy
18
+ @metabolic_rate = metabolic_rate.clamp(0.0, Float::INFINITY)
19
+ @efficiency = efficiency.clamp(0.0, 1.0)
20
+ @created_at = Time.now.utc
21
+ end
22
+
23
+ def energy_ratio
24
+ (@current_energy / @max_energy).clamp(0.0, 1.0)
25
+ end
26
+
27
+ def state
28
+ Constants.label_for(energy_ratio)
29
+ end
30
+
31
+ def depleted?
32
+ state == :depleted
33
+ end
34
+
35
+ def spend!(amount)
36
+ effective_cost = amount / @efficiency.clamp(0.01, 1.0)
37
+ before = @current_energy
38
+ @current_energy = (@current_energy - effective_cost).clamp(0.0, @max_energy)
39
+ @efficiency = (@efficiency - EFFICIENCY_DECAY).clamp(0.0, 1.0)
40
+ before - @current_energy
41
+ end
42
+
43
+ def recover!(amount)
44
+ before = @current_energy
45
+ @current_energy = (@current_energy + amount).clamp(0.0, @max_energy)
46
+ @efficiency = (@efficiency + (EFFICIENCY_DECAY * 0.5)).clamp(0.0, 1.0)
47
+ @current_energy - before
48
+ end
49
+
50
+ def catabolize!(complexity: 1.0)
51
+ energy_gained = (complexity * 10.0).round(10)
52
+ @current_energy = (@current_energy + energy_gained).clamp(0.0, @max_energy)
53
+ { energy_gained: energy_gained, current_energy: @current_energy.round(10), state: state }
54
+ end
55
+
56
+ def anabolize!(energy_cost: 5.0)
57
+ raise ArgumentError, 'insufficient energy for anabolism' if @current_energy < energy_cost
58
+
59
+ @current_energy = (@current_energy - energy_cost).clamp(0.0, @max_energy)
60
+ structure_value = (energy_cost * @efficiency).round(10)
61
+ { energy_spent: energy_cost, structure_value: structure_value, current_energy: @current_energy.round(10), state: state }
62
+ end
63
+
64
+ def to_h
65
+ {
66
+ id: @id,
67
+ current_energy: @current_energy.round(10),
68
+ max_energy: @max_energy,
69
+ metabolic_rate: @metabolic_rate,
70
+ efficiency: @efficiency.round(10),
71
+ energy_ratio: energy_ratio.round(10),
72
+ state: state,
73
+ depleted: depleted?,
74
+ created_at: @created_at
75
+ }
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveMetabolism
8
+ module Helpers
9
+ class MetabolicCycle
10
+ attr_reader :id, :cycle_count, :operations_log, :energy_spent_this_cycle, :started_at, :completed_at
11
+
12
+ def initialize
13
+ @id = SecureRandom.uuid
14
+ @cycle_count = 0
15
+ @operations_log = []
16
+ @energy_spent_this_cycle = 0.0
17
+ @started_at = Time.now.utc
18
+ @completed_at = nil
19
+ end
20
+
21
+ def record_operation(operation_type:, energy_spent:)
22
+ @operations_log << {
23
+ operation_type: operation_type,
24
+ energy_spent: energy_spent.round(10),
25
+ recorded_at: Time.now.utc
26
+ }
27
+ @energy_spent_this_cycle += energy_spent
28
+ @cycle_count += 1
29
+ end
30
+
31
+ def complete!
32
+ @completed_at = Time.now.utc
33
+ to_h
34
+ end
35
+
36
+ def duration_seconds
37
+ return nil unless @completed_at
38
+
39
+ (@completed_at - @started_at).round(4)
40
+ end
41
+
42
+ def average_energy_per_operation
43
+ return 0.0 if @cycle_count.zero?
44
+
45
+ (@energy_spent_this_cycle / @cycle_count).round(10)
46
+ end
47
+
48
+ def to_h
49
+ {
50
+ id: @id,
51
+ cycle_count: @cycle_count,
52
+ energy_spent_this_cycle: @energy_spent_this_cycle.round(10),
53
+ average_per_operation: average_energy_per_operation,
54
+ operations_log: @operations_log,
55
+ started_at: @started_at,
56
+ completed_at: @completed_at,
57
+ duration_seconds: duration_seconds
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveMetabolism
6
+ module Helpers
7
+ class MetabolismEngine
8
+ include Constants
9
+
10
+ MAX_EFFICIENCY_HISTORY = 200
11
+
12
+ def initialize
13
+ @reserves = {}
14
+ @efficiency_history = []
15
+ end
16
+
17
+ def create_reserve(max_energy: MAX_ENERGY, metabolic_rate: RESTING_METABOLIC_RATE, efficiency: 1.0)
18
+ reserve = EnergyReserve.new(max_energy: max_energy, metabolic_rate: metabolic_rate, efficiency: efficiency)
19
+ @reserves[reserve.id] = reserve
20
+ reserve
21
+ end
22
+
23
+ def spend_energy(reserve_id:, operation_type:)
24
+ reserve = fetch_reserve(reserve_id)
25
+ cost = OPERATION_COSTS.fetch(operation_type) do
26
+ raise ArgumentError, "Unknown operation type: #{operation_type.inspect}"
27
+ end
28
+ actual_spent = reserve.spend!(cost)
29
+ record_efficiency(reserve)
30
+ {
31
+ reserve_id: reserve_id,
32
+ operation_type: operation_type,
33
+ base_cost: cost,
34
+ actual_spent: actual_spent.round(10),
35
+ current_energy: reserve.current_energy.round(10),
36
+ state: reserve.state
37
+ }
38
+ end
39
+
40
+ def recover(reserve_id:, duration: 1.0)
41
+ reserve = fetch_reserve(reserve_id)
42
+ amount = (RECOVERY_RATE * duration.clamp(0.0, Float::INFINITY)).round(10)
43
+ gained = reserve.recover!(amount)
44
+ record_efficiency(reserve)
45
+ {
46
+ reserve_id: reserve_id,
47
+ duration: duration,
48
+ energy_gained: gained.round(10),
49
+ current_energy: reserve.current_energy.round(10),
50
+ state: reserve.state
51
+ }
52
+ end
53
+
54
+ def catabolize(reserve_id:, complexity: 1.0)
55
+ reserve = fetch_reserve(reserve_id)
56
+ result = reserve.catabolize!(complexity: complexity)
57
+ result.merge(reserve_id: reserve_id)
58
+ end
59
+
60
+ def anabolize(reserve_id:, energy_cost: 5.0)
61
+ reserve = fetch_reserve(reserve_id)
62
+ result = reserve.anabolize!(energy_cost: energy_cost)
63
+ result.merge(reserve_id: reserve_id)
64
+ end
65
+
66
+ def run_cycle(reserve_id:, operations: [])
67
+ reserve = fetch_reserve(reserve_id)
68
+ cycle = MetabolicCycle.new
69
+
70
+ operations.each do |op_type|
71
+ cost_base = OPERATION_COSTS.fetch(op_type, 0.0)
72
+ reserve.spend!(cost_base) if cost_base > 0.0
73
+ cycle.record_operation(operation_type: op_type, energy_spent: cost_base)
74
+ end
75
+
76
+ reserve.spend!(reserve.metabolic_rate)
77
+ cycle.record_operation(operation_type: :resting_rate, energy_spent: reserve.metabolic_rate)
78
+
79
+ cycle.complete!.merge(reserve_state: reserve.state, reserve_energy: reserve.current_energy.round(10))
80
+ end
81
+
82
+ def metabolic_report(reserve_id:)
83
+ reserve = fetch_reserve(reserve_id)
84
+ {
85
+ reserve: reserve.to_h,
86
+ efficiency_history: efficiency_history_for(reserve_id)
87
+ }
88
+ end
89
+
90
+ def efficiency_history
91
+ @efficiency_history.dup
92
+ end
93
+
94
+ def all_reserves
95
+ @reserves.transform_values(&:to_h)
96
+ end
97
+
98
+ private
99
+
100
+ def fetch_reserve(id)
101
+ @reserves.fetch(id) { raise ArgumentError, "Unknown reserve: #{id.inspect}" }
102
+ end
103
+
104
+ def record_efficiency(reserve)
105
+ @efficiency_history << {
106
+ reserve_id: reserve.id,
107
+ efficiency: reserve.efficiency.round(10),
108
+ state: reserve.state,
109
+ recorded_at: Time.now.utc
110
+ }
111
+ @efficiency_history.shift while @efficiency_history.size > MAX_EFFICIENCY_HISTORY
112
+ end
113
+
114
+ def efficiency_history_for(reserve_id)
115
+ @efficiency_history.select { |e| e[:reserve_id] == reserve_id }
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveMetabolism
6
+ module Runners
7
+ module CognitiveMetabolism
8
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
9
+ Legion::Extensions::Helpers.const_defined?(:Lex)
10
+
11
+ def create_reserve(max_energy: Helpers::Constants::MAX_ENERGY,
12
+ metabolic_rate: Helpers::Constants::RESTING_METABOLIC_RATE,
13
+ efficiency: 1.0, **)
14
+ reserve = engine.create_reserve(max_energy: max_energy, metabolic_rate: metabolic_rate, efficiency: efficiency)
15
+ Legion::Logging.debug "[cognitive_metabolism] reserve created: id=#{reserve.id} max_energy=#{reserve.max_energy}"
16
+ { success: true, reserve: reserve.to_h }
17
+ rescue ArgumentError => e
18
+ { success: false, error: e.message }
19
+ end
20
+
21
+ def spend_energy(reserve_id:, operation_type:, **)
22
+ result = engine.spend_energy(reserve_id: reserve_id, operation_type: operation_type)
23
+ Legion::Logging.debug "[cognitive_metabolism] spend: reserve=#{reserve_id} op=#{operation_type} " \
24
+ "spent=#{result[:actual_spent]} state=#{result[:state]}"
25
+ { success: true }.merge(result)
26
+ rescue ArgumentError => e
27
+ { success: false, error: e.message }
28
+ end
29
+
30
+ def recover(reserve_id:, duration: 1.0, **)
31
+ result = engine.recover(reserve_id: reserve_id, duration: duration)
32
+ Legion::Logging.debug "[cognitive_metabolism] recover: reserve=#{reserve_id} " \
33
+ "gained=#{result[:energy_gained]} state=#{result[:state]}"
34
+ { success: true }.merge(result)
35
+ rescue ArgumentError => e
36
+ { success: false, error: e.message }
37
+ end
38
+
39
+ def catabolize(reserve_id:, complexity: 1.0, **)
40
+ result = engine.catabolize(reserve_id: reserve_id, complexity: complexity)
41
+ Legion::Logging.debug "[cognitive_metabolism] catabolize: reserve=#{reserve_id} " \
42
+ "complexity=#{complexity} gained=#{result[:energy_gained]}"
43
+ { success: true }.merge(result)
44
+ rescue ArgumentError => e
45
+ { success: false, error: e.message }
46
+ end
47
+
48
+ def anabolize(reserve_id:, energy_cost: 5.0, **)
49
+ result = engine.anabolize(reserve_id: reserve_id, energy_cost: energy_cost)
50
+ Legion::Logging.debug "[cognitive_metabolism] anabolize: reserve=#{reserve_id} " \
51
+ "cost=#{energy_cost} value=#{result[:structure_value]}"
52
+ { success: true }.merge(result)
53
+ rescue ArgumentError => e
54
+ { success: false, error: e.message }
55
+ end
56
+
57
+ def metabolic_status(reserve_id:, **)
58
+ result = engine.metabolic_report(reserve_id: reserve_id)
59
+ Legion::Logging.debug "[cognitive_metabolism] status: reserve=#{reserve_id} state=#{result[:reserve][:state]}"
60
+ { success: true }.merge(result)
61
+ rescue ArgumentError => e
62
+ { success: false, error: e.message }
63
+ end
64
+
65
+ def run_cycle(reserve_id:, operations: [], **)
66
+ result = engine.run_cycle(reserve_id: reserve_id, operations: operations)
67
+ Legion::Logging.debug "[cognitive_metabolism] cycle: reserve=#{reserve_id} " \
68
+ "ops=#{result[:cycle_count]} spent=#{result[:energy_spent_this_cycle]} state=#{result[:reserve_state]}"
69
+ { success: true }.merge(result)
70
+ rescue ArgumentError => e
71
+ { success: false, error: e.message }
72
+ end
73
+
74
+ private
75
+
76
+ def engine
77
+ @engine ||= Helpers::MetabolismEngine.new
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveMetabolism
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 'legion/extensions/cognitive_metabolism/version'
5
+ require 'legion/extensions/cognitive_metabolism/helpers/constants'
6
+ require 'legion/extensions/cognitive_metabolism/helpers/energy_reserve'
7
+ require 'legion/extensions/cognitive_metabolism/helpers/metabolic_cycle'
8
+ require 'legion/extensions/cognitive_metabolism/helpers/metabolism_engine'
9
+ require 'legion/extensions/cognitive_metabolism/runners/cognitive_metabolism'
10
+ require 'legion/extensions/cognitive_metabolism/client'
11
+
12
+ module Legion
13
+ module Extensions
14
+ module CognitiveMetabolism
15
+ extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lex-cognitive-metabolism
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: ATP-like cognitive energy system with metabolic cycles, catabolism, and
27
+ anabolism for brain-modeled agentic AI
28
+ email:
29
+ - matthewdiverson@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".github/workflows/ci.yml"
35
+ - ".gitignore"
36
+ - ".rspec"
37
+ - ".rubocop.yml"
38
+ - CLAUDE.md
39
+ - Gemfile
40
+ - LICENSE
41
+ - README.md
42
+ - lex-cognitive-metabolism.gemspec
43
+ - lib/legion/extensions/cognitive_metabolism.rb
44
+ - lib/legion/extensions/cognitive_metabolism/client.rb
45
+ - lib/legion/extensions/cognitive_metabolism/helpers/constants.rb
46
+ - lib/legion/extensions/cognitive_metabolism/helpers/energy_reserve.rb
47
+ - lib/legion/extensions/cognitive_metabolism/helpers/metabolic_cycle.rb
48
+ - lib/legion/extensions/cognitive_metabolism/helpers/metabolism_engine.rb
49
+ - lib/legion/extensions/cognitive_metabolism/runners/cognitive_metabolism.rb
50
+ - lib/legion/extensions/cognitive_metabolism/version.rb
51
+ homepage: https://github.com/LegionIO/lex-cognitive-metabolism
52
+ licenses:
53
+ - MIT
54
+ metadata:
55
+ homepage_uri: https://github.com/LegionIO/lex-cognitive-metabolism
56
+ source_code_uri: https://github.com/LegionIO/lex-cognitive-metabolism
57
+ documentation_uri: https://github.com/LegionIO/lex-cognitive-metabolism
58
+ changelog_uri: https://github.com/LegionIO/lex-cognitive-metabolism
59
+ bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-metabolism/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 Metabolism
78
+ test_files: []