lex-cognitive-immune-memory 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 +10 -0
- data/.rspec +3 -0
- data/.rubocop.yml +37 -0
- data/CLAUDE.md +116 -0
- data/Gemfile +11 -0
- data/README.md +47 -0
- data/lex-cognitive-immune-memory.gemspec +29 -0
- data/lib/legion/extensions/cognitive_immune_memory/client.rb +15 -0
- data/lib/legion/extensions/cognitive_immune_memory/helpers/constants.rb +80 -0
- data/lib/legion/extensions/cognitive_immune_memory/helpers/encounter.rb +50 -0
- data/lib/legion/extensions/cognitive_immune_memory/helpers/immune_memory_engine.rb +167 -0
- data/lib/legion/extensions/cognitive_immune_memory/helpers/memory_cell.rb +93 -0
- data/lib/legion/extensions/cognitive_immune_memory/runners/cognitive_immune_memory.rb +72 -0
- data/lib/legion/extensions/cognitive_immune_memory/version.rb +9 -0
- data/lib/legion/extensions/cognitive_immune_memory.rb +16 -0
- data/spec/legion/extensions/cognitive_immune_memory/client_spec.rb +18 -0
- data/spec/legion/extensions/cognitive_immune_memory/helpers/encounter_spec.rb +85 -0
- data/spec/legion/extensions/cognitive_immune_memory/helpers/immune_memory_engine_spec.rb +203 -0
- data/spec/legion/extensions/cognitive_immune_memory/helpers/memory_cell_spec.rb +190 -0
- data/spec/legion/extensions/cognitive_immune_memory/runners_spec.rb +83 -0
- data/spec/legion/extensions/cognitive_immune_memory_spec.rb +7 -0
- data/spec/spec_helper.rb +28 -0
- metadata +84 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 012131c8a1758dd81ca39180981eeece28699fdd6e29b9e21c00150fbee3ba2b
|
|
4
|
+
data.tar.gz: 9fbc8c5b7f8d3cdc8e63e21de41b6012fd1e78266d78e214b0f1956f45c0da15
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 2f36b3a716fef71808de082745ec4cec13e31147d1e60140d3f18c4b0cedad0ffbb554b8823ab33dd3c2ffa7cf7d3f4b843e5b6ae060a978ca40408b8ba8b984
|
|
7
|
+
data.tar.gz: 9d2318d3428096bc2d882fbd954ffcf4728e8e4bcb8fa9ddf4864b3c1e3f1d62c830f28ad33918ec8f4da1617dde938ee1fd6803e9f672f87226f4e493300112
|
|
@@ -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,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,116 @@
|
|
|
1
|
+
# lex-cognitive-immune-memory
|
|
2
|
+
|
|
3
|
+
**Level 3 Leaf Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-agentic/CLAUDE.md`
|
|
5
|
+
- **Gem**: `lex-cognitive-immune-memory`
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Models long-term immunological memory for cognitive threat recognition. Memory cells are trained records of past threats — each encounter with a known threat type produces a primary response and creates or strengthens a memory cell. Subsequent encounters trigger secondary responses that are faster and stronger than primary. Vaccination artificially installs memory cells without requiring a live encounter. Memory cells decay over time if not reinforced. Tracks threat coverage, neutralization rate, and average response speed across the cell population.
|
|
10
|
+
|
|
11
|
+
## Gem Info
|
|
12
|
+
|
|
13
|
+
| Field | Value |
|
|
14
|
+
|---|---|
|
|
15
|
+
| Gem name | `lex-cognitive-immune-memory` |
|
|
16
|
+
| Version | `0.1.0` |
|
|
17
|
+
| Namespace | `Legion::Extensions::CognitiveImmuneMemory` |
|
|
18
|
+
| Ruby | `>= 3.4` |
|
|
19
|
+
| License | MIT |
|
|
20
|
+
| GitHub | https://github.com/LegionIO/lex-cognitive-immune-memory |
|
|
21
|
+
|
|
22
|
+
## File Structure
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
lib/legion/extensions/cognitive_immune_memory/
|
|
26
|
+
cognitive_immune_memory.rb # Top-level require
|
|
27
|
+
version.rb # VERSION = '0.1.0'
|
|
28
|
+
client.rb # Client class
|
|
29
|
+
helpers/
|
|
30
|
+
constants.rb # Threat types, cell types, activation thresholds, response speeds, labels
|
|
31
|
+
memory_cell.rb # MemoryCell value object
|
|
32
|
+
immune_memory_engine.rb # Engine: cells, vaccination, encounters, decay, coverage
|
|
33
|
+
runners/
|
|
34
|
+
cognitive_immune_memory.rb # Runner module
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Key Constants
|
|
38
|
+
|
|
39
|
+
| Constant | Value | Meaning |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `MAX_MEMORY_CELLS` | 500 | Memory cell cap |
|
|
42
|
+
| `T_CELL_ACTIVATION_THRESHOLD` | 0.5 | Strength threshold for T-cell activation |
|
|
43
|
+
| `B_CELL_ACTIVATION_THRESHOLD` | 0.4 | Strength threshold for B-cell activation |
|
|
44
|
+
| `T_CELL_BOOST` | 0.15 | Strength increase per encounter for T-cells |
|
|
45
|
+
| `B_CELL_BOOST` | 0.12 | Strength increase per encounter for B-cells |
|
|
46
|
+
| `PRIMARY_RESPONSE_SPEED` | 0.3 | Baseline response speed for primary encounter |
|
|
47
|
+
| `SECONDARY_RESPONSE_SPEED` | 0.8 | Elevated response speed for known threats |
|
|
48
|
+
| `VACCINATION_STRENGTH` | 0.5 | Starting strength for vaccinated cells |
|
|
49
|
+
| `THREAT_TYPES` | array | `[:manipulation, :deception, :coercion, :exploitation, :distraction, :flooding, :anchoring, :mirroring]` |
|
|
50
|
+
| `CELL_TYPES` | array | `[:t_cell, :b_cell, :memory_t, :memory_b, :natural_killer]` |
|
|
51
|
+
| `IMMUNITY_LABELS` | hash | `immune` (0.8+) through `naive` |
|
|
52
|
+
| `RESPONSE_SPEED_LABELS` | hash | `instant` (0.9+) through `slow` |
|
|
53
|
+
| `HEALTH_LABELS` | hash | `robust` through `depleted` |
|
|
54
|
+
| `MATURITY_LABELS` | hash | `veteran` through `naive` |
|
|
55
|
+
|
|
56
|
+
## Helpers
|
|
57
|
+
|
|
58
|
+
### `MemoryCell`
|
|
59
|
+
|
|
60
|
+
A trained immunological record for a specific threat type.
|
|
61
|
+
|
|
62
|
+
- `initialize(threat_type:, cell_type:, strength: 0.5, cell_id: nil)`
|
|
63
|
+
- `encounter!(boost)` — increases strength by cell-type boost; increments encounter_count; increases response_speed
|
|
64
|
+
- `decay!(rate)` — decreases strength, floor 0.0
|
|
65
|
+
- `active?` — strength >= cell-type activation threshold
|
|
66
|
+
- `veteran?` — encounter_count above veteran threshold
|
|
67
|
+
- `response_speed` — starts at PRIMARY_RESPONSE_SPEED; increases toward SECONDARY_RESPONSE_SPEED with encounters
|
|
68
|
+
- `to_h`
|
|
69
|
+
|
|
70
|
+
### `ImmuneMemoryEngine`
|
|
71
|
+
|
|
72
|
+
- `create_memory_cell(threat_type:, cell_type: :memory_t, strength: 0.5)` — returns `{ created:, cell_id:, cell: }` or capacity error
|
|
73
|
+
- `vaccinate(threat_type:)` — creates a memory cell at `VACCINATION_STRENGTH` without a live encounter
|
|
74
|
+
- `encounter_threat(threat_type:)` — checks for existing memory cells matching threat_type; if found, triggers secondary response (boosts all matching cells, returns fast response); if not found, triggers primary response and creates new memory cell
|
|
75
|
+
- `decay_all!` — decrements all cell strength values
|
|
76
|
+
- `secondary_response_rate` — proportion of threats that have established memory cells
|
|
77
|
+
- `neutralization_rate` — proportion of active (above-threshold) cells
|
|
78
|
+
- `average_response_speed` — mean response_speed across all cells
|
|
79
|
+
- `threat_coverage` — hash of threat_type -> strongest cell strength
|
|
80
|
+
- `overall_health` — composite score from neutralization, coverage breadth, and mean strength
|
|
81
|
+
- `immune_status_report` — full stats
|
|
82
|
+
|
|
83
|
+
## Runners
|
|
84
|
+
|
|
85
|
+
**Module**: `Legion::Extensions::CognitiveImmuneMemory::Runners::CognitiveImmuneMemory`
|
|
86
|
+
|
|
87
|
+
| Method | Key Args | Returns |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| `create_memory_cell` | `threat_type:`, `cell_type: :memory_t`, `strength: 0.5` | `{ success:, cell_id:, cell: }` |
|
|
90
|
+
| `vaccinate` | `threat_type:` | `{ success:, cell_id:, cell: }` |
|
|
91
|
+
| `encounter_threat` | `threat_type:` | `{ success:, response_type:, response_speed:, cells_activated: }` |
|
|
92
|
+
| `decay_all` | — | `{ success:, decayed: N }` |
|
|
93
|
+
| `immunity_for` | `threat_type:` | `{ success:, strength:, cells: }` |
|
|
94
|
+
| `active_cells` | `limit: 20` | `{ success:, cells: }` |
|
|
95
|
+
| `veteran_cells` | `limit: 10` | `{ success:, cells: }` |
|
|
96
|
+
| `threat_coverage` | — | `{ success:, coverage: { threat_type => strength } }` |
|
|
97
|
+
| `immune_status` | — | `{ success:, report: }` |
|
|
98
|
+
|
|
99
|
+
Private: `immune_memory_engine` — memoized `ImmuneMemoryEngine`. Logs via `log_debug` helper.
|
|
100
|
+
|
|
101
|
+
## Integration Points
|
|
102
|
+
|
|
103
|
+
- **`lex-cognitive-immunology`**: `lex-cognitive-immune-memory` handles long-term recognition and learned threat response. `lex-cognitive-immunology` handles live threat detection, quarantine, and inflammatory response. The two complement each other: immunology for acute response, immune-memory for durable recognition.
|
|
104
|
+
- **`lex-cognitive-immune-response`**: Immune response generates antibodies; immune memory stores the learned patterns. After a threat encounter in `lex-cognitive-immune-response`, a corresponding vaccination in immune-memory can install durable recognition.
|
|
105
|
+
- **`lex-trust`**: Low secondary_response_rate (few threats in memory) corresponds to a naive agent with undeveloped trust discrimination. High memory coverage supports more nuanced trust evaluation.
|
|
106
|
+
|
|
107
|
+
## Development Notes
|
|
108
|
+
|
|
109
|
+
- `encounter_threat` distinguishes primary vs. secondary response by whether any memory cell for the threat_type exists and is active. New memory cells are created on primary encounter regardless of capacity (up to MAX_MEMORY_CELLS).
|
|
110
|
+
- `vaccinate` creates a new cell at `VACCINATION_STRENGTH` each call — calling vaccinate multiple times for the same threat_type creates multiple cells.
|
|
111
|
+
- `decay_all!` decays all cells unconditionally. Cells that decay to 0.0 remain in the store; callers should check `active?` and prune manually.
|
|
112
|
+
- In-memory only.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
**Maintained By**: Matthew Iverson (@Esity)
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# lex-cognitive-immune-memory
|
|
2
|
+
|
|
3
|
+
Long-term cognitive threat recognition engine for brain-modeled agentic AI in the LegionIO ecosystem.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Models immunological memory for cognitive security. Memory cells are trained records of past threat encounters — manipulation, deception, coercion, exploitation, and related adversarial patterns. Encountering a known threat triggers a fast secondary response (response speed 0.8); encountering an unknown threat triggers a slower primary response (0.3) and installs a new memory cell. Vaccination artificially creates memory cells without a live encounter. Memory cells decay over time without reinforcement.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
require 'legion/extensions/cognitive_immune_memory'
|
|
13
|
+
|
|
14
|
+
client = Legion::Extensions::CognitiveImmuneMemory::Client.new
|
|
15
|
+
|
|
16
|
+
# Vaccinate against a known threat pattern
|
|
17
|
+
client.vaccinate(threat_type: :manipulation)
|
|
18
|
+
# => { success: true, cell_id: "...", cell: { strength: 0.5, response_speed: 0.3, ... } }
|
|
19
|
+
|
|
20
|
+
# Encounter a threat — secondary response since vaccination installed a cell
|
|
21
|
+
client.encounter_threat(threat_type: :manipulation)
|
|
22
|
+
# => { success: true, response_type: :secondary, response_speed: 0.65, cells_activated: 1 }
|
|
23
|
+
|
|
24
|
+
# Encounter an unknown threat — primary response, installs new memory cell
|
|
25
|
+
client.encounter_threat(threat_type: :anchoring)
|
|
26
|
+
# => { success: true, response_type: :primary, response_speed: 0.3, cells_activated: 0 }
|
|
27
|
+
|
|
28
|
+
# Check coverage across all known threats
|
|
29
|
+
client.threat_coverage
|
|
30
|
+
# => { success: true, coverage: { manipulation: 0.62, anchoring: 0.5, ... } }
|
|
31
|
+
|
|
32
|
+
# Overall immune health
|
|
33
|
+
client.immune_status
|
|
34
|
+
# => { success: true, report: { cell_count: 2, health: 0.55, ... } }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Development
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
bundle install
|
|
41
|
+
bundle exec rspec
|
|
42
|
+
bundle exec rubocop
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## License
|
|
46
|
+
|
|
47
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/cognitive_immune_memory/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-cognitive-immune-memory'
|
|
7
|
+
spec.version = Legion::Extensions::CognitiveImmuneMemory::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
spec.summary = 'Long-term adaptive immune memory for LegionIO agents'
|
|
11
|
+
spec.description = 'T-cell/B-cell persistent threat recognition with secondary response ' \
|
|
12
|
+
'amplification for the LegionIO cognitive architecture'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-cognitive-immune-memory'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata = {
|
|
18
|
+
'homepage_uri' => spec.homepage,
|
|
19
|
+
'source_code_uri' => spec.homepage,
|
|
20
|
+
'documentation_uri' => "#{spec.homepage}/blob/origin/README.md",
|
|
21
|
+
'changelog_uri' => "#{spec.homepage}/blob/origin/CHANGELOG.md",
|
|
22
|
+
'bug_tracker_uri' => "#{spec.homepage}/issues",
|
|
23
|
+
'rubygems_mfa_required' => 'true'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
spec.files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
|
+
spec.add_development_dependency 'legion-gaia'
|
|
29
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveImmuneMemory
|
|
6
|
+
class Client
|
|
7
|
+
include Runners::CognitiveImmuneMemory
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@default_engine = Helpers::ImmuneMemoryEngine.new
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveImmuneMemory
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
MAX_MEMORY_CELLS = 500
|
|
9
|
+
MAX_ENCOUNTERS = 1000
|
|
10
|
+
MAX_ANTIBODY_LIBRARY = 300
|
|
11
|
+
|
|
12
|
+
# T-cell parameters (cell-mediated: direct threat neutralization)
|
|
13
|
+
T_CELL_ACTIVATION_THRESHOLD = 0.4
|
|
14
|
+
T_CELL_BOOST = 0.12
|
|
15
|
+
T_CELL_DECAY = 0.01
|
|
16
|
+
T_CELL_LIFESPAN = 100 # decay cycles before expiry check
|
|
17
|
+
|
|
18
|
+
# B-cell parameters (humoral: antibody production)
|
|
19
|
+
B_CELL_ACTIVATION_THRESHOLD = 0.3
|
|
20
|
+
B_CELL_BOOST = 0.1
|
|
21
|
+
B_CELL_DECAY = 0.008
|
|
22
|
+
B_CELL_ANTIBODY_PRODUCTION = 0.15
|
|
23
|
+
|
|
24
|
+
# Secondary response amplification
|
|
25
|
+
PRIMARY_RESPONSE_SPEED = 1.0
|
|
26
|
+
SECONDARY_RESPONSE_SPEED = 3.0
|
|
27
|
+
MEMORY_RECOGNITION_THRESHOLD = 0.6
|
|
28
|
+
|
|
29
|
+
# Vaccination (pre-exposure)
|
|
30
|
+
VACCINATION_STRENGTH = 0.5
|
|
31
|
+
|
|
32
|
+
THREAT_TYPES = %i[
|
|
33
|
+
prompt_injection data_poisoning social_engineering
|
|
34
|
+
resource_exhaustion privilege_escalation information_leak
|
|
35
|
+
logic_manipulation identity_spoofing
|
|
36
|
+
].freeze
|
|
37
|
+
|
|
38
|
+
CELL_TYPES = %i[t_helper t_killer b_memory b_plasma].freeze
|
|
39
|
+
|
|
40
|
+
IMMUNITY_LABELS = {
|
|
41
|
+
(0.8..) => :immune,
|
|
42
|
+
(0.6...0.8) => :resistant,
|
|
43
|
+
(0.4...0.6) => :partial,
|
|
44
|
+
(0.2...0.4) => :vulnerable,
|
|
45
|
+
(..0.2) => :naive
|
|
46
|
+
}.freeze
|
|
47
|
+
|
|
48
|
+
RESPONSE_SPEED_LABELS = {
|
|
49
|
+
(2.5..) => :lightning,
|
|
50
|
+
(1.8...2.5) => :rapid,
|
|
51
|
+
(1.0...1.8) => :normal,
|
|
52
|
+
(0.5...1.0) => :slow,
|
|
53
|
+
(..0.5) => :impaired
|
|
54
|
+
}.freeze
|
|
55
|
+
|
|
56
|
+
HEALTH_LABELS = {
|
|
57
|
+
(0.8..) => :robust,
|
|
58
|
+
(0.6...0.8) => :healthy,
|
|
59
|
+
(0.4...0.6) => :adequate,
|
|
60
|
+
(0.2...0.4) => :weakened,
|
|
61
|
+
(..0.2) => :compromised
|
|
62
|
+
}.freeze
|
|
63
|
+
|
|
64
|
+
MATURITY_LABELS = {
|
|
65
|
+
(0.8..) => :veteran,
|
|
66
|
+
(0.6...0.8) => :experienced,
|
|
67
|
+
(0.4...0.6) => :developing,
|
|
68
|
+
(0.2...0.4) => :immature,
|
|
69
|
+
(..0.2) => :naive
|
|
70
|
+
}.freeze
|
|
71
|
+
|
|
72
|
+
def self.label_for(labels, value)
|
|
73
|
+
labels.each { |range, label| return label if range.cover?(value) }
|
|
74
|
+
:unknown
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module CognitiveImmuneMemory
|
|
8
|
+
module Helpers
|
|
9
|
+
class Encounter
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :id, :threat_type, :threat_signature, :severity,
|
|
13
|
+
:response_type, :response_speed, :outcome, :created_at
|
|
14
|
+
|
|
15
|
+
def initialize(threat_type:, threat_signature:, severity: 0.5, response_type: :primary,
|
|
16
|
+
response_speed: PRIMARY_RESPONSE_SPEED, outcome: :neutralized)
|
|
17
|
+
@id = SecureRandom.uuid
|
|
18
|
+
@threat_type = threat_type.to_sym
|
|
19
|
+
@threat_signature = threat_signature.to_s
|
|
20
|
+
@severity = severity.to_f.clamp(0.0, 1.0)
|
|
21
|
+
@response_type = response_type.to_sym
|
|
22
|
+
@response_speed = response_speed.to_f.round(10)
|
|
23
|
+
@outcome = outcome.to_sym
|
|
24
|
+
@created_at = Time.now
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def secondary? = @response_type == :secondary
|
|
28
|
+
def primary? = @response_type == :primary
|
|
29
|
+
def neutralized? = @outcome == :neutralized
|
|
30
|
+
def evaded? = @outcome == :evaded
|
|
31
|
+
def critical? = @severity >= 0.8
|
|
32
|
+
|
|
33
|
+
def to_h
|
|
34
|
+
{
|
|
35
|
+
id: @id,
|
|
36
|
+
threat_type: @threat_type,
|
|
37
|
+
threat_signature: @threat_signature,
|
|
38
|
+
severity: @severity,
|
|
39
|
+
response_type: @response_type,
|
|
40
|
+
response_speed: @response_speed,
|
|
41
|
+
outcome: @outcome,
|
|
42
|
+
critical: critical?,
|
|
43
|
+
created_at: @created_at.iso8601
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module CognitiveImmuneMemory
|
|
6
|
+
module Helpers
|
|
7
|
+
class ImmuneMemoryEngine
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@memory_cells = {}
|
|
12
|
+
@encounters = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create_memory_cell(threat_type:, signature:, cell_type: :b_memory, strength: VACCINATION_STRENGTH)
|
|
16
|
+
prune_expired
|
|
17
|
+
cell = MemoryCell.new(threat_type: threat_type, signature: signature,
|
|
18
|
+
cell_type: cell_type, strength: strength)
|
|
19
|
+
@memory_cells[cell.id] = cell
|
|
20
|
+
cell
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def vaccinate(threat_type:, signature:, strength: VACCINATION_STRENGTH)
|
|
24
|
+
existing = find_by_signature(signature)
|
|
25
|
+
return existing.activate! if existing
|
|
26
|
+
|
|
27
|
+
create_memory_cell(threat_type: threat_type, signature: signature,
|
|
28
|
+
cell_type: :b_memory, strength: strength)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def encounter_threat(threat_type:, threat_signature:, severity: 0.5)
|
|
32
|
+
matching = find_by_signature(threat_signature)
|
|
33
|
+
response_type = matching ? :secondary : :primary
|
|
34
|
+
speed = matching ? matching.response_speed : PRIMARY_RESPONSE_SPEED
|
|
35
|
+
outcome = determine_outcome(matching, severity)
|
|
36
|
+
|
|
37
|
+
matching&.activate!
|
|
38
|
+
|
|
39
|
+
record = Encounter.new(
|
|
40
|
+
threat_type: threat_type, threat_signature: threat_signature,
|
|
41
|
+
severity: severity, response_type: response_type,
|
|
42
|
+
response_speed: speed, outcome: outcome
|
|
43
|
+
)
|
|
44
|
+
@encounters << record
|
|
45
|
+
prune_encounters
|
|
46
|
+
|
|
47
|
+
unless matching
|
|
48
|
+
create_memory_cell(threat_type: threat_type, signature: threat_signature,
|
|
49
|
+
cell_type: :b_memory, strength: B_CELL_ACTIVATION_THRESHOLD)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
record
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def decay_all!
|
|
56
|
+
@memory_cells.each_value(&:decay!)
|
|
57
|
+
prune_expired
|
|
58
|
+
{ cells_remaining: @memory_cells.size }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def find_by_signature(signature)
|
|
62
|
+
@memory_cells.values.find { |c| c.signature == signature.to_s && !c.expired? }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def cells_for_threat(threat_type:)
|
|
66
|
+
@memory_cells.values.select { |c| c.threat_type == threat_type.to_sym && !c.expired? }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def immunity_for(threat_type:)
|
|
70
|
+
cells = cells_for_threat(threat_type: threat_type)
|
|
71
|
+
return 0.0 if cells.empty?
|
|
72
|
+
|
|
73
|
+
cells.max_by(&:strength).strength
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def active_cells = @memory_cells.values.reject(&:expired?)
|
|
77
|
+
def t_cells = @memory_cells.values.select(&:t_cell?)
|
|
78
|
+
def b_cells = @memory_cells.values.select(&:b_cell?)
|
|
79
|
+
def veteran_cells = @memory_cells.values.select(&:veteran?)
|
|
80
|
+
def naive_cells = @memory_cells.values.select(&:naive?)
|
|
81
|
+
|
|
82
|
+
def encounters_for(threat_type:)
|
|
83
|
+
@encounters.select { |e| e.threat_type == threat_type.to_sym }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def secondary_response_rate
|
|
87
|
+
return 0.0 if @encounters.empty?
|
|
88
|
+
|
|
89
|
+
secondary = @encounters.count(&:secondary?)
|
|
90
|
+
(secondary.to_f / @encounters.size).round(10)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def neutralization_rate
|
|
94
|
+
return 0.0 if @encounters.empty?
|
|
95
|
+
|
|
96
|
+
neutralized = @encounters.count(&:neutralized?)
|
|
97
|
+
(neutralized.to_f / @encounters.size).round(10)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def average_response_speed
|
|
101
|
+
return PRIMARY_RESPONSE_SPEED if @encounters.empty?
|
|
102
|
+
|
|
103
|
+
(@encounters.sum(&:response_speed) / @encounters.size).round(10)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def threat_coverage
|
|
107
|
+
known_types = @memory_cells.values.map(&:threat_type).uniq
|
|
108
|
+
(known_types.size.to_f / THREAT_TYPES.size).clamp(0.0, 1.0).round(10)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def overall_health
|
|
112
|
+
return 0.0 if @memory_cells.empty?
|
|
113
|
+
|
|
114
|
+
avg_strength = (@memory_cells.values.sum(&:strength) / @memory_cells.size).round(10)
|
|
115
|
+
coverage_factor = threat_coverage
|
|
116
|
+
((avg_strength * 0.6) + (coverage_factor * 0.4)).clamp(0.0, 1.0).round(10)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def health_label = Constants.label_for(HEALTH_LABELS, overall_health)
|
|
120
|
+
|
|
121
|
+
def immune_report
|
|
122
|
+
{
|
|
123
|
+
total_cells: @memory_cells.size,
|
|
124
|
+
active_cells: active_cells.size,
|
|
125
|
+
t_cells: t_cells.size,
|
|
126
|
+
b_cells: b_cells.size,
|
|
127
|
+
veteran_cells: veteran_cells.size,
|
|
128
|
+
total_encounters: @encounters.size,
|
|
129
|
+
secondary_response_rate: secondary_response_rate,
|
|
130
|
+
neutralization_rate: neutralization_rate,
|
|
131
|
+
average_response_speed: average_response_speed,
|
|
132
|
+
threat_coverage: threat_coverage,
|
|
133
|
+
overall_health: overall_health,
|
|
134
|
+
health_label: health_label
|
|
135
|
+
}
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def to_h
|
|
139
|
+
{
|
|
140
|
+
total_cells: @memory_cells.size,
|
|
141
|
+
active: active_cells.size,
|
|
142
|
+
encounters: @encounters.size,
|
|
143
|
+
health: overall_health,
|
|
144
|
+
threat_coverage: threat_coverage
|
|
145
|
+
}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
def determine_outcome(matching_cell, severity)
|
|
151
|
+
return :neutralized if matching_cell && matching_cell.strength >= severity
|
|
152
|
+
|
|
153
|
+
severity < 0.5 ? :neutralized : :evaded
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def prune_expired
|
|
157
|
+
@memory_cells.reject! { |_, c| c.expired? } if @memory_cells.size >= MAX_MEMORY_CELLS
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def prune_encounters
|
|
161
|
+
@encounters.shift while @encounters.size > MAX_ENCOUNTERS
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|