lex-cognitive-lucidity 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1fec45d2331b7f2662ee40b89229acd4de755c0fa9b86cffce4349aa35fa60dd
4
+ data.tar.gz: f052e627356cab0d38372d2348ec26389769719ba3cfb017180956cf9fe74091
5
+ SHA512:
6
+ metadata.gz: '09313a8814401598f155aac12b0f4ddcc6d37eee479f06c6ae83c75f32111a15a40208c1484dc3c96e17be8e5700c23758630868b703d273aeae6cf1d6fa3459'
7
+ data.tar.gz: 5a344a1b0d96e9003e88a1d654bb101410b5a04326f4606de39e2a79c1d06b5312c8c35869b3e72df771b33eefe6f9958c9a588bc0f635b845c5d59577582147
@@ -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
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.gem
10
+ .rspec_status
11
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
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/CyclomaticComplexity:
34
+ Max: 15
35
+
36
+ Metrics/PerceivedComplexity:
37
+ Max: 17
38
+
39
+ Metrics/ParameterLists:
40
+ Max: 8
41
+ MaxOptionalParameters: 8
42
+
43
+ Style/Documentation:
44
+ Enabled: false
45
+
46
+ Style/OneClassPerFile:
47
+ Exclude:
48
+ - 'spec/spec_helper.rb'
49
+
50
+ Style/SymbolArray:
51
+ Enabled: true
52
+
53
+ Style/FrozenStringLiteralComment:
54
+ Enabled: true
55
+ EnforcedStyle: always
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,105 @@
1
+ # lex-cognitive-lucidity
2
+
3
+ **Level 3 Leaf Documentation**
4
+ - **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
5
+
6
+ ## Purpose
7
+
8
+ Lucid dreaming metaphor for meta-cognitive awareness. Models dream states with continuously tracked lucidity levels. Reality tests (text_stability, hand_check, time_check, memory_check, logic_check) either boost or reduce lucidity depending on their result. When lucidity is sufficient (>= 0.5), the dream can be steered (directed). False awakenings are detected probabilistically, and completed dreams are recorded in an immutable journal with full metadata.
9
+
10
+ ## Gem Info
11
+
12
+ - **Gem name**: `lex-cognitive-lucidity`
13
+ - **Module**: `Legion::Extensions::CognitiveLucidity`
14
+ - **Version**: `0.1.0`
15
+ - **Ruby**: `>= 3.4`
16
+ - **License**: MIT
17
+
18
+ ## File Structure
19
+
20
+ ```
21
+ lib/legion/extensions/cognitive_lucidity/
22
+ version.rb
23
+ client.rb
24
+ helpers/
25
+ constants.rb
26
+ dream_state.rb
27
+ journal_entry.rb
28
+ lucidity_engine.rb
29
+ runners/
30
+ cognitive_lucidity.rb
31
+ ```
32
+
33
+ ## Key Constants
34
+
35
+ | Constant | Value | Purpose |
36
+ |---|---|---|
37
+ | `MAX_JOURNAL_ENTRIES` | `500` | Journal ring buffer capacity |
38
+ | `MAX_DREAMS` | `100` | Maximum simultaneous active dreams |
39
+ | `LUCIDITY_LEVELS` | range hash | From `:somnambulant` to `:hyper_lucid` |
40
+ | `REALITY_TEST_TYPES` | `%i[text_stability hand_check time_check memory_check logic_check]` | Valid test types |
41
+ | `LUCIDITY_DECAY` | `0.05` | Lucidity lost per tick without stimulation |
42
+ | `FALSE_AWAKENING_CHANCE` | `0.1` | Base probability of false awakening per reality test |
43
+ | `DREAM_QUALITY_LABELS` | range hash | From `:incoherent` to `:vivid` |
44
+
45
+ ## Helpers
46
+
47
+ ### `Helpers::DreamState`
48
+ Active dream session. Has `id`, `lucidity`, `themes` (array), `insights` (array), `false_awakening_count`, and `steered` flag.
49
+
50
+ - `reality_test!(test_type)` — performs a reality check; returns test result hash including lucidity delta. May trigger false awakening (raises `false_awakening_count`).
51
+ - `steer!(direction)` — sets a narrative direction; requires lucidity >= 0.5, returns error hash otherwise
52
+ - `destabilize!` — applies `LUCIDITY_DECAY` to lucidity
53
+ - `stabilize!(amount)` — increases lucidity
54
+ - `end!` — marks dream inactive
55
+ - `lucidity_label`
56
+
57
+ ### `Helpers::JournalEntry`
58
+ Immutable (frozen) record of a completed dream. Captures: `lucidity_achieved`, `reality_tests_performed`, `themes`, `insights`, `false_awakening_count`, `duration_seconds`, `steered`.
59
+
60
+ - Frozen at creation: no mutation after recording
61
+ - `to_h` for serialization
62
+
63
+ ### `Helpers::LucidityEngine`
64
+ Manages active dreams and the journal.
65
+
66
+ - `begin_dream(themes:)` → new `DreamState`
67
+ - `reality_test(dream_id:, test_type:)` → test result hash
68
+ - `steer_dream(dream_id:, direction:)` → steer result hash
69
+ - `end_dream(dream_id:)` → creates `JournalEntry`, returns entry hash
70
+ - `all_dreams` → all active dream states
71
+ - `active_dream` → most recently begun active dream
72
+ - `lucidity_report` → aggregate stats
73
+ - `most_lucid_dreams(limit:)` → journal entries sorted by lucidity
74
+ - `theme_analysis` → hash of theme frequencies across all journal entries
75
+
76
+ ## Runners
77
+
78
+ Module: `Runners::CognitiveLucidity`
79
+
80
+ | Runner Method | Description |
81
+ |---|---|
82
+ | `begin_dream(themes:)` | Start a new dream state |
83
+ | `reality_test(dream_id:, test_type:)` | Perform a reality check |
84
+ | `steer_dream(dream_id:, direction:)` | Steer the dream narrative |
85
+ | `end_dream(dream_id:)` | Complete and journal the dream |
86
+ | `lucidity_status` | Aggregate lucidity report |
87
+ | `journal_entries(limit:)` | Recent journal entries |
88
+
89
+ All runners return `{success: true/false, ...}` hashes.
90
+
91
+ ## Integration Points
92
+
93
+ - Directly parallels `lex-dream`'s dream cycle: lucidity can be attached to lex-dream association walks
94
+ - `reality_test` fits `lex-tick` `identity_entropy_check` phase (grounding checks)
95
+ - High lucidity states can boost `lex-emotion` arousal positively
96
+ - False awakening count over a threshold can trigger `lex-conflict` internal conflict
97
+ - Journal themes feed into `lex-memory` semantic trace creation
98
+
99
+ ## Development Notes
100
+
101
+ - `Client` instantiates `@lucidity_engine = Helpers::LucidityEngine.new`
102
+ - `JournalEntry` is frozen: records are write-once for integrity
103
+ - `reality_test!` applies a lucidity delta depending on test type and result; passing tests increase lucidity, failing tests decrease it
104
+ - False awakening uses `rand < FALSE_AWAKENING_CHANCE` check per test; it resets some state but does not end the dream
105
+ - `steer!` fails silently with `{success: false, error: :insufficient_lucidity}` when lucidity < 0.5
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,49 @@
1
+ # lex-cognitive-lucidity
2
+
3
+ Lucid dreaming metaphor for meta-cognitive awareness in LegionIO cognitive agents. Dream states have continuously tracked lucidity levels; reality tests stabilize or destabilize lucidity; sufficiently lucid states can be steered. Completed dreams are journaled as immutable records.
4
+
5
+ ## What It Does
6
+
7
+ - Begin dream states with thematic content
8
+ - Five reality test types: `text_stability`, `hand_check`, `time_check`, `memory_check`, `logic_check`
9
+ - Passing tests boost lucidity; failing tests reduce it
10
+ - False awakening: 10% chance per reality test to trigger a false-awakening event
11
+ - Steer the dream narrative when lucidity >= 0.5
12
+ - End dreams and record them in a journal with full metadata (lucidity achieved, test count, themes, insights, false awakenings, duration)
13
+ - Journal analysis: most-lucid entries and theme frequency analysis
14
+
15
+ ## Usage
16
+
17
+ ```ruby
18
+ # Begin a dream
19
+ result = runner.begin_dream(themes: [:problem_solving, :creativity])
20
+ dream_id = result[:dream][:id]
21
+
22
+ # Run reality tests to stabilize lucidity
23
+ runner.reality_test(dream_id: dream_id, test_type: :logic_check)
24
+ # => { success: true, test_type: :logic_check, passed: true, lucidity_delta: 0.1, lucidity: 0.6, false_awakening: false }
25
+
26
+ # Steer once lucid enough
27
+ runner.steer_dream(dream_id: dream_id, direction: 'explore the architectural pattern more deeply')
28
+
29
+ # End and journal
30
+ runner.end_dream(dream_id: dream_id)
31
+ # => { success: true, journal_entry: { lucidity_achieved: 0.6, steered: true, ... } }
32
+
33
+ # Analyze journal
34
+ runner.journal_entries(limit: 10)
35
+ runner.lucidity_status
36
+ # => { success: true, active_dreams: 0, journal_size: 1, ... }
37
+ ```
38
+
39
+ ## Development
40
+
41
+ ```bash
42
+ bundle install
43
+ bundle exec rspec
44
+ bundle exec rubocop
45
+ ```
46
+
47
+ ## License
48
+
49
+ MIT
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/legion/extensions/cognitive_lucidity/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lex-cognitive-lucidity'
7
+ spec.version = Legion::Extensions::CognitiveLucidity::VERSION
8
+ spec.authors = ['Esity']
9
+ spec.email = ['matthewdiverson@gmail.com']
10
+
11
+ spec.summary = 'LEX Cognitive Lucidity'
12
+ spec.description = 'Lucid dreaming for AI — self-aware dream processing with lucidity levels, ' \
13
+ 'reality testing, dream steering, and false awakening detection'
14
+ spec.homepage = 'https://github.com/LegionIO/lex-cognitive-lucidity'
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-lucidity'
20
+ spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-lucidity'
21
+ spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-lucidity'
22
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-lucidity/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,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLucidity
6
+ class Client
7
+ include Runners::CognitiveLucidity
8
+
9
+ attr_reader :engine
10
+
11
+ def initialize(engine: nil, **)
12
+ @default_engine = engine || Helpers::LucidityEngine.new
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :default_engine
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLucidity
6
+ module Helpers
7
+ module Constants
8
+ MAX_JOURNAL_ENTRIES = 500
9
+ MAX_DREAMS = 100
10
+
11
+ LUCIDITY_LEVELS = %i[non_lucid pre_lucid semi_lucid lucid fully_lucid].freeze
12
+
13
+ REALITY_TEST_TYPES = %i[
14
+ text_stability
15
+ hand_check
16
+ time_check
17
+ memory_check
18
+ logic_check
19
+ ].freeze
20
+
21
+ LUCIDITY_DECAY = 0.05
22
+ FALSE_AWAKENING_CHANCE = 0.1
23
+
24
+ DREAM_QUALITY_LABELS = {
25
+ 0.0..0.2 => :poor,
26
+ 0.2..0.4 => :fragmented,
27
+ 0.4..0.6 => :ordinary,
28
+ 0.6..0.8 => :vivid,
29
+ 0.8..1.0 => :hyper_vivid
30
+ }.freeze
31
+
32
+ module_function
33
+
34
+ def label_for(value)
35
+ DREAM_QUALITY_LABELS.each do |range, label|
36
+ return label if range.cover?(value.clamp(0.0, 1.0))
37
+ end
38
+ :ordinary
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveLucidity
8
+ module Helpers
9
+ class DreamState
10
+ attr_reader :id, :lucidity_level, :awareness, :content, :theme, :vividness, :stability, :emotional_tone, :started_at, :reality_tests_performed,
11
+ :false_awakening_count, :steered, :ended_at
12
+
13
+ def initialize(theme:, content:, vividness: 0.5, stability: 0.7,
14
+ emotional_tone: :neutral, lucidity_level: 0.0, **)
15
+ @id = SecureRandom.uuid
16
+ @theme = theme
17
+ @content = content
18
+ @vividness = vividness.clamp(0.0, 1.0)
19
+ @stability = stability.clamp(0.0, 1.0)
20
+ @emotional_tone = emotional_tone
21
+ @lucidity_level = lucidity_level.clamp(0.0, 1.0)
22
+ @awareness = @lucidity_level > 0.0
23
+ @started_at = Time.now.utc
24
+ @reality_tests_performed = []
25
+ @false_awakening_count = 0
26
+ @steered = false
27
+ @active = true
28
+ end
29
+
30
+ def active?
31
+ @active
32
+ end
33
+
34
+ def lucidity_label
35
+ thresholds = [
36
+ [0.0, :non_lucid],
37
+ [0.2, :pre_lucid],
38
+ [0.5, :semi_lucid],
39
+ [0.75, :lucid],
40
+ [0.9, :fully_lucid]
41
+ ]
42
+ label = :non_lucid
43
+ thresholds.each do |threshold, lbl|
44
+ label = lbl if @lucidity_level >= threshold
45
+ end
46
+ label
47
+ end
48
+
49
+ def reality_test!(test_type)
50
+ raise ArgumentError, "unknown test type: #{test_type}" unless Constants::REALITY_TEST_TYPES.include?(test_type)
51
+
52
+ result = perform_reality_test(test_type)
53
+ @reality_tests_performed << {
54
+ test_type: test_type,
55
+ result: result[:outcome],
56
+ lucidity_delta: result[:lucidity_delta],
57
+ tested_at: Time.now.utc
58
+ }
59
+
60
+ if result[:false_awakening]
61
+ @false_awakening_count += 1
62
+ return { outcome: :false_awakening, lucidity_delta: 0.0, false_awakening: true }
63
+ end
64
+
65
+ @lucidity_level = (@lucidity_level + result[:lucidity_delta]).clamp(0.0, 1.0)
66
+ @awareness = @lucidity_level > 0.0
67
+
68
+ { outcome: result[:outcome], lucidity_delta: result[:lucidity_delta], false_awakening: false }
69
+ end
70
+
71
+ def steer!(direction)
72
+ return { success: false, reason: :insufficient_lucidity } if @lucidity_level < 0.5
73
+
74
+ @content = "#{@content} [steered: #{direction}]"
75
+ @steered = true
76
+ @stability = (@stability - 0.1).clamp(0.0, 1.0)
77
+
78
+ { success: true, direction: direction, new_stability: @stability }
79
+ end
80
+
81
+ def destabilize!(amount)
82
+ @stability = (@stability - amount.clamp(0.0, 1.0)).clamp(0.0, 1.0)
83
+ @lucidity_level = (@lucidity_level - Constants::LUCIDITY_DECAY).clamp(0.0, 1.0)
84
+ @awareness = @lucidity_level > 0.0
85
+ { stability: @stability, lucidity_level: @lucidity_level }
86
+ end
87
+
88
+ def stabilize!(amount)
89
+ @stability = (@stability + amount.clamp(0.0, 1.0)).clamp(0.0, 1.0)
90
+ { stability: @stability, lucidity_level: @lucidity_level }
91
+ end
92
+
93
+ def end!
94
+ @active = false
95
+ @ended_at = Time.now.utc
96
+ end
97
+
98
+ def duration_seconds
99
+ end_time = @ended_at || Time.now.utc
100
+ (end_time - @started_at).round(10)
101
+ end
102
+
103
+ private
104
+
105
+ def perform_reality_test(test_type)
106
+ false_awakening = rand < Constants::FALSE_AWAKENING_CHANCE
107
+
108
+ return { outcome: :failed, lucidity_delta: 0.0, false_awakening: true } if false_awakening
109
+
110
+ base_gain = test_base_gain(test_type)
111
+ stability_modifier = @stability < 0.3 ? 0.5 : 1.0
112
+ lucidity_delta = (base_gain * stability_modifier).round(10)
113
+
114
+ { outcome: :passed, lucidity_delta: lucidity_delta, false_awakening: false }
115
+ end
116
+
117
+ def test_base_gain(test_type)
118
+ gains = {
119
+ text_stability: 0.15,
120
+ hand_check: 0.20,
121
+ time_check: 0.10,
122
+ memory_check: 0.12,
123
+ logic_check: 0.18
124
+ }
125
+ gains.fetch(test_type, 0.10)
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module CognitiveLucidity
8
+ module Helpers
9
+ class JournalEntry
10
+ attr_reader :id, :dream_state_id, :content_summary, :lucidity_achieved,
11
+ :reality_tests_performed, :themes, :insights, :recorded_at,
12
+ :false_awakening_count, :duration_seconds, :steered
13
+
14
+ def initialize(dream_state:, insights: [], **)
15
+ @id = SecureRandom.uuid
16
+ @dream_state_id = dream_state.id
17
+ @content_summary = dream_state.content.to_s
18
+ @lucidity_achieved = dream_state.lucidity_level.round(10)
19
+ @reality_tests_performed = dream_state.reality_tests_performed.dup.freeze
20
+ @themes = Array(dream_state.theme).freeze
21
+ @insights = Array(insights).freeze
22
+ @recorded_at = Time.now.utc
23
+ @false_awakening_count = dream_state.false_awakening_count
24
+ @duration_seconds = dream_state.duration_seconds
25
+ @steered = dream_state.steered
26
+ freeze
27
+ end
28
+
29
+ def lucidity_label
30
+ thresholds = [
31
+ [0.0, :non_lucid],
32
+ [0.2, :pre_lucid],
33
+ [0.5, :semi_lucid],
34
+ [0.75, :lucid],
35
+ [0.9, :fully_lucid]
36
+ ]
37
+ label = :non_lucid
38
+ thresholds.each do |threshold, lbl|
39
+ label = lbl if @lucidity_achieved >= threshold
40
+ end
41
+ label
42
+ end
43
+
44
+ def to_h
45
+ {
46
+ id: @id,
47
+ dream_state_id: @dream_state_id,
48
+ content_summary: @content_summary,
49
+ lucidity_achieved: @lucidity_achieved,
50
+ lucidity_label: lucidity_label,
51
+ reality_tests_performed: @reality_tests_performed,
52
+ themes: @themes,
53
+ insights: @insights,
54
+ false_awakening_count: @false_awakening_count,
55
+ duration_seconds: @duration_seconds,
56
+ steered: @steered,
57
+ recorded_at: @recorded_at
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLucidity
6
+ module Helpers
7
+ class LucidityEngine
8
+ attr_reader :journal
9
+
10
+ def initialize
11
+ @dreams = {}
12
+ @journal = []
13
+ end
14
+
15
+ def begin_dream(theme:, content:, vividness: 0.5, stability: 0.7,
16
+ emotional_tone: :neutral, lucidity_level: 0.0, **)
17
+ evict_oldest_dream! if @dreams.size >= Constants::MAX_DREAMS
18
+
19
+ state = DreamState.new(
20
+ theme: theme,
21
+ content: content,
22
+ vividness: vividness,
23
+ stability: stability,
24
+ emotional_tone: emotional_tone,
25
+ lucidity_level: lucidity_level
26
+ )
27
+ @dreams[state.id] = state
28
+ {
29
+ dream_id: state.id,
30
+ theme: state.theme,
31
+ lucidity_level: state.lucidity_level,
32
+ stability: state.stability
33
+ }
34
+ end
35
+
36
+ def reality_test(dream_id:, test_type:, **)
37
+ state = @dreams[dream_id]
38
+ return { success: false, error: 'dream not found' } unless state
39
+ return { success: false, error: 'dream is not active' } unless state.active?
40
+
41
+ result = state.reality_test!(test_type.to_sym)
42
+ {
43
+ success: true,
44
+ dream_id: dream_id,
45
+ outcome: result[:outcome],
46
+ lucidity_delta: result[:lucidity_delta],
47
+ lucidity_level: state.lucidity_level,
48
+ false_awakening: result[:false_awakening]
49
+ }
50
+ rescue ArgumentError => e
51
+ { success: false, error: e.message }
52
+ end
53
+
54
+ def steer_dream(dream_id:, direction:, **)
55
+ state = @dreams[dream_id]
56
+ return { success: false, error: 'dream not found' } unless state
57
+ return { success: false, error: 'dream is not active' } unless state.active?
58
+
59
+ result = state.steer!(direction)
60
+ result.merge(dream_id: dream_id)
61
+ end
62
+
63
+ def end_dream(dream_id:, insights: [], **)
64
+ state = @dreams[dream_id]
65
+ return { success: false, error: 'dream not found' } unless state
66
+ return { success: false, error: 'dream is not active' } unless state.active?
67
+
68
+ state.end!
69
+ entry = JournalEntry.new(dream_state: state, insights: insights)
70
+ add_journal_entry(entry)
71
+
72
+ {
73
+ success: true,
74
+ dream_id: dream_id,
75
+ journal_entry_id: entry.id,
76
+ lucidity_achieved: entry.lucidity_achieved,
77
+ duration_seconds: entry.duration_seconds
78
+ }
79
+ end
80
+
81
+ def all_dreams
82
+ @dreams.values
83
+ end
84
+
85
+ def active_dream
86
+ @dreams.values.find(&:active?)
87
+ end
88
+
89
+ def lucidity_report
90
+ return base_report if @journal.empty?
91
+
92
+ {
93
+ total_dreams: @journal.size,
94
+ avg_lucidity: compute_avg_lucidity,
95
+ false_awakening_count: @journal.sum(&:false_awakening_count),
96
+ steered_count: @journal.count(&:steered),
97
+ test_success_rates: compute_test_success_rates
98
+ }
99
+ end
100
+
101
+ def most_lucid_dreams(limit: 5, **)
102
+ sorted = @journal.sort_by { |e| -e.lucidity_achieved }
103
+ sorted.first(limit).map(&:to_h)
104
+ end
105
+
106
+ def theme_analysis
107
+ theme_map, lucidity_by_theme = build_theme_maps
108
+ results = theme_map.map do |theme, count|
109
+ avg = compute_theme_avg(lucidity_by_theme[theme])
110
+ { theme: theme, occurrences: count, avg_lucidity: avg }
111
+ end
112
+ results.sort_by { |t| -t[:occurrences] }
113
+ end
114
+
115
+ private
116
+
117
+ def compute_avg_lucidity
118
+ (@journal.sum(&:lucidity_achieved) / @journal.size.to_f).round(10)
119
+ end
120
+
121
+ def compute_test_success_rates
122
+ test_totals = Hash.new(0)
123
+ test_passes = Hash.new(0)
124
+ @journal.each do |entry|
125
+ entry.reality_tests_performed.each do |rt|
126
+ test_totals[rt[:test_type]] += 1
127
+ test_passes[rt[:test_type]] += 1 if rt[:result] == :passed
128
+ end
129
+ end
130
+ test_totals.to_h do |test_type, count|
131
+ rate = count.positive? ? (test_passes[test_type].to_f / count).round(10) : 0.0
132
+ [test_type, rate]
133
+ end
134
+ end
135
+
136
+ def build_theme_maps
137
+ theme_map = Hash.new(0)
138
+ lucidity_by_theme = Hash.new { |h, k| h[k] = [] }
139
+ @journal.each do |entry|
140
+ Array(entry.themes).each do |theme|
141
+ theme_map[theme] += 1
142
+ lucidity_by_theme[theme] << entry.lucidity_achieved
143
+ end
144
+ end
145
+ [theme_map, lucidity_by_theme]
146
+ end
147
+
148
+ def compute_theme_avg(values)
149
+ return 0.0 if values.empty?
150
+
151
+ (values.sum / values.size.to_f).round(10)
152
+ end
153
+
154
+ def add_journal_entry(entry)
155
+ @journal.shift while @journal.size >= Constants::MAX_JOURNAL_ENTRIES
156
+ @journal << entry
157
+ end
158
+
159
+ def evict_oldest_dream!
160
+ oldest_id = @dreams.min_by { |_id, state| state.started_at }&.first
161
+ @dreams.delete(oldest_id) if oldest_id
162
+ end
163
+
164
+ def base_report
165
+ {
166
+ total_dreams: 0,
167
+ avg_lucidity: 0.0,
168
+ false_awakening_count: 0,
169
+ steered_count: 0,
170
+ test_success_rates: {}
171
+ }
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLucidity
6
+ module Runners
7
+ module CognitiveLucidity
8
+ extend self
9
+
10
+ def begin_dream(theme:, content:, engine: nil, **)
11
+ eng = engine || default_engine
12
+ result = eng.begin_dream(theme: theme, content: content, **)
13
+ Legion::Logging.debug "[cognitive_lucidity] begin_dream theme=#{theme} id=#{result[:dream_id]}"
14
+ result.merge(success: true)
15
+ rescue ArgumentError => e
16
+ { success: false, error: e.message }
17
+ end
18
+
19
+ def reality_test(dream_id:, test_type:, engine: nil, **)
20
+ eng = engine || default_engine
21
+ result = eng.reality_test(dream_id: dream_id, test_type: test_type)
22
+ Legion::Logging.debug "[cognitive_lucidity] reality_test dream_id=#{dream_id} " \
23
+ "test=#{test_type} outcome=#{result[:outcome]}"
24
+ result
25
+ rescue ArgumentError => e
26
+ { success: false, error: e.message }
27
+ end
28
+
29
+ def steer_dream(dream_id:, direction:, engine: nil, **)
30
+ eng = engine || default_engine
31
+ result = eng.steer_dream(dream_id: dream_id, direction: direction)
32
+ Legion::Logging.debug "[cognitive_lucidity] steer_dream dream_id=#{dream_id} " \
33
+ "direction=#{direction} success=#{result[:success]}"
34
+ result
35
+ rescue ArgumentError => e
36
+ { success: false, error: e.message }
37
+ end
38
+
39
+ def end_dream(dream_id:, insights: [], engine: nil, **)
40
+ eng = engine || default_engine
41
+ result = eng.end_dream(dream_id: dream_id, insights: insights)
42
+ Legion::Logging.debug "[cognitive_lucidity] end_dream dream_id=#{dream_id} " \
43
+ "lucidity=#{result[:lucidity_achieved]}"
44
+ result
45
+ rescue ArgumentError => e
46
+ { success: false, error: e.message }
47
+ end
48
+
49
+ def lucidity_status(engine: nil, **)
50
+ eng = engine || default_engine
51
+ active = eng.active_dream
52
+ report = eng.lucidity_report
53
+ Legion::Logging.debug "[cognitive_lucidity] lucidity_status active=#{!active.nil?}"
54
+ {
55
+ success: true,
56
+ active_dream: if active
57
+ {
58
+ id: active.id,
59
+ theme: active.theme,
60
+ lucidity_level: active.lucidity_level,
61
+ stability: active.stability,
62
+ lucidity_label: active.lucidity_label
63
+ }
64
+ end,
65
+ report: report
66
+ }
67
+ rescue ArgumentError => e
68
+ { success: false, error: e.message }
69
+ end
70
+
71
+ def journal_entries(limit: 20, engine: nil, **)
72
+ eng = engine || default_engine
73
+ entries = eng.journal.last(limit).map(&:to_h)
74
+ Legion::Logging.debug "[cognitive_lucidity] journal_entries count=#{entries.size}"
75
+ { success: true, count: entries.size, entries: entries }
76
+ rescue ArgumentError => e
77
+ { success: false, error: e.message }
78
+ end
79
+
80
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
81
+
82
+ private
83
+
84
+ def default_engine
85
+ @default_engine ||= Helpers::LucidityEngine.new
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLucidity
6
+ VERSION = '0.1.0'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ require 'legion/extensions/cognitive_lucidity/version'
6
+ require 'legion/extensions/cognitive_lucidity/helpers/constants'
7
+ require 'legion/extensions/cognitive_lucidity/helpers/dream_state'
8
+ require 'legion/extensions/cognitive_lucidity/helpers/journal_entry'
9
+ require 'legion/extensions/cognitive_lucidity/helpers/lucidity_engine'
10
+ require 'legion/extensions/cognitive_lucidity/runners/cognitive_lucidity'
11
+ require 'legion/extensions/cognitive_lucidity/client'
12
+
13
+ module Legion
14
+ module Extensions
15
+ module CognitiveLucidity
16
+ extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lex-cognitive-lucidity
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: Lucid dreaming for AI — self-aware dream processing with lucidity levels,
27
+ reality testing, dream steering, and false awakening detection
28
+ email:
29
+ - matthewdiverson@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".github/workflows/ci.yml"
35
+ - ".gitignore"
36
+ - ".rspec"
37
+ - ".rubocop.yml"
38
+ - CLAUDE.md
39
+ - Gemfile
40
+ - README.md
41
+ - lex-cognitive-lucidity.gemspec
42
+ - lib/legion/extensions/cognitive_lucidity.rb
43
+ - lib/legion/extensions/cognitive_lucidity/client.rb
44
+ - lib/legion/extensions/cognitive_lucidity/helpers/constants.rb
45
+ - lib/legion/extensions/cognitive_lucidity/helpers/dream_state.rb
46
+ - lib/legion/extensions/cognitive_lucidity/helpers/journal_entry.rb
47
+ - lib/legion/extensions/cognitive_lucidity/helpers/lucidity_engine.rb
48
+ - lib/legion/extensions/cognitive_lucidity/runners/cognitive_lucidity.rb
49
+ - lib/legion/extensions/cognitive_lucidity/version.rb
50
+ homepage: https://github.com/LegionIO/lex-cognitive-lucidity
51
+ licenses:
52
+ - MIT
53
+ metadata:
54
+ homepage_uri: https://github.com/LegionIO/lex-cognitive-lucidity
55
+ source_code_uri: https://github.com/LegionIO/lex-cognitive-lucidity
56
+ documentation_uri: https://github.com/LegionIO/lex-cognitive-lucidity
57
+ changelog_uri: https://github.com/LegionIO/lex-cognitive-lucidity
58
+ bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-lucidity/issues
59
+ rubygems_mfa_required: 'true'
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '3.4'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 3.6.9
75
+ specification_version: 4
76
+ summary: LEX Cognitive Lucidity
77
+ test_files: []