lex-cognitive-reserve 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: 04a0cf12dceaf349aae570d73ec6bcffa44517823ec37a406f7da90382fe2275
4
+ data.tar.gz: 7b29466016bf0208f477a3c1f318663fa1817780e9b9c39d3aefad12429b6d90
5
+ SHA512:
6
+ metadata.gz: c3f3c4a34212ebd84030f41a065c2b4bdff31a5d9066c89e4cbe946172a7f08ec285abe5ab83e65c8a250105efaad14f6368ab97665334ac5e54896111cc8dca
7
+ data.tar.gz: 78c46e884de31a6fbedb45c2fa328e4cd17ad589b656bc67da34a963fcc8d4b2e976450fc760a21a1ac40d593a48e2630948e7cc7b4872bb211a40777f6ad2a5
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveReserve
6
+ class Client
7
+ include Runners::CognitiveReserve
8
+
9
+ def initialize(engine: nil)
10
+ @engine = engine
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveReserve
6
+ module Helpers
7
+ module Constants
8
+ # Maximum tracked pathways
9
+ MAX_PATHWAYS = 100
10
+
11
+ # Maximum tracked compensations
12
+ MAX_COMPENSATIONS = 200
13
+
14
+ # Maximum event history
15
+ MAX_HISTORY = 300
16
+
17
+ # Default pathway capacity (0..1)
18
+ DEFAULT_CAPACITY = 1.0
19
+
20
+ # Capacity bounds
21
+ CAPACITY_FLOOR = 0.0
22
+ CAPACITY_CEILING = 1.0
23
+
24
+ # Threshold below which a pathway is considered degraded
25
+ DEGRADED_THRESHOLD = 0.5
26
+
27
+ # Threshold below which a pathway is considered failed
28
+ FAILED_THRESHOLD = 0.1
29
+
30
+ # Compensation efficiency — how much of lost capacity a backup restores
31
+ COMPENSATION_EFFICIENCY = 0.7
32
+
33
+ # Recovery rate per tick
34
+ RECOVERY_RATE = 0.02
35
+
36
+ # Decay rate for unused compensatory pathways
37
+ COMPENSATION_DECAY = 0.01
38
+
39
+ # Reserve levels based on overall reserve ratio
40
+ RESERVE_LABELS = {
41
+ (0.8..) => :robust,
42
+ (0.6...0.8) => :adequate,
43
+ (0.4...0.6) => :reduced,
44
+ (0.2...0.4) => :vulnerable,
45
+ (..0.2) => :critical
46
+ }.freeze
47
+
48
+ # Pathway states
49
+ PATHWAY_STATES = %i[healthy degraded compensating failed].freeze
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveReserve
6
+ module Helpers
7
+ class Pathway
8
+ include Constants
9
+
10
+ attr_reader :id, :domain, :function, :capacity, :backup_ids,
11
+ :damage_count, :compensation_count, :created_at, :updated_at
12
+
13
+ def initialize(id:, function:, domain: :general, capacity: DEFAULT_CAPACITY)
14
+ @id = id
15
+ @function = function
16
+ @domain = domain
17
+ @capacity = capacity.clamp(CAPACITY_FLOOR, CAPACITY_CEILING)
18
+ @backup_ids = []
19
+ @damage_count = 0
20
+ @compensation_count = 0
21
+ @created_at = Time.now.utc
22
+ @updated_at = @created_at
23
+ end
24
+
25
+ def damage(amount:)
26
+ @capacity = (@capacity - amount.abs).clamp(CAPACITY_FLOOR, CAPACITY_CEILING)
27
+ @damage_count += 1
28
+ @updated_at = Time.now.utc
29
+ self
30
+ end
31
+
32
+ def recover(amount: RECOVERY_RATE)
33
+ @capacity = (@capacity + amount.abs).clamp(CAPACITY_FLOOR, CAPACITY_CEILING)
34
+ @updated_at = Time.now.utc
35
+ self
36
+ end
37
+
38
+ def add_backup(pathway_id:)
39
+ return self if @backup_ids.include?(pathway_id)
40
+
41
+ @backup_ids << pathway_id
42
+ @updated_at = Time.now.utc
43
+ self
44
+ end
45
+
46
+ def remove_backup(pathway_id:)
47
+ @backup_ids.delete(pathway_id)
48
+ @updated_at = Time.now.utc
49
+ self
50
+ end
51
+
52
+ def compensate!
53
+ @compensation_count += 1
54
+ @updated_at = Time.now.utc
55
+ end
56
+
57
+ def state
58
+ return :failed if @capacity <= FAILED_THRESHOLD
59
+ return :compensating if @capacity <= DEGRADED_THRESHOLD && !@backup_ids.empty?
60
+ return :degraded if @capacity <= DEGRADED_THRESHOLD
61
+
62
+ :healthy
63
+ end
64
+
65
+ def healthy?
66
+ state == :healthy
67
+ end
68
+
69
+ def degraded?
70
+ @capacity <= DEGRADED_THRESHOLD
71
+ end
72
+
73
+ def failed?
74
+ @capacity <= FAILED_THRESHOLD
75
+ end
76
+
77
+ def effective_capacity(backup_capacities: [])
78
+ return @capacity if @capacity > DEGRADED_THRESHOLD || backup_capacities.empty?
79
+
80
+ deficit = DEGRADED_THRESHOLD - @capacity
81
+ compensation = backup_capacities.sum(0.0) * COMPENSATION_EFFICIENCY
82
+ (@capacity + [compensation, deficit].min).clamp(CAPACITY_FLOOR, CAPACITY_CEILING)
83
+ end
84
+
85
+ def redundancy
86
+ @backup_ids.size
87
+ end
88
+
89
+ def to_h
90
+ {
91
+ id: @id,
92
+ function: @function,
93
+ domain: @domain,
94
+ capacity: @capacity.round(4),
95
+ state: state,
96
+ backup_count: @backup_ids.size,
97
+ backup_ids: @backup_ids.dup,
98
+ damage_count: @damage_count,
99
+ compensation_count: @compensation_count,
100
+ created_at: @created_at,
101
+ updated_at: @updated_at
102
+ }
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveReserve
6
+ module Helpers
7
+ class ReserveEngine
8
+ include Constants
9
+
10
+ attr_reader :pathways, :history
11
+
12
+ def initialize
13
+ @pathways = {}
14
+ @pathway_count = 0
15
+ @history = []
16
+ end
17
+
18
+ def add_pathway(function:, domain: :general, capacity: DEFAULT_CAPACITY)
19
+ return nil if @pathways.size >= MAX_PATHWAYS
20
+
21
+ @pathway_count += 1
22
+ pathway = Pathway.new(
23
+ id: :"path_#{@pathway_count}",
24
+ function: function,
25
+ domain: domain,
26
+ capacity: capacity
27
+ )
28
+ @pathways[pathway.id] = pathway
29
+ record_event(:add_pathway, pathway_id: pathway.id)
30
+ pathway
31
+ end
32
+
33
+ def link_backup(primary_id:, backup_id:)
34
+ primary = @pathways[primary_id]
35
+ backup = @pathways[backup_id]
36
+ return nil unless primary && backup
37
+
38
+ primary.add_backup(pathway_id: backup_id)
39
+ record_event(:link_backup, primary_id: primary_id, backup_id: backup_id)
40
+ primary
41
+ end
42
+
43
+ def damage_pathway(pathway_id:, amount:)
44
+ pathway = @pathways[pathway_id]
45
+ return nil unless pathway
46
+
47
+ pathway.damage(amount: amount)
48
+ activate_compensation(pathway) if pathway.degraded?
49
+ record_event(:damage, pathway_id: pathway_id, amount: amount, state: pathway.state)
50
+ pathway
51
+ end
52
+
53
+ def recover_pathway(pathway_id:, amount: RECOVERY_RATE)
54
+ pathway = @pathways[pathway_id]
55
+ return nil unless pathway
56
+
57
+ pathway.recover(amount: amount)
58
+ record_event(:recover, pathway_id: pathway_id)
59
+ pathway
60
+ end
61
+
62
+ def effective_capacity(pathway_id:)
63
+ pathway = @pathways[pathway_id]
64
+ return nil unless pathway
65
+
66
+ backup_caps = pathway.backup_ids.filter_map { |bid| @pathways[bid]&.capacity }
67
+ pathway.effective_capacity(backup_capacities: backup_caps)
68
+ end
69
+
70
+ def overall_reserve
71
+ return DEFAULT_CAPACITY if @pathways.empty?
72
+
73
+ caps = @pathways.values.map do |p|
74
+ backup_caps = p.backup_ids.filter_map { |bid| @pathways[bid]&.capacity }
75
+ p.effective_capacity(backup_capacities: backup_caps)
76
+ end
77
+ caps.sum / caps.size.to_f
78
+ end
79
+
80
+ def reserve_label
81
+ ratio = overall_reserve
82
+ RESERVE_LABELS.find { |range, _| range.cover?(ratio) }&.last || :critical
83
+ end
84
+
85
+ def degraded_pathways
86
+ @pathways.values.select(&:degraded?).map(&:to_h)
87
+ end
88
+
89
+ def failed_pathways
90
+ @pathways.values.select(&:failed?).map(&:to_h)
91
+ end
92
+
93
+ def healthy_pathways
94
+ @pathways.values.select(&:healthy?).map(&:to_h)
95
+ end
96
+
97
+ def domain_reserve(domain:)
98
+ relevant = @pathways.values.select { |p| p.domain == domain }
99
+ return DEFAULT_CAPACITY if relevant.empty?
100
+
101
+ caps = relevant.map do |p|
102
+ backup_caps = p.backup_ids.filter_map { |bid| @pathways[bid]&.capacity }
103
+ p.effective_capacity(backup_capacities: backup_caps)
104
+ end
105
+ caps.sum / caps.size.to_f
106
+ end
107
+
108
+ def most_vulnerable(limit: 5)
109
+ @pathways.values
110
+ .sort_by(&:capacity)
111
+ .first(limit)
112
+ .map(&:to_h)
113
+ end
114
+
115
+ def most_redundant(limit: 5)
116
+ @pathways.values
117
+ .sort_by { |p| -p.redundancy }
118
+ .first(limit)
119
+ .map(&:to_h)
120
+ end
121
+
122
+ def recover_all
123
+ @pathways.each_value { |p| p.recover unless p.failed? }
124
+ end
125
+
126
+ def to_h
127
+ {
128
+ pathway_count: @pathways.size,
129
+ overall_reserve: overall_reserve.round(4),
130
+ reserve_label: reserve_label,
131
+ healthy_count: @pathways.values.count(&:healthy?),
132
+ degraded_count: @pathways.values.count(&:degraded?),
133
+ failed_count: @pathways.values.count(&:failed?),
134
+ history_size: @history.size
135
+ }
136
+ end
137
+
138
+ private
139
+
140
+ def activate_compensation(pathway)
141
+ pathway.backup_ids.each do |backup_id|
142
+ backup = @pathways[backup_id]
143
+ next unless backup&.healthy?
144
+
145
+ pathway.compensate!
146
+ record_event(:compensate, pathway_id: pathway.id, backup_id: backup_id)
147
+ break
148
+ end
149
+ end
150
+
151
+ def record_event(type, **details)
152
+ @history << { type: type, at: Time.now.utc }.merge(details)
153
+ @history.shift while @history.size > MAX_HISTORY
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveReserve
6
+ module Runners
7
+ module CognitiveReserve
8
+ include Helpers::Constants
9
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
10
+
11
+ def add_cognitive_pathway(function:, domain: :general, capacity: DEFAULT_CAPACITY, **)
12
+ pathway = engine.add_pathway(function: function, domain: domain, capacity: capacity)
13
+ return { success: false, reason: :limit_reached } unless pathway
14
+
15
+ { success: true, pathway_id: pathway.id, capacity: pathway.capacity }
16
+ end
17
+
18
+ def link_backup_pathway(primary_id:, backup_id:, **)
19
+ result = engine.link_backup(primary_id: primary_id, backup_id: backup_id)
20
+ return { success: false, reason: :not_found } unless result
21
+
22
+ { success: true, primary_id: primary_id, backup_id: backup_id, backup_count: result.backup_ids.size }
23
+ end
24
+
25
+ def damage_cognitive_pathway(pathway_id:, amount:, **)
26
+ pathway = engine.damage_pathway(pathway_id: pathway_id, amount: amount)
27
+ return { success: false, reason: :not_found } unless pathway
28
+
29
+ {
30
+ success: true,
31
+ pathway_id: pathway_id,
32
+ capacity: pathway.capacity.round(4),
33
+ state: pathway.state,
34
+ effective_capacity: engine.effective_capacity(pathway_id: pathway_id)&.round(4)
35
+ }
36
+ end
37
+
38
+ def recover_cognitive_pathway(pathway_id:, amount: RECOVERY_RATE, **)
39
+ pathway = engine.recover_pathway(pathway_id: pathway_id, amount: amount)
40
+ return { success: false, reason: :not_found } unless pathway
41
+
42
+ { success: true, pathway_id: pathway_id, capacity: pathway.capacity.round(4), state: pathway.state }
43
+ end
44
+
45
+ def cognitive_reserve_assessment(**)
46
+ {
47
+ success: true,
48
+ overall_reserve: engine.overall_reserve.round(4),
49
+ reserve_label: engine.reserve_label,
50
+ most_vulnerable: engine.most_vulnerable,
51
+ degraded: engine.degraded_pathways,
52
+ failed: engine.failed_pathways
53
+ }
54
+ end
55
+
56
+ def domain_cognitive_reserve(domain:, **)
57
+ {
58
+ success: true,
59
+ domain: domain,
60
+ reserve: engine.domain_reserve(domain: domain).round(4),
61
+ pathway_count: engine.pathways.values.count { |p| p.domain == domain }
62
+ }
63
+ end
64
+
65
+ def most_redundant_pathways(**)
66
+ pathways = engine.most_redundant
67
+ { success: true, pathways: pathways, count: pathways.size }
68
+ end
69
+
70
+ def update_cognitive_reserve(**)
71
+ engine.recover_all
72
+ { success: true }.merge(engine.to_h)
73
+ end
74
+
75
+ def cognitive_reserve_stats(**)
76
+ { success: true }.merge(engine.to_h)
77
+ end
78
+
79
+ private
80
+
81
+ def engine
82
+ @engine ||= Helpers::ReserveEngine.new
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveReserve
6
+ VERSION = '0.1.0'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'cognitive_reserve/version'
4
+ require_relative 'cognitive_reserve/helpers/constants'
5
+ require_relative 'cognitive_reserve/helpers/pathway'
6
+ require_relative 'cognitive_reserve/helpers/reserve_engine'
7
+ require_relative 'cognitive_reserve/runners/cognitive_reserve'
8
+ require_relative 'cognitive_reserve/client'
9
+
10
+ module Legion
11
+ module Extensions
12
+ module CognitiveReserve
13
+ extend Legion::Extensions::Core if defined?(Legion::Extensions::Core)
14
+ end
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lex-cognitive-reserve
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: Cognitive reserve for LegionIO — resilience through redundant pathways,
27
+ compensatory mechanisms, and graceful degradation under damage
28
+ email:
29
+ - matthewdiverson@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/legion/extensions/cognitive_reserve.rb
35
+ - lib/legion/extensions/cognitive_reserve/client.rb
36
+ - lib/legion/extensions/cognitive_reserve/helpers/constants.rb
37
+ - lib/legion/extensions/cognitive_reserve/helpers/pathway.rb
38
+ - lib/legion/extensions/cognitive_reserve/helpers/reserve_engine.rb
39
+ - lib/legion/extensions/cognitive_reserve/runners/cognitive_reserve.rb
40
+ - lib/legion/extensions/cognitive_reserve/version.rb
41
+ homepage: https://github.com/LegionIO/lex-cognitive-reserve
42
+ licenses:
43
+ - MIT
44
+ metadata:
45
+ homepage_uri: https://github.com/LegionIO/lex-cognitive-reserve
46
+ source_code_uri: https://github.com/LegionIO/lex-cognitive-reserve
47
+ documentation_uri: https://github.com/LegionIO/lex-cognitive-reserve/blob/master/README.md
48
+ changelog_uri: https://github.com/LegionIO/lex-cognitive-reserve/blob/master/CHANGELOG.md
49
+ bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-reserve/issues
50
+ rubygems_mfa_required: 'true'
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '3.4'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 3.6.9
66
+ specification_version: 4
67
+ summary: LegionIO cognitive reserve extension
68
+ test_files: []