lex-agentic-self 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-self.gemspec +31 -0
- data/lib/legion/extensions/agentic/self/agency/client.rb +21 -0
- data/lib/legion/extensions/agentic/self/agency/helpers/constants.rb +77 -0
- data/lib/legion/extensions/agentic/self/agency/helpers/efficacy_model.rb +136 -0
- data/lib/legion/extensions/agentic/self/agency/helpers/outcome_event.rb +52 -0
- data/lib/legion/extensions/agentic/self/agency/runners/agency.rb +117 -0
- data/lib/legion/extensions/agentic/self/agency/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/agency.rb +19 -0
- data/lib/legion/extensions/agentic/self/anchor/client.rb +15 -0
- data/lib/legion/extensions/agentic/self/anchor/helpers/anchor.rb +92 -0
- data/lib/legion/extensions/agentic/self/anchor/helpers/anchor_engine.rb +123 -0
- data/lib/legion/extensions/agentic/self/anchor/helpers/chain.rb +93 -0
- data/lib/legion/extensions/agentic/self/anchor/helpers/constants.rb +46 -0
- data/lib/legion/extensions/agentic/self/anchor/runners/cognitive_anchor.rb +70 -0
- data/lib/legion/extensions/agentic/self/anchor/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/anchor.rb +22 -0
- data/lib/legion/extensions/agentic/self/anosognosia/client.rb +28 -0
- data/lib/legion/extensions/agentic/self/anosognosia/helpers/anosognosia_engine.rb +153 -0
- data/lib/legion/extensions/agentic/self/anosognosia/helpers/cognitive_deficit.rb +71 -0
- data/lib/legion/extensions/agentic/self/anosognosia/helpers/constants.rb +29 -0
- data/lib/legion/extensions/agentic/self/anosognosia/runners/anosognosia.rb +98 -0
- data/lib/legion/extensions/agentic/self/anosognosia/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/anosognosia.rb +19 -0
- data/lib/legion/extensions/agentic/self/architecture/client.rb +19 -0
- data/lib/legion/extensions/agentic/self/architecture/helpers/architecture_engine.rb +167 -0
- data/lib/legion/extensions/agentic/self/architecture/helpers/connection.rb +57 -0
- data/lib/legion/extensions/agentic/self/architecture/helpers/constants.rb +37 -0
- data/lib/legion/extensions/agentic/self/architecture/helpers/subsystem.rb +80 -0
- data/lib/legion/extensions/agentic/self/architecture/runners/cognitive_architecture.rb +125 -0
- data/lib/legion/extensions/agentic/self/architecture/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/architecture.rb +20 -0
- data/lib/legion/extensions/agentic/self/default_mode_network/actors/idle.rb +45 -0
- data/lib/legion/extensions/agentic/self/default_mode_network/client.rb +28 -0
- data/lib/legion/extensions/agentic/self/default_mode_network/helpers/constants.rb +53 -0
- data/lib/legion/extensions/agentic/self/default_mode_network/helpers/dmn_engine.rb +221 -0
- data/lib/legion/extensions/agentic/self/default_mode_network/helpers/wandering_thought.rb +60 -0
- data/lib/legion/extensions/agentic/self/default_mode_network/runners/default_mode_network.rb +122 -0
- data/lib/legion/extensions/agentic/self/default_mode_network/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/default_mode_network.rb +20 -0
- data/lib/legion/extensions/agentic/self/fingerprint/client.rb +28 -0
- data/lib/legion/extensions/agentic/self/fingerprint/helpers/cognitive_trait.rb +73 -0
- data/lib/legion/extensions/agentic/self/fingerprint/helpers/constants.rb +60 -0
- data/lib/legion/extensions/agentic/self/fingerprint/helpers/fingerprint_engine.rb +169 -0
- data/lib/legion/extensions/agentic/self/fingerprint/runners/cognitive_fingerprint.rb +86 -0
- data/lib/legion/extensions/agentic/self/fingerprint/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/fingerprint.rb +19 -0
- data/lib/legion/extensions/agentic/self/identity/actors/credential_refresh.rb +49 -0
- data/lib/legion/extensions/agentic/self/identity/actors/orphan_check.rb +52 -0
- data/lib/legion/extensions/agentic/self/identity/client.rb +27 -0
- data/lib/legion/extensions/agentic/self/identity/helpers/dimensions.rb +75 -0
- data/lib/legion/extensions/agentic/self/identity/helpers/fingerprint.rb +170 -0
- data/lib/legion/extensions/agentic/self/identity/helpers/graph_client.rb +29 -0
- data/lib/legion/extensions/agentic/self/identity/helpers/graph_token.rb +36 -0
- data/lib/legion/extensions/agentic/self/identity/helpers/token_cache.rb +59 -0
- data/lib/legion/extensions/agentic/self/identity/helpers/vault_secrets.rb +80 -0
- data/lib/legion/extensions/agentic/self/identity/local_migrations/20260316000030_create_fingerprint.rb +20 -0
- data/lib/legion/extensions/agentic/self/identity/runners/entra.rb +402 -0
- data/lib/legion/extensions/agentic/self/identity/runners/identity.rb +90 -0
- data/lib/legion/extensions/agentic/self/identity/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/identity.rb +28 -0
- data/lib/legion/extensions/agentic/self/metacognition/client.rb +27 -0
- data/lib/legion/extensions/agentic/self/metacognition/helpers/constants.rb +377 -0
- data/lib/legion/extensions/agentic/self/metacognition/helpers/narrator_bridge.rb +85 -0
- data/lib/legion/extensions/agentic/self/metacognition/helpers/registry_store.rb +70 -0
- data/lib/legion/extensions/agentic/self/metacognition/helpers/self_model.rb +160 -0
- data/lib/legion/extensions/agentic/self/metacognition/helpers/snapshot_store.rb +82 -0
- data/lib/legion/extensions/agentic/self/metacognition/runners/metacognition.rb +116 -0
- data/lib/legion/extensions/agentic/self/metacognition/runners/registry.rb +180 -0
- data/lib/legion/extensions/agentic/self/metacognition/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/metacognition.rb +22 -0
- data/lib/legion/extensions/agentic/self/metacognitive_monitoring/client.rb +25 -0
- data/lib/legion/extensions/agentic/self/metacognitive_monitoring/helpers/calibration_tracker.rb +96 -0
- data/lib/legion/extensions/agentic/self/metacognitive_monitoring/helpers/constants.rb +47 -0
- data/lib/legion/extensions/agentic/self/metacognitive_monitoring/helpers/monitoring_engine.rb +141 -0
- data/lib/legion/extensions/agentic/self/metacognitive_monitoring/helpers/monitoring_judgment.rb +79 -0
- data/lib/legion/extensions/agentic/self/metacognitive_monitoring/runners/metacognitive_monitoring.rb +151 -0
- data/lib/legion/extensions/agentic/self/metacognitive_monitoring/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/metacognitive_monitoring.rb +20 -0
- data/lib/legion/extensions/agentic/self/narrative_arc/client.rb +29 -0
- data/lib/legion/extensions/agentic/self/narrative_arc/helpers/arc.rb +137 -0
- data/lib/legion/extensions/agentic/self/narrative_arc/helpers/arc_engine.rb +119 -0
- data/lib/legion/extensions/agentic/self/narrative_arc/helpers/beat_event.rb +59 -0
- data/lib/legion/extensions/agentic/self/narrative_arc/helpers/constants.rb +66 -0
- data/lib/legion/extensions/agentic/self/narrative_arc/runners/narrative.rb +101 -0
- data/lib/legion/extensions/agentic/self/narrative_arc/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/narrative_arc.rb +20 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/actors/narrative_decay.rb +45 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/client.rb +22 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/helpers/chapter.rb +48 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/helpers/constants.rb +62 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/helpers/episode.rb +67 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/helpers/narrative_engine.rb +187 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/helpers/theme.rb +50 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/runners/narrative_identity.rb +158 -0
- data/lib/legion/extensions/agentic/self/narrative_identity/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/narrative_identity.rb +21 -0
- data/lib/legion/extensions/agentic/self/narrative_self/client.rb +27 -0
- data/lib/legion/extensions/agentic/self/narrative_self/helpers/autobiography.rb +187 -0
- data/lib/legion/extensions/agentic/self/narrative_self/helpers/constants.rb +42 -0
- data/lib/legion/extensions/agentic/self/narrative_self/helpers/episode.rb +81 -0
- data/lib/legion/extensions/agentic/self/narrative_self/helpers/narrative_thread.rb +65 -0
- data/lib/legion/extensions/agentic/self/narrative_self/runners/narrative_self.rb +86 -0
- data/lib/legion/extensions/agentic/self/narrative_self/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/narrative_self.rb +20 -0
- data/lib/legion/extensions/agentic/self/personality/client.rb +21 -0
- data/lib/legion/extensions/agentic/self/personality/helpers/constants.rb +84 -0
- data/lib/legion/extensions/agentic/self/personality/helpers/personality_store.rb +126 -0
- data/lib/legion/extensions/agentic/self/personality/helpers/trait_model.rb +147 -0
- data/lib/legion/extensions/agentic/self/personality/runners/personality.rb +102 -0
- data/lib/legion/extensions/agentic/self/personality/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/personality.rb +19 -0
- data/lib/legion/extensions/agentic/self/reflection/client.rb +27 -0
- data/lib/legion/extensions/agentic/self/reflection/helpers/constants.rb +66 -0
- data/lib/legion/extensions/agentic/self/reflection/helpers/llm_enhancer.rb +166 -0
- data/lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb +186 -0
- data/lib/legion/extensions/agentic/self/reflection/helpers/reflection.rb +54 -0
- data/lib/legion/extensions/agentic/self/reflection/helpers/reflection_store.rb +99 -0
- data/lib/legion/extensions/agentic/self/reflection/runners/reflection.rb +199 -0
- data/lib/legion/extensions/agentic/self/reflection/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/reflection.rb +21 -0
- data/lib/legion/extensions/agentic/self/self_model/client.rb +19 -0
- data/lib/legion/extensions/agentic/self/self_model/helpers/capability.rb +93 -0
- data/lib/legion/extensions/agentic/self/self_model/helpers/constants.rb +46 -0
- data/lib/legion/extensions/agentic/self/self_model/helpers/knowledge_domain.rb +82 -0
- data/lib/legion/extensions/agentic/self/self_model/helpers/self_model.rb +150 -0
- data/lib/legion/extensions/agentic/self/self_model/runners/self_model.rb +82 -0
- data/lib/legion/extensions/agentic/self/self_model/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/self_model.rb +21 -0
- data/lib/legion/extensions/agentic/self/self_talk/actors/volume_decay.rb +45 -0
- data/lib/legion/extensions/agentic/self/self_talk/client.rb +30 -0
- data/lib/legion/extensions/agentic/self/self_talk/helpers/constants.rb +63 -0
- data/lib/legion/extensions/agentic/self/self_talk/helpers/dialogue.rb +114 -0
- data/lib/legion/extensions/agentic/self/self_talk/helpers/dialogue_turn.rb +43 -0
- data/lib/legion/extensions/agentic/self/self_talk/helpers/inner_voice.rb +77 -0
- data/lib/legion/extensions/agentic/self/self_talk/helpers/llm_enhancer.rb +135 -0
- data/lib/legion/extensions/agentic/self/self_talk/helpers/self_talk_engine.rb +160 -0
- data/lib/legion/extensions/agentic/self/self_talk/runners/self_talk.rb +172 -0
- data/lib/legion/extensions/agentic/self/self_talk/version.rb +13 -0
- data/lib/legion/extensions/agentic/self/self_talk.rb +22 -0
- data/lib/legion/extensions/agentic/self/version.rb +11 -0
- data/lib/legion/extensions/agentic/self.rb +33 -0
- data/spec/legion/extensions/agentic/self/agency/client_spec.rb +67 -0
- data/spec/legion/extensions/agentic/self/agency/helpers/constants_spec.rb +73 -0
- data/spec/legion/extensions/agentic/self/agency/helpers/efficacy_model_spec.rb +190 -0
- data/spec/legion/extensions/agentic/self/agency/helpers/outcome_event_spec.rb +85 -0
- data/spec/legion/extensions/agentic/self/agency/runners/agency_spec.rb +132 -0
- data/spec/legion/extensions/agentic/self/anchor/client_spec.rb +30 -0
- data/spec/legion/extensions/agentic/self/anchor/helpers/anchor_engine_spec.rb +109 -0
- data/spec/legion/extensions/agentic/self/anchor/helpers/anchor_spec.rb +124 -0
- data/spec/legion/extensions/agentic/self/anchor/helpers/chain_spec.rb +106 -0
- data/spec/legion/extensions/agentic/self/anchor/helpers/constants_spec.rb +53 -0
- data/spec/legion/extensions/agentic/self/anchor/runners/cognitive_anchor_spec.rb +70 -0
- data/spec/legion/extensions/agentic/self/anosognosia/anosognosia_spec.rb +15 -0
- data/spec/legion/extensions/agentic/self/anosognosia/client_spec.rb +50 -0
- data/spec/legion/extensions/agentic/self/anosognosia/helpers/anosognosia_engine_spec.rb +266 -0
- data/spec/legion/extensions/agentic/self/anosognosia/helpers/cognitive_deficit_spec.rb +150 -0
- data/spec/legion/extensions/agentic/self/anosognosia/helpers/constants_spec.rb +58 -0
- data/spec/legion/extensions/agentic/self/anosognosia/runners/anosognosia_spec.rb +225 -0
- data/spec/legion/extensions/agentic/self/architecture/client_spec.rb +51 -0
- data/spec/legion/extensions/agentic/self/architecture/helpers/architecture_engine_spec.rb +321 -0
- data/spec/legion/extensions/agentic/self/architecture/helpers/connection_spec.rb +118 -0
- data/spec/legion/extensions/agentic/self/architecture/helpers/subsystem_spec.rb +189 -0
- data/spec/legion/extensions/agentic/self/architecture/runners/cognitive_architecture_spec.rb +181 -0
- data/spec/legion/extensions/agentic/self/default_mode_network/client_spec.rb +69 -0
- data/spec/legion/extensions/agentic/self/default_mode_network/helpers/constants_spec.rb +76 -0
- data/spec/legion/extensions/agentic/self/default_mode_network/helpers/dmn_engine_spec.rb +321 -0
- data/spec/legion/extensions/agentic/self/default_mode_network/helpers/wandering_thought_spec.rb +145 -0
- data/spec/legion/extensions/agentic/self/default_mode_network/runners/default_mode_network_spec.rb +269 -0
- data/spec/legion/extensions/agentic/self/fingerprint/client_spec.rb +54 -0
- data/spec/legion/extensions/agentic/self/fingerprint/helpers/cognitive_trait_spec.rb +180 -0
- data/spec/legion/extensions/agentic/self/fingerprint/helpers/constants_spec.rb +108 -0
- data/spec/legion/extensions/agentic/self/fingerprint/helpers/fingerprint_engine_spec.rb +318 -0
- data/spec/legion/extensions/agentic/self/fingerprint/runners/cognitive_fingerprint_spec.rb +232 -0
- data/spec/legion/extensions/agentic/self/identity/actors/orphan_check_spec.rb +104 -0
- data/spec/legion/extensions/agentic/self/identity/client_spec.rb +32 -0
- data/spec/legion/extensions/agentic/self/identity/helpers/dimensions_spec.rb +51 -0
- data/spec/legion/extensions/agentic/self/identity/helpers/fingerprint_spec.rb +66 -0
- data/spec/legion/extensions/agentic/self/identity/helpers/graph_client_spec.rb +19 -0
- data/spec/legion/extensions/agentic/self/identity/helpers/graph_token_spec.rb +31 -0
- data/spec/legion/extensions/agentic/self/identity/helpers/token_cache_spec.rb +50 -0
- data/spec/legion/extensions/agentic/self/identity/local_persistence_spec.rb +329 -0
- data/spec/legion/extensions/agentic/self/identity/runners/entra_spec.rb +655 -0
- data/spec/legion/extensions/agentic/self/identity/runners/identity_spec.rb +61 -0
- data/spec/legion/extensions/agentic/self/metacognition/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/self/metacognition/helpers/constants_spec.rb +31 -0
- data/spec/legion/extensions/agentic/self/metacognition/helpers/narrator_bridge_spec.rb +102 -0
- data/spec/legion/extensions/agentic/self/metacognition/helpers/registry_store_spec.rb +227 -0
- data/spec/legion/extensions/agentic/self/metacognition/helpers/self_model_spec.rb +117 -0
- data/spec/legion/extensions/agentic/self/metacognition/helpers/snapshot_store_spec.rb +128 -0
- data/spec/legion/extensions/agentic/self/metacognition/runners/metacognition_spec.rb +110 -0
- data/spec/legion/extensions/agentic/self/metacognition/runners/registry_spec.rb +281 -0
- data/spec/legion/extensions/agentic/self/metacognitive_monitoring/client_spec.rb +59 -0
- data/spec/legion/extensions/agentic/self/metacognitive_monitoring/helpers/calibration_tracker_spec.rb +143 -0
- data/spec/legion/extensions/agentic/self/metacognitive_monitoring/helpers/constants_spec.rb +91 -0
- data/spec/legion/extensions/agentic/self/metacognitive_monitoring/helpers/monitoring_engine_spec.rb +198 -0
- data/spec/legion/extensions/agentic/self/metacognitive_monitoring/helpers/monitoring_judgment_spec.rb +172 -0
- data/spec/legion/extensions/agentic/self/metacognitive_monitoring/runners/metacognitive_monitoring_spec.rb +244 -0
- data/spec/legion/extensions/agentic/self/narrative_arc/client_spec.rb +22 -0
- data/spec/legion/extensions/agentic/self/narrative_arc/helpers/arc_engine_spec.rb +183 -0
- data/spec/legion/extensions/agentic/self/narrative_arc/helpers/arc_spec.rb +177 -0
- data/spec/legion/extensions/agentic/self/narrative_arc/helpers/beat_event_spec.rb +96 -0
- data/spec/legion/extensions/agentic/self/narrative_arc/helpers/constants_spec.rb +75 -0
- data/spec/legion/extensions/agentic/self/narrative_arc/runners/narrative_spec.rb +142 -0
- data/spec/legion/extensions/agentic/self/narrative_identity/client_spec.rb +69 -0
- data/spec/legion/extensions/agentic/self/narrative_identity/helpers/chapter_spec.rb +85 -0
- data/spec/legion/extensions/agentic/self/narrative_identity/helpers/constants_spec.rb +83 -0
- data/spec/legion/extensions/agentic/self/narrative_identity/helpers/episode_spec.rb +180 -0
- data/spec/legion/extensions/agentic/self/narrative_identity/helpers/narrative_engine_spec.rb +307 -0
- data/spec/legion/extensions/agentic/self/narrative_identity/helpers/theme_spec.rb +107 -0
- data/spec/legion/extensions/agentic/self/narrative_identity/runners/narrative_identity_spec.rb +240 -0
- data/spec/legion/extensions/agentic/self/narrative_self/client_spec.rb +67 -0
- data/spec/legion/extensions/agentic/self/narrative_self/helpers/autobiography_spec.rb +155 -0
- data/spec/legion/extensions/agentic/self/narrative_self/helpers/constants_spec.rb +28 -0
- data/spec/legion/extensions/agentic/self/narrative_self/helpers/episode_spec.rb +144 -0
- data/spec/legion/extensions/agentic/self/narrative_self/helpers/narrative_thread_spec.rb +87 -0
- data/spec/legion/extensions/agentic/self/narrative_self/runners/narrative_self_spec.rb +118 -0
- data/spec/legion/extensions/agentic/self/personality/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/self/personality/helpers/constants_spec.rb +41 -0
- data/spec/legion/extensions/agentic/self/personality/helpers/personality_store_spec.rb +66 -0
- data/spec/legion/extensions/agentic/self/personality/helpers/trait_model_spec.rb +148 -0
- data/spec/legion/extensions/agentic/self/personality/runners/personality_spec.rb +67 -0
- data/spec/legion/extensions/agentic/self/reflection/client_spec.rb +24 -0
- data/spec/legion/extensions/agentic/self/reflection/helpers/llm_enhancer_spec.rb +191 -0
- data/spec/legion/extensions/agentic/self/reflection/helpers/monitors_spec.rb +120 -0
- data/spec/legion/extensions/agentic/self/reflection/helpers/reflection_spec.rb +49 -0
- data/spec/legion/extensions/agentic/self/reflection/helpers/reflection_store_spec.rb +93 -0
- data/spec/legion/extensions/agentic/self/reflection/runners/reflection_spec.rb +204 -0
- data/spec/legion/extensions/agentic/self/self_model/client_spec.rb +55 -0
- data/spec/legion/extensions/agentic/self/self_model/helpers/capability_spec.rb +160 -0
- data/spec/legion/extensions/agentic/self/self_model/helpers/knowledge_domain_spec.rb +128 -0
- data/spec/legion/extensions/agentic/self/self_model/helpers/self_model_spec.rb +238 -0
- data/spec/legion/extensions/agentic/self/self_model/runners/self_model_spec.rb +143 -0
- data/spec/legion/extensions/agentic/self/self_talk/actors/volume_decay_spec.rb +46 -0
- data/spec/legion/extensions/agentic/self/self_talk/client_spec.rb +26 -0
- data/spec/legion/extensions/agentic/self/self_talk/helpers/constants_spec.rb +110 -0
- data/spec/legion/extensions/agentic/self/self_talk/helpers/dialogue_spec.rb +191 -0
- data/spec/legion/extensions/agentic/self/self_talk/helpers/dialogue_turn_spec.rb +78 -0
- data/spec/legion/extensions/agentic/self/self_talk/helpers/inner_voice_spec.rb +172 -0
- data/spec/legion/extensions/agentic/self/self_talk/helpers/llm_enhancer_spec.rb +206 -0
- data/spec/legion/extensions/agentic/self/self_talk/helpers/self_talk_engine_spec.rb +239 -0
- data/spec/legion/extensions/agentic/self/self_talk/runners/self_talk_llm_spec.rb +169 -0
- data/spec/legion/extensions/agentic/self/self_talk/runners/self_talk_spec.rb +196 -0
- data/spec/spec_helper.rb +46 -0
- metadata +347 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::Agentic::Self::Reflection::Helpers::ReflectionStore do
|
|
4
|
+
subject(:store) { described_class.new }
|
|
5
|
+
|
|
6
|
+
let(:reflection) do
|
|
7
|
+
Legion::Extensions::Agentic::Self::Reflection::Helpers::ReflectionFactory.new_reflection(
|
|
8
|
+
category: :prediction_calibration,
|
|
9
|
+
observation: 'Low accuracy',
|
|
10
|
+
severity: :significant,
|
|
11
|
+
recommendation: :increase_curiosity
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '#store and #get' do
|
|
16
|
+
it 'stores and retrieves a reflection' do
|
|
17
|
+
store.store(reflection)
|
|
18
|
+
expect(store.get(reflection[:reflection_id])).to eq(reflection)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'increments total_generated' do
|
|
22
|
+
store.store(reflection)
|
|
23
|
+
expect(store.total_generated).to eq(1)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#recent' do
|
|
28
|
+
it 'returns reflections in reverse chronological order' do
|
|
29
|
+
r1 = Legion::Extensions::Agentic::Self::Reflection::Helpers::ReflectionFactory.new_reflection(
|
|
30
|
+
category: :trust_drift, observation: 'first'
|
|
31
|
+
)
|
|
32
|
+
store.store(r1)
|
|
33
|
+
r2 = Legion::Extensions::Agentic::Self::Reflection::Helpers::ReflectionFactory.new_reflection(
|
|
34
|
+
category: :memory_health, observation: 'second'
|
|
35
|
+
)
|
|
36
|
+
store.store(r2)
|
|
37
|
+
|
|
38
|
+
recent = store.recent(limit: 2)
|
|
39
|
+
expect(recent.first[:observation]).to eq('second')
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe '#by_category' do
|
|
44
|
+
it 'filters by category' do
|
|
45
|
+
store.store(reflection)
|
|
46
|
+
other = Legion::Extensions::Agentic::Self::Reflection::Helpers::ReflectionFactory.new_reflection(
|
|
47
|
+
category: :trust_drift, observation: 'other'
|
|
48
|
+
)
|
|
49
|
+
store.store(other)
|
|
50
|
+
|
|
51
|
+
results = store.by_category(:prediction_calibration)
|
|
52
|
+
expect(results.size).to eq(1)
|
|
53
|
+
expect(results.first[:category]).to eq(:prediction_calibration)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#mark_acted_on' do
|
|
58
|
+
it 'marks a reflection as acted on' do
|
|
59
|
+
store.store(reflection)
|
|
60
|
+
store.mark_acted_on(reflection[:reflection_id])
|
|
61
|
+
expect(store.get(reflection[:reflection_id])[:acted_on]).to be true
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'returns nil for unknown id' do
|
|
65
|
+
expect(store.mark_acted_on('nonexistent')).to be_nil
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe '#cognitive_health' do
|
|
70
|
+
it 'returns 1.0 when all scores are at default' do
|
|
71
|
+
expect(store.cognitive_health).to eq(1.0)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'decreases when category scores drop' do
|
|
75
|
+
store.update_category_score(:prediction_calibration, 0.3)
|
|
76
|
+
expect(store.cognitive_health).to be < 1.0
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe '#severity_counts' do
|
|
81
|
+
it 'counts reflections by severity' do
|
|
82
|
+
store.store(reflection)
|
|
83
|
+
critical = Legion::Extensions::Agentic::Self::Reflection::Helpers::ReflectionFactory.new_reflection(
|
|
84
|
+
category: :cognitive_load, observation: 'overload', severity: :critical
|
|
85
|
+
)
|
|
86
|
+
store.store(critical)
|
|
87
|
+
|
|
88
|
+
counts = store.severity_counts
|
|
89
|
+
expect(counts[:significant]).to eq(1)
|
|
90
|
+
expect(counts[:critical]).to eq(1)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::Agentic::Self::Reflection::Runners::Reflection do
|
|
4
|
+
let(:client) { Legion::Extensions::Agentic::Self::Reflection::Client.new }
|
|
5
|
+
|
|
6
|
+
describe '#reflect' do
|
|
7
|
+
it 'returns results with no tick data' do
|
|
8
|
+
result = client.reflect(tick_results: {})
|
|
9
|
+
expect(result[:reflections_generated]).to eq(0)
|
|
10
|
+
expect(result[:cognitive_health]).to eq(1.0)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'generates reflections from problematic tick results' do
|
|
14
|
+
result = client.reflect(tick_results: {
|
|
15
|
+
prediction_engine: { confidence: 0.2 },
|
|
16
|
+
emotional_evaluation: { stability: 0.1 },
|
|
17
|
+
memory_consolidation: { pruned: 90, total: 100 }
|
|
18
|
+
})
|
|
19
|
+
expect(result[:reflections_generated]).to be >= 2
|
|
20
|
+
expect(result[:cognitive_health]).to be < 1.0
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'accumulates metric history over multiple calls' do
|
|
24
|
+
5.times { client.reflect(tick_results: { prediction_engine: { confidence: 0.9 } }) }
|
|
25
|
+
5.times { client.reflect(tick_results: { prediction_engine: { confidence: 0.4 } }) }
|
|
26
|
+
|
|
27
|
+
# Should detect trend
|
|
28
|
+
result = client.reflect(tick_results: { prediction_engine: { confidence: 0.3 } })
|
|
29
|
+
predictions = result[:new_reflections].select { |r| r[:category] == :prediction_calibration }
|
|
30
|
+
expect(predictions).not_to be_empty
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '#cognitive_health' do
|
|
35
|
+
it 'returns full health with no data' do
|
|
36
|
+
result = client.cognitive_health
|
|
37
|
+
expect(result[:health]).to eq(1.0)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'degrades with bad tick results' do
|
|
41
|
+
client.reflect(tick_results: {
|
|
42
|
+
prediction_engine: { confidence: 0.2 },
|
|
43
|
+
emotional_evaluation: { stability: 0.1 }
|
|
44
|
+
})
|
|
45
|
+
result = client.cognitive_health
|
|
46
|
+
expect(result[:health]).to be < 1.0
|
|
47
|
+
expect(result[:category_scores][:prediction_calibration]).to eq(0.2)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '#recent_reflections' do
|
|
52
|
+
it 'returns recent reflections' do
|
|
53
|
+
client.reflect(tick_results: { prediction_engine: { confidence: 0.1 } })
|
|
54
|
+
result = client.recent_reflections(limit: 5)
|
|
55
|
+
expect(result[:reflections]).not_to be_empty
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe '#reflections_by_category' do
|
|
60
|
+
it 'filters by category' do
|
|
61
|
+
client.reflect(tick_results: {
|
|
62
|
+
prediction_engine: { confidence: 0.1 },
|
|
63
|
+
emotional_evaluation: { stability: 0.1 }
|
|
64
|
+
})
|
|
65
|
+
result = client.reflections_by_category(category: :emotional_stability)
|
|
66
|
+
result[:reflections].each do |r|
|
|
67
|
+
expect(r[:category]).to eq(:emotional_stability)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe '#adapt' do
|
|
73
|
+
it 'marks a reflection as acted upon' do
|
|
74
|
+
client.reflect(tick_results: { prediction_engine: { confidence: 0.1 } })
|
|
75
|
+
reflections = client.recent_reflections[:reflections]
|
|
76
|
+
id = reflections.first[:reflection_id]
|
|
77
|
+
|
|
78
|
+
result = client.adapt(reflection_id: id)
|
|
79
|
+
expect(result[:adapted]).to be true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'returns error for unknown id' do
|
|
83
|
+
result = client.adapt(reflection_id: 'nonexistent')
|
|
84
|
+
expect(result[:error]).to eq(:not_found)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe '#reflection_stats' do
|
|
89
|
+
it 'returns comprehensive stats' do
|
|
90
|
+
client.reflect(tick_results: { prediction_engine: { confidence: 0.1 } })
|
|
91
|
+
stats = client.reflection_stats
|
|
92
|
+
expect(stats[:total_generated]).to be >= 1
|
|
93
|
+
expect(stats[:cognitive_health]).to be_a(Float)
|
|
94
|
+
expect(stats[:severity_counts]).to be_a(Hash)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe '#reflect with LLM enhancement' do
|
|
99
|
+
let(:fake_chat) { double }
|
|
100
|
+
let(:llm_observation) { 'My prediction confidence is critically low at 10%, strongly correlated with declining memory health.' }
|
|
101
|
+
let(:fake_response) do
|
|
102
|
+
double(content: <<~TEXT)
|
|
103
|
+
EMOTION: Emotional state appears stable this tick.
|
|
104
|
+
PREDICTION: #{llm_observation}
|
|
105
|
+
MEMORY: Memory health is nominal.
|
|
106
|
+
TRUST: Trust scores unchanged.
|
|
107
|
+
CURIOSITY: Curiosity levels normal.
|
|
108
|
+
IDENTITY: Identity entropy within bounds.
|
|
109
|
+
TEXT
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
before do
|
|
113
|
+
stub_const('Legion::LLM', double(respond_to?: true, started?: true))
|
|
114
|
+
allow(Legion::LLM).to receive(:chat).and_return(fake_chat)
|
|
115
|
+
allow(fake_chat).to receive(:with_instructions)
|
|
116
|
+
allow(fake_chat).to receive(:ask).and_return(fake_response)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'replaces mechanical observation text with LLM-generated text' do
|
|
120
|
+
result = client.reflect(tick_results: { prediction_engine: { confidence: 0.1 } })
|
|
121
|
+
prediction_reflection = result[:new_reflections].find { |r| r[:category] == :prediction_calibration }
|
|
122
|
+
expect(prediction_reflection).not_to be_nil
|
|
123
|
+
expect(prediction_reflection[:observation]).to include('critically low')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'does not change recommendation symbols when using LLM' do
|
|
127
|
+
result = client.reflect(tick_results: { prediction_engine: { confidence: 0.1 } })
|
|
128
|
+
prediction_reflection = result[:new_reflections].find { |r| r[:category] == :prediction_calibration }
|
|
129
|
+
expect(prediction_reflection).not_to be_nil
|
|
130
|
+
expect(prediction_reflection[:recommendation]).to eq(:increase_curiosity)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'falls back to mechanical observations when LLM returns nil' do
|
|
134
|
+
allow(fake_chat).to receive(:ask).and_return(double(content: nil))
|
|
135
|
+
|
|
136
|
+
result = client.reflect(tick_results: {
|
|
137
|
+
prediction_engine: { confidence: 0.2 },
|
|
138
|
+
emotional_evaluation: { stability: 0.1 }
|
|
139
|
+
})
|
|
140
|
+
expect(result[:reflections_generated]).to be >= 1
|
|
141
|
+
# Mechanical observations still present (LLM returned nil)
|
|
142
|
+
result[:new_reflections].each do |r|
|
|
143
|
+
expect(r[:observation]).to be_a(String)
|
|
144
|
+
expect(r[:observation]).not_to be_empty
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
describe '#reflect_on_dream' do
|
|
150
|
+
context 'without LLM' do
|
|
151
|
+
it 'uses mechanical fallback for empty dream results' do
|
|
152
|
+
result = client.reflect_on_dream(dream_results: {})
|
|
153
|
+
expect(result[:reflection]).to eq('Dream cycle completed.')
|
|
154
|
+
expect(result[:source]).to eq(:mechanical)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'builds mechanical reflection from dream phase data' do
|
|
158
|
+
result = client.reflect_on_dream(dream_results: {
|
|
159
|
+
memory_audit: { decayed: 3, unresolved_count: 2 },
|
|
160
|
+
contradiction_resolution: { detected: 1, resolved: 1 },
|
|
161
|
+
agenda_formation: { agenda_items: 3 }
|
|
162
|
+
})
|
|
163
|
+
expect(result[:reflection]).to include('Memory audit')
|
|
164
|
+
expect(result[:source]).to eq(:mechanical)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
context 'with LLM available' do
|
|
169
|
+
let(:fake_chat) { double }
|
|
170
|
+
let(:fake_response) do
|
|
171
|
+
double(content: <<~TEXT)
|
|
172
|
+
REFLECTION: The dream cycle consolidated 3 traces and resolved a contradiction in the identity domain. I notice a strengthening of procedural memory pathways.
|
|
173
|
+
TEXT
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
before do
|
|
177
|
+
stub_const('Legion::LLM', double(respond_to?: true, started?: true))
|
|
178
|
+
allow(Legion::LLM).to receive(:chat).and_return(fake_chat)
|
|
179
|
+
allow(fake_chat).to receive(:with_instructions)
|
|
180
|
+
allow(fake_chat).to receive(:ask).and_return(fake_response)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it 'uses LLM-generated reflection when available' do
|
|
184
|
+
result = client.reflect_on_dream(dream_results: {
|
|
185
|
+
memory_audit: { decayed: 3, unresolved_count: 2 },
|
|
186
|
+
contradiction_resolution: { detected: 1, resolved: 1 }
|
|
187
|
+
})
|
|
188
|
+
expect(result[:reflection]).to include('consolidated 3 traces')
|
|
189
|
+
expect(result[:source]).to eq(:llm)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'falls back to mechanical when LLM returns nil' do
|
|
193
|
+
allow(fake_chat).to receive(:ask).and_return(double(content: nil))
|
|
194
|
+
|
|
195
|
+
result = client.reflect_on_dream(dream_results: {
|
|
196
|
+
memory_audit: { decayed: 1, unresolved_count: 0 }
|
|
197
|
+
})
|
|
198
|
+
expect(result[:source]).to eq(:mechanical)
|
|
199
|
+
expect(result[:reflection]).to be_a(String)
|
|
200
|
+
expect(result[:reflection]).not_to be_empty
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::Agentic::Self::SelfModel::Client do
|
|
4
|
+
subject(:client) { described_class.new }
|
|
5
|
+
|
|
6
|
+
it 'full lifecycle: add capability and knowledge, predict, record, introspect' do
|
|
7
|
+
cap_result = client.add_self_capability(name: 'problem solving', domain: :cognitive, competence: 0.6)
|
|
8
|
+
expect(cap_result[:success]).to be true
|
|
9
|
+
|
|
10
|
+
dom_result = client.add_self_knowledge(name: 'algorithms', depth: 0.5, breadth: 0.4)
|
|
11
|
+
expect(dom_result[:success]).to be true
|
|
12
|
+
|
|
13
|
+
pred = client.predict_own_success(capability_id: cap_result[:capability_id])
|
|
14
|
+
expect(pred[:success]).to be true
|
|
15
|
+
expect(pred[:predicted_probability]).to be_a(Float)
|
|
16
|
+
|
|
17
|
+
outcome = client.record_self_outcome(
|
|
18
|
+
capability_id: cap_result[:capability_id],
|
|
19
|
+
predicted: true,
|
|
20
|
+
actual: true
|
|
21
|
+
)
|
|
22
|
+
expect(outcome[:success]).to be true
|
|
23
|
+
|
|
24
|
+
introspection = client.self_introspection
|
|
25
|
+
expect(introspection[:success]).to be true
|
|
26
|
+
expect(introspection[:strengths]).to be_an(Array)
|
|
27
|
+
|
|
28
|
+
report = client.self_calibration_report
|
|
29
|
+
expect(report[:success]).to be true
|
|
30
|
+
|
|
31
|
+
stats = client.self_model_stats
|
|
32
|
+
expect(stats[:capability_count]).to eq(1)
|
|
33
|
+
expect(stats[:knowledge_domain_count]).to eq(1)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'accepts injected model' do
|
|
37
|
+
injected = Legion::Extensions::Agentic::Self::SelfModel::Helpers::SelfModel.new
|
|
38
|
+
c = described_class.new(model: injected)
|
|
39
|
+
c.add_self_capability(name: 'testing')
|
|
40
|
+
expect(injected.capabilities.size).to eq(1)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'tracks strengths and weaknesses separately' do
|
|
44
|
+
client.add_self_capability(name: 'expert task', competence: 0.9)
|
|
45
|
+
client.add_self_capability(name: 'beginner task', competence: 0.1)
|
|
46
|
+
|
|
47
|
+
strengths = client.self_strengths
|
|
48
|
+
weaknesses = client.self_weaknesses
|
|
49
|
+
|
|
50
|
+
expect(strengths[:count]).to eq(1)
|
|
51
|
+
expect(weaknesses[:count]).to eq(1)
|
|
52
|
+
expect(strengths[:strengths].first[:name]).to eq('expert task')
|
|
53
|
+
expect(weaknesses[:weaknesses].first[:name]).to eq('beginner task')
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::Agentic::Self::SelfModel::Helpers::Capability do
|
|
4
|
+
subject(:cap) do
|
|
5
|
+
described_class.new(id: :cap_one, name: 'write code', domain: :engineering, competence: 0.6)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe '#initialize' do
|
|
9
|
+
it 'sets id, name, domain' do
|
|
10
|
+
expect(cap.id).to eq(:cap_one)
|
|
11
|
+
expect(cap.name).to eq('write code')
|
|
12
|
+
expect(cap.domain).to eq(:engineering)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'sets competence' do
|
|
16
|
+
expect(cap.competence).to eq(0.6)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'starts with zero attempts and successes' do
|
|
20
|
+
expect(cap.attempts).to eq(0)
|
|
21
|
+
expect(cap.successes).to eq(0)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'starts with zero calibration error' do
|
|
25
|
+
expect(cap.calibration_error).to eq(0.0)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'clamps competence to floor' do
|
|
29
|
+
c = described_class.new(id: :x, name: 'x', competence: -1.0)
|
|
30
|
+
expect(c.competence).to eq(Legion::Extensions::Agentic::Self::SelfModel::Helpers::Constants::COMPETENCE_FLOOR)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'clamps competence to ceiling' do
|
|
34
|
+
c = described_class.new(id: :x, name: 'x', competence: 2.0)
|
|
35
|
+
expect(c.competence).to eq(Legion::Extensions::Agentic::Self::SelfModel::Helpers::Constants::COMPETENCE_CEILING)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'sets initial state based on competence' do
|
|
39
|
+
expect(cap.state).to eq(:competent)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe '#record_attempt' do
|
|
44
|
+
it 'increments attempts' do
|
|
45
|
+
cap.record_attempt(predicted_success: true, actual_success: true)
|
|
46
|
+
expect(cap.attempts).to eq(1)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'increments successes on actual success' do
|
|
50
|
+
cap.record_attempt(predicted_success: true, actual_success: true)
|
|
51
|
+
expect(cap.successes).to eq(1)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'does not increment successes on failure' do
|
|
55
|
+
cap.record_attempt(predicted_success: true, actual_success: false)
|
|
56
|
+
expect(cap.successes).to eq(0)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'updates competence toward actual outcome' do
|
|
60
|
+
original = cap.competence
|
|
61
|
+
cap.record_attempt(predicted_success: true, actual_success: false)
|
|
62
|
+
expect(cap.competence).to be < original
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'updates calibration error toward prediction error' do
|
|
66
|
+
cap.record_attempt(predicted_success: true, actual_success: false)
|
|
67
|
+
expect(cap.calibration_error).not_to eq(0.0)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'keeps competence within floor/ceiling' do
|
|
71
|
+
low_cap = described_class.new(id: :x, name: 'x', competence: 0.06)
|
|
72
|
+
20.times { low_cap.record_attempt(predicted_success: false, actual_success: false) }
|
|
73
|
+
expect(low_cap.competence).to be >= Legion::Extensions::Agentic::Self::SelfModel::Helpers::Constants::COMPETENCE_FLOOR
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe '#state transitions' do
|
|
78
|
+
it 'returns :unknown for competence < 0.2' do
|
|
79
|
+
c = described_class.new(id: :x, name: 'x', competence: 0.1)
|
|
80
|
+
expect(c.state).to eq(:unknown)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'returns :developing for competence 0.2-0.5' do
|
|
84
|
+
c = described_class.new(id: :x, name: 'x', competence: 0.35)
|
|
85
|
+
expect(c.state).to eq(:developing)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'returns :competent for competence 0.5-0.8' do
|
|
89
|
+
expect(cap.state).to eq(:competent)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'returns :expert for competence >= 0.8' do
|
|
93
|
+
c = described_class.new(id: :x, name: 'x', competence: 0.9)
|
|
94
|
+
expect(c.state).to eq(:expert)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe '#competence_label' do
|
|
99
|
+
it 'returns a symbol' do
|
|
100
|
+
expect(cap.competence_label).to be_a(Symbol)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'returns :moderate for 0.6' do
|
|
104
|
+
expect(cap.competence_label).to eq(:moderate)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'returns :high for 0.8' do
|
|
108
|
+
c = described_class.new(id: :x, name: 'x', competence: 0.8)
|
|
109
|
+
expect(c.competence_label).to eq(:high)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
describe '#calibrated?' do
|
|
114
|
+
it 'returns true when calibration_error is within threshold' do
|
|
115
|
+
expect(cap.calibrated?).to be true
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'returns false after many overconfident predictions' do
|
|
119
|
+
c = described_class.new(id: :x, name: 'x', competence: 0.9)
|
|
120
|
+
20.times { c.record_attempt(predicted_success: true, actual_success: false) }
|
|
121
|
+
expect(c.calibrated?).to be false
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
describe '#overconfident?' do
|
|
126
|
+
it 'returns false initially' do
|
|
127
|
+
expect(cap.overconfident?).to be false
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'returns true after sustained overconfident predictions' do
|
|
131
|
+
c = described_class.new(id: :x, name: 'x', competence: 0.9)
|
|
132
|
+
30.times { c.record_attempt(predicted_success: true, actual_success: false) }
|
|
133
|
+
expect(c.overconfident?).to be true
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
describe '#underconfident?' do
|
|
138
|
+
it 'returns false initially' do
|
|
139
|
+
expect(cap.underconfident?).to be false
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'returns true after sustained underconfident predictions' do
|
|
143
|
+
c = described_class.new(id: :x, name: 'x', competence: 0.1)
|
|
144
|
+
30.times { c.record_attempt(predicted_success: false, actual_success: true) }
|
|
145
|
+
expect(c.underconfident?).to be true
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
describe '#to_h' do
|
|
150
|
+
it 'returns expected keys' do
|
|
151
|
+
h = cap.to_h
|
|
152
|
+
expect(h).to include(:id, :name, :domain, :competence, :state, :attempts, :successes,
|
|
153
|
+
:calibration_error, :calibrated, :overconfident, :underconfident)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it 'rounds competence to 4 decimal places' do
|
|
157
|
+
expect(cap.to_h[:competence]).to eq(cap.competence.round(4))
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Legion::Extensions::Agentic::Self::SelfModel::Helpers::KnowledgeDomain do
|
|
4
|
+
subject(:dom) do
|
|
5
|
+
described_class.new(id: :dom_one, name: 'machine learning', depth: 0.4, breadth: 0.3)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe '#initialize' do
|
|
9
|
+
it 'sets id and name' do
|
|
10
|
+
expect(dom.id).to eq(:dom_one)
|
|
11
|
+
expect(dom.name).to eq('machine learning')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'sets depth and breadth' do
|
|
15
|
+
expect(dom.depth).to be_within(0.001).of(0.4)
|
|
16
|
+
expect(dom.breadth).to be_within(0.001).of(0.3)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'computes confidence as average of depth and breadth' do
|
|
20
|
+
expect(dom.confidence).to be_within(0.001).of(0.35)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'starts with nil last_accessed' do
|
|
24
|
+
expect(dom.last_accessed).to be_nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'clamps depth to 0-1' do
|
|
28
|
+
d = described_class.new(id: :x, name: 'x', depth: 2.0, breadth: 0.0)
|
|
29
|
+
expect(d.depth).to eq(1.0)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'clamps breadth to 0-1' do
|
|
33
|
+
d = described_class.new(id: :x, name: 'x', depth: 0.0, breadth: -0.5)
|
|
34
|
+
expect(d.breadth).to eq(0.0)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe '#deepen' do
|
|
39
|
+
it 'increases depth' do
|
|
40
|
+
original = dom.depth
|
|
41
|
+
dom.deepen(amount: 0.2)
|
|
42
|
+
expect(dom.depth).to be > original
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'updates confidence after deepening' do
|
|
46
|
+
original = dom.confidence
|
|
47
|
+
dom.deepen(amount: 0.3)
|
|
48
|
+
expect(dom.confidence).to be > original
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'clamps depth at 1.0' do
|
|
52
|
+
dom.deepen(amount: 5.0)
|
|
53
|
+
expect(dom.depth).to eq(1.0)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'updates state after deepening' do
|
|
57
|
+
d = described_class.new(id: :x, name: 'x', depth: 0.0, breadth: 0.0)
|
|
58
|
+
d.deepen(amount: 0.9)
|
|
59
|
+
expect(d.state).not_to eq(:ignorant)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#broaden' do
|
|
64
|
+
it 'increases breadth' do
|
|
65
|
+
original = dom.breadth
|
|
66
|
+
dom.broaden(amount: 0.2)
|
|
67
|
+
expect(dom.breadth).to be > original
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'updates confidence after broadening' do
|
|
71
|
+
original = dom.confidence
|
|
72
|
+
dom.broaden(amount: 0.3)
|
|
73
|
+
expect(dom.confidence).to be > original
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'clamps breadth at 1.0' do
|
|
77
|
+
dom.broaden(amount: 5.0)
|
|
78
|
+
expect(dom.breadth).to eq(1.0)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe '#access!' do
|
|
83
|
+
it 'sets last_accessed to current time' do
|
|
84
|
+
dom.access!
|
|
85
|
+
expect(dom.last_accessed).not_to be_nil
|
|
86
|
+
expect(dom.last_accessed).to be_a(Time)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe '#state' do
|
|
91
|
+
it 'returns :ignorant for very low scores' do
|
|
92
|
+
d = described_class.new(id: :x, name: 'x', depth: 0.05, breadth: 0.05)
|
|
93
|
+
expect(d.state).to eq(:ignorant)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'returns :aware for low scores' do
|
|
97
|
+
d = described_class.new(id: :x, name: 'x', depth: 0.3, breadth: 0.3)
|
|
98
|
+
expect(d.state).to eq(:aware)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'returns :familiar for moderate scores' do
|
|
102
|
+
expect(dom.state).to eq(:aware)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'returns :expert for high scores' do
|
|
106
|
+
d = described_class.new(id: :x, name: 'x', depth: 0.9, breadth: 0.9)
|
|
107
|
+
expect(d.state).to eq(:expert)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe '#knowledge_label' do
|
|
112
|
+
it 'returns a symbol' do
|
|
113
|
+
expect(dom.knowledge_label).to be_a(Symbol)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
describe '#to_h' do
|
|
118
|
+
it 'returns expected keys' do
|
|
119
|
+
h = dom.to_h
|
|
120
|
+
expect(h).to include(:id, :name, :depth, :breadth, :confidence, :state, :knowledge_label, :last_accessed)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'rounds depth and breadth' do
|
|
124
|
+
expect(dom.to_h[:depth]).to eq(dom.depth.round(4))
|
|
125
|
+
expect(dom.to_h[:breadth]).to eq(dom.breadth.round(4))
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|