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.
Files changed (249) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +12 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +21 -0
  5. data/README.md +13 -0
  6. data/lex-agentic-self.gemspec +31 -0
  7. data/lib/legion/extensions/agentic/self/agency/client.rb +21 -0
  8. data/lib/legion/extensions/agentic/self/agency/helpers/constants.rb +77 -0
  9. data/lib/legion/extensions/agentic/self/agency/helpers/efficacy_model.rb +136 -0
  10. data/lib/legion/extensions/agentic/self/agency/helpers/outcome_event.rb +52 -0
  11. data/lib/legion/extensions/agentic/self/agency/runners/agency.rb +117 -0
  12. data/lib/legion/extensions/agentic/self/agency/version.rb +13 -0
  13. data/lib/legion/extensions/agentic/self/agency.rb +19 -0
  14. data/lib/legion/extensions/agentic/self/anchor/client.rb +15 -0
  15. data/lib/legion/extensions/agentic/self/anchor/helpers/anchor.rb +92 -0
  16. data/lib/legion/extensions/agentic/self/anchor/helpers/anchor_engine.rb +123 -0
  17. data/lib/legion/extensions/agentic/self/anchor/helpers/chain.rb +93 -0
  18. data/lib/legion/extensions/agentic/self/anchor/helpers/constants.rb +46 -0
  19. data/lib/legion/extensions/agentic/self/anchor/runners/cognitive_anchor.rb +70 -0
  20. data/lib/legion/extensions/agentic/self/anchor/version.rb +13 -0
  21. data/lib/legion/extensions/agentic/self/anchor.rb +22 -0
  22. data/lib/legion/extensions/agentic/self/anosognosia/client.rb +28 -0
  23. data/lib/legion/extensions/agentic/self/anosognosia/helpers/anosognosia_engine.rb +153 -0
  24. data/lib/legion/extensions/agentic/self/anosognosia/helpers/cognitive_deficit.rb +71 -0
  25. data/lib/legion/extensions/agentic/self/anosognosia/helpers/constants.rb +29 -0
  26. data/lib/legion/extensions/agentic/self/anosognosia/runners/anosognosia.rb +98 -0
  27. data/lib/legion/extensions/agentic/self/anosognosia/version.rb +13 -0
  28. data/lib/legion/extensions/agentic/self/anosognosia.rb +19 -0
  29. data/lib/legion/extensions/agentic/self/architecture/client.rb +19 -0
  30. data/lib/legion/extensions/agentic/self/architecture/helpers/architecture_engine.rb +167 -0
  31. data/lib/legion/extensions/agentic/self/architecture/helpers/connection.rb +57 -0
  32. data/lib/legion/extensions/agentic/self/architecture/helpers/constants.rb +37 -0
  33. data/lib/legion/extensions/agentic/self/architecture/helpers/subsystem.rb +80 -0
  34. data/lib/legion/extensions/agentic/self/architecture/runners/cognitive_architecture.rb +125 -0
  35. data/lib/legion/extensions/agentic/self/architecture/version.rb +13 -0
  36. data/lib/legion/extensions/agentic/self/architecture.rb +20 -0
  37. data/lib/legion/extensions/agentic/self/default_mode_network/actors/idle.rb +45 -0
  38. data/lib/legion/extensions/agentic/self/default_mode_network/client.rb +28 -0
  39. data/lib/legion/extensions/agentic/self/default_mode_network/helpers/constants.rb +53 -0
  40. data/lib/legion/extensions/agentic/self/default_mode_network/helpers/dmn_engine.rb +221 -0
  41. data/lib/legion/extensions/agentic/self/default_mode_network/helpers/wandering_thought.rb +60 -0
  42. data/lib/legion/extensions/agentic/self/default_mode_network/runners/default_mode_network.rb +122 -0
  43. data/lib/legion/extensions/agentic/self/default_mode_network/version.rb +13 -0
  44. data/lib/legion/extensions/agentic/self/default_mode_network.rb +20 -0
  45. data/lib/legion/extensions/agentic/self/fingerprint/client.rb +28 -0
  46. data/lib/legion/extensions/agentic/self/fingerprint/helpers/cognitive_trait.rb +73 -0
  47. data/lib/legion/extensions/agentic/self/fingerprint/helpers/constants.rb +60 -0
  48. data/lib/legion/extensions/agentic/self/fingerprint/helpers/fingerprint_engine.rb +169 -0
  49. data/lib/legion/extensions/agentic/self/fingerprint/runners/cognitive_fingerprint.rb +86 -0
  50. data/lib/legion/extensions/agentic/self/fingerprint/version.rb +13 -0
  51. data/lib/legion/extensions/agentic/self/fingerprint.rb +19 -0
  52. data/lib/legion/extensions/agentic/self/identity/actors/credential_refresh.rb +49 -0
  53. data/lib/legion/extensions/agentic/self/identity/actors/orphan_check.rb +52 -0
  54. data/lib/legion/extensions/agentic/self/identity/client.rb +27 -0
  55. data/lib/legion/extensions/agentic/self/identity/helpers/dimensions.rb +75 -0
  56. data/lib/legion/extensions/agentic/self/identity/helpers/fingerprint.rb +170 -0
  57. data/lib/legion/extensions/agentic/self/identity/helpers/graph_client.rb +29 -0
  58. data/lib/legion/extensions/agentic/self/identity/helpers/graph_token.rb +36 -0
  59. data/lib/legion/extensions/agentic/self/identity/helpers/token_cache.rb +59 -0
  60. data/lib/legion/extensions/agentic/self/identity/helpers/vault_secrets.rb +80 -0
  61. data/lib/legion/extensions/agentic/self/identity/local_migrations/20260316000030_create_fingerprint.rb +20 -0
  62. data/lib/legion/extensions/agentic/self/identity/runners/entra.rb +402 -0
  63. data/lib/legion/extensions/agentic/self/identity/runners/identity.rb +90 -0
  64. data/lib/legion/extensions/agentic/self/identity/version.rb +13 -0
  65. data/lib/legion/extensions/agentic/self/identity.rb +28 -0
  66. data/lib/legion/extensions/agentic/self/metacognition/client.rb +27 -0
  67. data/lib/legion/extensions/agentic/self/metacognition/helpers/constants.rb +377 -0
  68. data/lib/legion/extensions/agentic/self/metacognition/helpers/narrator_bridge.rb +85 -0
  69. data/lib/legion/extensions/agentic/self/metacognition/helpers/registry_store.rb +70 -0
  70. data/lib/legion/extensions/agentic/self/metacognition/helpers/self_model.rb +160 -0
  71. data/lib/legion/extensions/agentic/self/metacognition/helpers/snapshot_store.rb +82 -0
  72. data/lib/legion/extensions/agentic/self/metacognition/runners/metacognition.rb +116 -0
  73. data/lib/legion/extensions/agentic/self/metacognition/runners/registry.rb +180 -0
  74. data/lib/legion/extensions/agentic/self/metacognition/version.rb +13 -0
  75. data/lib/legion/extensions/agentic/self/metacognition.rb +22 -0
  76. data/lib/legion/extensions/agentic/self/metacognitive_monitoring/client.rb +25 -0
  77. data/lib/legion/extensions/agentic/self/metacognitive_monitoring/helpers/calibration_tracker.rb +96 -0
  78. data/lib/legion/extensions/agentic/self/metacognitive_monitoring/helpers/constants.rb +47 -0
  79. data/lib/legion/extensions/agentic/self/metacognitive_monitoring/helpers/monitoring_engine.rb +141 -0
  80. data/lib/legion/extensions/agentic/self/metacognitive_monitoring/helpers/monitoring_judgment.rb +79 -0
  81. data/lib/legion/extensions/agentic/self/metacognitive_monitoring/runners/metacognitive_monitoring.rb +151 -0
  82. data/lib/legion/extensions/agentic/self/metacognitive_monitoring/version.rb +13 -0
  83. data/lib/legion/extensions/agentic/self/metacognitive_monitoring.rb +20 -0
  84. data/lib/legion/extensions/agentic/self/narrative_arc/client.rb +29 -0
  85. data/lib/legion/extensions/agentic/self/narrative_arc/helpers/arc.rb +137 -0
  86. data/lib/legion/extensions/agentic/self/narrative_arc/helpers/arc_engine.rb +119 -0
  87. data/lib/legion/extensions/agentic/self/narrative_arc/helpers/beat_event.rb +59 -0
  88. data/lib/legion/extensions/agentic/self/narrative_arc/helpers/constants.rb +66 -0
  89. data/lib/legion/extensions/agentic/self/narrative_arc/runners/narrative.rb +101 -0
  90. data/lib/legion/extensions/agentic/self/narrative_arc/version.rb +13 -0
  91. data/lib/legion/extensions/agentic/self/narrative_arc.rb +20 -0
  92. data/lib/legion/extensions/agentic/self/narrative_identity/actors/narrative_decay.rb +45 -0
  93. data/lib/legion/extensions/agentic/self/narrative_identity/client.rb +22 -0
  94. data/lib/legion/extensions/agentic/self/narrative_identity/helpers/chapter.rb +48 -0
  95. data/lib/legion/extensions/agentic/self/narrative_identity/helpers/constants.rb +62 -0
  96. data/lib/legion/extensions/agentic/self/narrative_identity/helpers/episode.rb +67 -0
  97. data/lib/legion/extensions/agentic/self/narrative_identity/helpers/narrative_engine.rb +187 -0
  98. data/lib/legion/extensions/agentic/self/narrative_identity/helpers/theme.rb +50 -0
  99. data/lib/legion/extensions/agentic/self/narrative_identity/runners/narrative_identity.rb +158 -0
  100. data/lib/legion/extensions/agentic/self/narrative_identity/version.rb +13 -0
  101. data/lib/legion/extensions/agentic/self/narrative_identity.rb +21 -0
  102. data/lib/legion/extensions/agentic/self/narrative_self/client.rb +27 -0
  103. data/lib/legion/extensions/agentic/self/narrative_self/helpers/autobiography.rb +187 -0
  104. data/lib/legion/extensions/agentic/self/narrative_self/helpers/constants.rb +42 -0
  105. data/lib/legion/extensions/agentic/self/narrative_self/helpers/episode.rb +81 -0
  106. data/lib/legion/extensions/agentic/self/narrative_self/helpers/narrative_thread.rb +65 -0
  107. data/lib/legion/extensions/agentic/self/narrative_self/runners/narrative_self.rb +86 -0
  108. data/lib/legion/extensions/agentic/self/narrative_self/version.rb +13 -0
  109. data/lib/legion/extensions/agentic/self/narrative_self.rb +20 -0
  110. data/lib/legion/extensions/agentic/self/personality/client.rb +21 -0
  111. data/lib/legion/extensions/agentic/self/personality/helpers/constants.rb +84 -0
  112. data/lib/legion/extensions/agentic/self/personality/helpers/personality_store.rb +126 -0
  113. data/lib/legion/extensions/agentic/self/personality/helpers/trait_model.rb +147 -0
  114. data/lib/legion/extensions/agentic/self/personality/runners/personality.rb +102 -0
  115. data/lib/legion/extensions/agentic/self/personality/version.rb +13 -0
  116. data/lib/legion/extensions/agentic/self/personality.rb +19 -0
  117. data/lib/legion/extensions/agentic/self/reflection/client.rb +27 -0
  118. data/lib/legion/extensions/agentic/self/reflection/helpers/constants.rb +66 -0
  119. data/lib/legion/extensions/agentic/self/reflection/helpers/llm_enhancer.rb +166 -0
  120. data/lib/legion/extensions/agentic/self/reflection/helpers/monitors.rb +186 -0
  121. data/lib/legion/extensions/agentic/self/reflection/helpers/reflection.rb +54 -0
  122. data/lib/legion/extensions/agentic/self/reflection/helpers/reflection_store.rb +99 -0
  123. data/lib/legion/extensions/agentic/self/reflection/runners/reflection.rb +199 -0
  124. data/lib/legion/extensions/agentic/self/reflection/version.rb +13 -0
  125. data/lib/legion/extensions/agentic/self/reflection.rb +21 -0
  126. data/lib/legion/extensions/agentic/self/self_model/client.rb +19 -0
  127. data/lib/legion/extensions/agentic/self/self_model/helpers/capability.rb +93 -0
  128. data/lib/legion/extensions/agentic/self/self_model/helpers/constants.rb +46 -0
  129. data/lib/legion/extensions/agentic/self/self_model/helpers/knowledge_domain.rb +82 -0
  130. data/lib/legion/extensions/agentic/self/self_model/helpers/self_model.rb +150 -0
  131. data/lib/legion/extensions/agentic/self/self_model/runners/self_model.rb +82 -0
  132. data/lib/legion/extensions/agentic/self/self_model/version.rb +13 -0
  133. data/lib/legion/extensions/agentic/self/self_model.rb +21 -0
  134. data/lib/legion/extensions/agentic/self/self_talk/actors/volume_decay.rb +45 -0
  135. data/lib/legion/extensions/agentic/self/self_talk/client.rb +30 -0
  136. data/lib/legion/extensions/agentic/self/self_talk/helpers/constants.rb +63 -0
  137. data/lib/legion/extensions/agentic/self/self_talk/helpers/dialogue.rb +114 -0
  138. data/lib/legion/extensions/agentic/self/self_talk/helpers/dialogue_turn.rb +43 -0
  139. data/lib/legion/extensions/agentic/self/self_talk/helpers/inner_voice.rb +77 -0
  140. data/lib/legion/extensions/agentic/self/self_talk/helpers/llm_enhancer.rb +135 -0
  141. data/lib/legion/extensions/agentic/self/self_talk/helpers/self_talk_engine.rb +160 -0
  142. data/lib/legion/extensions/agentic/self/self_talk/runners/self_talk.rb +172 -0
  143. data/lib/legion/extensions/agentic/self/self_talk/version.rb +13 -0
  144. data/lib/legion/extensions/agentic/self/self_talk.rb +22 -0
  145. data/lib/legion/extensions/agentic/self/version.rb +11 -0
  146. data/lib/legion/extensions/agentic/self.rb +33 -0
  147. data/spec/legion/extensions/agentic/self/agency/client_spec.rb +67 -0
  148. data/spec/legion/extensions/agentic/self/agency/helpers/constants_spec.rb +73 -0
  149. data/spec/legion/extensions/agentic/self/agency/helpers/efficacy_model_spec.rb +190 -0
  150. data/spec/legion/extensions/agentic/self/agency/helpers/outcome_event_spec.rb +85 -0
  151. data/spec/legion/extensions/agentic/self/agency/runners/agency_spec.rb +132 -0
  152. data/spec/legion/extensions/agentic/self/anchor/client_spec.rb +30 -0
  153. data/spec/legion/extensions/agentic/self/anchor/helpers/anchor_engine_spec.rb +109 -0
  154. data/spec/legion/extensions/agentic/self/anchor/helpers/anchor_spec.rb +124 -0
  155. data/spec/legion/extensions/agentic/self/anchor/helpers/chain_spec.rb +106 -0
  156. data/spec/legion/extensions/agentic/self/anchor/helpers/constants_spec.rb +53 -0
  157. data/spec/legion/extensions/agentic/self/anchor/runners/cognitive_anchor_spec.rb +70 -0
  158. data/spec/legion/extensions/agentic/self/anosognosia/anosognosia_spec.rb +15 -0
  159. data/spec/legion/extensions/agentic/self/anosognosia/client_spec.rb +50 -0
  160. data/spec/legion/extensions/agentic/self/anosognosia/helpers/anosognosia_engine_spec.rb +266 -0
  161. data/spec/legion/extensions/agentic/self/anosognosia/helpers/cognitive_deficit_spec.rb +150 -0
  162. data/spec/legion/extensions/agentic/self/anosognosia/helpers/constants_spec.rb +58 -0
  163. data/spec/legion/extensions/agentic/self/anosognosia/runners/anosognosia_spec.rb +225 -0
  164. data/spec/legion/extensions/agentic/self/architecture/client_spec.rb +51 -0
  165. data/spec/legion/extensions/agentic/self/architecture/helpers/architecture_engine_spec.rb +321 -0
  166. data/spec/legion/extensions/agentic/self/architecture/helpers/connection_spec.rb +118 -0
  167. data/spec/legion/extensions/agentic/self/architecture/helpers/subsystem_spec.rb +189 -0
  168. data/spec/legion/extensions/agentic/self/architecture/runners/cognitive_architecture_spec.rb +181 -0
  169. data/spec/legion/extensions/agentic/self/default_mode_network/client_spec.rb +69 -0
  170. data/spec/legion/extensions/agentic/self/default_mode_network/helpers/constants_spec.rb +76 -0
  171. data/spec/legion/extensions/agentic/self/default_mode_network/helpers/dmn_engine_spec.rb +321 -0
  172. data/spec/legion/extensions/agentic/self/default_mode_network/helpers/wandering_thought_spec.rb +145 -0
  173. data/spec/legion/extensions/agentic/self/default_mode_network/runners/default_mode_network_spec.rb +269 -0
  174. data/spec/legion/extensions/agentic/self/fingerprint/client_spec.rb +54 -0
  175. data/spec/legion/extensions/agentic/self/fingerprint/helpers/cognitive_trait_spec.rb +180 -0
  176. data/spec/legion/extensions/agentic/self/fingerprint/helpers/constants_spec.rb +108 -0
  177. data/spec/legion/extensions/agentic/self/fingerprint/helpers/fingerprint_engine_spec.rb +318 -0
  178. data/spec/legion/extensions/agentic/self/fingerprint/runners/cognitive_fingerprint_spec.rb +232 -0
  179. data/spec/legion/extensions/agentic/self/identity/actors/orphan_check_spec.rb +104 -0
  180. data/spec/legion/extensions/agentic/self/identity/client_spec.rb +32 -0
  181. data/spec/legion/extensions/agentic/self/identity/helpers/dimensions_spec.rb +51 -0
  182. data/spec/legion/extensions/agentic/self/identity/helpers/fingerprint_spec.rb +66 -0
  183. data/spec/legion/extensions/agentic/self/identity/helpers/graph_client_spec.rb +19 -0
  184. data/spec/legion/extensions/agentic/self/identity/helpers/graph_token_spec.rb +31 -0
  185. data/spec/legion/extensions/agentic/self/identity/helpers/token_cache_spec.rb +50 -0
  186. data/spec/legion/extensions/agentic/self/identity/local_persistence_spec.rb +329 -0
  187. data/spec/legion/extensions/agentic/self/identity/runners/entra_spec.rb +655 -0
  188. data/spec/legion/extensions/agentic/self/identity/runners/identity_spec.rb +61 -0
  189. data/spec/legion/extensions/agentic/self/metacognition/client_spec.rb +20 -0
  190. data/spec/legion/extensions/agentic/self/metacognition/helpers/constants_spec.rb +31 -0
  191. data/spec/legion/extensions/agentic/self/metacognition/helpers/narrator_bridge_spec.rb +102 -0
  192. data/spec/legion/extensions/agentic/self/metacognition/helpers/registry_store_spec.rb +227 -0
  193. data/spec/legion/extensions/agentic/self/metacognition/helpers/self_model_spec.rb +117 -0
  194. data/spec/legion/extensions/agentic/self/metacognition/helpers/snapshot_store_spec.rb +128 -0
  195. data/spec/legion/extensions/agentic/self/metacognition/runners/metacognition_spec.rb +110 -0
  196. data/spec/legion/extensions/agentic/self/metacognition/runners/registry_spec.rb +281 -0
  197. data/spec/legion/extensions/agentic/self/metacognitive_monitoring/client_spec.rb +59 -0
  198. data/spec/legion/extensions/agentic/self/metacognitive_monitoring/helpers/calibration_tracker_spec.rb +143 -0
  199. data/spec/legion/extensions/agentic/self/metacognitive_monitoring/helpers/constants_spec.rb +91 -0
  200. data/spec/legion/extensions/agentic/self/metacognitive_monitoring/helpers/monitoring_engine_spec.rb +198 -0
  201. data/spec/legion/extensions/agentic/self/metacognitive_monitoring/helpers/monitoring_judgment_spec.rb +172 -0
  202. data/spec/legion/extensions/agentic/self/metacognitive_monitoring/runners/metacognitive_monitoring_spec.rb +244 -0
  203. data/spec/legion/extensions/agentic/self/narrative_arc/client_spec.rb +22 -0
  204. data/spec/legion/extensions/agentic/self/narrative_arc/helpers/arc_engine_spec.rb +183 -0
  205. data/spec/legion/extensions/agentic/self/narrative_arc/helpers/arc_spec.rb +177 -0
  206. data/spec/legion/extensions/agentic/self/narrative_arc/helpers/beat_event_spec.rb +96 -0
  207. data/spec/legion/extensions/agentic/self/narrative_arc/helpers/constants_spec.rb +75 -0
  208. data/spec/legion/extensions/agentic/self/narrative_arc/runners/narrative_spec.rb +142 -0
  209. data/spec/legion/extensions/agentic/self/narrative_identity/client_spec.rb +69 -0
  210. data/spec/legion/extensions/agentic/self/narrative_identity/helpers/chapter_spec.rb +85 -0
  211. data/spec/legion/extensions/agentic/self/narrative_identity/helpers/constants_spec.rb +83 -0
  212. data/spec/legion/extensions/agentic/self/narrative_identity/helpers/episode_spec.rb +180 -0
  213. data/spec/legion/extensions/agentic/self/narrative_identity/helpers/narrative_engine_spec.rb +307 -0
  214. data/spec/legion/extensions/agentic/self/narrative_identity/helpers/theme_spec.rb +107 -0
  215. data/spec/legion/extensions/agentic/self/narrative_identity/runners/narrative_identity_spec.rb +240 -0
  216. data/spec/legion/extensions/agentic/self/narrative_self/client_spec.rb +67 -0
  217. data/spec/legion/extensions/agentic/self/narrative_self/helpers/autobiography_spec.rb +155 -0
  218. data/spec/legion/extensions/agentic/self/narrative_self/helpers/constants_spec.rb +28 -0
  219. data/spec/legion/extensions/agentic/self/narrative_self/helpers/episode_spec.rb +144 -0
  220. data/spec/legion/extensions/agentic/self/narrative_self/helpers/narrative_thread_spec.rb +87 -0
  221. data/spec/legion/extensions/agentic/self/narrative_self/runners/narrative_self_spec.rb +118 -0
  222. data/spec/legion/extensions/agentic/self/personality/client_spec.rb +20 -0
  223. data/spec/legion/extensions/agentic/self/personality/helpers/constants_spec.rb +41 -0
  224. data/spec/legion/extensions/agentic/self/personality/helpers/personality_store_spec.rb +66 -0
  225. data/spec/legion/extensions/agentic/self/personality/helpers/trait_model_spec.rb +148 -0
  226. data/spec/legion/extensions/agentic/self/personality/runners/personality_spec.rb +67 -0
  227. data/spec/legion/extensions/agentic/self/reflection/client_spec.rb +24 -0
  228. data/spec/legion/extensions/agentic/self/reflection/helpers/llm_enhancer_spec.rb +191 -0
  229. data/spec/legion/extensions/agentic/self/reflection/helpers/monitors_spec.rb +120 -0
  230. data/spec/legion/extensions/agentic/self/reflection/helpers/reflection_spec.rb +49 -0
  231. data/spec/legion/extensions/agentic/self/reflection/helpers/reflection_store_spec.rb +93 -0
  232. data/spec/legion/extensions/agentic/self/reflection/runners/reflection_spec.rb +204 -0
  233. data/spec/legion/extensions/agentic/self/self_model/client_spec.rb +55 -0
  234. data/spec/legion/extensions/agentic/self/self_model/helpers/capability_spec.rb +160 -0
  235. data/spec/legion/extensions/agentic/self/self_model/helpers/knowledge_domain_spec.rb +128 -0
  236. data/spec/legion/extensions/agentic/self/self_model/helpers/self_model_spec.rb +238 -0
  237. data/spec/legion/extensions/agentic/self/self_model/runners/self_model_spec.rb +143 -0
  238. data/spec/legion/extensions/agentic/self/self_talk/actors/volume_decay_spec.rb +46 -0
  239. data/spec/legion/extensions/agentic/self/self_talk/client_spec.rb +26 -0
  240. data/spec/legion/extensions/agentic/self/self_talk/helpers/constants_spec.rb +110 -0
  241. data/spec/legion/extensions/agentic/self/self_talk/helpers/dialogue_spec.rb +191 -0
  242. data/spec/legion/extensions/agentic/self/self_talk/helpers/dialogue_turn_spec.rb +78 -0
  243. data/spec/legion/extensions/agentic/self/self_talk/helpers/inner_voice_spec.rb +172 -0
  244. data/spec/legion/extensions/agentic/self/self_talk/helpers/llm_enhancer_spec.rb +206 -0
  245. data/spec/legion/extensions/agentic/self/self_talk/helpers/self_talk_engine_spec.rb +239 -0
  246. data/spec/legion/extensions/agentic/self/self_talk/runners/self_talk_llm_spec.rb +169 -0
  247. data/spec/legion/extensions/agentic/self/self_talk/runners/self_talk_spec.rb +196 -0
  248. data/spec/spec_helper.rb +46 -0
  249. metadata +347 -0
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Self
7
+ module NarrativeIdentity
8
+ module Helpers
9
+ class NarrativeEngine
10
+ attr_reader :episodes, :themes, :chapters
11
+
12
+ def initialize
13
+ @episodes = {}
14
+ @themes = {}
15
+ @chapters = {}
16
+ end
17
+
18
+ def add_episode(content:, episode_type:, emotional_valence:, significance:, domain:)
19
+ prune_episodes! if @episodes.size >= Constants::MAX_EPISODES
20
+ episode = Episode.new(
21
+ content: content,
22
+ episode_type: episode_type,
23
+ emotional_valence: emotional_valence,
24
+ significance: significance,
25
+ domain: domain
26
+ )
27
+ @episodes[episode.id] = episode
28
+ episode
29
+ end
30
+
31
+ def assign_to_chapter(episode_id:, chapter_id:)
32
+ episode = @episodes.fetch(episode_id, nil)
33
+ chapter = @chapters.fetch(chapter_id, nil)
34
+ return false unless episode && chapter
35
+
36
+ episode.chapter_id = chapter_id
37
+ chapter.episode_ids << episode_id unless chapter.episode_ids.include?(episode_id)
38
+ true
39
+ end
40
+
41
+ def create_chapter(title:, label:)
42
+ prune_chapters! if @chapters.size >= Constants::MAX_CHAPTERS
43
+ chapter = Chapter.new(title: title, label: label)
44
+ @chapters[chapter.id] = chapter
45
+ chapter
46
+ end
47
+
48
+ def close_chapter(chapter_id:)
49
+ chapter = @chapters.fetch(chapter_id, nil)
50
+ return false unless chapter
51
+
52
+ chapter.end_time = Time.now.utc
53
+ true
54
+ end
55
+
56
+ def add_theme(name:, theme_type:)
57
+ prune_themes! if @themes.size >= Constants::MAX_THEMES
58
+ theme = Theme.new(name: name, theme_type: theme_type)
59
+ @themes[theme.id] = theme
60
+ theme
61
+ end
62
+
63
+ def link_theme(episode_id:, theme_id:)
64
+ episode = @episodes.fetch(episode_id, nil)
65
+ theme = @themes.fetch(theme_id, nil)
66
+ return false unless episode && theme
67
+
68
+ episode.themes << theme_id unless episode.themes.include?(theme_id)
69
+ theme.episode_ids << episode_id unless theme.episode_ids.include?(episode_id)
70
+ true
71
+ end
72
+
73
+ def reinforce_theme(theme_id:, amount:)
74
+ theme = @themes.fetch(theme_id, nil)
75
+ return false unless theme
76
+
77
+ theme.reinforce!(amount)
78
+ true
79
+ end
80
+
81
+ def narrative_coherence
82
+ return 0.0 if @episodes.empty? || @themes.empty?
83
+
84
+ linked = @episodes.values.count { |ep| ep.themes.any? }
85
+ base = (linked.to_f / @episodes.size).round(10)
86
+ theme_factor = prominent_themes.size.to_f / [@themes.size, 1].max
87
+ ((base * 0.7) + (theme_factor * 0.3)).round(10).clamp(0.0, 1.0)
88
+ end
89
+
90
+ def identity_summary
91
+ {
92
+ top_themes: prominent_themes.first(5).map(&:to_h),
93
+ defining_episodes: most_defining_episodes(limit: 5).map(&:to_h),
94
+ current_chapter: current_chapter&.to_h,
95
+ coherence: narrative_coherence,
96
+ coherence_label: coherence_label,
97
+ episode_count: @episodes.size,
98
+ theme_count: @themes.size,
99
+ chapter_count: @chapters.size
100
+ }
101
+ end
102
+
103
+ def life_story
104
+ @chapters.values.sort_by(&:start_time).map do |chapter|
105
+ eps = chapter.episode_ids.filter_map { |id| @episodes[id] }.sort_by(&:created_at)
106
+ {
107
+ chapter: chapter.to_h,
108
+ episodes: eps.map { |ep| ep.to_h.merge(theme_names: theme_names_for(ep)) }
109
+ }
110
+ end
111
+ end
112
+
113
+ def most_defining_episodes(limit: 5)
114
+ @episodes.values.sort_by { |ep| -ep.significance }.first(limit)
115
+ end
116
+
117
+ def prominent_themes
118
+ @themes.values.select(&:prominent?).sort_by { |t| -t.strength }
119
+ end
120
+
121
+ def current_chapter
122
+ @chapters.values.find(&:current?)
123
+ end
124
+
125
+ def decay_all_themes!
126
+ @themes.each_value(&:decay!)
127
+ end
128
+
129
+ def narrative_report
130
+ {
131
+ identity_summary: identity_summary,
132
+ life_story: life_story,
133
+ narrative_state: {
134
+ coherence: narrative_coherence,
135
+ coherence_label: coherence_label,
136
+ prominent_themes: prominent_themes.map(&:to_h),
137
+ defining_episodes: most_defining_episodes(limit: 3).map(&:to_h),
138
+ current_chapter: current_chapter&.to_h
139
+ }
140
+ }
141
+ end
142
+
143
+ def to_h
144
+ {
145
+ episodes: @episodes.transform_values(&:to_h),
146
+ themes: @themes.transform_values(&:to_h),
147
+ chapters: @chapters.transform_values(&:to_h)
148
+ }
149
+ end
150
+
151
+ private
152
+
153
+ def coherence_label
154
+ score = narrative_coherence
155
+ Constants::COHERENCE_LABELS.each do |entry|
156
+ range, label = entry.first
157
+ return label if range.cover?(score)
158
+ end
159
+ :absent
160
+ end
161
+
162
+ def theme_names_for(episode)
163
+ episode.themes.filter_map { |tid| @themes[tid]&.name }
164
+ end
165
+
166
+ def prune_episodes!
167
+ oldest = @episodes.values.min_by(&:created_at)
168
+ @episodes.delete(oldest.id) if oldest
169
+ end
170
+
171
+ def prune_themes!
172
+ weakest = @themes.values.min_by(&:strength)
173
+ @themes.delete(weakest.id) if weakest
174
+ end
175
+
176
+ def prune_chapters!
177
+ closed = @chapters.values.reject(&:current?).min_by(&:start_time)
178
+ target = closed || @chapters.values.min_by(&:start_time)
179
+ @chapters.delete(target.id) if target
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Self
9
+ module NarrativeIdentity
10
+ module Helpers
11
+ class Theme
12
+ attr_reader :id, :name, :theme_type, :episode_ids
13
+ attr_accessor :strength
14
+
15
+ def initialize(name:, theme_type:, strength: 0.0, episode_ids: nil, id: nil)
16
+ @id = id || SecureRandom.uuid
17
+ @name = name
18
+ @theme_type = theme_type
19
+ @strength = strength.clamp(0.0, 1.0)
20
+ @episode_ids = episode_ids || []
21
+ end
22
+
23
+ def reinforce!(amount)
24
+ @strength = (@strength + amount).clamp(0.0, 1.0).round(10)
25
+ end
26
+
27
+ def decay!
28
+ @strength = (@strength - Constants::COHERENCE_DECAY).clamp(0.0, 1.0).round(10)
29
+ end
30
+
31
+ def prominent?
32
+ @strength >= 0.6
33
+ end
34
+
35
+ def to_h
36
+ {
37
+ id: @id,
38
+ name: @name,
39
+ theme_type: @theme_type,
40
+ strength: @strength,
41
+ episode_ids: @episode_ids.dup
42
+ }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Self
7
+ module NarrativeIdentity
8
+ module Runners
9
+ module NarrativeIdentity
10
+ extend self
11
+
12
+ def record_episode(content:, episode_type:, emotional_valence:, significance:, domain:,
13
+ engine: nil, **)
14
+ return { success: false, error: "unknown episode_type: #{episode_type.inspect}" } unless
15
+ Helpers::Constants::EPISODE_TYPES.include?(episode_type)
16
+
17
+ episode = resolve_engine(engine).add_episode(
18
+ content: content, episode_type: episode_type,
19
+ emotional_valence: emotional_valence, significance: significance, domain: domain
20
+ )
21
+ Legion::Logging.debug "[narrative_identity] recorded episode #{episode.id[0..7]} type=#{episode_type}"
22
+ { success: true, episode: episode.to_h }
23
+ rescue StandardError => e
24
+ { success: false, error: e.message }
25
+ end
26
+
27
+ def assign_episode_to_chapter(episode_id:, chapter_id:, engine: nil, **)
28
+ result = resolve_engine(engine).assign_to_chapter(episode_id: episode_id, chapter_id: chapter_id)
29
+ Legion::Logging.debug "[narrative_identity] assign episode=#{episode_id[0..7]} ok=#{result}"
30
+ { success: result, episode_id: episode_id, chapter_id: chapter_id }
31
+ rescue StandardError => e
32
+ { success: false, error: e.message }
33
+ end
34
+
35
+ def create_chapter(title:, label:, engine: nil, **)
36
+ return { success: false, error: "unknown chapter label: #{label.inspect}" } unless
37
+ Helpers::Constants::CHAPTER_LABELS.include?(label)
38
+
39
+ chapter = resolve_engine(engine).create_chapter(title: title, label: label)
40
+ Legion::Logging.debug "[narrative_identity] created chapter #{chapter.id[0..7]} label=#{label}"
41
+ { success: true, chapter: chapter.to_h }
42
+ rescue StandardError => e
43
+ { success: false, error: e.message }
44
+ end
45
+
46
+ def close_chapter(chapter_id:, engine: nil, **)
47
+ result = resolve_engine(engine).close_chapter(chapter_id: chapter_id)
48
+ Legion::Logging.debug "[narrative_identity] close_chapter #{chapter_id[0..7]} ok=#{result}"
49
+ { success: result, chapter_id: chapter_id }
50
+ rescue StandardError => e
51
+ { success: false, error: e.message }
52
+ end
53
+
54
+ def add_theme(name:, theme_type:, engine: nil, **)
55
+ return { success: false, error: "unknown theme_type: #{theme_type.inspect}" } unless
56
+ Helpers::Constants::THEME_TYPES.include?(theme_type)
57
+
58
+ theme = resolve_engine(engine).add_theme(name: name, theme_type: theme_type)
59
+ Legion::Logging.debug "[narrative_identity] added theme #{theme.id[0..7]} type=#{theme_type}"
60
+ { success: true, theme: theme.to_h }
61
+ rescue StandardError => e
62
+ { success: false, error: e.message }
63
+ end
64
+
65
+ def link_theme(episode_id:, theme_id:, engine: nil, **)
66
+ result = resolve_engine(engine).link_theme(episode_id: episode_id, theme_id: theme_id)
67
+ Legion::Logging.debug "[narrative_identity] link theme=#{theme_id[0..7]} episode=#{episode_id[0..7]} ok=#{result}"
68
+ { success: result, episode_id: episode_id, theme_id: theme_id }
69
+ rescue StandardError => e
70
+ { success: false, error: e.message }
71
+ end
72
+
73
+ def reinforce_theme(theme_id:, amount:, engine: nil, **)
74
+ result = resolve_engine(engine).reinforce_theme(theme_id: theme_id, amount: amount)
75
+ Legion::Logging.debug "[narrative_identity] reinforce theme=#{theme_id[0..7]} amount=#{amount} ok=#{result}"
76
+ { success: result, theme_id: theme_id, amount: amount }
77
+ rescue StandardError => e
78
+ { success: false, error: e.message }
79
+ end
80
+
81
+ def narrative_coherence(engine: nil, **)
82
+ score = resolve_engine(engine).narrative_coherence
83
+ Legion::Logging.debug "[narrative_identity] coherence=#{score}"
84
+ { success: true, coherence: score }
85
+ rescue StandardError => e
86
+ { success: false, error: e.message }
87
+ end
88
+
89
+ def identity_summary(engine: nil, **)
90
+ summary = resolve_engine(engine).identity_summary
91
+ Legion::Logging.debug '[narrative_identity] identity_summary requested'
92
+ { success: true, summary: summary }
93
+ rescue StandardError => e
94
+ { success: false, error: e.message }
95
+ end
96
+
97
+ def life_story(engine: nil, **)
98
+ story = resolve_engine(engine).life_story
99
+ Legion::Logging.debug "[narrative_identity] life_story chapters=#{story.size}"
100
+ { success: true, life_story: story }
101
+ rescue StandardError => e
102
+ { success: false, error: e.message }
103
+ end
104
+
105
+ def most_defining_episodes(limit: 5, engine: nil, **)
106
+ episodes = resolve_engine(engine).most_defining_episodes(limit: limit)
107
+ Legion::Logging.debug "[narrative_identity] defining_episodes count=#{episodes.size}"
108
+ { success: true, episodes: episodes.map(&:to_h) }
109
+ rescue StandardError => e
110
+ { success: false, error: e.message }
111
+ end
112
+
113
+ def prominent_themes(engine: nil, **)
114
+ themes = resolve_engine(engine).prominent_themes
115
+ Legion::Logging.debug "[narrative_identity] prominent_themes count=#{themes.size}"
116
+ { success: true, themes: themes.map(&:to_h) }
117
+ rescue StandardError => e
118
+ { success: false, error: e.message }
119
+ end
120
+
121
+ def current_chapter(engine: nil, **)
122
+ chapter = resolve_engine(engine).current_chapter
123
+ Legion::Logging.debug "[narrative_identity] current_chapter=#{chapter&.id&.slice(0..7)}"
124
+ { success: true, chapter: chapter&.to_h }
125
+ rescue StandardError => e
126
+ { success: false, error: e.message }
127
+ end
128
+
129
+ def decay_themes(engine: nil, **)
130
+ resolve_engine(engine).decay_all_themes!
131
+ Legion::Logging.debug '[narrative_identity] theme decay applied'
132
+ { success: true }
133
+ rescue StandardError => e
134
+ { success: false, error: e.message }
135
+ end
136
+
137
+ def narrative_report(engine: nil, **)
138
+ report = resolve_engine(engine).narrative_report
139
+ Legion::Logging.debug '[narrative_identity] narrative_report generated'
140
+ { success: true, report: report }
141
+ rescue StandardError => e
142
+ { success: false, error: e.message }
143
+ end
144
+
145
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
146
+
147
+ private
148
+
149
+ def resolve_engine(engine)
150
+ engine || (@default_engine ||= Helpers::NarrativeEngine.new)
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Self
7
+ module NarrativeIdentity
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/self/narrative_identity/version'
4
+ require 'legion/extensions/agentic/self/narrative_identity/helpers/constants'
5
+ require 'legion/extensions/agentic/self/narrative_identity/helpers/episode'
6
+ require 'legion/extensions/agentic/self/narrative_identity/helpers/theme'
7
+ require 'legion/extensions/agentic/self/narrative_identity/helpers/chapter'
8
+ require 'legion/extensions/agentic/self/narrative_identity/helpers/narrative_engine'
9
+ require 'legion/extensions/agentic/self/narrative_identity/runners/narrative_identity'
10
+ require 'legion/extensions/agentic/self/narrative_identity/client'
11
+
12
+ module Legion
13
+ module Extensions
14
+ module Agentic
15
+ module Self
16
+ module NarrativeIdentity
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/self/narrative_self/helpers/constants'
4
+ require 'legion/extensions/agentic/self/narrative_self/helpers/episode'
5
+ require 'legion/extensions/agentic/self/narrative_self/helpers/narrative_thread'
6
+ require 'legion/extensions/agentic/self/narrative_self/helpers/autobiography'
7
+ require 'legion/extensions/agentic/self/narrative_self/runners/narrative_self'
8
+
9
+ module Legion
10
+ module Extensions
11
+ module Agentic
12
+ module Self
13
+ module NarrativeSelf
14
+ class Client
15
+ include Runners::NarrativeSelf
16
+
17
+ attr_reader :autobiography
18
+
19
+ def initialize(autobiography: nil, **)
20
+ @autobiography = autobiography || Helpers::Autobiography.new
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Self
7
+ module NarrativeSelf
8
+ module Helpers
9
+ class Autobiography
10
+ include Constants
11
+
12
+ attr_reader :episodes, :threads, :self_concept
13
+
14
+ def initialize
15
+ @episodes = []
16
+ @threads = []
17
+ @self_concept = {}
18
+ end
19
+
20
+ def record_episode(description:, episode_type: :insight, domain: :general,
21
+ significance: nil, emotional_valence: 0.0, tags: [])
22
+ episode = Episode.new(
23
+ description: description,
24
+ episode_type: episode_type,
25
+ domain: domain,
26
+ significance: significance,
27
+ emotional_valence: emotional_valence,
28
+ tags: tags
29
+ )
30
+ @episodes << episode
31
+ auto_link_threads(episode)
32
+ update_self_concept(episode)
33
+ trim_episodes
34
+ episode
35
+ end
36
+
37
+ def find_episode(id)
38
+ @episodes.find { |e| e.id == id }
39
+ end
40
+
41
+ def recent_episodes(count = 10)
42
+ @episodes.last(count)
43
+ end
44
+
45
+ def significant_episodes(min_significance: 0.6)
46
+ @episodes.select { |e| e.significance >= min_significance }
47
+ .sort_by { |e| -e.significance }
48
+ end
49
+
50
+ def episodes_by_type(episode_type)
51
+ @episodes.select { |e| e.episode_type == episode_type }
52
+ end
53
+
54
+ def episodes_in_domain(domain)
55
+ @episodes.select { |e| e.domain == domain }
56
+ end
57
+
58
+ def create_thread(theme:, domain: :general)
59
+ thread = NarrativeThread.new(theme: theme, domain: domain)
60
+ @threads << thread
61
+ trim_threads
62
+ thread
63
+ end
64
+
65
+ def find_thread(id)
66
+ @threads.find { |t| t.id == id }
67
+ end
68
+
69
+ def find_threads_by_theme(theme)
70
+ @threads.select { |t| t.theme == theme }
71
+ end
72
+
73
+ def strongest_threads(count = 5)
74
+ @threads.sort_by { |t| -t.strength }.first(count)
75
+ end
76
+
77
+ def timeline(window: MAX_TIMELINE_WINDOW)
78
+ @episodes.last(window).map(&:to_h)
79
+ end
80
+
81
+ def self_summary
82
+ top_types = episode_type_distribution.first(3).map(&:first)
83
+ top_domains = domain_distribution.first(3).map(&:first)
84
+ top_threads = strongest_threads(3).map(&:theme)
85
+ {
86
+ total_episodes: @episodes.size,
87
+ dominant_types: top_types,
88
+ dominant_domains: top_domains,
89
+ active_threads: top_threads,
90
+ self_concept: @self_concept.dup,
91
+ pivotal_count: @episodes.count { |e| e.label == :pivotal },
92
+ narrative_richness: narrative_richness
93
+ }
94
+ end
95
+
96
+ def decay_all
97
+ @episodes.each(&:decay)
98
+ @episodes.reject!(&:faded?)
99
+ @threads.each(&:decay)
100
+ @threads.reject!(&:weak?)
101
+ end
102
+
103
+ def to_h
104
+ {
105
+ episode_count: @episodes.size,
106
+ thread_count: @threads.size,
107
+ self_concept: @self_concept.dup,
108
+ by_type: @episodes.group_by(&:episode_type).transform_values(&:size),
109
+ by_domain: @episodes.group_by(&:domain).transform_values(&:size),
110
+ avg_significance: avg_significance
111
+ }
112
+ end
113
+
114
+ private
115
+
116
+ def auto_link_threads(episode)
117
+ @threads.each do |thread|
118
+ relevance = episode.matches_tags?([thread.theme])
119
+ relevance += 0.2 if episode.domain == thread.domain
120
+ next unless relevance >= THREAD_MATCH_THRESHOLD
121
+
122
+ thread.add_episode(episode.id)
123
+ episode.link_thread(thread.id)
124
+ end
125
+ end
126
+
127
+ def update_self_concept(episode)
128
+ trait = episode.episode_type
129
+ current = @self_concept.fetch(trait, 0.0)
130
+ signal = episode.significance
131
+ @self_concept[trait] = ((TRAIT_ALPHA * signal) + ((1.0 - TRAIT_ALPHA) * current)).clamp(0.0, 1.0)
132
+ trim_self_concept
133
+ end
134
+
135
+ def trim_self_concept
136
+ return unless @self_concept.size > MAX_SELF_CONCEPT_TRAITS
137
+
138
+ sorted = @self_concept.sort_by { |_, v| v }
139
+ @self_concept = sorted.last(MAX_SELF_CONCEPT_TRAITS).to_h
140
+ end
141
+
142
+ def trim_episodes
143
+ return unless @episodes.size > MAX_EPISODES
144
+
145
+ @episodes.sort_by!(&:significance)
146
+ @episodes.shift(@episodes.size - MAX_EPISODES)
147
+ end
148
+
149
+ def trim_threads
150
+ return unless @threads.size > MAX_THREADS
151
+
152
+ @threads.sort_by!(&:strength)
153
+ @threads.shift(@threads.size - MAX_THREADS)
154
+ end
155
+
156
+ def episode_type_distribution
157
+ @episodes.group_by(&:episode_type)
158
+ .transform_values(&:size)
159
+ .sort_by { |_, count| -count }
160
+ end
161
+
162
+ def domain_distribution
163
+ @episodes.group_by(&:domain)
164
+ .transform_values(&:size)
165
+ .sort_by { |_, count| -count }
166
+ end
167
+
168
+ def avg_significance
169
+ return 0.0 if @episodes.empty?
170
+
171
+ @episodes.sum(&:significance) / @episodes.size
172
+ end
173
+
174
+ def narrative_richness
175
+ return 0.0 if @episodes.empty?
176
+
177
+ type_diversity = @episodes.map(&:episode_type).uniq.size.to_f / EPISODE_TYPES.size
178
+ thread_activity = @threads.empty? ? 0.0 : @threads.count { |t| t.size > 1 }.to_f / @threads.size
179
+ ((type_diversity + thread_activity) / 2.0).clamp(0.0, 1.0)
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Self
7
+ module NarrativeSelf
8
+ module Helpers
9
+ module Constants
10
+ MAX_EPISODES = 500
11
+ MAX_THREADS = 50
12
+ MAX_CHAPTER_SIZE = 20
13
+ EPISODE_DECAY = 0.005
14
+ THREAD_DECAY = 0.01
15
+ SIGNIFICANCE_FLOOR = 0.05
16
+ SIGNIFICANCE_ALPHA = 0.15
17
+ DEFAULT_SIGNIFICANCE = 0.5
18
+ EMOTIONAL_BOOST = 0.3
19
+ THREAD_MATCH_THRESHOLD = 0.3
20
+ MAX_SELF_CONCEPT_TRAITS = 30
21
+ TRAIT_ALPHA = 0.1
22
+ MAX_TIMELINE_WINDOW = 100
23
+
24
+ SIGNIFICANCE_LABELS = {
25
+ (0.8..) => :pivotal,
26
+ (0.6...0.8) => :important,
27
+ (0.3...0.6) => :routine,
28
+ (..0.3) => :minor
29
+ }.freeze
30
+
31
+ EPISODE_TYPES = %i[
32
+ achievement failure discovery connection
33
+ conflict resolution insight surprise
34
+ decision transition reflection
35
+ ].freeze
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end