lex-cognitive-lighthouse 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: 7f54885694491e600f6aee8f9b1e3457bb8919ee8a8cc6161139038c7997abdb
4
+ data.tar.gz: f834c005573627c985321c9c27a31853bc124ebf7d354a3dce8a779671536c37
5
+ SHA512:
6
+ metadata.gz: 860f2ba190a71695e20be6d7583008a7978ccd564bedb4623e81011434b50d8eb20d1ac02367dd2f653ffcee740bb9d3d94a0c94daeab65529cedc1bade4b5aa
7
+ data.tar.gz: 3e7c288083585b04cb5e3f7ed7be3979d26e76b168c14cf8c79a93ab0e3e9eafe472ea8edeab3e755b5243eb4cb6d1ac62445e848b380f20033495e2adbae157
@@ -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,2 @@
1
+ .rspec_status
2
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require spec_helper
2
+ --format documentation
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,107 @@
1
+ # lex-cognitive-lighthouse
2
+
3
+ **Level 3 Leaf Documentation**
4
+ - **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
5
+
6
+ ## Purpose
7
+
8
+ Beacon and fog metaphor for navigational clarity in cognitive processing. Beacons represent sources of truth, clarity, warning, guidance, and hope — each with a luminosity level. Fog banks represent confusion, uncertainty, ambiguity, doubt, and overwhelm — each with a density level. The sweep operation actively disperses fog using beacon luminosity, modeling how clarity-producing cognition reduces confusion.
9
+
10
+ ## Gem Info
11
+
12
+ - **Gem name**: `lex-cognitive-lighthouse`
13
+ - **Module**: `Legion::Extensions::CognitiveLighthouse`
14
+ - **Version**: `0.1.0`
15
+ - **Ruby**: `>= 3.4`
16
+ - **License**: MIT
17
+
18
+ ## File Structure
19
+
20
+ ```
21
+ lib/legion/extensions/cognitive_lighthouse/
22
+ version.rb
23
+ client.rb
24
+ helpers/
25
+ constants.rb
26
+ beacon.rb
27
+ fog.rb
28
+ lighthouse_engine.rb
29
+ runners/
30
+ cognitive_lighthouse.rb
31
+ ```
32
+
33
+ ## Key Constants
34
+
35
+ | Constant | Value | Purpose |
36
+ |---|---|---|
37
+ | `BEACON_TYPES` | `%i[truth clarity warning guidance hope]` | Valid beacon categories |
38
+ | `FOG_TYPES` | `%i[confusion uncertainty ambiguity doubt overwhelm]` | Valid fog categories |
39
+ | `MAX_BEACONS` | `100` | Per-engine beacon capacity |
40
+ | `MAX_FOG_BANKS` | `50` | Per-engine fog capacity |
41
+ | `LUMINOSITY_RATE` | `0.1` | Default brightness change per brighten/dim operation |
42
+ | `FOG_DENSITY_RATE` | `0.05` | Default density change per thicken/disperse operation |
43
+ | `VISIBILITY_LABELS` | range hash | From `:blind` to `:crystal_clear` |
44
+ | `LUMINOSITY_LABELS` | range hash | From `:dark` to `:blazing` |
45
+
46
+ ## Helpers
47
+
48
+ ### `Helpers::Beacon`
49
+ Emits light to cut through cognitive fog. Has `id`, `beacon_type`, `luminosity`, `domain`, `content`, and `created_at`.
50
+
51
+ - `brighten!(rate)` — increases luminosity
52
+ - `dim!(rate)` — decreases luminosity
53
+ - `extinguished?` — luminosity at or below zero
54
+ - `blazing?` — luminosity at maximum
55
+ - `luminosity_label`
56
+ - `to_h`
57
+
58
+ ### `Helpers::Fog`
59
+ Represents a cloud of cognitive obscuration. Has `id`, `fog_type`, `density`, `domain`, `content`, and `created_at`.
60
+
61
+ - `thicken!(rate)` — increases density
62
+ - `disperse!(rate)` — decreases density
63
+ - `impenetrable?` — density at maximum
64
+ - `clearing?` — density below a low threshold
65
+ - `visibility_label` — based on inverse of density
66
+ - `to_h`
67
+
68
+ ### `Helpers::LighthouseEngine`
69
+ Manages beacons and fog banks, enforces capacity limits.
70
+
71
+ - `light_beacon(beacon_type:, luminosity:, domain:, content:)` → beacon or capacity error
72
+ - `create_fog(fog_type:, density:, domain:, content:)` → fog or capacity error
73
+ - `sweep` — for each beacon, disperses fog banks in the same domain; dispersion amount = `beacon.luminosity * 0.5`; extinguished beacons are pruned
74
+ - `dim_all!(rate:)` — dims all beacons, prunes extinguished ones
75
+ - `thicken_all!(rate:)` — thickens all fog banks
76
+ - `brightest_beacons(limit:)` → top N by luminosity
77
+ - `densest_fogs(limit:)` → top N by density
78
+ - `visibility_report` → aggregate stats hash
79
+
80
+ ## Runners
81
+
82
+ Module: `Runners::CognitiveLighthouse`
83
+
84
+ | Runner Method | Description |
85
+ |---|---|
86
+ | `light_beacon(beacon_type:, luminosity:, domain:, content:)` | Create a new beacon |
87
+ | `create_fog(fog_type:, density:, domain:, content:)` | Create a new fog bank |
88
+ | `sweep` | Beacons disperse fog in matching domains |
89
+ | `list_beacons(limit:)` | Brightest beacons |
90
+ | `navigation_status` | Full visibility report |
91
+
92
+ All runners return `{success: true/false, ...}` hashes.
93
+
94
+ ## Integration Points
95
+
96
+ - No direct dependencies on other agentic LEX gems
97
+ - Can integrate with `lex-tick` phase handlers: low overall visibility → switch to sentinel mode
98
+ - Beacon luminosity can be boosted when `lex-emotion` valence is positive
99
+ - Fog density can be increased on `lex-conflict` escalation events
100
+ - `sweep` is the natural action for the agent's clarification-seeking behavior
101
+
102
+ ## Development Notes
103
+
104
+ - `Client` instantiates `@lighthouse_engine = Helpers::LighthouseEngine.new`
105
+ - `sweep` prunes beacons that become extinguished after dispersion calculations
106
+ - Beacon and fog domains are matched for targeted dispersion — a `:truth` beacon only disperses fog in its own domain
107
+ - `MAX_BEACONS = 100` and `MAX_FOG_BANKS = 50` are hard engine-level caps
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem 'rspec', '~> 3.13'
9
+ gem 'rubocop', '~> 1.75'
10
+ gem 'rubocop-rspec'
11
+ end
12
+
13
+ gem 'legion-gaia', path: '../../legion-gaia'
data/Gemfile.lock ADDED
@@ -0,0 +1,78 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lex-cognitive-lighthouse (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-lighthouse!
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,47 @@
1
+ # lex-cognitive-lighthouse
2
+
3
+ Beacon and fog navigation model for LegionIO cognitive agents. Beacons (truth, clarity, warning, guidance, hope) actively disperse fog banks (confusion, uncertainty, ambiguity, doubt, overwhelm) through sweep operations.
4
+
5
+ ## What It Does
6
+
7
+ - Light beacons with luminosity levels to represent sources of cognitive clarity
8
+ - Create fog banks with density levels to represent sources of cognitive obscuration
9
+ - Run `sweep` to have beacons disperse fog in their matching domains
10
+ - Track overall visibility across all fog banks
11
+ - Monitor brightest beacons and densest fog clusters
12
+ - Beacons that dim to zero are pruned automatically during sweep
13
+
14
+ ## Usage
15
+
16
+ ```ruby
17
+ # Light a beacon
18
+ runner.light_beacon(beacon_type: :clarity, luminosity: 0.8,
19
+ domain: :reasoning, content: 'Root cause identified')
20
+
21
+ # Create a fog bank
22
+ runner.create_fog(fog_type: :uncertainty, density: 0.6,
23
+ domain: :reasoning, content: 'Multiple conflicting hypotheses')
24
+
25
+ # Sweep: beacons disperse fog in their domain
26
+ runner.sweep
27
+ # => { success: true, swept: 1, beacons_dimmed: 0, beacons_pruned: 0 }
28
+
29
+ # Check navigation status
30
+ runner.navigation_status
31
+ # => { success: true, total_beacons: 1, total_fog_banks: 1, avg_luminosity: 0.8, avg_density: ..., ... }
32
+
33
+ # List brightest beacons
34
+ runner.list_beacons(limit: 5)
35
+ ```
36
+
37
+ ## Development
38
+
39
+ ```bash
40
+ bundle install
41
+ bundle exec rspec
42
+ bundle exec rubocop
43
+ ```
44
+
45
+ ## License
46
+
47
+ MIT
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/legion/extensions/cognitive_lighthouse/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lex-cognitive-lighthouse'
7
+ spec.version = Legion::Extensions::CognitiveLighthouse::VERSION
8
+ spec.authors = ['Esity']
9
+ spec.email = ['matthewdiverson@gmail.com']
10
+ spec.license = 'MIT'
11
+
12
+ spec.summary = 'Cognitive lighthouse LEX — guiding beacons that cut through cognitive fog'
13
+ spec.description = 'Models guiding beacons that periodically sweep their beam to illuminate areas ' \
14
+ 'of uncertainty, helping navigate complex decision spaces. Beacons can be steady ' \
15
+ 'or rotating, can dim in fog, and can guide other agents through ambiguity.'
16
+ spec.homepage = 'https://github.com/LegionIO/lex-cognitive-lighthouse'
17
+
18
+ spec.required_ruby_version = '>= 3.4'
19
+
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] = spec.homepage
22
+ spec.metadata['documentation_uri'] = "#{spec.homepage}#readme"
23
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
24
+ spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
25
+ spec.metadata['rubygems_mfa_required'] = 'true'
26
+
27
+ spec.files = Dir.chdir(__dir__) do
28
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(test|spec|features)/}) }
29
+ end
30
+
31
+ spec.require_paths = ['lib']
32
+ spec.add_development_dependency 'legion-gaia'
33
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLighthouse
6
+ class Client
7
+ include Runners::CognitiveLighthouse
8
+
9
+ def initialize(engine: nil, **)
10
+ @engine = engine || Helpers::LighthouseEngine.new
11
+ end
12
+
13
+ private
14
+
15
+ def default_engine
16
+ @engine
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLighthouse
6
+ module Helpers
7
+ class Beacon
8
+ attr_reader :id, :beacon_type, :domain, :content, :sweep_angle, :lit_at
9
+ attr_accessor :luminosity
10
+
11
+ def initialize(beacon_type:, domain:, content:, luminosity: nil, sweep_angle: nil)
12
+ validate_beacon_type!(beacon_type)
13
+ @id = SecureRandom.uuid
14
+ @beacon_type = beacon_type.to_sym
15
+ @domain = domain.to_s
16
+ @content = content.to_s
17
+ @luminosity = (luminosity || 0.7).to_f.clamp(0.0, 1.0).round(10)
18
+ @sweep_angle = (sweep_angle || 0.0).to_f.clamp(0.0, 360.0).round(10)
19
+ @lit_at = Time.now.utc
20
+ end
21
+
22
+ def brighten!(rate: Constants::LUMINOSITY_RATE)
23
+ @luminosity = (@luminosity + rate).clamp(0.0, 1.0).round(10)
24
+ self
25
+ end
26
+
27
+ def dim!(rate: Constants::LUMINOSITY_RATE)
28
+ @luminosity = (@luminosity - rate).clamp(0.0, 1.0).round(10)
29
+ self
30
+ end
31
+
32
+ def extinguished?
33
+ @luminosity <= 0.0
34
+ end
35
+
36
+ def blazing?
37
+ @luminosity >= 0.9
38
+ end
39
+
40
+ def luminosity_label
41
+ Constants.label_for(Constants::LUMINOSITY_LABELS, @luminosity)
42
+ end
43
+
44
+ def to_h
45
+ {
46
+ id: @id,
47
+ beacon_type: @beacon_type,
48
+ domain: @domain,
49
+ content: @content,
50
+ luminosity: @luminosity,
51
+ sweep_angle: @sweep_angle,
52
+ luminosity_label: luminosity_label,
53
+ extinguished: extinguished?,
54
+ blazing: blazing?,
55
+ lit_at: @lit_at
56
+ }
57
+ end
58
+
59
+ private
60
+
61
+ def validate_beacon_type!(type)
62
+ sym = type.to_sym
63
+ return if Constants::BEACON_TYPES.include?(sym)
64
+
65
+ raise ArgumentError,
66
+ "unknown beacon_type: #{type.inspect}; must be one of #{Constants::BEACON_TYPES.inspect}"
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLighthouse
6
+ module Helpers
7
+ module Constants
8
+ BEACON_TYPES = %i[truth clarity warning guidance hope].freeze
9
+ FOG_TYPES = %i[confusion uncertainty ambiguity doubt overwhelm].freeze
10
+
11
+ MAX_BEACONS = 100
12
+ MAX_FOG_BANKS = 50
13
+
14
+ LUMINOSITY_RATE = 0.1
15
+ FOG_DENSITY_RATE = 0.05
16
+
17
+ # Visibility labels (fog density: high density = low visibility)
18
+ VISIBILITY_LABELS = [
19
+ [(0.0...0.1), :crystal_clear],
20
+ [(0.1...0.3), :clear],
21
+ [(0.3...0.5), :hazy],
22
+ [(0.5...0.7), :foggy],
23
+ [(0.7...0.9), :dense_fog],
24
+ [(0.9..), :blind]
25
+ ].freeze
26
+
27
+ # Luminosity labels (beacon luminosity: high = bright)
28
+ LUMINOSITY_LABELS = [
29
+ [(0.9..), :blazing],
30
+ [(0.7...0.9), :bright],
31
+ [(0.5...0.7), :steady],
32
+ [(0.3...0.5), :dim],
33
+ [(0.1...0.3), :faint],
34
+ [(..0.1), :dark]
35
+ ].freeze
36
+
37
+ def self.label_for(table, value)
38
+ table.each { |range, label| return label if range.cover?(value) }
39
+ table.last.last
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLighthouse
6
+ module Helpers
7
+ class Fog
8
+ attr_reader :id, :fog_type, :domain, :extent, :formed_at
9
+ attr_accessor :density
10
+
11
+ def initialize(fog_type:, domain:, density: nil, extent: nil)
12
+ validate_fog_type!(fog_type)
13
+ @id = SecureRandom.uuid
14
+ @fog_type = fog_type.to_sym
15
+ @domain = domain.to_s
16
+ @density = (density || 0.5).to_f.clamp(0.0, 1.0).round(10)
17
+ @extent = (extent || 1.0).to_f.clamp(0.0, 1.0).round(10)
18
+ @formed_at = Time.now.utc
19
+ end
20
+
21
+ def thicken!(rate: Constants::FOG_DENSITY_RATE)
22
+ @density = (@density + rate).clamp(0.0, 1.0).round(10)
23
+ self
24
+ end
25
+
26
+ def disperse!(rate: Constants::FOG_DENSITY_RATE)
27
+ @density = (@density - rate).clamp(0.0, 1.0).round(10)
28
+ self
29
+ end
30
+
31
+ def impenetrable?
32
+ @density >= 1.0
33
+ end
34
+
35
+ def clearing?
36
+ @density < 0.2
37
+ end
38
+
39
+ def visibility_label
40
+ Constants.label_for(Constants::VISIBILITY_LABELS, @density)
41
+ end
42
+
43
+ def to_h
44
+ {
45
+ id: @id,
46
+ fog_type: @fog_type,
47
+ domain: @domain,
48
+ density: @density,
49
+ extent: @extent,
50
+ visibility_label: visibility_label,
51
+ impenetrable: impenetrable?,
52
+ clearing: clearing?,
53
+ formed_at: @formed_at
54
+ }
55
+ end
56
+
57
+ private
58
+
59
+ def validate_fog_type!(type)
60
+ sym = type.to_sym
61
+ return if Constants::FOG_TYPES.include?(sym)
62
+
63
+ raise ArgumentError,
64
+ "unknown fog_type: #{type.inspect}; must be one of #{Constants::FOG_TYPES.inspect}"
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLighthouse
6
+ module Helpers
7
+ class LighthouseEngine
8
+ def initialize
9
+ @beacons = {}
10
+ @fog_banks = {}
11
+ end
12
+
13
+ def light_beacon(beacon_type:, domain:, content:, luminosity: nil, sweep_angle: nil)
14
+ raise ArgumentError, 'too many beacons' if @beacons.size >= Constants::MAX_BEACONS
15
+
16
+ beacon = Beacon.new(
17
+ beacon_type: beacon_type,
18
+ domain: domain,
19
+ content: content,
20
+ luminosity: luminosity,
21
+ sweep_angle: sweep_angle
22
+ )
23
+ @beacons[beacon.id] = beacon
24
+ beacon
25
+ end
26
+
27
+ def create_fog(fog_type:, domain:, density: nil, extent: nil)
28
+ raise ArgumentError, 'too many fog banks' if @fog_banks.size >= Constants::MAX_FOG_BANKS
29
+
30
+ fog = Fog.new(fog_type: fog_type, domain: domain, density: density, extent: extent)
31
+ @fog_banks[fog.id] = fog
32
+ fog
33
+ end
34
+
35
+ def sweep(beacon_id:, fog_id:)
36
+ beacon = fetch_beacon(beacon_id)
37
+ fog = fetch_fog(fog_id)
38
+
39
+ reduction = (beacon.luminosity * 0.5).round(10)
40
+ fog.disperse!(rate: reduction)
41
+
42
+ { beacon: beacon.to_h, fog: fog.to_h, reduction: reduction }
43
+ end
44
+
45
+ def dim_all!(rate: Constants::LUMINOSITY_RATE)
46
+ @beacons.each_value { |b| b.dim!(rate: rate) }
47
+ pruned = @beacons.select { |_, b| b.extinguished? }.keys
48
+ pruned.each { |id| @beacons.delete(id) }
49
+ { remaining: @beacons.size, pruned: pruned.size }
50
+ end
51
+
52
+ def thicken_all!(rate: Constants::FOG_DENSITY_RATE)
53
+ @fog_banks.each_value { |f| f.thicken!(rate: rate) }
54
+ { fog_banks: @fog_banks.size }
55
+ end
56
+
57
+ def brightest_beacons(limit: 5)
58
+ @beacons.values
59
+ .reject(&:extinguished?)
60
+ .sort_by { |b| -b.luminosity }
61
+ .first(limit)
62
+ end
63
+
64
+ def densest_fogs(limit: 5)
65
+ @fog_banks.values
66
+ .sort_by { |f| -f.density }
67
+ .first(limit)
68
+ end
69
+
70
+ def visibility_report
71
+ avg_luminosity = compute_average_luminosity
72
+ avg_density = compute_average_density
73
+ net_visibility = (avg_luminosity - avg_density).clamp(0.0, 1.0).round(10)
74
+
75
+ {
76
+ total_beacons: @beacons.size,
77
+ total_fog_banks: @fog_banks.size,
78
+ avg_luminosity: avg_luminosity,
79
+ avg_density: avg_density,
80
+ net_visibility: net_visibility,
81
+ blazing_beacons: @beacons.count { |_, b| b.blazing? },
82
+ extinguished: @beacons.count { |_, b| b.extinguished? },
83
+ impenetrable_fog: @fog_banks.count { |_, f| f.impenetrable? },
84
+ clearing_fog: @fog_banks.count { |_, f| f.clearing? }
85
+ }
86
+ end
87
+
88
+ def all_beacons
89
+ @beacons.values
90
+ end
91
+
92
+ def all_fog_banks
93
+ @fog_banks.values
94
+ end
95
+
96
+ private
97
+
98
+ def fetch_beacon(id)
99
+ @beacons.fetch(id) { raise ArgumentError, "beacon not found: #{id}" }
100
+ end
101
+
102
+ def fetch_fog(id)
103
+ @fog_banks.fetch(id) { raise ArgumentError, "fog bank not found: #{id}" }
104
+ end
105
+
106
+ def compute_average_luminosity
107
+ return 0.0 if @beacons.empty?
108
+
109
+ total = @beacons.values.sum(&:luminosity)
110
+ (total / @beacons.size).round(10)
111
+ end
112
+
113
+ def compute_average_density
114
+ return 0.0 if @fog_banks.empty?
115
+
116
+ total = @fog_banks.values.sum(&:density)
117
+ (total / @fog_banks.size).round(10)
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLighthouse
6
+ module Runners
7
+ module CognitiveLighthouse
8
+ extend self
9
+
10
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
11
+
12
+ def light_beacon(beacon_type:, domain:, content:, luminosity: nil,
13
+ sweep_angle: nil, engine: nil, **)
14
+ eng = resolve_engine(engine)
15
+ beacon = eng.light_beacon(
16
+ beacon_type: beacon_type,
17
+ domain: domain,
18
+ content: content,
19
+ luminosity: luminosity,
20
+ sweep_angle: sweep_angle
21
+ )
22
+ Legion::Logging.debug "[lighthouse] lit beacon: type=#{beacon_type} domain=#{domain} " \
23
+ "luminosity=#{beacon.luminosity}"
24
+ { success: true, beacon: beacon.to_h }
25
+ rescue ArgumentError => e
26
+ { success: false, error: e.message }
27
+ end
28
+
29
+ def create_fog(fog_type:, domain:, density: nil, extent: nil, engine: nil, **)
30
+ eng = resolve_engine(engine)
31
+ fog = eng.create_fog(fog_type: fog_type, domain: domain,
32
+ density: density, extent: extent)
33
+ Legion::Logging.debug "[lighthouse] created fog: type=#{fog_type} domain=#{domain} " \
34
+ "density=#{fog.density}"
35
+ { success: true, fog: fog.to_h }
36
+ rescue ArgumentError => e
37
+ { success: false, error: e.message }
38
+ end
39
+
40
+ def sweep(beacon_id:, fog_id:, engine: nil, **)
41
+ eng = resolve_engine(engine)
42
+ result = eng.sweep(beacon_id: beacon_id, fog_id: fog_id)
43
+ Legion::Logging.debug "[lighthouse] sweep: beacon=#{beacon_id} fog=#{fog_id} " \
44
+ "reduction=#{result[:reduction]}"
45
+ { success: true, **result }
46
+ rescue ArgumentError => e
47
+ { success: false, error: e.message }
48
+ end
49
+
50
+ def list_beacons(engine: nil, domain: nil, beacon_type: nil, **)
51
+ eng = resolve_engine(engine)
52
+ results = eng.all_beacons
53
+ results = results.select { |b| b.domain == domain.to_s } if domain
54
+ results = results.select { |b| b.beacon_type == beacon_type.to_sym } if beacon_type
55
+ { success: true, beacons: results.map(&:to_h), count: results.size }
56
+ end
57
+
58
+ def navigation_status(engine: nil, **)
59
+ eng = resolve_engine(engine)
60
+ { success: true, report: eng.visibility_report }
61
+ end
62
+
63
+ private
64
+
65
+ def resolve_engine(engine)
66
+ engine || default_engine
67
+ end
68
+
69
+ def default_engine
70
+ @default_engine ||= Helpers::LighthouseEngine.new
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveLighthouse
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_relative 'cognitive_lighthouse/version'
6
+ require_relative 'cognitive_lighthouse/helpers/constants'
7
+ require_relative 'cognitive_lighthouse/helpers/beacon'
8
+ require_relative 'cognitive_lighthouse/helpers/fog'
9
+ require_relative 'cognitive_lighthouse/helpers/lighthouse_engine'
10
+ require_relative 'cognitive_lighthouse/runners/cognitive_lighthouse'
11
+ require_relative 'cognitive_lighthouse/client'
12
+
13
+ module Legion
14
+ module Extensions
15
+ module CognitiveLighthouse
16
+ extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lex-cognitive-lighthouse
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: Models guiding beacons that periodically sweep their beam to illuminate
27
+ areas of uncertainty, helping navigate complex decision spaces. Beacons can be steady
28
+ or rotating, can dim in fog, and can guide other agents through ambiguity.
29
+ email:
30
+ - matthewdiverson@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".github/workflows/ci.yml"
36
+ - ".gitignore"
37
+ - ".rspec"
38
+ - ".rubocop.yml"
39
+ - CLAUDE.md
40
+ - Gemfile
41
+ - Gemfile.lock
42
+ - README.md
43
+ - lex-cognitive-lighthouse.gemspec
44
+ - lib/legion/extensions/cognitive_lighthouse.rb
45
+ - lib/legion/extensions/cognitive_lighthouse/client.rb
46
+ - lib/legion/extensions/cognitive_lighthouse/helpers/beacon.rb
47
+ - lib/legion/extensions/cognitive_lighthouse/helpers/constants.rb
48
+ - lib/legion/extensions/cognitive_lighthouse/helpers/fog.rb
49
+ - lib/legion/extensions/cognitive_lighthouse/helpers/lighthouse_engine.rb
50
+ - lib/legion/extensions/cognitive_lighthouse/runners/cognitive_lighthouse.rb
51
+ - lib/legion/extensions/cognitive_lighthouse/version.rb
52
+ homepage: https://github.com/LegionIO/lex-cognitive-lighthouse
53
+ licenses:
54
+ - MIT
55
+ metadata:
56
+ homepage_uri: https://github.com/LegionIO/lex-cognitive-lighthouse
57
+ source_code_uri: https://github.com/LegionIO/lex-cognitive-lighthouse
58
+ documentation_uri: https://github.com/LegionIO/lex-cognitive-lighthouse#readme
59
+ changelog_uri: https://github.com/LegionIO/lex-cognitive-lighthouse/blob/main/CHANGELOG.md
60
+ bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-lighthouse/issues
61
+ rubygems_mfa_required: 'true'
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '3.4'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubygems_version: 3.6.9
77
+ specification_version: 4
78
+ summary: Cognitive lighthouse LEX — guiding beacons that cut through cognitive fog
79
+ test_files: []