lex-cognitive-compass 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: aabc5df25b6e0b4abd5a92508175ad6da5d036b5ce8f245540558f3f1702ab02
4
+ data.tar.gz: 41b0628f4ddfba105e7deda09d369b5e7f1bd9dba30a695f0b0cb427d42c1c07
5
+ SHA512:
6
+ metadata.gz: 4b97868fcac953522701fe87cfef7523d0f03fd37541656d77f3f983ba7a390099e29c9aea2fb762df115c61d442de55d209cf4a303fe7f6be8c3e254ef7e437
7
+ data.tar.gz: 3986bc6d68d324dc34d8b3ef032db800ecb233c9984bc254ee798cc7677bd2bf20b60c2435c5c5f8a79519fb076dbbb1ce6572268a52af12b2f127ec8acf9741
@@ -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,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
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,75 @@
1
+ # lex-cognitive-compass
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
+ Maps cardinal directions to value axes (truth/utility/beauty/safety), tracks magnetic declination from cognitive biases, and provides true north calibration for aligned decision-making. Bearings represent directional assessments toward value axes; biases cause declination that skews bearings away from true north.
10
+
11
+ ## Gem Info
12
+
13
+ - **Gem name**: `lex-cognitive-compass`
14
+ - **Version**: `0.1.0`
15
+ - **Module**: `Legion::Extensions::CognitiveCompass`
16
+ - **Ruby**: `>= 3.4`
17
+ - **License**: MIT
18
+
19
+ ## File Structure
20
+
21
+ ```
22
+ lib/legion/extensions/cognitive_compass/
23
+ cognitive_compass.rb
24
+ version.rb
25
+ client.rb
26
+ helpers/
27
+ constants.rb
28
+ compass_engine.rb
29
+ bearing.rb
30
+ magnetic_bias.rb
31
+ runners/
32
+ cognitive_compass.rb
33
+ ```
34
+
35
+ ## Key Constants
36
+
37
+ From `helpers/constants.rb`:
38
+
39
+ - `CARDINAL_DIRECTIONS` — `{ north: :truth, east: :utility, south: :beauty, west: :safety }`
40
+ - `INTERCARDINAL_DIRECTIONS` — `{ northeast: [:truth, :utility], southeast: [:utility, :beauty], southwest: [:beauty, :safety], northwest: [:safety, :truth] }`
41
+ - `BIAS_TYPES` — `%i[confirmation anchoring availability recency authority framing sunk_cost optimism]`
42
+ - `MAX_COMPASSES` = `50`, `MAX_BIASES` = `20`
43
+ - `DECLINATION_DECAY` = `0.02`, `CALIBRATION_BOOST` = `0.15`
44
+ - `ACCURACY_LABELS` — `0.8+` = `:precise`, `0.6` = `:reliable`, `0.4` = `:approximate`, `0.2` = `:drifting`, below = `:lost`
45
+ - `DECLINATION_LABELS` — `0.8+` = `:severe`, `0.6` = `:significant`, `0.4` = `:moderate`, `0.2` = `:mild`, below = `:negligible`
46
+
47
+ ## Runners
48
+
49
+ All methods in `Runners::CognitiveCompass` (`extend self`):
50
+
51
+ - `take_bearing(direction:, context:, confidence: nil)` — records a directional assessment toward a value axis; returns `Bearing` with accuracy derived from confidence
52
+ - `register_bias(bias_type:, domain:, declination: nil, strength: nil)` — registers a cognitive bias that causes magnetic declination; validates against `BIAS_TYPES`
53
+ - `calibrate(bias_id:, amount: nil)` — reduces declination on a bias by `CALIBRATION_BOOST` (or custom amount); represents active bias correction
54
+ - `list_bearings(direction: nil)` — all bearings, optionally filtered by direction
55
+ - `list_biases` — all registered biases with current declination
56
+ - `compass_status` — full compass report: bearing distribution, total declination, true north alignment
57
+
58
+ ## Helpers
59
+
60
+ - `CompassEngine` — manages bearings and biases. `compass_report` computes aggregate: directional distribution, average declination, calibration state.
61
+ - `Bearing` — directional assessment with `direction`, `context`, `confidence`, `accuracy`. `direction` must be a valid cardinal or intercardinal value.
62
+ - `MagneticBias` — cognitive bias with `bias_type`, `domain`, `declination`, `strength`. `calibrate!(amount)` reduces declination. `declination_label` classifies severity.
63
+
64
+ ## Integration Points
65
+
66
+ - `lex-cognitive-blindspot` tracks unknown-unknowns; compass tracks known value misalignments (biases that are registered and measurable).
67
+ - `lex-tick` action selection phase can check compass bearing toward `:safety` and `:truth` before executing high-stakes decisions — bearings with low accuracy or high declination should trigger deliberate mode.
68
+ - `calibrate` can be called after a `lex-conflict` resolution event, representing bias reduction through adversarial challenge.
69
+
70
+ ## Development Notes
71
+
72
+ - `CARDINAL_DIRECTIONS` maps direction symbols to value names — north=truth is the primary alignment axis. "True north" metaphor: an unbiased agent points north (toward truth) reliably.
73
+ - Intercardinal directions blend two value axes; callers use these for nuanced assessments (e.g., `northeast` = truth + utility balance).
74
+ - `MAX_BIASES = 20` is intentionally small — too many registered biases suggests the calibration model is incomplete; address biases, don't just log them.
75
+ - `DECLINATION_DECAY = 0.02` models natural bias reduction over time without active calibration (slow passive correction).
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-compass (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-compass!
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-compass
2
+
3
+ Cognitive compass LEX — internal directional sense for decision-making. Maps cardinal directions to value axes (truth/utility/beauty/safety), tracks magnetic declination from cognitive biases, and provides true north calibration for aligned decision-making.
4
+
5
+ ## What It Does
6
+
7
+ Decision-making has a direction — toward truth, utility, beauty, or safety. This extension models an internal compass that takes bearings (directional assessments in context), registers cognitive biases that cause magnetic declination (pulling bearings away from true north), and supports active calibration (reducing bias-driven drift).
8
+
9
+ Eight bias types are modeled: confirmation, anchoring, availability, recency, authority, framing, sunk cost, and optimism. Intercardinal directions blend two value axes for nuanced assessments.
10
+
11
+ ## Usage
12
+
13
+ ```ruby
14
+ client = Legion::Extensions::CognitiveCompass::Client.new
15
+
16
+ client.take_bearing(direction: :north, context: 'fact-checking response accuracy', confidence: 0.8)
17
+ client.take_bearing(direction: :west, context: 'evaluating action safety', confidence: 0.7)
18
+
19
+ bias = client.register_bias(
20
+ bias_type: :confirmation,
21
+ domain: :reasoning,
22
+ declination: 0.6
23
+ )
24
+
25
+ client.calibrate(bias_id: bias[:bias][:id]) # reduce declination
26
+ client.compass_status
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,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/legion/extensions/cognitive_compass/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lex-cognitive-compass'
7
+ spec.version = Legion::Extensions::CognitiveCompass::VERSION
8
+ spec.authors = ['Esity']
9
+ spec.email = ['matthewdiverson@gmail.com']
10
+ spec.license = 'MIT'
11
+
12
+ spec.summary = 'Cognitive compass LEX — internal directional sense for decision-making'
13
+ spec.description = 'Maps cardinal directions to value axes (truth/utility/beauty/safety), ' \
14
+ 'tracks magnetic declination from cognitive biases, and provides true ' \
15
+ 'north calibration for aligned decision-making.'
16
+ spec.homepage = 'https://github.com/LegionIO/lex-cognitive-compass'
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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveCompass
6
+ class Client
7
+ include Runners::CognitiveCompass
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveCompass
6
+ module Helpers
7
+ class Bearing
8
+ attr_reader :id, :direction, :value_axis, :context,
9
+ :taken_at
10
+ attr_accessor :confidence
11
+
12
+ def initialize(direction:, context:, confidence: nil)
13
+ validate_direction!(direction)
14
+ @id = SecureRandom.uuid
15
+ @direction = direction.to_sym
16
+ @value_axis = resolve_axis(direction.to_sym)
17
+ @context = context.to_s
18
+ @confidence = (confidence || 0.7).to_f.clamp(0.0, 1.0).round(10)
19
+ @taken_at = Time.now.utc
20
+ end
21
+
22
+ def reliable?
23
+ @confidence >= 0.6
24
+ end
25
+
26
+ def lost?
27
+ @confidence < 0.2
28
+ end
29
+
30
+ def cardinal?
31
+ Constants::CARDINAL_DIRECTIONS.key?(@direction)
32
+ end
33
+
34
+ def accuracy_label
35
+ Constants.label_for(Constants::ACCURACY_LABELS, @confidence)
36
+ end
37
+
38
+ def to_h
39
+ {
40
+ id: @id,
41
+ direction: @direction,
42
+ value_axis: @value_axis,
43
+ context: @context,
44
+ confidence: @confidence,
45
+ accuracy_label: accuracy_label,
46
+ cardinal: cardinal?,
47
+ reliable: reliable?,
48
+ lost: lost?,
49
+ taken_at: @taken_at
50
+ }
51
+ end
52
+
53
+ private
54
+
55
+ def resolve_axis(dir)
56
+ Constants::CARDINAL_DIRECTIONS.fetch(dir) do
57
+ Constants::INTERCARDINAL_DIRECTIONS.fetch(dir) do
58
+ raise ArgumentError, "unknown direction: #{dir}"
59
+ end
60
+ end
61
+ end
62
+
63
+ def validate_direction!(val)
64
+ sym = val.to_sym
65
+ return if Constants::CARDINAL_DIRECTIONS.key?(sym) ||
66
+ Constants::INTERCARDINAL_DIRECTIONS.key?(sym)
67
+
68
+ raise ArgumentError,
69
+ "unknown direction: #{val.inspect}; must be cardinal or intercardinal"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveCompass
6
+ module Helpers
7
+ class CompassEngine
8
+ def initialize
9
+ @bearings = {}
10
+ @biases = {}
11
+ end
12
+
13
+ def take_bearing(direction:, context:, confidence: nil)
14
+ bearing = Bearing.new(direction: direction, context: context,
15
+ confidence: confidence)
16
+ @bearings[bearing.id] = bearing
17
+ bearing
18
+ end
19
+
20
+ def register_bias(bias_type:, domain:, declination: nil, strength: nil)
21
+ raise ArgumentError, 'too many biases' if @biases.size >= Constants::MAX_BIASES
22
+
23
+ bias = MagneticBias.new(bias_type: bias_type, domain: domain,
24
+ declination: declination, strength: strength)
25
+ @biases[bias.id] = bias
26
+ bias
27
+ end
28
+
29
+ def calibrate(bias_id:, amount: Constants::CALIBRATION_BOOST)
30
+ fetch_bias(bias_id).correct!(amount: amount)
31
+ end
32
+
33
+ def true_north_offset
34
+ return 0.0 if @biases.empty?
35
+
36
+ total = @biases.values.sum(&:declination)
37
+ (total / @biases.size).round(10)
38
+ end
39
+
40
+ def accuracy
41
+ offset = true_north_offset
42
+ (1.0 - offset).clamp(0.0, 1.0).round(10)
43
+ end
44
+
45
+ def accuracy_label
46
+ Constants.label_for(Constants::ACCURACY_LABELS, accuracy)
47
+ end
48
+
49
+ def decay_biases!(rate: Constants::DECLINATION_DECAY)
50
+ @biases.each_value { |b| b.decay!(rate: rate) }
51
+ pruned = @biases.select { |_, b| b.negligible? && b.strength < 0.1 }.keys
52
+ pruned.each { |id| @biases.delete(id) }
53
+ { remaining: @biases.size, pruned: pruned.size }
54
+ end
55
+
56
+ def dominant_direction
57
+ return nil if @bearings.empty?
58
+
59
+ counts = Hash.new(0)
60
+ @bearings.each_value { |b| counts[b.direction] += b.confidence }
61
+ counts.max_by { |_, v| v }&.first
62
+ end
63
+
64
+ def bearings_by_direction
65
+ result = Hash.new(0)
66
+ @bearings.each_value { |b| result[b.direction] += 1 }
67
+ result
68
+ end
69
+
70
+ def strongest_biases(limit: 5)
71
+ @biases.values.sort_by { |b| -b.strength }.first(limit)
72
+ end
73
+
74
+ def compass_report
75
+ {
76
+ total_bearings: @bearings.size,
77
+ total_biases: @biases.size,
78
+ accuracy: accuracy,
79
+ accuracy_label: accuracy_label,
80
+ true_north_offset: true_north_offset,
81
+ dominant_direction: dominant_direction,
82
+ by_direction: bearings_by_direction,
83
+ severe_biases: @biases.count { |_, b| b.severe? }
84
+ }
85
+ end
86
+
87
+ def all_bearings
88
+ @bearings.values
89
+ end
90
+
91
+ def all_biases
92
+ @biases.values
93
+ end
94
+
95
+ private
96
+
97
+ def fetch_bias(id)
98
+ @biases.fetch(id) { raise ArgumentError, "bias not found: #{id}" }
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveCompass
6
+ module Helpers
7
+ module Constants
8
+ # Cardinal directions mapped to value axes
9
+ CARDINAL_DIRECTIONS = {
10
+ north: :truth,
11
+ east: :utility,
12
+ south: :beauty,
13
+ west: :safety
14
+ }.freeze
15
+
16
+ # Intercardinal directions (blended values)
17
+ INTERCARDINAL_DIRECTIONS = {
18
+ northeast: %i[truth utility],
19
+ southeast: %i[utility beauty],
20
+ southwest: %i[beauty safety],
21
+ northwest: %i[safety truth]
22
+ }.freeze
23
+
24
+ # Bias types that cause magnetic declination
25
+ BIAS_TYPES = %i[
26
+ confirmation anchoring availability recency
27
+ authority framing sunk_cost optimism
28
+ ].freeze
29
+
30
+ MAX_COMPASSES = 50
31
+ MAX_BIASES = 20
32
+ DECLINATION_DECAY = 0.02
33
+ CALIBRATION_BOOST = 0.15
34
+
35
+ # Bearing accuracy labels
36
+ ACCURACY_LABELS = [
37
+ [(0.8..), :precise],
38
+ [(0.6...0.8), :reliable],
39
+ [(0.4...0.6), :approximate],
40
+ [(0.2...0.4), :drifting],
41
+ [(..0.2), :lost]
42
+ ].freeze
43
+
44
+ # Declination severity labels
45
+ DECLINATION_LABELS = [
46
+ [(0.8..), :severe],
47
+ [(0.6...0.8), :significant],
48
+ [(0.4...0.6), :moderate],
49
+ [(0.2...0.4), :mild],
50
+ [(..0.2), :negligible]
51
+ ].freeze
52
+
53
+ def self.label_for(table, value)
54
+ table.each { |range, label| return label if range.cover?(value) }
55
+ table.last.last
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveCompass
6
+ module Helpers
7
+ class MagneticBias
8
+ attr_reader :id, :bias_type, :domain, :detected_at
9
+ attr_accessor :declination, :strength
10
+
11
+ def initialize(bias_type:, domain:, declination: nil, strength: nil)
12
+ validate_bias!(bias_type)
13
+ @id = SecureRandom.uuid
14
+ @bias_type = bias_type.to_sym
15
+ @domain = domain.to_sym
16
+ @declination = (declination || 0.3).to_f.clamp(0.0, 1.0).round(10)
17
+ @strength = (strength || 0.5).to_f.clamp(0.0, 1.0).round(10)
18
+ @detected_at = Time.now.utc
19
+ end
20
+
21
+ def correct!(amount: Constants::CALIBRATION_BOOST)
22
+ @declination = (@declination - amount.abs).clamp(0.0, 1.0).round(10)
23
+ self
24
+ end
25
+
26
+ def intensify!(amount: 0.1)
27
+ @strength = (@strength + amount.abs).clamp(0.0, 1.0).round(10)
28
+ @declination = (@declination + (amount.abs * 0.5)).clamp(0.0, 1.0).round(10)
29
+ self
30
+ end
31
+
32
+ def decay!(rate: Constants::DECLINATION_DECAY)
33
+ @strength = (@strength - rate.abs).clamp(0.0, 1.0).round(10)
34
+ @declination = (@declination - (rate.abs * 0.5)).clamp(0.0, 1.0).round(10)
35
+ self
36
+ end
37
+
38
+ def severe?
39
+ @declination >= 0.8
40
+ end
41
+
42
+ def negligible?
43
+ @declination < 0.2
44
+ end
45
+
46
+ def declination_label
47
+ Constants.label_for(Constants::DECLINATION_LABELS, @declination)
48
+ end
49
+
50
+ def to_h
51
+ {
52
+ id: @id,
53
+ bias_type: @bias_type,
54
+ domain: @domain,
55
+ declination: @declination,
56
+ declination_label: declination_label,
57
+ strength: @strength,
58
+ severe: severe?,
59
+ negligible: negligible?,
60
+ detected_at: @detected_at
61
+ }
62
+ end
63
+
64
+ private
65
+
66
+ def validate_bias!(val)
67
+ return if Constants::BIAS_TYPES.include?(val.to_sym)
68
+
69
+ raise ArgumentError,
70
+ "unknown bias type: #{val.inspect}; " \
71
+ "must be one of #{Constants::BIAS_TYPES.inspect}"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveCompass
6
+ module Runners
7
+ module CognitiveCompass
8
+ extend self
9
+
10
+ def take_bearing(direction:, context:, confidence: nil, engine: nil, **)
11
+ eng = resolve_engine(engine)
12
+ bearing = eng.take_bearing(direction: direction, context: context,
13
+ confidence: confidence)
14
+ { success: true, bearing: bearing.to_h }
15
+ rescue ArgumentError => e
16
+ { success: false, error: e.message }
17
+ end
18
+
19
+ def register_bias(bias_type:, domain:, declination: nil,
20
+ strength: nil, engine: nil, **)
21
+ eng = resolve_engine(engine)
22
+ bias = eng.register_bias(bias_type: bias_type, domain: domain,
23
+ declination: declination, strength: strength)
24
+ { success: true, bias: bias.to_h }
25
+ rescue ArgumentError => e
26
+ { success: false, error: e.message }
27
+ end
28
+
29
+ def calibrate(bias_id:, amount: nil, engine: nil, **)
30
+ eng = resolve_engine(engine)
31
+ opts = { bias_id: bias_id }
32
+ opts[:amount] = amount if amount
33
+ bias = eng.calibrate(**opts)
34
+ { success: true, bias: bias.to_h }
35
+ rescue ArgumentError => e
36
+ { success: false, error: e.message }
37
+ end
38
+
39
+ def list_bearings(engine: nil, direction: nil, **)
40
+ eng = resolve_engine(engine)
41
+ results = eng.all_bearings
42
+ results = results.select { |b| b.direction == direction.to_sym } if direction
43
+ { success: true, bearings: results.map(&:to_h), count: results.size }
44
+ end
45
+
46
+ def list_biases(engine: nil, **)
47
+ eng = resolve_engine(engine)
48
+ { success: true, biases: eng.all_biases.map(&:to_h),
49
+ count: eng.all_biases.size }
50
+ end
51
+
52
+ def compass_status(engine: nil, **)
53
+ eng = resolve_engine(engine)
54
+ { success: true, report: eng.compass_report }
55
+ end
56
+
57
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
58
+
59
+ private
60
+
61
+ def resolve_engine(engine)
62
+ engine || default_engine
63
+ end
64
+
65
+ def default_engine
66
+ @default_engine ||= Helpers::CompassEngine.new
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveCompass
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_compass/version'
6
+ require_relative 'cognitive_compass/helpers/constants'
7
+ require_relative 'cognitive_compass/helpers/bearing'
8
+ require_relative 'cognitive_compass/helpers/magnetic_bias'
9
+ require_relative 'cognitive_compass/helpers/compass_engine'
10
+ require_relative 'cognitive_compass/runners/cognitive_compass'
11
+ require_relative 'cognitive_compass/client'
12
+
13
+ module Legion
14
+ module Extensions
15
+ module CognitiveCompass
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-compass
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: Maps cardinal directions to value axes (truth/utility/beauty/safety),
27
+ tracks magnetic declination from cognitive biases, and provides true north calibration
28
+ for aligned decision-making.
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-compass.gemspec
44
+ - lib/legion/extensions/cognitive_compass.rb
45
+ - lib/legion/extensions/cognitive_compass/client.rb
46
+ - lib/legion/extensions/cognitive_compass/helpers/bearing.rb
47
+ - lib/legion/extensions/cognitive_compass/helpers/compass_engine.rb
48
+ - lib/legion/extensions/cognitive_compass/helpers/constants.rb
49
+ - lib/legion/extensions/cognitive_compass/helpers/magnetic_bias.rb
50
+ - lib/legion/extensions/cognitive_compass/runners/cognitive_compass.rb
51
+ - lib/legion/extensions/cognitive_compass/version.rb
52
+ homepage: https://github.com/LegionIO/lex-cognitive-compass
53
+ licenses:
54
+ - MIT
55
+ metadata:
56
+ homepage_uri: https://github.com/LegionIO/lex-cognitive-compass
57
+ source_code_uri: https://github.com/LegionIO/lex-cognitive-compass
58
+ documentation_uri: https://github.com/LegionIO/lex-cognitive-compass#readme
59
+ changelog_uri: https://github.com/LegionIO/lex-cognitive-compass/blob/main/CHANGELOG.md
60
+ bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-compass/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 compass LEX — internal directional sense for decision-making
79
+ test_files: []