lex-cognitive-echo 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 +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +41 -0
- data/CLAUDE.md +77 -0
- data/Gemfile +13 -0
- data/README.md +54 -0
- data/lex-cognitive-echo.gemspec +32 -0
- data/lib/legion/extensions/cognitive_echo/client.rb +15 -0
- data/lib/legion/extensions/cognitive_echo/helpers/constants.rb +53 -0
- data/lib/legion/extensions/cognitive_echo/helpers/echo.rb +91 -0
- data/lib/legion/extensions/cognitive_echo/helpers/echo_engine.rb +132 -0
- data/lib/legion/extensions/cognitive_echo/runners/cognitive_echo.rb +77 -0
- data/lib/legion/extensions/cognitive_echo/version.rb +9 -0
- data/lib/legion/extensions/cognitive_echo.rb +15 -0
- metadata +77 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 999f772ad29137ea8193c34453a986f9e9e5bf6c47aa280b574efb78b38c5e31
|
|
4
|
+
data.tar.gz: ebb34f4efe8a8c9ff2f2c80f616b1f8ac0937aa4a02efe868aeedfe4230c760f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9cc3212295c5644b89b9a457aef6ea938f4606531b37dd26209490c68b8ada6367b8cb2b083450afa9a3783d34c7fafac950beb0e82f82281a1100867423a4a5
|
|
7
|
+
data.tar.gz: 8a28e5a978aeda3b8ec2661340c194d11f7d73b625a4f80c50126b031ace7c229a2538c0015a746bc04f989f8f4a612220e202b8fb7189472c7fd6e31c2aa119
|
|
@@ -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,41 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
NewCops: enable
|
|
3
|
+
TargetRubyVersion: 3.4
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
6
|
+
Style/Documentation:
|
|
7
|
+
Enabled: false
|
|
8
|
+
|
|
9
|
+
Naming/PredicateMethod:
|
|
10
|
+
Enabled: false
|
|
11
|
+
|
|
12
|
+
Naming/PredicatePrefix:
|
|
13
|
+
Enabled: false
|
|
14
|
+
|
|
15
|
+
Metrics/ClassLength:
|
|
16
|
+
Max: 150
|
|
17
|
+
|
|
18
|
+
Metrics/MethodLength:
|
|
19
|
+
Max: 25
|
|
20
|
+
|
|
21
|
+
Metrics/AbcSize:
|
|
22
|
+
Max: 25
|
|
23
|
+
|
|
24
|
+
Metrics/ParameterLists:
|
|
25
|
+
Max: 8
|
|
26
|
+
MaxOptionalParameters: 8
|
|
27
|
+
|
|
28
|
+
Layout/HashAlignment:
|
|
29
|
+
EnforcedHashRocketStyle: table
|
|
30
|
+
EnforcedColonStyle: table
|
|
31
|
+
|
|
32
|
+
Metrics/BlockLength:
|
|
33
|
+
Exclude:
|
|
34
|
+
- 'spec/**/*'
|
|
35
|
+
|
|
36
|
+
Style/FrozenStringLiteralComment:
|
|
37
|
+
Enabled: true
|
|
38
|
+
|
|
39
|
+
Style/OneClassPerFile:
|
|
40
|
+
Exclude:
|
|
41
|
+
- 'spec/spec_helper.rb'
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# lex-cognitive-echo
|
|
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
|
+
Models residual cognitive activation from previous processing. Recent thoughts leave echoes that decay over time but influence current processing through priming and interference effects. Provides a background activation layer — the cognitive afterimage of prior thinking that shapes new processing without conscious attention.
|
|
10
|
+
|
|
11
|
+
## Gem Info
|
|
12
|
+
|
|
13
|
+
- **Gem name**: `lex-cognitive-echo`
|
|
14
|
+
- **Version**: `0.1.0`
|
|
15
|
+
- **Module**: `Legion::Extensions::CognitiveEcho`
|
|
16
|
+
- **Ruby**: `>= 3.4`
|
|
17
|
+
- **License**: MIT
|
|
18
|
+
|
|
19
|
+
## File Structure
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
lib/legion/extensions/cognitive_echo/
|
|
23
|
+
cognitive_echo.rb
|
|
24
|
+
version.rb
|
|
25
|
+
client.rb
|
|
26
|
+
helpers/
|
|
27
|
+
constants.rb
|
|
28
|
+
echo_engine.rb
|
|
29
|
+
echo.rb
|
|
30
|
+
runners/
|
|
31
|
+
cognitive_echo.rb
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Key Constants
|
|
35
|
+
|
|
36
|
+
From `helpers/constants.rb`:
|
|
37
|
+
|
|
38
|
+
- `ECHO_TYPES` — `%i[thought emotion decision observation prediction error success failure]`
|
|
39
|
+
- `MAX_ECHOES` = `300`, `MAX_INTERACTIONS` = `500`
|
|
40
|
+
- `DEFAULT_INTENSITY` = `0.8`, `ECHO_DECAY` = `0.1`, `REINFORCEMENT` = `0.15`
|
|
41
|
+
- `INTERFERENCE_THRESHOLD` = `0.4`, `PRIMING_THRESHOLD` = `0.3`, `SILENT_THRESHOLD` = `0.05`
|
|
42
|
+
- `INTENSITY_LABELS` — `0.8+` = `:reverberating`, `0.6` = `:strong`, `0.4` = `:moderate`, `0.2` = `:fading`, below = `:whisper`
|
|
43
|
+
- `EFFECT_LABELS` — `0.6+` = `:dominant`, `0.3` = `:influential`, `0.1` = `:subtle`, below = `:negligible`
|
|
44
|
+
- `CHAMBER_LABELS` — `0.8+` = `:echo_chamber`, `0.6` = `:resonant`, `0.4` = `:balanced`, `0.2` = `:diverse`, below = `:scattered`
|
|
45
|
+
|
|
46
|
+
## Runners
|
|
47
|
+
|
|
48
|
+
All methods in `Runners::CognitiveEcho`:
|
|
49
|
+
|
|
50
|
+
- `create_echo(content:, echo_type: :thought, domain: :general, intensity: 0.8)` — registers a new echo from a just-processed cognitive event
|
|
51
|
+
- `reinforce_echo(echo_id:, amount: 0.15)` — increases echo intensity; models repeated exposure reinforcing residual activation
|
|
52
|
+
- `decay_all` — applies `ECHO_DECAY` to all echoes; removes echoes below `SILENT_THRESHOLD`
|
|
53
|
+
- `active_echoes` — echoes above `SILENT_THRESHOLD`
|
|
54
|
+
- `priming_echoes` — echoes above `PRIMING_THRESHOLD` (influencing current processing)
|
|
55
|
+
- `interfering_echoes` — echoes above `INTERFERENCE_THRESHOLD` (strong enough to distort)
|
|
56
|
+
- `echoes_by_domain(domain:)` — filter by domain
|
|
57
|
+
- `strongest_echoes(limit: 5)` — top echoes by intensity
|
|
58
|
+
- `priming_effect(domain:)` — aggregate priming effect for a domain (sum of priming echo intensities)
|
|
59
|
+
- `echo_status` — full report: totals, decay stats, chamber resonance, domain distribution
|
|
60
|
+
|
|
61
|
+
## Helpers
|
|
62
|
+
|
|
63
|
+
- `EchoEngine` — manages echoes. `decay_all!` removes silent echoes. `priming_effect_for(domain:)` sums intensities of priming echoes in the domain.
|
|
64
|
+
- `Echo` — has `content`, `echo_type`, `domain`, `intensity`. `decay!` reduces by `ECHO_DECAY`. `reinforce!(amount)` increases intensity. `priming?`, `interfering?`, `silent?` predicates.
|
|
65
|
+
|
|
66
|
+
## Integration Points
|
|
67
|
+
|
|
68
|
+
- `lex-cognitive-echo-chamber` is the multi-echo, self-amplifying version — echo models single residual activations; echo chamber models self-reinforcing belief loops.
|
|
69
|
+
- `lex-cognitive-dwell` models active foreground attention; echo models passive background residual. They complement each other.
|
|
70
|
+
- `priming_effect(domain:)` can be called from `lex-tick` before prediction or memory retrieval phases — high priming in a domain biases retrieval toward domain-consistent content.
|
|
71
|
+
|
|
72
|
+
## Development Notes
|
|
73
|
+
|
|
74
|
+
- Echo decay is rapid (`ECHO_DECAY = 0.1` per cycle) — echoes are transient by design. Only reinforced echoes persist.
|
|
75
|
+
- `SILENT_THRESHOLD = 0.05` is the removal floor — echoes below this are pruned on `decay_all`.
|
|
76
|
+
- `CHAMBER_LABELS` keyed on the ratio of echoes above `INTERFERENCE_THRESHOLD` to total echoes — a high ratio indicates an echo chamber is forming.
|
|
77
|
+
- `priming_effect_for` returns a sum, not a ratio — high echo counts amplify domain priming linearly.
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# lex-cognitive-echo
|
|
2
|
+
|
|
3
|
+
Residual cognitive activation modeling for the LegionIO cognitive architecture. Recent thoughts leave echoes that decay over time but continue to influence current processing through priming and interference effects.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Cognitive echo models the afterimage of prior thinking — the background activation that persists after an active thought has passed. An echo is created when a cognitive event (thought, emotion, decision, observation, prediction, error, success, or failure) finishes processing. It starts at a configurable intensity, decays each cycle, and gets pruned once it falls below the silent threshold (0.05).
|
|
8
|
+
|
|
9
|
+
Echoes serve two roles: **priming** (echoes above 0.3 bias new retrieval and processing toward their domain) and **interference** (echoes above 0.4 are strong enough to distort new processing). The extension also tracks chamber resonance — the ratio of interfering echoes to total echoes — as an early signal that an echo chamber is forming.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
client = Legion::Extensions::CognitiveEcho::Client.new
|
|
15
|
+
|
|
16
|
+
# Register a new echo from a just-processed event
|
|
17
|
+
result = client.create_echo(
|
|
18
|
+
content: 'recursive planning loop detected',
|
|
19
|
+
echo_type: :thought,
|
|
20
|
+
domain: :planning,
|
|
21
|
+
intensity: 0.8
|
|
22
|
+
)
|
|
23
|
+
echo_id = result[:echo][:id]
|
|
24
|
+
|
|
25
|
+
# Reinforce an echo (e.g., it was encountered again)
|
|
26
|
+
client.reinforce_echo(echo_id: echo_id, amount: 0.15)
|
|
27
|
+
|
|
28
|
+
# Periodic maintenance — decay all echoes, prune silent ones
|
|
29
|
+
client.decay_all
|
|
30
|
+
|
|
31
|
+
# Query by role
|
|
32
|
+
client.active_echoes
|
|
33
|
+
client.priming_echoes # intensity > 0.3 — influencing current processing
|
|
34
|
+
client.interfering_echoes # intensity > 0.4 — strong enough to distort
|
|
35
|
+
|
|
36
|
+
# Domain-focused queries
|
|
37
|
+
client.echoes_by_domain(domain: :planning)
|
|
38
|
+
client.priming_effect(domain: :planning) # aggregate priming for a domain
|
|
39
|
+
|
|
40
|
+
# Status
|
|
41
|
+
client.echo_status
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Development
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
bundle install
|
|
48
|
+
bundle exec rspec
|
|
49
|
+
bundle exec rubocop
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_echo/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-echo'
|
|
7
|
+
spec.version = Legion::Extensions::CognitiveEcho::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Thought echo and residual activation tracking for LegionIO'
|
|
12
|
+
spec.description = 'Models residual cognitive activation from previous processing. Recent thoughts ' \
|
|
13
|
+
'leave echoes that decay over time but influence current processing through ' \
|
|
14
|
+
'priming and interference effects.'
|
|
15
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-echo'
|
|
16
|
+
spec.license = 'MIT'
|
|
17
|
+
|
|
18
|
+
spec.required_ruby_version = '>= 3.4'
|
|
19
|
+
|
|
20
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
21
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-cognitive-echo'
|
|
22
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-cognitive-echo/blob/master/README.md'
|
|
23
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-cognitive-echo/blob/master/CHANGELOG.md'
|
|
24
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-cognitive-echo/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
|
+
spec.require_paths = ['lib']
|
|
31
|
+
spec.add_development_dependency 'legion-gaia'
|
|
32
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveEcho
|
|
6
|
+
class Client
|
|
7
|
+
include Runners::CognitiveEcho
|
|
8
|
+
|
|
9
|
+
def initialize(engine: nil)
|
|
10
|
+
@default_engine = engine || Helpers::EchoEngine.new
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveEcho
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_ECHOES = 300
|
|
9
|
+
MAX_INTERACTIONS = 500
|
|
10
|
+
DEFAULT_INTENSITY = 0.8
|
|
11
|
+
ECHO_DECAY = 0.1
|
|
12
|
+
REINFORCEMENT = 0.15
|
|
13
|
+
INTERFERENCE_THRESHOLD = 0.4
|
|
14
|
+
PRIMING_THRESHOLD = 0.3
|
|
15
|
+
SILENT_THRESHOLD = 0.05
|
|
16
|
+
|
|
17
|
+
ECHO_TYPES = %i[
|
|
18
|
+
thought emotion decision observation
|
|
19
|
+
prediction error success failure
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
INTENSITY_LABELS = {
|
|
23
|
+
(0.8..) => :reverberating,
|
|
24
|
+
(0.6...0.8) => :strong,
|
|
25
|
+
(0.4...0.6) => :moderate,
|
|
26
|
+
(0.2...0.4) => :fading,
|
|
27
|
+
(..0.2) => :whisper
|
|
28
|
+
}.freeze
|
|
29
|
+
|
|
30
|
+
EFFECT_LABELS = {
|
|
31
|
+
(0.6..) => :dominant,
|
|
32
|
+
(0.3...0.6) => :influential,
|
|
33
|
+
(0.1...0.3) => :subtle,
|
|
34
|
+
(..0.1) => :negligible
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
CHAMBER_LABELS = {
|
|
38
|
+
(0.8..) => :echo_chamber,
|
|
39
|
+
(0.6...0.8) => :resonant,
|
|
40
|
+
(0.4...0.6) => :balanced,
|
|
41
|
+
(0.2...0.4) => :diverse,
|
|
42
|
+
(..0.2) => :scattered
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
45
|
+
def self.label_for(labels, value)
|
|
46
|
+
match = labels.find { |range, _| range.cover?(value) }
|
|
47
|
+
match&.last
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveEcho
|
|
8
|
+
module Helpers
|
|
9
|
+
class Echo
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :content, :echo_type, :domain, :intensity,
|
|
13
|
+
:original_intensity, :decay_count, :created_at
|
|
14
|
+
|
|
15
|
+
def initialize(content:, echo_type: :thought, domain: :general, intensity: DEFAULT_INTENSITY)
|
|
16
|
+
@id = SecureRandom.uuid
|
|
17
|
+
@content = content
|
|
18
|
+
@echo_type = validate_type(echo_type)
|
|
19
|
+
@domain = domain.to_sym
|
|
20
|
+
@intensity = intensity.to_f.clamp(0.0, 1.0).round(10)
|
|
21
|
+
@original_intensity = @intensity
|
|
22
|
+
@decay_count = 0
|
|
23
|
+
@created_at = Time.now.utc
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def decay!
|
|
27
|
+
@decay_count += 1
|
|
28
|
+
@intensity = (@intensity - ECHO_DECAY).clamp(0.0, 1.0).round(10)
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def reinforce!(amount = REINFORCEMENT)
|
|
33
|
+
@intensity = (@intensity + amount).clamp(0.0, 1.0).round(10)
|
|
34
|
+
self
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def silent?
|
|
38
|
+
@intensity <= SILENT_THRESHOLD
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def active?
|
|
42
|
+
@intensity > SILENT_THRESHOLD
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def priming?
|
|
46
|
+
@intensity >= PRIMING_THRESHOLD
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def interfering?
|
|
50
|
+
@intensity >= INTERFERENCE_THRESHOLD
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def persistence
|
|
54
|
+
return 0.0 if @original_intensity.zero?
|
|
55
|
+
|
|
56
|
+
(@intensity / @original_intensity).clamp(0.0, 1.0).round(10)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def intensity_label = Constants.label_for(INTENSITY_LABELS, @intensity)
|
|
60
|
+
def effect_label = Constants.label_for(EFFECT_LABELS, @intensity)
|
|
61
|
+
|
|
62
|
+
def to_h
|
|
63
|
+
{
|
|
64
|
+
id: @id,
|
|
65
|
+
content: @content,
|
|
66
|
+
echo_type: @echo_type,
|
|
67
|
+
domain: @domain,
|
|
68
|
+
intensity: @intensity,
|
|
69
|
+
original_intensity: @original_intensity,
|
|
70
|
+
intensity_label: intensity_label,
|
|
71
|
+
effect_label: effect_label,
|
|
72
|
+
priming: priming?,
|
|
73
|
+
interfering: interfering?,
|
|
74
|
+
silent: silent?,
|
|
75
|
+
persistence: persistence,
|
|
76
|
+
decay_count: @decay_count,
|
|
77
|
+
created_at: @created_at
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def validate_type(type)
|
|
84
|
+
sym = type.to_sym
|
|
85
|
+
ECHO_TYPES.include?(sym) ? sym : :thought
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveEcho
|
|
6
|
+
module Helpers
|
|
7
|
+
class EchoEngine
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@echoes = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create_echo(content:, echo_type: :thought, domain: :general, intensity: DEFAULT_INTENSITY)
|
|
15
|
+
prune_silent
|
|
16
|
+
echo = Echo.new(content: content, echo_type: echo_type, domain: domain, intensity: intensity)
|
|
17
|
+
@echoes[echo.id] = echo
|
|
18
|
+
echo
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def reinforce_echo(echo_id:, amount: REINFORCEMENT)
|
|
22
|
+
echo = @echoes[echo_id]
|
|
23
|
+
return nil unless echo
|
|
24
|
+
|
|
25
|
+
echo.reinforce!(amount)
|
|
26
|
+
echo
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def decay_all!
|
|
30
|
+
@echoes.each_value(&:decay!)
|
|
31
|
+
prune_silent
|
|
32
|
+
{ echoes_decayed: @echoes.size, pruned: count_silent }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def active_echoes = @echoes.values.select(&:active?)
|
|
36
|
+
def priming_echoes = @echoes.values.select(&:priming?)
|
|
37
|
+
def interfering_echoes = @echoes.values.select(&:interfering?)
|
|
38
|
+
|
|
39
|
+
def echoes_by_type(echo_type:)
|
|
40
|
+
@echoes.values.select { |e| e.echo_type == echo_type.to_sym }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def echoes_by_domain(domain:)
|
|
44
|
+
@echoes.values.select { |e| e.domain == domain.to_sym }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def strongest_echoes(limit: 5) = @echoes.values.sort_by { |e| -e.intensity }.first(limit)
|
|
48
|
+
def faintest_echoes(limit: 5) = @echoes.values.select(&:active?).sort_by(&:intensity).first(limit)
|
|
49
|
+
|
|
50
|
+
def echo_chamber_score
|
|
51
|
+
return 0.0 if @echoes.empty?
|
|
52
|
+
|
|
53
|
+
domains = @echoes.values.map(&:domain).uniq
|
|
54
|
+
return 1.0 if domains.size <= 1
|
|
55
|
+
|
|
56
|
+
domain_concentration(domains)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def chamber_label = Constants.label_for(CHAMBER_LABELS, echo_chamber_score)
|
|
60
|
+
|
|
61
|
+
def priming_effect_for(domain:)
|
|
62
|
+
matching = echoes_by_domain(domain: domain).select(&:priming?)
|
|
63
|
+
return 0.0 if matching.empty?
|
|
64
|
+
|
|
65
|
+
matching.sum(&:intensity).clamp(0.0, 1.0).round(10)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def interference_level
|
|
69
|
+
interfering = interfering_echoes
|
|
70
|
+
return 0.0 if interfering.empty?
|
|
71
|
+
|
|
72
|
+
(interfering.sum(&:intensity) / @echoes.size).clamp(0.0, 1.0).round(10)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def average_intensity
|
|
76
|
+
return 0.0 if @echoes.empty?
|
|
77
|
+
|
|
78
|
+
(@echoes.values.sum(&:intensity) / @echoes.size).round(10)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def echo_report
|
|
82
|
+
{
|
|
83
|
+
total_echoes: @echoes.size,
|
|
84
|
+
active_count: active_echoes.size,
|
|
85
|
+
priming_count: priming_echoes.size,
|
|
86
|
+
interfering_count: interfering_echoes.size,
|
|
87
|
+
average_intensity: average_intensity,
|
|
88
|
+
echo_chamber_score: echo_chamber_score,
|
|
89
|
+
chamber_label: chamber_label,
|
|
90
|
+
interference_level: interference_level,
|
|
91
|
+
strongest: strongest_echoes(limit: 3).map(&:to_h)
|
|
92
|
+
}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def to_h
|
|
96
|
+
{
|
|
97
|
+
total_echoes: @echoes.size,
|
|
98
|
+
active: active_echoes.size,
|
|
99
|
+
average_intensity: average_intensity,
|
|
100
|
+
chamber_score: echo_chamber_score
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def domain_concentration(domains)
|
|
107
|
+
intensities = domains.map { |d| @echoes.values.select { |e| e.domain == d }.sum(&:intensity) }
|
|
108
|
+
total = intensities.sum
|
|
109
|
+
return 0.0 if total.zero?
|
|
110
|
+
|
|
111
|
+
(intensities.max / total).round(10)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def count_silent
|
|
115
|
+
@echoes.values.count(&:silent?)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def prune_silent
|
|
119
|
+
return if @echoes.size < MAX_ECHOES
|
|
120
|
+
|
|
121
|
+
silent = @echoes.values.select(&:silent?)
|
|
122
|
+
silent.each { |e| @echoes.delete(e.id) }
|
|
123
|
+
return unless @echoes.size >= MAX_ECHOES
|
|
124
|
+
|
|
125
|
+
faintest = @echoes.values.min_by(&:intensity)
|
|
126
|
+
@echoes.delete(faintest.id) if faintest
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveEcho
|
|
6
|
+
module Runners
|
|
7
|
+
module CognitiveEcho
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
|
|
9
|
+
|
|
10
|
+
def create_echo(content:, echo_type: :thought, domain: :general, intensity: 0.8, engine: nil, **)
|
|
11
|
+
eng = engine || default_engine
|
|
12
|
+
echo = eng.create_echo(content: content, echo_type: echo_type, domain: domain, intensity: intensity)
|
|
13
|
+
{ success: true, echo: echo.to_h }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def reinforce_echo(echo_id:, amount: 0.15, engine: nil, **)
|
|
17
|
+
eng = engine || default_engine
|
|
18
|
+
echo = eng.reinforce_echo(echo_id: echo_id, amount: amount)
|
|
19
|
+
return { success: false, error: 'echo not found' } unless echo
|
|
20
|
+
|
|
21
|
+
{ success: true, echo: echo.to_h }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def decay_all(engine: nil, **)
|
|
25
|
+
eng = engine || default_engine
|
|
26
|
+
result = eng.decay_all!
|
|
27
|
+
{ success: true, **result }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def active_echoes(engine: nil, **)
|
|
31
|
+
eng = engine || default_engine
|
|
32
|
+
{ success: true, echoes: eng.active_echoes.map(&:to_h), count: eng.active_echoes.size }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def priming_echoes(engine: nil, **)
|
|
36
|
+
eng = engine || default_engine
|
|
37
|
+
{ success: true, echoes: eng.priming_echoes.map(&:to_h), count: eng.priming_echoes.size }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def interfering_echoes(engine: nil, **)
|
|
41
|
+
eng = engine || default_engine
|
|
42
|
+
{ success: true, echoes: eng.interfering_echoes.map(&:to_h), count: eng.interfering_echoes.size }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def echoes_by_domain(domain:, engine: nil, **)
|
|
46
|
+
eng = engine || default_engine
|
|
47
|
+
echoes = eng.echoes_by_domain(domain: domain)
|
|
48
|
+
{ success: true, echoes: echoes.map(&:to_h), count: echoes.size }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def strongest_echoes(limit: 5, engine: nil, **)
|
|
52
|
+
eng = engine || default_engine
|
|
53
|
+
{ success: true, echoes: eng.strongest_echoes(limit: limit).map(&:to_h) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def priming_effect(domain:, engine: nil, **)
|
|
57
|
+
eng = engine || default_engine
|
|
58
|
+
effect = eng.priming_effect_for(domain: domain)
|
|
59
|
+
label = Helpers::Constants.label_for(Helpers::Constants::EFFECT_LABELS, effect)
|
|
60
|
+
{ success: true, domain: domain.to_sym, priming_effect: effect, effect_label: label }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def echo_status(engine: nil, **)
|
|
64
|
+
eng = engine || default_engine
|
|
65
|
+
{ success: true, **eng.echo_report }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def default_engine
|
|
71
|
+
@default_engine ||= Helpers::EchoEngine.new
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'cognitive_echo/version'
|
|
4
|
+
require_relative 'cognitive_echo/helpers/constants'
|
|
5
|
+
require_relative 'cognitive_echo/helpers/echo'
|
|
6
|
+
require_relative 'cognitive_echo/helpers/echo_engine'
|
|
7
|
+
require_relative 'cognitive_echo/runners/cognitive_echo'
|
|
8
|
+
require_relative 'cognitive_echo/client'
|
|
9
|
+
|
|
10
|
+
module Legion
|
|
11
|
+
module Extensions
|
|
12
|
+
module CognitiveEcho
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-cognitive-echo
|
|
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 residual cognitive activation from previous processing. Recent
|
|
27
|
+
thoughts leave echoes that decay over time but influence current processing through
|
|
28
|
+
priming and interference effects.
|
|
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
|
+
- README.md
|
|
42
|
+
- lex-cognitive-echo.gemspec
|
|
43
|
+
- lib/legion/extensions/cognitive_echo.rb
|
|
44
|
+
- lib/legion/extensions/cognitive_echo/client.rb
|
|
45
|
+
- lib/legion/extensions/cognitive_echo/helpers/constants.rb
|
|
46
|
+
- lib/legion/extensions/cognitive_echo/helpers/echo.rb
|
|
47
|
+
- lib/legion/extensions/cognitive_echo/helpers/echo_engine.rb
|
|
48
|
+
- lib/legion/extensions/cognitive_echo/runners/cognitive_echo.rb
|
|
49
|
+
- lib/legion/extensions/cognitive_echo/version.rb
|
|
50
|
+
homepage: https://github.com/LegionIO/lex-cognitive-echo
|
|
51
|
+
licenses:
|
|
52
|
+
- MIT
|
|
53
|
+
metadata:
|
|
54
|
+
homepage_uri: https://github.com/LegionIO/lex-cognitive-echo
|
|
55
|
+
source_code_uri: https://github.com/LegionIO/lex-cognitive-echo
|
|
56
|
+
documentation_uri: https://github.com/LegionIO/lex-cognitive-echo/blob/master/README.md
|
|
57
|
+
changelog_uri: https://github.com/LegionIO/lex-cognitive-echo/blob/master/CHANGELOG.md
|
|
58
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-cognitive-echo/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: Thought echo and residual activation tracking for LegionIO
|
|
77
|
+
test_files: []
|