lex-agentic-defense 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/CHANGELOG.md +12 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +13 -0
- data/lex-agentic-defense.gemspec +30 -0
- data/lib/legion/extensions/agentic/defense/avalanche/client.rb +22 -0
- data/lib/legion/extensions/agentic/defense/avalanche/helpers/avalanche_engine.rb +132 -0
- data/lib/legion/extensions/agentic/defense/avalanche/helpers/cascade.rb +76 -0
- data/lib/legion/extensions/agentic/defense/avalanche/helpers/constants.rb +44 -0
- data/lib/legion/extensions/agentic/defense/avalanche/helpers/snowpack.rb +86 -0
- data/lib/legion/extensions/agentic/defense/avalanche/runners/cognitive_avalanche.rb +75 -0
- data/lib/legion/extensions/agentic/defense/avalanche/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/avalanche.rb +22 -0
- data/lib/legion/extensions/agentic/defense/bias/actors/update.rb +45 -0
- data/lib/legion/extensions/agentic/defense/bias/client.rb +30 -0
- data/lib/legion/extensions/agentic/defense/bias/helpers/bias_detector.rb +107 -0
- data/lib/legion/extensions/agentic/defense/bias/helpers/bias_event.rb +44 -0
- data/lib/legion/extensions/agentic/defense/bias/helpers/bias_store.rb +84 -0
- data/lib/legion/extensions/agentic/defense/bias/helpers/constants.rb +28 -0
- data/lib/legion/extensions/agentic/defense/bias/runners/bias.rb +151 -0
- data/lib/legion/extensions/agentic/defense/bias/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/bias.rb +20 -0
- data/lib/legion/extensions/agentic/defense/confabulation/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/defense/confabulation/client.rb +28 -0
- data/lib/legion/extensions/agentic/defense/confabulation/helpers/claim.rb +67 -0
- data/lib/legion/extensions/agentic/defense/confabulation/helpers/confabulation_engine.rb +120 -0
- data/lib/legion/extensions/agentic/defense/confabulation/helpers/constants.rb +29 -0
- data/lib/legion/extensions/agentic/defense/confabulation/runners/confabulation.rb +74 -0
- data/lib/legion/extensions/agentic/defense/confabulation/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/confabulation.rb +19 -0
- data/lib/legion/extensions/agentic/defense/dissonance/client.rb +32 -0
- data/lib/legion/extensions/agentic/defense/dissonance/helpers/belief.rb +46 -0
- data/lib/legion/extensions/agentic/defense/dissonance/helpers/constants.rb +27 -0
- data/lib/legion/extensions/agentic/defense/dissonance/helpers/dissonance_event.rb +52 -0
- data/lib/legion/extensions/agentic/defense/dissonance/helpers/dissonance_model.rb +159 -0
- data/lib/legion/extensions/agentic/defense/dissonance/runners/dissonance.rb +163 -0
- data/lib/legion/extensions/agentic/defense/dissonance/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/dissonance.rb +20 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/actors/update.rb +45 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/client.rb +27 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/claim.rb +78 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/client.rb +23 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/constants.rb +37 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/source.rb +64 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/helpers/vigilance_engine.rb +195 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/runners/epistemic_vigilance.rb +91 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/epistemic_vigilance.rb +20 -0
- data/lib/legion/extensions/agentic/defense/erosion/client.rb +23 -0
- data/lib/legion/extensions/agentic/defense/erosion/helpers/channel.rb +84 -0
- data/lib/legion/extensions/agentic/defense/erosion/helpers/constants.rb +47 -0
- data/lib/legion/extensions/agentic/defense/erosion/helpers/erosion_engine.rb +134 -0
- data/lib/legion/extensions/agentic/defense/erosion/helpers/formation.rb +100 -0
- data/lib/legion/extensions/agentic/defense/erosion/runners/cognitive_erosion.rb +93 -0
- data/lib/legion/extensions/agentic/defense/erosion/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/erosion.rb +21 -0
- data/lib/legion/extensions/agentic/defense/error_monitoring/actors/tick.rb +45 -0
- data/lib/legion/extensions/agentic/defense/error_monitoring/client.rb +28 -0
- data/lib/legion/extensions/agentic/defense/error_monitoring/helpers/constants.rb +50 -0
- data/lib/legion/extensions/agentic/defense/error_monitoring/helpers/error_monitor.rb +174 -0
- data/lib/legion/extensions/agentic/defense/error_monitoring/helpers/error_signal.rb +60 -0
- data/lib/legion/extensions/agentic/defense/error_monitoring/runners/error_monitoring.rb +102 -0
- data/lib/legion/extensions/agentic/defense/error_monitoring/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/error_monitoring.rb +19 -0
- data/lib/legion/extensions/agentic/defense/extinction/actors/protocol_monitor.rb +45 -0
- data/lib/legion/extensions/agentic/defense/extinction/client.rb +27 -0
- data/lib/legion/extensions/agentic/defense/extinction/helpers/levels.rb +43 -0
- data/lib/legion/extensions/agentic/defense/extinction/helpers/protocol_state.rb +125 -0
- data/lib/legion/extensions/agentic/defense/extinction/local_migrations/20260316000040_create_extinction_state.rb +13 -0
- data/lib/legion/extensions/agentic/defense/extinction/runners/extinction.rb +130 -0
- data/lib/legion/extensions/agentic/defense/extinction/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/extinction.rb +25 -0
- data/lib/legion/extensions/agentic/defense/friction/client.rb +15 -0
- data/lib/legion/extensions/agentic/defense/friction/helpers/constants.rb +38 -0
- data/lib/legion/extensions/agentic/defense/friction/helpers/friction_engine.rb +131 -0
- data/lib/legion/extensions/agentic/defense/friction/helpers/state_transition.rb +73 -0
- data/lib/legion/extensions/agentic/defense/friction/runners/cognitive_friction.rb +82 -0
- data/lib/legion/extensions/agentic/defense/friction/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/friction.rb +19 -0
- data/lib/legion/extensions/agentic/defense/immune_response/client.rb +19 -0
- data/lib/legion/extensions/agentic/defense/immune_response/helpers/antibody.rb +72 -0
- data/lib/legion/extensions/agentic/defense/immune_response/helpers/antigen.rb +87 -0
- data/lib/legion/extensions/agentic/defense/immune_response/helpers/constants.rb +75 -0
- data/lib/legion/extensions/agentic/defense/immune_response/helpers/immune_engine.rb +184 -0
- data/lib/legion/extensions/agentic/defense/immune_response/helpers/immune_response.rb +76 -0
- data/lib/legion/extensions/agentic/defense/immune_response/runners/cognitive_immune_response.rb +114 -0
- data/lib/legion/extensions/agentic/defense/immune_response/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/immune_response.rb +21 -0
- data/lib/legion/extensions/agentic/defense/immunology/client.rb +29 -0
- data/lib/legion/extensions/agentic/defense/immunology/helpers/antibody.rb +55 -0
- data/lib/legion/extensions/agentic/defense/immunology/helpers/constants.rb +43 -0
- data/lib/legion/extensions/agentic/defense/immunology/helpers/immune_engine.rb +187 -0
- data/lib/legion/extensions/agentic/defense/immunology/helpers/threat.rb +67 -0
- data/lib/legion/extensions/agentic/defense/immunology/runners/cognitive_immunology.rb +92 -0
- data/lib/legion/extensions/agentic/defense/immunology/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/immunology.rb +20 -0
- data/lib/legion/extensions/agentic/defense/phantom/client.rb +29 -0
- data/lib/legion/extensions/agentic/defense/phantom/helpers/constants.rb +54 -0
- data/lib/legion/extensions/agentic/defense/phantom/helpers/phantom_engine.rb +106 -0
- data/lib/legion/extensions/agentic/defense/phantom/helpers/phantom_limb.rb +103 -0
- data/lib/legion/extensions/agentic/defense/phantom/helpers/phantom_signal.rb +40 -0
- data/lib/legion/extensions/agentic/defense/phantom/runners/cognitive_phantom.rb +79 -0
- data/lib/legion/extensions/agentic/defense/phantom/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/phantom.rb +21 -0
- data/lib/legion/extensions/agentic/defense/quicksand/client.rb +15 -0
- data/lib/legion/extensions/agentic/defense/quicksand/helpers/constants.rb +48 -0
- data/lib/legion/extensions/agentic/defense/quicksand/helpers/pit.rb +82 -0
- data/lib/legion/extensions/agentic/defense/quicksand/helpers/quicksand_engine.rb +137 -0
- data/lib/legion/extensions/agentic/defense/quicksand/helpers/trap.rb +101 -0
- data/lib/legion/extensions/agentic/defense/quicksand/runners/cognitive_quicksand.rb +84 -0
- data/lib/legion/extensions/agentic/defense/quicksand/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/quicksand.rb +22 -0
- data/lib/legion/extensions/agentic/defense/quicksilver/client.rb +29 -0
- data/lib/legion/extensions/agentic/defense/quicksilver/helpers/constants.rb +50 -0
- data/lib/legion/extensions/agentic/defense/quicksilver/helpers/droplet.rb +126 -0
- data/lib/legion/extensions/agentic/defense/quicksilver/helpers/pool.rb +83 -0
- data/lib/legion/extensions/agentic/defense/quicksilver/helpers/quicksilver_engine.rb +124 -0
- data/lib/legion/extensions/agentic/defense/quicksilver/runners/cognitive_quicksilver.rb +130 -0
- data/lib/legion/extensions/agentic/defense/quicksilver/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/quicksilver.rb +21 -0
- data/lib/legion/extensions/agentic/defense/version.rb +11 -0
- data/lib/legion/extensions/agentic/defense/whirlpool/client.rb +65 -0
- data/lib/legion/extensions/agentic/defense/whirlpool/helpers/captured_thought.rb +67 -0
- data/lib/legion/extensions/agentic/defense/whirlpool/helpers/constants.rb +45 -0
- data/lib/legion/extensions/agentic/defense/whirlpool/helpers/vortex.rb +91 -0
- data/lib/legion/extensions/agentic/defense/whirlpool/helpers/whirlpool_engine.rb +92 -0
- data/lib/legion/extensions/agentic/defense/whirlpool/runners/cognitive_whirlpool.rb +117 -0
- data/lib/legion/extensions/agentic/defense/whirlpool/version.rb +13 -0
- data/lib/legion/extensions/agentic/defense/whirlpool.rb +22 -0
- data/lib/legion/extensions/agentic/defense.rb +32 -0
- data/spec/legion/extensions/agentic/defense/avalanche/client_spec.rb +96 -0
- data/spec/legion/extensions/agentic/defense/avalanche/helpers/avalanche_engine_spec.rb +276 -0
- data/spec/legion/extensions/agentic/defense/avalanche/helpers/cascade_spec.rb +190 -0
- data/spec/legion/extensions/agentic/defense/avalanche/helpers/constants_spec.rb +129 -0
- data/spec/legion/extensions/agentic/defense/avalanche/helpers/snowpack_spec.rb +197 -0
- data/spec/legion/extensions/agentic/defense/avalanche/runners/cognitive_avalanche_spec.rb +211 -0
- data/spec/legion/extensions/agentic/defense/bias/client_spec.rb +16 -0
- data/spec/legion/extensions/agentic/defense/bias/helpers/bias_detector_spec.rb +160 -0
- data/spec/legion/extensions/agentic/defense/bias/helpers/bias_event_spec.rb +64 -0
- data/spec/legion/extensions/agentic/defense/bias/helpers/bias_store_spec.rb +143 -0
- data/spec/legion/extensions/agentic/defense/bias/runners/bias_spec.rb +155 -0
- data/spec/legion/extensions/agentic/defense/confabulation/client_spec.rb +34 -0
- data/spec/legion/extensions/agentic/defense/confabulation/helpers/claim_spec.rb +119 -0
- data/spec/legion/extensions/agentic/defense/confabulation/helpers/confabulation_engine_spec.rb +163 -0
- data/spec/legion/extensions/agentic/defense/confabulation/helpers/constants_spec.rb +55 -0
- data/spec/legion/extensions/agentic/defense/confabulation/runners/confabulation_spec.rb +119 -0
- data/spec/legion/extensions/agentic/defense/dissonance/client_spec.rb +51 -0
- data/spec/legion/extensions/agentic/defense/dissonance/helpers/belief_spec.rb +103 -0
- data/spec/legion/extensions/agentic/defense/dissonance/helpers/constants_spec.rb +60 -0
- data/spec/legion/extensions/agentic/defense/dissonance/helpers/dissonance_event_spec.rb +113 -0
- data/spec/legion/extensions/agentic/defense/dissonance/helpers/dissonance_model_spec.rb +252 -0
- data/spec/legion/extensions/agentic/defense/dissonance/runners/dissonance_spec.rb +323 -0
- data/spec/legion/extensions/agentic/defense/epistemic_vigilance/client_spec.rb +28 -0
- data/spec/legion/extensions/agentic/defense/epistemic_vigilance/helpers/claim_spec.rb +135 -0
- data/spec/legion/extensions/agentic/defense/epistemic_vigilance/helpers/constants_spec.rb +59 -0
- data/spec/legion/extensions/agentic/defense/epistemic_vigilance/helpers/source_spec.rb +117 -0
- data/spec/legion/extensions/agentic/defense/epistemic_vigilance/helpers/vigilance_engine_spec.rb +273 -0
- data/spec/legion/extensions/agentic/defense/epistemic_vigilance/runners/epistemic_vigilance_spec.rb +157 -0
- data/spec/legion/extensions/agentic/defense/erosion/client_spec.rb +90 -0
- data/spec/legion/extensions/agentic/defense/erosion/helpers/channel_spec.rb +173 -0
- data/spec/legion/extensions/agentic/defense/erosion/helpers/constants_spec.rb +137 -0
- data/spec/legion/extensions/agentic/defense/erosion/helpers/erosion_engine_spec.rb +263 -0
- data/spec/legion/extensions/agentic/defense/erosion/helpers/formation_spec.rb +206 -0
- data/spec/legion/extensions/agentic/defense/erosion/runners/cognitive_erosion_spec.rb +153 -0
- data/spec/legion/extensions/agentic/defense/error_monitoring/client_spec.rb +40 -0
- data/spec/legion/extensions/agentic/defense/error_monitoring/helpers/error_monitor_spec.rb +178 -0
- data/spec/legion/extensions/agentic/defense/error_monitoring/helpers/error_signal_spec.rb +76 -0
- data/spec/legion/extensions/agentic/defense/error_monitoring/runners/error_monitoring_spec.rb +87 -0
- data/spec/legion/extensions/agentic/defense/extinction/actors/protocol_monitor_spec.rb +45 -0
- data/spec/legion/extensions/agentic/defense/extinction/client_spec.rb +13 -0
- data/spec/legion/extensions/agentic/defense/extinction/helpers/levels_spec.rb +180 -0
- data/spec/legion/extensions/agentic/defense/extinction/helpers/protocol_state_spec.rb +291 -0
- data/spec/legion/extensions/agentic/defense/extinction/local_persistence_spec.rb +188 -0
- data/spec/legion/extensions/agentic/defense/extinction/runners/extinction_spec.rb +114 -0
- data/spec/legion/extensions/agentic/defense/friction/helpers/constants_spec.rb +46 -0
- data/spec/legion/extensions/agentic/defense/friction/helpers/friction_engine_spec.rb +175 -0
- data/spec/legion/extensions/agentic/defense/friction/helpers/state_transition_spec.rb +124 -0
- data/spec/legion/extensions/agentic/defense/friction/runners/cognitive_friction_spec.rb +89 -0
- data/spec/legion/extensions/agentic/defense/immune_response/client_spec.rb +32 -0
- data/spec/legion/extensions/agentic/defense/immune_response/cognitive_immune_response_spec.rb +7 -0
- data/spec/legion/extensions/agentic/defense/immune_response/helpers/antibody_spec.rb +117 -0
- data/spec/legion/extensions/agentic/defense/immune_response/helpers/antigen_spec.rb +125 -0
- data/spec/legion/extensions/agentic/defense/immune_response/helpers/constants_spec.rb +45 -0
- data/spec/legion/extensions/agentic/defense/immune_response/helpers/immune_engine_spec.rb +222 -0
- data/spec/legion/extensions/agentic/defense/immune_response/helpers/immune_response_spec.rb +84 -0
- data/spec/legion/extensions/agentic/defense/immune_response/runners_spec.rb +141 -0
- data/spec/legion/extensions/agentic/defense/immunology/client_spec.rb +61 -0
- data/spec/legion/extensions/agentic/defense/immunology/helpers/antibody_spec.rb +98 -0
- data/spec/legion/extensions/agentic/defense/immunology/helpers/constants_spec.rb +86 -0
- data/spec/legion/extensions/agentic/defense/immunology/helpers/immune_engine_spec.rb +275 -0
- data/spec/legion/extensions/agentic/defense/immunology/helpers/threat_spec.rb +133 -0
- data/spec/legion/extensions/agentic/defense/immunology/runners/cognitive_immunology_spec.rb +177 -0
- data/spec/legion/extensions/agentic/defense/phantom/client_spec.rb +53 -0
- data/spec/legion/extensions/agentic/defense/phantom/helpers/constants_spec.rb +87 -0
- data/spec/legion/extensions/agentic/defense/phantom/helpers/phantom_engine_spec.rb +222 -0
- data/spec/legion/extensions/agentic/defense/phantom/helpers/phantom_limb_spec.rb +180 -0
- data/spec/legion/extensions/agentic/defense/phantom/helpers/phantom_signal_spec.rb +59 -0
- data/spec/legion/extensions/agentic/defense/phantom/runners/cognitive_phantom_spec.rb +193 -0
- data/spec/legion/extensions/agentic/defense/quicksand/client_spec.rb +35 -0
- data/spec/legion/extensions/agentic/defense/quicksand/helpers/constants_spec.rb +58 -0
- data/spec/legion/extensions/agentic/defense/quicksand/helpers/pit_spec.rb +103 -0
- data/spec/legion/extensions/agentic/defense/quicksand/helpers/quicksand_engine_spec.rb +153 -0
- data/spec/legion/extensions/agentic/defense/quicksand/helpers/trap_spec.rb +166 -0
- data/spec/legion/extensions/agentic/defense/quicksand/runners/cognitive_quicksand_spec.rb +90 -0
- data/spec/legion/extensions/agentic/defense/quicksilver/client_spec.rb +72 -0
- data/spec/legion/extensions/agentic/defense/quicksilver/helpers/constants_spec.rb +105 -0
- data/spec/legion/extensions/agentic/defense/quicksilver/helpers/droplet_spec.rb +310 -0
- data/spec/legion/extensions/agentic/defense/quicksilver/helpers/pool_spec.rb +174 -0
- data/spec/legion/extensions/agentic/defense/quicksilver/helpers/quicksilver_engine_spec.rb +226 -0
- data/spec/legion/extensions/agentic/defense/quicksilver/runners/cognitive_quicksilver_spec.rb +227 -0
- data/spec/legion/extensions/agentic/defense/whirlpool/client_spec.rb +63 -0
- data/spec/legion/extensions/agentic/defense/whirlpool/helpers/captured_thought_spec.rb +171 -0
- data/spec/legion/extensions/agentic/defense/whirlpool/helpers/constants_spec.rb +65 -0
- data/spec/legion/extensions/agentic/defense/whirlpool/helpers/vortex_spec.rb +189 -0
- data/spec/legion/extensions/agentic/defense/whirlpool/helpers/whirlpool_engine_spec.rb +227 -0
- data/spec/legion/extensions/agentic/defense/whirlpool/runners/cognitive_whirlpool_spec.rb +226 -0
- data/spec/spec_helper.rb +46 -0
- metadata +303 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Defense
|
|
9
|
+
module Phantom
|
|
10
|
+
module Helpers
|
|
11
|
+
class PhantomLimb
|
|
12
|
+
ADAPT_DECAY_MULTIPLIER = 2.5
|
|
13
|
+
|
|
14
|
+
attr_reader :id, :capability_name, :capability_domain, :removed_at,
|
|
15
|
+
:activation_count, :last_triggered, :trigger_history
|
|
16
|
+
|
|
17
|
+
def initialize(capability_name:, capability_domain:)
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@capability_name = capability_name
|
|
20
|
+
@capability_domain = capability_domain
|
|
21
|
+
@removed_at = Time.now.utc
|
|
22
|
+
@intensity = Constants::INITIAL_INTENSITY
|
|
23
|
+
@activation_count = 0
|
|
24
|
+
@last_triggered = nil
|
|
25
|
+
@trigger_history = []
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def intensity
|
|
29
|
+
@intensity.round(10)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def state
|
|
33
|
+
Constants.state_for(@intensity)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def trigger!(stimulus)
|
|
37
|
+
return false if resolved?
|
|
38
|
+
|
|
39
|
+
@activation_count += 1
|
|
40
|
+
prev_triggered = @last_triggered
|
|
41
|
+
@last_triggered = Time.now.utc
|
|
42
|
+
signal = PhantomSignal.new(
|
|
43
|
+
phantom_limb_id: @id,
|
|
44
|
+
stimulus: stimulus,
|
|
45
|
+
trigger_type: classify_trigger(stimulus, prev_triggered),
|
|
46
|
+
intensity_at_trigger: @intensity
|
|
47
|
+
)
|
|
48
|
+
@trigger_history << signal
|
|
49
|
+
@trigger_history.shift while @trigger_history.size > 50
|
|
50
|
+
boost = (@intensity * 0.05).clamp(0.0, 0.1)
|
|
51
|
+
@intensity = (@intensity + boost).clamp(Constants::MIN_INTENSITY, 1.0)
|
|
52
|
+
signal
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def decay!
|
|
56
|
+
return if resolved?
|
|
57
|
+
|
|
58
|
+
@intensity = (@intensity - Constants::INTENSITY_DECAY).clamp(Constants::MIN_INTENSITY, 1.0)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def adapt!
|
|
62
|
+
return if resolved?
|
|
63
|
+
|
|
64
|
+
accelerated = Constants::INTENSITY_DECAY * ADAPT_DECAY_MULTIPLIER
|
|
65
|
+
@intensity = (@intensity - accelerated).clamp(Constants::MIN_INTENSITY, 1.0)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def resolved?
|
|
69
|
+
@intensity <= Constants::MIN_INTENSITY
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def to_h
|
|
73
|
+
{
|
|
74
|
+
id: @id,
|
|
75
|
+
capability_name: @capability_name,
|
|
76
|
+
capability_domain: @capability_domain,
|
|
77
|
+
removed_at: @removed_at,
|
|
78
|
+
intensity: intensity,
|
|
79
|
+
activation_count: @activation_count,
|
|
80
|
+
last_triggered: @last_triggered,
|
|
81
|
+
state: state,
|
|
82
|
+
resolved: resolved?
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def classify_trigger(stimulus, prev_triggered)
|
|
89
|
+
return :stimulus_match if stimulus.is_a?(String) && stimulus.include?(@capability_name.to_s)
|
|
90
|
+
|
|
91
|
+
return :temporal_pattern if prev_triggered && (Time.now.utc - prev_triggered) < 60
|
|
92
|
+
|
|
93
|
+
return :habitual if @activation_count > 10
|
|
94
|
+
|
|
95
|
+
:contextual_association
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Defense
|
|
9
|
+
module Phantom
|
|
10
|
+
module Helpers
|
|
11
|
+
class PhantomSignal
|
|
12
|
+
attr_reader :id, :phantom_limb_id, :stimulus, :trigger_type,
|
|
13
|
+
:intensity_at_trigger, :timestamp
|
|
14
|
+
|
|
15
|
+
def initialize(phantom_limb_id:, stimulus:, trigger_type:, intensity_at_trigger:)
|
|
16
|
+
@id = SecureRandom.uuid
|
|
17
|
+
@phantom_limb_id = phantom_limb_id
|
|
18
|
+
@stimulus = stimulus
|
|
19
|
+
@trigger_type = trigger_type
|
|
20
|
+
@intensity_at_trigger = intensity_at_trigger.clamp(0.0, 1.0)
|
|
21
|
+
@timestamp = Time.now.utc
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_h
|
|
25
|
+
{
|
|
26
|
+
id: @id,
|
|
27
|
+
phantom_limb_id: @phantom_limb_id,
|
|
28
|
+
stimulus: @stimulus,
|
|
29
|
+
trigger_type: @trigger_type,
|
|
30
|
+
intensity_at_trigger: @intensity_at_trigger.round(10),
|
|
31
|
+
timestamp: @timestamp
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Defense
|
|
7
|
+
module Phantom
|
|
8
|
+
module Runners
|
|
9
|
+
module CognitivePhantom
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def register_removal(capability_name:, capability_domain: :general, engine: nil, **)
|
|
14
|
+
raise ArgumentError, 'capability_name is required' if capability_name.nil? || capability_name.to_s.strip.empty?
|
|
15
|
+
|
|
16
|
+
eng = engine || phantom_engine
|
|
17
|
+
limb = eng.register_removal(capability_name: capability_name, capability_domain: capability_domain)
|
|
18
|
+
return { success: false, error: 'MAX_PHANTOMS limit reached' } unless limb
|
|
19
|
+
|
|
20
|
+
Legion::Logging.debug "[cognitive_phantom] register_removal capability=#{capability_name}"
|
|
21
|
+
{ success: true, phantom_id: limb.id, capability_name: capability_name, state: limb.state, intensity: limb.intensity }
|
|
22
|
+
rescue ArgumentError => e
|
|
23
|
+
{ success: false, error: e.message }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def process_stimulus(stimulus:, domain: :general, engine: nil, **)
|
|
27
|
+
raise ArgumentError, 'stimulus is required' if stimulus.nil?
|
|
28
|
+
|
|
29
|
+
eng = engine || phantom_engine
|
|
30
|
+
fired = eng.process_stimulus(stimulus: stimulus, domain: domain)
|
|
31
|
+
Legion::Logging.debug "[cognitive_phantom] process_stimulus domain=#{domain} fired=#{fired.size}"
|
|
32
|
+
{
|
|
33
|
+
success: true,
|
|
34
|
+
fired_count: fired.size,
|
|
35
|
+
signals: fired.map(&:to_h),
|
|
36
|
+
domain: domain
|
|
37
|
+
}
|
|
38
|
+
rescue ArgumentError => e
|
|
39
|
+
{ success: false, error: e.message }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def acknowledge_phantom(phantom_id:, engine: nil, **)
|
|
43
|
+
raise ArgumentError, 'phantom_id is required' if phantom_id.nil? || phantom_id.to_s.strip.empty?
|
|
44
|
+
|
|
45
|
+
eng = engine || phantom_engine
|
|
46
|
+
result = eng.acknowledge(phantom_id: phantom_id)
|
|
47
|
+
Legion::Logging.debug "[cognitive_phantom] acknowledge phantom_id=#{phantom_id[0..7]}"
|
|
48
|
+
result.merge(success: result[:acknowledged])
|
|
49
|
+
rescue ArgumentError => e
|
|
50
|
+
{ success: false, error: e.message }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def phantom_status(engine: nil, **)
|
|
54
|
+
eng = engine || phantom_engine
|
|
55
|
+
report = eng.phantom_activity_report
|
|
56
|
+
Legion::Logging.debug "[cognitive_phantom] phantom_status total=#{report[:total]} active=#{report[:active]}"
|
|
57
|
+
{ success: true, **report }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def decay_all(engine: nil, **)
|
|
61
|
+
eng = engine || phantom_engine
|
|
62
|
+
resolved_count = eng.decay_all!
|
|
63
|
+
report = eng.phantom_activity_report
|
|
64
|
+
Legion::Logging.debug "[cognitive_phantom] decay_all resolved=#{resolved_count}"
|
|
65
|
+
{ success: true, resolved_this_cycle: resolved_count, **report }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def phantom_engine
|
|
71
|
+
@phantom_engine ||= Helpers::PhantomEngine.new
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
require 'legion/extensions/agentic/defense/phantom/version'
|
|
5
|
+
require 'legion/extensions/agentic/defense/phantom/helpers/constants'
|
|
6
|
+
require 'legion/extensions/agentic/defense/phantom/helpers/phantom_signal'
|
|
7
|
+
require 'legion/extensions/agentic/defense/phantom/helpers/phantom_limb'
|
|
8
|
+
require 'legion/extensions/agentic/defense/phantom/helpers/phantom_engine'
|
|
9
|
+
require 'legion/extensions/agentic/defense/phantom/runners/cognitive_phantom'
|
|
10
|
+
require 'legion/extensions/agentic/defense/phantom/client'
|
|
11
|
+
|
|
12
|
+
module Legion
|
|
13
|
+
module Extensions
|
|
14
|
+
module Agentic
|
|
15
|
+
module Defense
|
|
16
|
+
module Phantom
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Defense
|
|
7
|
+
module Quicksand
|
|
8
|
+
module Helpers
|
|
9
|
+
module Constants
|
|
10
|
+
TRAP_TYPES = %i[overthinking rumination analysis_paralysis
|
|
11
|
+
perfectionism indecision].freeze
|
|
12
|
+
|
|
13
|
+
STRUGGLE_MODES = %i[thrash freeze sink float escape].freeze
|
|
14
|
+
|
|
15
|
+
MAX_TRAPS = 200
|
|
16
|
+
MAX_PITS = 50
|
|
17
|
+
SINK_RATE = 0.08
|
|
18
|
+
STRUGGLE_PENALTY = 0.12
|
|
19
|
+
ESCAPE_THRESHOLD = 0.3
|
|
20
|
+
CALM_RATE = 0.03
|
|
21
|
+
|
|
22
|
+
DEPTH_LABELS = [
|
|
23
|
+
[(0.8..), :submerged],
|
|
24
|
+
[(0.6...0.8), :chest_deep],
|
|
25
|
+
[(0.4...0.6), :waist_deep],
|
|
26
|
+
[(0.2...0.4), :ankle_deep],
|
|
27
|
+
[(..0.2), :surface]
|
|
28
|
+
].freeze
|
|
29
|
+
|
|
30
|
+
VISCOSITY_LABELS = [
|
|
31
|
+
[(0.8..), :concrete],
|
|
32
|
+
[(0.6...0.8), :thick],
|
|
33
|
+
[(0.4...0.6), :moderate],
|
|
34
|
+
[(0.2...0.4), :thin],
|
|
35
|
+
[(..0.2), :dry]
|
|
36
|
+
].freeze
|
|
37
|
+
|
|
38
|
+
def self.label_for(table, value)
|
|
39
|
+
table.each { |range, label| return label if range.cover?(value) }
|
|
40
|
+
table.last.last
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Defense
|
|
7
|
+
module Quicksand
|
|
8
|
+
module Helpers
|
|
9
|
+
class Pit
|
|
10
|
+
attr_reader :id, :trap_ids, :created_at
|
|
11
|
+
attr_accessor :saturation, :danger_level
|
|
12
|
+
|
|
13
|
+
def initialize(saturation: nil, danger_level: nil)
|
|
14
|
+
@id = SecureRandom.uuid
|
|
15
|
+
@saturation = (saturation || 0.5).to_f.clamp(0.0, 1.0).round(10)
|
|
16
|
+
@danger_level = (danger_level || 0.3).to_f.clamp(0.0, 1.0).round(10)
|
|
17
|
+
@trap_ids = []
|
|
18
|
+
@created_at = Time.now.utc
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_trap(trap_id)
|
|
22
|
+
return :already_present if @trap_ids.include?(trap_id)
|
|
23
|
+
|
|
24
|
+
@trap_ids << trap_id
|
|
25
|
+
recalculate_danger!
|
|
26
|
+
:added
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def remove_trap(trap_id)
|
|
30
|
+
return :not_found unless @trap_ids.include?(trap_id)
|
|
31
|
+
|
|
32
|
+
@trap_ids.delete(trap_id)
|
|
33
|
+
recalculate_danger!
|
|
34
|
+
:removed
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def saturate!(rate: 0.1)
|
|
38
|
+
@saturation = (@saturation + rate.abs).clamp(0.0, 1.0).round(10)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def drain!(rate: 0.1)
|
|
42
|
+
@saturation = (@saturation - rate.abs).clamp(0.0, 1.0).round(10)
|
|
43
|
+
recalculate_danger!
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def deadly?
|
|
47
|
+
@danger_level >= 0.8
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def safe?
|
|
51
|
+
@danger_level < 0.2
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def trap_count
|
|
55
|
+
@trap_ids.size
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_h
|
|
59
|
+
{
|
|
60
|
+
id: @id,
|
|
61
|
+
saturation: @saturation,
|
|
62
|
+
danger_level: @danger_level,
|
|
63
|
+
trap_count: trap_count,
|
|
64
|
+
deadly: deadly?,
|
|
65
|
+
safe: safe?,
|
|
66
|
+
created_at: @created_at
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def recalculate_danger!
|
|
73
|
+
trap_factor = (@trap_ids.size / 10.0).clamp(0.0, 1.0)
|
|
74
|
+
@danger_level = ((trap_factor + @saturation) / 2.0).clamp(0.0, 1.0).round(10)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Defense
|
|
7
|
+
module Quicksand
|
|
8
|
+
module Helpers
|
|
9
|
+
class QuicksandEngine
|
|
10
|
+
def initialize
|
|
11
|
+
@traps = {}
|
|
12
|
+
@pits = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create_trap(trap_type:, domain:, content:, depth: nil, viscosity: nil)
|
|
16
|
+
raise ArgumentError, 'trap limit reached' if @traps.size >= Constants::MAX_TRAPS
|
|
17
|
+
|
|
18
|
+
t = Trap.new(trap_type: trap_type, domain: domain, content: content,
|
|
19
|
+
depth: depth, viscosity: viscosity)
|
|
20
|
+
@traps[t.id] = t
|
|
21
|
+
t
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def create_pit(saturation: nil, danger_level: nil)
|
|
25
|
+
raise ArgumentError, 'pit limit reached' if @pits.size >= Constants::MAX_PITS
|
|
26
|
+
|
|
27
|
+
p = Pit.new(saturation: saturation, danger_level: danger_level)
|
|
28
|
+
@pits[p.id] = p
|
|
29
|
+
p
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def sink_trap(trap_id:, rate: Constants::SINK_RATE)
|
|
33
|
+
trap = fetch_trap(trap_id)
|
|
34
|
+
trap.sink!(rate: rate)
|
|
35
|
+
trap
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def struggle(trap_id:)
|
|
39
|
+
trap = fetch_trap(trap_id)
|
|
40
|
+
trap.struggle!
|
|
41
|
+
{ trap: trap, depth: trap.depth, struggle_count: trap.struggle_count }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def calm(trap_id:, rate: Constants::CALM_RATE)
|
|
45
|
+
trap = fetch_trap(trap_id)
|
|
46
|
+
trap.calm!(rate: rate)
|
|
47
|
+
trap
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def attempt_escape(trap_id:)
|
|
51
|
+
trap = fetch_trap(trap_id)
|
|
52
|
+
result = trap.escape!
|
|
53
|
+
{ trap: trap, result: result }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def add_trap_to_pit(trap_id:, pit_id:)
|
|
57
|
+
fetch_trap(trap_id)
|
|
58
|
+
pit = fetch_pit(pit_id)
|
|
59
|
+
pit.add_trap(trap_id)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def sink_all!
|
|
63
|
+
@traps.each_value(&:sink!)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def calm_all!
|
|
67
|
+
@traps.each_value(&:calm!)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def traps_by_type
|
|
71
|
+
counts = Constants::TRAP_TYPES.to_h { |t| [t, 0] }
|
|
72
|
+
@traps.each_value { |t| counts[t.trap_type] += 1 }
|
|
73
|
+
counts
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def deepest(limit: 5)
|
|
77
|
+
@traps.values.sort_by { |t| -t.depth }.first(limit)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def shallowest(limit: 5)
|
|
81
|
+
@traps.values.sort_by(&:depth).first(limit)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def submerged_traps
|
|
85
|
+
@traps.values.select(&:submerged?)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def stuck_traps
|
|
89
|
+
@traps.values.select(&:stuck?)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def deadliest_pits(limit: 5)
|
|
93
|
+
@pits.values.sort_by { |p| -p.danger_level }.first(limit)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def avg_depth
|
|
97
|
+
return 0.0 if @traps.empty?
|
|
98
|
+
|
|
99
|
+
(@traps.values.sum(&:depth) / @traps.size).round(10)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def quicksand_report
|
|
103
|
+
{
|
|
104
|
+
total_traps: @traps.size,
|
|
105
|
+
total_pits: @pits.size,
|
|
106
|
+
by_type: traps_by_type,
|
|
107
|
+
submerged: submerged_traps.size,
|
|
108
|
+
stuck: stuck_traps.size,
|
|
109
|
+
avg_depth: avg_depth,
|
|
110
|
+
deadly_pits: @pits.values.count(&:deadly?)
|
|
111
|
+
}
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def all_traps
|
|
115
|
+
@traps.values
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def all_pits
|
|
119
|
+
@pits.values
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
private
|
|
123
|
+
|
|
124
|
+
def fetch_trap(id)
|
|
125
|
+
@traps.fetch(id) { raise ArgumentError, "trap not found: #{id}" }
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def fetch_pit(id)
|
|
129
|
+
@pits.fetch(id) { raise ArgumentError, "pit not found: #{id}" }
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Defense
|
|
7
|
+
module Quicksand
|
|
8
|
+
module Helpers
|
|
9
|
+
class Trap
|
|
10
|
+
attr_reader :id, :trap_type, :domain, :content,
|
|
11
|
+
:struggle_count, :created_at
|
|
12
|
+
attr_accessor :depth, :viscosity
|
|
13
|
+
|
|
14
|
+
def initialize(trap_type:, domain:, content:,
|
|
15
|
+
depth: nil, viscosity: nil)
|
|
16
|
+
validate_trap_type!(trap_type)
|
|
17
|
+
@id = SecureRandom.uuid
|
|
18
|
+
@trap_type = trap_type.to_sym
|
|
19
|
+
@domain = domain.to_sym
|
|
20
|
+
@content = content.to_s
|
|
21
|
+
@depth = (depth || 0.3).to_f.clamp(0.0, 1.0).round(10)
|
|
22
|
+
@viscosity = (viscosity || 0.5).to_f.clamp(0.0, 1.0).round(10)
|
|
23
|
+
@struggle_count = 0
|
|
24
|
+
@created_at = Time.now.utc
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def sink!(rate: Constants::SINK_RATE)
|
|
28
|
+
@depth = (@depth + rate.abs).clamp(0.0, 1.0).round(10)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def struggle!
|
|
32
|
+
@struggle_count += 1
|
|
33
|
+
penalty = Constants::STRUGGLE_PENALTY * @viscosity
|
|
34
|
+
@depth = (@depth + penalty).clamp(0.0, 1.0).round(10)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def calm!(rate: Constants::CALM_RATE)
|
|
38
|
+
@depth = (@depth - rate.abs).clamp(0.0, 1.0).round(10)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def escape!
|
|
42
|
+
return :too_deep if @depth > (1.0 - Constants::ESCAPE_THRESHOLD)
|
|
43
|
+
|
|
44
|
+
@depth = 0.0
|
|
45
|
+
:escaped
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def submerged?
|
|
49
|
+
@depth >= 0.8
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def surface?
|
|
53
|
+
@depth < 0.2
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def stuck?
|
|
57
|
+
@depth >= 0.5 && @viscosity >= 0.5
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def depth_label
|
|
61
|
+
Constants.label_for(Constants::DEPTH_LABELS, @depth)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def viscosity_label
|
|
65
|
+
Constants.label_for(Constants::VISCOSITY_LABELS, @viscosity)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def to_h
|
|
69
|
+
{
|
|
70
|
+
id: @id,
|
|
71
|
+
trap_type: @trap_type,
|
|
72
|
+
domain: @domain,
|
|
73
|
+
content: @content,
|
|
74
|
+
depth: @depth,
|
|
75
|
+
viscosity: @viscosity,
|
|
76
|
+
depth_label: depth_label,
|
|
77
|
+
viscosity_label: viscosity_label,
|
|
78
|
+
struggle_count: @struggle_count,
|
|
79
|
+
submerged: submerged?,
|
|
80
|
+
surface: surface?,
|
|
81
|
+
stuck: stuck?,
|
|
82
|
+
created_at: @created_at
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def validate_trap_type!(val)
|
|
89
|
+
return if Constants::TRAP_TYPES.include?(val.to_sym)
|
|
90
|
+
|
|
91
|
+
raise ArgumentError,
|
|
92
|
+
"unknown trap type: #{val.inspect}; " \
|
|
93
|
+
"must be one of #{Constants::TRAP_TYPES.inspect}"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|