lex-agentic-defense 0.1.6 → 0.1.7
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -0
- data/lib/legion/extensions/agentic/defense/avalanche/helpers/constants.rb +1 -1
- data/lib/legion/extensions/agentic/defense/bias/actors/update.rb +1 -1
- data/lib/legion/extensions/agentic/defense/bias/runners/bias.rb +15 -15
- data/lib/legion/extensions/agentic/defense/confabulation/actors/decay.rb +1 -1
- data/lib/legion/extensions/agentic/defense/confabulation/runners/confabulation.rb +12 -12
- data/lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb +13 -13
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/actors/update.rb +1 -1
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/runners/epistemic_vigilance.rb +12 -12
- data/lib/legion/extensions/agentic/defense/erosion/runners/cognitive_erosion.rb +8 -8
- data/lib/legion/extensions/agentic/defense/error_monitoring/actors/tick.rb +1 -1
- data/lib/legion/extensions/agentic/defense/error_monitoring/runners/error_monitoring.rb +12 -12
- data/lib/legion/extensions/agentic/defense/extinction/actors/protocol_monitor.rb +1 -1
- data/lib/legion/extensions/agentic/defense/extinction/helpers/protocol_state.rb +7 -7
- data/lib/legion/extensions/agentic/defense/extinction/runners/extinction.rb +18 -18
- data/lib/legion/extensions/agentic/defense/immunology/helpers/immune_engine.rb +11 -9
- data/lib/legion/extensions/agentic/defense/immunology/runners/cognitive_immunology.rb +2 -2
- data/lib/legion/extensions/agentic/defense/phantom/helpers/phantom_engine.rb +7 -5
- data/lib/legion/extensions/agentic/defense/phantom/runners/cognitive_phantom.rb +7 -7
- data/lib/legion/extensions/agentic/defense/quicksilver/runners/cognitive_quicksilver.rb +21 -21
- data/lib/legion/extensions/agentic/defense/version.rb +1 -1
- data/lib/legion/extensions/agentic/defense/whirlpool/runners/cognitive_whirlpool.rb +16 -16
- data/lib/legion/extensions/agentic/defense.rb +1 -1
- data/spec/legion/extensions/agentic/defense/extinction/local_persistence_spec.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 583446b8b39752f9796c8f86906319984b4a8ae9c4b9589a69f70d403b737aad
|
|
4
|
+
data.tar.gz: 38add46e9a7209f9f4266db6b6616dd04d6ae98d0e97f1122d5cb34a9ea7823c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 23b0d5d145f941e42167bd0f0d6211b7f560d43794e1b75eaf0a573fbc1323549e6eec52e80ad1b1546a5d633aef1fe4f6adeaf56cbc4415d4b7b1ed329031ab
|
|
7
|
+
data.tar.gz: c8c01a2513df60680899b495b7565892fd2d487b46d75db63f8a28adee67f5b94023688ef61a7448b2f66f7f16399ad5431c6c772335e120a0a47055c38358f6
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
|
@@ -33,7 +33,7 @@ module Legion
|
|
|
33
33
|
}.freeze
|
|
34
34
|
|
|
35
35
|
def self.label_for(table, value)
|
|
36
|
-
const_get(table).find { |range, _| range.cover?(value.clamp(0.0, 1.0)) }&.last || :unknown
|
|
36
|
+
const_get(table, false).find { |range, _| range.cover?(value.clamp(0.0, 1.0)) }&.last || :unknown
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
end
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Defense
|
|
9
9
|
module Bias
|
|
10
10
|
module Actor
|
|
11
|
-
class Update < Legion::Extensions::Actors::Every
|
|
11
|
+
class Update < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Defense::Bias::Runners::Bias
|
|
14
14
|
end
|
|
@@ -7,44 +7,44 @@ module Legion
|
|
|
7
7
|
module Bias
|
|
8
8
|
module Runners
|
|
9
9
|
module Bias
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def check_for_bias(domain:, decision_context: {}, **)
|
|
14
|
-
|
|
14
|
+
log.debug("[bias] check_for_bias domain=#{domain}")
|
|
15
15
|
detected = collect_bias_detections(domain, decision_context)
|
|
16
16
|
active = detected.select { |b| b[:magnitude] >= Helpers::Constants::DETECTION_THRESHOLD }
|
|
17
|
-
|
|
17
|
+
log.debug("[bias] check_for_bias domain=#{domain} detected=#{active.size}")
|
|
18
18
|
{ success: true, domain: domain, detected: active, all: detected }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def record_anchor(domain:, value:, **)
|
|
22
22
|
bias_store.register_anchor(domain, value: value)
|
|
23
|
-
|
|
23
|
+
log.debug("[bias] anchor recorded domain=#{domain} value=#{value}")
|
|
24
24
|
{ success: true, domain: domain, value: value }
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def update_bias(**)
|
|
28
28
|
bias_store.decay_anchors
|
|
29
|
-
|
|
29
|
+
log.debug('[bias] update_bias: anchors decayed')
|
|
30
30
|
{ success: true }
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def bias_report(domain: nil, **)
|
|
34
34
|
events = domain ? bias_store.by_domain(domain) : bias_store.recent(50)
|
|
35
|
-
|
|
35
|
+
log.debug("[bias] bias_report domain=#{domain.inspect} events=#{events.size}")
|
|
36
36
|
{ success: true, domain: domain, events: events, count: events.size }
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def susceptibility_profile(**)
|
|
40
40
|
profile = bias_detector.to_h
|
|
41
|
-
|
|
41
|
+
log.debug('[bias] susceptibility_profile')
|
|
42
42
|
{ success: true, **profile }
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def bias_stats(**)
|
|
46
46
|
stats = bias_store.stats
|
|
47
|
-
|
|
47
|
+
log.debug("[bias] bias_stats total=#{stats[:total]}")
|
|
48
48
|
{ success: true, **stats }
|
|
49
49
|
end
|
|
50
50
|
|
|
@@ -70,10 +70,10 @@ module Legion
|
|
|
70
70
|
|
|
71
71
|
def detect_anchoring_bias(domain, ctx)
|
|
72
72
|
anchors = bias_store.anchors_for(domain)
|
|
73
|
-
return [] unless anchors.any? && ctx[:current_value]
|
|
73
|
+
return [] unless anchors.any? && ctx[:current_value] # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
74
74
|
|
|
75
75
|
anchor_value = anchors.max_by { |a| a[:influence] }&.dig(:value)
|
|
76
|
-
return [] unless anchor_value
|
|
76
|
+
return [] unless anchor_value # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
77
77
|
|
|
78
78
|
mag = bias_detector.detect_anchoring(
|
|
79
79
|
current_value: ctx[:current_value],
|
|
@@ -84,7 +84,7 @@ module Legion
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def detect_confirmation_bias(domain, ctx)
|
|
87
|
-
return [] unless ctx[:evidence_direction] && ctx[:hypothesis_direction]
|
|
87
|
+
return [] unless ctx[:evidence_direction] && ctx[:hypothesis_direction] # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
88
88
|
|
|
89
89
|
mag = bias_detector.detect_confirmation(
|
|
90
90
|
evidence_direction: ctx[:evidence_direction],
|
|
@@ -95,21 +95,21 @@ module Legion
|
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
def detect_availability_bias(domain, ctx)
|
|
98
|
-
return [] unless ctx[:recent_events]
|
|
98
|
+
return [] unless ctx[:recent_events] # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
99
99
|
|
|
100
100
|
mag = bias_detector.detect_availability(recent_events: ctx[:recent_events], domain: domain)
|
|
101
101
|
[build_bias_result(:availability, domain, mag, ctx)]
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
def detect_recency_bias(domain, ctx)
|
|
105
|
-
return [] unless ctx[:data_points]
|
|
105
|
+
return [] unless ctx[:data_points] # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
106
106
|
|
|
107
107
|
mag = bias_detector.detect_recency(data_points: ctx[:data_points], domain: domain)
|
|
108
108
|
[build_bias_result(:recency, domain, mag, ctx)]
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
def detect_sunk_cost_bias(domain, ctx)
|
|
112
|
-
return [] unless ctx[:invested] && !ctx[:expected_return].nil?
|
|
112
|
+
return [] unless ctx[:invested] && !ctx[:expected_return].nil? # rubocop:disable Legion/Extension/RunnerReturnHash
|
|
113
113
|
|
|
114
114
|
mag = bias_detector.detect_sunk_cost(
|
|
115
115
|
invested: ctx[:invested],
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Defense
|
|
9
9
|
module Confabulation
|
|
10
10
|
module Actor
|
|
11
|
-
class Decay < Legion::Extensions::Actors::Every
|
|
11
|
+
class Decay < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Defense::Confabulation::Runners::Confabulation
|
|
14
14
|
end
|
|
@@ -7,8 +7,8 @@ module Legion
|
|
|
7
7
|
module Confabulation
|
|
8
8
|
module Runners
|
|
9
9
|
module Confabulation
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def register_claim(content:, claim_type: :factual, confidence: 0.5, evidence_strength: 0.5, **)
|
|
14
14
|
claim = confabulation_engine.register_claim(
|
|
@@ -17,17 +17,17 @@ module Legion
|
|
|
17
17
|
confidence: confidence,
|
|
18
18
|
evidence_strength: evidence_strength
|
|
19
19
|
)
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
log.debug("[confabulation] register: id=#{claim.id} type=#{claim.claim_type} " \
|
|
21
|
+
"risk=#{claim.confabulation_risk.round(2)} label=#{claim.risk_label}")
|
|
22
22
|
claim.to_h
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def verify_claim(claim_id:, **)
|
|
26
26
|
result = confabulation_engine.verify_claim(claim_id: claim_id)
|
|
27
27
|
if result[:found]
|
|
28
|
-
|
|
28
|
+
log.info("[confabulation] verified: claim_id=#{claim_id}")
|
|
29
29
|
else
|
|
30
|
-
|
|
30
|
+
log.debug("[confabulation] verify: claim_id=#{claim_id} not found")
|
|
31
31
|
end
|
|
32
32
|
result
|
|
33
33
|
end
|
|
@@ -35,24 +35,24 @@ module Legion
|
|
|
35
35
|
def flag_confabulation(claim_id:, **)
|
|
36
36
|
result = confabulation_engine.flag_confabulation(claim_id: claim_id)
|
|
37
37
|
if result[:found]
|
|
38
|
-
|
|
38
|
+
log.warn("[confabulation] flagged: claim_id=#{claim_id} marked as confabulated")
|
|
39
39
|
else
|
|
40
|
-
|
|
40
|
+
log.debug("[confabulation] flag: claim_id=#{claim_id} not found")
|
|
41
41
|
end
|
|
42
42
|
result
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def confabulation_report(**)
|
|
46
46
|
report = confabulation_engine.confabulation_report
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
log.debug("[confabulation] report: total=#{report[:total_claims]} " \
|
|
48
|
+
"high_risk=#{report[:high_risk_claims]} " \
|
|
49
|
+
"rate=#{report[:confabulation_rate].round(2)} label=#{report[:risk_label]}")
|
|
50
50
|
report
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def high_risk_claims(**)
|
|
54
54
|
claims = confabulation_engine.high_risk_claims
|
|
55
|
-
|
|
55
|
+
log.debug("[confabulation] high_risk_claims: count=#{claims.size}")
|
|
56
56
|
{ claims: claims.map(&:to_h), count: claims.size }
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -7,8 +7,8 @@ module Legion
|
|
|
7
7
|
module Dissonance
|
|
8
8
|
module Runners
|
|
9
9
|
module Dissonance
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def add_belief(domain:, content:, confidence: 0.7, importance: :moderate, **)
|
|
14
14
|
unless Helpers::Constants::IMPORTANCE_WEIGHTS.key?(importance)
|
|
@@ -21,7 +21,7 @@ module Legion
|
|
|
21
21
|
belief = result[:belief]
|
|
22
22
|
new_evs = result[:new_dissonance_events]
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
log.debug("[dissonance] add_belief: id=#{belief.id[0..7]} domain=#{domain} importance=#{importance} new_events=#{new_evs.size}")
|
|
25
25
|
|
|
26
26
|
{
|
|
27
27
|
success: true,
|
|
@@ -37,7 +37,7 @@ module Legion
|
|
|
37
37
|
new_stress = dissonance_model.decay
|
|
38
38
|
unresolved = dissonance_model.unresolved_events
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
log.debug("[dissonance] update: stress=#{new_stress.round(3)} unresolved=#{unresolved.size}")
|
|
41
41
|
|
|
42
42
|
{
|
|
43
43
|
success: true,
|
|
@@ -55,10 +55,10 @@ module Legion
|
|
|
55
55
|
|
|
56
56
|
event = dissonance_model.resolve(event_id, strategy: strategy)
|
|
57
57
|
if event
|
|
58
|
-
|
|
58
|
+
log.debug("[dissonance] resolved: id=#{event_id[0..7]} strategy=#{strategy}")
|
|
59
59
|
{ success: true, resolved: true, strategy: strategy, event: event.to_h }
|
|
60
60
|
else
|
|
61
|
-
|
|
61
|
+
log.debug("[dissonance] resolve failed: id=#{event_id[0..7]} not_found_or_already_resolved")
|
|
62
62
|
{ success: false, error: :not_found_or_already_resolved }
|
|
63
63
|
end
|
|
64
64
|
end
|
|
@@ -67,8 +67,8 @@ module Legion
|
|
|
67
67
|
model = dissonance_model
|
|
68
68
|
snapshot = model.to_h
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
log.debug("[dissonance] status: stress=#{snapshot[:stress].round(3)} " \
|
|
71
|
+
"beliefs=#{snapshot[:total_beliefs]} unresolved=#{snapshot[:unresolved_count]}")
|
|
72
72
|
|
|
73
73
|
{
|
|
74
74
|
success: true,
|
|
@@ -83,7 +83,7 @@ module Legion
|
|
|
83
83
|
stress = dissonance_model.domain_stress(domain)
|
|
84
84
|
unresolved = dissonance_model.unresolved_events.select { |ev| ev.domain == domain }
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
log.debug("[dissonance] domain_dissonance: domain=#{domain} stress=#{stress.round(3)} unresolved=#{unresolved.size}")
|
|
87
87
|
|
|
88
88
|
{
|
|
89
89
|
success: true,
|
|
@@ -97,7 +97,7 @@ module Legion
|
|
|
97
97
|
def beliefs_for(domain:, **)
|
|
98
98
|
beliefs = dissonance_model.beliefs.values.select { |b| b.domain == domain }
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
log.debug("[dissonance] beliefs_for: domain=#{domain} count=#{beliefs.size}")
|
|
101
101
|
|
|
102
102
|
{
|
|
103
103
|
success: true,
|
|
@@ -110,7 +110,7 @@ module Legion
|
|
|
110
110
|
def unresolved(**)
|
|
111
111
|
events = dissonance_model.unresolved_events
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
log.debug("[dissonance] unresolved: count=#{events.size}")
|
|
114
114
|
|
|
115
115
|
{
|
|
116
116
|
success: true,
|
|
@@ -133,8 +133,8 @@ module Legion
|
|
|
133
133
|
[s, resolved.count { |ev| ev.resolution_strategy == s }]
|
|
134
134
|
end
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
log.debug("[dissonance] stats: beliefs=#{snapshot[:total_beliefs]} " \
|
|
137
|
+
"events=#{snapshot[:total_events]} stress=#{snapshot[:stress].round(3)}")
|
|
138
138
|
|
|
139
139
|
{
|
|
140
140
|
success: true,
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Defense
|
|
9
9
|
module EpistemicVigilance
|
|
10
10
|
module Actor
|
|
11
|
-
class Update < Legion::Extensions::Actors::Every
|
|
11
|
+
class Update < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Defense::EpistemicVigilance::Runners::EpistemicVigilance
|
|
14
14
|
end
|
data/lib/legion/extensions/agentic/defense/epistemic_vigilance/runners/epistemic_vigilance.rb
CHANGED
|
@@ -7,69 +7,69 @@ module Legion
|
|
|
7
7
|
module EpistemicVigilance
|
|
8
8
|
module Runners
|
|
9
9
|
module EpistemicVigilance
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def register_epistemic_source(name:, domain:, **)
|
|
14
14
|
result = engine.register_source(name: name, domain: domain)
|
|
15
|
-
|
|
15
|
+
log.info("[epistemic_vigilance] registered source name=#{name} domain=#{domain} id=#{result[:id]}")
|
|
16
16
|
result
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def submit_epistemic_claim(content:, source_id:, domain:, initial_confidence: 0.5, **)
|
|
20
20
|
result = engine.submit_claim(content: content, source_id: source_id, domain: domain,
|
|
21
21
|
initial_confidence: initial_confidence)
|
|
22
|
-
|
|
22
|
+
log.debug("[epistemic_vigilance] claim submitted domain=#{domain} verdict=#{result.dig(:assessment, :recommended_verdict)}")
|
|
23
23
|
result
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def assess_epistemic_claim(claim_id:, **)
|
|
27
27
|
result = engine.assess_claim(claim_id: claim_id)
|
|
28
|
-
|
|
28
|
+
log.debug("[epistemic_vigilance] assess claim_id=#{claim_id} total=#{result[:total_score]&.round(3)}")
|
|
29
29
|
result
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def support_epistemic_claim(claim_id:, **)
|
|
33
33
|
result = engine.support_claim(claim_id: claim_id)
|
|
34
|
-
|
|
34
|
+
log.debug("[epistemic_vigilance] support claim_id=#{claim_id} confidence=#{result[:confidence]&.round(3)}")
|
|
35
35
|
result
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def challenge_epistemic_claim(claim_id:, **)
|
|
39
39
|
result = engine.challenge_claim(claim_id: claim_id)
|
|
40
|
-
|
|
40
|
+
log.debug("[epistemic_vigilance] challenge claim_id=#{claim_id} confidence=#{result[:confidence]&.round(3)}")
|
|
41
41
|
result
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def adjudicate_epistemic_claim(claim_id:, verdict:, **)
|
|
45
45
|
result = engine.adjudicate_claim(claim_id: claim_id, verdict: verdict)
|
|
46
|
-
|
|
46
|
+
log.info("[epistemic_vigilance] adjudicate claim_id=#{claim_id} verdict=#{verdict}")
|
|
47
47
|
result
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def source_reliability_report(source_id:, **)
|
|
51
51
|
result = engine.source_reliability(source_id: source_id)
|
|
52
|
-
|
|
52
|
+
log.debug("[epistemic_vigilance] source reliability source_id=#{source_id} label=#{result[:label]}")
|
|
53
53
|
result
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def contested_claims_report(**)
|
|
57
57
|
claims = engine.contested_claims
|
|
58
|
-
|
|
58
|
+
log.debug("[epistemic_vigilance] contested claims count=#{claims.size}")
|
|
59
59
|
{ contested: claims, count: claims.size }
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def domain_vigilance_report(domain:, **)
|
|
63
63
|
level = engine.domain_vigilance_level(domain: domain)
|
|
64
64
|
claims = engine.claims_by_domain(domain: domain)
|
|
65
|
-
|
|
65
|
+
log.debug("[epistemic_vigilance] domain=#{domain} vigilance_level=#{level} claims=#{claims.size}")
|
|
66
66
|
{ domain: domain, vigilance_level: level, claims: claims, count: claims.size }
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def update_epistemic_vigilance(**)
|
|
70
70
|
decay_result = engine.decay_all
|
|
71
71
|
prune_result = engine.prune_rejected
|
|
72
|
-
|
|
72
|
+
log.debug("[epistemic_vigilance] decay+prune decayed=#{decay_result[:decayed]} pruned=#{prune_result[:pruned]}")
|
|
73
73
|
{ decay: decay_result, prune: prune_result }
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -19,30 +19,30 @@ module Legion
|
|
|
19
19
|
content: content,
|
|
20
20
|
resistance: resistance
|
|
21
21
|
)
|
|
22
|
-
|
|
22
|
+
log.debug("[cognitive_erosion] formation created: #{result[:formation_id]}") if result[:success]
|
|
23
23
|
result
|
|
24
24
|
rescue ArgumentError => e
|
|
25
|
-
|
|
25
|
+
log.warn("[cognitive_erosion] create_formation failed: #{e.message}")
|
|
26
26
|
{ success: false, error: e.message }
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def erode(formation_id:, agent:, force:, engine: nil, **)
|
|
30
30
|
eng = engine || default_engine
|
|
31
31
|
result = eng.erode(formation_id: formation_id, agent: agent, force: force)
|
|
32
|
-
|
|
32
|
+
log.debug("[cognitive_erosion] eroded #{formation_id[0..7]} agent=#{agent} force=#{force.round(3)}") if result[:success]
|
|
33
33
|
result
|
|
34
34
|
rescue ArgumentError => e
|
|
35
|
-
|
|
35
|
+
log.warn("[cognitive_erosion] erode failed: #{e.message}")
|
|
36
36
|
{ success: false, error: e.message }
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def weather_all(force: 0.05, agent: :wind, engine: nil, **)
|
|
40
40
|
eng = engine || default_engine
|
|
41
41
|
result = eng.weather_all!(force: force, agent: agent)
|
|
42
|
-
|
|
42
|
+
log.debug("[cognitive_erosion] weather_all: #{result[:weathered]} formations weathered") if result[:success]
|
|
43
43
|
result
|
|
44
44
|
rescue ArgumentError => e
|
|
45
|
-
|
|
45
|
+
log.warn("[cognitive_erosion] weather_all failed: #{e.message}")
|
|
46
46
|
{ success: false, error: e.message }
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -65,8 +65,8 @@ module Legion
|
|
|
65
65
|
def erosion_report(engine: nil, **)
|
|
66
66
|
eng = engine || default_engine
|
|
67
67
|
result = eng.erosion_report
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
log.debug("[cognitive_erosion] report: formations=#{result[:total_formations]} " \
|
|
69
|
+
"channels=#{result[:total_channels]} canyons=#{result[:canyons]}")
|
|
70
70
|
result
|
|
71
71
|
rescue ArgumentError => e
|
|
72
72
|
{ success: false, error: e.message }
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Defense
|
|
9
9
|
module ErrorMonitoring
|
|
10
10
|
module Actor
|
|
11
|
-
class Tick < Legion::Extensions::Actors::Every
|
|
11
|
+
class Tick < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Defense::ErrorMonitoring::Runners::ErrorMonitoring
|
|
14
14
|
end
|
|
@@ -7,11 +7,11 @@ module Legion
|
|
|
7
7
|
module ErrorMonitoring
|
|
8
8
|
module Runners
|
|
9
9
|
module ErrorMonitoring
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def report_error(action:, domain:, intended:, actual:, severity:, **)
|
|
14
|
-
|
|
14
|
+
log.debug("[error_monitor] error: action=#{action} domain=#{domain} severity=#{severity}")
|
|
15
15
|
signal = monitor.register_error(
|
|
16
16
|
action: action, domain: domain,
|
|
17
17
|
intended: intended, actual: actual, severity: severity
|
|
@@ -25,13 +25,13 @@ module Legion
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def report_success(action:, domain:, **)
|
|
28
|
-
|
|
28
|
+
log.debug("[error_monitor] success: action=#{action} domain=#{domain}")
|
|
29
29
|
result = monitor.register_success(action: action, domain: domain)
|
|
30
30
|
{ success: true, action: action, domain: domain, error_rate: result[:error_rate] }
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def report_conflict(action_a:, action_b:, domain:, intensity:, **)
|
|
34
|
-
|
|
34
|
+
log.debug("[error_monitor] conflict: #{action_a} vs #{action_b} domain=#{domain}")
|
|
35
35
|
entry = monitor.register_conflict(
|
|
36
36
|
action_a: action_a, action_b: action_b,
|
|
37
37
|
domain: domain, intensity: intensity
|
|
@@ -40,7 +40,7 @@ module Legion
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def apply_correction(action:, domain:, original_error:, correction:, **)
|
|
43
|
-
|
|
43
|
+
log.debug("[error_monitor] correction: action=#{action} domain=#{domain}")
|
|
44
44
|
entry = monitor.register_correction(
|
|
45
45
|
action: action, domain: domain,
|
|
46
46
|
original_error: original_error, correction: correction
|
|
@@ -50,25 +50,25 @@ module Legion
|
|
|
50
50
|
|
|
51
51
|
def recent_errors(limit: 10, **)
|
|
52
52
|
errors = monitor.recent_errors(limit: limit.to_i).map(&:to_h)
|
|
53
|
-
|
|
53
|
+
log.debug("[error_monitor] recent_errors: #{errors.size}")
|
|
54
54
|
{ success: true, errors: errors, count: errors.size }
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def errors_in_domain(domain:, **)
|
|
58
58
|
errors = monitor.errors_in(domain: domain).map(&:to_h)
|
|
59
|
-
|
|
59
|
+
log.debug("[error_monitor] errors_in: domain=#{domain} count=#{errors.size}")
|
|
60
60
|
{ success: true, domain: domain, errors: errors, count: errors.size }
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
def uncorrected_errors(**)
|
|
64
64
|
errors = monitor.uncorrected_errors.map(&:to_h)
|
|
65
|
-
|
|
65
|
+
log.debug("[error_monitor] uncorrected: #{errors.size}")
|
|
66
66
|
{ success: true, errors: errors, count: errors.size }
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def monitoring_state(**)
|
|
70
70
|
state = monitor.monitoring_state
|
|
71
|
-
|
|
71
|
+
log.debug("[error_monitor] state: #{state}")
|
|
72
72
|
{
|
|
73
73
|
success: true, state: state,
|
|
74
74
|
label: Helpers::Constants::MONITORING_STATE_LABELS[state],
|
|
@@ -78,13 +78,13 @@ module Legion
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def update_error_monitoring(**)
|
|
81
|
-
|
|
81
|
+
log.debug('[error_monitor] tick')
|
|
82
82
|
monitor.tick
|
|
83
83
|
{ success: true, state: monitor.monitoring_state, slowdown: monitor.slowdown.round(4) }
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def error_monitoring_stats(**)
|
|
87
|
-
|
|
87
|
+
log.debug('[error_monitor] stats')
|
|
88
88
|
{ success: true, stats: monitor.to_h }
|
|
89
89
|
end
|
|
90
90
|
|
|
@@ -8,7 +8,7 @@ module Legion
|
|
|
8
8
|
module Defense
|
|
9
9
|
module Extinction
|
|
10
10
|
module Actor
|
|
11
|
-
class ProtocolMonitor < Legion::Extensions::Actors::Every
|
|
11
|
+
class ProtocolMonitor < Legion::Extensions::Actors::Every # rubocop:disable Legion/Extension/EveryActorRequiresTime
|
|
12
12
|
def runner_class
|
|
13
13
|
Legion::Extensions::Agentic::Defense::Extinction::Runners::Extinction
|
|
14
14
|
end
|
|
@@ -63,7 +63,7 @@ module Legion
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def save_to_local
|
|
66
|
-
return unless defined?(Legion::Data::Local) &&
|
|
66
|
+
return unless defined?(Legion::Data::Local) && local_data_connected?
|
|
67
67
|
|
|
68
68
|
row = {
|
|
69
69
|
id: 1,
|
|
@@ -72,13 +72,13 @@ module Legion
|
|
|
72
72
|
history: ::JSON.dump(@history.map { |h| h.merge(at: h[:at].to_s) }),
|
|
73
73
|
updated_at: Time.now.utc
|
|
74
74
|
}
|
|
75
|
-
db =
|
|
75
|
+
db = local_data_connection
|
|
76
76
|
if db[:extinction_state].where(id: 1).any?
|
|
77
77
|
db[:extinction_state].where(id: 1).update(row.except(:id))
|
|
78
78
|
else
|
|
79
79
|
db[:extinction_state].insert(row)
|
|
80
80
|
end
|
|
81
|
-
rescue StandardError
|
|
81
|
+
rescue StandardError => _e
|
|
82
82
|
nil
|
|
83
83
|
end
|
|
84
84
|
|
|
@@ -89,16 +89,16 @@ module Legion
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
def load_from_local
|
|
92
|
-
return unless defined?(Legion::Data::Local) &&
|
|
92
|
+
return unless defined?(Legion::Data::Local) && local_data_connected?
|
|
93
93
|
|
|
94
|
-
row =
|
|
94
|
+
row = local_data_connection[:extinction_state].where(id: 1).first
|
|
95
95
|
return unless row
|
|
96
96
|
|
|
97
97
|
db_level = row[:current_level].to_i
|
|
98
98
|
@current_level = [db_level, @current_level].max
|
|
99
99
|
@active = [true, 1].include?(row[:active])
|
|
100
100
|
@history = parse_history(row[:history])
|
|
101
|
-
rescue StandardError
|
|
101
|
+
rescue StandardError => _e
|
|
102
102
|
nil
|
|
103
103
|
end
|
|
104
104
|
|
|
@@ -113,7 +113,7 @@ module Legion
|
|
|
113
113
|
at: Time.parse(h[:at].to_s)
|
|
114
114
|
)
|
|
115
115
|
end
|
|
116
|
-
rescue StandardError
|
|
116
|
+
rescue StandardError => _e
|
|
117
117
|
[]
|
|
118
118
|
end
|
|
119
119
|
end
|
|
@@ -7,20 +7,20 @@ module Legion
|
|
|
7
7
|
module Extinction
|
|
8
8
|
module Runners
|
|
9
9
|
module Extinction
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def escalate(level:, authority:, reason:, **)
|
|
14
14
|
result = protocol_state.escalate(level, authority: authority, reason: reason)
|
|
15
15
|
case result
|
|
16
16
|
when :escalated
|
|
17
17
|
info = Helpers::Levels.level_info(level)
|
|
18
|
-
|
|
18
|
+
log.warn("[extinction] ESCALATED: level=#{level} name=#{info[:name]} authority=#{authority} reason=#{reason}")
|
|
19
19
|
enforce_escalation_effects(level)
|
|
20
20
|
emit_escalation_event(level, authority, reason)
|
|
21
21
|
{ escalated: true, level: level, info: info }
|
|
22
22
|
else
|
|
23
|
-
|
|
23
|
+
log.debug("[extinction] escalation denied: level=#{level} reason=#{result}")
|
|
24
24
|
{ escalated: false, reason: result }
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -29,17 +29,17 @@ module Legion
|
|
|
29
29
|
result = protocol_state.deescalate(target_level, authority: authority, reason: reason)
|
|
30
30
|
case result
|
|
31
31
|
when :deescalated
|
|
32
|
-
|
|
32
|
+
log.info("[extinction] de-escalated: target=#{target_level} authority=#{authority} reason=#{reason}")
|
|
33
33
|
{ deescalated: true, level: target_level }
|
|
34
34
|
else
|
|
35
|
-
|
|
35
|
+
log.debug("[extinction] de-escalation denied: target=#{target_level} reason=#{result}")
|
|
36
36
|
{ deescalated: false, reason: result }
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def extinction_status(**)
|
|
41
41
|
status = protocol_state.to_h
|
|
42
|
-
|
|
42
|
+
log.debug("[extinction] status: level=#{status[:current_level]} active=#{status[:active]}")
|
|
43
43
|
status
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -48,10 +48,10 @@ module Legion
|
|
|
48
48
|
level = status[:current_level]
|
|
49
49
|
|
|
50
50
|
if level.positive?
|
|
51
|
-
|
|
51
|
+
log.warn("[extinction] ACTIVE: level=#{level} active=#{status[:active]}")
|
|
52
52
|
detect_stale_escalation(level)
|
|
53
53
|
else
|
|
54
|
-
|
|
54
|
+
log.debug('[extinction] status: level=0 active=false')
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
status
|
|
@@ -59,7 +59,7 @@ module Legion
|
|
|
59
59
|
|
|
60
60
|
def check_reversibility(level:, **)
|
|
61
61
|
reversible = Helpers::Levels.reversible?(level)
|
|
62
|
-
|
|
62
|
+
log.debug("[extinction] reversibility: level=#{level} reversible=#{reversible}")
|
|
63
63
|
{
|
|
64
64
|
level: level,
|
|
65
65
|
reversible: reversible,
|
|
@@ -74,14 +74,14 @@ module Legion
|
|
|
74
74
|
def enforce_escalation_effects(level)
|
|
75
75
|
if level >= 1 && defined?(Legion::Extensions::Mesh::Runners::Mesh)
|
|
76
76
|
Legion::Extensions::Mesh::Runners::Mesh.disconnect rescue nil # rubocop:disable Style/RescueModifier
|
|
77
|
-
|
|
77
|
+
log.warn('[extinction] mesh isolation enforced')
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
return unless level == 4
|
|
81
81
|
|
|
82
82
|
if defined?(Legion::Extensions::Privatecore::Runners::Privatecore)
|
|
83
83
|
Legion::Extensions::Privatecore::Runners::Privatecore.erase_all rescue nil # rubocop:disable Style/RescueModifier
|
|
84
|
-
|
|
84
|
+
log.warn('[extinction] cryptographic erasure triggered')
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
if defined?(Legion::Data::Model::DigitalWorker)
|
|
@@ -89,10 +89,10 @@ module Legion
|
|
|
89
89
|
Legion::Data::Model::DigitalWorker.where(lifecycle_state: 'active').update(
|
|
90
90
|
lifecycle_state: 'terminated', updated_at: Time.now.utc
|
|
91
91
|
)
|
|
92
|
-
rescue StandardError
|
|
92
|
+
rescue StandardError => _e
|
|
93
93
|
nil
|
|
94
94
|
end
|
|
95
|
-
|
|
95
|
+
log.warn('[extinction] all active workers terminated')
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
return unless defined?(Legion::Extensions::Apollo::Runners::Knowledge)
|
|
@@ -100,9 +100,9 @@ module Legion
|
|
|
100
100
|
begin
|
|
101
101
|
obj = Object.new.extend(Legion::Extensions::Apollo::Runners::Knowledge)
|
|
102
102
|
obj.handle_erasure_request(agent_id: 'system:extinction')
|
|
103
|
-
|
|
103
|
+
log.warn('[extinction] apollo erasure propagated')
|
|
104
104
|
rescue StandardError => e
|
|
105
|
-
|
|
105
|
+
log.error("[extinction] apollo erasure failed: #{e.message}")
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
|
|
@@ -116,10 +116,10 @@ module Legion
|
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
def detect_stale_escalation(level)
|
|
119
|
-
last_escalation = protocol_state.history.
|
|
119
|
+
last_escalation = protocol_state.history.reverse.find { |h| h[:action] == :escalate }
|
|
120
120
|
return unless last_escalation && (Time.now.utc - last_escalation[:at]) > STALE_ESCALATION_THRESHOLD
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
log.warn("[extinction] STALE: level=#{level} has been active > 24 hours")
|
|
123
123
|
return unless defined?(Legion::Events)
|
|
124
124
|
|
|
125
125
|
Legion::Events.emit('extinction.stale_escalation', {
|
|
@@ -7,6 +7,8 @@ module Legion
|
|
|
7
7
|
module Immunology
|
|
8
8
|
module Helpers
|
|
9
9
|
class ImmuneEngine
|
|
10
|
+
include Legion::Extensions::Helpers::Lex
|
|
11
|
+
|
|
10
12
|
attr_reader :resistance, :inflammatory
|
|
11
13
|
|
|
12
14
|
def initialize
|
|
@@ -36,7 +38,7 @@ module Legion
|
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
@threats[threat.id] = threat
|
|
39
|
-
|
|
41
|
+
log.debug("[cognitive_immunology] threat detected: id=#{threat.id} tactic=#{tactic} level=#{threat.threat_level.round(2)}")
|
|
40
42
|
threat
|
|
41
43
|
end
|
|
42
44
|
|
|
@@ -45,7 +47,7 @@ module Legion
|
|
|
45
47
|
return { success: false, reason: 'not found' } unless threat
|
|
46
48
|
|
|
47
49
|
threat.quarantine!
|
|
48
|
-
|
|
50
|
+
log.info("[cognitive_immunology] quarantined: id=#{threat_id} tactic=#{threat.tactic}")
|
|
49
51
|
{ success: true, threat_id: threat_id }
|
|
50
52
|
end
|
|
51
53
|
|
|
@@ -54,7 +56,7 @@ module Legion
|
|
|
54
56
|
return { success: false, reason: 'not found' } unless threat
|
|
55
57
|
|
|
56
58
|
threat.release!
|
|
57
|
-
|
|
59
|
+
log.debug("[cognitive_immunology] released: id=#{threat_id}")
|
|
58
60
|
{ success: true, threat_id: threat_id }
|
|
59
61
|
end
|
|
60
62
|
|
|
@@ -65,7 +67,7 @@ module Legion
|
|
|
65
67
|
threat.expose!
|
|
66
68
|
boost = (Constants::RESISTANCE_BOOST / (threat.exposure_count + 1)).round(10)
|
|
67
69
|
@resistance = (@resistance + boost).clamp(0.0, 1.0).round(10)
|
|
68
|
-
|
|
70
|
+
log.debug("[cognitive_immunology] inoculate: id=#{threat_id} exposure=#{threat.exposure_count} resistance=#{@resistance.round(2)}")
|
|
69
71
|
{ success: true, threat_id: threat_id, exposure_count: threat.exposure_count, resistance: @resistance }
|
|
70
72
|
end
|
|
71
73
|
|
|
@@ -76,7 +78,7 @@ module Legion
|
|
|
76
78
|
|
|
77
79
|
ab = Antibody.new(tactic: tactic, pattern: pattern, strength: strength)
|
|
78
80
|
@antibodies[ab.id] = ab
|
|
79
|
-
|
|
81
|
+
log.info("[cognitive_immunology] antibody created: id=#{ab.id} tactic=#{tactic} strength=#{strength}")
|
|
80
82
|
ab
|
|
81
83
|
end
|
|
82
84
|
|
|
@@ -86,13 +88,13 @@ module Legion
|
|
|
86
88
|
|
|
87
89
|
def trigger_inflammatory_response
|
|
88
90
|
@inflammatory = true
|
|
89
|
-
|
|
91
|
+
log.warn('[cognitive_immunology] inflammatory response triggered — heightened scrutiny mode')
|
|
90
92
|
{ inflammatory: true }
|
|
91
93
|
end
|
|
92
94
|
|
|
93
95
|
def resolve_inflammation
|
|
94
96
|
@inflammatory = false
|
|
95
|
-
|
|
97
|
+
log.info('[cognitive_immunology] inflammation resolved — returning to normal scrutiny')
|
|
96
98
|
{ inflammatory: false }
|
|
97
99
|
end
|
|
98
100
|
|
|
@@ -127,7 +129,7 @@ module Legion
|
|
|
127
129
|
def decay_all
|
|
128
130
|
@antibodies.each_value(&:decay!)
|
|
129
131
|
@resistance = (@resistance - Constants::RESISTANCE_DECAY).clamp(0.0, 1.0).round(10)
|
|
130
|
-
|
|
132
|
+
log.debug("[cognitive_immunology] decay cycle: resistance=#{@resistance.round(2)} antibodies=#{@antibodies.size}")
|
|
131
133
|
{ resistance: @resistance, antibodies_decayed: @antibodies.size }
|
|
132
134
|
end
|
|
133
135
|
|
|
@@ -135,7 +137,7 @@ module Legion
|
|
|
135
137
|
before = @antibodies.size
|
|
136
138
|
@antibodies.select! { |_, ab| ab.effective? }
|
|
137
139
|
pruned = before - @antibodies.size
|
|
138
|
-
|
|
140
|
+
log.debug("[cognitive_immunology] pruned #{pruned} ineffective antibodies")
|
|
139
141
|
{ pruned: pruned, remaining: @antibodies.size }
|
|
140
142
|
end
|
|
141
143
|
|
|
@@ -7,8 +7,8 @@ module Legion
|
|
|
7
7
|
module Immunology
|
|
8
8
|
module Runners
|
|
9
9
|
module CognitiveImmunology
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def detect_threat(source:, tactic:, content_hash:, threat_level: 0.5, **)
|
|
14
14
|
threat = engine.detect_threat(source: source, tactic: tactic, content_hash: content_hash, threat_level: threat_level)
|
|
@@ -7,19 +7,21 @@ module Legion
|
|
|
7
7
|
module Phantom
|
|
8
8
|
module Helpers
|
|
9
9
|
class PhantomEngine
|
|
10
|
+
include Legion::Extensions::Helpers::Lex
|
|
11
|
+
|
|
10
12
|
def initialize
|
|
11
13
|
@phantoms = {}
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
def register_removal(capability_name:, capability_domain: :general)
|
|
15
17
|
if @phantoms.size >= Constants::MAX_PHANTOMS
|
|
16
|
-
|
|
18
|
+
log.warn("[cognitive_phantom] MAX_PHANTOMS (#{Constants::MAX_PHANTOMS}) reached, skipping #{capability_name}")
|
|
17
19
|
return nil
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
limb = PhantomLimb.new(capability_name: capability_name, capability_domain: capability_domain)
|
|
21
23
|
@phantoms[limb.id] = limb
|
|
22
|
-
|
|
24
|
+
log.info("[cognitive_phantom] registered phantom: capability=#{capability_name} domain=#{capability_domain} id=#{limb.id[0..7]}")
|
|
23
25
|
limb
|
|
24
26
|
end
|
|
25
27
|
|
|
@@ -34,7 +36,7 @@ module Legion
|
|
|
34
36
|
|
|
35
37
|
fired << signal
|
|
36
38
|
intensity_str = limb.intensity.round(3).to_s
|
|
37
|
-
|
|
39
|
+
log.debug("[cognitive_phantom] phantom fired: cap=#{limb.capability_name} trigger=#{signal.trigger_type} i=#{intensity_str}")
|
|
38
40
|
end
|
|
39
41
|
fired
|
|
40
42
|
end
|
|
@@ -49,7 +51,7 @@ module Legion
|
|
|
49
51
|
return { acknowledged: false, reason: :not_found } unless limb
|
|
50
52
|
|
|
51
53
|
limb.adapt!
|
|
52
|
-
|
|
54
|
+
log.info("[cognitive_phantom] acknowledged phantom id=#{phantom_id[0..7]} intensity=#{limb.intensity.round(3)} state=#{limb.state}")
|
|
53
55
|
{ acknowledged: true, phantom_id: phantom_id, state: limb.state, intensity: limb.intensity }
|
|
54
56
|
end
|
|
55
57
|
|
|
@@ -87,7 +89,7 @@ module Legion
|
|
|
87
89
|
def resolve_check!
|
|
88
90
|
newly_resolved = @phantoms.values.select(&:resolved?)
|
|
89
91
|
newly_resolved.each do |limb|
|
|
90
|
-
|
|
92
|
+
log.info("[cognitive_phantom] resolved: capability=#{limb.capability_name} activations=#{limb.activation_count}")
|
|
91
93
|
end
|
|
92
94
|
newly_resolved.size
|
|
93
95
|
end
|
|
@@ -7,8 +7,8 @@ module Legion
|
|
|
7
7
|
module Phantom
|
|
8
8
|
module Runners
|
|
9
9
|
module CognitivePhantom
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def register_removal(capability_name:, capability_domain: :general, engine: nil, **)
|
|
14
14
|
raise ArgumentError, 'capability_name is required' if capability_name.nil? || capability_name.to_s.strip.empty?
|
|
@@ -17,7 +17,7 @@ module Legion
|
|
|
17
17
|
limb = eng.register_removal(capability_name: capability_name, capability_domain: capability_domain)
|
|
18
18
|
return { success: false, error: 'MAX_PHANTOMS limit reached' } unless limb
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
log.debug("[cognitive_phantom] register_removal capability=#{capability_name}")
|
|
21
21
|
{ success: true, phantom_id: limb.id, capability_name: capability_name, state: limb.state, intensity: limb.intensity }
|
|
22
22
|
rescue ArgumentError => e
|
|
23
23
|
{ success: false, error: e.message }
|
|
@@ -28,7 +28,7 @@ module Legion
|
|
|
28
28
|
|
|
29
29
|
eng = engine || phantom_engine
|
|
30
30
|
fired = eng.process_stimulus(stimulus: stimulus, domain: domain)
|
|
31
|
-
|
|
31
|
+
log.debug("[cognitive_phantom] process_stimulus domain=#{domain} fired=#{fired.size}")
|
|
32
32
|
{
|
|
33
33
|
success: true,
|
|
34
34
|
fired_count: fired.size,
|
|
@@ -44,7 +44,7 @@ module Legion
|
|
|
44
44
|
|
|
45
45
|
eng = engine || phantom_engine
|
|
46
46
|
result = eng.acknowledge(phantom_id: phantom_id)
|
|
47
|
-
|
|
47
|
+
log.debug("[cognitive_phantom] acknowledge phantom_id=#{phantom_id[0..7]}")
|
|
48
48
|
result.merge(success: result[:acknowledged])
|
|
49
49
|
rescue ArgumentError => e
|
|
50
50
|
{ success: false, error: e.message }
|
|
@@ -53,7 +53,7 @@ module Legion
|
|
|
53
53
|
def phantom_status(engine: nil, **)
|
|
54
54
|
eng = engine || phantom_engine
|
|
55
55
|
report = eng.phantom_activity_report
|
|
56
|
-
|
|
56
|
+
log.debug("[cognitive_phantom] phantom_status total=#{report[:total]} active=#{report[:active]}")
|
|
57
57
|
{ success: true, **report }
|
|
58
58
|
end
|
|
59
59
|
|
|
@@ -61,7 +61,7 @@ module Legion
|
|
|
61
61
|
eng = engine || phantom_engine
|
|
62
62
|
resolved_count = eng.decay_all!
|
|
63
63
|
report = eng.phantom_activity_report
|
|
64
|
-
|
|
64
|
+
log.debug("[cognitive_phantom] decay_all resolved=#{resolved_count}")
|
|
65
65
|
{ success: true, resolved_this_cycle: resolved_count, **report }
|
|
66
66
|
end
|
|
67
67
|
|
|
@@ -7,18 +7,18 @@ module Legion
|
|
|
7
7
|
module Quicksilver
|
|
8
8
|
module Runners
|
|
9
9
|
module CognitiveQuicksilver
|
|
10
|
-
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
-
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex, false)
|
|
12
12
|
|
|
13
13
|
def create_droplet(form: :droplet, content: '', engine: nil, **)
|
|
14
14
|
raise ArgumentError, "invalid form: #{form}" unless Helpers::Constants::FORM_TYPES.include?(form)
|
|
15
15
|
|
|
16
16
|
eng = engine || quicksilver_engine
|
|
17
17
|
droplet = eng.create_droplet(form: form, content: content.to_s)
|
|
18
|
-
|
|
18
|
+
log.debug("[cognitive_quicksilver] create_droplet id=#{droplet.id} form=#{droplet.form}")
|
|
19
19
|
{ success: true, droplet: droplet.to_h }
|
|
20
20
|
rescue ArgumentError => e
|
|
21
|
-
|
|
21
|
+
log.debug("[cognitive_quicksilver] create_droplet failed: #{e.message}")
|
|
22
22
|
{ success: false, error: e.message }
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -27,10 +27,10 @@ module Legion
|
|
|
27
27
|
|
|
28
28
|
eng = engine || quicksilver_engine
|
|
29
29
|
pool = eng.create_pool(surface_type: surface_type)
|
|
30
|
-
|
|
30
|
+
log.debug("[cognitive_quicksilver] create_pool id=#{pool.id} surface=#{pool.surface_type}")
|
|
31
31
|
{ success: true, pool: pool.to_h }
|
|
32
32
|
rescue ArgumentError => e
|
|
33
|
-
|
|
33
|
+
log.debug("[cognitive_quicksilver] create_pool failed: #{e.message}")
|
|
34
34
|
{ success: false, error: e.message }
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -39,20 +39,20 @@ module Legion
|
|
|
39
39
|
|
|
40
40
|
eng = engine || quicksilver_engine
|
|
41
41
|
droplet = eng.shift_form(droplet_id: droplet_id, new_form: new_form)
|
|
42
|
-
|
|
42
|
+
log.debug("[cognitive_quicksilver] shift_form id=#{droplet_id} new_form=#{new_form}")
|
|
43
43
|
{ success: true, droplet: droplet.to_h }
|
|
44
44
|
rescue ArgumentError => e
|
|
45
|
-
|
|
45
|
+
log.debug("[cognitive_quicksilver] shift_form failed: #{e.message}")
|
|
46
46
|
{ success: false, error: e.message }
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def merge(droplet_a_id:, droplet_b_id:, engine: nil, **)
|
|
50
50
|
eng = engine || quicksilver_engine
|
|
51
51
|
droplet = eng.merge_droplets(droplet_a_id: droplet_a_id, droplet_b_id: droplet_b_id)
|
|
52
|
-
|
|
52
|
+
log.debug("[cognitive_quicksilver] merge a=#{droplet_a_id} b=#{droplet_b_id} result_mass=#{droplet.mass.round(2)}")
|
|
53
53
|
{ success: true, droplet: droplet.to_h }
|
|
54
54
|
rescue ArgumentError => e
|
|
55
|
-
|
|
55
|
+
log.debug("[cognitive_quicksilver] merge failed: #{e.message}")
|
|
56
56
|
{ success: false, error: e.message }
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -60,59 +60,59 @@ module Legion
|
|
|
60
60
|
eng = engine || quicksilver_engine
|
|
61
61
|
result = eng.split_droplet(droplet_id: droplet_id)
|
|
62
62
|
if result.nil?
|
|
63
|
-
|
|
63
|
+
log.debug("[cognitive_quicksilver] split id=#{droplet_id} too_small")
|
|
64
64
|
return { success: false, error: 'droplet mass too small to split' }
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
original, twin = result
|
|
68
|
-
|
|
68
|
+
log.debug("[cognitive_quicksilver] split id=#{droplet_id} twin_id=#{twin.id}")
|
|
69
69
|
{ success: true, original: original.to_h, twin: twin.to_h }
|
|
70
70
|
rescue ArgumentError => e
|
|
71
|
-
|
|
71
|
+
log.debug("[cognitive_quicksilver] split failed: #{e.message}")
|
|
72
72
|
{ success: false, error: e.message }
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def capture(droplet_id:, engine: nil, **)
|
|
76
76
|
eng = engine || quicksilver_engine
|
|
77
77
|
droplet = eng.capture_droplet(droplet_id: droplet_id)
|
|
78
|
-
|
|
78
|
+
log.debug("[cognitive_quicksilver] capture id=#{droplet_id} fluidity=#{droplet.fluidity.round(2)}")
|
|
79
79
|
{ success: true, droplet: droplet.to_h }
|
|
80
80
|
rescue ArgumentError => e
|
|
81
|
-
|
|
81
|
+
log.debug("[cognitive_quicksilver] capture failed: #{e.message}")
|
|
82
82
|
{ success: false, error: e.message }
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def release(droplet_id:, engine: nil, **)
|
|
86
86
|
eng = engine || quicksilver_engine
|
|
87
87
|
droplet = eng.release_droplet(droplet_id: droplet_id)
|
|
88
|
-
|
|
88
|
+
log.debug("[cognitive_quicksilver] release id=#{droplet_id} fluidity=#{droplet.fluidity.round(2)}")
|
|
89
89
|
{ success: true, droplet: droplet.to_h }
|
|
90
90
|
rescue ArgumentError => e
|
|
91
|
-
|
|
91
|
+
log.debug("[cognitive_quicksilver] release failed: #{e.message}")
|
|
92
92
|
{ success: false, error: e.message }
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def add_to_pool(droplet_id:, pool_id:, engine: nil, **)
|
|
96
96
|
eng = engine || quicksilver_engine
|
|
97
97
|
pool = eng.add_to_pool(droplet_id: droplet_id, pool_id: pool_id)
|
|
98
|
-
|
|
98
|
+
log.debug("[cognitive_quicksilver] add_to_pool droplet=#{droplet_id} pool=#{pool_id}")
|
|
99
99
|
{ success: true, pool: pool.to_h }
|
|
100
100
|
rescue ArgumentError => e
|
|
101
|
-
|
|
101
|
+
log.debug("[cognitive_quicksilver] add_to_pool failed: #{e.message}")
|
|
102
102
|
{ success: false, error: e.message }
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
def list_droplets(engine: nil, **)
|
|
106
106
|
eng = engine || quicksilver_engine
|
|
107
107
|
items = eng.droplets
|
|
108
|
-
|
|
108
|
+
log.debug("[cognitive_quicksilver] list_droplets count=#{items.size}")
|
|
109
109
|
{ success: true, droplets: items, count: items.size }
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
def quicksilver_status(engine: nil, **)
|
|
113
113
|
eng = engine || quicksilver_engine
|
|
114
114
|
report = eng.quicksilver_report
|
|
115
|
-
|
|
115
|
+
log.debug("[cognitive_quicksilver] status droplets=#{report[:total_droplets]} pools=#{report[:total_pools]}")
|
|
116
116
|
{ success: true, **report }
|
|
117
117
|
end
|
|
118
118
|
|
|
@@ -20,10 +20,10 @@ module Legion
|
|
|
20
20
|
depth: depth,
|
|
21
21
|
capture_radius: capture_radius
|
|
22
22
|
)
|
|
23
|
-
|
|
23
|
+
log.info("[cognitive_whirlpool] created vortex id=#{vortex.vortex_id} type=#{vortex_type}")
|
|
24
24
|
{ success: true, vortex: vortex.to_h }
|
|
25
25
|
rescue ArgumentError => e
|
|
26
|
-
|
|
26
|
+
log.warn("[cognitive_whirlpool] create_vortex failed: #{e.message}")
|
|
27
27
|
{ success: false, error: e.message }
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -36,70 +36,70 @@ module Legion
|
|
|
36
36
|
domain: domain,
|
|
37
37
|
distance_from_core: distance_from_core
|
|
38
38
|
)
|
|
39
|
-
|
|
39
|
+
log.info("[cognitive_whirlpool] injected thought=#{result[:thought_id]} into vortex=#{vortex_id}")
|
|
40
40
|
result.merge(success: true)
|
|
41
41
|
rescue ArgumentError => e
|
|
42
|
-
|
|
42
|
+
log.warn("[cognitive_whirlpool] inject_thought failed: #{e.message}")
|
|
43
43
|
{ success: false, error: e.message }
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def tick_all(spiral_rate: nil, engine: nil, **)
|
|
47
47
|
eng = engine || default_engine
|
|
48
48
|
result = eng.tick_all!(spiral_rate: spiral_rate)
|
|
49
|
-
|
|
49
|
+
log.debug("[cognitive_whirlpool] tick: vortices=#{result[:ticked]}")
|
|
50
50
|
result.merge(success: true)
|
|
51
51
|
rescue ArgumentError => e
|
|
52
|
-
|
|
52
|
+
log.warn("[cognitive_whirlpool] tick_all failed: #{e.message}")
|
|
53
53
|
{ success: false, error: e.message }
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def dissipate_all(rate: Helpers::Constants::VELOCITY_DECAY, engine: nil, **)
|
|
57
57
|
eng = engine || default_engine
|
|
58
58
|
result = eng.dissipate_all!(rate: rate)
|
|
59
|
-
|
|
59
|
+
log.debug("[cognitive_whirlpool] dissipate: removed=#{result[:dissipated]} remaining=#{result[:remaining]}")
|
|
60
60
|
result.merge(success: true)
|
|
61
61
|
rescue ArgumentError => e
|
|
62
|
-
|
|
62
|
+
log.warn("[cognitive_whirlpool] dissipate_all failed: #{e.message}")
|
|
63
63
|
{ success: false, error: e.message }
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def vortex_report(engine: nil, **)
|
|
67
67
|
eng = engine || default_engine
|
|
68
68
|
report = eng.vortex_report
|
|
69
|
-
|
|
69
|
+
log.debug("[cognitive_whirlpool] report: vortices=#{report[:total_vortices]}")
|
|
70
70
|
report.merge(success: true)
|
|
71
71
|
rescue ArgumentError => e
|
|
72
|
-
|
|
72
|
+
log.warn("[cognitive_whirlpool] vortex_report failed: #{e.message}")
|
|
73
73
|
{ success: false, error: e.message }
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def deepest_vortices(limit: 3, engine: nil, **)
|
|
77
77
|
eng = engine || default_engine
|
|
78
78
|
vortices = eng.deepest_vortices(limit: limit)
|
|
79
|
-
|
|
79
|
+
log.debug("[cognitive_whirlpool] deepest: count=#{vortices.size}")
|
|
80
80
|
{ success: true, vortices: vortices }
|
|
81
81
|
rescue ArgumentError => e
|
|
82
|
-
|
|
82
|
+
log.warn("[cognitive_whirlpool] deepest_vortices failed: #{e.message}")
|
|
83
83
|
{ success: false, error: e.message }
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def remove_vortex(vortex_id:, engine: nil, **)
|
|
87
87
|
eng = engine || default_engine
|
|
88
88
|
result = eng.remove_vortex(vortex_id)
|
|
89
|
-
|
|
89
|
+
log.debug("[cognitive_whirlpool] removed vortex=#{vortex_id}")
|
|
90
90
|
result.merge(success: true)
|
|
91
91
|
rescue ArgumentError => e
|
|
92
|
-
|
|
92
|
+
log.warn("[cognitive_whirlpool] remove_vortex failed: #{e.message}")
|
|
93
93
|
{ success: false, error: e.message }
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
def clear_engine(engine: nil, **)
|
|
97
97
|
eng = engine || default_engine
|
|
98
98
|
result = eng.clear
|
|
99
|
-
|
|
99
|
+
log.info('[cognitive_whirlpool] engine cleared')
|
|
100
100
|
result.merge(success: true)
|
|
101
101
|
rescue ArgumentError => e
|
|
102
|
-
|
|
102
|
+
log.warn("[cognitive_whirlpool] clear_engine failed: #{e.message}")
|
|
103
103
|
{ success: false, error: e.message }
|
|
104
104
|
end
|
|
105
105
|
|
|
@@ -21,7 +21,7 @@ module Legion
|
|
|
21
21
|
module Extensions
|
|
22
22
|
module Agentic
|
|
23
23
|
module Defense
|
|
24
|
-
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
24
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core, false
|
|
25
25
|
|
|
26
26
|
def self.remote_invocable?
|
|
27
27
|
false
|