lex-cognitive-avalanche 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 +7 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/.rubocop.yml +64 -0
- data/CLAUDE.md +74 -0
- data/Gemfile +13 -0
- data/README.md +44 -0
- data/lex-cognitive-avalanche.gemspec +30 -0
- data/lib/legion/extensions/cognitive_avalanche/client.rb +18 -0
- data/lib/legion/extensions/cognitive_avalanche/helpers/avalanche_engine.rb +128 -0
- data/lib/legion/extensions/cognitive_avalanche/helpers/cascade.rb +72 -0
- data/lib/legion/extensions/cognitive_avalanche/helpers/constants.rb +40 -0
- data/lib/legion/extensions/cognitive_avalanche/helpers/snowpack.rb +82 -0
- data/lib/legion/extensions/cognitive_avalanche/runners/cognitive_avalanche.rb +71 -0
- data/lib/legion/extensions/cognitive_avalanche/version.rb +9 -0
- data/lib/legion/extensions/cognitive_avalanche.rb +19 -0
- metadata +78 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6567ff48d15aa79fa8c5ff8766debc2450945d512170b24d35ffe7a066b60734
|
|
4
|
+
data.tar.gz: fbf7bbb237b72fd3d50611b4711a1332d2915d5ce301b4dc51592f3956aad276
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8202662f77b3ea2642aaee609a8a2b5312ee38e79d64391d1277375e48ba9d8e3046ad1878c40d6a720880992c817a7bf31fcd7b77b7c5d4017162981befa2c5
|
|
7
|
+
data.tar.gz: a349476ee03ae01fcffb805b455ff26f630a9b1b12c6445fa4f3dab38a839d5c125be6832441c53d295156f03a5ed39799c6a92d4adc14aa67709efa47810545
|
|
@@ -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
data/.rspec
ADDED
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/ParameterLists:
|
|
34
|
+
Max: 8
|
|
35
|
+
MaxOptionalParameters: 8
|
|
36
|
+
|
|
37
|
+
Metrics/CyclomaticComplexity:
|
|
38
|
+
Max: 15
|
|
39
|
+
|
|
40
|
+
Metrics/PerceivedComplexity:
|
|
41
|
+
Max: 17
|
|
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
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# lex-cognitive-avalanche
|
|
2
|
+
|
|
3
|
+
**Level 3 Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
|
|
5
|
+
- **Grandparent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Cascading thought-chain model for LegionIO. Models how small perturbations become massive cognitive avalanches: snowpack stability, trigger events, cascade propagation, and debris fields. Used to detect and model runaway thought cascades — both creative (productive cascades) and chaotic (destructive spirals).
|
|
10
|
+
|
|
11
|
+
## Gem Info
|
|
12
|
+
|
|
13
|
+
- **Gem name**: `lex-cognitive-avalanche`
|
|
14
|
+
- **Version**: `0.1.0`
|
|
15
|
+
- **Module**: `Legion::Extensions::CognitiveAvalanche`
|
|
16
|
+
- **Ruby**: `>= 3.4`
|
|
17
|
+
- **License**: MIT
|
|
18
|
+
|
|
19
|
+
## File Structure
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
lib/legion/extensions/cognitive_avalanche/
|
|
23
|
+
cognitive_avalanche.rb
|
|
24
|
+
version.rb
|
|
25
|
+
client.rb
|
|
26
|
+
helpers/
|
|
27
|
+
constants.rb
|
|
28
|
+
avalanche_engine.rb
|
|
29
|
+
snowpack.rb
|
|
30
|
+
cascade.rb
|
|
31
|
+
runners/
|
|
32
|
+
cognitive_avalanche.rb
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Key Constants
|
|
36
|
+
|
|
37
|
+
From `helpers/constants.rb`:
|
|
38
|
+
|
|
39
|
+
- `SNOWPACK_TYPES` — `%i[ideas emotions memories associations impulses]`
|
|
40
|
+
- `CASCADE_TYPES` — `%i[creative emotional analytical chaotic convergent]`
|
|
41
|
+
- `MAX_SNOWPACKS` = `100`, `MAX_CASCADE_HISTORY` = `500`
|
|
42
|
+
- `TRIGGER_THRESHOLD` = `0.75` (depth >= this makes snowpack trigger-ready)
|
|
43
|
+
- `ACCUMULATION_RATE` = `0.06`, `MELT_RATE` = `0.02`
|
|
44
|
+
- `STABILITY_LABELS` — `0.8+` = `:bedrock`, `0.6` = `:moderate`, `0.4` = `:unstable`, `0.2` = `:critical`, below = `:catastrophic`
|
|
45
|
+
- `MAGNITUDE_LABELS` — `0.8+` = `:devastating`, `0.6` = `:major`, `0.4` = `:significant`, `0.2` = `:moderate`, below = `:minor`
|
|
46
|
+
|
|
47
|
+
## Runners
|
|
48
|
+
|
|
49
|
+
All methods in `Runners::CognitiveAvalanche` (`extend self`):
|
|
50
|
+
|
|
51
|
+
- `create_snowpack(snowpack_type:, domain:, content:, depth: 0.0, stability: 1.0)` — creates a new accumulating snowpack; `snowpack_type`, `domain`, and `content` are required
|
|
52
|
+
- `trigger(snowpack_id:, force: 0.5, cascade_type: :chaotic)` — triggers an avalanche from a snowpack if depth is sufficient; produces a cascade record
|
|
53
|
+
- `accumulate(rate: ACCUMULATION_RATE)` — applies accumulation to all snowpacks (depth increases)
|
|
54
|
+
- `list_snowpacks` — returns all snowpacks with their current state
|
|
55
|
+
- `terrain_status` — returns terrain report: total snowpacks, stability averages, recent cascade history
|
|
56
|
+
|
|
57
|
+
## Helpers
|
|
58
|
+
|
|
59
|
+
- `AvalancheEngine` — manages snowpacks and cascade history. `trigger` produces `Cascade` objects when depth >= threshold.
|
|
60
|
+
- `Snowpack` — accumulating thought store with `depth`, `stability`, `snowpack_type`, `domain`. Stability degrades under accumulation and recovers during melt. `trigger_ready?` checks depth vs `TRIGGER_THRESHOLD`.
|
|
61
|
+
- `Cascade` — records a triggered avalanche: `cascade_type`, `magnitude`, `source_snowpack_id`, `debris` (residual fragments from the cascade).
|
|
62
|
+
|
|
63
|
+
## Integration Points
|
|
64
|
+
|
|
65
|
+
- `lex-cognitive-dwell` and `lex-cognitive-echo` both model persistence of cognitive content; avalanche models the threshold crossing where that persistence becomes runaway.
|
|
66
|
+
- `lex-tick` can call `accumulate` on each tick to model slow pressure buildup, with `trigger` called when external force is applied (e.g., a high-intensity signal).
|
|
67
|
+
- `cascade_type: :creative` and `:analytical` are positive cascades; `:chaotic` and `:emotional` represent instability.
|
|
68
|
+
|
|
69
|
+
## Development Notes
|
|
70
|
+
|
|
71
|
+
- `create_snowpack` requires all three arguments (`snowpack_type`, `domain`, `content`) — missing any raises `ArgumentError`.
|
|
72
|
+
- `AvalancheEngine` state is in-memory only; history cap enforced via `MAX_CASCADE_HISTORY`.
|
|
73
|
+
- `accumulate_all!` is the periodic maintenance runner — intended to be called every tick or at set intervals.
|
|
74
|
+
- Cascade debris represents unprocessed fragments after the avalanche — callers can read these as input for downstream extensions (e.g., feed debris into memory traces).
|
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,44 @@
|
|
|
1
|
+
# lex-cognitive-avalanche
|
|
2
|
+
|
|
3
|
+
Cascading thought-chain model for LegionIO. Models how small perturbations become massive cognitive avalanches through snowpack accumulation, trigger events, and cascade propagation.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Thoughts accumulate like snow: slow buildup increases depth, reducing stability over time. When depth crosses a threshold and external force is applied, an avalanche triggers. The cascade type determines the character of the runaway — creative cascades are productive bursts of association, chaotic cascades are destabilizing spirals.
|
|
8
|
+
|
|
9
|
+
The extension tracks snowpacks by type (ideas, emotions, memories, associations, impulses) and domain, records cascade history with magnitude scores, and provides terrain stability reports.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
client = Legion::Extensions::CognitiveAvalanche::Client.new
|
|
15
|
+
|
|
16
|
+
pack = client.create_snowpack(
|
|
17
|
+
snowpack_type: :ideas,
|
|
18
|
+
domain: :problem_solving,
|
|
19
|
+
content: 'unprocessed ideas about the architecture',
|
|
20
|
+
stability: 0.8
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
client.accumulate(rate: 0.06) # call periodically to build depth
|
|
24
|
+
|
|
25
|
+
cascade = client.trigger(
|
|
26
|
+
snowpack_id: pack[:snowpack][:id],
|
|
27
|
+
force: 0.6,
|
|
28
|
+
cascade_type: :creative
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
client.terrain_status
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Development
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
bundle install
|
|
38
|
+
bundle exec rspec
|
|
39
|
+
bundle exec rubocop
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_avalanche/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-avalanche'
|
|
7
|
+
spec.version = Legion::Extensions::CognitiveAvalanche::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'LEX Cognitive Avalanche'
|
|
12
|
+
spec.description = 'Cascading thought-chain model for LegionIO — snowpack stability, trigger events, ' \
|
|
13
|
+
'cascade propagation, and debris fields model how small perturbations become massive cognitive avalanches'
|
|
14
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-avalanche'
|
|
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-avalanche'
|
|
20
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-avalanche'
|
|
21
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-avalanche'
|
|
22
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-avalanche/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,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveAvalanche
|
|
6
|
+
class Client
|
|
7
|
+
include Runners::CognitiveAvalanche
|
|
8
|
+
|
|
9
|
+
attr_reader :engine
|
|
10
|
+
|
|
11
|
+
def initialize(engine: nil, **)
|
|
12
|
+
@engine = engine || Helpers::AvalancheEngine.new
|
|
13
|
+
@avalanche_engine = @engine
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveAvalanche
|
|
6
|
+
module Helpers
|
|
7
|
+
class AvalancheEngine
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :snowpacks, :cascade_history
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@snowpacks = {}
|
|
14
|
+
@cascade_history = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_snowpack(snowpack_type:, domain:, content:, depth: 0.0, stability: 1.0, **)
|
|
18
|
+
raise ArgumentError, 'snowpack limit reached' if @snowpacks.size >= Constants::MAX_SNOWPACKS
|
|
19
|
+
|
|
20
|
+
pack = Snowpack.new(
|
|
21
|
+
snowpack_type: snowpack_type,
|
|
22
|
+
domain: domain,
|
|
23
|
+
content: content,
|
|
24
|
+
depth: depth,
|
|
25
|
+
stability: stability
|
|
26
|
+
)
|
|
27
|
+
@snowpacks[pack.id] = pack
|
|
28
|
+
{ success: true, snowpack_id: pack.id, snowpack: pack.to_h }
|
|
29
|
+
rescue ArgumentError => e
|
|
30
|
+
{ success: false, error: e.message }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def trigger(snowpack_id:, force:, cascade_type: :chaotic, **)
|
|
34
|
+
pack = @snowpacks[snowpack_id]
|
|
35
|
+
raise ArgumentError, "snowpack not found: #{snowpack_id}" unless pack
|
|
36
|
+
|
|
37
|
+
pack.destabilize!(force)
|
|
38
|
+
instability = pack.instability
|
|
39
|
+
|
|
40
|
+
return { success: true, triggered: false, instability: instability, reason: :below_threshold } \
|
|
41
|
+
if (force + instability) < Constants::TRIGGER_THRESHOLD
|
|
42
|
+
|
|
43
|
+
cascade = Cascade.new(
|
|
44
|
+
cascade_type: cascade_type,
|
|
45
|
+
trigger_source: snowpack_id,
|
|
46
|
+
magnitude: ((force + instability) / 2.0).clamp(0.0, 1.0).round(10),
|
|
47
|
+
propagation_speed: instability.round(10),
|
|
48
|
+
debris: [pack.content]
|
|
49
|
+
)
|
|
50
|
+
record_cascade(cascade)
|
|
51
|
+
{ success: true, triggered: true, cascade_id: cascade.id, cascade: cascade.to_h, instability: instability }
|
|
52
|
+
rescue ArgumentError => e
|
|
53
|
+
{ success: false, error: e.message }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def accumulate_all!(rate: Constants::ACCUMULATION_RATE, **)
|
|
57
|
+
count = 0
|
|
58
|
+
@snowpacks.each_value do |pack|
|
|
59
|
+
pack.accumulate!(rate)
|
|
60
|
+
count += 1
|
|
61
|
+
end
|
|
62
|
+
{ success: true, packs_accumulated: count, rate: rate }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def melt_all!(rate: Constants::MELT_RATE, **)
|
|
66
|
+
count = 0
|
|
67
|
+
@snowpacks.each_value do |pack|
|
|
68
|
+
pack.melt!(rate)
|
|
69
|
+
count += 1
|
|
70
|
+
end
|
|
71
|
+
{ success: true, packs_melted: count, rate: rate }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def active_cascades
|
|
75
|
+
@cascade_history.select(&:active?)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def most_unstable
|
|
79
|
+
@snowpacks.values.min_by(&:stability)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def terrain_report
|
|
83
|
+
packs = @snowpacks.values
|
|
84
|
+
active_cascades = self.active_cascades
|
|
85
|
+
critical_packs = packs.select(&:critical?)
|
|
86
|
+
unstable_packs = packs.select(&:unstable?)
|
|
87
|
+
|
|
88
|
+
{
|
|
89
|
+
total_snowpacks: packs.size,
|
|
90
|
+
critical_count: critical_packs.size,
|
|
91
|
+
unstable_count: unstable_packs.size,
|
|
92
|
+
stable_count: packs.count(&:stable?),
|
|
93
|
+
active_cascades: active_cascades.size,
|
|
94
|
+
cascade_history: @cascade_history.size,
|
|
95
|
+
avg_stability: avg_stability(packs),
|
|
96
|
+
avg_depth: avg_depth(packs),
|
|
97
|
+
most_unstable_id: most_unstable&.id,
|
|
98
|
+
recent_cascades: recent_cascades(5)
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def record_cascade(cascade)
|
|
105
|
+
@cascade_history << cascade
|
|
106
|
+
@cascade_history.shift if @cascade_history.size > Constants::MAX_CASCADE_HISTORY
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def avg_stability(packs)
|
|
110
|
+
return 0.0 if packs.empty?
|
|
111
|
+
|
|
112
|
+
(packs.sum(&:stability) / packs.size.to_f).round(10)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def avg_depth(packs)
|
|
116
|
+
return 0.0 if packs.empty?
|
|
117
|
+
|
|
118
|
+
(packs.sum(&:depth) / packs.size.to_f).round(10)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def recent_cascades(count)
|
|
122
|
+
@cascade_history.last(count).map(&:to_h)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveAvalanche
|
|
8
|
+
module Helpers
|
|
9
|
+
class Cascade
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :cascade_type, :trigger_source, :started_at
|
|
13
|
+
attr_accessor :magnitude, :propagation_speed, :debris
|
|
14
|
+
|
|
15
|
+
def initialize(cascade_type:, trigger_source:, magnitude:, propagation_speed: 0.5, debris: [], **)
|
|
16
|
+
raise ArgumentError, "unknown cascade_type: #{cascade_type}" unless Constants::CASCADE_TYPES.include?(cascade_type)
|
|
17
|
+
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@cascade_type = cascade_type
|
|
20
|
+
@trigger_source = trigger_source
|
|
21
|
+
@magnitude = magnitude.clamp(0.0, 1.0)
|
|
22
|
+
@propagation_speed = propagation_speed.clamp(0.0, 1.0)
|
|
23
|
+
@debris = Array(debris).dup
|
|
24
|
+
@active = true
|
|
25
|
+
@started_at = Time.now.utc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def propagate!(rate = 0.1)
|
|
29
|
+
return unless @active
|
|
30
|
+
|
|
31
|
+
@magnitude = (@magnitude + rate.abs).clamp(0.0, 1.0).round(10)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def dissipate!(rate = 0.08)
|
|
35
|
+
@magnitude = (@magnitude - rate.abs).clamp(0.0, 1.0).round(10)
|
|
36
|
+
@active = false if @magnitude <= 0.0
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def active?
|
|
40
|
+
@active && @magnitude > 0.0
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def spent?
|
|
44
|
+
!@active || @magnitude <= 0.0
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def magnitude_label
|
|
48
|
+
Constants.label_for(:MAGNITUDE_LABELS, @magnitude)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def add_debris(item)
|
|
52
|
+
@debris << item
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def to_h
|
|
56
|
+
{
|
|
57
|
+
id: @id,
|
|
58
|
+
cascade_type: @cascade_type,
|
|
59
|
+
trigger_source: @trigger_source,
|
|
60
|
+
magnitude: @magnitude,
|
|
61
|
+
magnitude_label: magnitude_label,
|
|
62
|
+
propagation_speed: @propagation_speed,
|
|
63
|
+
debris: @debris.dup,
|
|
64
|
+
active: @active,
|
|
65
|
+
started_at: @started_at
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveAvalanche
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_SNOWPACKS = 100
|
|
9
|
+
MAX_CASCADE_HISTORY = 500
|
|
10
|
+
TRIGGER_THRESHOLD = 0.75
|
|
11
|
+
ACCUMULATION_RATE = 0.06
|
|
12
|
+
MELT_RATE = 0.02
|
|
13
|
+
|
|
14
|
+
SNOWPACK_TYPES = %i[ideas emotions memories associations impulses].freeze
|
|
15
|
+
CASCADE_TYPES = %i[creative emotional analytical chaotic convergent].freeze
|
|
16
|
+
|
|
17
|
+
STABILITY_LABELS = {
|
|
18
|
+
(0.0...0.2) => :catastrophic,
|
|
19
|
+
(0.2...0.4) => :critical,
|
|
20
|
+
(0.4...0.6) => :unstable,
|
|
21
|
+
(0.6...0.8) => :moderate,
|
|
22
|
+
(0.8..1.0) => :bedrock
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
MAGNITUDE_LABELS = {
|
|
26
|
+
(0.0...0.2) => :minor,
|
|
27
|
+
(0.2...0.4) => :moderate,
|
|
28
|
+
(0.4...0.6) => :significant,
|
|
29
|
+
(0.6...0.8) => :major,
|
|
30
|
+
(0.8..1.0) => :devastating
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
def self.label_for(table, value)
|
|
34
|
+
const_get(table).find { |range, _| range.cover?(value.clamp(0.0, 1.0)) }&.last || :unknown
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveAvalanche
|
|
8
|
+
module Helpers
|
|
9
|
+
class Snowpack
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :snowpack_type, :domain, :content, :created_at
|
|
13
|
+
attr_accessor :depth, :stability
|
|
14
|
+
|
|
15
|
+
def initialize(snowpack_type:, domain:, content:, depth: 0.0, stability: 1.0, **)
|
|
16
|
+
raise ArgumentError, "unknown snowpack_type: #{snowpack_type}" unless Constants::SNOWPACK_TYPES.include?(snowpack_type)
|
|
17
|
+
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@snowpack_type = snowpack_type
|
|
20
|
+
@domain = domain
|
|
21
|
+
@content = content
|
|
22
|
+
@depth = depth.clamp(0.0, 1.0)
|
|
23
|
+
@stability = stability.clamp(0.0, 1.0)
|
|
24
|
+
@created_at = Time.now.utc
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def accumulate!(rate = Constants::ACCUMULATION_RATE)
|
|
28
|
+
@depth = (@depth + rate.abs).clamp(0.0, 1.0).round(10)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def compact!
|
|
32
|
+
@stability = (@stability + 0.05).clamp(0.0, 1.0).round(10)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def melt!(rate = Constants::MELT_RATE)
|
|
36
|
+
@depth = (@depth - rate.abs).clamp(0.0, 1.0).round(10)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def destabilize!(force)
|
|
40
|
+
@stability = (@stability - force.abs).clamp(0.0, 1.0).round(10)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def stable?
|
|
44
|
+
@stability >= 0.6
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def unstable?
|
|
48
|
+
@stability < 0.4
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def critical?
|
|
52
|
+
@stability < 0.2
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def stability_label
|
|
56
|
+
Constants.label_for(:STABILITY_LABELS, @stability)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def instability
|
|
60
|
+
(1.0 - @stability).round(10)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_h
|
|
64
|
+
{
|
|
65
|
+
id: @id,
|
|
66
|
+
snowpack_type: @snowpack_type,
|
|
67
|
+
domain: @domain,
|
|
68
|
+
content: @content,
|
|
69
|
+
depth: @depth,
|
|
70
|
+
stability: @stability,
|
|
71
|
+
stable: stable?,
|
|
72
|
+
unstable: unstable?,
|
|
73
|
+
critical: critical?,
|
|
74
|
+
stability_label: stability_label,
|
|
75
|
+
created_at: @created_at
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveAvalanche
|
|
6
|
+
module Runners
|
|
7
|
+
module CognitiveAvalanche
|
|
8
|
+
extend self
|
|
9
|
+
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
|
|
11
|
+
|
|
12
|
+
def create_snowpack(snowpack_type: nil, domain: nil, content: nil,
|
|
13
|
+
depth: 0.0, stability: 1.0, engine: nil, **)
|
|
14
|
+
raise ArgumentError, 'snowpack_type is required' if snowpack_type.nil?
|
|
15
|
+
raise ArgumentError, 'domain is required' if domain.nil?
|
|
16
|
+
raise ArgumentError, 'content is required' if content.nil?
|
|
17
|
+
|
|
18
|
+
avalanche_engine(engine).create_snowpack(
|
|
19
|
+
snowpack_type: snowpack_type,
|
|
20
|
+
domain: domain,
|
|
21
|
+
content: content,
|
|
22
|
+
depth: depth,
|
|
23
|
+
stability: stability
|
|
24
|
+
)
|
|
25
|
+
rescue ArgumentError => e
|
|
26
|
+
{ success: false, error: e.message }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def trigger(snowpack_id: nil, force: 0.5, cascade_type: :chaotic, engine: nil, **)
|
|
30
|
+
raise ArgumentError, 'snowpack_id is required' if snowpack_id.nil?
|
|
31
|
+
|
|
32
|
+
avalanche_engine(engine).trigger(
|
|
33
|
+
snowpack_id: snowpack_id,
|
|
34
|
+
force: force,
|
|
35
|
+
cascade_type: cascade_type
|
|
36
|
+
)
|
|
37
|
+
rescue ArgumentError => e
|
|
38
|
+
{ success: false, error: e.message }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def accumulate(rate: Helpers::Constants::ACCUMULATION_RATE, engine: nil, **)
|
|
42
|
+
avalanche_engine(engine).accumulate_all!(rate: rate)
|
|
43
|
+
rescue ArgumentError => e
|
|
44
|
+
{ success: false, error: e.message }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def list_snowpacks(engine: nil, **)
|
|
48
|
+
eng = avalanche_engine(engine)
|
|
49
|
+
packs = eng.snowpacks.values.map(&:to_h)
|
|
50
|
+
{ success: true, snowpacks: packs, count: packs.size }
|
|
51
|
+
rescue ArgumentError => e
|
|
52
|
+
{ success: false, error: e.message }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def terrain_status(engine: nil, **)
|
|
56
|
+
report = avalanche_engine(engine).terrain_report
|
|
57
|
+
{ success: true }.merge(report)
|
|
58
|
+
rescue ArgumentError => e
|
|
59
|
+
{ success: false, error: e.message }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def avalanche_engine(engine)
|
|
65
|
+
engine || @avalanche_engine ||= Helpers::AvalancheEngine.new
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
require 'legion/extensions/cognitive_avalanche/version'
|
|
6
|
+
require 'legion/extensions/cognitive_avalanche/helpers/constants'
|
|
7
|
+
require 'legion/extensions/cognitive_avalanche/helpers/snowpack'
|
|
8
|
+
require 'legion/extensions/cognitive_avalanche/helpers/cascade'
|
|
9
|
+
require 'legion/extensions/cognitive_avalanche/helpers/avalanche_engine'
|
|
10
|
+
require 'legion/extensions/cognitive_avalanche/runners/cognitive_avalanche'
|
|
11
|
+
require 'legion/extensions/cognitive_avalanche/client'
|
|
12
|
+
|
|
13
|
+
module Legion
|
|
14
|
+
module Extensions
|
|
15
|
+
module CognitiveAvalanche
|
|
16
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-cognitive-avalanche
|
|
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: Cascading thought-chain model for LegionIO — snowpack stability, trigger
|
|
27
|
+
events, cascade propagation, and debris fields model how small perturbations become
|
|
28
|
+
massive cognitive avalanches
|
|
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-avalanche.gemspec
|
|
43
|
+
- lib/legion/extensions/cognitive_avalanche.rb
|
|
44
|
+
- lib/legion/extensions/cognitive_avalanche/client.rb
|
|
45
|
+
- lib/legion/extensions/cognitive_avalanche/helpers/avalanche_engine.rb
|
|
46
|
+
- lib/legion/extensions/cognitive_avalanche/helpers/cascade.rb
|
|
47
|
+
- lib/legion/extensions/cognitive_avalanche/helpers/constants.rb
|
|
48
|
+
- lib/legion/extensions/cognitive_avalanche/helpers/snowpack.rb
|
|
49
|
+
- lib/legion/extensions/cognitive_avalanche/runners/cognitive_avalanche.rb
|
|
50
|
+
- lib/legion/extensions/cognitive_avalanche/version.rb
|
|
51
|
+
homepage: https://github.com/LegionIO/lex-cognitive-avalanche
|
|
52
|
+
licenses:
|
|
53
|
+
- MIT
|
|
54
|
+
metadata:
|
|
55
|
+
homepage_uri: https://github.com/LegionIO/lex-cognitive-avalanche
|
|
56
|
+
source_code_uri: https://github.com/LegionIO/lex-cognitive-avalanche
|
|
57
|
+
documentation_uri: https://github.com/LegionIO/lex-cognitive-avalanche
|
|
58
|
+
changelog_uri: https://github.com/LegionIO/lex-cognitive-avalanche
|
|
59
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-avalanche/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 Avalanche
|
|
78
|
+
test_files: []
|