lex-cognitive-fermentation 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 +37 -0
- data/CLAUDE.md +117 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +78 -0
- data/README.md +53 -0
- data/lex-cognitive-fermentation.gemspec +29 -0
- data/lib/legion/extensions/cognitive_fermentation/client.rb +15 -0
- data/lib/legion/extensions/cognitive_fermentation/helpers/batch.rb +71 -0
- data/lib/legion/extensions/cognitive_fermentation/helpers/constants.rb +74 -0
- data/lib/legion/extensions/cognitive_fermentation/helpers/fermentation_engine.rb +143 -0
- data/lib/legion/extensions/cognitive_fermentation/helpers/substrate.rb +104 -0
- data/lib/legion/extensions/cognitive_fermentation/runners/cognitive_fermentation.rb +56 -0
- data/lib/legion/extensions/cognitive_fermentation/version.rb +9 -0
- data/lib/legion/extensions/cognitive_fermentation.rb +18 -0
- data/spec/legion/extensions/cognitive_fermentation/client_spec.rb +36 -0
- data/spec/legion/extensions/cognitive_fermentation/helpers/batch_spec.rb +72 -0
- data/spec/legion/extensions/cognitive_fermentation/helpers/fermentation_engine_spec.rb +138 -0
- data/spec/legion/extensions/cognitive_fermentation/helpers/substrate_spec.rb +146 -0
- data/spec/spec_helper.rb +28 -0
- metadata +83 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4ea50c03dfbb3796b24114e8395d00e9a70bbc9efd2801912528f909f931ea39
|
|
4
|
+
data.tar.gz: ee361053997fc4d64fdcd522abb6ff406a621d190b8c7002c8b7ac2cdaf11fc5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e35f786a95a757afb400bc8827ee11fe685f37514a657afe4c05132cb18d6a987bdba670690f5afff19896a6d0b0d5b3d02f87f9aa2dc9fd0ed704eeee9abf1a
|
|
7
|
+
data.tar.gz: 55444692dc3361b8c1ef6272d59a94767bc69ad603215d0fd1feaf2d6622ad2d7e85ee5894ec01c7aeb6e895ae71744fc4649ccb51900d281187535d4066159f
|
|
@@ -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,37 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
NewCops: enable
|
|
3
|
+
TargetRubyVersion: 3.4
|
|
4
|
+
|
|
5
|
+
Style/Documentation:
|
|
6
|
+
Enabled: false
|
|
7
|
+
|
|
8
|
+
Naming/PredicateMethod:
|
|
9
|
+
Enabled: false
|
|
10
|
+
|
|
11
|
+
Naming/PredicatePrefix:
|
|
12
|
+
Enabled: false
|
|
13
|
+
|
|
14
|
+
Metrics/ClassLength:
|
|
15
|
+
Max: 150
|
|
16
|
+
|
|
17
|
+
Metrics/MethodLength:
|
|
18
|
+
Max: 25
|
|
19
|
+
|
|
20
|
+
Metrics/AbcSize:
|
|
21
|
+
Max: 25
|
|
22
|
+
|
|
23
|
+
Metrics/ParameterLists:
|
|
24
|
+
Max: 8
|
|
25
|
+
MaxOptionalParameters: 8
|
|
26
|
+
|
|
27
|
+
Layout/HashAlignment:
|
|
28
|
+
EnforcedColonStyle: table
|
|
29
|
+
EnforcedHashRocketStyle: table
|
|
30
|
+
|
|
31
|
+
Metrics/BlockLength:
|
|
32
|
+
Exclude:
|
|
33
|
+
- spec/**/*
|
|
34
|
+
|
|
35
|
+
Style/OneClassPerFile:
|
|
36
|
+
Exclude:
|
|
37
|
+
- spec/spec_helper.rb
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# lex-cognitive-fermentation
|
|
2
|
+
|
|
3
|
+
**Level 3 Leaf Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
|
|
5
|
+
- **Gem**: `lex-cognitive-fermentation`
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Models slow, non-linear cognitive maturation using a fermentation metaphor. Raw, unresolved, or partial cognitive material (substrates) ferments over time, developing potency and maturity through natural processing and catalysis. When substrates reach peak stage, they are ready for use or harvest. Over-fermented substrates decay. Domain-grouped batches track collective fermentation progress.
|
|
10
|
+
|
|
11
|
+
## Gem Info
|
|
12
|
+
|
|
13
|
+
| Field | Value |
|
|
14
|
+
|---|---|
|
|
15
|
+
| Gem name | `lex-cognitive-fermentation` |
|
|
16
|
+
| Version | `0.1.0` |
|
|
17
|
+
| Namespace | `Legion::Extensions::CognitiveFermentation` |
|
|
18
|
+
| Ruby | `>= 3.4` |
|
|
19
|
+
| License | MIT |
|
|
20
|
+
| GitHub | https://github.com/LegionIO/lex-cognitive-fermentation |
|
|
21
|
+
|
|
22
|
+
## File Structure
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
lib/legion/extensions/cognitive_fermentation/
|
|
26
|
+
cognitive_fermentation.rb # Top-level require
|
|
27
|
+
version.rb # VERSION = '0.1.0'
|
|
28
|
+
client.rb # Client class
|
|
29
|
+
helpers/
|
|
30
|
+
constants.rb # Types, stages, rates, label hashes
|
|
31
|
+
substrate.rb # Substrate value object
|
|
32
|
+
batch.rb # Batch (domain group) value object
|
|
33
|
+
fermentation_engine.rb # Engine: substrates + batches
|
|
34
|
+
runners/
|
|
35
|
+
cognitive_fermentation.rb # Runner module
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Key Constants
|
|
39
|
+
|
|
40
|
+
| Constant | Value | Meaning |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `MAX_SUBSTRATES` | 500 | Hard cap; evicts spoiled then lowest-potency |
|
|
43
|
+
| `MAX_BATCHES` | 50 | Batch cap |
|
|
44
|
+
| `MATURATION_RATE` | 0.05 | Default fermentation step size |
|
|
45
|
+
| `CATALYSIS_BOOST` | 0.12 | Potency boost from catalyst application |
|
|
46
|
+
| `SPOILAGE_THRESHOLD` | 0.1 | Potency below this = spoiled |
|
|
47
|
+
| `RIPE_THRESHOLD` | 0.7 | Potency above this = ripe |
|
|
48
|
+
| `PEAK_THRESHOLD` | 0.9 | Potency above this = peak |
|
|
49
|
+
| `OVER_FERMENTED_DECAY` | 0.03 | Post-peak potency loss rate |
|
|
50
|
+
| `SUBSTRATE_TYPES` | array | `raw_idea`, `unresolved_problem`, `partial_pattern`, etc. |
|
|
51
|
+
| `FERMENTATION_STAGES` | array | `inoculation` through `over_fermented` |
|
|
52
|
+
| `CATALYST_TYPES` | array | `analogy`, `contrast`, `emotional_charge`, `dream_residue`, etc. |
|
|
53
|
+
|
|
54
|
+
## Helpers
|
|
55
|
+
|
|
56
|
+
### `Substrate`
|
|
57
|
+
|
|
58
|
+
Tracks the fermentation state of a single cognitive material unit.
|
|
59
|
+
|
|
60
|
+
- `initialize(substrate_type:, domain:, content:, potency: nil, volatility: nil)`
|
|
61
|
+
- `ferment!(rate)` — advances maturity and potency by rate; transitions stage
|
|
62
|
+
- `catalyze!(catalyst_type)` — boosts potency by `CATALYSIS_BOOST` if valid catalyst
|
|
63
|
+
- `ripe?`, `peak?`, `spoiled?`, `raw?` — state predicates
|
|
64
|
+
- `to_h` — includes stage, potency, maturity, volatility, labels
|
|
65
|
+
|
|
66
|
+
### `Batch`
|
|
67
|
+
|
|
68
|
+
Groups substrates by domain.
|
|
69
|
+
|
|
70
|
+
- `add_substrate(substrate)`
|
|
71
|
+
- `ferment_all!(rate)` — delegates to each substrate
|
|
72
|
+
|
|
73
|
+
### `FermentationEngine`
|
|
74
|
+
|
|
75
|
+
Manages substrates and batches.
|
|
76
|
+
|
|
77
|
+
- `create_substrate(substrate_type:, domain:, content:, potency: nil, volatility: nil)` — auto-assigns to batch; prunes when at cap
|
|
78
|
+
- `ferment(substrate_id:, rate: MATURATION_RATE)` — single substrate advance
|
|
79
|
+
- `catalyze(substrate_id:, catalyst_type:)` — catalyzes single substrate
|
|
80
|
+
- `ferment_all!(rate: MATURATION_RATE)` — advances all batches
|
|
81
|
+
- `substrates_by_domain(domain:)`, `substrates_by_type(type:)`, `substrates_by_stage(stage:)`
|
|
82
|
+
- `ripe_substrates`, `peak_substrates`, `spoiled_substrates`, `raw_substrates`
|
|
83
|
+
- `most_potent(limit: 5)`, `most_mature(limit: 5)`
|
|
84
|
+
- `overall_potency`, `overall_maturity`, `overall_volatility`, `yield_rate`, `stage_distribution`
|
|
85
|
+
- `fermentation_report` — full stats with labels and top substrates
|
|
86
|
+
|
|
87
|
+
## Runners
|
|
88
|
+
|
|
89
|
+
**Module**: `Legion::Extensions::CognitiveFermentation::Runners::CognitiveFermentation`
|
|
90
|
+
|
|
91
|
+
| Method | Key Args | Returns |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| `create_substrate` | `substrate_type:`, `domain:`, `content:` | `{ success:, substrate: }` |
|
|
94
|
+
| `ferment` | `substrate_id:`, `rate: nil` | `{ success:, substrate: }` |
|
|
95
|
+
| `catalyze` | `substrate_id:`, `catalyst_type:` | `{ success:, substrate: }` |
|
|
96
|
+
| `ferment_all` | `rate: nil` | `{ success: }` |
|
|
97
|
+
| `list_ripe` | — | `{ count:, substrates: }` |
|
|
98
|
+
| `fermentation_status` | — | Full fermentation report |
|
|
99
|
+
|
|
100
|
+
Private: `@default_engine` — memoized `FermentationEngine`. Runner uses `engine || @default_engine` pattern.
|
|
101
|
+
|
|
102
|
+
## Integration Points
|
|
103
|
+
|
|
104
|
+
- **`lex-dream`**: Dream cycle is a natural catalyst source. The `dream_residue` catalyst type in the constants is specifically for materials that surface during the dream cycle and catalyze substrate development.
|
|
105
|
+
- **`lex-memory`**: Ripe substrates could be promoted to memory traces after maturation.
|
|
106
|
+
- **`lex-genesis`**: Fermentation produces potent substrates ready for concept birth.
|
|
107
|
+
|
|
108
|
+
## Development Notes
|
|
109
|
+
|
|
110
|
+
- Pruning order on cap: first removes `spoiled?` substrates, then lowest-potency if still over cap.
|
|
111
|
+
- `ferment_all!` works through the batch grouping, not directly over substrates. Batch-level iteration.
|
|
112
|
+
- `CATALYST_TYPES` includes `sleep` and `dream_residue` — these are valid symbols recognized by `catalyze!`.
|
|
113
|
+
- In-memory only. No persistence.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
**Maintained By**: Matthew Iverson (@Esity)
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
lex-cognitive-fermentation (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-fermentation!
|
|
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,53 @@
|
|
|
1
|
+
# lex-cognitive-fermentation
|
|
2
|
+
|
|
3
|
+
Slow non-linear cognitive maturation model for brain-modeled agentic AI in the LegionIO ecosystem.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Not all cognitive processing is immediate. Raw ideas, unresolved problems, partial patterns, and lingering questions sometimes need time to develop before they yield useful output. This extension models that incubation process using a fermentation metaphor: substrates move through stages from `inoculation` to `peak` maturity, developing potency along the way. Catalysts (analogies, emotional charge, dream residue) accelerate the process. Over-fermented substrates decay.
|
|
8
|
+
|
|
9
|
+
Substrates are grouped into domain-based batches for collective tracking. The engine surfaces which substrates are ripe or at peak, and provides an overall yield rate.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
require 'legion/extensions/cognitive_fermentation'
|
|
15
|
+
|
|
16
|
+
client = Legion::Extensions::CognitiveFermentation::Client.new
|
|
17
|
+
|
|
18
|
+
# Add a substrate
|
|
19
|
+
result = client.create_substrate(
|
|
20
|
+
substrate_type: :unresolved_problem,
|
|
21
|
+
domain: :analytical,
|
|
22
|
+
content: 'Why do requests cluster in the morning?'
|
|
23
|
+
)
|
|
24
|
+
id = result[:substrate][:id]
|
|
25
|
+
|
|
26
|
+
# Advance fermentation naturally
|
|
27
|
+
client.ferment(substrate_id: id)
|
|
28
|
+
|
|
29
|
+
# Apply a catalyst to boost potency
|
|
30
|
+
client.catalyze(substrate_id: id, catalyst_type: :analogy)
|
|
31
|
+
|
|
32
|
+
# Run a full fermentation cycle on all substrates
|
|
33
|
+
client.ferment_all
|
|
34
|
+
|
|
35
|
+
# See what's ready
|
|
36
|
+
client.list_ripe
|
|
37
|
+
# => { count: 0, substrates: [] }
|
|
38
|
+
|
|
39
|
+
# Full status report
|
|
40
|
+
client.fermentation_status
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Development
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bundle install
|
|
47
|
+
bundle exec rspec
|
|
48
|
+
bundle exec rubocop
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_fermentation/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-fermentation'
|
|
7
|
+
spec.version = Legion::Extensions::CognitiveFermentation::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
spec.summary = 'Slow unconscious cognitive processing for LegionIO agents'
|
|
11
|
+
spec.description = 'Models cognitive fermentation — the slow transformation of raw ideas ' \
|
|
12
|
+
'into refined insights through unconscious incubation and catalysis'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-fermentation'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata = {
|
|
18
|
+
'homepage_uri' => spec.homepage,
|
|
19
|
+
'source_code_uri' => spec.homepage,
|
|
20
|
+
'documentation_uri' => "#{spec.homepage}/blob/master/README.md",
|
|
21
|
+
'changelog_uri' => "#{spec.homepage}/blob/master/CHANGELOG.md",
|
|
22
|
+
'bug_tracker_uri' => "#{spec.homepage}/issues",
|
|
23
|
+
'rubygems_mfa_required' => 'true'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
spec.files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
|
+
spec.add_development_dependency 'legion-gaia'
|
|
29
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveFermentation
|
|
6
|
+
class Client
|
|
7
|
+
include Runners::CognitiveFermentation
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@default_engine = Helpers::FermentationEngine.new
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveFermentation
|
|
6
|
+
module Helpers
|
|
7
|
+
class Batch
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :id, :domain, :substrates, :created_at
|
|
11
|
+
|
|
12
|
+
def initialize(domain:)
|
|
13
|
+
@id = SecureRandom.uuid
|
|
14
|
+
@domain = domain.to_sym
|
|
15
|
+
@substrates = []
|
|
16
|
+
@created_at = Time.now.utc
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def add_substrate(substrate)
|
|
20
|
+
@substrates << substrate
|
|
21
|
+
substrate
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def ferment_all!(rate = MATURATION_RATE)
|
|
25
|
+
@substrates.each { |s| s.ferment!(rate) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def average_potency
|
|
29
|
+
return 0.0 if @substrates.empty?
|
|
30
|
+
|
|
31
|
+
(@substrates.sum(&:potency) / @substrates.size).round(10)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def average_maturity
|
|
35
|
+
return 0.0 if @substrates.empty?
|
|
36
|
+
|
|
37
|
+
(@substrates.sum(&:maturity) / @substrates.size).round(10)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def ripe_count = @substrates.count(&:ripe?)
|
|
41
|
+
def peak_count = @substrates.count(&:peak?)
|
|
42
|
+
def spoiled_count = @substrates.count(&:spoiled?)
|
|
43
|
+
def raw_count = @substrates.count(&:raw?)
|
|
44
|
+
|
|
45
|
+
def yield_rate
|
|
46
|
+
return 0.0 if @substrates.empty?
|
|
47
|
+
|
|
48
|
+
(ripe_count.to_f / @substrates.size).round(10)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def ready_to_harvest? = yield_rate >= 0.5
|
|
52
|
+
|
|
53
|
+
def to_h
|
|
54
|
+
{
|
|
55
|
+
id: @id,
|
|
56
|
+
domain: @domain,
|
|
57
|
+
substrate_count: @substrates.size,
|
|
58
|
+
average_potency: average_potency,
|
|
59
|
+
average_maturity: average_maturity,
|
|
60
|
+
ripe_count: ripe_count,
|
|
61
|
+
peak_count: peak_count,
|
|
62
|
+
spoiled_count: spoiled_count,
|
|
63
|
+
yield_rate: yield_rate,
|
|
64
|
+
ready_to_harvest: ready_to_harvest?
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveFermentation
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_SUBSTRATES = 500
|
|
9
|
+
MAX_BATCHES = 50
|
|
10
|
+
|
|
11
|
+
DEFAULT_POTENCY = 0.3
|
|
12
|
+
MATURATION_RATE = 0.05
|
|
13
|
+
VOLATILITY_DECAY = 0.02
|
|
14
|
+
CATALYSIS_BOOST = 0.12
|
|
15
|
+
SPOILAGE_THRESHOLD = 0.1
|
|
16
|
+
RIPE_THRESHOLD = 0.7
|
|
17
|
+
PEAK_THRESHOLD = 0.9
|
|
18
|
+
OVER_FERMENTED_DECAY = 0.03
|
|
19
|
+
|
|
20
|
+
SUBSTRATE_TYPES = %i[
|
|
21
|
+
raw_idea unresolved_problem partial_pattern
|
|
22
|
+
dormant_association vague_intuition half_formed_belief
|
|
23
|
+
contradictory_evidence lingering_question
|
|
24
|
+
].freeze
|
|
25
|
+
|
|
26
|
+
FERMENTATION_STAGES = %i[
|
|
27
|
+
inoculation primary_fermentation secondary_fermentation
|
|
28
|
+
conditioning maturation aging peak over_fermented
|
|
29
|
+
].freeze
|
|
30
|
+
|
|
31
|
+
CATALYST_TYPES = %i[
|
|
32
|
+
analogy contrast juxtaposition
|
|
33
|
+
emotional_charge sleep dream_residue
|
|
34
|
+
environmental_stimulus social_interaction
|
|
35
|
+
].freeze
|
|
36
|
+
|
|
37
|
+
DOMAINS = %i[
|
|
38
|
+
cognitive emotional procedural semantic
|
|
39
|
+
episodic social creative analytical
|
|
40
|
+
].freeze
|
|
41
|
+
|
|
42
|
+
POTENCY_LABELS = {
|
|
43
|
+
(0.8..) => :transcendent,
|
|
44
|
+
(0.6...0.8) => :potent,
|
|
45
|
+
(0.4...0.6) => :developing,
|
|
46
|
+
(0.2...0.4) => :mild,
|
|
47
|
+
(..0.2) => :inert
|
|
48
|
+
}.freeze
|
|
49
|
+
|
|
50
|
+
MATURITY_LABELS = {
|
|
51
|
+
(0.8..) => :peak,
|
|
52
|
+
(0.6...0.8) => :mature,
|
|
53
|
+
(0.4...0.6) => :developing,
|
|
54
|
+
(0.2...0.4) => :young,
|
|
55
|
+
(..0.2) => :raw
|
|
56
|
+
}.freeze
|
|
57
|
+
|
|
58
|
+
VOLATILITY_LABELS = {
|
|
59
|
+
(0.8..) => :explosive,
|
|
60
|
+
(0.6...0.8) => :volatile,
|
|
61
|
+
(0.4...0.6) => :active,
|
|
62
|
+
(0.2...0.4) => :stable,
|
|
63
|
+
(..0.2) => :dormant
|
|
64
|
+
}.freeze
|
|
65
|
+
|
|
66
|
+
def self.label_for(labels, value)
|
|
67
|
+
labels.each { |range, label| return label if range.cover?(value) }
|
|
68
|
+
:unknown
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveFermentation
|
|
6
|
+
module Helpers
|
|
7
|
+
class FermentationEngine
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@substrates = {}
|
|
12
|
+
@batches = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create_substrate(substrate_type:, domain:, content: '', potency: nil, volatility: nil)
|
|
16
|
+
sub = Substrate.new(substrate_type: substrate_type, domain: domain, content: content,
|
|
17
|
+
potency: potency, volatility: volatility)
|
|
18
|
+
@substrates[sub.id] = sub
|
|
19
|
+
batch = find_or_create_batch(domain: domain)
|
|
20
|
+
batch.add_substrate(sub)
|
|
21
|
+
prune_substrates
|
|
22
|
+
sub
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ferment(substrate_id:, rate: MATURATION_RATE)
|
|
26
|
+
sub = @substrates[substrate_id]
|
|
27
|
+
return nil unless sub
|
|
28
|
+
|
|
29
|
+
sub.ferment!(rate)
|
|
30
|
+
sub
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def catalyze(substrate_id:, catalyst_type:)
|
|
34
|
+
sub = @substrates[substrate_id]
|
|
35
|
+
return nil unless sub
|
|
36
|
+
|
|
37
|
+
sub.catalyze!(catalyst_type)
|
|
38
|
+
sub
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ferment_all!(rate: MATURATION_RATE)
|
|
42
|
+
@batches.each_value { |b| b.ferment_all!(rate) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def substrates_by_domain(domain:) = @substrates.values.select { |s| s.domain == domain.to_sym }
|
|
46
|
+
def substrates_by_type(type:) = @substrates.values.select { |s| s.substrate_type == type.to_sym }
|
|
47
|
+
def substrates_by_stage(stage:) = @substrates.values.select { |s| s.stage == stage.to_sym }
|
|
48
|
+
def ripe_substrates = @substrates.values.select(&:ripe?)
|
|
49
|
+
def peak_substrates = @substrates.values.select(&:peak?)
|
|
50
|
+
def spoiled_substrates = @substrates.values.select(&:spoiled?)
|
|
51
|
+
def raw_substrates = @substrates.values.select(&:raw?)
|
|
52
|
+
|
|
53
|
+
def most_potent(limit: 5)
|
|
54
|
+
@substrates.values.sort_by { |s| -s.potency }.first(limit)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def most_mature(limit: 5)
|
|
58
|
+
@substrates.values.sort_by { |s| -s.maturity }.first(limit)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def overall_potency
|
|
62
|
+
return 0.0 if @substrates.empty?
|
|
63
|
+
|
|
64
|
+
(@substrates.values.sum(&:potency) / @substrates.size).round(10)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def overall_maturity
|
|
68
|
+
return 0.0 if @substrates.empty?
|
|
69
|
+
|
|
70
|
+
(@substrates.values.sum(&:maturity) / @substrates.size).round(10)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def overall_volatility
|
|
74
|
+
return 0.0 if @substrates.empty?
|
|
75
|
+
|
|
76
|
+
(@substrates.values.sum(&:volatility) / @substrates.size).round(10)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def yield_rate
|
|
80
|
+
return 0.0 if @substrates.empty?
|
|
81
|
+
|
|
82
|
+
(ripe_substrates.size.to_f / @substrates.size).round(10)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def stage_distribution
|
|
86
|
+
dist = Hash.new(0)
|
|
87
|
+
@substrates.each_value { |s| dist[s.stage] += 1 }
|
|
88
|
+
dist
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def fermentation_report
|
|
92
|
+
{
|
|
93
|
+
total_substrates: @substrates.size,
|
|
94
|
+
total_batches: @batches.size,
|
|
95
|
+
overall_potency: overall_potency,
|
|
96
|
+
potency_label: Constants.label_for(POTENCY_LABELS, overall_potency),
|
|
97
|
+
overall_maturity: overall_maturity,
|
|
98
|
+
maturity_label: Constants.label_for(MATURITY_LABELS, overall_maturity),
|
|
99
|
+
overall_volatility: overall_volatility,
|
|
100
|
+
volatility_label: Constants.label_for(VOLATILITY_LABELS, overall_volatility),
|
|
101
|
+
yield_rate: yield_rate,
|
|
102
|
+
ripe_count: ripe_substrates.size,
|
|
103
|
+
peak_count: peak_substrates.size,
|
|
104
|
+
spoiled_count: spoiled_substrates.size,
|
|
105
|
+
stage_distribution: stage_distribution,
|
|
106
|
+
batches: @batches.values.map(&:to_h),
|
|
107
|
+
most_potent: most_potent(limit: 3).map(&:to_h)
|
|
108
|
+
}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def to_h
|
|
112
|
+
{
|
|
113
|
+
total_substrates: @substrates.size,
|
|
114
|
+
total_batches: @batches.size,
|
|
115
|
+
potency: overall_potency,
|
|
116
|
+
maturity: overall_maturity,
|
|
117
|
+
volatility: overall_volatility
|
|
118
|
+
}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
def find_or_create_batch(domain:)
|
|
124
|
+
key = domain.to_sym
|
|
125
|
+
@batches[key] ||= Batch.new(domain: key)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def prune_substrates
|
|
129
|
+
return if @substrates.size <= MAX_SUBSTRATES
|
|
130
|
+
|
|
131
|
+
spoiled = @substrates.values.select(&:spoiled?)
|
|
132
|
+
spoiled.each { |s| @substrates.delete(s.id) }
|
|
133
|
+
return if @substrates.size <= MAX_SUBSTRATES
|
|
134
|
+
|
|
135
|
+
sorted = @substrates.values.sort_by(&:potency)
|
|
136
|
+
to_remove = sorted.first(@substrates.size - MAX_SUBSTRATES)
|
|
137
|
+
to_remove.each { |s| @substrates.delete(s.id) }
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|