lex-cognitive-chrysalis 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 +12 -0
- data/.rspec +4 -0
- data/.rubocop.yml +32 -0
- data/CLAUDE.md +81 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +78 -0
- data/README.md +42 -0
- data/lex-cognitive-chrysalis.gemspec +28 -0
- data/lib/legion/extensions/cognitive_chrysalis/client.rb +18 -0
- data/lib/legion/extensions/cognitive_chrysalis/helpers/chrysalis.rb +133 -0
- data/lib/legion/extensions/cognitive_chrysalis/helpers/cocoon.rb +85 -0
- data/lib/legion/extensions/cognitive_chrysalis/helpers/constants.rb +45 -0
- data/lib/legion/extensions/cognitive_chrysalis/helpers/metamorphosis_engine.rb +153 -0
- data/lib/legion/extensions/cognitive_chrysalis/runners/cognitive_chrysalis.rb +125 -0
- data/lib/legion/extensions/cognitive_chrysalis/version.rb +9 -0
- data/lib/legion/extensions/cognitive_chrysalis.rb +18 -0
- data/spec/legion/extensions/cognitive_chrysalis/client_spec.rb +83 -0
- data/spec/legion/extensions/cognitive_chrysalis/helpers/chrysalis_engine_spec.rb +57 -0
- data/spec/legion/extensions/cognitive_chrysalis/helpers/chrysalis_spec.rb +305 -0
- data/spec/legion/extensions/cognitive_chrysalis/helpers/cocoon_spec.rb +206 -0
- data/spec/legion/extensions/cognitive_chrysalis/helpers/constants_spec.rb +109 -0
- data/spec/legion/extensions/cognitive_chrysalis/helpers/metamorphic_cycle_spec.rb +76 -0
- data/spec/legion/extensions/cognitive_chrysalis/helpers/metamorphosis_engine_spec.rb +247 -0
- data/spec/legion/extensions/cognitive_chrysalis/helpers/transformation_phase_spec.rb +98 -0
- data/spec/legion/extensions/cognitive_chrysalis/runners/cognitive_chrysalis_spec.rb +180 -0
- data/spec/legion/extensions/cognitive_chrysalis/runners/reporting_spec.rb +81 -0
- data/spec/legion/extensions/cognitive_chrysalis/runners/transformation_spec.rb +74 -0
- data/spec/legion/extensions/cognitive_chrysalis_spec.rb +15 -0
- data/spec/spec_helper.rb +20 -0
- metadata +91 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c7aed07ab9c483e7513ebc0122e1c571c1d0edc409a568cd929bc3e5d75d6b79
|
|
4
|
+
data.tar.gz: c74edc3c6961ae25718351bebacdd8ed30a5a8964eff553428108292cbc3a0d4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: bc485de3f19aef24d91a1ab266e22cc07b22744f58f47f83f6c6ecae8dba9cc05a8fb2068fa04c9f86982c5fb7d32897e77fb365b9c3e30a09b31777d3758c44
|
|
7
|
+
data.tar.gz: ec30ffc37864ca2282108040efbe4eb91113e6455b95584480219f60810894da6f7cc7e064e762693038c8322e7946dfb45c62710cc17065d2da4b8371168167
|
|
@@ -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,32 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
NewCops: enable
|
|
3
|
+
TargetRubyVersion: 3.4
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
Layout/LineLength:
|
|
6
|
+
Max: 160
|
|
7
|
+
Style/Documentation:
|
|
8
|
+
Enabled: false
|
|
9
|
+
Naming/PredicateMethod:
|
|
10
|
+
Enabled: false
|
|
11
|
+
Naming/PredicatePrefix:
|
|
12
|
+
Enabled: false
|
|
13
|
+
Metrics/ClassLength:
|
|
14
|
+
Max: 150
|
|
15
|
+
Metrics/MethodLength:
|
|
16
|
+
Max: 25
|
|
17
|
+
Metrics/AbcSize:
|
|
18
|
+
Max: 25
|
|
19
|
+
Metrics/ParameterLists:
|
|
20
|
+
Max: 8
|
|
21
|
+
MaxOptionalParameters: 8
|
|
22
|
+
Layout/HashAlignment:
|
|
23
|
+
EnforcedColonStyle: table
|
|
24
|
+
EnforcedHashRocketStyle: table
|
|
25
|
+
Metrics/BlockLength:
|
|
26
|
+
Exclude:
|
|
27
|
+
- 'spec/**/*'
|
|
28
|
+
Style/FrozenStringLiteralComment:
|
|
29
|
+
Enabled: true
|
|
30
|
+
Style/OneClassPerFile:
|
|
31
|
+
Exclude:
|
|
32
|
+
- 'spec/spec_helper.rb'
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# lex-cognitive-chrysalis
|
|
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
|
+
Metamorphic identity transformation for LegionIO agents. Models structured dissolution and reformation cycles: ideas or identity facets enter a chrysalis, transform through protected incubation, and emerge as something qualitatively different. Premature emergence (forced before transformation is complete) reduces beauty and can produce damaged outputs.
|
|
10
|
+
|
|
11
|
+
## Gem Info
|
|
12
|
+
|
|
13
|
+
- **Gem name**: `lex-cognitive-chrysalis`
|
|
14
|
+
- **Version**: `0.1.0`
|
|
15
|
+
- **Module**: `Legion::Extensions::CognitiveChrysalis`
|
|
16
|
+
- **Ruby**: `>= 3.4`
|
|
17
|
+
- **License**: MIT
|
|
18
|
+
|
|
19
|
+
## File Structure
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
lib/legion/extensions/cognitive_chrysalis/
|
|
23
|
+
cognitive_chrysalis.rb
|
|
24
|
+
version.rb
|
|
25
|
+
client.rb
|
|
26
|
+
helpers/
|
|
27
|
+
constants.rb
|
|
28
|
+
chrysalis.rb
|
|
29
|
+
cocoon.rb
|
|
30
|
+
metamorphosis_engine.rb
|
|
31
|
+
runners/
|
|
32
|
+
cognitive_chrysalis.rb
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Key Constants
|
|
36
|
+
|
|
37
|
+
From `helpers/constants.rb`:
|
|
38
|
+
|
|
39
|
+
- `LIFE_STAGES` — `%i[larva spinning cocooned transforming emerging butterfly]`
|
|
40
|
+
- `CHRYSALIS_TYPES` — `%i[silk paper bark leaf underground]`
|
|
41
|
+
- `MAX_CHRYSALISES` = `200`, `MAX_BUTTERFLIES` = `500`
|
|
42
|
+
- `TRANSFORMATION_RATE` = `0.08`, `PROTECTION_DECAY` = `0.03`
|
|
43
|
+
- `EMERGENCE_THRESHOLD` = `0.9` (transformation_progress must reach this for natural emergence)
|
|
44
|
+
- `PREMATURE_PENALTY` = `0.4` (beauty penalty for forced emergence before threshold)
|
|
45
|
+
- `STAGE_LABELS` — progress-to-stage mapping: `0.0-0.20` = `:larva`, `0.20-0.40` = `:spinning`, up to `0.90-1.0` = `:butterfly`
|
|
46
|
+
- `BEAUTY_LABELS` — `0.85+` = `:magnificent`, `0.65` = `:beautiful`, `0.40` = `:striking`, `0.20` = `:plain`, below = `:dull`
|
|
47
|
+
|
|
48
|
+
## Runners
|
|
49
|
+
|
|
50
|
+
All methods in `Runners::CognitiveChrysalis` (`extend self`):
|
|
51
|
+
|
|
52
|
+
- `create_chrysalis(chrysalis_type: :silk, content: '')` — creates a new chrysalis in `:larva` stage
|
|
53
|
+
- `create_cocoon(environment: 'default', temperature: 0.5, humidity: 0.5)` — creates a protective cocoon environment
|
|
54
|
+
- `spin(chrysalis_id:)` — advances chrysalis from `:larva` to `:spinning`; must be in `:larva` state
|
|
55
|
+
- `enclose(chrysalis_id:, cocoon_id:)` — places a chrysalis inside a cocoon
|
|
56
|
+
- `incubate(chrysalis_id:)` — advances transformation progress by `TRANSFORMATION_RATE`
|
|
57
|
+
- `incubate_all` — incubates all eligible (non-butterfly) chrysalises
|
|
58
|
+
- `emerge(chrysalis_id:, force: false)` — natural emergence requires `transformation_progress >= 0.9`; forced emergence applies `PREMATURE_PENALTY` to beauty
|
|
59
|
+
- `disturb(cocoon_id:, force: 0.1)` — degrades cocoon protection; if protection drops to 0 during active transformation, triggers forced emergence
|
|
60
|
+
- `list_chrysalises` — all chrysalises with current state
|
|
61
|
+
- `metamorphosis_status` — aggregate report
|
|
62
|
+
|
|
63
|
+
## Helpers
|
|
64
|
+
|
|
65
|
+
- `MetamorphosisEngine` — manages chrysalises and cocoons.
|
|
66
|
+
- `Chrysalis` — state machine through `LIFE_STAGES`. `transform!(rate)` advances progress and beauty. `emerge!(force:)` checks threshold; forced emergence sets `@premature = true` and applies beauty penalty. `disturb!(force)` degrades protection.
|
|
67
|
+
- `Cocoon` — protective environment with temperature, humidity, protection score.
|
|
68
|
+
|
|
69
|
+
## Integration Points
|
|
70
|
+
|
|
71
|
+
- `lex-cognitive-cocoon` is a related but distinct extension — cocoon models the protective encapsulation of fragile ideas; chrysalis models the full metamorphic transformation lifecycle (larva through butterfly). They can compose: a cocoon provides the environment, a chrysalis undergoes the transformation inside it.
|
|
72
|
+
- `lex-memory` can hold chrysalis IDs as pending transformation traces — ideas that are not ready for activation but are undergoing gradual consolidation.
|
|
73
|
+
- `lex-coldstart` imprint window is conceptually similar to the chrysalis state: ideas absorbed during cold start are in a protected transformation phase.
|
|
74
|
+
|
|
75
|
+
## Development Notes
|
|
76
|
+
|
|
77
|
+
- Stage progression is strictly one-directional: larva -> spinning -> cocooned -> transforming -> emerging -> butterfly. No regression.
|
|
78
|
+
- `spin!` on a non-larva chrysalis raises `ArgumentError`. The runner returns `{ success: false, reason: e.message }`.
|
|
79
|
+
- `transform!` auto-advances stage by comparing current stage rank vs progress-derived stage rank, taking the maximum. This means a chrysalis never regresses stages even if progress somehow decreases.
|
|
80
|
+
- `premature?` convenience predicate: `butterfly? && beauty < 0.5`.
|
|
81
|
+
- `beauty` is computed as `transformation_progress * 0.9` during incubation; full beauty (1.0) only on natural emergence.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
lex-cognitive-chrysalis (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-chrysalis!
|
|
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,42 @@
|
|
|
1
|
+
# lex-cognitive-chrysalis
|
|
2
|
+
|
|
3
|
+
Metamorphic identity transformation for LegionIO agents. Models structured dissolution and reformation cycles for the cognitive architecture.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Some ideas and identity facets require deep transformation before they are useful — not incremental improvement, but dissolution and reformation into something qualitatively different. This extension models that metamorphic process: a larva enters a protective chrysalis, incubates through multiple transformation stages, and emerges as a butterfly. Emergence quality (beauty) depends on whether the transformation ran to completion or was forced prematurely.
|
|
8
|
+
|
|
9
|
+
Five chrysalis types provide different protection levels: silk (0.6), leaf (protected), bark (0.7), paper, and underground (highest). External disturbances can degrade cocoon protection and trigger premature emergence with a beauty penalty.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
client = Legion::Extensions::CognitiveChrysalis::Client.new
|
|
15
|
+
|
|
16
|
+
cocoon = client.create_cocoon(environment: 'quiet_space', temperature: 0.6, humidity: 0.5)
|
|
17
|
+
|
|
18
|
+
chrysalis = client.create_chrysalis(
|
|
19
|
+
chrysalis_type: :silk,
|
|
20
|
+
content: 'core identity belief under revision'
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
client.spin(chrysalis_id: chrysalis[:chrysalis][:id])
|
|
24
|
+
client.enclose(chrysalis_id: chrysalis[:chrysalis][:id],
|
|
25
|
+
cocoon_id: cocoon[:cocoon][:id])
|
|
26
|
+
|
|
27
|
+
10.times { client.incubate(chrysalis_id: chrysalis[:chrysalis][:id]) }
|
|
28
|
+
|
|
29
|
+
client.emerge(chrysalis_id: chrysalis[:chrysalis][:id])
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Development
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bundle install
|
|
36
|
+
bundle exec rspec
|
|
37
|
+
bundle exec rubocop
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## License
|
|
41
|
+
|
|
42
|
+
MIT
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_chrysalis/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-chrysalis'
|
|
7
|
+
spec.version = Legion::Extensions::CognitiveChrysalis::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'LEX Cognitive Chrysalis'
|
|
12
|
+
spec.description = 'Metamorphic identity transformation for LegionIO agents — structured dissolution and reformation cycles'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-chrysalis'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-cognitive-chrysalis'
|
|
19
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-chrysalis'
|
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-chrysalis'
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-chrysalis/issues'
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
|
+
|
|
24
|
+
spec.files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
|
|
25
|
+
|
|
26
|
+
spec.require_paths = ['lib']
|
|
27
|
+
spec.add_development_dependency 'legion-gaia'
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveChrysalis
|
|
6
|
+
class Client
|
|
7
|
+
include Runners::CognitiveChrysalis
|
|
8
|
+
|
|
9
|
+
attr_reader :engine
|
|
10
|
+
|
|
11
|
+
def initialize(**)
|
|
12
|
+
@engine = Helpers::MetamorphosisEngine.new
|
|
13
|
+
@default_engine = @engine
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveChrysalis
|
|
8
|
+
module Helpers
|
|
9
|
+
class Chrysalis
|
|
10
|
+
attr_reader :id, :chrysalis_type, :content, :stage,
|
|
11
|
+
:transformation_progress, :protection, :beauty, :created_at
|
|
12
|
+
|
|
13
|
+
def initialize(chrysalis_type:, content:, **)
|
|
14
|
+
@id = SecureRandom.uuid
|
|
15
|
+
@chrysalis_type = chrysalis_type.to_sym
|
|
16
|
+
@content = content.to_s
|
|
17
|
+
@stage = :larva
|
|
18
|
+
@transformation_progress = 0.0
|
|
19
|
+
@protection = 0.8
|
|
20
|
+
@beauty = 0.0
|
|
21
|
+
@created_at = Time.now.utc
|
|
22
|
+
@premature = false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def spin!
|
|
26
|
+
raise ArgumentError, "must be :larva to spin, currently #{@stage}" unless @stage == :larva
|
|
27
|
+
|
|
28
|
+
@stage = :spinning
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def cocoon!
|
|
33
|
+
raise ArgumentError, "must be :spinning to cocoon, currently #{@stage}" unless @stage == :spinning
|
|
34
|
+
|
|
35
|
+
@stage = :cocooned
|
|
36
|
+
true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def transform!(rate = Helpers::Constants::TRANSFORMATION_RATE)
|
|
40
|
+
return false if @stage == :butterfly
|
|
41
|
+
|
|
42
|
+
@transformation_progress = (@transformation_progress + rate).clamp(0.0, 1.0).round(10)
|
|
43
|
+
@beauty = (@transformation_progress * 0.9).clamp(0.0, 1.0).round(10)
|
|
44
|
+
update_stage_from_progress!
|
|
45
|
+
true
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def emerge!(force: false)
|
|
49
|
+
if @transformation_progress >= Helpers::Constants::EMERGENCE_THRESHOLD
|
|
50
|
+
@stage = :butterfly
|
|
51
|
+
@beauty = 1.0
|
|
52
|
+
elsif force
|
|
53
|
+
@premature = true
|
|
54
|
+
@stage = :butterfly
|
|
55
|
+
@beauty = (@beauty - Helpers::Constants::PREMATURE_PENALTY).clamp(0.0, 1.0).round(10)
|
|
56
|
+
else
|
|
57
|
+
return false
|
|
58
|
+
end
|
|
59
|
+
true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def decay_protection!
|
|
63
|
+
@protection = (@protection - Helpers::Constants::PROTECTION_DECAY).clamp(0.0, 1.0).round(10)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def disturb!(force)
|
|
67
|
+
@protection = (@protection - force.to_f).clamp(0.0, 1.0).round(10)
|
|
68
|
+
emerge!(force: true) if @protection <= 0 && %i[cocooned transforming].include?(@stage)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def butterfly?
|
|
72
|
+
@stage == :butterfly
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def cocooned?
|
|
76
|
+
@stage == :cocooned
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def transforming?
|
|
80
|
+
@stage == :transforming
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def premature?
|
|
84
|
+
butterfly? && @beauty < 0.5
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def stage_label
|
|
88
|
+
Helpers::Constants.label_for(Helpers::Constants::STAGE_LABELS, @transformation_progress)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def beauty_label
|
|
92
|
+
Helpers::Constants.label_for(Helpers::Constants::BEAUTY_LABELS, @beauty)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def to_h
|
|
96
|
+
{
|
|
97
|
+
id: @id,
|
|
98
|
+
chrysalis_type: @chrysalis_type,
|
|
99
|
+
content: @content,
|
|
100
|
+
stage: @stage,
|
|
101
|
+
transformation_progress: @transformation_progress,
|
|
102
|
+
protection: @protection,
|
|
103
|
+
beauty: @beauty,
|
|
104
|
+
stage_label: stage_label,
|
|
105
|
+
beauty_label: beauty_label,
|
|
106
|
+
premature: @premature,
|
|
107
|
+
created_at: @created_at
|
|
108
|
+
}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def update_stage_from_progress!
|
|
114
|
+
progress_stage = if @transformation_progress >= 0.8
|
|
115
|
+
:emerging
|
|
116
|
+
elsif @transformation_progress >= 0.6
|
|
117
|
+
:transforming
|
|
118
|
+
elsif @transformation_progress >= 0.4
|
|
119
|
+
:cocooned
|
|
120
|
+
elsif @transformation_progress >= 0.2
|
|
121
|
+
:spinning
|
|
122
|
+
else
|
|
123
|
+
:larva
|
|
124
|
+
end
|
|
125
|
+
current_rank = Helpers::Constants::LIFE_STAGES.index(@stage) || 0
|
|
126
|
+
progress_rank = Helpers::Constants::LIFE_STAGES.index(progress_stage) || 0
|
|
127
|
+
@stage = Helpers::Constants::LIFE_STAGES[[current_rank, progress_rank].max]
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveChrysalis
|
|
8
|
+
module Helpers
|
|
9
|
+
class Cocoon
|
|
10
|
+
attr_reader :id, :environment, :temperature, :humidity, :chrysalis_ids, :created_at
|
|
11
|
+
|
|
12
|
+
TEMP_ADJUST = 0.05
|
|
13
|
+
HUMID_ADJUST = 0.05
|
|
14
|
+
|
|
15
|
+
def initialize(environment:, temperature: 0.5, humidity: 0.5, **)
|
|
16
|
+
@id = SecureRandom.uuid
|
|
17
|
+
@environment = environment.to_s
|
|
18
|
+
@temperature = temperature.to_f.clamp(0.0, 1.0)
|
|
19
|
+
@humidity = humidity.to_f.clamp(0.0, 1.0)
|
|
20
|
+
@chrysalis_ids = []
|
|
21
|
+
@created_at = Time.now.utc
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def shelter(chrysalis_id)
|
|
25
|
+
@chrysalis_ids << chrysalis_id unless @chrysalis_ids.include?(chrysalis_id)
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def expose(chrysalis_id)
|
|
30
|
+
@chrysalis_ids.delete(chrysalis_id)
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def warm!
|
|
35
|
+
@temperature = (@temperature + TEMP_ADJUST).clamp(0.0, 1.0).round(10)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def cool!
|
|
39
|
+
@temperature = (@temperature - TEMP_ADJUST).clamp(0.0, 1.0).round(10)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def moisten!
|
|
43
|
+
@humidity = (@humidity + HUMID_ADJUST).clamp(0.0, 1.0).round(10)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def dry!
|
|
47
|
+
@humidity = (@humidity - HUMID_ADJUST).clamp(0.0, 1.0).round(10)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def ideal?
|
|
51
|
+
@temperature.between?(0.4, 0.7) && @humidity.between?(0.4, 0.7)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def hostile?
|
|
55
|
+
@temperature > 0.9 || @humidity < 0.1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def growth_modifier
|
|
59
|
+
if ideal?
|
|
60
|
+
0.1
|
|
61
|
+
elsif hostile?
|
|
62
|
+
-0.05
|
|
63
|
+
else
|
|
64
|
+
0.0
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def to_h
|
|
69
|
+
{
|
|
70
|
+
id: @id,
|
|
71
|
+
environment: @environment,
|
|
72
|
+
temperature: @temperature,
|
|
73
|
+
humidity: @humidity,
|
|
74
|
+
chrysalis_ids: @chrysalis_ids.dup,
|
|
75
|
+
ideal: ideal?,
|
|
76
|
+
hostile: hostile?,
|
|
77
|
+
growth_modifier: growth_modifier,
|
|
78
|
+
created_at: @created_at
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveChrysalis
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
LIFE_STAGES = %i[larva spinning cocooned transforming emerging butterfly].freeze
|
|
9
|
+
CHRYSALIS_TYPES = %i[silk paper bark leaf underground].freeze
|
|
10
|
+
|
|
11
|
+
MAX_CHRYSALISES = 200
|
|
12
|
+
MAX_BUTTERFLIES = 500
|
|
13
|
+
TRANSFORMATION_RATE = 0.08
|
|
14
|
+
PROTECTION_DECAY = 0.03
|
|
15
|
+
EMERGENCE_THRESHOLD = 0.9
|
|
16
|
+
PREMATURE_PENALTY = 0.4
|
|
17
|
+
|
|
18
|
+
STAGE_LABELS = {
|
|
19
|
+
(0.0...0.20) => :larva,
|
|
20
|
+
(0.20...0.40) => :spinning,
|
|
21
|
+
(0.40...0.60) => :cocooned,
|
|
22
|
+
(0.60...0.80) => :transforming,
|
|
23
|
+
(0.80...0.90) => :emerging,
|
|
24
|
+
(0.90..1.0) => :butterfly
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
BEAUTY_LABELS = {
|
|
28
|
+
(0.0...0.20) => :dull,
|
|
29
|
+
(0.20...0.40) => :plain,
|
|
30
|
+
(0.40...0.65) => :striking,
|
|
31
|
+
(0.65...0.85) => :beautiful,
|
|
32
|
+
(0.85..1.0) => :magnificent
|
|
33
|
+
}.freeze
|
|
34
|
+
|
|
35
|
+
def self.label_for(table, value)
|
|
36
|
+
table.each do |range, label|
|
|
37
|
+
return label if range.cover?(value)
|
|
38
|
+
end
|
|
39
|
+
table.values.last
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|