lex-cognitive-cocoon 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 +3 -0
- data/.rubocop.yml +37 -0
- data/CLAUDE.md +72 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +78 -0
- data/README.md +39 -0
- data/lex-cognitive-cocoon.gemspec +29 -0
- data/lib/legion/extensions/cognitive_cocoon/client.rb +15 -0
- data/lib/legion/extensions/cognitive_cocoon/helpers/cocoon.rb +99 -0
- data/lib/legion/extensions/cognitive_cocoon/helpers/constants.rb +41 -0
- data/lib/legion/extensions/cognitive_cocoon/helpers/incubator.rb +98 -0
- data/lib/legion/extensions/cognitive_cocoon/runners/cognitive_cocoon.rb +68 -0
- data/lib/legion/extensions/cognitive_cocoon/version.rb +9 -0
- data/lib/legion/extensions/cognitive_cocoon.rb +19 -0
- data/spec/legion/extensions/cognitive_cocoon/client_spec.rb +146 -0
- data/spec/legion/extensions/cognitive_cocoon/helpers/cocoon_spec.rb +282 -0
- data/spec/legion/extensions/cognitive_cocoon/helpers/constants_spec.rb +105 -0
- data/spec/legion/extensions/cognitive_cocoon/helpers/incubator_spec.rb +230 -0
- data/spec/spec_helper.rb +28 -0
- metadata +84 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: '015861041cc51dbe313a2557691ba5e0ff0b791ad8d85f847554943303eb6e94'
|
|
4
|
+
data.tar.gz: 52d9550926706ae26259b4f1f1e7dfb1ad1feab47aa8b22de87ae074bde16683
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f6e19065a979162ccaa24c6cdb81a96806d7e2009b9573c3da0c54f553c5507e9d19221701241a6637f38065e558e3de112f1154c4df111ec6e9f9fd3667cd33
|
|
7
|
+
data.tar.gz: 1818eaedc7a0be8fbbee37f4c59b0f35a014c3c47c3495ba102c97d46bb470d5a628569564b221cd322c32596c4f956725e40ed989965a9c8732e4be6918ee97
|
|
@@ -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,72 @@
|
|
|
1
|
+
# lex-cognitive-cocoon
|
|
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
|
+
Protective encapsulation of fragile ideas during development. Models cognitive cocooning: fragile ideas enter protective shells, gestate at complexity-appropriate rates, and emerge transformed. Premature exposure risks idea death (premature penalty). Distinct from `lex-cognitive-chrysalis` — cocoon focuses on the protective encapsulation container, while chrysalis models the full metamorphic transformation lifecycle.
|
|
10
|
+
|
|
11
|
+
## Gem Info
|
|
12
|
+
|
|
13
|
+
- **Gem name**: `lex-cognitive-cocoon`
|
|
14
|
+
- **Version**: `0.1.0`
|
|
15
|
+
- **Module**: `Legion::Extensions::CognitiveCocoon`
|
|
16
|
+
- **Ruby**: `>= 3.4`
|
|
17
|
+
- **License**: MIT
|
|
18
|
+
|
|
19
|
+
## File Structure
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
lib/legion/extensions/cognitive_cocoon/
|
|
23
|
+
cognitive_cocoon.rb
|
|
24
|
+
version.rb
|
|
25
|
+
client.rb
|
|
26
|
+
helpers/
|
|
27
|
+
constants.rb
|
|
28
|
+
cocoon.rb
|
|
29
|
+
incubator.rb
|
|
30
|
+
runners/
|
|
31
|
+
cognitive_cocoon.rb
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Key Constants
|
|
35
|
+
|
|
36
|
+
From `helpers/constants.rb`:
|
|
37
|
+
|
|
38
|
+
- `GESTATION_STAGES` — `%i[encapsulating developing transforming ready emerged]`
|
|
39
|
+
- `COCOON_TYPES` — `%i[silk chrysalis shell pod web]`
|
|
40
|
+
- `PROTECTION_BY_TYPE` — `silk: 0.6, chrysalis: 0.8, shell: 0.9, pod: 0.7, web: 0.5`
|
|
41
|
+
- `MAX_COCOONS` = `100`
|
|
42
|
+
- `MATURITY_RATE` = `0.1`, `PREMATURE_PENALTY` = `0.5`
|
|
43
|
+
- `MATURITY_LABELS` — `0.9+` = `:fully_gestated`, `0.7` = `:nearly_ready`, `0.5` = `:mid_gestation`, `0.3` = `:early_gestation`, `0.1` = `:just_encapsulated`, below = `:newly_formed`
|
|
44
|
+
|
|
45
|
+
## Runners
|
|
46
|
+
|
|
47
|
+
All methods in `Runners::CognitiveCocoon`:
|
|
48
|
+
|
|
49
|
+
- `create_cocoon(cocoon_type:, domain:, content: '', maturity: nil, protection: nil)` — creates a new cocoon; protection defaults to `PROTECTION_BY_TYPE[cocoon_type]`
|
|
50
|
+
- `gestate_all(rate: MATURITY_RATE)` — advances maturity on all non-emerged cocoons by rate
|
|
51
|
+
- `harvest_ready` — returns all cocoons that have reached `:ready` or `:emerged` state
|
|
52
|
+
- `force_emerge(id:)` — forces premature emergence; applies `PREMATURE_PENALTY`
|
|
53
|
+
- `cocoon_status` — aggregate incubator report
|
|
54
|
+
- `list_by_stage(stage:)` — filters cocoons by gestation stage
|
|
55
|
+
|
|
56
|
+
## Helpers
|
|
57
|
+
|
|
58
|
+
- `Incubator` — manages the cocoon collection. `harvest_ready` transitions ready cocoons to `:emerged` and returns them.
|
|
59
|
+
- `Cocoon` — has `cocoon_type`, `domain`, `content`, `maturity`, `protection`. `gestate!(rate)` advances maturity; stage is derived from maturity value. `force_emerge!` applies premature penalty and sets stage to `:emerged`.
|
|
60
|
+
|
|
61
|
+
## Integration Points
|
|
62
|
+
|
|
63
|
+
- `lex-cognitive-chrysalis` composes with this extension: a chrysalis can be enclosed in a cocoon (the cocoon provides protection, the chrysalis undergoes transformation inside it).
|
|
64
|
+
- Newly registered `lex-memory` traces during the imprint window (`lex-coldstart`) are conceptually in a cocooned state — fragile associations that should not be immediately overwritten or decayed.
|
|
65
|
+
- `gestate_all` is the natural periodic runner to call each tick cycle.
|
|
66
|
+
|
|
67
|
+
## Development Notes
|
|
68
|
+
|
|
69
|
+
- `@default_engine` is referenced directly in runner methods (not via a private method helper) — this differs from other extensions. The runner accesses `@default_engine` directly; callers must pass `engine:` to avoid sharing state across runner instances.
|
|
70
|
+
- `protection` defaults to `PROTECTION_BY_TYPE[cocoon_type]` if not specified — callers who want to set a custom protection must pass it explicitly.
|
|
71
|
+
- `PREMATURE_PENALTY = 0.5` reduces maturity on forced emergence, not a separate beauty score.
|
|
72
|
+
- `MAX_COCOONS = 100` — at capacity, new cocoon creation raises an error.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
lex-cognitive-cocoon (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-cocoon!
|
|
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,39 @@
|
|
|
1
|
+
# lex-cognitive-cocoon
|
|
2
|
+
|
|
3
|
+
Protective encapsulation of fragile ideas during development for LegionIO agents. Models cognitive cocooning — fragile ideas enter protective shells, gestate at complexity-appropriate rates, and emerge transformed.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Not all ideas are ready for the world. Some need protected incubation before they are robust enough to integrate with existing knowledge. This extension models that protective phase: ideas are wrapped in type-appropriate cocoons (silk, chrysalis, shell, pod, web) with different protection strengths, and gestate through stages until they are ready to emerge. Premature forced emergence applies a maturity penalty.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
client = Legion::Extensions::CognitiveCocoon::Client.new
|
|
13
|
+
|
|
14
|
+
cocoon = client.create_cocoon(
|
|
15
|
+
cocoon_type: :shell,
|
|
16
|
+
domain: :identity,
|
|
17
|
+
content: 'tentative belief about autonomy thresholds'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Call periodically to advance gestation
|
|
21
|
+
5.times { client.gestate_all(rate: 0.1) }
|
|
22
|
+
|
|
23
|
+
client.cocoon_status
|
|
24
|
+
# => { total: 1, ready: 0, emerged: 0, ... }
|
|
25
|
+
|
|
26
|
+
ready = client.harvest_ready
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Development
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bundle install
|
|
33
|
+
bundle exec rspec
|
|
34
|
+
bundle exec rubocop
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_cocoon/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-cocoon'
|
|
7
|
+
spec.version = Legion::Extensions::CognitiveCocoon::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
spec.summary = 'Protective encapsulation of fragile ideas during development for LegionIO agents'
|
|
11
|
+
spec.description = 'Models cognitive cocooning — fragile ideas enter protective shells, gestate ' \
|
|
12
|
+
'at complexity-appropriate rates, and emerge transformed. Premature exposure risks idea death.'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-cocoon'
|
|
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,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveCocoon
|
|
6
|
+
module Helpers
|
|
7
|
+
class Cocoon
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :id, :cocoon_type, :domain, :content, :maturity,
|
|
11
|
+
:stage, :protection, :created_at
|
|
12
|
+
|
|
13
|
+
def initialize(cocoon_type:, domain:, content: '', maturity: nil, protection: nil)
|
|
14
|
+
@id = SecureRandom.uuid
|
|
15
|
+
@cocoon_type = cocoon_type.to_sym
|
|
16
|
+
@domain = domain.to_sym
|
|
17
|
+
@content = content
|
|
18
|
+
@maturity = (maturity || 0.0).to_f.clamp(0.0, 1.0)
|
|
19
|
+
@protection = (protection || PROTECTION_BY_TYPE.fetch(@cocoon_type, 0.7)).to_f.clamp(0.0, 1.0)
|
|
20
|
+
@stage = :encapsulating
|
|
21
|
+
@created_at = Time.now.utc
|
|
22
|
+
advance_stage!
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def gestate!(rate = MATURITY_RATE)
|
|
26
|
+
return self if @stage == :emerged
|
|
27
|
+
|
|
28
|
+
@maturity = (@maturity + rate).clamp(0.0, 1.0).round(10)
|
|
29
|
+
advance_stage!
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def emerge!
|
|
34
|
+
return { success: false, error: 'not ready', damaged: false } unless ready?
|
|
35
|
+
|
|
36
|
+
@stage = :emerged
|
|
37
|
+
{ success: true, content: @content, damaged: false, maturity: @maturity }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def expose!
|
|
41
|
+
damaged = premature?
|
|
42
|
+
@maturity = (@maturity * PREMATURE_PENALTY).round(10) if damaged
|
|
43
|
+
@stage = :emerged
|
|
44
|
+
{ success: true, content: @content, damaged: damaged, maturity: @maturity }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def ready?
|
|
48
|
+
@maturity >= 1.0 || @stage == :ready
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def premature?
|
|
52
|
+
@stage != :ready && @stage != :emerged && @maturity < 1.0
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def age_seconds
|
|
56
|
+
(Time.now.utc - @created_at).round(2)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def to_h
|
|
60
|
+
{
|
|
61
|
+
id: @id,
|
|
62
|
+
cocoon_type: @cocoon_type,
|
|
63
|
+
domain: @domain,
|
|
64
|
+
content: @content,
|
|
65
|
+
maturity: @maturity.round(10),
|
|
66
|
+
stage: @stage,
|
|
67
|
+
protection: @protection.round(10),
|
|
68
|
+
ready: ready?,
|
|
69
|
+
premature: premature?,
|
|
70
|
+
maturity_label: Constants.label_for(MATURITY_LABELS, @maturity),
|
|
71
|
+
age_seconds: age_seconds,
|
|
72
|
+
created_at: @created_at.iso8601
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def advance_stage!
|
|
79
|
+
@stage = compute_stage
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def compute_stage
|
|
83
|
+
return :emerged if @stage == :emerged
|
|
84
|
+
|
|
85
|
+
if @maturity >= 1.0
|
|
86
|
+
:ready
|
|
87
|
+
elsif @maturity >= 0.75
|
|
88
|
+
:transforming
|
|
89
|
+
elsif @maturity >= 0.4
|
|
90
|
+
:developing
|
|
91
|
+
else
|
|
92
|
+
:encapsulating
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveCocoon
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_COCOONS = 100
|
|
9
|
+
MATURITY_RATE = 0.1
|
|
10
|
+
PREMATURE_PENALTY = 0.5
|
|
11
|
+
|
|
12
|
+
GESTATION_STAGES = %i[encapsulating developing transforming ready emerged].freeze
|
|
13
|
+
|
|
14
|
+
COCOON_TYPES = %i[silk chrysalis shell pod web].freeze
|
|
15
|
+
|
|
16
|
+
PROTECTION_BY_TYPE = {
|
|
17
|
+
silk: 0.6,
|
|
18
|
+
chrysalis: 0.8,
|
|
19
|
+
shell: 0.9,
|
|
20
|
+
pod: 0.7,
|
|
21
|
+
web: 0.5
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
MATURITY_LABELS = {
|
|
25
|
+
(0.9..) => :fully_gestated,
|
|
26
|
+
(0.7...0.9) => :nearly_ready,
|
|
27
|
+
(0.5...0.7) => :mid_gestation,
|
|
28
|
+
(0.3...0.5) => :early_gestation,
|
|
29
|
+
(0.1...0.3) => :just_encapsulated,
|
|
30
|
+
(..0.1) => :newly_formed
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
def self.label_for(labels, value)
|
|
34
|
+
labels.each { |range, label| return label if range.cover?(value) }
|
|
35
|
+
:unknown
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveCocoon
|
|
6
|
+
module Helpers
|
|
7
|
+
class Incubator
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@cocoons = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create_cocoon(cocoon_type:, domain:, content: '', maturity: nil, protection: nil)
|
|
15
|
+
prune_cocoons
|
|
16
|
+
cocoon = Cocoon.new(
|
|
17
|
+
cocoon_type: cocoon_type,
|
|
18
|
+
domain: domain,
|
|
19
|
+
content: content,
|
|
20
|
+
maturity: maturity,
|
|
21
|
+
protection: protection
|
|
22
|
+
)
|
|
23
|
+
@cocoons[cocoon.id] = cocoon
|
|
24
|
+
cocoon
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def gestate_all!(rate = MATURITY_RATE)
|
|
28
|
+
@cocoons.each_value { |c| c.gestate!(rate) unless c.stage == :emerged }
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def harvest_ready
|
|
33
|
+
ready = @cocoons.values.select(&:ready?)
|
|
34
|
+
results = ready.map(&:emerge!)
|
|
35
|
+
ready.each { |c| @cocoons.delete(c.id) if c.stage == :emerged }
|
|
36
|
+
results
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def force_emerge(id)
|
|
40
|
+
cocoon = @cocoons[id]
|
|
41
|
+
return { success: false, error: 'cocoon not found' } unless cocoon
|
|
42
|
+
|
|
43
|
+
result = cocoon.expose!
|
|
44
|
+
@cocoons.delete(id) if cocoon.stage == :emerged
|
|
45
|
+
result
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def by_stage(stage)
|
|
49
|
+
@cocoons.values.select { |c| c.stage == stage.to_sym }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def most_mature(limit: 5)
|
|
53
|
+
@cocoons.values.sort_by { |c| -c.maturity }.first(limit)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def incubator_report
|
|
57
|
+
total = @cocoons.size
|
|
58
|
+
by_s = Hash.new(0)
|
|
59
|
+
@cocoons.each_value { |c| by_s[c.stage] += 1 }
|
|
60
|
+
avg_mat = total.zero? ? 0.0 : (@cocoons.values.sum(&:maturity) / total).round(10)
|
|
61
|
+
avg_prot = total.zero? ? 0.0 : (@cocoons.values.sum(&:protection) / total).round(10)
|
|
62
|
+
|
|
63
|
+
{
|
|
64
|
+
total_cocoons: total,
|
|
65
|
+
average_maturity: avg_mat,
|
|
66
|
+
maturity_label: Constants.label_for(MATURITY_LABELS, avg_mat),
|
|
67
|
+
average_protection: avg_prot,
|
|
68
|
+
stage_distribution: by_s,
|
|
69
|
+
ready_count: by_stage(:ready).size,
|
|
70
|
+
most_mature: most_mature(limit: 3).map(&:to_h)
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_h
|
|
75
|
+
{
|
|
76
|
+
total_cocoons: @cocoons.size,
|
|
77
|
+
average_maturity: @cocoons.empty? ? 0.0 : (@cocoons.values.sum(&:maturity) / @cocoons.size).round(10)
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def prune_cocoons
|
|
84
|
+
return if @cocoons.size < MAX_COCOONS
|
|
85
|
+
|
|
86
|
+
emerged = @cocoons.values.select { |c| c.stage == :emerged }
|
|
87
|
+
emerged.each { |c| @cocoons.delete(c.id) }
|
|
88
|
+
return if @cocoons.size < MAX_COCOONS
|
|
89
|
+
|
|
90
|
+
sorted = @cocoons.values.sort_by(&:maturity)
|
|
91
|
+
to_remove = sorted.first(@cocoons.size - MAX_COCOONS + 1)
|
|
92
|
+
to_remove.each { |c| @cocoons.delete(c.id) }
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveCocoon
|
|
6
|
+
module Runners
|
|
7
|
+
module CognitiveCocoon
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
|
|
9
|
+
|
|
10
|
+
def create_cocoon(cocoon_type:, domain:, content: '', maturity: nil,
|
|
11
|
+
protection: nil, engine: nil, **)
|
|
12
|
+
eng = engine || @default_engine
|
|
13
|
+
cocoon = eng.create_cocoon(
|
|
14
|
+
cocoon_type: cocoon_type,
|
|
15
|
+
domain: domain,
|
|
16
|
+
content: content,
|
|
17
|
+
maturity: maturity,
|
|
18
|
+
protection: protection
|
|
19
|
+
)
|
|
20
|
+
{ success: true, cocoon: cocoon.to_h }
|
|
21
|
+
rescue ArgumentError => e
|
|
22
|
+
{ success: false, error: e.message }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def gestate_all(rate: nil, engine: nil, **)
|
|
26
|
+
eng = engine || @default_engine
|
|
27
|
+
eng.gestate_all!(rate || Helpers::Constants::MATURITY_RATE)
|
|
28
|
+
{ success: true }
|
|
29
|
+
rescue ArgumentError => e
|
|
30
|
+
{ success: false, error: e.message }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def harvest_ready(engine: nil, **)
|
|
34
|
+
eng = engine || @default_engine
|
|
35
|
+
emerged = eng.harvest_ready
|
|
36
|
+
{ success: true, count: emerged.size, emerged: emerged }
|
|
37
|
+
rescue ArgumentError => e
|
|
38
|
+
{ success: false, error: e.message }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def force_emerge(id:, engine: nil, **)
|
|
42
|
+
eng = engine || @default_engine
|
|
43
|
+
result = eng.force_emerge(id)
|
|
44
|
+
result.merge(success: result[:error].nil?)
|
|
45
|
+
rescue ArgumentError => e
|
|
46
|
+
{ success: false, error: e.message }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def cocoon_status(engine: nil, **)
|
|
50
|
+
eng = engine || @default_engine
|
|
51
|
+
report = eng.incubator_report
|
|
52
|
+
{ success: true, **report }
|
|
53
|
+
rescue ArgumentError => e
|
|
54
|
+
{ success: false, error: e.message }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def list_by_stage(stage:, engine: nil, **)
|
|
58
|
+
eng = engine || @default_engine
|
|
59
|
+
cocoons = eng.by_stage(stage)
|
|
60
|
+
{ success: true, stage: stage, count: cocoons.size, cocoons: cocoons.map(&:to_h) }
|
|
61
|
+
rescue ArgumentError => e
|
|
62
|
+
{ success: false, error: e.message }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
require_relative 'cognitive_cocoon/version'
|
|
6
|
+
require_relative 'cognitive_cocoon/helpers/constants'
|
|
7
|
+
require_relative 'cognitive_cocoon/helpers/cocoon'
|
|
8
|
+
require_relative 'cognitive_cocoon/helpers/incubator'
|
|
9
|
+
require_relative 'cognitive_cocoon/runners/cognitive_cocoon'
|
|
10
|
+
require_relative 'cognitive_cocoon/client'
|
|
11
|
+
|
|
12
|
+
module Legion
|
|
13
|
+
module Extensions
|
|
14
|
+
module CognitiveCocoon
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Legion::Extensions.extend(Legion::Extensions::Core) if Legion::Extensions.const_defined?(:Core)
|