ruvector_crv/lib.rs
1//! # ruvector-crv
2//!
3//! CRV (Coordinate Remote Viewing) protocol integration for ruvector.
4//!
5//! Maps the 6-stage CRV signal line methodology to ruvector's subsystems:
6//!
7//! | CRV Stage | Data Type | ruvector Component |
8//! |-----------|-----------|-------------------|
9//! | Stage I (Ideograms) | Gestalt primitives | Poincaré ball hyperbolic embeddings |
10//! | Stage II (Sensory) | Textures, colors, temps | Multi-head attention vectors |
11//! | Stage III (Dimensional) | Spatial sketches | GNN graph topology |
12//! | Stage IV (Emotional) | AOL, intangibles | SNN temporal encoding |
13//! | Stage V (Interrogation) | Signal line probing | Differentiable search |
14//! | Stage VI (3D Model) | Composite model | MinCut partitioning |
15//!
16//! ## Quick Start
17//!
18//! ```rust,no_run
19//! use ruvector_crv::{CrvConfig, CrvSessionManager, GestaltType, StageIData};
20//!
21//! // Create session manager with default config (384 dimensions)
22//! let config = CrvConfig::default();
23//! let mut manager = CrvSessionManager::new(config);
24//!
25//! // Create a session for a target coordinate
26//! manager.create_session("session-001".to_string(), "1234-5678".to_string()).unwrap();
27//!
28//! // Add Stage I ideogram data
29//! let stage_i = StageIData {
30//! stroke: vec![(0.0, 0.0), (1.0, 0.5), (2.0, 1.0), (3.0, 0.5)],
31//! spontaneous_descriptor: "angular rising".to_string(),
32//! classification: GestaltType::Manmade,
33//! confidence: 0.85,
34//! };
35//!
36//! let embedding = manager.add_stage_i("session-001", &stage_i).unwrap();
37//! assert_eq!(embedding.len(), 384);
38//! ```
39//!
40//! ## Architecture
41//!
42//! The Poincaré ball embedding for Stage I gestalts encodes the hierarchical
43//! gestalt taxonomy (root → manmade/natural/movement/energy/water/land) with
44//! exponentially less distortion than Euclidean space.
45//!
46//! For AOL (Analytical Overlay) separation, the spiking neural network temporal
47//! encoding models signal-vs-noise discrimination: high-frequency spike bursts
48//! correlate with AOL contamination, while sustained low-frequency patterns
49//! indicate clean signal line data.
50//!
51//! MinCut partitioning in Stage VI identifies natural cluster boundaries in the
52//! accumulated session graph, separating distinct target aspects.
53//!
54//! ## Cross-Session Convergence
55//!
56//! Multiple sessions targeting the same coordinate can be analyzed for
57//! convergence — agreement between independent viewers strengthens the
58//! signal validity:
59//!
60//! ```rust,no_run
61//! # use ruvector_crv::{CrvConfig, CrvSessionManager};
62//! # let mut manager = CrvSessionManager::new(CrvConfig::default());
63//! // After adding data to multiple sessions for "1234-5678"...
64//! let convergence = manager.find_convergence("1234-5678", 0.75).unwrap();
65//! // convergence.scores contains similarity values for converging entries
66//! ```
67
68pub mod error;
69pub mod session;
70pub mod stage_i;
71pub mod stage_ii;
72pub mod stage_iii;
73pub mod stage_iv;
74pub mod stage_v;
75pub mod stage_vi;
76pub mod types;
77
78// Re-export main types
79pub use error::{CrvError, CrvResult};
80pub use session::CrvSessionManager;
81pub use stage_i::StageIEncoder;
82pub use stage_ii::StageIIEncoder;
83pub use stage_iii::StageIIIEncoder;
84pub use stage_iv::StageIVEncoder;
85pub use stage_v::StageVEngine;
86pub use stage_vi::StageVIModeler;
87pub use types::{
88 AOLDetection, ConvergenceResult, CrossReference, CrvConfig, CrvSessionEntry,
89 GeometricKind, GestaltType, SensoryModality, SignalLineProbe, SketchElement,
90 SpatialRelationType, SpatialRelationship, StageIData, StageIIData, StageIIIData,
91 StageIVData, StageVData, StageVIData, TargetPartition,
92};
93
94/// Library version.
95pub const VERSION: &str = env!("CARGO_PKG_VERSION");
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_version() {
103 assert!(!VERSION.is_empty());
104 }
105
106 #[test]
107 fn test_end_to_end_session() {
108 let config = CrvConfig {
109 dimensions: 32,
110 ..CrvConfig::default()
111 };
112 let mut manager = CrvSessionManager::new(config);
113
114 // Create two sessions for the same coordinate
115 manager
116 .create_session("viewer-a".to_string(), "target-001".to_string())
117 .unwrap();
118 manager
119 .create_session("viewer-b".to_string(), "target-001".to_string())
120 .unwrap();
121
122 // Viewer A: Stage I
123 let s1_a = StageIData {
124 stroke: vec![(0.0, 0.0), (1.0, 1.0), (2.0, 0.5), (3.0, 0.0)],
125 spontaneous_descriptor: "tall angular".to_string(),
126 classification: GestaltType::Manmade,
127 confidence: 0.85,
128 };
129 manager.add_stage_i("viewer-a", &s1_a).unwrap();
130
131 // Viewer B: Stage I (similar gestalt)
132 let s1_b = StageIData {
133 stroke: vec![(0.0, 0.0), (0.5, 1.2), (1.5, 0.8), (2.5, 0.0)],
134 spontaneous_descriptor: "structured upward".to_string(),
135 classification: GestaltType::Manmade,
136 confidence: 0.78,
137 };
138 manager.add_stage_i("viewer-b", &s1_b).unwrap();
139
140 // Viewer A: Stage II
141 let s2_a = StageIIData {
142 impressions: vec![
143 (SensoryModality::Texture, "rough stone".to_string()),
144 (SensoryModality::Temperature, "cool".to_string()),
145 (SensoryModality::Color, "gray".to_string()),
146 ],
147 feature_vector: None,
148 };
149 manager.add_stage_ii("viewer-a", &s2_a).unwrap();
150
151 // Viewer B: Stage II (overlapping sensory)
152 let s2_b = StageIIData {
153 impressions: vec![
154 (SensoryModality::Texture, "grainy rough".to_string()),
155 (SensoryModality::Color, "dark gray".to_string()),
156 (SensoryModality::Luminosity, "dim".to_string()),
157 ],
158 feature_vector: None,
159 };
160 manager.add_stage_ii("viewer-b", &s2_b).unwrap();
161
162 // Verify entries
163 assert_eq!(manager.session_entry_count("viewer-a"), 2);
164 assert_eq!(manager.session_entry_count("viewer-b"), 2);
165
166 // Both sessions should have embeddings
167 let entries_a = manager.get_session_embeddings("viewer-a").unwrap();
168 let entries_b = manager.get_session_embeddings("viewer-b").unwrap();
169
170 assert_eq!(entries_a.len(), 2);
171 assert_eq!(entries_b.len(), 2);
172
173 // All embeddings should be 32-dimensional
174 for entry in entries_a.iter().chain(entries_b.iter()) {
175 assert_eq!(entry.embedding.len(), 32);
176 }
177 }
178}