lex-cognitive-magnet 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.rubocop.yml +64 -0
- data/CLAUDE.md +116 -0
- data/Gemfile +11 -0
- data/README.md +51 -0
- data/lex-cognitive-magnet.gemspec +27 -0
- data/lib/legion/extensions/cognitive_magnet/client.rb +25 -0
- data/lib/legion/extensions/cognitive_magnet/helpers/constants.rb +53 -0
- data/lib/legion/extensions/cognitive_magnet/helpers/field.rb +101 -0
- data/lib/legion/extensions/cognitive_magnet/helpers/magnet_engine.rb +175 -0
- data/lib/legion/extensions/cognitive_magnet/helpers/pole.rb +76 -0
- data/lib/legion/extensions/cognitive_magnet/runners/cognitive_magnet.rb +120 -0
- data/lib/legion/extensions/cognitive_magnet/version.rb +9 -0
- data/lib/legion/extensions/cognitive_magnet.rb +18 -0
- metadata +77 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8878597a795cca69e3919ff364db407c2a96b322271ec9929669f9a4ccfbd75b
|
|
4
|
+
data.tar.gz: 8ca1026de6ed94260b07e084e502a0c6a876dbecc893a3c78824c36b288b528b
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: cedc41cdfaec14b72dc6987cf68c2de9b7c2154483b8d50c59d34db2434348c5032e315dd05005a413c17c2de8f8b2dd0f2fc9921532afa8676aa61fa9ad0e57
|
|
7
|
+
data.tar.gz: 2edad7d627afaec664d81211115566f5bc90ae00f3e2872f961ee8301bc34ef813fe833dce63cdbbbe87c2d1a0e919c87c79f5cc3729b8499422b1d04f812e49
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
10
|
+
|
|
11
|
+
release:
|
|
12
|
+
needs: ci
|
|
13
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
14
|
+
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
15
|
+
secrets:
|
|
16
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,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: 1500
|
|
24
|
+
|
|
25
|
+
Metrics/BlockLength:
|
|
26
|
+
Max: 40
|
|
27
|
+
Exclude:
|
|
28
|
+
- 'spec/**/*'
|
|
29
|
+
|
|
30
|
+
Metrics/AbcSize:
|
|
31
|
+
Max: 25
|
|
32
|
+
|
|
33
|
+
Metrics/ParameterLists:
|
|
34
|
+
Max: 8
|
|
35
|
+
MaxOptionalParameters: 8
|
|
36
|
+
|
|
37
|
+
Metrics/CyclomaticComplexity:
|
|
38
|
+
Max: 15
|
|
39
|
+
|
|
40
|
+
Metrics/PerceivedComplexity:
|
|
41
|
+
Max: 17
|
|
42
|
+
|
|
43
|
+
Style/Documentation:
|
|
44
|
+
Enabled: false
|
|
45
|
+
|
|
46
|
+
Style/SymbolArray:
|
|
47
|
+
Enabled: true
|
|
48
|
+
|
|
49
|
+
Style/FrozenStringLiteralComment:
|
|
50
|
+
Enabled: true
|
|
51
|
+
EnforcedStyle: always
|
|
52
|
+
|
|
53
|
+
Style/OneClassPerFile:
|
|
54
|
+
Exclude:
|
|
55
|
+
- 'spec/spec_helper.rb'
|
|
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,116 @@
|
|
|
1
|
+
# lex-cognitive-magnet
|
|
2
|
+
|
|
3
|
+
**Level 3 Leaf Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Magnetic field metaphor for cognitive attraction and repulsion. Poles represent cognitive elements with a polarity (positive, negative, neutral, bipolar) and a material type. When poles interact, attraction strengthens both; repulsion weakens both. Fields group poles and compute alignment scores via pair-wise interaction analysis. Models how ideas, beliefs, or preferences cluster and conflict in cognitive space.
|
|
9
|
+
|
|
10
|
+
## Gem Info
|
|
11
|
+
|
|
12
|
+
- **Gem name**: `lex-cognitive-magnet`
|
|
13
|
+
- **Module**: `Legion::Extensions::CognitiveMagnet`
|
|
14
|
+
- **Version**: `0.1.0`
|
|
15
|
+
- **Ruby**: `>= 3.4`
|
|
16
|
+
- **License**: MIT
|
|
17
|
+
|
|
18
|
+
## File Structure
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
lib/legion/extensions/cognitive_magnet/
|
|
22
|
+
version.rb
|
|
23
|
+
client.rb
|
|
24
|
+
helpers/
|
|
25
|
+
constants.rb
|
|
26
|
+
pole.rb
|
|
27
|
+
field.rb
|
|
28
|
+
magnet_engine.rb
|
|
29
|
+
runners/
|
|
30
|
+
cognitive_magnet.rb
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Key Constants
|
|
34
|
+
|
|
35
|
+
| Constant | Value | Purpose |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `POLARITY_TYPES` | `%i[positive negative neutral bipolar]` | Valid pole polarity values |
|
|
38
|
+
| `MATERIAL_TYPES` | `%i[iron cobalt nickel lodestone ferrite]` | Valid material types |
|
|
39
|
+
| `MAX_POLES` | `500` | Per-engine pole capacity |
|
|
40
|
+
| `MAX_FIELDS` | `50` | Per-engine field capacity |
|
|
41
|
+
| `ATTRACTION_RATE` | `0.08` | Base strength increase per attraction interaction |
|
|
42
|
+
| `REPULSION_RATE` | `0.06` | Base strength decrease per repulsion interaction |
|
|
43
|
+
| `DECAY_RATE` | `0.02` | Default strength reduction per demagnetize cycle |
|
|
44
|
+
| `STRENGTH_LABELS` | range hash | From `:negligible` to `:overwhelming` |
|
|
45
|
+
| `ALIGNMENT_LABELS` | range hash | From `:chaotic` to `:perfect` |
|
|
46
|
+
|
|
47
|
+
## Helpers
|
|
48
|
+
|
|
49
|
+
### `Helpers::Pole`
|
|
50
|
+
Individual magnetic pole. Has `id`, `polarity`, `strength` (0.0–1.0), `material_type`, `domain`, `content`, and `created_at`.
|
|
51
|
+
|
|
52
|
+
- `magnetize!(rate)` — increases strength by rate
|
|
53
|
+
- `demagnetize!(rate)` — decreases strength by rate
|
|
54
|
+
- `attracts?(other_pole)` — true if polarities are opposite; always true for `:bipolar`, always false for `:neutral`
|
|
55
|
+
- `repels?(other_pole)` — true if polarities match; always false for `:neutral` or `:bipolar`
|
|
56
|
+
- `saturated?` — strength >= 1.0
|
|
57
|
+
- `weak?` — strength <= 0.1
|
|
58
|
+
- `strength_label`
|
|
59
|
+
- `to_h`
|
|
60
|
+
|
|
61
|
+
### `Helpers::Field`
|
|
62
|
+
Named container for poles. Has `id`, `name`, `pole_ids`, `alignment`, and `flux_density`.
|
|
63
|
+
|
|
64
|
+
- `add_pole(pole_id)` — adds pole ID (idempotent)
|
|
65
|
+
- `remove_pole(pole_id)` — removes pole ID
|
|
66
|
+
- `calculate_alignment!(poles)` — pair-wise computation: attraction pairs add `(a.strength + b.strength) / 2.0`, repulsion pairs subtract half that weight; result normalized to [0.0, 1.0]
|
|
67
|
+
- `coherent?` — alignment >= 0.6
|
|
68
|
+
- `chaotic?` — alignment < 0.2
|
|
69
|
+
- `alignment_label`
|
|
70
|
+
- `pole_count`
|
|
71
|
+
- `to_h`
|
|
72
|
+
|
|
73
|
+
### `Helpers::MagnetEngine`
|
|
74
|
+
Top-level store. Enforces `MAX_POLES` and `MAX_FIELDS`.
|
|
75
|
+
|
|
76
|
+
- `create_pole(polarity:, content:, strength:, material_type:, domain:)` → pole or capacity error
|
|
77
|
+
- `create_field(name:)` → field or capacity error
|
|
78
|
+
- `magnetize(pole_id, rate:)` → strength hash
|
|
79
|
+
- `interact(pole_a_id, pole_b_id)` — mutual magnetize/demagnetize based on attraction/repulsion; logs interaction event
|
|
80
|
+
- `demagnetize_all!(rate:)` → count hash
|
|
81
|
+
- `most_aligned_fields(limit:)` → top N fields by alignment (recalculates before sort)
|
|
82
|
+
- `strongest_poles(limit:)` → top N poles by strength (excludes weak poles)
|
|
83
|
+
- `field_report` → aggregate stats including coherent/chaotic field counts
|
|
84
|
+
- `add_pole_to_field(field_id:, pole_id:)` → status hash
|
|
85
|
+
- `remove_pole_from_field(field_id:, pole_id:)` → status hash
|
|
86
|
+
|
|
87
|
+
## Runners
|
|
88
|
+
|
|
89
|
+
Module: `Runners::CognitiveMagnet`
|
|
90
|
+
|
|
91
|
+
| Runner Method | Description |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `create_pole(polarity:, content:, strength:, material_type:, domain:)` | Register a new pole |
|
|
94
|
+
| `create_field(name:)` | Create a field |
|
|
95
|
+
| `magnetize(pole_id:, rate:)` | Strengthen a pole |
|
|
96
|
+
| `interact(pole_a_id:, pole_b_id:)` | Trigger mutual interaction |
|
|
97
|
+
| `list_poles(limit:)` | Strongest poles |
|
|
98
|
+
| `magnetic_status` | Full field report |
|
|
99
|
+
|
|
100
|
+
All runners return `{success: true/false, ...}` hashes.
|
|
101
|
+
|
|
102
|
+
## Integration Points
|
|
103
|
+
|
|
104
|
+
- No direct dependencies on other agentic LEX gems
|
|
105
|
+
- Fields with high coherence represent stable belief clusters; can feed `lex-emotion` valence
|
|
106
|
+
- Repulsion events between poles can register as `lex-conflict` conflicts
|
|
107
|
+
- `interact` drives organic reinforcement and weakening as ideas encounter each other in `lex-tick` cycles
|
|
108
|
+
- Chaotic fields (low alignment) can trigger `lex-prediction` uncertainty signals
|
|
109
|
+
|
|
110
|
+
## Development Notes
|
|
111
|
+
|
|
112
|
+
- `Client` instantiates `@magnet_engine = Helpers::MagnetEngine.new`
|
|
113
|
+
- `attract?` / `repels?` are asymmetric: `:bipolar` always attracts any polarity, `:neutral` never attracts or repels
|
|
114
|
+
- `interact` logs to `@interaction_log` (unbounded array — callers should periodically prune for long-running sessions)
|
|
115
|
+
- `most_aligned_fields` calls `recalculate_all_fields` before sorting — this is O(fields * poles^2/2) pairs
|
|
116
|
+
- Alignment formula maps raw weighted average to [0.0, 1.0] via `(raw + 1.0) / 2.0`
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# lex-cognitive-magnet
|
|
2
|
+
|
|
3
|
+
Magnetic field metaphor for cognitive attraction and repulsion in LegionIO agents. Poles represent ideas or beliefs with polarities; interacting poles strengthen or weaken each other; fields group poles and measure their collective alignment.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
- Four polarity types: `positive`, `negative`, `neutral`, `bipolar`
|
|
8
|
+
- Five material types: `iron`, `cobalt`, `nickel`, `lodestone`, `ferrite`
|
|
9
|
+
- Attraction: opposite polarities strengthen each other on interaction
|
|
10
|
+
- Repulsion: matching polarities weaken each other on interaction
|
|
11
|
+
- `bipolar` attracts everything; `neutral` never attracts or repels
|
|
12
|
+
- Fields group poles and compute alignment via pair-wise strength-weighted analysis
|
|
13
|
+
- Coherent fields (alignment >= 0.6) and chaotic fields (< 0.2) are classified
|
|
14
|
+
- `demagnetize_all` provides a global decay cycle
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
# Create poles
|
|
20
|
+
a = runner.create_pole(polarity: :positive, content: 'hypothesis_A',
|
|
21
|
+
strength: 0.6, material_type: :iron, domain: :reasoning)
|
|
22
|
+
b = runner.create_pole(polarity: :negative, content: 'counter_hypothesis',
|
|
23
|
+
strength: 0.5, material_type: :iron, domain: :reasoning)
|
|
24
|
+
|
|
25
|
+
# Interact — opposite polarities attract, both strengthen
|
|
26
|
+
runner.interact(pole_a_id: a[:pole][:id], pole_b_id: b[:pole][:id])
|
|
27
|
+
# => { type: :attraction, force: 0.3, ... }
|
|
28
|
+
|
|
29
|
+
# Create a field and add poles
|
|
30
|
+
field = runner.create_field(name: 'reasoning_cluster')
|
|
31
|
+
# (add poles to field via engine directly or via future runner method)
|
|
32
|
+
|
|
33
|
+
# Status
|
|
34
|
+
runner.magnetic_status
|
|
35
|
+
# => { success: true, total_poles: 2, coherent_fields: 0, chaotic_fields: 0, ... }
|
|
36
|
+
|
|
37
|
+
# Strongest poles
|
|
38
|
+
runner.list_poles(limit: 5)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Development
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bundle install
|
|
45
|
+
bundle exec rspec
|
|
46
|
+
bundle exec rubocop
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## License
|
|
50
|
+
|
|
51
|
+
MIT
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_magnet/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-magnet'
|
|
7
|
+
spec.version = Legion::Extensions::CognitiveMagnet::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'LEX Cognitive Magnet'
|
|
12
|
+
spec.description = 'Magnetic attraction and repulsion between ideas — polarity-driven cognitive clustering for LegionIO agentic AI'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-magnet'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-cognitive-magnet'
|
|
19
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-magnet'
|
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-magnet'
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-magnet/issues'
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
|
+
|
|
24
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.start_with?('spec/') }
|
|
25
|
+
spec.require_paths = ['lib']
|
|
26
|
+
spec.add_development_dependency 'legion-gaia'
|
|
27
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/cognitive_magnet/helpers/constants'
|
|
4
|
+
require 'legion/extensions/cognitive_magnet/helpers/pole'
|
|
5
|
+
require 'legion/extensions/cognitive_magnet/helpers/field'
|
|
6
|
+
require 'legion/extensions/cognitive_magnet/helpers/magnet_engine'
|
|
7
|
+
require 'legion/extensions/cognitive_magnet/runners/cognitive_magnet'
|
|
8
|
+
|
|
9
|
+
module Legion
|
|
10
|
+
module Extensions
|
|
11
|
+
module CognitiveMagnet
|
|
12
|
+
class Client
|
|
13
|
+
include Runners::CognitiveMagnet
|
|
14
|
+
|
|
15
|
+
def initialize(**)
|
|
16
|
+
@magnet_engine = Helpers::MagnetEngine.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
attr_reader :magnet_engine
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveMagnet
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
POLARITY_TYPES = %i[positive negative neutral bipolar].freeze
|
|
9
|
+
MATERIAL_TYPES = %i[iron cobalt nickel lodestone ferrite].freeze
|
|
10
|
+
MAX_POLES = 500
|
|
11
|
+
MAX_FIELDS = 50
|
|
12
|
+
ATTRACTION_RATE = 0.08
|
|
13
|
+
REPULSION_RATE = 0.06
|
|
14
|
+
DECAY_RATE = 0.02
|
|
15
|
+
|
|
16
|
+
STRENGTH_LABELS = {
|
|
17
|
+
(0.0..0.1) => :negligible,
|
|
18
|
+
(0.1..0.3) => :faint,
|
|
19
|
+
(0.3..0.5) => :moderate,
|
|
20
|
+
(0.5..0.7) => :strong,
|
|
21
|
+
(0.7..0.9) => :intense,
|
|
22
|
+
(0.9..1.0) => :overwhelming
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
ALIGNMENT_LABELS = {
|
|
26
|
+
(0.0..0.2) => :chaotic,
|
|
27
|
+
(0.2..0.4) => :discordant,
|
|
28
|
+
(0.4..0.6) => :neutral,
|
|
29
|
+
(0.6..0.8) => :coherent,
|
|
30
|
+
(0.8..1.0) => :perfect
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
module_function
|
|
34
|
+
|
|
35
|
+
def label_for(table, value)
|
|
36
|
+
table.each do |range, label|
|
|
37
|
+
return label if range.cover?(value)
|
|
38
|
+
end
|
|
39
|
+
:unknown
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def valid_polarity?(polarity)
|
|
43
|
+
POLARITY_TYPES.include?(polarity)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def valid_material?(material)
|
|
47
|
+
MATERIAL_TYPES.include?(material)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveMagnet
|
|
8
|
+
module Helpers
|
|
9
|
+
class Field
|
|
10
|
+
attr_reader :id, :name, :pole_ids, :alignment, :flux_density, :created_at
|
|
11
|
+
|
|
12
|
+
def initialize(name:)
|
|
13
|
+
@id = SecureRandom.uuid
|
|
14
|
+
@name = name
|
|
15
|
+
@pole_ids = []
|
|
16
|
+
@alignment = 0.0
|
|
17
|
+
@flux_density = 0.0
|
|
18
|
+
@created_at = Time.now.utc
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_pole(pole_id)
|
|
22
|
+
return false if @pole_ids.include?(pole_id)
|
|
23
|
+
|
|
24
|
+
@pole_ids << pole_id
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def remove_pole(pole_id)
|
|
29
|
+
removed = @pole_ids.delete(pole_id)
|
|
30
|
+
!removed.nil?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def calculate_alignment!(poles)
|
|
34
|
+
field_poles = poles.values.select { |p| @pole_ids.include?(p.id) }
|
|
35
|
+
return self if field_poles.empty?
|
|
36
|
+
|
|
37
|
+
@flux_density = field_poles.sum(&:strength) / field_poles.size.to_f
|
|
38
|
+
@alignment = compute_alignment(field_poles).round(10)
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def coherent?
|
|
43
|
+
@alignment >= 0.6
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def chaotic?
|
|
47
|
+
@alignment < 0.2
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def alignment_label
|
|
51
|
+
Constants.label_for(Constants::ALIGNMENT_LABELS, @alignment)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def pole_count
|
|
55
|
+
@pole_ids.size
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_h
|
|
59
|
+
{
|
|
60
|
+
id: @id,
|
|
61
|
+
name: @name,
|
|
62
|
+
pole_ids: @pole_ids.dup,
|
|
63
|
+
alignment: @alignment,
|
|
64
|
+
flux_density: @flux_density,
|
|
65
|
+
pole_count: pole_count,
|
|
66
|
+
coherent: coherent?,
|
|
67
|
+
chaotic: chaotic?,
|
|
68
|
+
alignment_label: alignment_label,
|
|
69
|
+
created_at: @created_at
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def compute_alignment(field_poles)
|
|
76
|
+
return 0.0 if field_poles.size < 2
|
|
77
|
+
|
|
78
|
+
total_pairs = 0
|
|
79
|
+
aligned_weight = 0.0
|
|
80
|
+
|
|
81
|
+
field_poles.combination(2) do |a, b|
|
|
82
|
+
total_pairs += 1
|
|
83
|
+
pair_weight = (a.strength + b.strength) / 2.0
|
|
84
|
+
|
|
85
|
+
if a.attracts?(b)
|
|
86
|
+
aligned_weight += pair_weight
|
|
87
|
+
elsif a.repels?(b)
|
|
88
|
+
aligned_weight -= pair_weight * 0.5
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
return 0.5 if total_pairs.zero?
|
|
93
|
+
|
|
94
|
+
raw = aligned_weight / total_pairs.to_f
|
|
95
|
+
((raw + 1.0) / 2.0).clamp(0.0, 1.0)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveMagnet
|
|
6
|
+
module Helpers
|
|
7
|
+
class MagnetEngine
|
|
8
|
+
attr_reader :poles, :fields, :interaction_log
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@poles = {}
|
|
12
|
+
@fields = {}
|
|
13
|
+
@interaction_log = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create_pole(polarity:, content:, strength: 0.5, material_type: :iron, domain: :general)
|
|
17
|
+
return { error: :capacity_exceeded, max: Constants::MAX_POLES } if at_pole_capacity?
|
|
18
|
+
|
|
19
|
+
pole = Pole.new(
|
|
20
|
+
polarity: polarity,
|
|
21
|
+
content: content,
|
|
22
|
+
strength: strength,
|
|
23
|
+
material_type: material_type,
|
|
24
|
+
domain: domain
|
|
25
|
+
)
|
|
26
|
+
@poles[pole.id] = pole
|
|
27
|
+
pole
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def create_field(name:)
|
|
31
|
+
return { error: :capacity_exceeded, max: Constants::MAX_FIELDS } if at_field_capacity?
|
|
32
|
+
|
|
33
|
+
field = Field.new(name: name)
|
|
34
|
+
@fields[field.id] = field
|
|
35
|
+
field
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def magnetize(pole_id, rate: Constants::ATTRACTION_RATE)
|
|
39
|
+
pole = @poles[pole_id]
|
|
40
|
+
return { error: :not_found } unless pole
|
|
41
|
+
|
|
42
|
+
pole.magnetize!(rate)
|
|
43
|
+
{ magnetized: true, id: pole_id, strength: pole.strength }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def interact(pole_a_id, pole_b_id)
|
|
47
|
+
pole_a = @poles[pole_a_id]
|
|
48
|
+
pole_b = @poles[pole_b_id]
|
|
49
|
+
return { error: :pole_a_not_found } unless pole_a
|
|
50
|
+
return { error: :pole_b_not_found } unless pole_b
|
|
51
|
+
return { error: :same_pole } if pole_a_id == pole_b_id
|
|
52
|
+
|
|
53
|
+
force = compute_force(pole_a, pole_b)
|
|
54
|
+
type = determine_interaction_type(pole_a, pole_b)
|
|
55
|
+
|
|
56
|
+
apply_interaction(pole_a, pole_b, type)
|
|
57
|
+
|
|
58
|
+
event = build_interaction_event(pole_a, pole_b, type, force)
|
|
59
|
+
@interaction_log << event
|
|
60
|
+
event
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def demagnetize_all!(rate: Constants::DECAY_RATE)
|
|
64
|
+
count = 0
|
|
65
|
+
@poles.each_value do |pole|
|
|
66
|
+
pole.demagnetize!(rate)
|
|
67
|
+
count += 1
|
|
68
|
+
end
|
|
69
|
+
{ demagnetized: count, rate: rate }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def most_aligned_fields(limit: 5)
|
|
73
|
+
recalculate_all_fields
|
|
74
|
+
@fields.values
|
|
75
|
+
.sort_by { |f| -f.alignment }
|
|
76
|
+
.first(limit)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def strongest_poles(limit: 5)
|
|
80
|
+
@poles.values
|
|
81
|
+
.reject(&:weak?)
|
|
82
|
+
.sort_by { |p| -p.strength }
|
|
83
|
+
.first(limit)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def field_report
|
|
87
|
+
recalculate_all_fields
|
|
88
|
+
coherent = @fields.values.select(&:coherent?)
|
|
89
|
+
chaotic = @fields.values.select(&:chaotic?)
|
|
90
|
+
saturated = @poles.values.select(&:saturated?)
|
|
91
|
+
weak = @poles.values.select(&:weak?)
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
total_poles: @poles.size,
|
|
95
|
+
total_fields: @fields.size,
|
|
96
|
+
coherent_fields: coherent.size,
|
|
97
|
+
chaotic_fields: chaotic.size,
|
|
98
|
+
saturated_poles: saturated.size,
|
|
99
|
+
weak_poles: weak.size,
|
|
100
|
+
total_interactions: @interaction_log.size,
|
|
101
|
+
strongest: strongest_poles(limit: 3).map(&:to_h),
|
|
102
|
+
top_fields: most_aligned_fields(limit: 3).map(&:to_h)
|
|
103
|
+
}
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def add_pole_to_field(field_id:, pole_id:)
|
|
107
|
+
field = @fields[field_id]
|
|
108
|
+
return { error: :field_not_found } unless field
|
|
109
|
+
return { error: :pole_not_found } unless @poles[pole_id]
|
|
110
|
+
|
|
111
|
+
added = field.add_pole(pole_id)
|
|
112
|
+
{ added: added, field_id: field_id, pole_id: pole_id }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def remove_pole_from_field(field_id:, pole_id:)
|
|
116
|
+
field = @fields[field_id]
|
|
117
|
+
return { error: :field_not_found } unless field
|
|
118
|
+
|
|
119
|
+
removed = field.remove_pole(pole_id)
|
|
120
|
+
{ removed: removed, field_id: field_id, pole_id: pole_id }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
def at_pole_capacity?
|
|
126
|
+
@poles.size >= Constants::MAX_POLES
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def at_field_capacity?
|
|
130
|
+
@fields.size >= Constants::MAX_FIELDS
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def compute_force(pole_a, pole_b)
|
|
134
|
+
(pole_a.strength * pole_b.strength).round(10)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def determine_interaction_type(pole_a, pole_b)
|
|
138
|
+
if pole_a.attracts?(pole_b)
|
|
139
|
+
:attraction
|
|
140
|
+
elsif pole_a.repels?(pole_b)
|
|
141
|
+
:repulsion
|
|
142
|
+
else
|
|
143
|
+
:neutral
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def apply_interaction(pole_a, pole_b, type)
|
|
148
|
+
case type
|
|
149
|
+
when :attraction
|
|
150
|
+
pole_a.magnetize!(Constants::ATTRACTION_RATE * pole_b.strength)
|
|
151
|
+
pole_b.magnetize!(Constants::ATTRACTION_RATE * pole_a.strength)
|
|
152
|
+
when :repulsion
|
|
153
|
+
pole_a.demagnetize!(Constants::REPULSION_RATE * pole_b.strength)
|
|
154
|
+
pole_b.demagnetize!(Constants::REPULSION_RATE * pole_a.strength)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def build_interaction_event(pole_a, pole_b, type, force)
|
|
159
|
+
{
|
|
160
|
+
type: type,
|
|
161
|
+
pole_a_id: pole_a.id,
|
|
162
|
+
pole_b_id: pole_b.id,
|
|
163
|
+
force: force,
|
|
164
|
+
at: Time.now.utc
|
|
165
|
+
}
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def recalculate_all_fields
|
|
169
|
+
@fields.each_value { |f| f.calculate_alignment!(@poles) }
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveMagnet
|
|
8
|
+
module Helpers
|
|
9
|
+
class Pole
|
|
10
|
+
attr_reader :id, :polarity, :strength, :material_type, :domain, :content, :created_at
|
|
11
|
+
|
|
12
|
+
def initialize(polarity:, content:, strength: 0.5, material_type: :iron, domain: :general)
|
|
13
|
+
@id = SecureRandom.uuid
|
|
14
|
+
@polarity = polarity
|
|
15
|
+
@content = content
|
|
16
|
+
@strength = strength.to_f.clamp(0.0, 1.0).round(10)
|
|
17
|
+
@material_type = material_type
|
|
18
|
+
@domain = domain
|
|
19
|
+
@created_at = Time.now.utc
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def magnetize!(rate = Constants::ATTRACTION_RATE)
|
|
23
|
+
@strength = (@strength + rate.to_f).clamp(0.0, 1.0).round(10)
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def demagnetize!(rate = Constants::DECAY_RATE)
|
|
28
|
+
@strength = (@strength - rate.to_f).clamp(0.0, 1.0).round(10)
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def attracts?(other_pole)
|
|
33
|
+
return false if @polarity == :neutral || other_pole.polarity == :neutral
|
|
34
|
+
return true if @polarity == :bipolar || other_pole.polarity == :bipolar
|
|
35
|
+
|
|
36
|
+
@polarity != other_pole.polarity
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def repels?(other_pole)
|
|
40
|
+
return false if @polarity == :neutral || other_pole.polarity == :neutral
|
|
41
|
+
return false if @polarity == :bipolar || other_pole.polarity == :bipolar
|
|
42
|
+
|
|
43
|
+
@polarity == other_pole.polarity
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def saturated?
|
|
47
|
+
@strength >= 1.0
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def weak?
|
|
51
|
+
@strength <= 0.1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def strength_label
|
|
55
|
+
Constants.label_for(Constants::STRENGTH_LABELS, @strength)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_h
|
|
59
|
+
{
|
|
60
|
+
id: @id,
|
|
61
|
+
polarity: @polarity,
|
|
62
|
+
strength: @strength,
|
|
63
|
+
material_type: @material_type,
|
|
64
|
+
domain: @domain,
|
|
65
|
+
content: @content,
|
|
66
|
+
saturated: saturated?,
|
|
67
|
+
weak: weak?,
|
|
68
|
+
strength_label: strength_label,
|
|
69
|
+
created_at: @created_at
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveMagnet
|
|
6
|
+
module Runners
|
|
7
|
+
module CognitiveMagnet
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
9
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
|
|
11
|
+
extend self
|
|
12
|
+
|
|
13
|
+
def create_pole(polarity:, content:, strength: 0.5, material_type: :iron,
|
|
14
|
+
domain: :general, engine: nil, **)
|
|
15
|
+
unless Helpers::Constants.valid_polarity?(polarity)
|
|
16
|
+
return { success: false, error: :invalid_polarity,
|
|
17
|
+
valid_polarities: Helpers::Constants::POLARITY_TYPES }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
unless Helpers::Constants.valid_material?(material_type)
|
|
21
|
+
return { success: false, error: :invalid_material,
|
|
22
|
+
valid_materials: Helpers::Constants::MATERIAL_TYPES }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
eng = engine || magnet_engine
|
|
26
|
+
result = eng.create_pole(
|
|
27
|
+
polarity: polarity,
|
|
28
|
+
content: content,
|
|
29
|
+
strength: strength,
|
|
30
|
+
material_type: material_type,
|
|
31
|
+
domain: domain
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if result.is_a?(Hash) && result[:error]
|
|
35
|
+
Legion::Logging.warn "[cognitive_magnet] create_pole failed: #{result[:error]}"
|
|
36
|
+
return { success: false, **result }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
Legion::Logging.debug "[cognitive_magnet] pole created id=#{result.id[0..7]} " \
|
|
40
|
+
"polarity=#{polarity} strength=#{strength}"
|
|
41
|
+
{ success: true, pole: result.to_h }
|
|
42
|
+
rescue ArgumentError => e
|
|
43
|
+
{ success: false, error: :argument_error, message: e.message }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def create_field(name:, engine: nil, **)
|
|
47
|
+
eng = engine || magnet_engine
|
|
48
|
+
result = eng.create_field(name: name)
|
|
49
|
+
|
|
50
|
+
if result.is_a?(Hash) && result[:error]
|
|
51
|
+
Legion::Logging.warn "[cognitive_magnet] create_field failed: #{result[:error]}"
|
|
52
|
+
return { success: false, **result }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Legion::Logging.debug "[cognitive_magnet] field created id=#{result.id[0..7]} name=#{name}"
|
|
56
|
+
{ success: true, field: result.to_h }
|
|
57
|
+
rescue ArgumentError => e
|
|
58
|
+
{ success: false, error: :argument_error, message: e.message }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def magnetize(pole_id:, rate: Helpers::Constants::ATTRACTION_RATE, engine: nil, **)
|
|
62
|
+
eng = engine || magnet_engine
|
|
63
|
+
result = eng.magnetize(pole_id, rate: rate)
|
|
64
|
+
|
|
65
|
+
if result[:error]
|
|
66
|
+
Legion::Logging.warn "[cognitive_magnet] magnetize failed: #{result[:error]}"
|
|
67
|
+
return { success: false, **result }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
Legion::Logging.debug "[cognitive_magnet] magnetized id=#{pole_id[0..7]} strength=#{result[:strength]}"
|
|
71
|
+
{ success: true, **result }
|
|
72
|
+
rescue ArgumentError => e
|
|
73
|
+
{ success: false, error: :argument_error, message: e.message }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def interact(pole_a_id:, pole_b_id:, engine: nil, **)
|
|
77
|
+
eng = engine || magnet_engine
|
|
78
|
+
result = eng.interact(pole_a_id, pole_b_id)
|
|
79
|
+
|
|
80
|
+
if result[:error]
|
|
81
|
+
Legion::Logging.warn "[cognitive_magnet] interact failed: #{result[:error]}"
|
|
82
|
+
return { success: false, **result }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
Legion::Logging.debug "[cognitive_magnet] interaction type=#{result[:type]} " \
|
|
86
|
+
"force=#{result[:force].round(4)}"
|
|
87
|
+
{ success: true, **result }
|
|
88
|
+
rescue ArgumentError => e
|
|
89
|
+
{ success: false, error: :argument_error, message: e.message }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def list_poles(engine: nil, limit: 50, **)
|
|
93
|
+
eng = engine || magnet_engine
|
|
94
|
+
poles = eng.poles.values.first(limit).map(&:to_h)
|
|
95
|
+
Legion::Logging.debug "[cognitive_magnet] list_poles count=#{poles.size}"
|
|
96
|
+
{ success: true, poles: poles, count: poles.size }
|
|
97
|
+
rescue ArgumentError => e
|
|
98
|
+
{ success: false, error: :argument_error, message: e.message }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def magnetic_status(engine: nil, **)
|
|
102
|
+
eng = engine || magnet_engine
|
|
103
|
+
report = eng.field_report
|
|
104
|
+
Legion::Logging.debug "[cognitive_magnet] status: poles=#{report[:total_poles]} " \
|
|
105
|
+
"fields=#{report[:total_fields]} interactions=#{report[:total_interactions]}"
|
|
106
|
+
{ success: true, report: report }
|
|
107
|
+
rescue ArgumentError => e
|
|
108
|
+
{ success: false, error: :argument_error, message: e.message }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def magnet_engine
|
|
114
|
+
@magnet_engine ||= Helpers::MagnetEngine.new
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
require 'legion/extensions/cognitive_magnet/version'
|
|
5
|
+
require 'legion/extensions/cognitive_magnet/helpers/constants'
|
|
6
|
+
require 'legion/extensions/cognitive_magnet/helpers/pole'
|
|
7
|
+
require 'legion/extensions/cognitive_magnet/helpers/field'
|
|
8
|
+
require 'legion/extensions/cognitive_magnet/helpers/magnet_engine'
|
|
9
|
+
require 'legion/extensions/cognitive_magnet/runners/cognitive_magnet'
|
|
10
|
+
require 'legion/extensions/cognitive_magnet/client'
|
|
11
|
+
|
|
12
|
+
module Legion
|
|
13
|
+
module Extensions
|
|
14
|
+
module CognitiveMagnet
|
|
15
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-cognitive-magnet
|
|
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: Magnetic attraction and repulsion between ideas — polarity-driven cognitive
|
|
27
|
+
clustering for LegionIO agentic AI
|
|
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-magnet.gemspec
|
|
42
|
+
- lib/legion/extensions/cognitive_magnet.rb
|
|
43
|
+
- lib/legion/extensions/cognitive_magnet/client.rb
|
|
44
|
+
- lib/legion/extensions/cognitive_magnet/helpers/constants.rb
|
|
45
|
+
- lib/legion/extensions/cognitive_magnet/helpers/field.rb
|
|
46
|
+
- lib/legion/extensions/cognitive_magnet/helpers/magnet_engine.rb
|
|
47
|
+
- lib/legion/extensions/cognitive_magnet/helpers/pole.rb
|
|
48
|
+
- lib/legion/extensions/cognitive_magnet/runners/cognitive_magnet.rb
|
|
49
|
+
- lib/legion/extensions/cognitive_magnet/version.rb
|
|
50
|
+
homepage: https://github.com/LegionIO/lex-cognitive-magnet
|
|
51
|
+
licenses:
|
|
52
|
+
- MIT
|
|
53
|
+
metadata:
|
|
54
|
+
homepage_uri: https://github.com/LegionIO/lex-cognitive-magnet
|
|
55
|
+
source_code_uri: https://github.com/LegionIO/lex-cognitive-magnet
|
|
56
|
+
documentation_uri: https://github.com/LegionIO/lex-cognitive-magnet
|
|
57
|
+
changelog_uri: https://github.com/LegionIO/lex-cognitive-magnet
|
|
58
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-magnet/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 Magnet
|
|
77
|
+
test_files: []
|