lex-cognitive-anchor 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: 59a9a520a9d3e551fd8affba60f56d2e7d675199745b75bed909b106b38a5905
4
+ data.tar.gz: 9ba81b07934db4cfb3de2bec2be52abd588256761d0af1882361ad6f8d6adc4b
5
+ SHA512:
6
+ metadata.gz: 657a67870dca71022858a61d53592df527681066fb55f6ace939da6f87e763e93337e6a0216a21245a8c72c59c76ba8c8c2a3be0d42e08da73ca58274793ad06
7
+ data.tar.gz: 45e95298b0615d6071d18e3098a59d711907b9cbfc590c9699c0eed238b965b2a595531627b0aa73529e7ce51962240eb969852ca4d083db2d1bcfad5385aa65
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CLAUDE.md ADDED
@@ -0,0 +1,88 @@
1
+ # lex-cognitive-anchor
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
+ Cognitive anchoring and belief tethering — anchor points resist change via grip, chains link anchors with material-dependent flexibility, and bias application models how anchors distort estimates.
10
+
11
+ ## Gem Info
12
+
13
+ - **Gem name**: `lex-cognitive-anchor`
14
+ - **Version**: `0.1.0`
15
+ - **Module**: `Legion::Extensions::CognitiveAnchor`
16
+ - **Ruby**: `>= 3.4`
17
+ - **License**: MIT
18
+
19
+ ## File Structure
20
+
21
+ ```
22
+ lib/legion/extensions/cognitive_anchor/
23
+ cognitive_anchor.rb # Main extension module
24
+ version.rb # VERSION = '0.1.0'
25
+ client.rb # Client wrapper
26
+ helpers/
27
+ constants.rb # Anchor types, chain materials, drag/drift rates, grip/flexibility labels
28
+ anchor.rb # Anchor value object (grip, type, domain, age)
29
+ chain.rb # Chain value object (material, two anchors, flexibility)
30
+ anchor_store.rb # AnchorStore — manages anchors and chains, applies bias
31
+ runners/
32
+ cognitive_anchor.rb # Runner module (extend self) with 6 public methods
33
+ spec/
34
+ (spec files)
35
+ ```
36
+
37
+ ## Key Constants
38
+
39
+ ```ruby
40
+ ANCHOR_TYPES = %i[belief assumption experience authority number]
41
+ CHAIN_MATERIALS = %i[steel rope wire thread cobweb]
42
+ DRAG_RATE = 0.06 # how much grip decays when an anchor is dragged (challenged)
43
+ DRIFT_RATE = 0.03 # passive grip decay over time
44
+ BREAK_THRESHOLD = 0.1 # grip level at which an anchor breaks (chain severs)
45
+ GRIP_LABELS = {
46
+ (0.85..) => :immovable, (0.65...0.85) => :firm, (0.45...0.65) => :moderate,
47
+ (0.25...0.45) => :loose, (..0.25) => :slipping
48
+ }
49
+ FLEXIBILITY_LABELS = {
50
+ steel: :rigid, rope: :flexible, wire: :semiflexible,
51
+ thread: :very_flexible, cobweb: :fragile
52
+ }
53
+ ```
54
+
55
+ ## Runners
56
+
57
+ ### `Runners::CognitiveAnchor`
58
+
59
+ Uses `extend self` — methods are module-level, not instance-delegating. Delegates to a per-call `engine` (parameter-injected `Helpers::AnchorStore` instance via `engine:` keyword, defaulting to a shared `@engine ||=`).
60
+
61
+ - `create_anchor(name:, anchor_type:, domain: :general, grip: 0.7, engine: @engine)` — register an anchor point with initial grip
62
+ - `create_chain(anchor_a:, anchor_b:, material:, engine: @engine)` — link two anchors with a chain of specified material; chain flexibility depends on material
63
+ - `apply_bias(anchor_id:, estimate:, engine: @engine)` — apply the anchor's distortion to an estimate; returns adjusted estimate and bias magnitude
64
+ - `list_anchors(engine: @engine)` — all anchors as array of hashes with grip labels
65
+ - `anchor_status(engine: @engine)` — summary: anchor count, chain count, average grip, broken chain count
66
+
67
+ ## Helpers
68
+
69
+ ### `Helpers::AnchorStore`
70
+ Core engine managing `@anchors` and `@chains` hashes. `apply_bias` computes how strongly the anchor distorts the given estimate based on current grip. `drag_anchor` reduces grip by `DRAG_RATE`; if grip drops below `BREAK_THRESHOLD`, all chains involving the anchor are severed. `drift_all` applies passive `DRIFT_RATE` decay to all anchors.
71
+
72
+ ### `Helpers::Anchor`
73
+ Value object: name, anchor_type, domain, grip (0.0–1.0), age. `drag!` reduces grip by `DRAG_RATE` clamped to 0.0. `drift!` reduces grip by `DRIFT_RATE`. `broken?` returns true when `grip <= BREAK_THRESHOLD`. `grip_label` maps current grip to human-readable label.
74
+
75
+ ### `Helpers::Chain`
76
+ Value object: material, anchor_a_id, anchor_b_id, flexibility (derived from material). `flexibility_label` maps material to label from `FLEXIBILITY_LABELS`. `active?` returns true only when neither linked anchor is broken.
77
+
78
+ ## Integration Points
79
+
80
+ No actor defined — no automatic drift or drag. This extension models how existing beliefs and anchors resist or distort new information. Pairs with lex-anchoring (which models Kahneman/Tversky numeric anchoring and prospect theory) — these are complementary; lex-anchoring covers numeric estimation bias, lex-cognitive-anchor covers structural belief tethering. Pairs with lex-bias (anchor bias detection feeds here) and lex-belief-revision (chain breaks can trigger belief revision events).
81
+
82
+ ## Development Notes
83
+
84
+ - `extend self` pattern: runner is a module with module-level methods; shared `@engine` lives in the module's singleton
85
+ - `BREAK_THRESHOLD = 0.1` is intentionally low — anchors are persistent; they require sustained challenge (`drag_anchor` calls) to break
86
+ - `DRAG_RATE (0.06) > DRIFT_RATE (0.03)`: active challenge degrades grip twice as fast as passive time decay
87
+ - Chain material determines flexibility label only — the mechanics of chain flexibility are not yet enforced on bias calculations (stub intent)
88
+ - `apply_bias` returns a hash with both the adjusted estimate and bias magnitude — callers must decide how to apply the adjustment
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # lex-cognitive-anchor
2
+
3
+ Cognitive anchoring and belief tethering — anchor points resist change via grip, chains link anchors, and bias application models how they distort estimates.
4
+
5
+ ## What It Does
6
+
7
+ Models how beliefs and assumptions act as anchors that resist revision. Each anchor has a `grip` (0.0–1.0) that decays when the anchor is challenged (`drag`) or simply ages (`drift`). Anchors can be chained together with material-dependent flexibility (steel = rigid, cobweb = fragile). When an anchor's grip falls below the break threshold, its chains sever.
8
+
9
+ ## Core Concept: Anchor Types and Materials
10
+
11
+ ```
12
+ ANCHOR_TYPES: belief, assumption, experience, authority, number
13
+ CHAIN_MATERIALS: steel (rigid) -> rope -> wire -> thread -> cobweb (fragile)
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```ruby
19
+ client = Legion::Extensions::CognitiveAnchor::Client.new
20
+
21
+ # Register a strong belief anchor
22
+ belief = client.create_anchor(
23
+ name: :microservices_are_always_better,
24
+ anchor_type: :belief,
25
+ domain: :architecture,
26
+ grip: 0.85
27
+ )
28
+
29
+ # Register an experience-based anchor
30
+ exp = client.create_anchor(
31
+ name: :monolith_failure_2019,
32
+ anchor_type: :experience,
33
+ domain: :architecture,
34
+ grip: 0.70
35
+ )
36
+
37
+ # Chain them together with a semi-flexible wire link
38
+ client.create_chain(
39
+ anchor_a: belief[:anchor][:id],
40
+ anchor_b: exp[:anchor][:id],
41
+ material: :wire
42
+ )
43
+
44
+ # Apply anchor bias to a new architectural estimate
45
+ client.apply_bias(
46
+ anchor_id: belief[:anchor][:id],
47
+ estimate: { approach: :monolith, confidence: 0.7 }
48
+ )
49
+ # => { adjusted_estimate: ..., bias_magnitude: 0.72 }
50
+
51
+ # Check overall anchor landscape
52
+ client.anchor_status
53
+ # => { anchor_count: 2, chain_count: 1, average_grip: 0.78, broken_chains: 0 }
54
+ ```
55
+
56
+ ## Integration
57
+
58
+ Pairs with lex-anchoring (numeric anchoring and prospect theory) and lex-bias (bias detection feeds here). Pairs with lex-belief-revision — when an anchor breaks, the freed beliefs become candidates for revision.
59
+
60
+ ## Development
61
+
62
+ ```bash
63
+ bundle install
64
+ bundle exec rspec
65
+ bundle exec rubocop
66
+ ```
67
+
68
+ ## License
69
+
70
+ MIT
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/legion/extensions/cognitive_anchor/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'lex-cognitive-anchor'
7
+ spec.version = Legion::Extensions::CognitiveAnchor::VERSION
8
+ spec.authors = ['Esity']
9
+ spec.email = ['matthewdiverson@gmail.com']
10
+
11
+ spec.summary = 'Cognitive anchoring bias dynamics for LegionIO agentic architecture'
12
+ spec.description = 'Models anchoring biases where fixed reference points pull new information ' \
13
+ 'toward them with configurable grip, weight, and chain flexibility'
14
+ spec.homepage = 'https://github.com/LegionIO/lex-cognitive-anchor'
15
+ spec.license = 'MIT'
16
+
17
+ spec.required_ruby_version = '>= 3.4'
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = spec.homepage
21
+ spec.metadata['documentation_uri'] = "#{spec.homepage}/blob/master/README.md"
22
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/master/CHANGELOG.md"
23
+ spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
24
+ spec.metadata['rubygems_mfa_required'] = 'true'
25
+
26
+ spec.files = Dir.chdir(__dir__) do
27
+ `git ls-files -z`.split("\x0").reject do |f|
28
+ (File.expand_path(f) == __FILE__) ||
29
+ f.start_with?('spec/', '.git', '.rubocop', 'Gemfile')
30
+ end
31
+ end
32
+
33
+ spec.require_paths = ['lib']
34
+ spec.add_development_dependency 'legion-gaia'
35
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveAnchor
6
+ class Client
7
+ include Runners::CognitiveAnchor
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveAnchor
6
+ module Helpers
7
+ class Anchor
8
+ attr_reader :id, :anchor_type, :domain, :content,
9
+ :reference_value, :created_at
10
+ attr_accessor :grip, :weight
11
+
12
+ def initialize(anchor_type:, domain:, content:,
13
+ reference_value: nil, grip: nil, weight: nil)
14
+ validate_anchor_type!(anchor_type)
15
+ @id = SecureRandom.uuid
16
+ @anchor_type = anchor_type.to_sym
17
+ @domain = domain.to_sym
18
+ @content = content.to_s
19
+ @reference_value = (reference_value || 0.5).to_f.clamp(0.0, 1.0).round(10)
20
+ @grip = (grip || 0.7).to_f.clamp(0.0, 1.0).round(10)
21
+ @weight = (weight || 0.5).to_f.clamp(0.0, 1.0).round(10)
22
+ @created_at = Time.now.utc
23
+ end
24
+
25
+ def drag!(rate: Constants::DRAG_RATE)
26
+ @grip = (@grip + rate.abs).clamp(0.0, 1.0).round(10)
27
+ end
28
+
29
+ def drift!(rate: Constants::DRIFT_RATE)
30
+ @grip = (@grip - rate.abs).clamp(0.0, 1.0).round(10)
31
+ end
32
+
33
+ def bias_pull(new_value)
34
+ pull_strength = @grip * @weight
35
+ adjusted = new_value + ((reference_value - new_value) * pull_strength)
36
+ adjusted.clamp(0.0, 1.0).round(10)
37
+ end
38
+
39
+ def ironclad?
40
+ @grip >= 0.8
41
+ end
42
+
43
+ def drifting?
44
+ @grip < 0.2
45
+ end
46
+
47
+ def heavy?
48
+ @weight >= 0.7
49
+ end
50
+
51
+ def light?
52
+ @weight < 0.3
53
+ end
54
+
55
+ def grip_label
56
+ Constants.label_for(Constants::GRIP_LABELS, @grip)
57
+ end
58
+
59
+ def to_h
60
+ {
61
+ id: @id,
62
+ anchor_type: @anchor_type,
63
+ domain: @domain,
64
+ content: @content,
65
+ reference_value: @reference_value,
66
+ grip: @grip,
67
+ weight: @weight,
68
+ grip_label: grip_label,
69
+ ironclad: ironclad?,
70
+ drifting: drifting?,
71
+ created_at: @created_at
72
+ }
73
+ end
74
+
75
+ private
76
+
77
+ def validate_anchor_type!(val)
78
+ return if Constants::ANCHOR_TYPES.include?(val.to_sym)
79
+
80
+ raise ArgumentError,
81
+ "unknown anchor type: #{val.inspect}; " \
82
+ "must be one of #{Constants::ANCHOR_TYPES.inspect}"
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveAnchor
6
+ module Helpers
7
+ class AnchorEngine
8
+ def initialize
9
+ @anchors = {}
10
+ @chains = {}
11
+ end
12
+
13
+ def create_anchor(anchor_type:, domain:, content:,
14
+ reference_value: nil, grip: nil, weight: nil)
15
+ raise ArgumentError, 'anchor limit reached' if @anchors.size >= Constants::MAX_ANCHORS
16
+
17
+ a = Anchor.new(anchor_type: anchor_type, domain: domain, content: content,
18
+ reference_value: reference_value, grip: grip, weight: weight)
19
+ @anchors[a.id] = a
20
+ a
21
+ end
22
+
23
+ def create_chain(anchor_id:, material: :steel, length: nil, flexibility: nil)
24
+ raise ArgumentError, 'chain limit reached' if @chains.size >= Constants::MAX_CHAINS
25
+
26
+ fetch_anchor(anchor_id)
27
+ c = Chain.new(anchor_id: anchor_id, material: material,
28
+ length: length, flexibility: flexibility)
29
+ @chains[c.id] = c
30
+ c
31
+ end
32
+
33
+ def apply_bias(anchor_id:, new_value:)
34
+ anchor = fetch_anchor(anchor_id)
35
+ pulled = anchor.bias_pull(new_value.to_f)
36
+ { anchor: anchor, original: new_value.to_f, biased: pulled,
37
+ shift: (pulled - new_value.to_f).abs.round(10) }
38
+ end
39
+
40
+ def drag_anchor(anchor_id:, rate: Constants::DRAG_RATE)
41
+ anchor = fetch_anchor(anchor_id)
42
+ anchor.drag!(rate: rate)
43
+ anchor
44
+ end
45
+
46
+ def drift_all!
47
+ @anchors.each_value(&:drift!)
48
+ end
49
+
50
+ def wear_all_chains!
51
+ @chains.each_value(&:wear!)
52
+ end
53
+
54
+ def broken_chains
55
+ @chains.values.select(&:broken?)
56
+ end
57
+
58
+ def anchors_by_type
59
+ counts = Constants::ANCHOR_TYPES.to_h { |t| [t, 0] }
60
+ @anchors.each_value { |a| counts[a.anchor_type] += 1 }
61
+ counts
62
+ end
63
+
64
+ def strongest_anchors(limit: 5)
65
+ @anchors.values.sort_by { |a| -a.grip }.first(limit)
66
+ end
67
+
68
+ def weakest_anchors(limit: 5)
69
+ @anchors.values.sort_by(&:grip).first(limit)
70
+ end
71
+
72
+ def ironclad_anchors
73
+ @anchors.values.select(&:ironclad?)
74
+ end
75
+
76
+ def drifting_anchors
77
+ @anchors.values.select(&:drifting?)
78
+ end
79
+
80
+ def chains_for(anchor_id)
81
+ @chains.values.select { |c| c.anchor_id == anchor_id }
82
+ end
83
+
84
+ def avg_grip
85
+ return 0.0 if @anchors.empty?
86
+
87
+ (@anchors.values.sum(&:grip) / @anchors.size).round(10)
88
+ end
89
+
90
+ def anchor_report
91
+ {
92
+ total_anchors: @anchors.size,
93
+ total_chains: @chains.size,
94
+ by_type: anchors_by_type,
95
+ ironclad_count: ironclad_anchors.size,
96
+ drifting_count: drifting_anchors.size,
97
+ broken_chains: broken_chains.size,
98
+ avg_grip: avg_grip
99
+ }
100
+ end
101
+
102
+ def all_anchors
103
+ @anchors.values
104
+ end
105
+
106
+ def all_chains
107
+ @chains.values
108
+ end
109
+
110
+ private
111
+
112
+ def fetch_anchor(id)
113
+ @anchors.fetch(id) { raise ArgumentError, "anchor not found: #{id}" }
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveAnchor
6
+ module Helpers
7
+ class Chain
8
+ attr_reader :id, :anchor_id, :material, :created_at
9
+ attr_accessor :length, :flexibility
10
+
11
+ def initialize(anchor_id:, material: :steel, length: nil, flexibility: nil)
12
+ validate_material!(material)
13
+ @id = SecureRandom.uuid
14
+ @anchor_id = anchor_id
15
+ @material = material.to_sym
16
+ @length = (length || 0.5).to_f.clamp(0.0, 1.0).round(10)
17
+ @flexibility = (flexibility || material_flexibility).to_f.clamp(0.0, 1.0).round(10)
18
+ @created_at = Time.now.utc
19
+ end
20
+
21
+ def extend!(amount: 0.1)
22
+ @length = (@length + amount.abs).clamp(0.0, 1.0).round(10)
23
+ end
24
+
25
+ def shorten!(amount: 0.1)
26
+ @length = (@length - amount.abs).clamp(0.0, 1.0).round(10)
27
+ end
28
+
29
+ def wear!(rate: 0.05)
30
+ @flexibility = (@flexibility - rate.abs).clamp(0.0, 1.0).round(10)
31
+ end
32
+
33
+ def broken?
34
+ @flexibility < Constants::BREAK_THRESHOLD
35
+ end
36
+
37
+ def elastic?
38
+ @flexibility >= 0.8
39
+ end
40
+
41
+ def rigid?
42
+ @flexibility < 0.2
43
+ end
44
+
45
+ def short?
46
+ @length < 0.3
47
+ end
48
+
49
+ def long?
50
+ @length >= 0.7
51
+ end
52
+
53
+ def flexibility_label
54
+ Constants.label_for(Constants::FLEXIBILITY_LABELS, @flexibility)
55
+ end
56
+
57
+ def to_h
58
+ {
59
+ id: @id,
60
+ anchor_id: @anchor_id,
61
+ material: @material,
62
+ length: @length,
63
+ flexibility: @flexibility,
64
+ flexibility_label: flexibility_label,
65
+ broken: broken?,
66
+ elastic: elastic?,
67
+ created_at: @created_at
68
+ }
69
+ end
70
+
71
+ private
72
+
73
+ def validate_material!(val)
74
+ return if Constants::CHAIN_MATERIALS.include?(val.to_sym)
75
+
76
+ raise ArgumentError,
77
+ "unknown material: #{val.inspect}; " \
78
+ "must be one of #{Constants::CHAIN_MATERIALS.inspect}"
79
+ end
80
+
81
+ def material_flexibility
82
+ { steel: 0.3, rope: 0.6, wire: 0.4, thread: 0.8, cobweb: 0.9 }
83
+ .fetch(@material, 0.5)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveAnchor
6
+ module Helpers
7
+ module Constants
8
+ ANCHOR_TYPES = %i[belief assumption experience authority number].freeze
9
+
10
+ CHAIN_MATERIALS = %i[steel rope wire thread cobweb].freeze
11
+
12
+ MAX_ANCHORS = 200
13
+ MAX_CHAINS = 100
14
+ DRAG_RATE = 0.06
15
+ DRIFT_RATE = 0.03
16
+ BREAK_THRESHOLD = 0.1
17
+
18
+ GRIP_LABELS = [
19
+ [(0.8..), :ironclad],
20
+ [(0.6...0.8), :firm],
21
+ [(0.4...0.6), :moderate],
22
+ [(0.2...0.4), :loose],
23
+ [(..0.2), :drifting]
24
+ ].freeze
25
+
26
+ FLEXIBILITY_LABELS = [
27
+ [(0.8..), :elastic],
28
+ [(0.6...0.8), :flexible],
29
+ [(0.4...0.6), :moderate],
30
+ [(0.2...0.4), :rigid],
31
+ [(..0.2), :brittle]
32
+ ].freeze
33
+
34
+ def self.label_for(table, value)
35
+ table.each { |range, label| return label if range.cover?(value) }
36
+ table.last.last
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveAnchor
6
+ module Runners
7
+ module CognitiveAnchor
8
+ extend self
9
+
10
+ def create_anchor(anchor_type:, domain:, content:,
11
+ reference_value: nil, grip: nil, weight: nil, engine: nil, **)
12
+ eng = resolve_engine(engine)
13
+ a = eng.create_anchor(anchor_type: anchor_type, domain: domain, content: content,
14
+ reference_value: reference_value, grip: grip, weight: weight)
15
+ { success: true, anchor: a.to_h }
16
+ rescue ArgumentError => e
17
+ { success: false, error: e.message }
18
+ end
19
+
20
+ def create_chain(anchor_id:, material: :steel, length: nil,
21
+ flexibility: nil, engine: nil, **)
22
+ eng = resolve_engine(engine)
23
+ c = eng.create_chain(anchor_id: anchor_id, material: material,
24
+ length: length, flexibility: flexibility)
25
+ { success: true, chain: c.to_h }
26
+ rescue ArgumentError => e
27
+ { success: false, error: e.message }
28
+ end
29
+
30
+ def apply_bias(anchor_id:, new_value:, engine: nil, **)
31
+ eng = resolve_engine(engine)
32
+ result = eng.apply_bias(anchor_id: anchor_id, new_value: new_value)
33
+ { success: true, anchor: result[:anchor].to_h,
34
+ original: result[:original], biased: result[:biased], shift: result[:shift] }
35
+ rescue ArgumentError => e
36
+ { success: false, error: e.message }
37
+ end
38
+
39
+ def list_anchors(engine: nil, anchor_type: nil, **)
40
+ eng = resolve_engine(engine)
41
+ results = eng.all_anchors
42
+ results = results.select { |a| a.anchor_type == anchor_type.to_sym } if anchor_type
43
+ { success: true, anchors: results.map(&:to_h), count: results.size }
44
+ end
45
+
46
+ def anchor_status(engine: nil, **)
47
+ eng = resolve_engine(engine)
48
+ { success: true, report: eng.anchor_report }
49
+ end
50
+
51
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
52
+
53
+ private
54
+
55
+ def resolve_engine(engine)
56
+ engine || default_engine
57
+ end
58
+
59
+ def default_engine
60
+ @default_engine ||= Helpers::AnchorEngine.new
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module CognitiveAnchor
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_anchor/version'
6
+ require_relative 'cognitive_anchor/helpers/constants'
7
+ require_relative 'cognitive_anchor/helpers/anchor'
8
+ require_relative 'cognitive_anchor/helpers/chain'
9
+ require_relative 'cognitive_anchor/helpers/anchor_engine'
10
+ require_relative 'cognitive_anchor/runners/cognitive_anchor'
11
+ require_relative 'cognitive_anchor/client'
12
+
13
+ module Legion
14
+ module Extensions
15
+ module CognitiveAnchor
16
+ extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lex-cognitive-anchor
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 anchoring biases where fixed reference points pull new information
27
+ toward them with configurable grip, weight, and chain flexibility
28
+ email:
29
+ - matthewdiverson@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".rspec"
35
+ - CLAUDE.md
36
+ - README.md
37
+ - lex-cognitive-anchor.gemspec
38
+ - lib/legion/extensions/cognitive_anchor.rb
39
+ - lib/legion/extensions/cognitive_anchor/client.rb
40
+ - lib/legion/extensions/cognitive_anchor/helpers/anchor.rb
41
+ - lib/legion/extensions/cognitive_anchor/helpers/anchor_engine.rb
42
+ - lib/legion/extensions/cognitive_anchor/helpers/chain.rb
43
+ - lib/legion/extensions/cognitive_anchor/helpers/constants.rb
44
+ - lib/legion/extensions/cognitive_anchor/runners/cognitive_anchor.rb
45
+ - lib/legion/extensions/cognitive_anchor/version.rb
46
+ homepage: https://github.com/LegionIO/lex-cognitive-anchor
47
+ licenses:
48
+ - MIT
49
+ metadata:
50
+ homepage_uri: https://github.com/LegionIO/lex-cognitive-anchor
51
+ source_code_uri: https://github.com/LegionIO/lex-cognitive-anchor
52
+ documentation_uri: https://github.com/LegionIO/lex-cognitive-anchor/blob/master/README.md
53
+ changelog_uri: https://github.com/LegionIO/lex-cognitive-anchor/blob/master/CHANGELOG.md
54
+ bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-anchor/issues
55
+ rubygems_mfa_required: 'true'
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '3.4'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubygems_version: 3.6.9
71
+ specification_version: 4
72
+ summary: Cognitive anchoring bias dynamics for LegionIO agentic architecture
73
+ test_files: []