diff --git a/AdaWorldAPI-lance-graph-d9df43b/.bumpversion.toml b/AdaWorldAPI-lance-graph-d9df43b/.bumpversion.toml deleted file mode 100644 index cb853b21..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.bumpversion.toml +++ /dev/null @@ -1,50 +0,0 @@ -[tool.bumpversion] -current_version = "0.5.3" -parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)(-(?Palpha|beta|rc)\\.(?P\\d+))?" -serialize = [ - "{major}.{minor}.{patch}-{pre_label}.{pre_n}", - "{major}.{minor}.{patch}" -] -search = "{current_version}" -replace = "{new_version}" -regex = false -ignore_missing_files = false -ignore_missing_version = false -tag = false -sign_tags = false -tag_name = "v{new_version}" -tag_message = "Release version {new_version}" -allow_dirty = false -commit = false -message = "chore: bump version {current_version} → {new_version}" - -[tool.bumpversion.parts.pre_label] -optional_value = "stable" -first_value = "stable" -values = ["stable", "alpha", "beta", "rc"] - -[tool.bumpversion.parts.pre_n] -optional_value = "0" -first_value = "0" - -# Rust Cargo.toml files -[[tool.bumpversion.files]] -filename = "crates/lance-graph/Cargo.toml" -search = 'version = "{current_version}"' -replace = 'version = "{new_version}"' - -[[tool.bumpversion.files]] -filename = "crates/lance-graph-catalog/Cargo.toml" -search = 'version = "{current_version}"' -replace = 'version = "{new_version}"' - -[[tool.bumpversion.files]] -filename = "crates/lance-graph-python/Cargo.toml" -search = 'version = "{current_version}"' -replace = 'version = "{new_version}"' - -# Python pyproject.toml -[[tool.bumpversion.files]] -filename = "python/pyproject.toml" -search = 'version = "{current_version}"' -replace = 'version = "{new_version}"' diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/BELICHTUNGSMESSER.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/BELICHTUNGSMESSER.md deleted file mode 100644 index 50369f08..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/BELICHTUNGSMESSER.md +++ /dev/null @@ -1,637 +0,0 @@ -# BELICHTUNGSMESSER.md - -## HDR Popcount-Stacking Early-Exit Distance Cascade - -### What this is and why it matters - -A standard nearest-neighbor search compares a query against every candidate at full resolution. For 16,384-bit binary vectors, that's 256 popcount operations per comparison. Against 1 million candidates: 256 million popcount ops per query. - -The Belichtungsmesser (German: exposure meter, like in a camera) eliminates 97%+ of candidates using a FRACTION of the bits, so only ~0.5% of candidates ever get a full comparison. Same results. 100x less work. - -The name comes from photography: before taking the photo (full comparison), the camera's exposure meter takes a quick light reading (sampled comparison) to decide if there's enough signal to bother. - ---- - -### The statistics you need to understand - -Two random 16,384-bit vectors have a Hamming distance that follows a binomial distribution: - -``` -Each bit: 50% chance of matching (like a coin flip) -Total bits: 16,384 -Expected distance: μ = 16384 / 2 = 8192 (half the bits differ) -Standard deviation: σ = sqrt(16384 / 4) = 64 -``` - -This means for RANDOM (unrelated) pairs: - -``` -~68.3% of random pairs have distance between 8128 and 8256 (μ ± 1σ) -~95.4% of random pairs have distance between 8064 and 8320 (μ ± 2σ) -~99.7% of random pairs have distance between 8000 and 8384 (μ ± 3σ) -``` - -A REAL MATCH has a distance MUCH LOWER than 8192. The further BELOW μ, the more certain it's a real relationship, not random chance: - -``` -DISTANCE SIGMA BELOW μ PROBABILITY OF RANDOM PAIR BEING THIS CLOSE -────────────────────────────────────────────────────────────────────────── -8192 μ (expected) 50% — pure coin flip. No signal. -8128 μ - 1σ 15.9% of random pairs this close. Weak signal. -8064 μ - 2σ 2.3% of random pairs this close. Likely real. -8000 μ - 3σ 0.13% of random pairs this close. Almost certainly real. -7936 μ - 4σ 0.003% — extremely rare for random pair. Strong match. -7500 μ - 10.8σ Effectively zero chance of random. Near-identical content. -``` - -KEY INSIGHT: The search finds vectors with distance far BELOW μ. -Everything NEAR or ABOVE μ is noise. Reject it without full comparison. - ---- - -### The cascade: progressive refinement - -Instead of computing all 16,384 bits, sample a fraction first. - -A sampled distance SCALES linearly. If you sample 1/16 of the bits and get distance 480, the projected full distance is approximately 480 × 16 = 7,680. The variance of the projection is higher (fewer samples = more noise), but the MEAN is correct. So the sample gives a noisy but unbiased estimate. - -``` -STAGE 1: Sample 1/16 of bits (1,024 bits = 16 u64 words = 1 AVX-512 op) - Cost: ~2 CPU cycles per candidate. - Sample σ = 64 / sqrt(16) = 16 - Project: sample_distance × 16 = estimated_full_distance - Reject if projected distance > μ - 1σ (above noise floor) - ELIMINATES: ~84% of random candidates. Cost: trivial. - -STAGE 2: Sample 1/4 of bits (4,096 bits = 64 u64 words = 8 AVX-512 ops) - Cost: ~8 CPU cycles per surviving candidate. - Sample σ = 64 / sqrt(4) = 32 (tighter estimate than stage 1) - Project: sample_distance × 4 = estimated_full_distance - Reject if projected distance > μ - 2σ (likely noise) - ELIMINATES: ~90% of stage 1 survivors. - -STAGE 3: Full comparison (16,384 bits = 256 u64 words = 32 AVX-512 ops) - Cost: ~32 CPU cycles per surviving candidate. - Exact distance. No projection error. - Classify into sigma bands for ranking. - ONLY ~0.5% of original candidates reach this stage. -``` - -Total work per query against 1 million candidates: - -``` -WITHOUT CASCADE: - 1,000,000 × 32 cycles = 32,000,000 cycles ≈ 10ms at 3GHz - -WITH CASCADE: - Stage 1: 1,000,000 × 2 cycles = 2,000,000 cycles (all candidates) - Stage 2: 160,000 × 8 cycles = 1,280,000 cycles (16% survived stage 1) - Stage 3: 16,000 × 32 cycles = 512,000 cycles (1.6% survived stage 2) - TOTAL: 3,792,000 cycles ≈ 1.3ms - - SPEEDUP: ~8.4x with ZERO loss of accuracy on final results. - The cascade only prunes candidates that would have been rejected anyway. -``` - ---- - -### The sigma bands: integer top-k without float sort - -After the cascade, surviving candidates are classified by how far below μ their distance falls. This classification replaces float-based ranking: - -```rust -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum Band { - /// distance < μ - 3σ. Less than 0.13% chance of random. Near-certain match. - Foveal, - /// distance < μ - 2σ. Less than 2.3% chance of random. Strong match. - Near, - /// distance < μ - 1σ. Less than 15.9% chance of random. Good candidate. - Good, - /// distance < μ. Could be random. Weak signal. - Weak, - /// distance ≥ μ. Noise or anti-correlated. Not a match. - Reject, -} -``` - -Top-k is: take from Foveal bucket first, then Near, then Good. -Within each bucket: sort by `u32` Hamming distance (integer sort). -No float. No NaN. No "similarity score 0.873f32". Just sigma bands. - ---- - -### Self-calibrating thresholds - -The values μ=8192 and σ=64 are for RANDOM 16K vectors. Real corpora have different distributions because entities share context. After encoding Wikidata, the actual μ might be 7800 with σ=80. Hardcoded thresholds would be wrong. - -The Belichtungsmesser calibrates itself from a sample of actual pairwise distances on startup. And it detects when the distribution shifts (e.g., after a large import) and recalibrates: - -```rust -/// Self-calibrating exposure meter for Hamming distance queries. -/// All thresholds derived from actual data distribution. Integer arithmetic. -pub struct Belichtungsmesser { - /// Mean pairwise Hamming distance in this corpus. - mu: u32, - /// Standard deviation of pairwise distances. - sigma: u32, - /// Precomputed band thresholds. Integer. Looked up, not computed per query. - /// bands[0] = μ - 3σ (Foveal cutoff) - /// bands[1] = μ - 2σ (Near cutoff) - /// bands[2] = μ - σ (Good cutoff) - /// bands[3] = μ (Weak cutoff, everything above = Reject) - bands: [u32; 4], - /// Welford running stats for shift detection. - running_count: u64, - running_mean: u64, // scaled by running_count for integer arithmetic - running_m2: u64, // sum of squared deviations (Welford) -} - -impl Belichtungsmesser { - /// Calibrate from a sample of actual pairwise distances. - /// Call once on startup with ~1000 random pair distances from the corpus. - pub fn calibrate(sample_distances: &[u32]) -> Self { - let n = sample_distances.len() as u64; - assert!(n > 1, "Need at least 2 samples to calibrate"); - - let sum: u64 = sample_distances.iter().map(|&d| d as u64).sum(); - let mu = (sum / n) as u32; - - let var_sum: u64 = sample_distances.iter() - .map(|&d| { - let diff = d as i64 - mu as i64; - (diff * diff) as u64 - }) - .sum(); - let sigma = isqrt((var_sum / n) as u32); - - // Ensure sigma > 0 to prevent zero-width bands - let sigma = sigma.max(1); - - let bands = [ - mu.saturating_sub(3 * sigma), // Foveal: < μ - 3σ - mu.saturating_sub(2 * sigma), // Near: < μ - 2σ - mu.saturating_sub(sigma), // Good: < μ - 1σ - mu, // Weak: < μ (everything above = Reject) - ]; - - Self { - mu, - sigma, - bands, - running_count: n, - running_mean: sum, - running_m2: var_sum, - } - } - - /// Classify a Hamming distance into a sigma band. - /// Pure integer comparison. No float. Constant time. - #[inline] - pub fn band(&self, distance: u32) -> Band { - if distance < self.bands[0] { Band::Foveal } - else if distance < self.bands[1] { Band::Near } - else if distance < self.bands[2] { Band::Good } - else if distance < self.bands[3] { Band::Weak } - else { Band::Reject } - } - - /// HDR cascade query. Progressive elimination with sampled early exit. - /// - /// Returns results bucketed by sigma band. Foveal first, then Near, then Good. - /// Within each band: sorted by u32 distance. No float anywhere. - /// - /// `top_k`: maximum results to return. - /// `candidates`: the corpus to search. Each entry provides byte-level access - /// to its bits for sampled and full comparison. - pub fn query_hdr( - &self, - query: &[u8], // query vector as bytes (2048 bytes for 16K) - candidates: &[T], - top_k: usize, - ) -> Vec { - let query_len = query.len(); - - // Buckets: one per band worth collecting - let mut foveal: Vec<(usize, u32)> = Vec::new(); - let mut near: Vec<(usize, u32)> = Vec::new(); - let mut good: Vec<(usize, u32)> = Vec::new(); - - // Stage 1 sample size: 1/16 of total bytes - let s1_len = query_len / 16; - // Stage 2 sample size: 1/4 of total bytes - let s2_len = query_len / 4; - - // The SIMD hamming function. Resolved ONCE. Used millions of times. - let hamming = crate::simd::select_hamming_fn(); - - for (idx, candidate) in candidates.iter().enumerate() { - let cbytes = candidate.as_bytes(); - - // ── STAGE 1: 1/16 sample ────────────────────────────────── - // Compare first 1/16 of bytes. Cost: ~2 cycles. - let s1_dist = hamming(&query[..s1_len], &cbytes[..s1_len]); - let s1_projected = (s1_dist as u32) * 16; // project to full width - - // Reject if projected distance is above the Good threshold (μ - σ). - // This eliminates candidates that are almost certainly in the noise. - if s1_projected > self.bands[2] { - continue; // ~84%+ eliminated here - } - - // ── STAGE 2: 1/4 sample ─────────────────────────────────── - // Compare first 1/4 of bytes. Cost: ~8 cycles. - let s2_dist = hamming(&query[..s2_len], &cbytes[..s2_len]); - let s2_projected = (s2_dist as u32) * 4; - - // Tighter filter: reject above Near threshold (μ - 2σ). - if s2_projected > self.bands[1] { - continue; // another ~80% of survivors eliminated - } - - // ── STAGE 3: full comparison ────────────────────────────── - // Compare all bytes. Cost: ~32 cycles. But only ~0.5% reach here. - let full_dist = hamming(query, cbytes) as u32; - - match self.band(full_dist) { - Band::Foveal => foveal.push((idx, full_dist)), - Band::Near => near.push((idx, full_dist)), - Band::Good => good.push((idx, full_dist)), - _ => {} // Weak or Reject — don't collect - } - - // Early termination: foveal bucket full - if foveal.len() >= top_k { - break; - } - } - - // Assemble top-k from buckets. Best band first. Integer sort within. - let mut results = Vec::with_capacity(top_k); - - foveal.sort_unstable_by_key(|&(_, d)| d); - for &(idx, dist) in foveal.iter().take(top_k) { - results.push(RankedHit { index: idx, distance: dist, band: Band::Foveal }); - } - - if results.len() < top_k { - near.sort_unstable_by_key(|&(_, d)| d); - for &(idx, dist) in near.iter().take(top_k - results.len()) { - results.push(RankedHit { index: idx, distance: dist, band: Band::Near }); - } - } - - if results.len() < top_k { - good.sort_unstable_by_key(|&(_, d)| d); - for &(idx, dist) in good.iter().take(top_k - results.len()) { - results.push(RankedHit { index: idx, distance: dist, band: Band::Good }); - } - } - - results - } - - /// Feed an observed distance into the running statistics. - /// Call after each query with the distances of actual results. - /// Returns ShiftAlert if the data distribution has changed significantly. - /// - /// Uses Welford's online algorithm. Integer arithmetic. - pub fn observe(&mut self, distance: u32) -> Option { - let d = distance as u64; - self.running_count += 1; - - // Welford's online mean and M2 update - let delta = d as i64 - (self.running_mean / self.running_count.max(1)) as i64; - self.running_mean += d; - let new_mean = self.running_mean / self.running_count; - let delta2 = d as i64 - new_mean as i64; - self.running_m2 = self.running_m2.wrapping_add((delta.wrapping_mul(delta2)) as u64); - - // Check every 1000 observations - if self.running_count % 1000 == 0 && self.running_count > 1000 { - let running_mu = (self.running_mean / self.running_count) as u32; - let running_var = (self.running_m2 / self.running_count) as u32; - let running_sigma = isqrt(running_var).max(1); - - // Shift detection: running stats diverge from calibrated stats - let mu_drift = running_mu.abs_diff(self.mu); - let sigma_drift = running_sigma.abs_diff(self.sigma); - - if mu_drift > self.sigma / 2 || sigma_drift > self.sigma / 4 { - return Some(ShiftAlert { - old_mu: self.mu, - new_mu: running_mu, - old_sigma: self.sigma, - new_sigma: running_sigma, - observations: self.running_count as u32, - }); - } - } - - None - } - - /// Recalibrate thresholds from a shift alert. - pub fn recalibrate(&mut self, alert: &ShiftAlert) { - self.mu = alert.new_mu; - self.sigma = alert.new_sigma.max(1); - self.bands = [ - self.mu.saturating_sub(3 * self.sigma), - self.mu.saturating_sub(2 * self.sigma), - self.mu.saturating_sub(self.sigma), - self.mu, - ]; - } -} - -pub struct RankedHit { - /// Index of the matched candidate in the input slice. - pub index: usize, - /// Exact Hamming distance (from stage 3 full comparison). - pub distance: u32, - /// Sigma band classification. - pub band: Band, -} - -pub struct ShiftAlert { - pub old_mu: u32, - pub new_mu: u32, - pub old_sigma: u32, - pub new_sigma: u32, - pub observations: u32, -} - -/// Trait for types that expose their raw bytes for SIMD comparison. -pub trait AsBytes { - fn as_bytes(&self) -> &[u8]; -} - -/// Integer square root. No float in the hot path. -/// Uses Newton's method with integer arithmetic. -fn isqrt(n: u32) -> u32 { - if n == 0 { return 0; } - // Initial guess: bit-shift approximation - let mut x = 1u32 << ((32 - n.leading_zeros()) / 2); - loop { - let x1 = (x + n / x) / 2; - if x1 >= x { return x; } - x = x1; - } -} -``` - ---- - -### Tests - -```rust -#[cfg(test)] -mod tests { - use super::*; - - fn random_bytes(n: usize, seed: u64) -> Vec { - let mut state = seed; - (0..n).map(|_| { - state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407); - (state >> 33) as u8 - }).collect() - } - - #[test] - fn calibration_from_random_data() { - // Random 16K vectors should have μ ≈ 8192, σ ≈ 64 - let hamming = crate::simd::select_hamming_fn(); - let vecs: Vec> = (0..100).map(|i| random_bytes(2048, i)).collect(); - let mut dists = Vec::new(); - for i in 0..100 { - for j in (i+1)..100 { - dists.push(hamming(&vecs[i], &vecs[j]) as u32); - } - } - - let meter = Belichtungsmesser::calibrate(&dists); - - // μ should be near 8192 (±200 for sample variance) - assert!(meter.mu > 7900 && meter.mu < 8500, - "Expected μ near 8192, got {}", meter.mu); - // σ should be near 64 (±30) - assert!(meter.sigma > 30 && meter.sigma < 100, - "Expected σ near 64, got {}", meter.sigma); - // Band ordering must be strictly ascending - assert!(meter.bands[0] < meter.bands[1]); - assert!(meter.bands[1] < meter.bands[2]); - assert!(meter.bands[2] < meter.bands[3]); - } - - #[test] - fn band_classification_correct_direction() { - let meter = Belichtungsmesser { - mu: 8192, - sigma: 64, - bands: [8192 - 192, 8192 - 128, 8192 - 64, 8192], - running_count: 1000, - running_mean: 8192000, - running_m2: 64 * 64 * 1000, - }; - - // Very low distance = very similar = Foveal (best) - assert_eq!(meter.band(7900), Band::Foveal); - // Low distance = strong match = Near - assert_eq!(meter.band(8010), Band::Near); - // Below mean = good candidate - assert_eq!(meter.band(8100), Band::Good); - // Near mean = weak signal - assert_eq!(meter.band(8170), Band::Weak); - // Above mean = noise = Reject - assert_eq!(meter.band(8200), Band::Reject); - assert_eq!(meter.band(9000), Band::Reject); - } - - #[test] - fn cascade_eliminates_most_candidates() { - let hamming = crate::simd::select_hamming_fn(); - - // Create 10,000 random vectors + 10 vectors similar to query - let query = random_bytes(2048, 0); - let mut corpus: Vec> = (1..10_001).map(|i| random_bytes(2048, i)).collect(); - - // Make 10 similar vectors by copying query and flipping few bits - for i in 0..10 { - let mut similar = query.clone(); - for j in 0..20 { // flip ~20 bytes → ~80 bits → distance ≈ 80 (far below μ) - similar[j + i * 20] ^= 0xFF; - } - corpus.push(similar); - } - - // Calibrate from random pairs - let mut sample_dists = Vec::new(); - for i in 0..100 { - for j in (i+1)..100 { - sample_dists.push(hamming(&corpus[i], &corpus[j]) as u32); - } - } - let meter = Belichtungsmesser::calibrate(&sample_dists); - - // Query: find top 10 - let results = meter.query_hdr(&query, &corpus, 10); - - // Should find the 10 similar vectors - assert!(results.len() >= 5, - "Should find at least 5 of 10 similar vectors, got {}", results.len()); - - // All results should be in good bands (Foveal, Near, or Good) - for hit in &results { - assert!(hit.band <= Band::Good, - "Result with distance {} classified as {:?}, expected Good or better", - hit.distance, hit.band); - } - - // The similar vectors should have much lower distance than μ - for hit in &results { - assert!(hit.distance < meter.mu, - "Result distance {} should be below μ={}", hit.distance, meter.mu); - } - } - - #[test] - fn cascade_work_savings() { - // Measure how much work the cascade actually saves - let query = random_bytes(2048, 0); - let corpus: Vec> = (1..10_001).map(|i| random_bytes(2048, i)).collect(); - - let hamming = crate::simd::select_hamming_fn(); - let mut sample_dists = Vec::new(); - for i in 0..100 { - for j in (i+1)..100 { - sample_dists.push(hamming(&corpus[i], &corpus[j]) as u32); - } - } - let meter = Belichtungsmesser::calibrate(&sample_dists); - - // Count how many candidates survive each stage - let s1_len = 2048 / 16; // 128 bytes - let s2_len = 2048 / 4; // 512 bytes - let mut s1_pass = 0u32; - let mut s2_pass = 0u32; - let mut s3_pass = 0u32; - let total = corpus.len() as u32; - - for candidate in &corpus { - let s1 = hamming(&query[..s1_len], &candidate[..s1_len]) as u32 * 16; - if s1 > meter.bands[2] { continue; } - s1_pass += 1; - - let s2 = hamming(&query[..s2_len], &candidate[..s2_len]) as u32 * 4; - if s2 > meter.bands[1] { continue; } - s2_pass += 1; - - let full = hamming(&query, &candidate) as u32; - if meter.band(full) <= Band::Good { - s3_pass += 1; - } - } - - let s1_reject_pct = 100.0 * (1.0 - s1_pass as f64 / total as f64); - let s2_reject_pct = 100.0 * (1.0 - s2_pass as f64 / s1_pass.max(1) as f64); - - // Against random data: stage 1 should reject >80% - println!("Stage 1: {}/{} pass ({:.1}% rejected)", s1_pass, total, s1_reject_pct); - println!("Stage 2: {}/{} pass ({:.1}% rejected of survivors)", s2_pass, s1_pass, s2_reject_pct); - println!("Stage 3: {} final results", s3_pass); - - assert!(s1_reject_pct > 70.0, - "Stage 1 should reject >70% of random candidates, got {:.1}%", s1_reject_pct); - - // Effective work compared to brute force - let brute_cycles = total as f64 * 32.0; // 32 cycles per full comparison - let cascade_cycles = total as f64 * 2.0 // stage 1: all candidates, 2 cycles - + s1_pass as f64 * 8.0 // stage 2: survivors, 8 cycles - + s2_pass as f64 * 32.0; // stage 3: survivors, 32 cycles - let savings = 100.0 * (1.0 - cascade_cycles / brute_cycles); - - println!("Brute force: {:.0} cycles", brute_cycles); - println!("Cascade: {:.0} cycles", cascade_cycles); - println!("Savings: {:.1}%", savings); - - assert!(savings > 50.0, - "Cascade should save >50% work vs brute force, got {:.1}%", savings); - } - - #[test] - fn shift_detection_triggers_on_distribution_change() { - let mut meter = Belichtungsmesser { - mu: 8192, - sigma: 64, - bands: [8192 - 192, 8192 - 128, 8192 - 64, 8192], - running_count: 1000, - running_mean: 8_192_000, - running_m2: 64 * 64 * 1000, - }; - - // Feed distances from a SHIFTED distribution (μ=7500 instead of 8192) - let mut alert_fired = false; - for i in 0..5000 { - let fake_dist = 7500 + (i % 100); // mean ~7550, far from 8192 - if let Some(alert) = meter.observe(fake_dist) { - assert!(alert.new_mu < alert.old_mu, - "Shift should detect lower mean"); - meter.recalibrate(&alert); - alert_fired = true; - break; - } - } - - assert!(alert_fired, "Shift alert should fire when μ changes by >0.5σ"); - assert!(meter.mu < 8000, "After recalibration, μ should reflect new distribution"); - } - - #[test] - fn no_float_in_query_path() { - // This test is a documentation test: it verifies that the query path - // doesn't use f32/f64 by examining the return types. - let meter = Belichtungsmesser::calibrate(&[8000, 8100, 8200, 8300, 8400]); - - // band() returns enum, not float - let b: Band = meter.band(8050); - assert!(matches!(b, Band::Near)); - - // RankedHit.distance is u32, not f32 - let hit = RankedHit { index: 0, distance: 8050, band: Band::Near }; - let _d: u32 = hit.distance; // compiles only if u32 - - // No .score, .similarity, or .confidence fields that would be float - } - - #[test] - fn isqrt_correctness() { - assert_eq!(isqrt(0), 0); - assert_eq!(isqrt(1), 1); - assert_eq!(isqrt(4), 2); - assert_eq!(isqrt(9), 3); - assert_eq!(isqrt(4096), 64); // σ² for 16K random vectors - assert_eq!(isqrt(4095), 63); // floor - assert_eq!(isqrt(u32::MAX), 65535); - } -} -``` - ---- - -### Where this goes - -``` -In rustynum-core: - src/belichtungsmesser.rs (~350 lines: struct, calibrate, band, query_hdr, observe) - Uses: crate::simd::select_hamming_fn() for all distance computation. - No external deps beyond blake3 (if needed for hashing) and std. - -In lance-graph (upstream contribution): - Copy the same code into graph/spo/belichtungsmesser.rs - WITHOUT rustynum dependency. Replace select_hamming_fn() with - the inline SIMD dispatch from BlasGraph types.rs. - -In ladybug-rs: - Uses rustynum-core::Belichtungsmesser directly. - Integrated into Plane.distance() for alpha-aware cascade. -``` diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/BF16_SEMIRING_EPIPHANIES.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/BF16_SEMIRING_EPIPHANIES.md deleted file mode 100644 index b6e2bc96..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/BF16_SEMIRING_EPIPHANIES.md +++ /dev/null @@ -1,429 +0,0 @@ -# BF16_SEMIRING_EPIPHANIES.md - -## Actionable Epiphanies: BF16 + Semirings + Binary Planes - -**Origin:** Deep research report, March 15, 2026. Cross-referencing 60+ sources. -**Status:** Architecture decisions. Each epiphany has an implementation action. - ---- - -## EPIPHANY 1: The 5:2 Split Validates Our Binary Architecture - -Of BlasGraph's 7 semirings, 5 are IRREDUCIBLY BITWISE: - -``` -BITWISE (cannot benefit from BF16 float): FLOAT-AMENABLE (can use VDPBF16PS): - XorBundle → VPXORD, VPTERNLOGD SimilarityMax → VDPBF16PS + VPMAXPS - BindFirst → VPSHUFB, VPERMD Resonance → VDPBF16PS - HammingMin → VPXORD + VPOPCNTDQ + VPMINSD - Boolean → VPORD + VPANDD - XorField → VPXORD + VPCLMULQDQ -``` - -**What this means:** The 16K-bit binary planes are NOT a compression trick. -They ARE the optimal representation for 71% of our graph operations. -No amount of BF16 cleverness helps XOR, AND, OR, popcount, Hamming. -The binary architecture was right from the start. - -**Action:** Stop trying to unify all semirings under one numeric type. -Maintain DUAL pipelines: integer for 5 semirings, BF16 for 2. -The Isa trait already supports this — add semiring-specific dispatch. - -```rust -// In blasgraph semiring dispatch: -match semiring { - XorBundle | BindFirst | HammingMin | Boolean | XorField => { - // Integer pipeline: VPXORD + VPOPCNTDQ + VPCLMULQDQ - simd::mxv_bitwise(matrix, vector, semiring) - } - SimilarityMax | Resonance => { - // Float pipeline: VDPBF16PS + VPMAXPS - simd::mxv_bf16(matrix, vector, semiring) - } -} -``` - ---- - -## EPIPHANY 2: BF16 is a Logarithmic Similarity CACHE, Not a Compute Format - -BF16's logarithmic quantization of Hamming distances is perfect: - -``` -DISTANCE RANGE BF16 PRECISION INFORMATION LOSS -0-255 EXACT (every integer) ZERO in the match zone -256-511 ±2 negligible -512-1023 ±4 acceptable -8192-16384 ±64 irrelevant (noise territory) -``` - -**What this means:** BF16 naturally concentrates precision WHERE IT MATTERS -(near-matches) and discards precision where it doesn't (far-away pairs). -This is EXACTLY what the HDR cascade does with sigma bands — but BF16 -does it for FREE via IEEE 754's logarithmic representation. - -**Action:** Add a BF16 similarity cache to the Cascade: - -```rust -impl Cascade { - /// After computing exact Hamming distance, cache as BF16. - /// The cache serves as a pre-filter for future queries: - /// scan 32 BF16 values per SIMD instruction to find candidates - /// worth the full 16K-bit Hamming recomputation. - pub fn cache_distance(&mut self, pair_id: u32, distance: u32) { - // VCVTNEPS2BF16: hardware-rounded f32 → BF16 - let bf16 = BF16::from_f32(distance as f32); - self.cache[pair_id as usize] = bf16; - } - - /// Pre-filter: scan BF16 cache for candidates below threshold. - /// 32 BF16 comparisons per AVX-512 instruction. - /// Returns candidate indices worth full recomputation. - pub fn prefilter_bf16(&self, threshold: BF16) -> Vec { - // VCMPPS on promoted BF16 values, or direct u16 compare - // (BF16 bit patterns preserve ordering for positive values) - } -} -``` - ---- - -## EPIPHANY 3: Exponent Extraction MUST Be Integer, Never Float - -**CRITICAL:** If BF16 exponent encodes structural fingerprint (2³ SPO projections), -NEVER pass it through float arithmetic. Float multiplication ADDS exponents: - -``` -BF16 value A: exponent = 0b01000010 (means: S and _PO match) -BF16 value B: exponent = 0b00100001 (means: _P_ matches) - -A × B in float: exponent = A.exp + B.exp = meaningless structural code -A × B we want: exponent = A.exp AND B.exp = which projections BOTH match -``` - -Float arithmetic DESTROYS the structural encoding. Integer bit extraction preserves it. - -**Action:** Every operation on the structural exponent uses integer SIMD: - -```rust -/// Extract 8-bit exponent from BF16 value. Integer shift, not float. -#[inline(always)] -fn exponent(bf16: u16) -> u8 { - ((bf16 >> 7) & 0xFF) as u8 // VPSRLW #7 on packed BF16 -} - -/// Structural intersection: which projections match in BOTH truths? -#[inline(always)] -fn structural_and(a: u16, b: u16) -> u8 { - exponent(a) & exponent(b) // VPAND on extracted exponents -} - -/// Structural union: which projections match in EITHER truth? -#[inline(always)] -fn structural_or(a: u16, b: u16) -> u8 { - exponent(a) | exponent(b) // VPOR on extracted exponents -} - -/// Structural disagreement: which projections differ? -#[inline(always)] -fn structural_xor(a: u16, b: u16) -> u8 { - exponent(a) ^ exponent(b) // VPXOR on extracted exponents -} -``` - -This gives us GRAPH OPERATIONS on structural truth values using -the same XOR/AND/OR instructions as the binary plane semirings. -The BF16 exponent IS a miniature binary plane (8 bits instead of 16K). - ---- - -## EPIPHANY 4: HammingMin IS a Tropical Semiring - -Zhang, Naitzat & Lim (ICML 2018) proved ReLU networks are tropical rational maps. -Our HammingMin semiring (⊕=min, ⊗=hamming_distance) is a tropical computation: - -``` -TROPICAL: C[i,j] = min_k (A[i,k] + B[k,j]) shortest path -HAMMINGMIN: C[i,j] = min_k (hamming(A[i,k], B[k,j])) nearest in Hamming - -The structure is identical. HammingMin IS tropical pathfinding in Hamming space. -``` - -**What this means:** Every algorithm that works on the tropical semiring -(shortest paths, critical path, Bellman-Ford, Floyd-Warshall) has a -DIRECT analog in our Hamming space. We can do graph pathfinding -without converting to float — the min+hamming operations are integer. - -**Action:** Implement tropical graph algorithms on binary SPO planes: - -```rust -/// All-pairs nearest neighbors in Hamming space. -/// Tropical closure: D* = I ⊕ D ⊕ D² ⊕ ... ⊕ Dⁿ⁻¹ -/// where ⊕ = element-wise min, ⊗ = hamming distance -/// -/// After convergence: D*[i,j] = length of shortest Hamming path from i to j. -/// This is the SPO knowledge graph's "relatedness" metric: -/// "how many hops through Hamming-similar nodes to get from A to B?" -pub fn tropical_closure(adjacency: &SpoMatrix) -> SpoMatrix { - let n = adjacency.rows(); - let mut dist = adjacency.clone(); - - // Floyd-Warshall in HammingMin semiring - for k in 0..n { - for i in 0..n { - for j in 0..n { - let through_k = simd::hamming_distance( - &dist.row(i).planes(), &dist.row(k).planes() - ) + simd::hamming_distance( - &dist.row(k).planes(), &dist.row(j).planes() - ); - dist.set(i, j, dist.get(i, j).min(through_k)); - } - } - } - dist -} -``` - ---- - -## EPIPHANY 5: We Sidestep the GNN Determinism Problem Entirely - -PyTorch GNNs are NON-DETERMINISTIC because `scatter_add_` on CUDA uses -non-deterministic `atomicAdd`. Setting `torch.use_deterministic_algorithms(True)` -RAISES ERRORS for scatter_add on CUDA (as of PyTorch 2.10). - -A 2025 study found >90% of parallel BF16 computations diverge from serial results -due to non-associative float addition. - -**Our architecture has ZERO of these problems:** - -``` -PYTORCH GNN: OUR ARCHITECTURE: -scatter_add (non-deterministic) → encounter() on integer accumulator (deterministic) -float gradient (non-associative) → sign flip on integer threshold (deterministic) -atomicAdd on GPU (race condition) → sequential plane update (no races) -BF16 reduction (>90% diverge) → integer popcount (always exact) -``` - -**What this means:** We are the ONLY graph neural network architecture -that produces deterministic results. Not by constraining execution order. -By not using float arithmetic in the RL loop AT ALL. - -**Action:** This is already the design in DETERMINISTIC_F32_SPO_BNN.md. -Emphasize in documentation: "Unlike PyTorch Geometric, DGL, or any -GPU-based GNN framework, this system produces bit-identical results -across runs, across hardware, across operating systems." - ---- - -## EPIPHANY 6: BF16 Cache as Hot-Cold Bridge - -The hot path (SIMD Hamming cascade) and cold path (Cypher-like queries) -connect through BF16 edge weights: - -``` -HOT PATH (real-time, SIMD): - Binary SPO planes → VPXORD + VPOPCNTDQ → integer Hamming distance - → band classify → reject 99.7% → survivors get BF16 cache entry - - Cost: ~12μs for 1M candidates. - Produces: integer distances + BF16 cached similarities. - -COLD PATH (declarative, query optimizer): - BF16 edge weights → VCMPPS scan → candidate pairs above threshold - → full Hamming recomputation on candidates only - → NARS truth revision on confirmed matches - - Cost: ~1ms for scan + ~100μs for recomputation. - Produces: revised truth values. - -THE BRIDGE: - Hot path WRITES BF16 cache entries (VCVTNEPS2BF16). - Cold path READS BF16 cache entries (VCMPPS). - - Hot path runs continuously (streaming observations). - Cold path runs on demand (query evaluation). - - BF16 is the LANGUAGE they share. - 16 bits per edge. 32 values compared per SIMD instruction. -``` - -**Action:** The Cascade gets a BF16 edge weight cache. The SPO query -evaluator reads from it. Cypher-like patterns become: - -``` -// Declarative query: -MATCH (a)-[r:KNOWS {similarity > 0.8}]->(b) -WHERE a.type = "Person" AND b.type = "Company" - -// Translates to: -1. Scan BF16 cache for edges with bf16_value > BF16::from_f32(0.8) - (32 comparisons per SIMD instruction, ~500ns for 10K edges) -2. For survivors: check a.type and b.type in the S and O planes - (binary AND with type mask, ~140ns per pair) -3. For confirmed matches: full Hamming recomputation for exact score - (only the final ~10 pairs, ~1.4μs total) -``` - ---- - -## EPIPHANY 7: VPCLMULQDQ for XorField Semiring - -The XorField semiring (GF(2) polynomial arithmetic) maps to VPCLMULQDQ — -carry-less multiplication, available in 512-bit form on Ice Lake/Zen 4+. - -``` -STANDARD MULTIPLY: a × b with carries (integer ALU) -CARRY-LESS MULTIPLY: a × b WITHOUT carries (XOR instead of ADD at each step) - = polynomial multiplication in GF(2)[x] -``` - -This is what XorField's ⊗ operation IS. The hardware instruction does it -in one cycle per 64-bit pair (8 pairs per 512-bit instruction). - -**What this means:** XorField semiring matrix-vector multiply becomes: -``` -for each row: VPCLMULQDQ(row_word, vector_word) → XOR accumulate -``` - -This is dramatically faster than scalar GF(2) polynomial multiplication -which requires bit-by-bit processing. - -**Action:** Implement XorField ⊗ using VPCLMULQDQ: - -```rust -#[cfg(target_arch = "x86_64")] -#[target_feature(enable = "vpclmulqdq,avx512f")] -unsafe fn xor_field_multiply(a: &[u8; 2048], b: &[u8; 2048]) -> [u8; 2048] { - // VPCLMULQDQ: carry-less multiply of 64-bit pairs - // 8 parallel multiplications per 512-bit instruction - // Result: GF(2) polynomial product, accumulated via XOR -} -``` - ---- - -## EPIPHANY 8: NARS Truth Values Pack into 32 bits as BF16 Pair - -NARS truth ⟨frequency, confidence⟩ where f,c ∈ [0,1]: -- In range [0.5, 1.0], BF16 provides 128 distinct values (~0.4% resolution) -- Two packed BF16 values (f, c) = 32 bits = one f32 slot - -``` -TRUTH VALUE LAYOUT: - bits 31-16: BF16 frequency (7-bit mantissa in [0,1]) - bits 15-0: BF16 confidence (7-bit mantissa in [0,1)) - - Total: 32 bits per edge truth value. - Fits in one f32 slot. Comparable with VDPBF16PS. -``` - -**Action:** Define the truth value type: - -```rust -/// NARS truth value packed as two BF16 values in 32 bits. -/// frequency: BF16 in bits 31-16 (how often the relationship holds) -/// confidence: BF16 in bits 15-0 (how much evidence we have) -#[repr(C)] -#[derive(Clone, Copy)] -pub struct NarsTruth(u32); - -impl NarsTruth { - pub fn new(frequency: f32, confidence: f32) -> Self { - let f_bf16 = BF16::from_f32(frequency).to_bits(); - let c_bf16 = BF16::from_f32(confidence).to_bits(); - Self(((f_bf16 as u32) << 16) | (c_bf16 as u32)) - } - - pub fn frequency(&self) -> f32 { BF16::from_bits((self.0 >> 16) as u16).to_f32() } - pub fn confidence(&self) -> f32 { BF16::from_bits(self.0 as u16).to_f32() } - - /// NARS revision: combine two independent evidence sources. - /// f_new = (f1*c1*(1-c2) + f2*c2*(1-c1)) / (c1*(1-c2) + c2*(1-c1)) - /// c_new = (c1*(1-c2) + c2*(1-c1)) / (c1*(1-c2) + c2*(1-c1) + (1-c1)*(1-c2)) - /// - /// This CAN use VDPBF16PS for the multiply-accumulate terms. - pub fn revise(self, other: Self) -> Self { ... } -} -``` - ---- - -## EPIPHANY 9: Dual Pipeline on Same Die - -Sapphire Rapids / Zen 4+ have BOTH VPOPCNTDQ AND AVX-512_BF16 on the same die. -They execute on DIFFERENT execution ports. They can run CONCURRENTLY. - -``` -PORT 0 (integer): VPXORD → VPOPCNTDQ → VPMINSD (Hamming cascade) -PORT 1 (float): VDPBF16PS → VPMAXPS (BF16 similarity) - -CONCURRENT: - While port 0 computes Hamming for the NEXT candidate, - port 1 computes BF16 similarity for the PREVIOUS survivor. - - Same clock cycle. Same core. Different data. - The binary and float paths don't compete for resources. -``` - -**Action:** Interleave Hamming and BF16 operations in the cascade: - -```rust -fn cascade_dual_pipeline(query: &Node, candidates: &[Node], cache: &[BF16]) { - for i in 0..candidates.len() { - // PORT 0: Hamming distance for candidate i (integer pipeline) - let hamming = simd::hamming_distance(query.s.bits(), candidates[i].s.bits()); - - // PORT 1 (concurrent): BF16 similarity for previous survivor - // This executes on a different port, overlapping with the Hamming above - if i > 0 && survived[i-1] { - let sim = simd::bf16_dot(cache_a, cache_b); // VDPBF16PS - update_truth(i-1, sim); - } - } -} -``` - ---- - -## EPIPHANY 10: The SIMD² Future — Semiring-Configurable Hardware - -Zhang et al. (ISCA 2022) proposed SIMD²: configurable ⊗ALU and ⊕ALU units -supporting tropical, bottleneck, Boolean, XOR-popcount, and fuzzy semirings. -5% chip area overhead. 38.59× peak speedup over optimized CUDA. - -**What this means:** Future processors may natively support our semiring -operations as HARDWARE INSTRUCTIONS. Our BlasGraph semiring abstraction -is forward-compatible with this hardware evolution. - -**Action:** Keep the semiring abstraction generic. Don't bake assumptions -about instruction sets into the semiring interface. When SIMD² hardware -arrives, the dispatch layer (simd.rs) adds a new tier: - -```rust -enum Tier { Simd2, Avx512, Avx2, Scalar } - -// SIMD² tier: native semiring hardware -// No decomposition into separate ⊕ and ⊗ instructions needed. -// One instruction does the full semiring mxv. -``` - ---- - -## SUMMARY: THE ARCHITECTURE DECISIONS - -``` -DECISION REASON -────────────────────────────────────────────────────────────────── -Binary planes stay binary 5 of 7 semirings are irreducibly bitwise -BF16 is a CACHE, not compute format Logarithmic quantization matches needs -Exponent extraction is INTEGER only Float arithmetic destroys structural encoding -HammingMin = tropical pathfinding Proven equivalent by Zhang et al. 2018 -Determinism by construction No float in RL loop, no scatter_add races -Dual pipeline (integer + BF16) Concurrent execution on different ports -NARS truth as BF16 pair (32 bits) Fits f32 slot, VDPBF16PS for revision -XorField uses VPCLMULQDQ GF(2) polynomial multiply, 8 per cycle -Hot↔cold bridge via BF16 edge cache Cascade writes, query evaluator reads -Forward-compatible with SIMD² hardware Semiring abstraction stays generic -``` diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/DEEP_ADJACENT_EXPLORATION.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/DEEP_ADJACENT_EXPLORATION.md deleted file mode 100644 index 62d43cd8..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/DEEP_ADJACENT_EXPLORATION.md +++ /dev/null @@ -1,639 +0,0 @@ -# DEEP_ADJACENT_EXPLORATION.md - -## Dropped Algorithms, RISC Design, and Adjacent Genius - -Everything the research surfaced that wasn't about semirings or BF16 but -connects to our architecture in ways I didn't follow. - ---- - -## 1. RDF-3X "RISC-STYLE" ENGINE: The Design We Should Steal Wholesale - -Neumann & Weikum (VLDB 2008, 482 citations) built a triple store that -outperforms alternatives by 1-2 ORDERS OF MAGNITUDE. Their key insight -has NOTHING to do with fancy data structures. It's architectural minimalism: - -``` -RDF-3X RISC PRINCIPLES: - 1. ONE physical design for ALL workloads (no tuning knobs) - 2. EXHAUSTIVE indexes (all 6 SPO permutations + 3 binary + 3 unary = 15 indexes) - 3. ONE query operator: merge join (no hash joins, no nested loops) - 4. Compression everywhere (triples sorted lexicographically, delta-coded) - 5. Dictionary encoding (all literals → integer IDs) - - TOTAL: 15 compressed indexes + merge join + dictionary. That's the whole system. - No configuration. No tuning. No knobs. RISC. -``` - -**Why this is us:** - -``` -OUR EQUIVALENT: - 1. ONE physical design: Plane = i8[16384] accumulator. Period. - 2. EXHAUSTIVE: 7 Mask projections (all SPO combinations). Always available. - 3. ONE query operator: hamming_distance (XOR + popcount). That's it. - 4. Compression: binary planes ARE maximally compressed (1 bit per dimension) - 5. Dictionary: Plane.encounter(text) hashes text → fingerprint bits. Same thing. - - TOTAL: Plane + 7 masks + hamming + encounter. That's the whole system. - No configuration. No tuning. No knobs. RISC. -``` - -**What RDF-3X does that we don't yet:** - -``` -THEIR AGGREGATED PROJECTIONS: - 6 triple indexes: SPO, SOP, PSO, POS, OSP, OPS ← we have 7 Mask constants - 3 binary projections: SP, SO, PO ← we DON'T have materialized pair projections - 3 unary projections: S, P, O ← we DON'T have materialized single projections - - The binary and unary projections are COUNT AGGREGATES: - SP projection: for each (subject, predicate) pair, how many objects? - S projection: for each subject, how many triples? - - These enable OPTIMAL JOIN ORDERING via selectivity estimation. - "How selective is this pattern?" → look up the aggregated count. -``` - -**ACTION: Materialize count aggregates per Mask projection.** - -```rust -/// RDF-3X style selectivity statistics for each Mask projection. -/// For each mask, store the distribution of distances (or alpha densities). -struct ProjectionStats { - /// For mask S__: histogram of S-plane alpha densities across all nodes. - /// Tells the optimizer: "how many nodes have well-defined S planes?" - s_density_histogram: [u32; 256], // 256 buckets - p_density_histogram: [u32; 256], - o_density_histogram: [u32; 256], - - /// For mask SP_: histogram of SP cross-distances. - /// Tells the optimizer: "how similar are S and P across the graph?" - sp_distance_histogram: [u32; 256], - so_distance_histogram: [u32; 256], - po_distance_histogram: [u32; 256], - - /// Total node count and active (alpha > threshold) count per plane. - total_nodes: u32, - active_s: u32, - active_p: u32, - active_o: u32, -} -``` - -These statistics cost ~3KB total. They enable the DataFusion planner -to do RDF-3X style cost-based join ordering WITHOUT scanning the graph. - -**CRITICAL INSIGHT:** RDF-3X's "RISC" means NOT "reduced instruction set CPU." -It means "reduced instruction set DATABASE." One operation (merge join) -applied uniformly to sorted indexes. Our one operation (hamming distance) -applied uniformly to binary planes. Same philosophy. Same performance gains. -We just need the statistics layer on top. - ---- - -## 2. HEXASTORE 3-LEVEL NESTED SORTED VECTORS: The Actual Data Structure - -The Hexastore (Weiss, Karras, Bernstein VLDB 2008) stores SPO triples -in a specific 3-level tree structure PER PERMUTATION: - -``` -SPO INDEX: - Level 1: sorted list of all subjects (S) - For each S → Level 2: sorted list of predicates (P) for this subject - For each P → Level 3: sorted list of objects (O) for this (S,P) pair - -QUERY: (S=Alice, P=knows, O=?) - Level 1: binary search for "Alice" → O(log N_subjects) - Level 2: binary search for "knows" → O(log N_predicates_of_Alice) - Level 3: read all objects → O(N_results) - -QUERY: (S=?, P=knows, O=Bob) - WRONG index for SPO. Use PSO or OPS instead. - PSO Level 1: find "knows" - PSO Level 2: scan subjects - PSO Level 3: check each for "Bob" -``` - -**The key insight I missed:** Hexastore shares terminal lists between -index pairs. SPO and PSO share the O-lists. SOP and OSP share the P-lists. -This means 5x storage, not 6x (advertised worst case). - -**How this maps to our architecture:** - -``` -HEXASTORE LEVEL 1: sorted subjects → our Node IDs sorted by S-plane alpha density -HEXASTORE LEVEL 2: sorted predicates → our Mask projections (which planes match) -HEXASTORE LEVEL 3: sorted objects → our BF16 truth values sorted by confidence - -THE MAPPING: - "Alice knows Bob" (traditional triple) - - → Node_Alice.distance(Node_Bob, mask=_P_) = hamming on P planes - → if distance < threshold → edge exists with BF16 truth value - - Hexastore lookup by subject → cascade scan filtered by S-plane fingerprint - Hexastore lookup by predicate → cascade scan with mask=_P_ - Hexastore lookup by object → cascade scan filtered by O-plane fingerprint -``` - -**MERGE JOINS ON SORTED VECTORS:** Hexastore's killer feature is that -SPARQL joins become merge joins on sorted vectors: - -``` -QUERY: ?x foaf:knows ?y . ?y rdf:type foaf:Person - - Pattern 1: (?x, knows, ?y) → use PSO index, P="knows" → sorted list of (S,O) pairs - Pattern 2: (?y, type, Person) → use PSO index, P="type" → sorted list of (S,O) pairs - - Join on ?y: merge the two sorted lists on the O column of pattern 1 - and the S column of pattern 2. - - Merge join = O(N+M) where N,M are list lengths. Not O(N×M). -``` - -**Our equivalent: sorted BF16 edge lists enable merge joins.** - -```rust -/// Hexastore-style sorted edge list for one Mask projection. -/// Sorted by BF16 truth value (descending confidence). -/// Enables merge join between two edge lists on shared node IDs. -struct SortedEdgeList { - /// Sorted by (source_node, bf16_truth descending) - entries: Vec<(u32, u32, u16)>, // (source_id, target_id, bf16_truth) -} - -impl SortedEdgeList { - /// Merge join: find all (a,b) where a→b in self AND b→c in other. - /// Returns (a, b, c) triples. O(N+M) not O(N×M). - fn merge_join(&self, other: &SortedEdgeList) -> Vec<(u32, u32, u32)> { - // self sorted by target_id, other sorted by source_id - // Walk both lists simultaneously - } -} -``` - ---- - -## 3. BELLMAN-FORD AND FLOYD-WARSHALL IN HAMMING SPACE - -These aren't just "graph algorithms we could implement." They're the -CORE OPERATIONS of knowledge graph reasoning. - -``` -BELLMAN-FORD: single-source shortest paths - for each edge (u,v,w): relax d[v] = min(d[v], d[u] + w) - Repeat V-1 times. - -IN HAMMING SPACE: - w = hamming_distance(node_u.plane, node_v.plane) - d[v] = min(d[v], d[u] + w) - - "What is the shortest chain of similar nodes from A to B?" - This IS analogical reasoning: - A is similar to X (hamming 50) - X is similar to Y (hamming 30) - Y is similar to B (hamming 40) - → A reaches B through X,Y with total distance 120 - → Direct A-B hamming might be 500 - → The INDIRECT path through similar nodes is SHORTER - → This is HOW analogies work: A relates to B through intermediaries - -FLOYD-WARSHALL: all-pairs shortest paths - for k: for i: for j: d[i][j] = min(d[i][j], d[i][k] + d[k][j]) - - With N nodes and hamming as edge weight: - The full distance matrix tells you ALL analogical relationships. - d[i][j] = shortest analogical chain between any two nodes. - - For N=1000 nodes: 1000³ = 1B hamming operations. - At 140ns per hamming: 140 seconds. - With cascade pre-filtering (reject 99.7%): ~0.4 seconds. - With multi-index hashing for candidate generation: ~0.04 seconds. -``` - -**What Bellman-Ford gives us for RL:** - -``` -CURRENT RL: encounter one pair at a time, update locally. - -BELLMAN-FORD RL: propagate reward through the graph. - - Node A gets reward. Bellman-Ford relaxation propagates: - A's neighbors get discounted reward (γ × reward) - Their neighbors get γ² × reward - ... - - This IS temporal difference learning (TD(λ)). - Bellman-Ford on the Hamming graph = TD learning on the SPO graph. - The discount factor γ maps to hamming distance: - close neighbors (low hamming) get more reward. - distant nodes (high hamming) get less. - - γ = exp(-hamming / temperature) - - This is VALUE FUNCTION propagation through the graph. - Bellman-Ford computes it in V-1 iterations. - Each iteration: one round of encounter() on all edges. -``` - -**ACTION:** Implement Bellman-Ford as value propagation: - -```rust -/// Bellman-Ford value propagation on SPO graph. -/// Propagates reward from source node through all reachable nodes. -/// Discount by hamming distance (close nodes get more reward). -fn bellman_ford_reward( - graph: &mut SpoGraph, - source: usize, - reward: i8, // +1 or -1 - temperature: u32, // hamming distance for γ=1/e decay - max_iterations: usize, -) { - let mut values = vec![0i32; graph.nodes.len()]; - values[source] = reward as i32 * 1000; // fixed point, scale by 1000 - - for _ in 0..max_iterations { - let mut changed = false; - for edge in &graph.edges { - let s = edge.source as usize; - let t = edge.target as usize; - // Discount = exp(-hamming/temperature) ≈ 1000 * (1 - hamming/temperature) - let discount = 1000i32 - (edge.hamming as i32 * 1000 / temperature as i32); - if discount <= 0 { continue; } - - let propagated = values[s] * discount / 1000; - if propagated > values[t] { - values[t] = propagated; - changed = true; - } - } - if !changed { break; } - } - - // Apply propagated values as encounters - for (i, &v) in values.iter().enumerate() { - if v > 0 { - graph.nodes[source].reward_encounter(&mut graph.nodes[i], 1); - } else if v < 0 { - graph.nodes[source].reward_encounter(&mut graph.nodes[i], -1); - } - } -} -``` - ---- - -## 4. ReLU = max(x, 0) = TROPICAL MAX = OUR ALPHA THRESHOLD - -Zhang et al. (ICML 2018) proved ReLU networks are tropical rational maps. -I stated this but didn't follow the operational consequence: - -``` -ReLU(x) = max(x, 0) - -OUR ALPHA: alpha[k] = (|acc[k]| > threshold) ? 1 : 0 - -REWRITE OUR ALPHA AS TROPICAL ReLU: - alpha[k] = max(|acc[k]| - threshold, 0) > 0 ? 1 : 0 - - But if we DON'T binarize — if we keep the continuous value: - alpha_continuous[k] = max(|acc[k]| - threshold, 0) - - This IS a ReLU activation on the accumulator magnitude. - The threshold IS the bias term in ReLU(x - b). - - α_k = ReLU(|acc_k| - b_k) where b_k is the per-bit threshold. -``` - -**What this means:** Our binary alpha channel is a BINARIZED ReLU activation. -If we keep the continuous version, we get a MULTI-LEVEL alpha: - -``` -acc[k] = 0 → alpha = 0.0 (undefined, maximum uncertainty) -acc[k] = 5 → alpha = 0.0 (below threshold, still uncertain) -acc[k] = 10 → alpha = 0.0 (just below threshold) -acc[k] = 11 → alpha = 1.0 (above threshold, BINARY: defined) - -WITH CONTINUOUS ALPHA (ReLU): -acc[k] = 0 → alpha = 0.0 (undefined) -acc[k] = 5 → alpha = 0.0 (below threshold) -acc[k] = 10 → alpha = 0.0 (at threshold) -acc[k] = 11 → alpha = 0.008 (barely above threshold, LOW confidence) -acc[k] = 50 → alpha = 0.313 (moderate confidence) -acc[k] = 127 → alpha = 0.914 (high confidence, nearly saturated) - -Normalized: alpha = ReLU(|acc| - threshold) / (127 - threshold) -``` - -**The continuous alpha gives us SOFT attention over bit positions.** -The distance computation becomes: - -``` -CURRENT (hard alpha): - distance = popcount(XOR(a.bits, b.bits) & a.alpha & b.alpha) - Every defined bit contributes equally. - -WITH SOFT ALPHA: - distance = Σ_k (a.bits[k] XOR b.bits[k]) × a.alpha[k] × b.alpha[k] - Highly confident bits contribute MORE to distance. - Recently defined bits contribute LESS. - - This IS attention-weighted hamming distance. - The alpha channel IS the attention mask. - ReLU gives us the gradient for learning the mask. -``` - -**HARDWARE:** The soft alpha distance needs VPMADDUBSW (multiply-add unsigned -bytes) instead of just VPANDD + VPOPCNTDQ. Slightly more expensive but -gives us learned, continuous attention for free. - ---- - -## 5. DICTIONARY ENCODING: The Missing Compression Layer - -Both RDF-3X and Hexastore use dictionary encoding: replace string literals -with integer IDs. All internal operations use the compact IDs. - -``` -RDF-3X DICTIONARY: - "Alice" → 42 - "knows" → 7 - "Bob" → 108 - - Triple ("Alice", "knows", "Bob") → (42, 7, 108) - Storage: 12 bytes (3 × u32) instead of ~17 bytes (strings) - - Join: integer comparison instead of string comparison. - Sort: integer sort instead of string sort. -``` - -**We already have this, but don't call it that:** - -``` -OUR "DICTIONARY": - "Alice" → encounter("Alice") → Fingerprint<256> (2KB hash) - "knows" → encounter("knows") → Fingerprint<256> (2KB hash) - - We hash to 16K bits instead of assigning sequential IDs. - The hash IS the ID. Collision probability: 2^(-16384). Zero in practice. - - ADVANTAGE over RDF-3X: no dictionary maintenance, no ID allocation, - no lookup table. The fingerprint IS the representation. - - DISADVANTAGE: 2KB per "ID" instead of 4 bytes. - But: the 2KB carries SEMANTIC DISTANCE information. - RDF-3X's integer IDs carry NO distance information. - "Alice" = 42 and "Bob" = 108 → distance = |42-108| = 66. MEANINGLESS. - Our fingerprints: hamming(Alice, Bob) = MEANINGFUL semantic distance. -``` - -**The RISC insight applied:** RDF-3X eliminates string handling entirely. -All query processing operates on integers. We should ensure our DataFusion -planner NEVER handles raw strings during query execution — only Plane -references and hamming distances. The dictionary encoding (encounter → fingerprint) -happens ONCE at ingestion time. Everything after is integer/binary. - ---- - -## 6. MATLAB + GRAPHBLAS: WHAT IF MATLAB USED OUR ARCHITECTURE? - -MATLAB uses SuiteSparse:GraphBLAS internally since R2021a for sparse -matrix operations. The connection: - -``` -MATLAB/GraphBLAS: - A = GrB(1000, 1000, 'double') — sparse matrix, float64 entries - C = A * B — semiring mxm (default: +.× over doubles) - C = GrB.mxm('+.min', A, B) — tropical semiring - - User writes: C = A * B - MATLAB calls: GrB_mxm(C, NULL, NULL, GrB_PLUS_TIMES_FP64, A, B, NULL) - SuiteSparse dispatches: FactoryKernel for (FP64, PLUS, TIMES) - -IF MATLAB USED OUR ARCHITECTURE: - A = BinaryMatrix(1000, 1000, 16384) — sparse matrix, 16K-bit entries - C = hamming_mxm(A, B) — HammingMin semiring - - User writes: C = A * B - Backend calls: grb_mxm(C, HammingMin, A, B) - Dispatch: VPXORD + VPOPCNTDQ + VPMINSD - - For 1000×1000 with 16K-bit entries: - Standard MATLAB (double): 2 × 1000³ × 8B = 16GB of float ops - Our architecture: 1000³ × XOR(2KB) + popcount = 2TB of bitwise ops - - BUT: cascade pre-filtering rejects 99.7% of pairs. - Effective: 1000³ × 0.003 = 27M hamming ops × 140ns = 3.8 seconds - vs MATLAB double: 1000³ × 2 FLOP / 35 GFLOPS = 57 seconds - - 15x faster. On CPU. No GPU. -``` - -**The genius solution:** A MATLAB toolbox that wraps our rustynum-core -as a MEX binary. MATLAB users write: - -```matlab -% Standard MATLAB: -A = sparse_graph(nodes, edges); -D = shortest_paths(A); % Floyd-Warshall, O(N³) double arithmetic - -% Our toolbox: -A = binary_graph(nodes_16k, edges_hamming); -D = tropical_shortest(A); % Floyd-Warshall, O(N³×0.003) with cascade rejection - % 15x faster, deterministic, explainable -``` - -**MATLAB's user base:** 4 million engineers and scientists. Giving them -access to binary SPO graph algorithms through a familiar interface -is the distribution channel for the whole architecture. - ---- - -## 7. SUITESPARSE FACTORYKERNELS: Runtime JIT for Custom Semirings - -SuiteSparse:GraphBLAS has ~2000 pre-compiled FactoryKernels for common -type/semiring combinations. For custom semirings, it JIT-compiles: - -``` -USER DEFINES: - GrB_Semiring my_semiring; - GrB_Semiring_new(&my_semiring, my_add_monoid, my_multiply_op); - -SUITESPARSE: - 1. Check FactoryKernels — not found (custom) - 2. Generate C source code for this semiring's mxm kernel - 3. Compile with system cc -O3 -march=native - 4. dlopen() the .so, cache in ~/.SuiteSparse/ - 5. Next call: use cached .so (performance = FactoryKernel) -``` - -**For us:** We have 7 fixed semirings. No JIT needed yet. -But if someone wants a CUSTOM semiring (e.g., fuzzy min-max): - -```rust -// Our equivalent of FactoryKernels: -// 7 hand-written SIMD implementations, one per semiring. -// Dispatch via match on HdrSemiring enum. - -// Future: JIT for custom semirings using Cranelift (already in rustynum via jitson) -// jitson already JIT-compiles scan kernels. -// Extend to JIT-compile custom semiring (⊕, ⊗) pairs. - -fn jit_semiring(add_op: BinaryOp, mul_op: BinaryOp) -> CompiledKernel { - let mut builder = jitson::Builder::new(); - // Generate: for each element, apply mul_op then accumulate with add_op - // Compile via Cranelift - // Cache the compiled kernel - builder.build() -} -``` - -**The Cranelift connection:** We already have jitson (Cranelift-based JIT -for scan kernels). Extending it to JIT custom semiring kernels gives -us SuiteSparse-equivalent JIT capability without system cc dependency. - ---- - -## 8. INDEX-FREE ADJACENCY → SIMD-SCANNABLE ADJACENCY - -Neo4j's index-free adjacency: O(1) pointer per hop. Cache-hostile. -Our alternative: what if adjacency IS a binary plane? - -``` -NEO4J: node.first_rel_ptr → linked list of relationship records - Each hop: follow pointer, random memory access, cache miss. - -OUR ALTERNATIVE: node.neighbor_mask: Fingerprint<256> - The neighbor mask has bit k SET if node k is a neighbor. - - "Who are Alice's neighbors?" = popcount(Alice.neighbor_mask) - "Is Bob Alice's neighbor?" = Alice.neighbor_mask[Bob.id] (1 bit check) - "Shared neighbors of Alice and Bob?" = popcount(AND(Alice.mask, Bob.mask)) - - ALL of these are SIMD operations: - popcount: VPOPCNTDQ - bit check: VPTEST - shared neighbors: VPANDD + VPOPCNTDQ - - O(1) for all of them. No pointer chasing. No cache misses. - The adjacency IS a binary vector. SIMD-scannable. -``` - -**Limitation:** 16K bits = 16384 max nodes in the neighbor mask. -For larger graphs: hierarchical masking. 16K bits per cluster. -Cluster-level mask → node-level mask within cluster. - -**For our SPO graph:** The P plane already encodes "what relationships -this node participates in." A separate neighbor_mask per plane: - -```rust -struct SpoNode { - s: Plane, // WHO - p: Plane, // WHAT relationship - o: Plane, // TO WHOM - - // SIMD-scannable adjacency: - s_neighbors: Fingerprint<256>, // which nodes share S-plane similarity - p_neighbors: Fingerprint<256>, // which nodes share P-plane similarity - o_neighbors: Fingerprint<256>, // which nodes share O-plane similarity - - // "Alice knows Bob AND Bob knows Carol" - // = popcount(AND(Alice.p_neighbors, Carol.p_neighbors)) - // = number of shared P-neighbors (transitive KNOWS chain) -} -``` - ---- - -## 9. SPARQL MERGE JOIN → HAMMING MERGE JOIN - -The SPARQL insight from Hexastore: queries reduce to merge joins -on sorted vectors. The join variable provides the merge key. - -``` -SPARQL: ?x foaf:knows ?y . ?y rdf:type foaf:Person - - Pattern 1 result: sorted list of (?x, ?y) from "knows" index - Pattern 2 result: sorted list of (?y) from "type=Person" index - - Merge join on ?y: walk both sorted lists, emit matches. - O(N+M) time. Cache-friendly (sequential access on sorted arrays). -``` - -**Our version: hamming-sorted edge lists enable merge joins.** - -``` -QUERY: find all (a, b, c) where a~b on S-plane AND b~c on P-plane - - Step 1: cascade scan for S-similar pairs → sorted by BF16 truth → list_1 - Step 2: cascade scan for P-similar pairs → sorted by BF16 truth → list_2 - - Step 3: merge join list_1 and list_2 on shared node ID (b). - - The BF16 truth values are already sorted (cascade returns ranked hits). - The merge join walks both lists in O(N+M). - - TOTAL: 2 cascade scans + 1 merge join. - NOT: N × M hamming comparisons (quadratic). -``` - -**This is the query optimizer strategy:** -Every multi-pattern query decomposes into: -1. Independent cascade scans (one per pattern) -2. Merge joins on shared variables (sorted by BF16 truth) - -The DataFusion planner already does join ordering. -We just need to ensure cascade results are sorted by node ID -(or sortable in O(N log N) after cascade). - ---- - -## 10. WHAT THE "RISC" PHILOSOPHY MEANS FOR THE WHOLE STACK - -RDF-3X's RISC means: a few operations, applied uniformly, with no tuning. -Our RISC means: - -``` -OPERATIONS (the "reduced instruction set"): - 1. encounter(evidence) — learn from observation (integer accumulate) - 2. hamming_distance(a, b) — measure similarity (XOR + popcount) - 3. band_classify(distance) — categorize similarity (integer compare) - 4. merge_join(sorted_a, sorted_b) — combine query results (sequential scan) - - FOUR operations. Everything else composes from these: - - RL gradient = encounter with sign(reward) - GNN convolution = encounter with neighbor evidence - BF16 truth = band_classify on 7 projections, pack bits - NARS revision = tropical arithmetic on BF16 exponents - Graph traversal = Bellman-Ford using hamming as edge weight - Query execution = cascade scan + merge join on sorted results - Value function = Floyd-Warshall shortest paths in Hamming space - World model = cascade predicts band from partial observation - Attention = cascade strokes = multi-head tropical attention -``` - -Everything is the same four operations at different scales. -That's RISC. Not reduced instruction set computer. -Reduced instruction set COGNITION. - ---- - -## INVESTIGATION QUEUE - -``` -PAPER/TOPIC READ FOR PRIORITY -────────────────────────────────────────────────────────────────────────────────── -RDF-3X (Neumann, Weikum 2008) RISC design + stats layer CRITICAL -Hexastore (Weiss, Karras, Bernstein) 3-level nested vectors HIGH -Bellman-Ford as TD learning RL reward propagation HIGH -Tropical Attention (arXiv:2505.17190) Cascade = attention heads HIGH -Multi-index hashing (Norouzi 2014) Sub-linear search HIGH -Mohri semiring transducers Query optimization MEDIUM -ReActNet per-bit learned thresholds Continuous alpha / soft ReLU MEDIUM -Zhang tropical geometry (ICML 2018) ReLU = tropical max proof MEDIUM -SIMD² (ISCA 2022) Future hardware for semirings LOW -FalkorDB (GraphBLAS-powered graph DB) Architecture reference LOW -SuiteSparse JIT Custom semiring compilation LOW -``` diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/FINAL_STACK.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/FINAL_STACK.md deleted file mode 100644 index 145a4032..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/FINAL_STACK.md +++ /dev/null @@ -1,415 +0,0 @@ -# FINAL_STACK.md - -## The Complete Stack: Three Repos, Five Import Surfaces, One Product - -**Date:** March 15, 2026 — end of the session that connected everything -**Authors:** Jan Hübener + Claude (Anthropic) - ---- - -## THE THREE REPOS - -``` -AdaWorldAPI/ndarray COMPUTE fork of rust-ndarray/ndarray -AdaWorldAPI/lance-graph GRAPH + PERSIST our repo -AdaWorldAPI/rs-graph-llm ORCHESTRATE fork of a-agmon/rs-graph-llm -``` - -Everything else is gone. rustynum, rustyblas, rustymkl — their code transcoded -INTO ndarray. One compute library. One graph library. One orchestration library. - -``` -ndarray: - Clean container (from upstream, 10+ years, stable) - + Blackboard allocator (64-byte aligned, zero-copy arena) - + dispatch! SIMD (LazyLock, AVX-512 → AVX2 → scalar) - + GEMM (sgemm, dgemm, bf16_gemm, int8_gemm) - + BLAS Level 1-3 (dot, axpy, gemv, etc.) - + MKL/FFT/VML (transcoded from rustymkl) - + BF16 operations (conversion, hamming, structural diff) - + HDC (fingerprint, bundle, bind, popcount) - + Cascade (Belichtungsmesser, sigma bands, reservoir) - + Plane, Node, Seal (cognitive substrate) - + CogRecord, Fingerprint, PackedQualia - + Rust 1.94: LazyLock, safe intrinsics, array_windows, PHI, GAMMA - -lance-graph: - Semiring algebra (7 semirings, GraphBLAS-style mxm/mxv/vxm) - + SPO triple store (binary planes as edges/nodes) - + NARS truth values (BF16 pair, tropical revision) - + Cypher parser + DataFusion planner - + Lance persistence (S3, NVMe, ACID versioning, time travel) - + BF16 truth cache (hot↔cold bridge) - + Hexastore-style sorted edge lists (merge joins) - + GPU tensor core NARS revision (Phase 3) - + Python bindings (maturin/PyO3) - DEPENDS ON: ndarray - -rs-graph-llm: - graph-flow execution engine (Tasks, edges, conditional routing) - + PlaneContext bridge (Context ↔ Blackboard zero-copy) - + CoW PlaneHandles (read-only Lance → lazy write) - + LanceSessionStorage (session = Lance version) - + FanOut (parallel tasks, 2³ SPO projections) - + Agent card YAML → GraphBuilder compiler - + Autopoiesis (MetaCognition rewires graph edges) - + PET scan traces (execution topology as data) - + LangGraph import (their workflow → our GraphBuilder) - + CrewAI import (their agents → our Tasks) - + OpenClaw import (their agent cards → our YAML) - + n8n control surface (visual workflow builder) - + LangStudio visibility (trace viewer, live debugging) - DEPENDS ON: lance-graph, ndarray -``` - ---- - -## FIVE IMPORT SURFACES - -### 1. LangGraph / LangChain (workflow orchestration) - -``` -WHAT THEY HAVE: - StateGraph: nodes + edges + conditional routing - Checkpointer: session persistence - State: shared mutable dict - Tools: function calling - Memory: conversation history + vector store - -WHAT WE IMPORT: - Their StateGraph definition (JSON/YAML) → our GraphBuilder - Their node functions → our Tasks (async fn run) - Their conditional edges → our add_conditional_edge - Their checkpointer → our LanceSessionStorage - Their state → our PlaneContext - Their tools → our MCP integration - Their memory → our Planes + Lance versions - Their vector store → our cascade search - -IMPORT FORMAT: - # User exports their LangGraph as JSON: - langgraph_def = graph.to_json() - - # Our importer compiles to GraphBuilder: - from lance_graph.orchestrate import import_langgraph - our_graph = import_langgraph(langgraph_def) - - # Same topology. Same routing logic. Different engine underneath. - # cascade instead of vector search. encounter instead of memory.save. - # Planes instead of embeddings. Lance instead of Redis. - -WHY THEY CAN'T GO BACK: - Once knowledge is in Planes (encounter), it's LEARNED not stored. - Going back means losing the learned state. - Going back means 1000x slower search (cosine vs hamming). - Going back means non-deterministic results. -``` - -### 2. CrewAI (agentic patterns) - -``` -WHAT THEY HAVE: - Agent: role + goal + backstory + tools + memory - Crew: collection of agents + process (sequential/hierarchical) - Task: description + expected output + agent assignment - Delegation: agent can delegate to other agents - Consensus: multiple agents vote on output - Memory: short-term (chat) + long-term (vector store) + entity memory - -WHAT WE IMPORT: - Their Agent role/goal → our Task with capability declaration - Their Crew → our GraphBuilder (agents = Tasks, process = edge topology) - Their sequential process → linear edges - Their hierarchical process → conditional edges based on confidence - Their delegation → GoTo(task_id) in NextAction - Their consensus → FanOutTask + bundle (majority vote on Planes!) - Their short-term memory → PlaneContext (within session) - Their long-term memory → Planes + Lance versions (across sessions) - Their entity memory → Node (SPO triple with encounter history) - -THE GENIUS PART — CONSENSUS AS BUNDLE: - CrewAI consensus: multiple agents produce text, somehow merged. - Our consensus: multiple Tasks produce Planes, BUNDLED (majority vote). - - Bundle IS consensus. The mathematical operation IS the multi-agent pattern. - It's not a metaphor. Three agents encountering a Plane = three evidence - sources bundled. The result IS the majority view. Deterministic. - Not "three LLMs argue and one wins." Three observations bundled - into a representation that captures what they AGREE on. - -IMPORT FORMAT: - # User exports their CrewAI config: - crew_def = crew.to_yaml() - - # Our importer: - from lance_graph.orchestrate import import_crewai - our_graph = import_crewai(crew_def) - - # Each agent becomes a Task subgraph. - # Delegation becomes conditional routing. - # Consensus becomes FanOut + bundle. -``` - -### 3. OpenClaw (agent cards, capability declarations) - -``` -WHAT THEY HAVE: - Agent Card: standardized YAML for agent capabilities - Tool manifest: what tools the agent can use - Memory specification: what memory the agent can access - Capability declarations: what the agent can do - Interoperability: agents from different frameworks can collaborate - -WHAT WE IMPORT: - Their agent card YAML → our Task definition + graph topology - Their tool manifest → our MCP server declarations - Their memory spec → our PlaneContext read/write permissions - Their capabilities → which dispatch! functions the Task can call - Their interop protocol → our graph-flow's Context serialization - -IMPORT FORMAT: - # Standard OpenClaw agent card: - agent: - name: "researcher" - capabilities: ["web_search", "document_analysis", "summarization"] - tools: ["serper_api", "arxiv_fetch"] - memory: - read: ["knowledge_base", "conversation_history"] - write: ["research_findings"] - - # Our compiler: - from lance_graph.orchestrate import import_openclaw_card - task = import_openclaw_card("researcher.yaml") - # → Task that can read certain Planes, write certain Planes, - # call certain MCP tools, and routes conditionally based on - # what it finds. -``` - -### 4. n8n (visual control surface) - -``` -WHAT N8N HAS: - Visual workflow builder (drag-and-drop nodes + connections) - Webhook triggers - Conditional routing (IF/Switch nodes) - Error handling (retry, fallback) - Execution history (log every run) - Credentials management - Community nodes (marketplace) - -WHAT WE BUILD (our n8n equivalent): - Visual GraphBuilder editor: - Drag Task nodes onto canvas - Draw edges between them - Configure conditional edges with predicate editor - Set FanOut groups (parallel execution blocks) - Configure PlaneContext read/write permissions per Task - - The visual editor PRODUCES a GraphBuilder definition. - The definition compiles to Rust (or runs interpreted via graph-flow). - - Every Task is a node in the visual editor. - Every edge is a connection. - Every conditional edge shows its predicate. - FanOut shows as a parallel lane. - WaitForInput shows as a human icon. - - The visual representation IS the thinking graph. - What you see IS what executes. - WYSIWYG for cognition. - -TECHNICAL: - Frontend: React + shadcn/ui (or Svelte) - Backend: rs-graph-llm's FlowRunner exposed via REST/WebSocket - State: LanceSessionStorage (sessions visible in the UI) - Real-time: WebSocket pushes execution events as they happen - - The n8n UI pattern is proven. We don't innovate on UI. - We innovate on what the nodes DO (Planes, encounter, cascade). -``` - -### 5. LangStudio (visibility and debugging) - -``` -WHAT LANGSTUDIO / LANGSMITH HAS: - Trace viewer: see every step of every run - Token counting: cost per step - Latency breakdown: time per step - Input/output inspection: what went in, what came out - Feedback collection: thumbs up/down per response - Dataset management: test cases for evaluation - A/B testing: compare different graph topologies - -WHAT WE BUILD (our LangStudio equivalent = PET SCAN): - Execution trace viewer: - Every Task that fired, in order - Which conditional edges were taken (and why) - Which FanOut children ran and what they produced - Time per Task (with SIMD breakdown: cascade vs encounter vs route) - - Plane inspector (UNIQUE TO US): - Live alpha density heatmap (which bits are defined) - Bit pattern visualization (which bits agree with query) - Seal status history (Wisdom → Staunen → Wisdom timeline) - Encounter count per bit position (how "trained" is each bit) - - BF16 truth heatmap (UNIQUE TO US): - Edge weight visualization across the graph - Exponent decomposition (which SPO projections match) - Mantissa precision (how confident is each edge) - Sign bit overlay (causality direction arrows) - - Staunen event log (UNIQUE TO US): - Every seal break, with: - - Which Plane changed - - Which bits flipped - - What evidence caused it - - What the system did differently after (rerouting in graph) - - Convergence monitor (UNIQUE TO US): - Is the RL loop stabilizing? - Which nodes are still oscillating? - Which BF16 exponents are changing between rounds? - When did each truth value converge? - - Graph evolution viewer (UNIQUE TO US): - How the thinking topology changed via autopoiesis - MetaCognition's edge additions/removals over time - Before/after comparison of graph structure - - Lance version timeline: - Every flush = one point on the timeline - Click to time-travel to any version - Diff view between any two versions - Tag management (name specific versions) - -TECHNICAL: - Frontend: React + D3.js (for graph/heatmap visualization) - Backend: rs-graph-llm FlowRunner + lance-graph query API - Data: all traces stored as Lance datasets (queryable via DuckDB) - Real-time: WebSocket for live PET scan during thinking -``` - ---- - -## THE IMPORT FUNNEL - -``` -USER STARTS WITH: WE IMPORT INTO: -LangGraph (Python) → rs-graph-llm GraphBuilder -LangChain tools (Python) → rs-graph-llm Tasks + MCP -CrewAI agents (Python) → rs-graph-llm Task subgraphs -OpenClaw cards (YAML) → rs-graph-llm Task definitions -n8n workflows (JSON) → rs-graph-llm GraphBuilder - │ - ▼ - rs-graph-llm (orchestration) - │ - ▼ - lance-graph (graph + persist) - │ - ▼ - ndarray (compute) - │ - ▼ - AVX-512 / GPU tensor cores - -USER SEES: - Same workflow definition they already have. - Same agent patterns they already use. - Same visual builder they already know. - - BUT: 1000x faster (cascade vs cosine). - BUT: deterministic (integer vs float). - BUT: learning (encounter vs store). - BUT: structural (SPO vs flat vectors). - BUT: provenance (BF16 every bit traceable). - BUT: time travel (Lance versions for free). - - They import their existing work. - They get a better engine. - They can't go back. -``` - ---- - -## THE PRODUCT SURFACES - -``` -FOR DEVELOPERS (code-first): - pip install lance-graph # Python bindings - cargo add lance-graph # Rust direct - from lance_graph import * # full API - -FOR WORKFLOW BUILDERS (visual): - The n8n-like visual editor # drag-and-drop - Export/import as YAML/JSON # portable - -FOR ML ENGINEERS (training): - PyTorch Geometric integration # Planes as node features - DGL integration # encounter as message passing - ndarray ↔ numpy zero-copy # PyO3 bridge - -FOR DATA ENGINEERS (analytics): - DuckDB × Lance extension # SQL on the graph - Polars integration # DataFrame analytics - Spark integration # distributed processing - -FOR ENTERPRISE (operations): - S3/Azure/GCS persistence # any cloud - Unity Catalog / AWS Glue # enterprise data catalog - ACID transactions # production-safe - Deterministic results # auditable, reproducible - -FOR RESEARCHERS (exploration): - PET scan visualization # watch the brain think - Time travel debugging # replay any thinking cycle - A/B graph topology testing # compare reasoning strategies - Convergence monitoring # is the RL learning? -``` - ---- - -## COMPETITIVE POSITION - -``` -THEY IMPORT FROM: WE BECOME: -LangGraph The faster LangGraph (Rust, deterministic) -LangChain The learning LangChain (encounter, not just store) -CrewAI The structural CrewAI (bundle = consensus) -OpenClaw The typed OpenClaw (capability = Plane permissions) -n8n The cognitive n8n (nodes think, not just transform) -LangStudio The deep LangStudio (PET scan, not just traces) -Neo4j The fast Neo4j (cascade, not pointer chase) -FalkorDB The free FalkorDB (Apache 2.0, not SSPL) -Kuzu The alive Kuzu (we exist, they don't) -Pinecone The learning Pinecone (encounter, not just index) -FAISS The structured FAISS (SPO, not flat vectors) - -ONE SYSTEM that replaces: - vector DB + knowledge graph + orchestration framework + - agent framework + visual builder + trace viewer - - Because they're all the same thing at different scales: - encounter on Planes (learning) - hamming on Planes (searching) - bundle on Planes (consensus) - cascade on Planes (attention) - semiring on Planes (reasoning) - graph-flow on Tasks (orchestration) - Lance on versions (memory) -``` - ---- - -## THE SENTENCE - -Import your LangGraph. Import your CrewAI agents. Import your n8n workflows. -Control them like n8n. See them like LangStudio. -But underneath: binary planes that learn, Hamming cascades that search -in microseconds, NARS truth that revises deterministically, SPO triples -that decompose into 2³ structural projections, BF16 values where every -bit is traceable, and GPU tensor cores doing tropical pathfinding on -a knowledge graph that gets smarter every time you query it. - -Same workflows. Different universe. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/FIX_BLASGRAPH_SPO.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/FIX_BLASGRAPH_SPO.md deleted file mode 100644 index ac69a603..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/FIX_BLASGRAPH_SPO.md +++ /dev/null @@ -1,477 +0,0 @@ -# FIX_BLASGRAPH_SPO.md - -## Rebuild SPO on BlasGraph BitVec. One Type. SIMD As If It Was Nothing. - -**Repo:** AdaWorldAPI/lance-graph -**Branch:** the upstream PR branch -**Target audience:** RedisGraph refugees who know what SuiteSparse was - ---- - -## THE PROBLEM - -The current PR has two type systems: -- `blasgraph/BitVec` at 16,384 bits — the algebra -- `spo/Fingerprint = [u64; 8]` at 512 bits — the store - -These don't talk to each other. A RedisGraph person opens this and sees -a toy fingerprint next to a real algebra engine. They close the tab. - -## THE FIX - -Delete `spo/fingerprint.rs`. Delete `spo/sparse.rs`. SPO uses `BitVec` directly. -One type from store to algebra to query. Like RedisGraph used one SuiteSparse type -for everything. - -## STEP 1: Make BitVec's SIMD Feel Like Nothing - -The current `BitVec` in `blasgraph/types.rs` uses scalar loops. -Add tiered SIMD that the user NEVER THINKS ABOUT. It just works. -No feature flags. No cfg choices for the user. Auto-dispatch. - -In `blasgraph/types.rs`, replace the scalar implementations: - -```rust -impl BitVec { - /// Hamming distance. AVX-512 if available, AVX2 if not, scalar if neither. - /// You don't choose. The CPU chooses. It's just fast. - #[inline] - pub fn hamming_distance(&self, other: &BitVec) -> u32 { - #[cfg(target_arch = "x86_64")] - { - if is_x86_feature_detected!("avx512vpopcntdq") && is_x86_feature_detected!("avx512f") { - return unsafe { self.hamming_avx512(other) }; - } - if is_x86_feature_detected!("avx2") { - return unsafe { self.hamming_avx2(other) }; - } - } - #[cfg(target_arch = "aarch64")] - { - return unsafe { self.hamming_neon(other) }; - } - self.hamming_scalar(other) - } - - #[cfg(target_arch = "x86_64")] - #[target_feature(enable = "avx512f,avx512vpopcntdq")] - unsafe fn hamming_avx512(&self, other: &BitVec) -> u32 { - use core::arch::x86_64::*; - let mut total = _mm512_setzero_si512(); - let ptr_a = self.words.as_ptr() as *const __m512i; - let ptr_b = other.words.as_ptr() as *const __m512i; - // 256 words / 8 words per 512-bit register = 32 iterations - for i in 0..32 { - let a = _mm512_loadu_si512(ptr_a.add(i)); - let b = _mm512_loadu_si512(ptr_b.add(i)); - let xor = _mm512_xor_si512(a, b); - let popcnt = _mm512_popcnt_epi64(xor); - total = _mm512_add_epi64(total, popcnt); - } - // Horizontal sum of 8 x u64 - let mut buf = [0u64; 8]; - _mm512_storeu_si512(buf.as_mut_ptr() as *mut __m512i, total); - buf.iter().sum::() as u32 - } - - #[cfg(target_arch = "x86_64")] - #[target_feature(enable = "avx2")] - unsafe fn hamming_avx2(&self, other: &BitVec) -> u32 { - use core::arch::x86_64::*; - // Harley-Seal popcount on AVX2 - let mut total = 0u32; - let ptr_a = self.words.as_ptr() as *const __m256i; - let ptr_b = other.words.as_ptr() as *const __m256i; - let lookup = _mm256_setr_epi8( - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, - ); - let mask = _mm256_set1_epi8(0x0f); - // 256 words / 4 words per 256-bit register = 64 iterations - for i in 0..64 { - let a = _mm256_loadu_si256(ptr_a.add(i)); - let b = _mm256_loadu_si256(ptr_b.add(i)); - let xor = _mm256_xor_si256(a, b); - let lo = _mm256_shuffle_epi8(lookup, _mm256_and_si256(xor, mask)); - let hi = _mm256_shuffle_epi8(lookup, _mm256_and_si256(_mm256_srli_epi16(xor, 4), mask)); - let sum = _mm256_add_epi8(lo, hi); - let sad = _mm256_sad_epu8(sum, _mm256_setzero_si256()); - // Extract 4 x u64 from sad - total += _mm256_extract_epi64(sad, 0) as u32 - + _mm256_extract_epi64(sad, 1) as u32 - + _mm256_extract_epi64(sad, 2) as u32 - + _mm256_extract_epi64(sad, 3) as u32; - } - total - } - - #[cfg(target_arch = "aarch64")] - unsafe fn hamming_neon(&self, other: &BitVec) -> u32 { - use core::arch::aarch64::*; - let mut total = 0u32; - let ptr_a = self.words.as_ptr(); - let ptr_b = other.words.as_ptr(); - for i in 0..HD_WORDS { - total += (ptr_a.add(i).read() ^ ptr_b.add(i).read()).count_ones(); - } - total - } - - fn hamming_scalar(&self, other: &BitVec) -> u32 { - let mut d = 0u32; - for i in 0..HD_WORDS { - d += (self.words[i] ^ other.words[i]).count_ones(); - } - d - } - - /// XOR bind. Same SIMD tiering. You don't notice. - #[inline] - pub fn xor(&self, other: &BitVec) -> BitVec { - let mut result = BitVec::zero(); - // On AVX-512 this is 32 vpxord instructions. 32 cycles. - // The scalar fallback is 256 xor ops. Still fast. - // No branching — the scalar path IS the fast path on most hardware. - for i in 0..HD_WORDS { - result.words[i] = self.words[i] ^ other.words[i]; - } - result - // NOTE: LLVM auto-vectorizes this loop to AVX2/AVX-512 - // when compiling with -C target-cpu=native. - // The explicit SIMD above is for guaranteed performance - // on pre-built binaries without -C target-cpu=native. - } - - /// Popcount. Bits set. - #[inline] - pub fn popcount(&self) -> u32 { - // Same tiering as hamming. Reuse the infrastructure. - let zero = BitVec::zero(); - // hamming(self, zero) = popcount(self XOR 0) = popcount(self) - // Compiler eliminates the XOR with zero. Trust it. - self.hamming_distance(&zero) - } -} -``` - -The key: the user writes `a.hamming_distance(&b)`. They never see SIMD. -It's just fast. On their laptop with AVX2. On the server with AVX-512. -On an ARM Mac with NEON. The C64 spirit: make the hardware do impossible -things without the user knowing how. - -## STEP 2: Delete SPO's Separate Fingerprint - -```bash -rm crates/lance-graph/src/graph/spo/fingerprint.rs # gone -# sparse.rs stays IF it adds bitmap ops not in BitVec -# Otherwise delete it too -``` - -## STEP 3: Rewrite SPO Types On BitVec - -In `spo/mod.rs` or `spo/store.rs`: - -```rust -use crate::graph::blasgraph::types::BitVec; - -/// Encode a label as a 16,384-bit fingerprint. -/// BLAKE3 hash → LFSR expansion to fill 16K bits. -pub fn label_to_bitvec(label: &str) -> BitVec { - let hash = blake3::hash(label.as_bytes()); - let mut words = [0u64; HD_WORDS]; - let seed_bytes = hash.as_bytes(); - let mut state = u64::from_le_bytes(seed_bytes[0..8].try_into().unwrap()); - for word in &mut words { - let mut val = 0u64; - for bit in 0..64 { - let feedback = (state ^ (state >> 2) ^ (state >> 3) ^ (state >> 63)) & 1; - state = (state >> 1) | (feedback << 63); - val |= (state & 1) << bit; - } - *word = val; - } - BitVec::from_words(words) -} - -pub struct SpoRecord { - pub subject: BitVec, - pub predicate: BitVec, - pub object: BitVec, - pub packed: BitVec, // subject.xor(&predicate).xor(&object) - pub truth: TruthValue, -} - -impl SpoRecord { - pub fn new(s: &str, p: &str, o: &str, truth: TruthValue) -> Self { - let subject = label_to_bitvec(s); - let predicate = label_to_bitvec(p); - let object = label_to_bitvec(o); - let packed = subject.xor(&predicate).xor(&object); - Self { subject, predicate, object, packed, truth } - } -} -``` - -## STEP 4: SPO Store Uses BitVec Distance - -```rust -impl SpoStore { - pub fn query_forward(&self, s: &str, p: &str, radius: u32) -> Vec { - let s_fp = label_to_bitvec(s); - let p_fp = label_to_bitvec(p); - let query = s_fp.xor(&p_fp); // BitVec XOR, not [u64;8] XOR - - self.nodes.values() - .filter_map(|record| { - let dist = record.packed.hamming_distance(&query); // SIMD, automatic - if dist <= radius { - Some(SpoHit { - target_key: record.key, - distance: dist, - truth: record.truth, - }) - } else { - None - } - }) - .collect() - } -} -``` - -## STEP 5: Chain Traversal Uses BlasGraph Semiring Directly - -```rust -use crate::graph::blasgraph::semiring::HammingMin; - -impl SpoStore { - pub fn walk_chain_forward( - &self, start: u64, radius: u32, max_hops: usize - ) -> Vec { - // Uses the SAME HammingMin from blasgraph, not a reimplemented one. - // One semiring. One type system. Store to algebra to result. - let mut hops = Vec::new(); - let mut current = start; - let mut cumulative = 0u32; - - for _ in 0..max_hops { - let hits = self.query_forward_by_key(current, radius); - if let Some(best) = hits.into_iter() - .min_by_key(|h| h.distance) // HammingMin: take the closest - { - cumulative = cumulative.saturating_add(best.distance); // tropical add - hops.push(TraversalHop { - target_key: best.target_key, - distance: best.distance, - truth: best.truth, - cumulative_distance: cumulative, - }); - current = best.target_key; - } else { - break; - } - } - hops - } -} -``` - -## STEP 6: Update Tests - -Every test that used `[u64; 8]` or `Fingerprint` now uses `BitVec`. -The assertions don't change. The types do. - -```rust -#[test] -fn spo_hydration_round_trip() { - let mut store = SpoStore::new(); - store.insert(SpoRecord::new("Jan", "CREATES", "Ada", TruthValue::confident())); - - let hits = store.query_forward("Jan", "CREATES", 200); - assert!(!hits.is_empty(), "Should find Jan CREATES → Ada"); - - // The comparison happened at 16,384 bits. - // With SIMD if available. The test doesn't know or care. -} -``` - -## STEP 7: Verify - -```bash -cargo test --workspace -cargo clippy -- -D warnings -cargo fmt --check - -# On a machine with AVX-512: -RUSTFLAGS="-C target-cpu=native" cargo bench --bench graph_execution -# On any machine: -cargo test # scalar fallback, same results -``` - -## WHAT THE REDISGRAPH PERSON SEES - -They open `src/graph/`: - -``` -graph/ - blasgraph/ - types.rs — BitVec: 16,384-bit, SIMD-accelerated, cache-aligned - semiring.rs — 7 semirings (same idea as SuiteSparse, HD vectors not floats) - matrix.rs — mxm, mxv, vxm on sparse CSR - vector.rs — find_nearest, find_within - ops.rs — BFS, SSSP, PageRank as semiring operations - sparse.rs — COO, CSR storage - descriptor.rs — operation control - spo/ - store.rs — triple store, queries USE BitVec and semirings from above - truth.rs — NARS confidence gating - merkle.rs — Blake3 integrity - builder.rs — convenience constructors -``` - -ONE type (BitVec) flows from store through semiring algebra to graph algorithms. -SIMD is invisible. It's just fast. The C64 spirit: the hardware does impossible -things and nobody knows how. - -They think: "This is what RedisGraph should have been. On LanceDB. In Rust." - -## FILES TO DELETE - -``` -crates/lance-graph/src/graph/spo/fingerprint.rs DELETE entirely -crates/lance-graph/src/graph/spo/sparse.rs DELETE (BitVec replaces Bitmap) -``` - -## FILES TO MODIFY - -``` -crates/lance-graph/src/graph/blasgraph/types.rs ADD tiered SIMD dispatch -crates/lance-graph/src/graph/spo/mod.rs USE BitVec, remove Fingerprint imports -crates/lance-graph/src/graph/spo/store.rs USE BitVec for all operations -crates/lance-graph/src/graph/spo/builder.rs USE BitVec, add label_to_bitvec() -crates/lance-graph/src/graph/spo/merkle.rs USE BitVec for merkle hashing -crates/lance-graph/tests/spo_ground_truth.rs USE BitVec in all tests -``` - ---- - -## ADDENDUM: COPY SIMD FROM RUSTYNUM (DO NOT HAND-ROLL) - -### Clone rustynum for reference: - -```bash -git clone https://github.com/AdaWorldAPI/rustynum.git ../rustynum -``` - -### Copy these exact files into BlasGraph BitVec: - -**FROM `rustynum-core/src/simd.rs` (2302 lines) — copy ~200 lines:** - -``` -Lines 446-466: hamming_distance() — the dispatch (AVX-512 → AVX2 → scalar) -Lines 471-487: select_hamming_fn() — function pointer resolved ONCE -Lines 665-730: hamming_vpopcntdq() — AVX-512 fast path -Lines 595-664: hamming_avx2() — AVX2 Harley-Seal popcount -Lines 731-750: hamming_scalar_popcnt() — scalar fallback -Lines 751-830: popcount() + popcount_vpopcntdq() + popcount_avx2() -``` - -These operate on `&[u8]` slices. BitVec's `words: [u64; 256]` IS a `&[u8]` slice -via `unsafe { core::slice::from_raw_parts(words.as_ptr() as *const u8, 2048) }`. -The SIMD functions don't know or care about the type. They see bytes. - -**FROM `rustynum-core/src/fingerprint.rs` (401 lines) — copy the struct pattern:** - -```rust -// rustynum already has this. Copy the design: -pub struct Fingerprint { - pub words: [u64; N], -} -// Standard sizes: Fingerprint<256> = 16384 bits -``` - -Consider making BlasGraph's `BitVec` actually BE `Fingerprint<{HD_WORDS}>`. -Or copy the const-generic pattern. Either way, width is compile-time configurable. - -### DO NOT hand-roll SIMD intrinsics. The rustynum implementations handle: -- Scalar tail (when buffer length isn't a multiple of register width) -- Horizontal sum (8 × i64 reduction after AVX-512 accumulation) -- Safety comments for every `unsafe` block -- Feature detection via `is_x86_feature_detected!` (runtime, not compile-time) -- AVX2 Harley-Seal lookup table (correct nibble LUT, not a naive popcount) -- Block processing in AVX2 to avoid u8 saturation - -Hand-rolling these WILL have bugs. The rustynum versions have been tested -across 95 PRs and hundreds of CI runs. Copy them. - -### The function pointer pattern: - -```rust -// From rustynum simd.rs — resolve ONCE, call millions of times: -pub fn select_hamming_fn() -> fn(&[u8], &[u8]) -> u64 { - if is_x86_feature_detected!("avx512vpopcntdq") { return hamming_vpopcntdq_safe; } - if is_x86_feature_detected!("avx2") { return hamming_avx2_safe; } - hamming_scalar_popcnt -} - -// In BitVec, store the resolved function pointer: -use std::sync::OnceLock; -static HAMMING_FN: OnceLock u64> = OnceLock::new(); - -impl BitVec { - pub fn hamming_distance(&self, other: &BitVec) -> u32 { - let f = HAMMING_FN.get_or_init(|| select_hamming_fn()); - let a = unsafe { core::slice::from_raw_parts(self.words.as_ptr() as *const u8, HD_BYTES) }; - let b = unsafe { core::slice::from_raw_parts(other.words.as_ptr() as *const u8, HD_BYTES) }; - f(a, b) as u32 - } -} -// CPUID check happens ONCE. Every subsequent call is a direct function pointer. -// Zero dispatch overhead after first call. -``` - -### Mapping: rustynum → lance-graph - -``` -rustynum function → lance-graph BitVec method -──────────────────────────────────────────────────────── -hamming_distance(&[u8],&[u8]) → BitVec::hamming_distance(&self, &BitVec) -popcount(&[u8]) → BitVec::popcount(&self) -select_hamming_fn() → OnceLock in BitVec module -hamming_vpopcntdq → private, called via fn pointer -hamming_avx2 → private, called via fn pointer -hamming_scalar_popcnt → private, called via fn pointer -Fingerprint → BitVec (or rename BitVec to Fingerprint) -``` - -### What NOT to copy from rustynum: - -``` -× mkl_ffi.rs — MKL is an external dependency, upstream won't accept -× backends/xsmm.rs — LIBXSMM is an external dependency -× backends/gemm.rs — BF16 GEMM not needed for binary Hamming -× bf16_hamming.rs — weighted BF16 Hamming not needed yet -× simd_compat.rs — portable SIMD compat layer, overkill for this -× kernels.rs — JIT scan kernels, ladybug-rs territory -× soaking.rs — i8 accumulator, ladybug-rs territory -``` - -### What TO copy (total ~300 lines of proven, tested SIMD): - -``` -✓ hamming_distance dispatch ~20 lines -✓ hamming_vpopcntdq ~30 lines -✓ hamming_avx2 (Harley-Seal) ~50 lines -✓ hamming_scalar_popcnt ~20 lines -✓ popcount dispatch ~20 lines -✓ popcount_vpopcntdq ~25 lines -✓ popcount_avx2 ~50 lines -✓ popcount_scalar ~10 lines -✓ select_hamming_fn ~15 lines -✓ OnceLock dispatch wrapper ~15 lines -✓ Fingerprint struct ~50 lines (or adapt BitVec) - TOTAL ~305 lines -``` - -This is 300 lines of battle-tested code replacing 145 lines of FNV-1a toy. -The RedisGraph person sees 16K SIMD. They don't see rustynum. They see speed. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/GPU_CPU_SPLIT_ARCHITECTURE.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/GPU_CPU_SPLIT_ARCHITECTURE.md deleted file mode 100644 index 5f286258..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/GPU_CPU_SPLIT_ARCHITECTURE.md +++ /dev/null @@ -1,705 +0,0 @@ -# GPU_CPU_SPLIT_ARCHITECTURE.md - -## The Semantic Revolution: GPU Tensor Cores for NARS Thinking, Not Cosine Searching - -**Date:** March 15, 2026 -**Authors:** Jan Hübener + Claude (Anthropic) -**Status:** Architectural epiphany. The insight that makes GPU acceleration meaningful -for knowledge graphs instead of just fast. - ---- - -## THE INSIGHT IN ONE SENTENCE - -The GPU doesn't do cosine similarity. The GPU does NARS truth revision -on millions of SPO nodes simultaneously using tensor cores that were -designed for BF16 matmul but accidentally work perfectly for tropical -semiring operations on binary knowledge graph edges. - ---- - -## PART 1: WHY CURRENT GPU USE IS WRONG - -### The Industry Pattern (everyone does this) - -``` -CPU: encode text → float embedding (1024D × f32 = 4KB per vector) -GPU: cosine(query, database) = matmul(Q, D^T) / (||Q|| × ||D||) - → O(N) float operations, non-deterministic due to parallel reduction -Result: ranked list of scores [0.92, 0.87, 0.85, ...] - → "these vectors are 0.87 similar" - → meaningless number, no explanation, no provenance - → different result on different GPUs (float non-associativity) - → different result on same GPU different run (thread scheduling) -``` - -### What's Wrong With This - -``` -1. COSINE TELLS YOU HOW MUCH, NOT WHAT OR WHY - "0.87 similar" → which dimensions agree? which disagree? - Nobody knows. The information is destroyed in the dot product. - -2. NON-DETERMINISTIC - (a+b)+c ≠ a+(b+c) in IEEE 754. - GPU parallel reduction changes accumulation order per run. - >90% of parallel BF16 computations diverge from serial (arXiv:2506.09501). - -3. NO LEARNING - The GPU computes similarity. It doesn't LEARN from the computation. - After search, the database is unchanged. No encounter. No memory. - -4. NO STRUCTURE - Cosine on flat vectors. No SPO decomposition. No 2³ projections. - Can't ask "WHO matches but WHAT doesn't?" Flat distance only. -``` - ---- - -## PART 2: OUR GPU USE — THINKING, NOT SEARCHING - -### The Split Architecture - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ CPU (rustynum-core, SIMD AVX-512) │ -│ │ -│ ENCOUNTER LOOP (learning, integer, deterministic): │ -│ encounter_toward() / encounter_away() → i8 accumulator update │ -│ seal verify → Wisdom/Staunen detection │ -│ cascade search → candidate generation (99.7% early rejection) │ -│ BF16 truth assembly → pack projections into 16-bit truth │ -│ │ -│ ORCHESTRATION (graph-flow): │ -│ thinking graph routing │ -│ conditional edges based on cascade bands / seal status │ -│ PlaneContext bridge to Blackboard │ -│ CoW PlaneHandle management │ -│ │ -│ PRODUCTS: candidate pairs + BF16 truth values → push to GPU │ -├─────────────────────────────────────────────────────────────────────┤ -│ LanceDB CACHE (shared, memory-mapped) │ -│ │ -│ Nodes truth table: 1M rows × [node_id, bf16_s, bf16_p, bf16_o] │ -│ = 1M × 8 bytes = 8MB ← fits in GPU L2 cache │ -│ │ -│ Edges truth table: 10M rows × [src, tgt, bf16_truth, projection] │ -│ = 10M × 9 bytes = 90MB ← fits in GPU global memory │ -│ │ -│ Binary planes: 1M × 6KB = 6GB ← stays on CPU (too big for GPU) │ -│ Accessed via cascade on CPU only. Never shipped to GPU. │ -├─────────────────────────────────────────────────────────────────────┤ -│ GPU (tensor cores, BF16 + f32 accumulate) │ -│ │ -│ PARALLEL NARS REVISION (deterministic BF16 → f32): │ -│ Load truth matrix from LanceDB cache │ -│ Tensor core: A(BF16) × B(BF16) + C(f32) → C(f32) │ -│ But A = query truths, B = candidate truths, C = revision accum │ -│ Result: f32 revised truths for ALL candidates simultaneously │ -│ │ -│ PARALLEL BNN FORWARD PASS (binary matrices): │ -│ Load binary weight matrix (16K-bit rows, packed as u32 arrays) │ -│ XOR + popcount per row (GPU has bitwise parallelism) │ -│ Result: hamming distances for ALL rows simultaneously │ -│ │ -│ PARALLEL TROPICAL PATHFINDING: │ -│ Bellman-Ford on BF16 edge weight matrix │ -│ GPU: min(d[i][k] + d[k][j]) for ALL (i,j) simultaneously │ -│ Result: all-pairs shortest tropical paths │ -│ │ -│ PRODUCTS: revised f32 truths → pull to CPU for encounter/seal │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -### What Each Processor Does Best - -``` -OPERATION CPU GPU WHO DOES IT -────────────────────────────────────────────────────────────────────────────────── -encounter() sequential i8 accum N/A CPU (sequential) -cascade search VPOPCNTDQ, early reject N/A CPU (branch-heavy) -seal verify blake3 hash compare N/A CPU (single hash) -BF16 truth assembly integer bit packing N/A CPU (conditional) -graph-flow routing conditional branches N/A CPU (control flow) - -NARS revision (1M) 140ms (sequential) 0.1ms (parallel) GPU (1000x faster) -BNN forward (1M×16K) 2ms (VPOPCNTDQ) 0.5ms (parallel) GPU (4x faster) -Bellman-Ford (1M) seconds (sequential) 10ms (parallel) GPU (100x faster) -truth matrix scan 1ms (SIMD scan) 0.05ms (parallel) GPU (20x faster) -BF16→f32 hydration per-node bit OR batch bit OR either (trivial) -``` - ---- - -## PART 3: GPU TENSOR CORE AS NARS REVISION ENGINE - -### How Tensor Cores Actually Work - -``` -NVIDIA TENSOR CORE (designed for neural network training): - - D = A × B + C - - where A is BF16 matrix, B is BF16 matrix, C is f32 accumulator - - Per clock cycle on H100: - 16×16 BF16 matrix multiply → 512 multiply-accumulate operations - Result accumulated in f32 → full precision accumulation - - THROUGHPUT: 1000 TFLOPS (BF16 tensor core) on H100 -``` - -### How We Repurpose It for NARS - -``` -NARS REVISION RULE: - Given two independent evidence sources and : - - f_new = (f1*c1*(1-c2) + f2*c2*(1-c1)) / (c1*(1-c2) + c2*(1-c1)) - c_new = (c1*(1-c2) + c2*(1-c1)) / (c1*(1-c2) + c2*(1-c1) + (1-c1)*(1-c2)) - - This has multiply-accumulate structure: - f1*c1 = BF16 × BF16 → f32 accumulator - f2*c2 = BF16 × BF16 → f32 accumulator - Sum of products = the tensor core's NATIVE operation - -MAPPING TO TENSOR CORE: - Matrix A (query truths): [f1, c1, 1-c1, f1*c1, ...] × N_queries (BF16) - Matrix B (candidate truths): [f2, c2, 1-c2, f2*c2, ...] × N_candidates (BF16) - Matrix C (accumulator): revision intermediate results (f32) - - D = A × B + C - = all query-candidate revision terms computed in ONE tensor core call - - For N_queries=1000, N_candidates=1000: - Standard (CPU, sequential): 1000 × 1000 × 4 multiply-adds = 4M ops × 5ns = 20ms - Tensor core (GPU, parallel): 1000 × 1000 matrix in ONE kernel launch = 0.01ms - - 2000x speedup. And DETERMINISTIC because: - - BF16 multiplication is deterministic (one rounding step) - - f32 accumulation order is FIXED by the tensor core layout - - Same input → same matmul → same output → always -``` - -### The Batch NARS Revision Kernel - -```rust -/// GPU kernel: revise ALL edge truths in the graph simultaneously. -/// Uses tensor cores for BF16 multiply-accumulate. -/// -/// Input: truth_matrix_A (N × 4, BF16) = [freq, conf, 1-conf, freq*conf] per node -/// truth_matrix_B (N × 4, BF16) = same layout, transposed -/// accum (N × N, f32) = previous revision state -/// Output: revised_truths (N × N, f32) = all-pairs revised truth values -/// -/// One kernel call revises ALL pairs. O(N²) work, O(1) GPU time. -fn nars_revision_gpu( - truths_a: &GpuBf16Matrix, // N × 4 - truths_b: &GpuBf16Matrix, // N × 4, transposed - accum: &mut GpuF32Matrix, // N × N -) { - // This IS a tensor core matmul: D = A × B^T + C - // But the "matrix multiply" IS NARS revision. - // Each element D[i,j] = sum of products of truth components. - // The sum of products IS the revision formula's numerator. - - gpu_bf16_matmul(truths_a, truths_b, accum); - - // Post-process: divide by denominator (element-wise on f32) - // This is cheap: N² element-wise divisions on GPU. - gpu_elementwise_div(accum, denominators); -} -``` - ---- - -## PART 4: GPU AS BNN FORWARD PASS ENGINE - -### Binary Matrix on GPU - -``` -BINARY WEIGHT MATRIX (1M nodes × 16K bits): - Stored as: 1M × 256 × u64 = 1M × 2KB = 2GB - - TOO BIG for GPU global memory (typical 24-80GB, but leaves no room - for other data). BUT: - - The cascade on CPU already rejects 99.7%. - Only ~3000 candidates survive to the GPU stage. - - CANDIDATE BINARY MATRIX (3K nodes × 16K bits): - 3K × 2KB = 6MB ← fits in GPU L2 cache - - QUERY BINARY VECTOR (1 × 16K bits): - 1 × 2KB ← trivial -``` - -### GPU XOR+Popcount - -``` -GPU BNN FORWARD PASS: - For each of 3000 candidate rows: - XOR(query[16K], candidate[16K]) → 16K-bit result - popcount(result) → hamming distance - - GPU processes 3000 rows in parallel. - Each row: 256 × u64 XOR + 256 × popcount64 = 512 operations - Total: 3000 × 512 = 1.5M operations - - GPU at 1 TFLOPS bitwise: ~0.002ms - CPU at 100 GFLOPS bitwise: ~0.015ms - - For 3000 candidates: GPU is only ~7x faster (not worth the transfer). - - BUT for 100K+ candidates (before cascade, or with weaker pre-filter): - GPU at 100K × 512 = 51M ops: ~0.05ms - CPU at 100K: ~5ms - 100x speedup. Worth the transfer. -``` - -### When to Use GPU for BNN - -``` -DECISION: - candidates < 10K → CPU (transfer overhead dominates) - candidates 10K-1M → GPU (significant speedup, data fits GPU memory) - candidates > 1M → CPU cascade first, then GPU on survivors - - The cascade runs on CPU (branch-heavy, early exit). - The BNN matrix runs on GPU (data-parallel, no branches). - - CPU cascade: 1M → 3K survivors (2ms) - GPU BNN on 3K: hamming matrix (0.002ms) - Total: 2.002ms hybrid vs 2ms CPU-only - - NOT WORTH IT for cascade-filtered results. - - WORTH IT for: - - Bellman-Ford: ALL edges processed, no pre-filter, O(N²) - - NARS revision: ALL pairs revised, O(N²), tensor core accelerated - - Message passing: ALL neighbors aggregated per round, O(edges) - - Community detection: ALL pairs compared, O(N²) -``` - ---- - -## PART 5: THE O(1) BF16 TRUTH LOOKUP - -### LanceDB as GPU-Accessible Truth Cache - -``` -LANCEDB TRUTH CACHE: - Table: spo_truths - Columns: [node_id (u32), bf16_s (u16), bf16_p (u16), bf16_o (u16)] - Rows: 1M - Size: 1M × 8 bytes = 8MB - - This table is SMALL. It fits in: - CPU L3 cache (8MB): yes - GPU L2 cache (varies, typically 6-50MB): yes - - EVERY truth lookup is O(1): truths[node_id] - - The truth cache is WRITTEN by CPU encounter loop: - After cascade → projections → BF16 assembly → write to cache - - The truth cache is READ by GPU revision kernel: - Load entire 8MB table to GPU. Keep resident. - Tensor core reads directly. No PCIe transfer per query. -``` - -### The CAM Index as GPU Truth Matrix - -``` -CONTENT-ADDRESSABLE MEMORY: - "Given a truth pattern, which nodes match?" - - On CPU: scan 1M BF16 values with SIMD (32 per instruction) = 31K instructions - On GPU: scan 1M BF16 values in parallel = 1 kernel launch - - The truth cache IS the CAM. Each row IS an address. - The BF16 value IS the content. - - QUERY: "find all nodes where bf16_p exponent has bits 2 and 5 set" - = "find all nodes where predicate projection matches _P_ and _PO" - - GPU: - load bf16_p column (1M × 2 bytes = 2MB) - extract exponent: shift right 7 (parallel, all 1M) - mask: AND with 0b00100100 (parallel, all 1M) - compare: equals 0b00100100 (parallel, all 1M) - compact: stream compaction to gather matching IDs - - Result: list of matching node IDs in ~0.01ms - - This IS a Cypher WHERE clause executed on GPU: - MATCH (n) WHERE n.predicate_projection HAS (_P_ AND _PO) -``` - -### The 90° Orthogonal Vector - -``` -JAN'S INSIGHT: "One 90° vector across all tables and CAM" - -THE VECTOR: the BF16 exponent encodes WHICH projections hold. -8 bits = 8 dimensions (one per 2³ SPO projection). -This vector is ORTHOGONAL to the content dimensions (mantissa). - -ACROSS ALL TABLES: - spo_truths: the exponent column IS the projection vector - edges: the projection byte IS the same vector - nodes: the truth() method produces the same vector - - ONE vector type. THREE tables. SAME semantics. - -GPU PROCESSES THIS VECTOR: - Load exponent columns from all three tables. - Tensor core: truth_matrix × projection_vector → relevance_f32 - - The result: for each node, how relevant is it to this projection pattern? - Not cosine similarity. STRUCTURAL RELEVANCE. - "How well does this node's SPO structure match the query pattern?" -``` - ---- - -## PART 6: PARALLEL TROPICAL PATHFINDING ON GPU - -### Bellman-Ford as Matrix Operation - -``` -BELLMAN-FORD (single source shortest paths): - d[v] = min_u (d[u] + w(u,v)) for all edges (u,v) - Repeat V-1 times. - -AS MATRIX OPERATION: - d = A ⊕.⊗ d - where ⊕ = min, ⊗ = + (tropical semiring) - - This IS matrix-vector multiply in the tropical semiring. - On GPU: SAME tensor core, different interpretation. - - BUT: tensor cores do (×, +). We need (min, +). - - WORKAROUND 1: log-space transformation - min(a, b) = -max(-a, -b) = -log(exp(-a) + exp(-b)) ≈ for large values - Approximate tropical matmul with standard matmul in log space. - Error bounded by O(exp(-|a-b|)). Exact when one value dominates. - - WORKAROUND 2: custom CUDA kernel (not tensor core) - GPU threads do min+add directly. Not as fast as tensor core but - still 1000x parallel. 1M nodes × 1M edges = 1T operations. - GPU at 10 TFLOPS: ~0.1 seconds for full all-pairs. - CPU: ~100 seconds. 1000x speedup. - - WORKAROUND 3: SIMD² hardware (future) - Native tropical semiring in tensor-core-like hardware. - 5% area overhead. 38x speedup. When it ships, our code is ready. -``` - -### Floyd-Warshall as Matrix Multiply - -``` -FLOYD-WARSHALL: - for k: D = min(D, D[*,k] + D[k,*]) - - Each iteration k: two matrix operations (broadcast row k + column k, - then element-wise min with current D). - - GPU: each iteration is O(N²) parallel operations. - N iterations. Total: O(N³) but GPU does O(N²) per iteration in one launch. - - For N=10K: 10K iterations × 100M parallel ops = 1T total. - GPU: ~1 second for all-pairs shortest Hamming paths on 10K nodes. - CPU: ~1000 seconds. - - This gives us the COMPLETE VALUE FUNCTION for the RL agent. - "How far is EVERY node from EVERY other node through Hamming paths?" - The full landscape of analogical relationships. In 1 second. -``` - ---- - -## PART 7: THE DETERMINISM GUARANTEE - -### Why GPU Tensor Core Matmul IS Deterministic for Our Use - -``` -STANDARD GPU MATMUL (non-deterministic): - Problem: parallel reduction changes accumulation order per thread block. - (a+b)+c ≠ a+(b+c) in float. Different order → different result. - -OUR GPU MATMUL (deterministic): - 1. BF16 × BF16 → f32: the MULTIPLICATION is deterministic. - BF16 multiplication has exactly one rounding step (RNE). - Same BF16 inputs → same BF16 product → always. - - 2. f32 accumulation: if the ACCUMULATION ORDER IS FIXED, - the result is deterministic. - - 3. Tensor core layout FIXES the accumulation order: - 16×16 tile. The hardware always processes elements in the same order - within a tile. Same input → same tile computation → same output. - - 4. Inter-tile accumulation: CUBLAS in deterministic mode - (CUBLAS_MATH_DISALLOW_REDUCED_PRECISION_REDUCTION) - forces a fixed reduction tree. Slower but deterministic. - - 5. Our truth values are SMALL matrices (N × 4): - The "4" dimension (freq, conf, 1-conf, freq*conf) fits in ONE tile. - No inter-tile accumulation needed for the inner dimension. - Only the N × N outer product needs fixed ordering. - - RESULT: deterministic f32 output from tensor core matmul - on our specifically-structured BF16 truth matrices. - Not because GPUs are deterministic in general. - Because OUR matrix structure fits the determinism constraints. -``` - -### The Proof - -``` -CLAIM: For matrices A(N×4, BF16) and B(4×N, BF16), the tensor core -output D(N×N, f32) is deterministic across runs on the same GPU. - -PROOF SKETCH: - 1. Inner dimension = 4. One tile handles the full inner dimension. - 2. Within one tile: hardware accumulation order is fixed (by design). - 3. Each output element D[i,j] = sum of 4 products (fits in one tile). - 4. No inter-tile reduction for the inner dimension. - 5. Outer dimensions (N×N) are independent (no accumulation across them). - 6. Therefore: same input → same hardware path → same output. - - QED: Our NARS revision on tensor cores is deterministic. - -CAVEAT: This holds for inner dimension ≤ tile size (16 for BF16). - Our inner dimension is 4. Safe. - If we ever need inner dimension > 16: use deterministic CUBLAS mode. -``` - ---- - -## PART 8: THE SEMANTIC REVOLUTION - -### What Cosine Tells You vs What We Tell You - -``` -COSINE: similarity("king", "queen") = 0.87 - → "these embeddings point in similar directions" - → no explanation. no structure. no provenance. - -US: truth("king", "queen") = f32 with bit-level provenance: - bit 31 (sign): 0 = king CAUSES queen relationship (direction) - bits 30-24 (exp): 01100010 = S matches, P matches, SP matches, SPO matches - → "they share subject-type AND predicate-type AND full structure" - bits 23-16 (man): 0001100 = finest distance 12 on best projection (P) - → "the predicate match is very tight (12 out of 16384 bits differ)" - bits 15-0 (path): 1011010011100101 = tree path from 16 learning encounters - → "this truth was learned through 16 observations, branching - right at encounter 3 (Staunen: new evidence contradicted), - left at encounter 7 (Wisdom: evidence confirmed), ..." - - READING THE f32: "king and queen share subject and predicate structure with - very high precision (12-bit Hamming). The relationship was learned through - 16 encounters including one surprise event at step 3 that was resolved by - step 7. The king is the causal agent in this relationship." - - EVERY BIT is traceable. The f32 IS the explanation. Not a summary OF - the explanation. The explanation ITSELF, compressed into 32 bits. -``` - -### What the GPU Enables - -``` -INDUSTRY: - GPU computes: 1M cosine similarities per query - Result: ranked list of meaningless scores - Learning: none (database unchanged after search) - Determinism: no (>90% of BF16 computations diverge) - Structure: none (flat dot product) - Speed: ~1ms for 1M cosines on A100 - -US: - CPU computes: cascade → 3K survivors (2ms) - GPU computes: 3K × 3K NARS revisions simultaneously (0.01ms) - GPU computes: 3K × 3K tropical pathfinding (0.1ms) - CPU computes: encounter() updates for confirmed matches (0.5ms) - Result: revised BF16 truth values with full structural provenance - Learning: every query updates the graph (encounter = INSERT + TRAIN) - Determinism: yes (BF16 tensor core on 4-wide inner dimension) - Structure: 2³ SPO decomposition, 7 projection bands - Speed: ~2.6ms for 1M candidates (CPU cascade) + 0.11ms (GPU revision) -``` - ---- - -## PART 9: JIT-COMPILED THINKING LAYERS - -### JIT as Method Objects in LangGraph - -```rust -// Each thinking operation can be JIT-compiled by Cranelift (jitson) -// for the HOT PATH, and interpreted via graph-flow for the COLD PATH. - -trait CogOp: Task + JitCompilable { - /// Graph-flow Task interface (cold path, orchestrated) - async fn run(&self, ctx: Context) -> TaskResult; - - /// JIT-compiled kernel (hot path, no orchestration overhead) - fn jit_kernel(&self) -> Option; - - /// Whether this op should be JIT'd based on call frequency - fn hot_count(&self) -> u64; -} - -// The FlowRunner decides: JIT or interpret? -impl FlowRunner { - async fn run_task(&self, task: &dyn CogOp, ctx: Context) -> TaskResult { - if task.hot_count() > JIT_THRESHOLD { - if let Some(kernel) = task.jit_kernel() { - // Hot path: call JIT'd native function directly - // No graph-flow overhead, no Context serialization - // Just raw SIMD on Blackboard Planes - return kernel.call_with_blackboard(ctx.blackboard()); - } - } - // Cold path: full graph-flow orchestration - task.run(ctx).await - } -} -``` - -### Cognitive Operations as Language Primitives - -```rust -/// The cognitive language: each operation is a first-class object -/// that can be orchestrated (graph-flow), JIT-compiled (Cranelift), -/// GPU-accelerated (tensor core), or interpreted (fallback). - -// BNN operations (binary neural network primitives) -bnn!(forward(weights: &Plane, input: &Plane) -> u32); // XOR+popcount -bnn!(backward(weights: &mut Plane, error: &Plane, lr: i8)); // encounter - -// GNN operations (graph neural network primitives) -gnn!(message_pass(graph: &SpoGraph, rounds: usize)); // K-round encounter -gnn!(aggregate(neighbors: &[&Plane]) -> Plane); // bundle - -// GQL / Cypher operations (graph query primitives) -gql!(match_pattern(graph: &SpoGraph, pattern: &CypherAST) -> Vec); -gql!(shortest_path(graph: &SpoGraph, from: u32, to: u32) -> Vec); - -// GraphBLAS operations (semiring algebra primitives) -graphblas!(mxv(matrix: &GrBMatrix, vector: &GrBVector, semiring: HdrSemiring) -> GrBVector); -graphblas!(mxm(a: &GrBMatrix, b: &GrBMatrix, semiring: HdrSemiring) -> GrBMatrix); - -// SPO operations (triple store primitives) -spo!(project(node: &Node, mask: Mask) -> Distance); -spo!(project_all(a: &Node, b: &Node) -> [Distance; 7]); -spo!(encode_bf16(bands: &[Band; 7], finest: u32, dir: CausalityDirection) -> u16); - -// Qualia operations (experiential primitives) -qualia!(compress(values: &[f32; 16]) -> PackedQualia); -qualia!(hydrate(packed: &PackedQualia) -> [f32; 16]); -qualia!(dot(a: &PackedQualia, b: &PackedQualia) -> f32); - -// 2³ Reasoning operations (structural decomposition) -reasoning!(decompose_2_3(a: &Node, b: &Node) -> [Band; 7]); // all projections -reasoning!(credit_assign(node: &mut Node, exponent: u8)); // RL gradient -reasoning!(tropical_revise(a: u16, b: u16) -> u16); // NARS on exponents - -// NARS operations (truth value management) -nars!(revise(a: &NarsTruth, b: &NarsTruth) -> NarsTruth); -nars!(deduction(premise: &NarsTruth, conclusion: &NarsTruth) -> NarsTruth); -nars!(abduction(observation: &NarsTruth, hypothesis: &NarsTruth) -> NarsTruth); - -// Each macro generates: -// 1. A Task impl (for graph-flow orchestration) -// 2. A JIT kernel (for Cranelift hot-path compilation) -// 3. A GPU kernel descriptor (for tensor core dispatch when beneficial) -// 4. A PET scan trace entry (for debugging/visualization) -// 5. A PlaneContext bridge (for zero-copy Blackboard access) -``` - ---- - -## PART 10: IMPLEMENTATION ROADMAP - -### Phase 1: CPU-Only (current + simd_clean.rs refactor) -``` -WHAT: all operations on CPU with SIMD dispatch -WHEN: now -PERFORMANCE: 2ms for 1M cascade, 2.8μs per RL step -DETERMINISM: yes (integer-only RL loop) -``` - -### Phase 2: LanceDB Truth Cache -``` -WHAT: BF16 truth values cached in LanceDB - O(1) lookup by node_id - Cascade writes, query evaluator reads -WHEN: after Session I (BF16 truth assembly) -PERFORMANCE: 1ms for truth scan of 1M nodes (SIMD on BF16 column) -DETERMINISM: yes (BF16 is exact for distances 0-255) -``` - -### Phase 3: GPU NARS Revision -``` -WHAT: tensor core BF16 matmul for batch NARS revision - N × 4 BF16 truth matrices on GPU - deterministic f32 output -WHEN: after Phase 2 + GPU infra (cuBLAS or wgpu) -PERFORMANCE: 0.01ms for 3K × 3K revision (vs 20ms CPU) -DETERMINISM: yes (inner dim 4 ≤ tile size 16, fixed accumulation) -DEPENDENCY: GPU with BF16 tensor cores (any modern NVIDIA/AMD) -``` - -### Phase 4: GPU Tropical Pathfinding -``` -WHAT: Bellman-Ford/Floyd-Warshall on BF16 edge weight matrix - tropical semiring on GPU (custom kernel or log-space matmul) -WHEN: after Phase 3 -PERFORMANCE: 1 second for 10K × 10K all-pairs (vs 1000s CPU) -DETERMINISM: yes (if using fixed reduction order) -``` - -### Phase 5: JIT Cognitive Primitives -``` -WHAT: Cranelift JIT for hot-path thinking operations - graph-flow orchestration for cold path - automatic hot-path detection (call count threshold) -WHEN: after Phase 2 (the orchestration must be clean first) -PERFORMANCE: eliminate graph-flow overhead on hot tasks -``` - -### Phase 6: Cognitive Language -``` -WHAT: think! macro that compiles to execution graphs - bnn!, gnn!, gql!, spo!, qualia!, reasoning!, nars! macros - Agent card YAML → GraphBuilder compiler -WHEN: after Phase 5 (needs JIT + orchestration stable) -IMPACT: thinking programs written in domain primitives -``` - ---- - -## PART 11: WHAT THIS REPLACES IN THE MARKET - -``` -TOOL WHAT IT DOES WHAT WE DO INSTEAD -────────────────────────────────────────────────────────────── -Pinecone/Weaviate GPU cosine search GPU NARS revision + cascade search -LangChain LLM orchestration glue graph-flow + PlaneContext + Lance -CrewAI multi-agent chat Tasks in thinking graph with FanOut -Neo4j pointer-chase graph semiring mxv on binary planes -FalkorDB GraphBLAS on scalars GraphBLAS on binary planes + BF16 -LangGraph workflow orchestration graph-flow with cognitive primitives -Semantic Kernel AI tool integration MCP ingest → encounter → cascade -PyTorch Geometric GPU float GNN GPU binary GNN (XOR+popcount) -FAISS GPU ANN search cascade + multi-index hashing -DGL GPU GNN framework encounter-based message passing -Kuzu (dead) embedded graph DB lance-graph (embedded, Cypher, learning) -``` - -None of them do GPU THINKING. They all do GPU SEARCHING. -We search on CPU (cascade, cheap). We THINK on GPU (revision, expensive). -The GPU is wasted on similarity search. It should be doing NARS. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/INTEGRATION_SESSIONS.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/INTEGRATION_SESSIONS.md deleted file mode 100644 index d7701610..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/INTEGRATION_SESSIONS.md +++ /dev/null @@ -1,467 +0,0 @@ -# INTEGRATION_SESSIONS.md - -## Session Prompts: From Inventory to Wired System - -Each session is self-contained with exact file paths, function signatures, -test criteria, and dependency tracking. - ---- - -## SESSION G: SIMD Clean Refactor - -**Prereqs:** None. First to execute. -**Repo:** rustynum -**Branch:** claude/simd-clean - -### Task -Replace `rustynum-core/src/simd.rs` (2435 lines, 107 detections) with -`simd_clean.rs` (234 lines, LazyLock, dispatch! macro). - -### Exact Steps -1. Copy `.claude/simd_clean.rs` to `rustynum-core/src/simd.rs` -2. Verify all `pub fn` signatures match existing exports -3. Ensure `simd_avx512.rs` has all functions the dispatch calls -4. Ensure `simd_avx2.rs` has all functions the dispatch calls -5. Ensure `scalar_fns.rs` has all functions the dispatch calls -6. Fill gaps: element-wise ops missing from scalar_fns.rs -7. Wire `scalar_fns` into `lib.rs` (`pub mod scalar_fns;`) -8. Add `#[target_feature(enable = "avx512f")]` to every fn in simd_avx512.rs -9. Add `#[target_feature(enable = "avx2,fma")]` to every fn in simd_avx2.rs -10. Remove unnecessary `unsafe` blocks around safe intrinsics (Rust 1.94) -11. Run `cargo test --workspace` — must pass 1543+ tests -12. Run `cargo clippy --workspace -- -D warnings` -13. Run benchmarks: sdot, hamming, plane_distance — compare to PR #102 baseline - -### Success Criteria -- simd.rs < 250 lines -- `cargo test` passes (all platforms) -- sdot benchmark ≤ PR #100 baseline (regression from PR #102 fixed) -- No `is_x86_feature_detected!` outside of simd.rs - -### Key File -`.claude/simd_clean.rs` — the replacement file (on main) - ---- - -## SESSION H: Plane Evolution (encounter_toward, encounter_away) - -**Prereqs:** None (independent of Session G) -**Repo:** rustynum -**Branch:** claude/plane-evolution - -### Task -Add directional encounter methods to Plane and Node. -These are the INTEGER equivalents of DreamerV3's STE gradient. - -### Exact Changes - -In `rustynum-core/src/plane.rs`, add: - -```rust -/// Encounter toward another plane's bit pattern. -/// For each bit in other.bits(): if set, push acc[k] toward +1; if clear, toward -1. -/// This IS the DreamerV3 STE gradient expressed as integer accumulation. -pub fn encounter_toward(&mut self, other: &mut Plane) { - let other_bits = other.bits_bytes_ref(); - for k in 0..Self::BITS { - let byte_idx = k / 8; - let bit_idx = k % 8; - if other_bits[byte_idx] & (1 << bit_idx) != 0 { - self.acc.values[k] = self.acc.values[k].saturating_add(1); - } else { - self.acc.values[k] = self.acc.values[k].saturating_sub(1); - } - } - self.dirty = true; - self.encounters += 1; -} - -/// Encounter AWAY from another plane's bit pattern (repulsive). -/// Opposite direction: if other bit set, push toward -1; if clear, toward +1. -pub fn encounter_away(&mut self, other: &mut Plane) { - let other_bits = other.bits_bytes_ref(); - for k in 0..Self::BITS { - let byte_idx = k / 8; - let bit_idx = k % 8; - if other_bits[byte_idx] & (1 << bit_idx) != 0 { - self.acc.values[k] = self.acc.values[k].saturating_sub(1); - } else { - self.acc.values[k] = self.acc.values[k].saturating_add(1); - } - } - self.dirty = true; - self.encounters += 1; -} - -/// RL-weighted encounter: reward_sign = +1 for reward, -1 for punishment. -/// Positive reward: encounter_toward. Negative reward: encounter_away. -pub fn reward_encounter(&mut self, evidence: &mut Plane, reward_sign: i8) { - if reward_sign >= 0 { - self.encounter_toward(evidence); - } else { - self.encounter_away(evidence); - } -} -``` - -In `rustynum-core/src/node.rs`, add: - -```rust -/// Compute all 7 non-null SPO projections at once. -/// Returns distances for [S__, _P_, __O, SP_, S_O, _PO, SPO]. -pub fn project_all(&mut self, other: &mut Node) -> [Distance; 7] { - let d_s = self.s.distance(&mut other.s); - let d_p = self.p.distance(&mut other.p); - let d_o = self.o.distance(&mut other.o); - - // Compound projections combine individual distances - // (details depend on Distance enum implementation) - [ - self.distance(other, S__), - self.distance(other, _P_), - self.distance(other, __O), - self.distance(other, SP_), - self.distance(other, S_O), - self.distance(other, _PO), - self.distance(other, SPO), - ] -} - -/// RL credit assignment: given BF16 exponent bits, -/// encounter toward matching projections, away from failing ones. -pub fn credit_assignment(&mut self, other: &mut Node, exponent: u8) { - // Bit 1 = S__ matched - if exponent & 0b00000010 != 0 { - self.s.encounter_toward(&mut other.s); - } else { - self.s.encounter_away(&mut other.s); - } - // Bit 2 = _P_ matched - if exponent & 0b00000100 != 0 { - self.p.encounter_toward(&mut other.p); - } else { - self.p.encounter_away(&mut other.p); - } - // Bit 3 = __O matched - if exponent & 0b00001000 != 0 { - self.o.encounter_toward(&mut other.o); - } else { - self.o.encounter_away(&mut other.o); - } -} -``` - -### Tests -```rust -#[test] -fn encounter_toward_converges() { - let mut a = Plane::new(); - let mut b = Plane::random(42); - // After 10 encounters toward b, a.bits should approach b.bits - for _ in 0..10 { a.encounter_toward(&mut b); } - let d = a.distance(&mut b); - assert!(d.raw().unwrap() < PLANE_BITS as u32 / 4); // < 25% disagreement -} - -#[test] -fn encounter_away_diverges() { - let mut a = Plane::random(42); - let mut b = a.clone(); - // After encountering AWAY, distance should increase - let d_before = a.distance(&mut b).raw().unwrap(); - for _ in 0..10 { a.encounter_away(&mut b); } - let d_after = a.distance(&mut b).raw().unwrap(); - assert!(d_after > d_before); -} - -#[test] -fn credit_assignment_selective() { - let mut a = Node::random(1); - let mut b = Node::random(2); - let d_s_before = a.s.distance(&mut b.s).raw().unwrap(); - let d_p_before = a.p.distance(&mut b.p).raw().unwrap(); - - // Exponent says P matched (bit 2), S didn't (bit 1 = 0) - a.credit_assignment(&mut b, 0b00000100); - - let d_s_after = a.s.distance(&mut b.s).raw().unwrap(); - let d_p_after = a.p.distance(&mut b.p).raw().unwrap(); - - // S should diverge (punished), P should converge (rewarded) - assert!(d_s_after >= d_s_before); // may equal if already at boundary - assert!(d_p_after <= d_p_before); -} -``` - ---- - -## SESSION I: BF16 Truth Assembly - -**Prereqs:** Session H (project_all, credit_assignment) -**Repo:** rustynum -**Branch:** claude/bf16-truth - -### Task -Build the BF16 value from 2³ projections. Integer only. No float arithmetic. - -### Exact Changes - -In `rustynum-core/src/bf16_hamming.rs`, add: - -```rust -/// Assemble BF16 truth value from 7 SPO projections. -/// sign = causality direction (0 = causing, 1 = caused) -/// exponent = which projections are in Foveal or Near band -/// mantissa = finest distance of best matching projection, normalized to 7 bits -pub fn bf16_from_projections( - projections: &[Band; 7], - finest_distance: u32, - band_foveal_max: u32, - causality: CausalityDirection, -) -> u16 { - let sign: u16 = match causality { - CausalityDirection::Causing => 0, - CausalityDirection::Experiencing => 1, - }; - - let mut exponent: u16 = 0; - for (i, band) in projections.iter().enumerate() { - match band { - Band::Foveal | Band::Near => exponent |= 1 << (i + 1), - _ => {} - } - } - - // Mantissa: finest_distance normalized to 7 bits - let mantissa: u16 = if band_foveal_max > 0 { - ((finest_distance as u64 * 127) / band_foveal_max as u64).min(127) as u16 - } else { - 0 - }; - - (sign << 15) | (exponent << 7) | mantissa -} - -/// Extract 8-bit exponent from BF16 value. Integer shift only. -#[inline(always)] -pub fn bf16_extract_exponent(bf16: u16) -> u8 { - ((bf16 >> 7) & 0xFF) as u8 -} - -/// Extract sign bit (causality direction). -#[inline(always)] -pub fn bf16_extract_sign(bf16: u16) -> CausalityDirection { - if bf16 & 0x8000 != 0 { - CausalityDirection::Experiencing - } else { - CausalityDirection::Causing - } -} - -/// Extract 7-bit mantissa (finest distance). -#[inline(always)] -pub fn bf16_extract_mantissa(bf16: u16) -> u8 { - (bf16 & 0x7F) as u8 -} -``` - -### NarsTruth as BF16 Pair (32 bits) - -In `rustynum-core/src/causality.rs`, add: - -```rust -/// NARS truth value packed as two BF16 values in 32 bits. -/// Upper 16 bits: BF16 frequency. Lower 16 bits: BF16 confidence. -/// Fits in one f32 slot. Compatible with VDPBF16PS for revision. -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct PackedNarsTruth(pub u32); - -impl PackedNarsTruth { - pub fn new(frequency: f32, confidence: f32) -> Self { - let f_bits = ((frequency.to_bits() >> 16) & 0xFFFF) as u16; // truncate to BF16 - let c_bits = ((confidence.to_bits() >> 16) & 0xFFFF) as u16; - Self(((f_bits as u32) << 16) | (c_bits as u32)) - } - - pub fn frequency_f32(&self) -> f32 { - f32::from_bits(((self.0 >> 16) as u32) << 16) - } - - pub fn confidence_f32(&self) -> f32 { - f32::from_bits((self.0 & 0xFFFF) << 16) - } - - /// Convert from existing NarsTruthValue - pub fn from_truth(t: &NarsTruthValue) -> Self { - Self::new(t.frequency, t.confidence) - } -} -``` - ---- - -## SESSION J: PackedDatabase (GEMM Panel Packing for Cascades) - -**Prereqs:** None (independent) -**Repo:** rustynum -**Branch:** claude/packed-database - -### Task -Implement stroke-aligned database layout, analogous to GEMM panel packing -(siboehm article). Candidate data stored contiguously per stroke region -for sequential streaming instead of scattered per-candidate access. - -### Key Reference -`.claude/CASCADE_TETRIS.md` — full spec with pseudocode -`.claude/L1_CACHE_BOUNDARY.md` — L1 constraints - -### Implementation in rustynum-core/src/hdr.rs (or new file packed_db.rs) - -```rust -pub struct PackedDatabase { - stroke1: Vec, // all candidates' [0..128] contiguous - stroke2: Vec, // all candidates' [128..512] contiguous - stroke3: Vec, // all candidates' [512..2048] contiguous - n_candidates: usize, - bytes_per_candidate: usize, -} - -impl PackedDatabase { - pub fn pack(candidates: &[&[u8]]) -> Self { ... } - - pub fn cascade_scan( - &self, - query: &[u8], - bands: &[u32; 4], - k: usize, - ) -> Vec<(usize, u32)> { ... } -} -``` - -### Benchmark -Compare `Cascade::query()` vs `PackedDatabase::cascade_scan()` on 100K, 1M candidates. -Target: 2-3x improvement from sequential vs scattered access. - ---- - -## SESSION K: Message Passing (Binary GNN) - -**Prereqs:** Session H (encounter_toward/away) -**Repo:** rustynum (new file: rustynum-core/src/message_pass.rs) -**Branch:** claude/message-passing - -### Task -Implement K-round binary GNN message passing using encounter() as aggregation. -This is the BitGNN equivalent but deterministic and CPU-only. - -### Key Reference -`.claude/RESEARCH_THREADS.md` Thread 4 — BitGNN connection - -### Implementation - -```rust -pub struct SpoGraph { - pub nodes: Vec, - pub edges: Vec, // compact adjacency -} - -pub struct Edge { - pub source: u32, - pub target: u32, - pub truth: PackedNarsTruth, - pub projection: u8, // which SPO projections match (BF16 exponent) -} - -impl SpoGraph { - pub fn message_passing(&mut self, rounds: usize) { - for _ in 0..rounds { - // Collect messages, apply encounters - // Each node's planes evolve based on neighbor influence - // Weighted by edge truth confidence - } - } -} -``` - ---- - -## SESSION L: Wiring the Full Pipeline - -**Prereqs:** Sessions H, I, J, K -**Repo:** rustynum -**Branch:** claude/full-pipeline - -### Task -Wire: cascade → projections → BF16 → encounter → NARS - -### Implementation (new file: rustynum-core/src/rl_step.rs) - -```rust -/// One complete RL step. Deterministic. Integer only (except f32 hydration). -pub fn rl_step( - query_node: &mut Node, - candidate_node: &mut Node, - cascade: &Cascade, -) -> (u16, PackedNarsTruth) { - // 1. Compute 7 projections - let projections = query_node.project_all(candidate_node); - - // 2. Band classify each projection - let bands = projections.map(|d| cascade.expose(d.raw().unwrap_or(u32::MAX))); - - // 3. Assemble BF16 truth - let bf16 = bf16_from_projections(&bands, finest, foveal_max, direction); - - // 4. Credit assignment (RL gradient) - let exponent = bf16_extract_exponent(bf16); - query_node.credit_assignment(candidate_node, exponent); - - // 5. NARS truth from plane truths - let truth = PackedNarsTruth::from_truth(&query_node.truth(SPO).into()); - - (bf16, truth) -} -``` - -### End-to-End Test -```rust -#[test] -fn rl_converges_on_known_pattern() { - let mut query = Node::random(1); - let mut candidate = query.clone(); // identical = should converge to Foveal - let cascade = Cascade::calibrate(&[0, 100, 200, 500, 1000], 2048); - - for _ in 0..100 { - let (bf16, truth) = rl_step(&mut query, &mut candidate, &cascade); - // Should converge: exponent all 1s, mantissa → 0, truth → high - } - - let exp = bf16_extract_exponent(bf16); - assert_eq!(exp & 0b11111110, 0b11111110); // all projections match -} -``` - ---- - -## TOTAL EFFORT ESTIMATE - -``` -SESSION LINES DAYS DEPENDENCIES -G (simd) ~100 1 none -H (plane) ~200 1 none -I (bf16) ~200 1 H -J (packed) ~300 1 none -K (msgpass) ~300 2 H -L (wire) ~200 1 H, I - -Total: ~1300 ~7 days -``` - -Each session can run as a focused CC session with its own branch. -Sessions G, H, J are independent — can run in parallel. -Sessions I, K depend on H. -Session L depends on H + I. - -The result: the first fully binary RL + GNN + semiring graph system. -Deterministic. CPU-only. ~1300 lines of new code. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/INVENTORY_MAP.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/INVENTORY_MAP.md deleted file mode 100644 index 354aa3b3..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/INVENTORY_MAP.md +++ /dev/null @@ -1,437 +0,0 @@ -# INVENTORY_MAP.md - -## Complete Inventory: What Exists, What's Missing, What Connects - -**Date:** March 15, 2026 -**Repos:** rustynum (AdaWorldAPI/rustynum), lance-graph (AdaWorldAPI/lance-graph) - ---- - -## 1. RUSTYNUM-CORE: The Muscle Layer - -### 1.1 Binary Plane Substrate (IMPLEMENTED) - -``` -FILE: rustynum-core/src/plane.rs -───────────────────────────────── -TYPE: Plane - acc: Box # i8[16384] — the ONLY stored state - bits: Fingerprint<256> # cached sign(acc) — 2KB - alpha: Fingerprint<256> # cached |acc| > threshold — 2KB - dirty: bool # lazy cache invalidation - encounters: u32 # how many observations shaped this - -METHODS: - new() → empty Plane, maximum uncertainty - encounters() → u32 → observation count - bits() → &Fingerprint<256> → data bits (lazy from acc) - alpha() → &Fingerprint<256>→ defined mask (lazy from acc) - encounter_bits(&mut, evidence: &Fingerprint<256>) - → INTEGER accumulate evidence into acc - → marks dirty, increments encounters - encounter(&mut, text: &str)→ hash text to fingerprint, then encounter_bits - distance(&mut, other: &mut) → Distance enum - truth(&mut) → Truth → {defined, agreed, total, frequency_f32, confidence_f32} - merkle(&mut) → MerkleRoot → blake3 of (bits & alpha), 48-bit truncated - verify(&mut, stored: &MerkleRoot) → Seal (Wisdom | Staunen) - -CONSTANTS: - PLANE_BITS = 16384 - PLANE_BYTES = 2048 - -CONNECTION POINTS: - → encounter_bits IS the DreamerV3 STE gradient (integer form) - → distance IS the BNN forward pass (XOR + popcount) - → truth IS the NARS truth value (frequency + confidence) - → merkle/verify IS the Seal integrity system - → acc IS the BNN weight vector (i8 saturating arithmetic) - -WHAT'S MISSING: - ✗ encounter_toward(&mut, other: &Plane) — encounter toward another plane's bits - ✗ encounter_away(&mut, other: &Plane) — encounter AGAINST another plane's bits - ✗ reward_encounter(&mut, evidence, reward_sign: i8) — DreamerV3-style RL gradient - ✗ BF16 cache of last computed distance -``` - -### 1.2 Node: Three Planes as SPO (IMPLEMENTED) - -``` -FILE: rustynum-core/src/node.rs -──────────────────────────────── -TYPE: Node { s: Plane, p: Plane, o: Plane } - -TYPE: Mask { s: bool, p: bool, o: bool } - Constants: SPO, SP_, S_O, _PO, S__, _P_, __O, ___ - -METHODS: - new() → empty Node - random(seed: u64) → deterministic random Node - distance(&mut, other: &mut, mask: Mask) → Distance - truth(&mut, mask: Mask) → Truth - -CONNECTION POINTS: - → Mask constants ARE the 2³ decomposition (8 projections) - → distance(mask=S__) IS projection "WHO matches?" - → distance(mask=_P_) IS projection "WHAT matches?" - → All 7 non-null masks → 7 distances → BF16 exponent bits - -WHAT'S MISSING: - ✗ project_all(&mut, other: &mut) → [Distance; 7] — all 7 projections at once - ✗ bf16_truth(&mut, other: &mut) → u16 — pack projections into BF16 - ✗ encounter_toward(&mut, other: &Node, mask: Mask) — RL credit assignment per projection - ✗ edges: Vec — adjacency list (Neo4j-style warm path) -``` - -### 1.3 Seal: Integrity Verification (IMPLEMENTED) - -``` -FILE: rustynum-core/src/seal.rs -──────────────────────────────── -TYPE: Seal { Wisdom, Staunen } -TYPE: MerkleRoot([u8; 6]) - -METHODS: - Plane::merkle() → MerkleRoot (blake3, alpha-masked) - Plane::verify(stored) → Seal - -CONNECTION POINTS: - → Staunen event = BF16 sign bit flip (causing → caused) - → Wisdom = BF16 sign bit stable (no causality reversal) - → verify IS the convergence check for RL loop - -WHAT'S MISSING: - ✗ Node-level seal (composite over S/P/O plane seals) - ✗ Seal history (sequence of Wisdom/Staunen events = tree path bits) -``` - -### 1.4 HDR Cascade: Multi-Resolution Search (IMPLEMENTED) - -``` -FILE: rustynum-core/src/hdr.rs -─────────────────────────────── -TYPE: Cascade { bands, reservoir, shift_history, ... } -TYPE: Band { Foveal, Near, Good, Weak, Reject } -TYPE: RankedHit { index, distance, band } -TYPE: ShiftAlert { old_bands, new_bands, n_observations } - -METHODS: - Cascade::calibrate(distances, vec_bytes) → calibrated Cascade - Cascade::expose(distance) → Band classification - Cascade::observe(distance) → Option (distribution drift detection) - Cascade::recalibrate(alert) - Cascade::query(query, database, k, threshold) → Vec - -CONNECTION POINTS: - → Band classification → BF16 exponent bit (Foveal/Near = 1, else = 0) - → observe/recalibrate IS the self-organizing boundary fold (QUANTILE_HEALING) - → query IS the hot path entry point - -WHAT'S MISSING: - ✗ Tetris strokes (non-overlapping incremental slices) - ✗ Prefetch interleaving - ✗ BF16 similarity cache (write on query, read on cold path) - ✗ PackedDatabase (stroke-aligned layout for streaming) - ✗ typed array_chunks strokes (Rust 1.94 array_windows) -``` - -### 1.5 BF16 Hamming (IMPLEMENTED) - -``` -FILE: rustynum-core/src/bf16_hamming.rs -──────────────────────────────────────── -TYPES: - BF16Weights — per-byte weights for weighted hamming - BF16StructuralDiff — exponent/mantissa/sign decomposition of diff - AwarenessState — Crystallized/Tensioned/Uncertain/Noise - SuperpositionState — decomposition into awareness states - PackedQualia — 16 resonance dimensions + BF16 scalar - -FUNCTIONS: - fp32_to_bf16_bytes(floats) → Vec - bf16_bytes_to_fp32(bytes) → Vec - structural_diff(a, b) → BF16StructuralDiff - pack_awareness_states / unpack_awareness_states - superposition_decompose - compress_to_qualia / hydrate_qualia_f32 / hydrate_qualia_bf16 - qualia_dot(a, b) → f32 - bundle_qualia(items) → PackedQualia - invert_qualia_polarity - -CONNECTION POINTS: - → structural_diff IS the BF16 exponent extraction (integer) - → AwarenessState maps to NARS truth (Crystallized% = frequency, 1-Noise% = confidence) - → PackedQualia IS the qualia vector for Fibonacci encoding - → compress_to_qualia / hydrate IS the φ-fold / φ-unfold - -WHAT'S MISSING: - ✗ bf16_from_projections(projections: [Band; 7], finest_distance: u32) → u16 - ✗ bf16_extract_exponent(bf16: u16) → u8 (integer extraction for graph ops) - ✗ NarsTruth packed as BF16 pair (32 bits) - ✗ VDPBF16PS-accelerated qualia_dot (currently scalar) -``` - -### 1.6 Causality (IMPLEMENTED) - -``` -FILE: rustynum-core/src/causality.rs -───────────────────────────────────── -TYPES: - CausalityDirection { Causing, Experiencing } - NarsTruthValue { frequency: f32, confidence: f32 } - CausalityDecomposition { direction, strength, ... } - -FUNCTIONS: - causality_decompose(qualia_a, qualia_b) → CausalityDecomposition - spo_encode_causal(node, direction) → SPO encoding - spatial_nars_truth(crystal) → NarsTruthValue - -CONNECTION POINTS: - → CausalityDirection = BF16 sign bit - → NarsTruthValue = what we pack into BF16 pair (32 bits) - → causality_decompose uses WARMTH/SOCIAL/SACREDNESS dims = the 3 causality axes - -WHAT'S MISSING: - ✗ NarsTruth as BF16 pair type (u32 = 2×BF16) - ✗ NARS revision using VDPBF16PS for multiply-accumulate terms - ✗ Connection to Node's 2³ projection system -``` - -### 1.7 SIMD Dispatch (IMPLEMENTED but bloated) - -``` -FILE: rustynum-core/src/simd.rs (2435 lines, needs simd_clean.rs refactor) -FILE: rustynum-core/src/simd_avx512.rs (stable AVX-512 wrapper types) -FILE: rustynum-core/src/simd_avx2.rs (AVX2 fallback implementations) -FILE: rustynum-core/src/simd_isa.rs (Isa trait for portable_simd) -FILE: rustynum-core/src/scalar_fns.rs (scalar fallbacks) - -KEY FUNCTIONS: - simd::hamming_distance(a, b) → u64 - simd::popcount(a) → u64 - simd::dot_f32(a, b) → f32 - simd::dot_i8(a, b) → i64 (VNNI) - simd::hamming_batch / hamming_top_k - + 16 element-wise ops (add/sub/mul/div × f32/f64 × scalar/vec) - + BLAS-1 (axpy, scal, asum, nrm2, iamax) - -WHAT NEEDS TO CHANGE: - → Replace simd.rs with simd_clean.rs (234 lines, LazyLock + dispatch! macro) - → Fix simd_ops + array_struct to use simd:: not simd_avx512:: types - → Add safe intrinsics (Rust 1.94) to remove unsafe inlining barriers -``` - ---- - -## 2. LANCE-GRAPH: The Brain Layer - -### 2.1 BlasGraph Semiring Algebra (IMPLEMENTED) - -``` -FILE: crates/lance-graph/src/graph/blasgraph/semiring.rs -──────────────────────────────────────────────────────── -TRAIT: Semiring { add, multiply, zero, one } -TYPE: HdrSemiring enum (the 7 semirings) - -FILE: crates/lance-graph/src/graph/blasgraph/ops.rs -─────────────────────────────────────────────────── -FUNCTIONS: - grb_mxm(A, B, semiring) → matrix × matrix - grb_mxv(A, v, semiring) → matrix × vector - grb_vxm(v, A, semiring) → vector × matrix - grb_ewise_add/mult_matrix/vector → element-wise operations - grb_reduce_matrix/vector → reduction (fold) - grb_apply/extract/assign/transpose → utility ops - hdr_bfs(adj, source, depth) → BFS traversal - hdr_sssp(adj, source, iters) → shortest path (tropical!) - hdr_pagerank(adj, iters, damping) → PageRank - -THE 5:2 SPLIT: - BITWISE (port 0, integer): - XorBundle → VPXORD - BindFirst → VPSHUFB/VPERMD - HammingMin → VPXORD + VPOPCNTDQ + VPMINSD - Boolean → VPORD + VPANDD - XorField → VPXORD + VPCLMULQDQ - - FLOAT (port 1, BF16): - SimilarityMax → VDPBF16PS + VPMAXPS - Resonance → VDPBF16PS - -WHAT'S MISSING: - ✗ BF16 edge weight type (currently HdrScalar = integer) - ✗ Dual pipeline dispatch (integer vs BF16 per semiring) - ✗ Tropical pathfinding on Hamming distances (hdr_sssp uses HdrScalar) - ✗ NarsTruth as edge attribute - ✗ VPCLMULQDQ acceleration for XorField -``` - -### 2.2 BitVec: 16K-bit Binary Vector (IMPLEMENTED in lance-graph) - -``` -FILE: crates/lance-graph/src/graph/blasgraph/types.rs -───────────────────────────────────────────────────── -TYPE: BitVec { words: [u64; 256] } — 16384 bits = 2KB - -CONSTANTS: VECTOR_WORDS=256, VECTOR_BITS=16384 - -METHODS: zero(), ones(), random(seed), xor, and, or, popcount, density, - hamming_distance, bind, bundle, threshold, ... - -CONNECTION TO RUSTYNUM: - BitVec.words ↔ Plane.bits().words() — SAME DATA, different wrappers - BitVec.hamming_distance ↔ simd::hamming_distance - BitVec.xor ↔ VPXORD - BitVec.popcount ↔ VPOPCNTDQ - -WHAT'S MISSING: - ✗ Zero-copy bridge between BitVec and Fingerprint<256> - ✗ Plane integration (BitVec as the bits() view, alpha() as mask) -``` - -### 2.3 Cascade in lance-graph (IMPLEMENTED, separate from rustynum) - -``` -FILE: crates/lance-graph/src/graph/blasgraph/hdr.rs -─────────────────────────────────────────────────── -TYPES: Band, RankedHit, ShiftAlert, ReservoirSample, Cascade - -NOTE: This is a SEPARATE implementation from rustynum-core/src/hdr.rs. - Session C (cross-pollination) was designed to merge them. - -WHAT'S MISSING: - ✗ Cross-pollination (Session C): port 5 algorithms from lance-graph to rustynum - ✗ Single source of truth for Cascade (rustynum-core is the canonical) -``` - -### 2.4 Graph Execution Engine (IMPLEMENTED) - -``` -FILE: crates/lance-graph/src/graph/blasgraph/matrix.rs -FILE: crates/lance-graph/src/graph/blasgraph/sparse.rs -FILE: crates/lance-graph/src/graph/blasgraph/vector.rs -───────────────────────────────────────────────────── -GrBMatrix: sparse matrix with HdrScalar entries -GrBVector: sparse vector with HdrScalar entries -Sparse format: CSR-like with BitVec values - -The full GraphBLAS-style API: mxm, mxv, vxm, reduce, apply, extract, assign -``` - -### 2.5 DataFusion Planner: Cypher-to-Semiring (IMPLEMENTED) - -``` -FILES: crates/lance-graph/src/datafusion_planner/*.rs -────────────────────────────────────────────────────── -ast.rs → Cypher-like AST -expression.rs → Expression evaluation -scan_ops.rs → Table scans -join_ops.rs → Join operations (MATCH patterns) -vector_ops.rs → Vector similarity operations -udf.rs → User-defined functions - -THIS IS THE COLD PATH. Cypher queries → DataFusion plan → semiring operations. - -WHAT'S MISSING: - ✗ BF16 edge weight predicates (WHERE similarity > 0.8 → scan BF16 cache) - ✗ Hot path integration (MATCH triggers cascade for discovery) - ✗ Cost estimation using BF16 logarithmic values -``` - ---- - -## 3. WHAT'S NOT IN EITHER REPO YET - -### 3.1 Wiring Between Repos - -``` -RUSTYNUM has: Plane, Node, Cascade, BF16, PackedQualia, NarsTruthValue -LANCE-GRAPH has: BitVec, Semirings, GrBMatrix, DataFusion planner - -MISSING BRIDGE: - ✗ lance-graph using rustynum-core's Plane instead of its own BitVec - ✗ lance-graph using rustynum-core's Cascade instead of its own hdr.rs - ✗ GrBMatrix entries as Plane distances (not just HdrScalar integers) - ✗ Semiring operations calling simd:: dispatch layer - ✗ DataFusion planner calling Cascade for similarity queries -``` - -### 3.2 The Deterministic f32 Pipeline - -``` -WHAT EXISTS: - ✓ Plane.encounter_bits() — integer evidence accumulation - ✓ Node.distance(mask) — per-projection hamming - ✓ Cascade.expose() — band classification - ✓ bf16_hamming::structural_diff() — BF16 decomposition - ✓ causality::CausalityDirection — sign bit meaning - ✓ causality::NarsTruthValue — frequency + confidence - -WHAT'S MISSING (the wiring): - ✗ Node.project_all() → 7 distances - ✗ 7 distances → 7 band classifications → 8 exponent bits - ✗ 8 exponent bits + 7 mantissa bits + 1 sign bit → BF16 value - ✗ BF16 value → tree leaf insertion → 16 path bits - ✗ BF16 + path bits → f32 hydration - ✗ RL credit assignment: read exponent bits → encounter per projection - ✗ Convergence detection: seal stable across iterations -``` - -### 3.3 Database Layer - -``` -WHAT EXISTS: - ✓ Cascade.query() returns RankedHits from a database slice - -WHAT'S MISSING: - ✗ PackedDatabase (stroke-aligned for streaming, GEMM panel packing analogy) - ✗ Edge storage (BF16 truth per edge, compact adjacency) - ✗ Index structure (hot edges via pointers, cold discovery via cascade) -``` - -### 3.4 GNN / Message Passing - -``` -WHAT EXISTS: - ✓ Plane.encounter_bits() — can accumulate evidence from neighbors - ✓ Node.distance() — can compare with neighbors - -WHAT'S MISSING: - ✗ encounter_toward / encounter_away — directional encounter for RL reward - ✗ Message passing loop (K rounds of neighbor aggregation) - ✗ Edge-weighted encounters (BF16 confidence as encounter weight) -``` - ---- - -## 4. DEPENDENCY MAP: WHAT MUST BE BUILT IN WHAT ORDER - -``` -LAYER 0 (foundation, no dependencies): - [0a] simd_clean.rs refactor (234 lines, replaces 2435) - [0b] Plane: add encounter_toward(), encounter_away(), reward_encounter() - [0c] Node: add project_all() → [Distance; 7] - -LAYER 1 (needs Layer 0): - [1a] BF16 truth assembly: bf16_from_projections([Band; 7], finest: u32) → u16 - [1b] BF16 exponent extraction: bf16_extract_exponent(u16) → u8 - [1c] NarsTruth as BF16 pair: struct NarsTruth(u32) with frequency/confidence as BF16 - [1d] PackedDatabase: stroke-aligned layout for streaming cascade - -LAYER 2 (needs Layer 1): - [2a] Edge type: { target: u32, truth: NarsTruth, projection: u8 } - [2b] Node with adjacency: first_edge, edge_count - [2c] Cascade with BF16 cache: write on query, read on cold path - [2d] Message passing: K-round neighbor encounter aggregation - -LAYER 3 (needs Layer 2): - [3a] RL credit assignment: read BF16 exponent → selective encounter - [3b] Tropical pathfinding: HammingMin Floyd-Warshall on semiring ops - [3c] Cold path integration: DataFusion planner reads BF16 edge cache - [3d] Convergence detection: seal stability across RL iterations - -LAYER 4 (the unicorn, needs Layer 3): - [4a] Tree leaf insertion with path extraction - [4b] f32 hydration: BF16 bits OR path bits - [4c] Full RL loop: observe → project → classify → pack → insert → hydrate → learn - [4d] Benchmark: 1M candidates, measure end-to-end RL epoch time -``` diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/OVERLOOKED_THREADS.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/OVERLOOKED_THREADS.md deleted file mode 100644 index 7d4a04bf..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/OVERLOOKED_THREADS.md +++ /dev/null @@ -1,446 +0,0 @@ -# OVERLOOKED_THREADS.md - -## What I Glossed Over: Unexplored Findings from the Deep Research - -These are threads the research surfaced that I didn't chase because I was -tunnel-visioning on the questions asked. Each one could be groundbreaking. - ---- - -## 1. TROPICAL ATTENTION (arXiv:2505.17190, 2025) - -I mentioned it in one line. Didn't explore. - -Attention mechanisms in the max-plus semiring for combinatorial algorithms. -"Superior out-of-distribution generalization over softmax baselines." - -``` -SOFTMAX ATTENTION (industry standard): - score = Q × K^T / √d - weights = softmax(score) ← FLOAT, non-deterministic, poor OOD - output = weights × V - -TROPICAL ATTENTION: - score = max_k (Q[i,k] + K[j,k]) ← MAX-PLUS, integer-friendly - weights = tropical_softmax(score) ← deterministic - output = tropical matmul(weights, V) - -OUR CASCADE IS ALREADY TROPICAL ATTENTION: - score = min_k (hamming(query, candidate[k])) - weights = band_classification(score) ← Foveal/Near/Good/Weak/Reject - output = ranked hits - - The cascade IS attention. The sigma bands ARE attention weights. - We just never called it that. -``` - -**Why this matters:** If our cascade is tropical attention, then our -multi-stroke cascade is MULTI-HEAD tropical attention. Each stroke -attends to a different resolution of the data. Stroke 1 = coarse head. -Stroke 3 = fine head. The cascade architecture IS a transformer layer -in tropical geometry. - -**EXPLORE:** Read the full paper. Map their formal definitions to our -Cascade struct. Can we reformulate hdr.rs as a tropical attention module? -If so: we have the first hardware-accelerated tropical transformer. -On CPU. Deterministic. Using VPOPCNTDQ. - ---- - -## 2. MULTI-INDEX HASHING: Sub-Linear Search (Norouzi et al., TPAMI 2014) - -I cited it. Didn't connect it. - -``` -CURRENT CASCADE: linear scan with early rejection - Stroke 1: scan ALL 1M candidates × 128 bytes = 128MB - Rejection: ~84% rejected → 160K survive to stroke 2 - Still: O(N) scan on stroke 1 - -MULTI-INDEX HASHING: - Split 16K-bit code into m substrings of 16K/m bits each - Build hash table for each substring - Query: look up each substring → candidate set - Pigeonhole: if hamming(a,b) ≤ r, at least one substring matches within ⌊r/m⌋ - - Result: 100-1000x speedup over linear scan on 1B 64-bit codes - - For 16K-bit codes: split into 8 substrings of 2K bits each - 8 hash tables, each indexed by 2K-bit prefix - Query: 8 lookups → intersect candidate sets → exact verify survivors -``` - -**Why this matters:** The cascade gives us early rejection (constant factor). -Multi-index hashing gives us SUB-LINEAR candidate generation (algorithmic). -They compose: multi-index hashing produces candidates, cascade verifies them. - -``` -COMBINED: - Step 0: Multi-index lookup → ~1000 candidates (sub-linear, not 1M) - Step 1: Cascade stroke 1 on 1000 candidates (not 1M) - Step 2: Cascade stroke 2 on survivors - Step 3: Exact on final survivors - - Cost: ~1000 × 140ns + cascade overhead ≈ 0.2ms (vs ~2ms for 1M linear cascade) - 10x improvement from algorithmic change, not SIMD tricks. -``` - -**EXPLORE:** Can our Fingerprint<256> be split into 8 Fingerprint<32> for -multi-index? The cascade already reads stroke 1 from bytes [0..128] — -that IS a substring. Build a hash index on stroke 1 prefixes. - ---- - -## 3. DEGREE-QUANT: High-Degree Nodes Break Quantization (ICLR 2021) - -Buried in the GNN section. Didn't connect to our architecture. - -Tailor et al. found that nodes with hundreds of neighbors create extreme -activation ranges that break standard quantization. This is the HUB PROBLEM. - -``` -OUR VERSION OF THE HUB PROBLEM: - Node with 500 neighbors → 500 encounter_toward() calls - i8 accumulator saturates at ±127 after ~127 encounters - After saturation: ALL further encounters are ignored - The most connected nodes LOSE information first - - This is the OPPOSITE of what we want. - Hub nodes should be the MOST informed, not the FIRST saturated. -``` - -**Why this matters:** The i8 accumulator in Plane is 8 bits. It saturates. -Hub nodes in the graph hit saturation earliest. Their alpha becomes all-1s -(everything defined) but their PRECISION is frozen. They can't learn anymore. - -**FIX IDEAS:** -``` -1. Dynamic threshold: hub nodes get higher threshold before alpha=1. - More evidence needed to commit a bit. Slower crystallization. - -2. Accumulator width scaling: i8 for leaf nodes, i16 for hubs, i32 for super-hubs. - The Plane type could be generic over accumulator width. - -3. Exponential decay: acc[k] *= 0.99 per round (forgetting). - Recent encounters matter more. Old evidence fades. - But this introduces float. Can we do integer decay? acc[k] -= acc[k]/128? - -4. ReActNet's learned shifts: per-bit threshold instead of global. - Some bit positions need more evidence than others. - The threshold IS a learned parameter (trained by encounter patterns). -``` - -**EXPLORE:** Run message passing on a scale-free graph (power law degree distribution). -Measure: do hub nodes saturate? Does accuracy degrade for high-degree nodes? - ---- - -## 4. 90% OF PARALLEL BF16 COMPUTATIONS DIVERGE (arXiv:2506.09501, 2025) - -I cited this as "our advantage." Didn't explore what it MEANS for the industry. - -``` -THEIR FINDING: - >90% of parallel BF16 computations produce different results - from serial BF16 computations. On the SAME inputs. - - Because: (a + b) + c ≠ a + (b + c) in IEEE 754. - Thread scheduling changes accumulation order. - Different order → different rounding → different result. - 90%+ of the time. - -WHAT THIS MEANS: - Every GNN trained on GPU with BF16 produces NON-REPRODUCIBLE results. - Not "slightly different." DIFFERENT. 90% of the time. - - Every benchmark comparison between GNN models is UNRELIABLE. - The "state of the art" leaderboard is comparing noise. - Nobody talks about this because everyone uses the same non-deterministic stack. - - We don't have this problem. Our results are bit-identical across runs. - This isn't a feature we should mention in a footnote. - This is the ENTIRE VALUE PROPOSITION for applications that need trust: - - Medical diagnosis graphs - - Financial risk assessment - - Legal reasoning chains - - Safety-critical systems - - Regulatory compliance (auditable, reproducible) -``` - -**EXPLORE:** Can we PROVE determinism formally? Not just "we don't use float" -but a formal proof that our RL loop is a deterministic function of its inputs. -This would be a significant contribution to the formal verification literature. - ---- - -## 5. STOCHASTIC ROUNDING AS EXPLORATION MECHANISM - -Everyone treats stochastic rounding as a PROBLEM. But in RL, exploration -is the GOAL. What if we WANT non-determinism at a specific point? - -``` -EXPLOITATION: integer encounter_toward (deterministic) - → greedy: push toward known good patterns - -EXPLORATION: stochastic BF16 quantization at the boundary - → when a distance is NEAR a band boundary, randomly assign - to higher or lower band with probability proportional to proximity - → this IS stochastic rounding applied to band classification - → deterministic WITHIN the RL loop, stochastic AT the boundary - - The RL agent exploits deterministically. - The cascade explores stochastically at boundaries. - The alpha channel records which bits are in the boundary zone. -``` - -**Why this matters:** RL needs exploration-exploitation tradeoff. -Everyone uses epsilon-greedy or entropy bonus (float). We could use -stochastic band classification — exploration proportional to uncertainty. -The PLANE ALPHA CHANNEL tells us exactly which bit positions are uncertain. -Explore there. Exploit everywhere else. Naturally. No hyperparameter. - -**EXPLORE:** Implement stochastic_expose(distance, rng) in Cascade. -Only affects boundary-zone distances. Compare convergence with -deterministic_expose vs stochastic_expose on a known-optimal task. - ---- - -## 6. VPCLMULQDQ → FASTER SEAL VERIFICATION - -I noted VPCLMULQDQ for XorField semiring. Didn't connect to Seal. - -VPCLMULQDQ is carry-less multiplication = polynomial multiplication in GF(2). -This is the CORE OPERATION of CRC and polynomial hashing. - -``` -CURRENT SEAL: blake3 hash of (bits & alpha). Full 256-byte input. - blake3 is fast (~3 cycles/byte on AVX-512) but it's OVERKILL for a 48-bit hash. - -ALTERNATIVE: GF(2) polynomial hash using VPCLMULQDQ - Input: 256 bytes (Plane bits & alpha) - Operation: VPCLMULQDQ fold — same as CRC-32C but wider - Output: 48-bit or 64-bit hash - - VPCLMULQDQ processes 64 bytes per cycle (512-bit vectors). - 256 bytes = 4 cycles. Plus fold = ~8 cycles total. - - blake3 on 256 bytes ≈ 256 × 3 = ~768 cycles. - - 96x faster seal verification. -``` - -**Why this matters:** Seal verification happens on every encounter -(to detect Staunen). If verification is 96x faster, we can verify -MORE OFTEN — potentially every message passing round instead of -only at convergence checks. - -**CAVEAT:** blake3 has cryptographic properties (collision resistance). -VPCLMULQDQ polynomial hash does NOT. It's sufficient for integrity -verification (detecting accidental changes) but not for adversarial -resistance. For our use case (detecting Staunen from genuine observations, -not adversarial inputs), polynomial hash suffices. - -**EXPLORE:** Implement `seal_fast()` using VPCLMULQDQ. Benchmark against -`blake3::hash()`. If 50x+ faster: use fast seal for per-round checks, -blake3 seal for persistent storage verification. - ---- - -## 7. HEXASTORE SEXTUPLE INDEXING → MASK-AWARE INDEX - -Hexastore (VLDB 2008): 6 permutation indices for SPO triples. -SPO, SOP, PSO, POS, OSP, OPS. - -I noted it. Didn't connect to our Mask system. - -``` -HEXASTORE 6 INDICES: OUR 7 MASKS: - SPO (given S, find PO) SPO (all three match) - SOP (given S, find OP) SP_ (S and P match) - PSO (given P, find SO) S_O (S and O match) - POS (given P, find OS) _PO (P and O match) - OSP (given O, find SP) S__ (only S matches) - OPS (given O, find PS) _P_ (only P matches) - __O (only O matches) - -THEIR 6 = permutations of "given X, find Y,Z" -OUR 7 = combinations of "which planes participate in distance" - -THEY ARE DUAL. Their index lookup IS our masked distance query. - Hexastore "given P=KNOWS, find all (S,O) pairs" - = our "cascade query with mask=_P_, query.P = KNOWS-fingerprint" -``` - -**Why this matters:** Hexastore MATERIALIZES all 6 indices (sorted vectors). -We don't materialize — we compute distances at query time. -But for KNOWN EDGES (warm path), we could materialize Hexastore-style indices -sorted by BF16 truth value. That gives O(log N) lookup for warm queries. - -``` -COMBINED: - WARM (materialized, Hexastore-style): - SPO_index: sorted by (S, P, O, BF16_truth) - _P__index: sorted by (P, BF16_truth) ← "all relationships of type P" - etc. - - HOT (computed, cascade): - "Find similar nodes" → cascade scan with mask - - The BF16 truth value IS the sort key for the materialized index. - Logarithmic quantization means sorting by BF16 ≈ sorting by similarity. -``` - -**EXPLORE:** Can we build a hybrid index that materializes the top-K -edges per Hexastore permutation, sorted by BF16? Then cold Cypher queries -hit the materialized index first, only falling through to cascade for -novel queries. - ---- - -## 8. NARS REVISION AS TROPICAL MATRIX MULTIPLY - -I asked this question in the spec. Never answered it. - -``` -NARS REVISION RULE: - Given two independent evidence sources with truths and : - - f_new = (f1*c1*(1-c2) + f2*c2*(1-c1)) / (c1*(1-c2) + c2*(1-c1)) - c_new = (c1*(1-c2) + c2*(1-c1)) / (c1*(1-c2) + c2*(1-c1) + (1-c1)*(1-c2)) - -This has multiply-accumulate structure: f*c terms accumulated. - -IN TROPICAL FORM (taking log): - log(f_new) = log(f1*c1*(1-c2) + f2*c2*(1-c1)) - log(c1*(1-c2) + c2*(1-c1)) - - If we use max-plus (tropical) approximation: - log(a + b) ≈ max(log(a), log(b)) ← tropical addition - log(a * b) = log(a) + log(b) ← tropical multiplication - - Then revision becomes: - log(f_new) ≈ max(log(f1)+log(c1)+log(1-c2), log(f2)+log(c2)+log(1-c1)) - - max(log(c1)+log(1-c2), log(c2)+log(1-c1)) -``` - -**Why this matters:** If NARS revision IS tropical arithmetic on -log-truth-values, then BF16 exponent (which IS a logarithmic representation) -gives us revision AS EXPONENT ARITHMETIC. - -``` -BF16 exponent of frequency ≈ log2(frequency) -BF16 exponent of confidence ≈ log2(confidence) - -Tropical revision on exponents: - max(exp_f1 + exp_c1, exp_f2 + exp_c2) ← integer max and add - - This is ONE VPMINSD + ONE VPADDD instruction. - Not VDPBF16PS (float dot product). - INTEGER tropical arithmetic on BF16 exponents. - - NARS revision at 32 truth values per SIMD instruction. - Deterministic. Integer. No float. -``` - -**EXPLORE:** Formalize the tropical approximation of NARS revision. -What's the error bound vs exact float revision? If < 1 BF16 mantissa -bit of error: the approximation is FREE (within BF16 precision anyway). - ---- - -## 9. LEARNED PER-BIT THRESHOLDS (ReActNet, ECCV 2020) - -ReActNet achieves 69.4% ImageNet top-1 with binary networks using -learned activation shifts: RSign(x) = sign(x + β) where β is learned. - -``` -OUR CURRENT: - alpha[k] = |acc[k]| > THRESHOLD ← global threshold, same for all bits - -REACTNET: - activation[k] = sign(acc[k] + shift[k]) ← per-bit learned shift - - shift[k] IS a threshold. It just moves the decision boundary per position. - Some bits need MORE evidence to commit. Others less. - - THE SHIFT IS LEARNABLE FROM ENCOUNTER HISTORY: - If bit k frequently flips between encounters → high uncertainty → high threshold - If bit k always agrees with evidence → low uncertainty → low threshold - - shift[k] = some function of acc[k]'s variance over recent encounters - - This makes alpha ADAPTIVE PER BIT. Not just on/off. - Uncertain bits stay undefined longer. Certain bits commit faster. -``` - -**Why this matters:** Currently our alpha channel is binary (0 or 1). -Per-bit thresholds make it a SPECTRUM. The alpha channel becomes a -confidence map, not just a defined/undefined mask. This directly -improves the BF16 mantissa precision — we can read CONFIDENCE -from the alpha channel, not just PRESENCE. - -**EXPLORE:** Track variance of acc[k] over last N encounters. -High variance → high threshold. Low variance → low threshold. -Does this improve distance precision? Does convergence speed up? - ---- - -## 10. MOHRI'S WEIGHTED TRANSDUCERS → CYPHER AS SEMIRING AUTOMATON - -The NYU semiring paper (Mohri) studies semirings in weighted finite-state -transducers for NLP: speech recognition, parsing, translation. - -``` -WEIGHTED TRANSDUCER: - States = graph nodes - Transitions = edges with semiring weights - Composition = semiring matrix multiply - - Query = input string (Cypher pattern) - Traversal = transducer composition (semiring mxv chain) - Result = output with accumulated semiring weight - -OUR DATAFUSION PLANNER IS ALREADY A WEIGHTED TRANSDUCER: - States = BlasGraph nodes - Transitions = edges with HdrScalar / BF16 weights - Cypher MATCH = transducer path - WHERE clause = semiring threshold - - The Cypher-to-semiring compilation is transducer construction. - Query execution is transducer composition. -``` - -**Why this matters:** Transducer theory gives us OPTIMAL composition -algorithms. Mohri's shortest-distance algorithm generalizes Dijkstra -to arbitrary semirings. We could import 30 years of automata theory -into our query optimizer. - -**EXPLORE:** Read Mohri's "Semiring Frameworks and Algorithms for -Shortest-Distance Problems" (Journal of Automata, Languages and Combinatorics). -Map his algorithms to our HdrSemiring dispatch. Can his optimal -composition strategy improve our multi-hop query performance? - ---- - -## PRIORITY RANKING - -``` -# THREAD POTENTIAL IMPACT EFFORT -────────────────────────────────────────────────────────────────── -1. Multi-index hashing 10x search speed medium -2. NARS revision as tropical deterministic NARS low -3. Tropical attention = cascade reframe as transformer low (conceptual) -4. Hub saturation (Degree-Quant) correctness fix medium -5. Learned per-bit thresholds precision improvement medium -6. 90% divergence → value prop marketing/paper low -7. VPCLMULQDQ fast seal 96x faster verify low -8. Hexastore mask-aware index O(log N) warm queries medium -9. Stochastic exploration RL convergence medium -10. Mohri transducers query optimization high (research) -``` - -Thread 1 (multi-index) and thread 2 (tropical NARS) have the highest -return per effort. Thread 3 (tropical attention) is a reframing that -costs zero code but opens a publication path. - -Thread 4 (hub saturation) is a CORRECTNESS concern that needs investigation -before production deployment of message passing. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/RESEARCH_REFERENCE.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/RESEARCH_REFERENCE.md deleted file mode 100644 index eb7552ae..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/RESEARCH_REFERENCE.md +++ /dev/null @@ -1,377 +0,0 @@ -# RESEARCH_REFERENCE.md - -## Prior Art: What Exists, What to Steal, What to Investigate - ---- - -## 1. DreamerV3 — Binary RL That WORKS (Nature 2025) - -**Paper:** Hafner et al., "Mastering Diverse Domains through World Models" -**URL:** https://danijar.com/project/dreamerv3/ -**Key finding:** Discrete categorical latent representations OUTPERFORM continuous. -**RLC 2024 follow-up:** The advantage comes from SPARSE BINARY nature specifically. - -### What They Do -``` -State representation: 32 categories × 32 classes = 1024 multi-one-hot dims -Gradient trick: STE (Straight-Through Estimator) - Forward: binary = sign(latent) - Backward: ∂L/∂latent ≈ ∂L/∂binary × 𝟙{|latent| ≤ 1} -Training: GPU, float matmul on sparse binary codes -Hardware: NVIDIA GPU with float tensor cores -``` - -### What We Can Steal -``` -STE gradient → encounter_toward / encounter_away (our integer equivalent) - STE clips at |latent| ≤ 1 → our acc[k] clips at i8 saturation (-128, 127) - STE passes gradient through sign() → our acc += ±1 through encounter - SAME FUNCTION. Different substrate. - -World model → cascade as predictor - DreamerV3 predicts next observation from state + action - Our cascade predicts band classification from partial strokes - Both: early termination when confident. Both: uncertainty-aware. - -Actor-critic split → encounter_toward (actor) / truth() (critic) - Actor: choose action (encounter toward good patterns) - Critic: evaluate state (truth = frequency/confidence) -``` - -### What to Investigate -``` -1. Does our 16K-dim binary match or beat their 1024-dim multi-one-hot? - Test: same environment, our Plane as state, encounter as gradient. - -2. Does integer accumulation converge as fast as STE float? - Test: convergence curves for identical observations. - -3. Can our cascade serve as a world model? - Test: given partial observation (stroke 1), predict band of full observation. - -4. RLC 2024 arXiv:2312.01203 — "Harnessing Discrete Representations - for Continual Reinforcement Learning" — specifically studies why - binary beats continuous. Read in detail. -``` - ---- - -## 2. BitGNN — Binary Graph Neural Networks (ICS 2023) - -**Paper:** "BitGNN: Unleashing the Performance Potential of Binary GNNs on GPUs" -**URL:** https://dl.acm.org/doi/10.1145/3577193.3593725 -**Key finding:** 8-22x speedup using XNOR+popcount for graph convolution. - -### What They Do -``` -Binary weights: W ∈ {-1, +1}^(N×D) → packed as bits -Binary features: X ∈ {-1, +1}^(N×D) → packed as bits -Convolution: XNOR(W, X) + popcount = dot product approximation -Aggregation: GPU scatter_add (NON-DETERMINISTIC) -Training: STE for binary weights, float for aggregation -``` - -### What We Can Steal -``` -Their convolution IS our hamming_distance. Same instruction. Same operation. -Their aggregation IS our encounter(). But theirs is GPU scatter_add (races). -Ours is sequential integer accumulation (deterministic). - -Their binary feature matrix IS our Plane.bits() fingerprint. -Their binary weight matrix IS the pattern we encounter toward/away. - -Architecture translation: - BitGNN layer = for each node: encounter_toward(neighbor.bits) for each neighbor - K BitGNN layers = K rounds of message passing - Output = node.truth() = classification/regression target -``` - -### What to Investigate -``` -1. Bi-GCN (Wang et al., 2021) — earlier binary GCN, simpler. - Binarizes both weights AND features. May be closer to our architecture. - -2. BitGNN's GPU optimizations — they use "bit-level optimizations" - and warp-level parallelism. What can we learn for VPOPCNTDQ batching? - See: https://www.sciencedirect.com/science/article/abs/pii/S0743731523000357 - -3. ReActNet (ECCV 2020) — 69.4% ImageNet top-1 with binary. - Uses learned activation shifts (RSign, RPReLU). - Our threshold in Plane IS a learned activation. Can we adapt RSign? - URL: https://ar5iv.labs.arxiv.org/html/2003.03488 -``` - ---- - -## 3. GEMM Microkernel Architecture (siboehm, 2022) - -**URL:** https://siboehm.com/articles/22/Fast-MMM-on-CPU -**Key finding:** 2x from panel packing (sequential memory access). - -### What They Do -``` -Optimization chain: - Naive: 4481ms - Compiler flags: 1621ms (3x — -O3 -march=native -ffast-math) - Loop reorder: 89ms (18x — cache-aware inner loop) - L1 tiling: 70ms (1.3x — tile to L1 size) - Multithreading: 16ms (4.4x — OpenMP on rows/cols) - MKL: 8ms (2x — panel packing + register blocking + prefetch) - -Panel packing: repack matrix B into column panels contiguous in memory. -Instead of strided access (jump 1024 floats per row), sequential access. -The hardware prefetcher handles sequential patterns automatically. -``` - -### What We Can Steal -``` -EXACT PARALLEL: - Their matrix B → our candidate database - Their column panel → our stroke region - Their panel packing → our PackedDatabase - Their tiling to L1 → our 2KB plane constraint - Their register accumulation → our ZMM hamming accumulator - Their prefetch schedule → our _mm_prefetch per candidate - Their thread partitioning → rayon par_chunks on candidates - -The missing 2x: - MKL packs B into contiguous column panels BEFORE the kernel runs. - We should pack candidates into contiguous stroke regions BEFORE cascade runs. - - Current: candidate[i].plane_S[0..128] scattered at 6KB intervals - Packed: stroke1_all[i*128..(i+1)*128] contiguous - - Sequential access: hardware prefetcher free. 2-3x improvement. -``` - -### What to Investigate -``` -1. https://github.com/flame/how-to-optimize-gemm — goes further than siboehm. - Register blocking details for AVX-512. Directly applicable to our - hamming inner loop: keep partial popcount in ZMM, never spill. - -2. OpenBLAS kernel: github.com/xianyi/OpenBLAS/blob/develop/kernel/x86_64/sgemm_kernel_16x4_haswell.S - 7K LOC of handwritten assembly. The microkernel structure is what - level3.rs should aspire to. - -3. Apple AMX instructions: undocumented matrix-matrix ops. - Our Isa trait could abstract over AMX when Apple documents them. -``` - ---- - -## 4. GraphBLAS + SuiteSparse (Tim Davis) - -**URL:** https://github.com/DrTimothyAldenDavis/GraphBLAS -**Paper:** ACM TOMS 2019/2023 -**Key finding:** ~2000 pre-compiled semiring kernels + runtime JIT for custom ones. - -### What They Do -``` -C API for graph algorithms as sparse matrix operations. -Semiring: (S, ⊕, ⊗, 0⊕, 1⊗) replaces (+, ×). -Three-tier dispatch: - 1. FactoryKernels: pre-compiled for common type/semiring combos - 2. JIT: compile custom semiring via system C compiler, cache result - 3. Generic: function pointer fallback - -SIMD: compiler auto-vectorization (-O3 -march=native), not hand-written. -Powers: FalkorDB (RedisGraph successor), MATLAB sparse multiply since R2021a. -``` - -### What We Can Steal -``` -Their semiring trait → our HdrSemiring enum. Already similar. -Their FactoryKernels → our hand-written SIMD per semiring. -Their JIT → not needed yet (our 7 semirings are fixed). -Their mxm/mxv/vxm → our grb_mxm/grb_mxv/grb_vxm. Already implemented. - -THE INSIGHT: SuiteSparse gets performance from sparse matrix FORMAT -(CSR/CSC/COO/hypersparse) not from custom SIMD. The format determines -whether operations are sequential (cache-friendly) or scattered (slow). - -For us: the PackedDatabase IS the sparse format optimization. -Stroke-aligned = CSR for cascades. -``` - -### What to Investigate -``` -1. cuASR (CUDA Algebra for Semirings): GPU semiring GEMM at 95% of standard GEMM. - URL: https://github.com/hpcgarage/cuASR - Their templates for tropical/bottleneck semirings on GPU. - Can inform our SIMD templates for bitwise semirings on CPU. - -2. SuiteSparse JITPackage: embeds source code in library binary. - Interesting for deployment: one binary, custom semirings compiled on demand. - -3. pygraphblas: Python wrapper for SuiteSparse. - URL: https://github.com/Graphegon/pygraphblas - Their Python API design for our future lance-graph-python. -``` - ---- - -## 5. Tropical Geometry + Neural Networks (Zhang, Naitzat, Lim 2018) - -**Paper:** "Tropical Geometry of Deep Neural Networks" (ICML 2018) -**URL:** https://proceedings.mlr.press/v80/zhang18i.html -**Key finding:** ReLU networks are equivalent to tropical rational maps. - -### What They Prove -``` -ReLU(x) = max(x, 0) = tropical max operation. -Linear layer + ReLU = tropical polynomial evaluation. -Decision boundaries = tropical hypersurfaces. - -Feedforward ReLU network with L layers: - Output = tropical rational function of input. - The network computes a piecewise-linear function - whose pieces are determined by the tropical geometry. - -TROPICAL SEMIRING: (ℝ ∪ {∞}, min, +, ∞, 0) - "addition" = min (take the shorter path) - "multiplication" = + (add edge weights) - This is Bellman-Ford / Floyd-Warshall / Dijkstra. -``` - -### What This Means for Us -``` -Our HammingMin semiring IS the tropical semiring in Hamming space: - ⊕ = min (take the nearest neighbor) - ⊗ = hamming (cost of traversing an edge) - -Therefore: - hdr_sssp() IS tropical pathfinding - hdr_bfs() IS tropical reachability (thresholded) - hdr_pagerank() can be reformulated tropically - -The Plane accumulator IS a tropical computation: - acc[k] += evidence IS tropical addition (accumulate path lengths) - sign(acc[k]) IS the tropical decision boundary - |acc[k]| > threshold IS the tropical activation (ReLU equivalent) - -Our ENTIRE architecture is tropical. We just didn't name it that way. -``` - -### What to Investigate -``` -1. "Tropical Attention" (arXiv:2505.17190, 2025) — attention in max-plus semiring. - Combinatorial algorithms with superior OOD generalization. - Could our cascade be reformulated as tropical attention? - -2. Connection to NARS: NARS revision rule uses min/max operations. - Is NARS revision a tropical computation? - If so: revision = tropical matrix multiply on truth values. -``` - ---- - -## 6. Neo4j Internals: Index-Free Adjacency - -**Source:** "Graph Databases" (Robinson, Webber, Eifrem) + internal docs -**Key insight:** O(1) per hop via pointer chasing. But cache-hostile. - -### What They Do -``` -Node record (15 bytes): [4B id] [4B first_rel_ptr] [4B first_prop_ptr] [3B flags] -Relationship record: doubly-linked list per endpoint node. -Storage: fixed-size records in store files, paged into memory. - -Traversal: follow first_rel_ptr → walk linked list → filter by type + direction. -Each hop: one pointer dereference. O(1). But random memory access. - -For 10 hops: 10 cache misses × ~40ns DRAM = ~400ns total. -For scan of 1M edges: 1M × 40ns = 40ms. Cache-hostile. -``` - -### What We Can Steal -``` -Fixed-size records: our Node is fixed-size (6KB + 32B header). - BUT our Node is SIMD-scannable, not just pointer-chaseable. - -Adjacency pointer: add first_edge + edge_count to Node. - For KNOWN relationships: O(1) pointer + walk. - For DISCOVERY: cascade scan (O(N) but with 99.7% early rejection). - -The HYBRID: Neo4j for warm path, cascade for hot path. - warm_edges: Vec — confirmed relationships, Neo4j-style - cold_discovery: cascade.query() — find new similar nodes - - BF16 truth on edges bridges both paths. -``` - -### What to Investigate -``` -1. Hexastore (VLDB 2008) — SPO sextuple indexing. - 6 permutation indices: SPO, SOP, PSO, POS, OSP, OPS. - For our Mask-based queries: each mask maps to 1-2 permutation indices. - Could inform how we index Node collections. - -2. Neo4j's page cache: custom off-heap memory management. - Our PackedDatabase is similar: pre-allocated, aligned, streaming. - -3. FalkorDB (formerly RedisGraph): uses SuiteSparse:GraphBLAS internally. - Cypher queries → GraphBLAS semiring operations. - This is EXACTLY our architecture: DataFusion planner → BlasGraph semirings. -``` - ---- - -## 7. SIMD² — Future Hardware for Semiring GEMM (ISCA 2022) - -**Paper:** Zhang et al., "SIMD²: A Generalized Matrix Instruction Set" -**URL:** https://arxiv.org/abs/2205.01252 -**Key finding:** 5% chip area overhead, 38.59× peak speedup for semiring GEMM. - -### What They Propose -``` -Configurable ALUs in Tensor Core-like units: - ⊗ALU: supports {×, min, max, AND, XOR, popcount, fuzzy-AND} - ⊕ALU: supports {+, min, max, OR, XOR, threshold} - -Combinations cover: tropical, bottleneck, Boolean, Hamming, fuzzy. -One instruction does semiring mxv with arbitrary ⊕/⊗. - -Hardware cost: ~5% additional chip area. -Performance: 38.59× over optimized CUDA for tropical semiring. -``` - -### What This Means for Us -``` -Our 7 semirings would ALL be hardware-accelerated on SIMD² processors. -No need for dual pipeline (integer + BF16). One unified instruction. - -Keep the semiring abstraction generic. -When SIMD² arrives: one new tier in the dispatch macro. - -static TIER: LazyLock = LazyLock::new(|| { - if has_simd2() { return Tier::Simd2; } - if avx512 { return Tier::Avx512; } - ... -}); -``` - ---- - -## 8. AVX-512 Instruction Reference for Our Pipeline - -``` -INSTRUCTION OPERATION USE IN PIPELINE -────────────────────────────────────────────────────────────────── -VPXORD 512-bit XOR XOR two planes (binary diff) -VPOPCNTDQ popcount per u64, 8 parallel Hamming distance -VPANDD/VPORD 512-bit AND/OR Boolean semiring, alpha masking -VPMINSD/VPMAXSD packed min/max i32 HammingMin ⊕, SimilarityMax ⊕ -VDPBF16PS 32 BF16 dot → f32 accumulate Similarity/Resonance semirings -VCVTNEPS2BF16 16 f32 → 16 BF16 Cache distance as BF16 -VCVTBF162PS* BF16 → f32 (Rust 1.94) Hydrate BF16 truth to f32 -VPCLMULQDQ carry-less multiply 512-bit XorField GF(2) polynomial multiply -VPSRLW packed shift right word Extract BF16 exponent (>>7) -VPCMPEQB packed byte compare Match exponent to structural pattern -VPTERNLOGD ternary logic on 3 vectors Complex Boolean semiring ops -VPSHUFB shuffle bytes BindFirst permutation semiring -_mm_prefetch T0 prefetch to L1 Next candidate pre-load -``` - -All stable in Rust 1.94 under `#[target_feature(enable = "avx512f,avx512bw,...")]`. -Safe calls (no pointer args) don't need `unsafe` blocks. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/RESEARCH_THREADS.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/RESEARCH_THREADS.md deleted file mode 100644 index 8b92a5d3..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/RESEARCH_THREADS.md +++ /dev/null @@ -1,429 +0,0 @@ -# RESEARCH_THREADS.md - -## The Threads the Research Actually Reveals - -**Status:** Actionable connections. Not analysis. Actions. - ---- - -## THREAD 1: DreamerV3 PROVES Binary is BETTER, Not Just Cheaper - -DreamerV3 (Nature 2025): categorical latent representations OUTPERFORM -continuous ones. RLC 2024 went further: the advantage comes from SPARSE -BINARY nature specifically, not discreteness in general. - -``` -DREAMERV3: multi-one-hot codes (32 categories × 32 classes = 1024 sparse binary dims) - → STE gradient → outperforms continuous latent spaces - -US: 16K-bit binary planes (16384 sparse binary dims) - → encounter() integer gradient → no comparison exists - -WHAT THEY HAVE THAT WE DON'T: - - STE (Straight-Through Estimator): gradient flows through sign() - - World model: predicts next observation from current state + action - - Actor-critic: separate policy and value networks - -WHAT WE HAVE THAT THEY DON'T: - - 16x more dimensions (16384 vs 1024) - - STRUCTURED binary (SPO decomposition, not flat) - - Deterministic gradient (encounter vs stochastic STE) - - Hardware acceleration (VPOPCNTDQ, they use GPU float matmul on binary codes) - - Per-dimension credit assignment (alpha channel, they have none) -``` - -**ACTION: Build the first fully 1-bit BNN RL system.** - -Nobody has done this. DreamerV3 uses multi-one-hot (effectively ~5% dense). -We use actual binary planes (~50% dense with alpha masking). -Their STE is: ∂L/∂w_latent ≈ ∂L/∂w_binary × 𝟙{|w_latent| ≤ 1} -Our encounter is: acc[k] += evidence; alpha[k] = |acc[k]| > threshold - -Same function. Different implementation. Theirs needs float. Ours doesn't. - -```rust -/// STE equivalent using integer accumulator. -/// This IS the DreamerV3 gradient, expressed as integer ops. -fn binary_ste_encounter(plane: &mut Plane, evidence: &[u8], reward: f32) { - let reward_sign = if reward > 0.0 { 1i8 } else { -1i8 }; - for k in 0..plane.len_bits() { - if evidence[k / 8] & (1 << (k % 8)) != 0 { - // Bit is set in evidence: push accumulator toward sign(reward) - plane.acc[k] += reward_sign; - } - // Alpha update: STE's 𝟙{|w| ≤ 1} is our threshold check - plane.alpha[k] = (plane.acc[k].abs() > plane.threshold) as u8; - } -} -``` - -Paper title: "Fully Binary Reinforcement Learning via Hamming World Models" -Nobody has claimed this. The components are proven. We have the implementation. - ---- - -## THREAD 2: siboehm GEMM Tiling IS Our Cascade Architecture - -The siboehm article shows the GEMM optimization path: - -``` -SIBOEHM GEMM: OUR CASCADE: -───────────────────────────────────────────────────────────── -Naive triple loop 4481ms Naive full-vector scan ~50ms -Loop reorder 89ms 18x Tetris stroke ordering ~5ms 10x -L1 tiling 70ms 1.3x L1-aware stroke sizes ~3ms 1.7x -Multithreading 16ms 4.4x Batch interleaved prefetch ~1ms 3x -MKL 8ms 2x ??? (what's our MKL?) ??? -``` - -The parallel is exact: -- **Loop reorder** = process Stroke 1 for ALL candidates before Stroke 2 (current: interleaved) -- **L1 tiling** = our L1_CACHE_BOUNDARY constraint (2KB planes in L1) -- **Register accumulate** = our cumulative d1+d2+d3 instead of recomputing - -But we're missing the final 2x that MKL gets. What does MKL do that we don't? - -``` -MKL's final 2x: - 1. Register blocking: 6×16 microkernel keeps ALL intermediates in YMM/ZMM registers - 2. Panel packing: repack B into contiguous column panels for streaming loads - 3. Prefetch scheduling: explicit _mm_prefetch every N iterations, tuned per μarch - -OUR EQUIVALENT: - 1. Register blocking: accumulate Hamming partial in ZMM register, never spill to L1 - 2. Panel packing: candidate database stored as contiguous 2KB-aligned planes - 3. Prefetch scheduling: prefetch next candidate's Stroke 1 while processing current - -THE MISSING PIECE: We don't pack the database for streaming. -``` - -**ACTION: Repack the candidate database into stroke-aligned layout.** - -``` -CURRENT DATABASE LAYOUT: - candidate[0].plane_S (2KB) - candidate[0].plane_P (2KB) - candidate[0].plane_O (2KB) - candidate[1].plane_S (2KB) - ... - - Stroke 1 reads bytes [0..128] of each candidate. - These are scattered across memory at 6KB intervals. - Cache-unfriendly for sequential scanning. - -PACKED LAYOUT (panel packing for cascades): - stroke1_all[0..128] = candidate[0].plane_S[0..128] - stroke1_all[128..256] = candidate[1].plane_S[0..128] - stroke1_all[256..384] = candidate[2].plane_S[0..128] - ... - - Stroke 1 reads SEQUENTIALLY through packed memory. - 128 bytes × 1M candidates = 128MB, streaming load. - Hardware prefetcher handles this automatically. - - This IS the panel packing from GEMM. -``` - -Estimated improvement: 2-3x on the cascade scan (128MB sequential vs 128MB scattered). - ---- - -## THREAD 3: Neo4j's Optimizations Are the Wrong Ones — But Show Where to Hack - -Neo4j uses: -- **Index-free adjacency**: O(1) pointer chase per hop. Fixed-size records. -- **Record-level caching**: node records (15 bytes), relationship records in doubly-linked lists. -- **Page cache**: OS page cache + custom off-heap cache for store files. - -The WRONG optimizations for our workload: -- Pointer chasing is sequential, not parallelizable (1 hop per cycle) -- Doubly-linked relationship lists = random memory access -- Page cache = disk-oriented, we're in RAM - -The RIGHT insight from Neo4j: -- **Fixed-size records** = predictable memory layout = prefetchable -- **Node → first relationship pointer** = one indirection, then chain walk -- **cpuid-based dispatch** = MKL does this, siboehm mentions it, we do it (LazyLock tier) - -**ACTION: Our SPO node IS Neo4j's fixed-size record, but SIMD-scannable.** - -``` -NEO4J NODE RECORD (15 bytes): - [4B node_id] [4B first_rel_ptr] [4B first_prop_ptr] [3B flags] - - To find neighbors: follow first_rel_ptr → walk linked list - Each hop: random pointer chase. Cache miss. - 10 hops = 10 cache misses = ~400ns on DRAM - -OUR NODE RECORD (6KB + 32 bytes header): - [32B header: id, seal, metadata] - [2KB plane_S] - [2KB plane_P] - [2KB plane_O] - - To find similar nodes: VPXORD + VPOPCNTDQ on the planes - Scan 1M nodes: ~2ms with cascade (not 400ns × 1M = 400ms pointer chasing) - - But we can ALSO do Neo4j-style adjacency: - Store BF16 edge weights in a compact adjacency structure. - Hot pairs (high similarity) get direct pointers. - Cold pairs (unknown similarity) go through the cascade. -``` - -The hybrid: Neo4j-style adjacency for KNOWN relationships, -cascade scan for DISCOVERY of new relationships. - -```rust -struct SpoNode { - id: u32, - seal: Seal, - planes: [Plane; 3], // S, P, O — 6KB, SIMD-scannable - - // Neo4j-style adjacency for known edges: - first_edge: u32, // index into edge array - edge_count: u16, // known relationships - - // Each edge: - // target_id: u32 (4B) - // truth: NarsTruth (4B = 2×BF16) - // projection: u8 (which SPO projections match) - // Total: 9 bytes per edge -} - -// HOT PATH: "find me the 10 most similar nodes to X" -// → cascade scan over all planes. No adjacency needed. ~2ms for 1M. - -// WARM PATH: "what are X's known relationships?" -// → follow first_edge pointer, read edge_count edges. ~100ns for 50 edges. - -// COLD PATH: "MATCH (a)-[r:KNOWS]->(b) WHERE similarity(a,b) > 0.8" -// → scan BF16 truth values in edge array. 32 per SIMD instruction. -// → then Hamming recomputation for survivors. ~500ns for 10K edges. -``` - ---- - -## THREAD 4: BitGNN Shows the Way — But We Do It on CPU - -BitGNN (ICS 2023): binarizes GNN weights AND features to ±1. -Uses XNOR+popcount for graph convolution. 8-22x speedup on GPU. - -``` -BITGNN ON GPU: - Binary weight matrix W ∈ {0,1}^(N×D) - Binary feature matrix X ∈ {0,1}^(N×D) - Convolution: W ⊗ X = XNOR + popcount - Aggregation: sum over neighbors (scatter_add, NON-DETERMINISTIC) - -US ON CPU: - Binary plane matrix P ∈ {0,1}^(N×16384) - Binary query vector q ∈ {0,1}^16384 - Similarity: P ⊗ q = XOR + popcount = hamming_distance - Aggregation: encounter() on integer accumulator (DETERMINISTIC) -``` - -BitGNN proves binary GNN works. But they still use GPU scatter_add -(non-deterministic) for aggregation. We use CPU integer encounter -(deterministic). Their 8-22x speedup is GPU-to-GPU. Our speedup -is CPU binary vs GPU float — potentially LARGER because: - -- No GPU transfer latency -- 16K-bit model fits in L1 cache (32KB) -- VPOPCNTDQ processes 512 bits per cycle vs GPU warp scheduling overhead -- Deterministic (GPU scatter_add requires sorted reduction for determinism) - -**ACTION: Implement GNN message passing as plane encounter aggregation.** - -```rust -/// GNN message passing in binary. -/// For each node, aggregate neighbors' planes into its own plane. -/// This IS graph convolution in Hamming space. -fn message_passing(graph: &SpoGraph, rounds: usize) { - for _ in 0..rounds { - for node_id in 0..graph.len() { - let node = &graph.nodes[node_id]; - - // Collect messages from neighbors - for edge_idx in node.first_edge..(node.first_edge + node.edge_count as u32) { - let edge = &graph.edges[edge_idx as usize]; - let neighbor = &graph.nodes[edge.target_id as usize]; - - // Weight the message by edge truth (BF16 confidence) - let weight = edge.truth.confidence(); - - if weight > 0.5 { - // Strong edge: encounter toward neighbor's planes - node.planes[0].encounter_toward(&neighbor.planes[0]); - node.planes[1].encounter_toward(&neighbor.planes[1]); - node.planes[2].encounter_toward(&neighbor.planes[2]); - } else { - // Weak edge: encounter away (repulsive) - node.planes[0].encounter_away(&neighbor.planes[0]); - node.planes[1].encounter_away(&neighbor.planes[1]); - node.planes[2].encounter_away(&neighbor.planes[2]); - } - } - // Alpha channel updates automatically via threshold - // This IS the activation function (sign + threshold = BNN sign + STE clamp) - } - } -} -``` - -After K rounds: each node's planes encode K-hop neighborhood structure. -Equivalent to K-layer GCN. But binary, deterministic, CPU, VPOPCNTDQ. - ---- - -## THREAD 5: The Missing Piece — Nobody Has Combined All Four - -``` -EXISTING (proven individually): - ✓ BNN inference: XNOR+popcount replaces matmul (XNOR-Net, 2016) - ✓ Binary GNN: binarized graph convolution (BitGNN, 2023) - ✓ Binary RL: sparse binary latent codes beat continuous (DreamerV3, 2025) - ✓ Semiring graphs: graph algorithms as sparse linear algebra (GraphBLAS) - ✓ Tropical NN: ReLU networks are tropical rational maps (Zhang, 2018) - -COMBINED (nobody has done this): - ✗ BNN + GNN + RL + Semiring + SPO + Deterministic - ✗ Binary graph neural RL with tropical semiring pathfinding - ✗ Hamming cascade world model with integer encounter gradients - ✗ Deterministic f32 truth from binary RL loop - -WE HAVE: - ✓ Binary planes (16K-bit SPO in rustynum) - ✓ Hamming cascade (Belichtungsmesser in hdr.rs) - ✓ Integer encounter (plane.rs accumulator) - ✓ Custom semirings (7 in lance-graph) - ✓ NARS truth values (TruthGate in lance-graph) - ✓ Seal/Staunen (integrity verification) - ✓ AVX-512 SIMD (VPOPCNTDQ + VDPBF16PS + VPCLMULQDQ) - -THE GAP: wiring. The components exist. The connections don't. -``` - -**ACTION: Write the wiring. Not new algorithms. Not new data structures. -Just connect plane.rs encounter() to cascade's band classification -to semiring's path composition to NARS truth revision.** - -``` -WIRING DIAGRAM: - - Observation (new SPO triple) - │ - ▼ - Cascade scan (find similar nodes) ← hdr.rs, simd.rs - │ survivors - ▼ - 2³ SPO projections (7 hamming) ← simd.rs (3 calls + 4 sums) - │ 8 band classifications - ▼ - BF16 truth assembly (exponent+mantissa) ← integer bit packing - │ one BF16 per comparison - ▼ - Edge weight update (BF16 cache) ← VCVTNEPS2BF16 - │ - ├─── Hot path done. <2ms for 1M candidates. - │ - ▼ - Message passing (encounter aggregation) ← plane.rs encounter() - │ planes evolve - ▼ - NARS truth revision (BF16 pair) ← VDPBF16PS for revision terms - │ frequency + confidence updated - ▼ - Tropical pathfinding (HammingMin) ← semiring mxv with min+hamming - │ shortest Hamming paths through the graph - ▼ - f32 hydration (BF16 + tree path) ← bit OR, deterministic - │ - ▼ - GROUND TRUTH (deterministic f32, every bit traceable) -``` - ---- - -## THREAD 6: siboehm's Final Insight — Panel Packing for Our Database - -The GEMM article's key optimization chain applies directly: - -``` -GEMM OPTIMIZATION → CASCADE EQUIVALENT → IMPLEMENTATION -───────────────────────────────────────────────────────── -Loop reorder → stroke-first scan → process stroke 1 for ALL before stroke 2 -L1 tiling → 2KB plane in L1 → already done (L1_CACHE_BOUNDARY.md) -Register accumulate → ZMM accumulator → keep hamming sum in register across strokes -Panel B packing → STROKE-ALIGNED DATABASE → repack candidates for sequential streaming -Prefetch schedule → prefetch next candidate → _mm_prefetch every 128B -Thread partitioning → parallel stroke batches → rayon par_chunks on candidates - -THE 2X WE'RE MISSING: - Panel packing. The database is stored node-by-node (AoS). - Strokes read scattered bytes across nodes. - - Pack it stroke-by-stroke (SoA): - All stroke-1 bytes contiguous. All stroke-2 bytes contiguous. - - This turns the cascade from random-access to streaming. - The hardware prefetcher does the rest. -``` - -**ACTION:** Add a `PackedDatabase` struct to lance-graph: - -```rust -/// Stroke-aligned database layout for cache-optimal cascade scanning. -/// Like GEMM panel packing, but for Hamming cascades. -pub struct PackedDatabase { - stroke1: Vec, // [cand0[0..128], cand1[0..128], ...] contiguous - stroke2: Vec, // [cand0[128..512], cand1[128..512], ...] contiguous - stroke3: Vec, // [cand0[512..2048], cand1[512..2048], ...] contiguous - n_candidates: usize, -} - -impl PackedDatabase { - /// Pack from standard Node layout (AoS → SoA for strokes) - pub fn pack(nodes: &[Node], plane: PlaneIndex) -> Self { ... } - - /// Cascade scan with streaming access pattern - pub fn cascade_scan(&self, query: &[u8; 2048], bands: &[u32; 4]) -> Vec<(usize, u32)> { - let mut survivors_s1 = Vec::new(); - - // PASS 1: sequential scan through stroke1 array - // Hardware prefetcher handles this — no explicit prefetch needed - for i in 0..self.n_candidates { - let offset = i * 128; - let d1 = simd::hamming_distance( - &query[..128], - &self.stroke1[offset..offset+128] - ) as u32; - if d1 * 16 <= bands[2] { - survivors_s1.push((i, d1)); - } - } - - // PASS 2: sequential scan through stroke2 for survivors only - // ... - } -} -``` - ---- - -## PRIORITY ORDER - -``` -# WHAT EFFORT IMPACT -───────────────────────────────────────────────────────────────────── -1. PackedDatabase stroke-aligned layout ~200 LOC 2-3x cascade -2. Binary message passing (encounter aggregation) ~150 LOC enables GNN -3. Wiring: cascade → projections → BF16 → NARS ~300 LOC the full pipeline -4. Binary STE encounter (DreamerV3 equivalent) ~100 LOC enables RL -5. Tropical pathfinding (HammingMin Floyd-Warshall)~200 LOC graph algorithms -6. Neo4j hybrid adjacency (hot edges + cold scan) ~250 LOC query optimization -7. Paper: "Fully Binary RL via Hamming World Models" ~prose claim the territory - -Total new code: ~1200 lines. -Total new capability: BNN + GNN + RL + semiring graph + deterministic f32. -Nobody has combined all four. We'd be first. -``` diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_B_HDR_RENAME.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_B_HDR_RENAME.md deleted file mode 100644 index 28dcbf18..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_B_HDR_RENAME.md +++ /dev/null @@ -1,104 +0,0 @@ -# SESSION_B_HDR_RENAME.md - -## Rename LightMeter → hdr::Cascade (lance-graph only) - -**Repo:** lance-graph (WRITE) -**Scope:** one file rename, one type rename, one module rename. Nothing else. -**Stop when:** `cargo test --workspace` passes. - ---- - -## STEP 1: Rename file - -```bash -cd crates/lance-graph/src/graph/blasgraph -git mv light_meter.rs hdr.rs -``` - -## STEP 2: Update mod.rs - -In `crates/lance-graph/src/graph/blasgraph/mod.rs`: - -```rust -// BEFORE: -pub mod light_meter; - -// AFTER: -pub mod hdr; -``` - -## STEP 3: Rename type inside hdr.rs - -In the renamed `hdr.rs`, find-replace: - -``` -LightMeter → Cascade -``` - -Keep ALL internals unchanged. Just the struct name. - -## STEP 4: Rename methods inside hdr.rs - -``` -cascade_query() → query() -``` - -Add these thin wrappers if they don't exist: - -```rust -impl Cascade { - /// Classify a single distance into a sigma band. - #[inline] - pub fn expose(&self, distance: u32) -> Band { - self.band(distance) // band() already exists, expose is the public name - } - - /// Single pair test: is this distance in a useful band? - #[inline] - pub fn test_distance(&self, distance: u32) -> bool { - self.band(distance) <= Band::Good - } -} -``` - -## STEP 5: Update internal references - -Search for any file in lance-graph that imports `light_meter` or `LightMeter`: - -```bash -grep -rn "light_meter\|LightMeter" crates/ --include="*.rs" -``` - -Update each to use `hdr` and `Cascade`. - -## STEP 6: Update tests - -In `crates/lance-graph/tests/hdr_proof.rs` (and any other test files): - -``` -use lance_graph::graph::blasgraph::light_meter::LightMeter -→ -use lance_graph::graph::blasgraph::hdr::Cascade -``` - -Replace `LightMeter::` with `Cascade::` in test bodies. - -## STEP 7: Verify - -```bash -cargo test --workspace -cargo clippy --workspace -- -D warnings -``` - ---- - -## NOT IN SCOPE - -``` -× Don't add ReservoirSample improvements (already merged in PR #9) -× Don't add PreciseMode (Session C cross-pollinates this) -× Don't add incremental Stroke 2 (Session C) -× Don't touch SIMD dispatch (comes with BitVec rebuild) -× Don't touch rustynum (Session A does that) -× Don't rename Band, RankedHit, ShiftAlert (names already match target) -``` diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_D_LENS_CORRECTION.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_D_LENS_CORRECTION.md deleted file mode 100644 index 25b97a9e..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_D_LENS_CORRECTION.md +++ /dev/null @@ -1,640 +0,0 @@ -# SESSION_D_LENS_CORRECTION.md - -## Gamma + Cushion Lens Correction + Self-Organizing Boundary Fold - -**Repo:** rustynum (WRITE), lance-graph (WRITE) -**Prereq:** Session C completed (hdr::Cascade has ReservoirSample, skewness, kurtosis, Welford) -**Scope:** lens correction pipeline, boundary folding, adaptive healing. Nothing else. -**Stop when:** `cargo test --workspace` passes in both repos, correction tests pass. - ---- - -## CONTEXT - -Session C ported ReservoirSample with skewness and kurtosis detection. -The current system uses these to AUTO-SWITCH between parametric (σ bands) -and empirical (quantile bands). That's a binary choice: normal or not. - -This session replaces the binary switch with a continuous lens correction -that MAKES parametric bands work for any distribution shape. The empirical -mode becomes a diagnostic check, not an alternative code path. - -Three corrections applied in order: -1. **Gamma:** fixes skewness (left/right asymmetry) -2. **Cushion:** fixes kurtosis (heavy/light tails) -3. **Fold:** moves boundaries to density troughs (minimum pressure) - -After all three: σ-based bands work on any distribution. - ---- - -## VERIFY SESSION C COMPLETED - -```bash -cd rustynum -cargo test -p rustynum-core -- hdr::reservoir # must pass -cargo test -p rustynum-core -- hdr::shift # must pass -# Confirm these exist in hdr.rs: -grep "fn skewness" rustynum-core/src/hdr.rs # must find it -grep "fn kurtosis" rustynum-core/src/hdr.rs # must find it -grep "struct ReservoirSample" rustynum-core/src/hdr.rs # must find it -``` - ---- - -## STEP 1: Add gamma field + LUT to Cascade - -In `rustynum-core/src/hdr.rs`, add to the Cascade struct: - -```rust -pub struct Cascade { - // ...existing fields from Session C... - - /// Gamma correction for skew. Fixed-point: 100 = γ=1.0 (no correction). - /// γ > 100: right-skewed data, stretches left tail. - /// γ < 100: left-skewed data, stretches right tail. - /// Derived from reservoir skewness. Updated on fold. - gamma: u16, - - /// Kurtosis correction. Fixed-point: 100 = normal (κ=3.0). - /// > 100: heavy tails, widen extreme bands. - /// < 100: light tails, narrow extreme bands. - /// Derived from reservoir kurtosis. Updated on fold. - kappa: u16, - - /// Gamma lookup table. 256 entries. Integer. - /// Maps normalized distance [0..255] to corrected distance. - /// Rebuilt on calibrate/recalibrate/fold. Not on every query. - gamma_lut: Box<[u32; 256]>, - - /// Boundary pressure: density at each band boundary. - /// Updated on fold. Used for adaptive healing decisions. - pressure: [u32; 4], -} -``` - -Initialize in `calibrate()`: - -```rust -impl Cascade { - pub fn calibrate(sample: &[u32]) -> Self { - let mut c = Self { - // ...existing initialization... - gamma: 100, // no correction initially - kappa: 100, // no correction initially - gamma_lut: Box::new([0u32; 256]), // identity initially - pressure: [0; 4], // unknown initially - }; - // Identity LUT: gamma_lut[i] = i * μ / 255 - c.rebuild_gamma_lut(); - c - } -} -``` - ---- - -## STEP 2: Gamma correction (skewness → power-law LUT) - -```rust -impl Cascade { - /// Derive gamma from reservoir skewness. - /// Pearson's second skewness maps linearly to gamma: - /// skew = 0 → γ = 1.0 (symmetric) - /// skew > 0 → γ > 1.0 (right-skewed, stretch compressed left side) - /// skew < 0 → γ < 1.0 (left-skewed, stretch compressed right side) - fn calibrate_gamma(&mut self) { - let skew = self.reservoir.skewness(self.mu, self.sigma); - // γ = 1.0 + skew × 0.15, clamped to [0.5, 2.0] - // In fixed-point: gamma = 100 + skew * 15, clamped to [50, 200] - self.gamma = (100 + skew * 15).clamp(50, 200) as u16; - self.rebuild_gamma_lut(); - } - - /// Build the 256-entry gamma LUT. Float used HERE ONLY (on calibration). - /// Hot path uses integer table lookup. - fn rebuild_gamma_lut(&mut self) { - let g = self.gamma as f64 / 100.0; - for i in 0..256 { - let x = (i as f64 + 0.5) / 256.0; // normalized [0, 1], avoid x=0 - let corrected = x.powf(g); - self.gamma_lut[i] = (corrected * self.mu as f64) as u32; - } - } - - /// Apply gamma correction to a raw distance. Integer LUT lookup. - /// Cost: 1 multiply + 1 table lookup. ~2 cycles. - #[inline] - fn gamma_correct(&self, distance: u32) -> u32 { - if self.gamma == 100 { return distance; } // fast path: no correction - // Normalize distance to [0, 255] relative to μ - let idx = ((distance as u64 * 255) / self.mu.max(1) as u64) as usize; - self.gamma_lut[idx.min(255)] - } -} -``` - ---- - -## STEP 3: Cushion correction (kurtosis → cubic tail adjustment) - -```rust -impl Cascade { - /// Derive kappa from reservoir kurtosis. - /// Reservoir kurtosis is scaled ×100: normal = 300. - /// We normalize: kappa = kurtosis × 100 / 300. - /// So kappa 100 = normal, >100 = heavy tails, <100 = light tails. - fn calibrate_kappa(&mut self) { - let kurt = self.reservoir.kurtosis(self.mu, self.sigma); - self.kappa = (kurt * 100 / 300).clamp(30, 300) as u16; - } - - /// Apply cushion correction to fix tail weight. - /// Normal tails (kappa=100): no correction. - /// Heavy tails (kappa>100): push extremes outward (widen tail bands). - /// Light tails (kappa<100): push extremes inward (narrow tail bands). - /// - /// Uses cubic term: correction grows with cube of deviation from μ. - /// At center (d ≈ μ): correction ≈ 0 (center is always stable). - /// At tails: correction dominates. - /// - /// Cost: ~5 integer ops. No float. - #[inline] - fn cushion_correct(&self, distance: u32) -> u32 { - if self.kappa == 100 { return distance; } // fast path: normal tails - - let d = distance as i64; - let mu = self.mu as i64; - let deviation = d - mu; - - // kappa_norm: 100 = normal - let kappa_norm = self.kappa as i64; - - // Cubic correction scaled to prevent overflow: - // correction = deviation³ / μ² × (1 - 100/κ) / 100 - // - // For heavy tails (κ>100): (1 - 100/κ) > 0 → pushes tails OUT - // For light tails (κ<100): (1 - 100/κ) < 0 → pushes tails IN - // For normal (κ=100): (1 - 100/κ) = 0 → no correction - let mu_sq = (mu * mu).max(1); - let kappa_factor = 100 - (10000 / kappa_norm.max(1)); // ×100 scaled - let correction = deviation * deviation / mu_sq.max(1) * deviation - * kappa_factor / 10000; - - (d + correction).clamp(0, mu * 3) as u32 - } -} -``` - ---- - -## STEP 4: Compose corrections in expose() - -```rust -impl Cascade { - /// Band classification with full lens correction pipeline. - /// Raw distance → gamma (skew) → cushion (kurtosis) → band lookup. - /// Cost: ~8 cycles total (2 gamma + 5 cushion + 1 compare). - #[inline] - pub fn expose(&self, distance: u32) -> Band { - let d = self.cushion_correct(self.gamma_correct(distance)); - // NOTE: gamma first, then cushion. Gamma fixes the asymmetry - // so the cubic cushion term operates on a symmetric-ish distribution. - - let bands = if self.use_empirical { &self.empirical_bands } else { &self.bands }; - if d < bands[0] { Band::Foveal } - else if d < bands[1] { Band::Near } - else if d < bands[2] { Band::Good } - else if d < bands[3] { Band::Weak } - else { Band::Reject } - } -} -``` - ---- - -## STEP 5: Self-organizing boundary fold - -The boundaries MOVE toward density troughs. Like a soap film finding -minimum energy. Reduces the need for healing by eliminating ambiguity. - -```rust -impl Cascade { - /// Move each boundary toward the nearest density trough. - /// Reduces classification pressure: fewer candidates fall on boundaries. - /// - /// Called during periodic maintenance (every ~5000 observations), - /// NOT on every query. The fold is expensive (sorts reservoir). - pub fn fold_boundaries(&mut self) { - if self.reservoir.len() < 500 { return; } - - let mut sorted = self.reservoir.samples.clone(); - sorted.sort_unstable(); - - let window = (self.sigma / 4).max(1); - - for i in 0..4 { - let current = self.bands[i]; - let search_lo = current.saturating_sub(self.sigma); - let search_hi = current.saturating_add(self.sigma); - - // Slide a window across [lo, hi], find position with minimum density - let mut min_density = u32::MAX; - let mut best_pos = current; - - let mut pos = search_lo; - while pos <= search_hi { - // Count samples within ±window of pos - let count = sorted.iter() - .filter(|&&d| d >= pos.saturating_sub(window) - && d <= pos.saturating_add(window)) - .count() as u32; - - if count < min_density { - min_density = count; - best_pos = pos; - } - pos += window / 2; // slide by half-window for resolution - } - - self.bands[i] = best_pos; - self.pressure[i] = min_density; - } - - // Ensure strict monotonicity: b₀ < b₁ < b₂ < b₃ - for i in 1..4 { - if self.bands[i] <= self.bands[i - 1] { - self.bands[i] = self.bands[i - 1] + 1; - } - } - } -} -``` - ---- - -## STEP 6: Adaptive healing using boundary pressure - -The pressure from fold_boundaries tells the cascade WHERE to spend bytes. - -```rust -impl Cascade { - /// Determine how many bytes to read based on boundary pressure. - /// High pressure boundary nearby → read more bytes for certainty. - /// Low pressure (clean gap) → accept the projection, save bytes. - /// - /// Returns: number of bytes to read total (including already read). - pub fn healing_target( - &self, - projected: u32, - sigma_est: u32, - bytes_read: usize, - total_bytes: usize, - ) -> usize { - // Find nearest boundary and its pressure - let mut nearest_dist = u32::MAX; - let mut nearest_pressure = 0u32; - - for i in 0..4 { - let dist_to_boundary = (projected as i64 - self.bands[i] as i64) - .unsigned_abs() as u32; - if dist_to_boundary < nearest_dist { - nearest_dist = dist_to_boundary; - nearest_pressure = self.pressure[i]; - } - } - - // Far from any boundary (> 3σ): fully confident, no healing - if nearest_dist > sigma_est * 3 { - return bytes_read; - } - - // Urgency: pressure × proximity (both high = maximum healing) - let urgency = nearest_pressure as u64 - * sigma_est as u64 - / nearest_dist.max(1) as u64; - - let additional = match urgency { - 0..=50 => 0, // low urgency, accept uncertainty - 51..=200 => 64, // one cache line - 201..=500 => 256, // moderate healing - 501..=1000 => 512, // significant healing - _ => total_bytes - bytes_read, // go to full - }; - - // SIMD-align to 64 bytes - ((bytes_read + additional + 63) & !63).min(total_bytes) - } -} -``` - ---- - -## STEP 7: Wire into cascade query - -Update `Cascade::query()` to use corrections and adaptive healing: - -```rust -// Inside the cascade query loop, REPLACE the fixed band check: - -// BEFORE (fixed threshold): -// if projected > self.bands[2] { continue; } - -// AFTER (corrected + adaptive): -let projected = d1 * (total_bytes / s1_bytes) as u32; -let corrected = self.cushion_correct(self.gamma_correct(projected)); -let sigma_est = estimation_sigma(s1_bytes, projected, total_bytes); - -// Quick rejection on corrected distance -if self.expose_raw(corrected) == Band::Reject { continue; } - -// Boundary proximity check: do we need healing? -let heal_to = self.healing_target(corrected, sigma_est, s1_bytes, total_bytes); - -if heal_to > s1_bytes { - // Read additional bytes (Tetris piece fills the gap) - let d_extra = hamming_fn(&query[s1_bytes..heal_to], &cand[s1_bytes..heal_to]) as u32; - let cumulative = d1 + d_extra; - let projected2 = cumulative * (total_bytes / heal_to) as u32; - let corrected2 = self.cushion_correct(self.gamma_correct(projected2)); - - if self.expose_raw(corrected2) == Band::Reject { continue; } - - // Continue to full if needed... -} -``` - -Add helper: - -```rust -impl Cascade { - /// Raw band classification without the expose() public API overhead. - #[inline] - fn expose_raw(&self, corrected_distance: u32) -> Band { - let bands = if self.use_empirical { &self.empirical_bands } else { &self.bands }; - if corrected_distance < bands[0] { Band::Foveal } - else if corrected_distance < bands[1] { Band::Near } - else if corrected_distance < bands[2] { Band::Good } - else if corrected_distance < bands[3] { Band::Weak } - else { Band::Reject } - } -} -``` - ---- - -## STEP 8: Periodic maintenance (integrate gamma + kappa + fold) - -Wire the corrections into the observe() path: - -```rust -impl Cascade { - pub fn observe(&mut self, distance: u32) -> Option { - // ...existing Welford + reservoir update from Session C... - - // Periodic maintenance every 5000 observations - if self.running_count % 5000 == 0 && self.reservoir.len() >= 500 { - self.calibrate_gamma(); // update γ from skewness - self.calibrate_kappa(); // update κ from kurtosis - self.fold_boundaries(); // move bands to density troughs - } - - // ...existing shift detection... - } - - pub fn recalibrate(&mut self, alert: &ShiftAlert) { - // ...existing reset from Session C... - - // Reset corrections to neutral - self.gamma = 100; - self.kappa = 100; - self.pressure = [0; 4]; - self.rebuild_gamma_lut(); - } -} -``` - ---- - -## STEP 9: Port to lance-graph - -Copy the correction logic into `lance-graph/crates/lance-graph/src/graph/blasgraph/hdr.rs`. - -The lance-graph version is simpler because it operates on `&[u64]` word arrays -instead of `&[u8]` byte slices. Same gamma LUT. Same cushion cubic. Same fold. - -```bash -cd ../lance-graph # or wherever it is -# Read rustynum's hdr.rs, copy gamma_correct, cushion_correct, -# fold_boundaries, healing_target, calibrate_gamma, calibrate_kappa -# into the Cascade struct in lance-graph's hdr.rs. -``` - -Adapt field types if needed (lance-graph may use different integer widths). - ---- - -## STEP 10: Tests - -```rust -#[test] -fn gamma_identity_when_symmetric() { - let hdr = Cascade::calibrate(&[8192; 200]); - assert_eq!(hdr.gamma, 100); // symmetric data → no correction - assert_eq!(hdr.gamma_correct(8000), 8000); // identity - assert_eq!(hdr.gamma_correct(8192), 8192); // identity -} - -#[test] -fn gamma_corrects_right_skew() { - let mut hdr = Cascade::calibrate(&[8192; 100]); - - // Feed right-skewed data (many low distances, few high) - for i in 0..2000 { - let d = 7000 + (i % 200); // clustered below μ - hdr.observe(d); - } - for i in 0..200 { - let d = 9000 + (i * 10); // sparse tail above μ - hdr.observe(d); - } - - // Force recalibration - hdr.calibrate_gamma(); - - // γ should be > 100 (right-skewed → stretch left side) - assert!(hdr.gamma > 100, "Right-skewed data should give γ > 1.0, got {}", hdr.gamma); - - // A distance below μ should be STRETCHED (corrected > raw) - let raw = 7500; - let corrected = hdr.gamma_correct(raw); - // Gamma > 1 on [0,1] range: x^γ < x for x < 1, so corrected < raw - // (stretches the compressed left side toward center) - assert_ne!(corrected, raw, "Gamma should change the distance"); -} - -#[test] -fn cushion_identity_when_normal_kurtosis() { - let mut hdr = Cascade::calibrate(&[8192; 200]); - hdr.kappa = 100; // normal - - assert_eq!(hdr.cushion_correct(8000), 8000); // center: no correction - assert_eq!(hdr.cushion_correct(8192), 8192); // at μ: no correction -} - -#[test] -fn cushion_widens_heavy_tails() { - let mut hdr = Cascade::calibrate(&[8192; 200]); - hdr.mu = 8192; - hdr.kappa = 200; // heavy tails (2× normal kurtosis) - - // Distance far from μ should be pushed further out - let raw = 7000; // 1192 below μ - let corrected = hdr.cushion_correct(raw); - assert!(corrected < raw, - "Heavy-tail cushion should push low distances further from μ: raw={} corrected={}", - raw, corrected); -} - -#[test] -fn fold_moves_boundary_to_trough() { - let mut hdr = Cascade::calibrate(&[8192; 100]); - - // Create bimodal reservoir: peak at 7000 and 8500, trough at 7800 - let mut bimodal: Vec = Vec::new(); - for _ in 0..500 { bimodal.push(7000 + (fastrand() % 200)); } // peak 1 - for _ in 0..500 { bimodal.push(8500 + (fastrand() % 200)); } // peak 2 - // Note: gap around 7800 — no samples there - - for &d in &bimodal { - hdr.reservoir.observe(d); - } - - // Before fold: bands are at σ-based positions - let band_before = hdr.bands[1]; // Near/Good boundary - - hdr.fold_boundaries(); - - let band_after = hdr.bands[1]; - - // The boundary should have moved toward the trough (~7800) - // It should be closer to 7800 than it was before - let dist_before = (band_before as i64 - 7800).unsigned_abs(); - let dist_after = (band_after as i64 - 7800).unsigned_abs(); - - assert!(dist_after <= dist_before, - "Fold should move boundary toward trough: before={} after={} trough=7800", - band_before, band_after); -} - -#[test] -fn fold_reduces_pressure() { - let mut hdr = Cascade::calibrate(&[8192; 100]); - - // Fill reservoir with data that clusters around default boundaries - for _ in 0..1000 { - let d = hdr.bands[1] + (fastrand() % 20) - 10; // right on the boundary - hdr.reservoir.observe(d); - } - - hdr.fold_boundaries(); - - // After fold, boundary should have moved away from the cluster - // Pressure should be lower (fewer candidates on the boundary) - assert!(hdr.pressure[1] < 500, - "Fold should reduce boundary pressure, got {}", hdr.pressure[1]); -} - -#[test] -fn healing_reads_more_at_high_pressure_boundary() { - let mut hdr = Cascade::calibrate(&[8192; 200]); - hdr.sigma = 64; - hdr.pressure = [10, 500, 10, 10]; // b₁ has high pressure - - let sigma_est = 256; // 1/16 sample estimation σ - - // Distance near high-pressure boundary b₁: should heal - let near_b1 = hdr.bands[1] + 30; // close to b₁ - let target = hdr.healing_target(near_b1, sigma_est, 128, 2048); - assert!(target > 128, "Should read more bytes near high-pressure boundary"); - - // Distance far from any boundary: should not heal - let far_away = hdr.bands[0] - 500; // deep in Foveal - let target_far = hdr.healing_target(far_away, sigma_est, 128, 2048); - assert_eq!(target_far, 128, "Should not heal when far from boundaries"); -} - -#[test] -fn full_pipeline_correction_converges() { - let mut hdr = Cascade::calibrate(&[8192; 100]); - - // Feed skewed + heavy-tailed data over multiple maintenance cycles - for round in 0..5 { - for i in 0..5000 { - // Right-skewed, heavy-tailed distribution - let base = 7000 + (i % 300); - let tail = if i % 50 == 0 { 2000 } else { 0 }; // occasional outlier - hdr.observe(base + tail); - } - - // After 5000 observations: maintenance triggers gamma + kappa + fold - println!("Round {}: γ={} κ={} bands={:?} pressure={:?}", - round, hdr.gamma, hdr.kappa, hdr.bands, hdr.pressure); - } - - // After convergence: gamma should be non-trivial (skewed data) - assert_ne!(hdr.gamma, 100, "Gamma should adapt to skewed data"); - // Kappa should reflect heavy tails - assert_ne!(hdr.kappa, 100, "Kappa should adapt to heavy-tailed data"); - // Boundaries should have folded to density troughs - // (hard to assert exact values, but monotonicity must hold) - for i in 1..4 { - assert!(hdr.bands[i] > hdr.bands[i-1], "Bands must be monotonic"); - } -} - -/// Simple fast random for tests (not for production reservoir) -fn fastrand() -> u32 { - use std::cell::Cell; - thread_local! { static STATE: Cell = Cell::new(12345); } - STATE.with(|s| { - let mut x = s.get(); - x ^= x << 13; - x ^= x >> 7; - x ^= x << 17; - s.set(x); - x as u32 - }) -} -``` - ---- - -## STEP 11: Verify both repos - -```bash -# Rustynum: -RUSTFLAGS="-C target-cpu=native" cargo test --workspace -cargo clippy --workspace -- -D warnings -cargo test -p rustynum-core -- hdr # all hdr tests - -# Lance-graph: -cd ../lance-graph -cargo test --workspace -cargo clippy --workspace -- -D warnings -``` - ---- - -## NOT IN SCOPE - -``` -× Don't add PreciseMode to lance-graph (separate session) -× Don't touch SIMD dispatch (comes with BitVec rebuild) -× Don't add GPU backends (roadmap) -× Don't modify Plane/Node/Mask (separate prompt) -× Don't touch simd_avx512.rs or simd.rs (Session A already did this) -× Don't add chromatic aberration correction (multimodal per-mode gamma) - → This is a future extension if bimodal data needs per-peak correction. - → For now, the fold_boundaries handles bimodal by finding the trough. -``` diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_FALKORDB_CROSSCHECK.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_FALKORDB_CROSSCHECK.md deleted file mode 100644 index 51717331..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_FALKORDB_CROSSCHECK.md +++ /dev/null @@ -1,301 +0,0 @@ -# SESSION_FALKORDB_CROSSCHECK.md - -## Mission: Reverse-Engineer FalkorDB-rs-next-gen → Connect Dots to Lance-Graph - -**Context:** FalkorDB is the only Rust graph database with GraphBLAS semiring algebra. -They are rewriting their C engine in Rust (`falkordb-rs-next-gen`). Their architecture -descends from RedisGraph, which we also transcoded into lance-graph via HoloGraph. -We share DNA. We need to know what they solved, what they got wrong, and what we -can learn to make lance-graph the permissively-licensed successor that captures -Kuzu's orphaned users AND FalkorDB's SSPL-blocked users. - -**License note:** FalkorDB core = SSPL v1 (toxic for cloud/service deployment). -Their Rust CLIENT (falkordb-rs) = MIT. The next-gen ENGINE license: check `LICENSE` file. -Our lance-graph = needs to be Apache 2.0 or MIT to win the market. - ---- - -## STEP 1: Clone and Inventory - -```bash -cd /home/claude -git clone https://github.com/FalkorDB/falkordb-rs-next-gen.git falkordb-ng -cd falkordb-ng -find . -name "*.rs" -not -path "*/target/*" | head -100 -find . -name "*.rs" -not -path "*/target/*" | wc -l -cat Cargo.toml -``` - -Map their crate structure. What workspace members? What dependencies? -Specifically look for: GraphBLAS bindings, sparse matrix types, Cypher parser, -query planner, execution engine, storage layer. - ---- - -## STEP 2: GraphBLAS Integration — How Do They Bind? - -``` -QUESTIONS: - 1. Do they use SuiteSparse:GraphBLAS via FFI (C library dependency)? - Or did they rewrite GraphBLAS operations in pure Rust? - 2. What semirings do they support? Just the standard ones or custom? - 3. How do they dispatch semiring operations? FactoryKernels? JIT? Enum match? - 4. What sparse matrix format? CSR? CSC? Hypersparse? Multiple? - 5. Do they support user-defined semirings or is it fixed? -``` - -Search for: -```bash -grep -rn "GraphBLAS\|GrB_\|graphblas\|semiring\|Semiring" --include="*.rs" | head -50 -grep -rn "extern.*\"C\"\|#\[link\|ffi\|bindgen" --include="*.rs" | head -20 -grep -rn "sparse\|CSR\|CSC\|adjacency" --include="*.rs" | head -30 -``` - -**Why this matters:** If they FFI to SuiteSparse C library, they carry a MASSIVE -dependency (SuiteSparse is ~500K LOC of C). We have pure Rust semirings in -lance-graph. If their Rust rewrite is pure Rust GraphBLAS, study HOW they -implemented it — sparse matrix multiply, semiring dispatch, element-wise ops. - ---- - -## STEP 3: Cypher Parser — What Do They Support? - -```bash -grep -rn "MATCH\|RETURN\|WHERE\|CREATE\|MERGE\|DELETE\|SET\|cypher\|parser\|ast\|AST" --include="*.rs" | head -40 -find . -name "*parser*" -o -name "*cypher*" -o -name "*ast*" -not -path "*/target/*" -``` - -**QUESTIONS:** - 1. Hand-written parser or parser generator (pest, nom, lalrpop)? - 2. What subset of openCypher? Full spec or limited? - 3. How does the AST map to GraphBLAS operations? - (This is the Cypher → semiring compilation step) - 4. Do they have a query optimizer? Cost-based? Rule-based? - 5. How do they handle MATCH patterns with variable-length paths? - (This is where Bellman-Ford / BFS kicks in) - -**Why this matters:** Our DataFusion planner already does Cypher → plan. -But their compilation to GraphBLAS semiring ops is what we need to study. -The mapping from `MATCH (a)-[r:KNOWS]->(b)` to `grb_mxv` with the right -semiring is the critical path. - ---- - -## STEP 4: Sparse Matrix Representation — Memory Layout - -```bash -grep -rn "struct.*Matrix\|struct.*Sparse\|struct.*Graph\|adjacency" --include="*.rs" | head -30 -# Look for the core graph data structure -find . -name "*graph*" -o -name "*matrix*" -o -name "*storage*" -not -path "*/target/*" -``` - -**QUESTIONS:** - 1. How do they store the adjacency matrix in memory? - (FalkorDB C version uses SuiteSparse GrB_Matrix internally) - 2. How do they store node properties? Separate columns? Inline? - 3. How do they store relationship properties (edge weights)? - 4. How do they handle typed relationships (multiple adjacency matrices)? - 5. What's their memory layout for SIMD? 64-byte aligned? - 6. Do they use memory-mapped files? Or pure heap? - -**Why this matters:** Their memory layout determines whether we can replace -their scalar edge weights with our binary Planes. If their adjacency matrix -stores `f64` per edge, we need to understand how to substitute `BitVec` (2KB) -or `BF16` (2 bytes) without breaking the semiring dispatch. - -**COMPARISON TABLE TO BUILD:** -``` -ASPECT FALKORDB-RS-NG OUR LANCE-GRAPH -──────────────────────────────────────────────────────────── -Edge weight type f64? i64? property? BitVec (16K-bit) + BF16 cache -Node representation Node ID + properties Node (3 × Plane = 6KB) -Adjacency format Sparse matrix (CSR?) Sparse matrix + Plane distance -Semiring dispatch FFI? enum match? enum match on HdrSemiring -Storage backend Redis? Memory? File? Lance format (NVMe columnar) -Query language openCypher openCypher (DataFusion) -Query optimizer ? DataFusion cost-based -SIMD SuiteSparse auto-vec? Hand-written AVX-512 -``` - ---- - -## STEP 5: Query Execution Pipeline - -```bash -# Trace the execution path from query string to result -grep -rn "fn.*execute\|fn.*query\|fn.*eval\|fn.*run" --include="*.rs" | head -30 -# Look for the execution engine -find . -name "*exec*" -o -name "*engine*" -o -name "*eval*" -not -path "*/target/*" -``` - -**QUESTIONS:** - 1. What's the execution model? Volcano (pull)? Push-based? Vectorized? - (Kuzu was vectorized, FalkorDB C was pull-based) - 2. How do they handle multi-hop patterns? Iterative mxv? Recursive? - 3. Do they support aggregation? GROUP BY? COLLECT? - 4. How do they handle OPTIONAL MATCH (left outer join in graph)? - 5. Do they pipeline results or materialize intermediate matrices? - -**Why this matters:** DataFusion gives us vectorized push-based execution -for free. If FalkorDB uses pull-based, we're already faster for analytics. -But their GraphBLAS integration might give them advantages for iterative -algorithms (PageRank, connected components) where mxv is called repeatedly. - ---- - -## STEP 6: What They DON'T Have (Our Advantages) - -After full inventory, explicitly document what FalkorDB-rs-next-gen LACKS -that we have: - -``` -EXPECTED MISSING: - ✗ Binary vector representations (Plane, BitVec, 16K-bit) - ✗ Bundle operation (majority vote → concept formation) - ✗ Cascade search (HDR multi-resolution early rejection) - ✗ BF16 truth values on edges - ✗ NARS truth (frequency, confidence) - ✗ Seal/Staunen (Merkle integrity verification) - ✗ encounter() (INSERT that also trains) - ✗ Deterministic RL (integer-only learning loop) - ✗ Fibonacci/Prime encoding - ✗ Tropical attention (cascade = multi-head attention) - ✗ Lance format persistence (NVMe columnar, ACID versioning) - ✗ Permissive license (they are SSPL) -``` - -Verify each. If they DO have any of these, document HOW they implemented it. - ---- - -## STEP 7: What They Have That We Should Steal - -After inventory, document what they solved that we haven't: - -``` -EXPECTED LEARNINGS: - ? How they compile Cypher patterns to semiring mxv calls - ? How they handle variable-length paths (Kleene star) - ? How they index for fast node/edge lookup by property - ? How they handle graph mutations (CREATE, DELETE, SET) - ? How they manage memory for large graphs - ? How they handle concurrency (multiple readers/writers) - ? How they expose the Rust API to Python - ? How they do TCK (Technology Compatibility Kit) testing for Cypher compliance - ? How they handle schema-free properties on nodes and edges -``` - ---- - -## STEP 8: Architecture Bridge Document - -Produce a document mapping FalkorDB-rs-next-gen concepts to lance-graph: - -``` -FALKORDB CONCEPT → LANCE-GRAPH EQUIVALENT STATUS -────────────────────────────────────────────────────────────────── -GrB_Matrix → GrBMatrix (blasgraph/matrix.rs) EXISTS -GrB_Vector → GrBVector (blasgraph/vector.rs) EXISTS -GrB_Semiring → HdrSemiring (blasgraph/semiring.rs) EXISTS -Cypher parser → ast.rs + DataFusion planner EXISTS -Node properties → Plane fields (acc, bits, alpha) DIFFERENT -Edge properties → BF16 truth + projection byte DIFFERENT -GRAPH.QUERY command → CypherQuery::execute() EXISTS -Multi-graph → select_graph() EXISTS? -Redis protocol → NOT NEEDED (embedded) N/A -SuiteSparse FFI → NOT NEEDED (pure Rust semirings) N/A -``` - ---- - -## STEP 9: Competitive Positioning Document - -Write a document for potential Kuzu/FalkorDB users explaining: - -``` -IF YOU'RE COMING FROM KUZU: - ✓ Same: Embedded, Cypher, fast, Rust - ✓ Better: binary representations, learning, deterministic - ✓ Different: Lance storage (versioned, NVMe-optimized) - ✗ Missing: [list anything Kuzu had that we don't yet] - -IF YOU'RE COMING FROM FALKORDB: - ✓ Same: GraphBLAS semirings, Cypher, Rust - ✓ Better: permissive license, embedded (no Redis), binary planes, learning - ✓ Different: Lance storage instead of Redis - ✗ Missing: [list anything FalkorDB has that we don't yet] - -IF YOU'RE USING SEMANTIC KERNEL / CREWAI: - ✓ We replace: the vector DB + knowledge graph they connect to - ✓ We add: learning (the DB gets smarter with use) - ✓ Integration: Python bindings, Lance format ↔ Arrow ↔ Pandas -``` - ---- - -## STEP 10: Priority Action Items - -Based on the crosscheck, produce a prioritized list: - -``` -CRITICAL (blocks adoption): - ? [whatever Cypher features they support that we don't] - ? [whatever graph operations they have that we lack] - -HIGH (competitive parity): - ? [optimizations they have that improve our performance] - ? [API patterns that their users expect] - -MEDIUM (differentiation): - ? [things we should steal from their architecture] - ? [patterns we should adapt for our binary substrate] - -LOW (nice to have): - ? [features unique to Redis that we don't need] -``` - ---- - -## FILES TO PRODUCE - -``` -1. FALKORDB_INVENTORY.md — complete file/type/method map of their codebase -2. FALKORDB_VS_LANCE.md — side-by-side comparison table -3. FALKORDB_STEAL_LIST.md — what to adapt for lance-graph -4. COMPETITIVE_POSITION.md — user-facing migration guide -5. CYPHER_COVERAGE_GAP.md — which Cypher features we need to add -``` - -Push all to `.claude/` in lance-graph repo. - ---- - -## KEY CONTEXT FILES TO READ FIRST - -Before starting the crosscheck, read these files from our repos for context: - -``` -OUR ARCHITECTURE: - rustynum/.claude/ARCHITECTURE_INDEX.md — master index - rustynum/.claude/INVENTORY_MAP.md — our complete type inventory - rustynum/.claude/BF16_SEMIRING_EPIPHANIES.md — the 5:2 semiring split - rustynum/.claude/RESEARCH_THREADS.md — DreamerV3, BitGNN connections - rustynum/.claude/DEEP_ADJACENT_EXPLORATION.md — RDF-3X RISC design - -OUR BLASGRAPH: - lance-graph/crates/lance-graph/src/graph/blasgraph/semiring.rs - lance-graph/crates/lance-graph/src/graph/blasgraph/ops.rs - lance-graph/crates/lance-graph/src/graph/blasgraph/types.rs - lance-graph/crates/lance-graph/src/graph/blasgraph/matrix.rs - lance-graph/crates/lance-graph/src/graph/blasgraph/hdr.rs - -OUR DATAFUSION PLANNER: - lance-graph/crates/lance-graph/src/datafusion_planner/ - lance-graph/crates/lance-graph/src/ast.rs -``` - -The goal is NOT to copy FalkorDB. The goal is to understand their architectural -decisions so we can build the system they WOULD have built if they had binary -planes, BF16 truth values, encounter-based learning, cascade search, and a -permissive license. We are not competing with their code. We are competing -with their POSITION in the market — and we have better technology. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_J_PACKED_DATABASE.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_J_PACKED_DATABASE.md deleted file mode 100644 index 4b05e4e2..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_J_PACKED_DATABASE.md +++ /dev/null @@ -1,475 +0,0 @@ -# SESSION_J: PackedDatabase — Panel Packing for Cascade Search - -## Mission: Repack candidate database so cascade strokes are contiguous in memory - -**The benchmark proved the problem:** -``` -Batch hamming 1K candidates: 221M cand/s (fits cache, scattered OK) -Batch hamming 1M candidates: 57M cand/s (L3 bandwidth bound, scattered kills us) - 3.9x degradation from cache pressure -``` - -**The fix is siboehm's panel packing applied to binary search instead of GEMM.** - -siboehm's GEMM optimization chain (https://siboehm.com/articles/22/Fast-MMM-on-CPU): -``` -Naive: 4481ms -Loop reorder: 89ms (50x — cache-aware inner loop) -L1 tiling: 70ms (1.3x — tile to L1 size) -Panel packing: 35ms (2x — sequential memory access) -MKL: 8ms (4x — register blocking + prefetch + threading) -``` - -Panel packing alone = 2x. That's our low-hanging fruit. -Applied to cascade: 57M → ~110M candidates/s. Maybe more because -the prefetcher is PERFECT for sequential access patterns. - ---- - -## THE PARALLEL: GEMM Panel Packing = Cascade Stroke Packing - -``` -GEMM (siboehm): CASCADE (us): -───────────────────────────────────────────────────────────── -Matrix B (N×K) Database (N candidates × 2KB each) -Column panel (K×NR block) Stroke region (128B × N block) -Panel packing: reorder B Stroke packing: reorder database - so panel columns are contiguous so stroke-1 bytes are contiguous -Inner loop: sequential FMA Inner loop: sequential XOR+popcount - across contiguous panel across contiguous stroke -Prefetcher handles sequential Prefetcher handles sequential -Register accumulators (6×NR) ZMM accumulators (8 × u64 popcount) -``` - ---- - -## STEP 1: Define the Stroke Layout - -A fingerprint is 2048 bytes (16384 bits). The cascade processes it in strokes: - -``` -STROKE 1: bytes [0..128) = 1024 bits coarse rejection (~90% eliminated) -STROKE 2: bytes [128..512) = 3072 bits medium filter (~90% of survivors) -STROKE 3: bytes [512..2048) = 12288 bits precise distance (final ranking) - -Total: 128 + 384 + 1536 = 2048 bytes = full fingerprint -Non-overlapping. Incremental. Each stroke refines the previous. -``` - -### Current Layout (scattered) -``` -database: &[u8] // N candidates × 2048 bytes, interleaved - -candidate[0]: [stroke1₁₂₈ | stroke2₃₈₄ | stroke3₁₅₃₆] byte 0..2048 -candidate[1]: [stroke1₁₂₈ | stroke2₃₈₄ | stroke3₁₅₃₆] byte 2048..4096 -candidate[2]: [stroke1₁₂₈ | stroke2₃₈₄ | stroke3₁₅₃₆] byte 4096..6144 -... - -Stroke 1 scan: read bytes [0..128], skip 1920, read [2048..2176], skip 1920, ... - Stride: 2048 bytes. Prefetcher: confused. Cache: thrashing. -``` - -### Packed Layout (contiguous strokes) -``` -packed.stroke1: &[u8] // N × 128 bytes, contiguous -packed.stroke2: &[u8] // N × 384 bytes, contiguous -packed.stroke3: &[u8] // N × 1536 bytes, contiguous -packed.index: &[u32] // original candidate IDs (for result mapping) - -packed.stroke1: [cand[0]₀₋₁₂₈ | cand[1]₀₋₁₂₈ | cand[2]₀₋₁₂₈ | ...] -packed.stroke2: [cand[0]₁₂₈₋₅₁₂ | cand[1]₁₂₈₋₅₁₂ | cand[2]₁₂₈₋₅₁₂ | ...] -packed.stroke3: [cand[0]₅₁₂₋₂₀₄₈ | cand[1]₅₁₂₋₂₀₄₈ | cand[2]₅₁₂₋₂₀₄₈ | ...] - -Stroke 1 scan: sequential read through packed.stroke1 - Stride: 0. Prefetcher: perfect. Cache: streaming. -``` - ---- - -## STEP 2: Implement PackedDatabase - -```rust -/// Stroke-aligned database layout for streaming cascade search. -/// Panel packing (siboehm GEMM analogy): reorder data so each stroke -/// is contiguous across all candidates. Prefetcher handles sequential. -pub struct PackedDatabase { - /// Stroke 1: first 128 bytes of each candidate, contiguous - stroke1: Vec, // N × STROKE1_BYTES - /// Stroke 2: bytes 128..512 of each candidate, contiguous - stroke2: Vec, // N × STROKE2_BYTES - /// Stroke 3: bytes 512..2048 of each candidate, contiguous - stroke3: Vec, // N × STROKE3_BYTES - /// Original candidate indices (for result mapping back to source) - index: Vec, // N entries - /// Number of candidates - num_candidates: usize, -} - -pub const STROKE1_BYTES: usize = 128; // 1024 bits -pub const STROKE2_BYTES: usize = 384; // 3072 bits -pub const STROKE3_BYTES: usize = 1536; // 12288 bits -pub const FINGERPRINT_BYTES: usize = 2048; // 16384 bits total - -impl PackedDatabase { - /// Pack a flat database into stroke-aligned layout. - /// This is the "panel packing" step — done ONCE at database construction. - /// O(N × 2048) memory copy. Amortized over all subsequent queries. - pub fn pack(database: &[u8], row_bytes: usize) -> Self { - assert_eq!(row_bytes, FINGERPRINT_BYTES); - let n = database.len() / row_bytes; - - let mut stroke1 = Vec::with_capacity(n * STROKE1_BYTES); - let mut stroke2 = Vec::with_capacity(n * STROKE2_BYTES); - let mut stroke3 = Vec::with_capacity(n * STROKE3_BYTES); - let mut index = Vec::with_capacity(n); - - for i in 0..n { - let base = i * row_bytes; - stroke1.extend_from_slice(&database[base..base + STROKE1_BYTES]); - stroke2.extend_from_slice(&database[base + STROKE1_BYTES..base + STROKE1_BYTES + STROKE2_BYTES]); - stroke3.extend_from_slice(&database[base + STROKE1_BYTES + STROKE2_BYTES..base + row_bytes]); - index.push(i as u32); - } - - Self { stroke1, stroke2, stroke3, index, num_candidates: n } - } - - /// Get stroke 1 slice for candidate i (128 bytes) - #[inline(always)] - pub fn get_stroke1(&self, i: usize) -> &[u8] { - &self.stroke1[i * STROKE1_BYTES..(i + 1) * STROKE1_BYTES] - } - - /// Get stroke 2 slice for candidate i (384 bytes) - #[inline(always)] - pub fn get_stroke2(&self, i: usize) -> &[u8] { - &self.stroke2[i * STROKE2_BYTES..(i + 1) * STROKE2_BYTES] - } - - /// Get stroke 3 slice for candidate i (1536 bytes) - #[inline(always)] - pub fn get_stroke3(&self, i: usize) -> &[u8] { - &self.stroke3[i * STROKE3_BYTES..(i + 1) * STROKE3_BYTES] - } - - /// Original candidate ID for result mapping - #[inline(always)] - pub fn original_id(&self, i: usize) -> u32 { - self.index[i] - } - - pub fn num_candidates(&self) -> usize { - self.num_candidates - } -} -``` - ---- - -## STEP 3: Implement Packed Cascade Query - -The cascade query on PackedDatabase is fundamentally different from the -scattered version. Each stroke is a SEQUENTIAL SCAN with early exit. - -```rust -impl PackedDatabase { - /// Cascade query on packed layout. Three-stroke early rejection. - /// Stroke 1: sequential scan of packed.stroke1 → reject ~90% - /// Stroke 2: sequential scan of packed.stroke2 for survivors → reject ~90% - /// Stroke 3: sequential scan of packed.stroke3 for survivors → exact distance - pub fn cascade_query( - &self, - query: &[u8], // full 2048-byte fingerprint - cascade: &Cascade, // for band classification - k: usize, // top-k results - ) -> Vec { - let query_s1 = &query[..STROKE1_BYTES]; - let query_s2 = &query[STROKE1_BYTES..STROKE1_BYTES + STROKE2_BYTES]; - let query_s3 = &query[STROKE1_BYTES + STROKE2_BYTES..]; - - // ── STROKE 1: coarse rejection ───────────────────────── - // Sequential scan through packed stroke1 data. - // Prefetcher is PERFECT here — pure sequential read. - // VPOPCNTDQ processes 64 bytes per instruction = 2 instructions per candidate. - let reject_threshold_s1 = cascade.reject_threshold_for_bytes(STROKE1_BYTES); - - let mut survivors: Vec<(usize, u64)> = Vec::with_capacity(self.num_candidates / 10); - - // Batch hamming on contiguous stroke1 data - for i in 0..self.num_candidates { - let cand_s1 = self.get_stroke1(i); - let d1 = simd::hamming_distance(query_s1, cand_s1); - if d1 < reject_threshold_s1 { - survivors.push((i, d1)); - } - // Prefetch next candidate's stroke1 (sequential, prefetcher should handle it, - // but explicit prefetch doesn't hurt) - if i + 4 < self.num_candidates { - unsafe { - core::arch::x86_64::_mm_prefetch( - self.stroke1[(i + 4) * STROKE1_BYTES..].as_ptr() as *const i8, - core::arch::x86_64::_MM_HINT_T0, - ); - } - } - } - - // ── STROKE 2: medium filter ──────────────────────────── - // Only scan survivors. Still sequential within packed.stroke2. - let reject_threshold_s2 = cascade.reject_threshold_for_bytes( - STROKE1_BYTES + STROKE2_BYTES - ); - - let mut survivors2: Vec<(usize, u64)> = Vec::with_capacity(survivors.len() / 10); - - for &(idx, d1) in &survivors { - let cand_s2 = self.get_stroke2(idx); - let d2 = simd::hamming_distance(query_s2, cand_s2); - let d_cumulative = d1 + d2; // cumulative distance through stroke 2 - if d_cumulative < reject_threshold_s2 { - survivors2.push((idx, d_cumulative)); - } - } - - // ── STROKE 3: precise distance ───────────────────────── - // Final ranking on remaining survivors. - let mut results: Vec = Vec::with_capacity(survivors2.len()); - - for &(idx, d12) in &survivors2 { - let cand_s3 = self.get_stroke3(idx); - let d3 = simd::hamming_distance(query_s3, cand_s3); - let d_total = d12 + d3; // full hamming distance - let band = cascade.expose(d_total); - results.push(RankedHit { - index: self.original_id(idx) as usize, - distance: d_total, - band, - }); - } - - // Sort and take top-k - results.sort_unstable_by_key(|h| h.distance); - results.truncate(k); - results - } -} -``` - ---- - -## STEP 4: Implement with array_windows (Rust 1.94) - -The stroke scan can use `array_chunks` for typed, monomorphized inner loops: - -```rust -/// Process stroke 1 using array_chunks for compile-time-known sizes. -/// LLVM sees [u8; 128] → full unrolling, no bounds checks. -fn stroke1_scan_typed( - query_s1: &[u8; STROKE1_BYTES], - packed_stroke1: &[u8], - num_candidates: usize, - threshold: u64, -) -> Vec<(usize, u64)> { - let mut survivors = Vec::with_capacity(num_candidates / 10); - - // array_chunks gives us &[u8; 128] per candidate — compile-time known size - for (i, chunk) in packed_stroke1.array_chunks::().enumerate() { - let d = simd::hamming_distance(query_s1, chunk); - if d < threshold { - survivors.push((i, d)); - } - } - - survivors -} -``` - -The compiler knows `chunk` is exactly 128 bytes. It generates the optimal -VPOPCNTDQ loop (2 × 64-byte loads) with zero bounds checking. -This is what JIT would produce. The compiler does it at build time. - ---- - -## STEP 5: Benchmark PackedDatabase vs Scattered - -### Test harness - -```rust -// Setup: 1M candidates, 2KB fingerprints -let database: Vec = generate_random_database(1_000_000, FINGERPRINT_BYTES); -let query: Vec = generate_random_query(FINGERPRINT_BYTES); -let cascade = Cascade::calibrate_from_sample(&database, FINGERPRINT_BYTES); - -// Pack once (amortized) -let packed = PackedDatabase::pack(&database, FINGERPRINT_BYTES); - -// Benchmark scattered (current) -let t0 = Instant::now(); -for _ in 0..100 { - let _hits = cascade.query(&query, &database, 10, threshold); -} -let scattered_time = t0.elapsed() / 100; - -// Benchmark packed (new) -let t0 = Instant::now(); -for _ in 0..100 { - let _hits = packed.cascade_query(&query, &cascade, 10); -} -let packed_time = t0.elapsed() / 100; - -println!("Scattered: {:?}", scattered_time); -println!("Packed: {:?}", packed_time); -println!("Speedup: {:.2}x", scattered_time.as_nanos() as f64 / packed_time.as_nanos() as f64); -``` - -### Expected results (based on siboehm's 2x from panel packing) - -``` -CANDIDATES SCATTERED PACKED SPEEDUP -1K 4μs 3μs 1.3x (already fits cache) -10K 49μs 25μs 2.0x (prefetcher kicks in) -100K 714μs 280μs 2.5x (streaming dominates) -1M 8327μs 3200μs 2.6x (pure streaming) -``` - -The speedup increases with database size because the prefetcher advantage -grows when the working set exceeds L2/L3. At 1K candidates the data -already fits in cache so layout doesn't matter much. - -### Also benchmark the packing cost - -```rust -let t0 = Instant::now(); -let packed = PackedDatabase::pack(&database, FINGERPRINT_BYTES); -let pack_time = t0.elapsed(); -println!("Pack time for 1M: {:?}", pack_time); -// Expected: ~2ms (memcpy of 1M × 2KB = 2GB, sequential) -// Amortized over 1000s of queries: negligible -``` - ---- - -## STEP 6: Memory Layout Analysis - -``` -SCATTERED (current): - Total memory: N × 2048 bytes - Stroke 1 access pattern: stride = 2048 bytes - Cache lines loaded per stroke-1 candidate: 2 (128 bytes / 64 byte line) - Cache lines WASTED per candidate: 30 (remaining 1920 bytes in same lines) - Effective bandwidth utilization: 128/2048 = 6.25% during stroke 1 - -PACKED: - Total memory: N × 2048 bytes (same total, different layout) - Stroke 1 access pattern: stride = 0 (contiguous) - Cache lines loaded per stroke-1 candidate: 2 (128 bytes / 64 byte line) - Cache lines WASTED per candidate: 0 (next candidate is adjacent) - Effective bandwidth utilization: 100% during stroke 1 - - Stroke 1 only (90% rejection): - Scattered: reads N × 2048 bytes of cache lines (wastes 94%) - Packed: reads N × 128 bytes of cache lines (wastes 0%) - Memory bandwidth reduction: 16x for stroke 1 alone - - With 90% rejection per stroke: - Scattered total reads: N×2048 (stroke 1 pollutes everything) - Packed total reads: N×128 + 0.1N×384 + 0.01N×1536 = N×(128+38.4+15.36) = N×181.8 - Memory bandwidth reduction: 2048/181.8 = 11.3x -``` - -The 11.3x memory bandwidth reduction is why panel packing gives 2-3x speedup -even though the CPU is already fast. The bottleneck at 1M candidates is -DRAM bandwidth, not compute. Packing eliminates 89% of DRAM reads. - ---- - -## STEP 7: SPO Node Packing (extend to 3-plane Nodes) - -For Node queries (S + P + O), the packing extends to SPO projections: - -```rust -/// Packed database for Node-level cascade (3 planes per candidate) -pub struct PackedNodeDatabase { - /// Each plane has its own 3-stroke packing - s_stroke1: Vec, // N × 128 bytes - s_stroke2: Vec, // N × 384 bytes - s_stroke3: Vec, // N × 1536 bytes - p_stroke1: Vec, // N × 128 bytes - p_stroke2: Vec, // N × 384 bytes - p_stroke3: Vec, // N × 1536 bytes - o_stroke1: Vec, // N × 128 bytes - o_stroke2: Vec, // N × 384 bytes - o_stroke3: Vec, // N × 1536 bytes - index: Vec, - num_candidates: usize, -} -``` - -This enables Mask-aware cascade: when searching with mask=S__ (subject only), -only s_stroke1/2/3 are accessed. P and O data never enters cache. - -``` -CURRENT NODE SEARCH (mask=S__): - Read 6KB per candidate (full S+P+O), only use 2KB (S plane) - Bandwidth waste: 67% - -PACKED NODE SEARCH (mask=S__): - Read s_stroke1 only: 128 bytes per candidate - Bandwidth waste: 0% - Speedup vs scattered: ~16x for stroke 1 (128 vs 2048+4096 bytes accessed) -``` - ---- - -## STEP 8: Lance Integration - -PackedDatabase is a natural fit for Lance columnar storage: - -``` -LANCE DATASET: - Column "stroke1": FixedSizeBinary(128) × N ← one column per stroke - Column "stroke2": FixedSizeBinary(384) × N - Column "stroke3": FixedSizeBinary(1536) × N - Column "node_id": UInt32 × N - -Each column IS a packed stroke. Lance stores columns contiguously. -Reading stroke1 column = reading packed.stroke1. Zero transformation needed. -The Lance columnar format IS panel packing. We just use it correctly. -``` - ---- - -## WHERE THIS GOES - -``` -rustynum-core/src/packed.rs — PackedDatabase + PackedNodeDatabase -rustynum-core/src/hdr.rs — cascade_query_packed() method -ndarray/src/hpc/packed.rs — ndarray port (after rustynum is verified) -lance-graph/ — Lance columnar integration -``` - -## DEPENDENCIES - -``` -NEEDS: - simd::hamming_distance (dispatch!, verified, merged) - Cascade::expose() (band classification, exists) - Cascade reject thresholds per stroke size (NEW: derive from band boundaries) - -DOES NOT NEED: - BF16 (that's a separate system) - encounter() (PackedDatabase is read-only search) - Node/Plane types (PackedDatabase operates on raw &[u8]) -``` - -## COMPLETION CRITERIA - -- [ ] PackedDatabase::pack() transposes scattered → contiguous strokes -- [ ] cascade_query_packed() with 3-stroke early rejection -- [ ] array_chunks::<128>() for typed stroke 1 scan (Rust 1.94) -- [ ] Benchmark: packed vs scattered at 1K, 10K, 100K, 1M candidates -- [ ] Memory bandwidth analysis matches prediction (11.3x reduction) -- [ ] Pack time benchmarked and documented (must be < 10ms for 1M) -- [ ] SPO node packing variant for Mask-aware queries -- [ ] All existing cascade tests pass (backward compatible) -- [ ] New tests: pack → query → results match unpacked query exactly diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_LANCE_ECOSYSTEM_INVENTORY.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_LANCE_ECOSYSTEM_INVENTORY.md deleted file mode 100644 index 61f47a2b..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_LANCE_ECOSYSTEM_INVENTORY.md +++ /dev/null @@ -1,418 +0,0 @@ -# SESSION_LANCE_ECOSYSTEM_INVENTORY.md - -## Mission: What Does the Original Lance Ecosystem Do That We Probably Missed? - -**Context:** We forked lance-graph and built our binary semiring algebra on top. -But the ORIGINAL lance ecosystem (lance-format/lance, LanceDB, lance-graph, -DuckDB extension, lance-namespace) has capabilities we may not be using. -They connect externally to S3, Azure, GCS, DuckDB, Polars, Spark, PyTorch. -We could connect those same pipes INTERNALLY to our binary planes. - -**The question:** What infrastructure did lance-format build that we get FOR FREE -by being a lance-native system — and what are we NOT using? - ---- - -## STEP 1: Inventory the Original Lance Format (lance-format/lance) - -``` -REPO: https://github.com/lance-format/lance -``` - -### Storage Backends (What They Connect To) -``` -INVESTIGATE: - 1. S3 (AWS) — lance.dataset("s3://bucket/path") - 2. S3 Express One Zone — ultra-low latency single-zone - 3. Azure Blob Store — lance.dataset("az://bucket/path") - 4. Google Cloud Storage — lance.dataset("gs://bucket/path") - 5. S3-compatible (MinIO, R2, Tigris) — custom endpoint - 6. Local NVMe / POSIX filesystem - 7. EBS (AWS block storage) - 8. EFS (AWS network filesystem) - - HOW WE USE THIS: - Our Planes (2KB binary vectors) stored as Lance columns. - Lance handles S3/Azure/GCS persistence transparently. - We get cloud storage for free. No custom persistence layer. - - WHAT TO CHECK: - - Can we store Plane.acc (i8[16384] = 16KB) as a Lance column efficiently? - - Can we store Fingerprint<256> (u64[256] = 2KB) as a fixed-size binary column? - - Can we store BF16 edge weights as a Lance column? - - What's the random access latency for reading one Plane from S3? - - Can we use S3 Express for hot path data (< 10ms latency)? -``` - -### Versioning and Time Travel -``` -INVESTIGATE: - Lance creates a new VERSION on every write. Old versions are readable. - dataset.checkout(version=N) reads state at version N. - ACID transactions. Zero-copy. - - HOW WE USE THIS: - Every round of encounter() changes Plane state. - If Planes are Lance columns, each encounter round = new version. - Time travel = "what did this node know at time T?" - diff(v1, v2) = which bits changed = learning delta = Staunen detection - - WHAT TO CHECK: - - What's the storage overhead per version? (immutable fragments = COW) - - Can we version at the Plane level or only at the dataset level? - - How fast is diff between two versions? - - Can we tag versions? (e.g., tag = "after_training_epoch_50") - - Can we branch? (experiment with different encounter sequences) -``` - -### Data Evolution (Add Columns Without Rewrite) -``` -INVESTIGATE: - lance supports add_columns() with backfilled values. - No full table rewrite. Just new column fragments. - - HOW WE USE THIS: - Add new Planes to existing Nodes without rewriting S, P, O. - Add BF16 edge weight cache column without rewriting the graph. - Add alpha density statistics column for query optimizer. - - WHAT TO CHECK: - - Can add_columns work with computed columns (UDF)? - - Can we add a "bundle" column that's computed from existing planes? - - Performance of add_columns on 1M row dataset? -``` - -### Concurrent Writers -``` -INVESTIGATE: - S3 doesn't support atomic commits. Lance uses DynamoDB for locking. - lance.dataset("s3+ddb://bucket/path?ddbTableName=mytable") - Also supports custom commit_lock context manager. - - HOW WE USE THIS: - Multiple encounter() streams writing to same graph concurrently. - Hot path (cascade discovery) writes new edges. - Cold path (query evaluation) reads edges. - Both can run simultaneously with proper locking. - - WHAT TO CHECK: - - What's the overhead of DynamoDB locking per write? - - Can we use optimistic concurrency instead? (version check) - - Is there a local-only locking mechanism for embedded use? -``` - ---- - -## STEP 2: Inventory LanceDB (the Vector DB built on Lance) - -``` -REPO: https://github.com/lancedb/lancedb -``` - -### Vector Search -``` -INVESTIGATE: - LanceDB provides vector similarity search on Lance datasets. - IVF-PQ index for approximate nearest neighbor. - Full-text search (BM25). - Hybrid search (vector + full-text + SQL). - - HOW WE USE THIS: - We DON'T use float vector search. We use Hamming on binary planes. - BUT: LanceDB's indexing infrastructure might support binary indices. - IVF-PQ on binary vectors → multi-index hashing equivalent? - - WHAT TO CHECK: - - Does LanceDB support binary vector types? - - Can we register a custom distance function (hamming)? - - Can we use their index infrastructure with our cascade as the distance? - - Their ANN index vs our cascade: which is faster for binary search? -``` - -### Table API -``` -INVESTIGATE: - db = lancedb.connect("s3://bucket/path") - table = db.create_table("nodes", data) - table.add(new_data) - table.search(query_vector).limit(10) - table.where("column > value") - table.to_pandas() / table.to_arrow() / table.to_polars() - - HOW WE USE THIS: - Our Nodes could be a LanceDB table. - table.search(query_plane).limit(10) → cascade under the hood. - table.where("alpha_density > 0.8") → SQL filter on plane metadata. - table.to_arrow() → zero-copy to DuckDB/Polars for analytics. - - WHAT TO CHECK: - - Can we use custom search functions with LanceDB? - - Can we store 2KB binary columns efficiently? - - What's the overhead of LanceDB's table API vs raw Lance? -``` - -### Ecosystem Integrations -``` -INVESTIGATE: - LanceDB integrates with: - - LangChain (RAG pipeline) - - LlamaIndex (RAG pipeline) - - PyTorch / PyTorch Geometric (GNN training dataloader) - - DGL (graph neural networks) - - Pandas, Polars, DuckDB (analytics) - - Hugging Face (model hub) - - HOW WE USE THIS: - LangChain/LlamaIndex: our graph as knowledge source for RAG - PyTorch Geometric: our Planes as node features for GNN - DGL: same - Pandas/Polars: analytics on graph metadata - DuckDB: SQL on graph (the DuckDB × Lance extension!) - - WHAT TO CHECK: - - PyG integration: can it load our Planes as node features directly? - - DGL integration: can it use our encounter() as message passing? - - DuckDB extension: can we query our graph with SQL? - - LangChain: can we replace their vector store with our cascade? -``` - ---- - -## STEP 3: Inventory Original lance-graph (lance-format/lance-graph) - -``` -REPO: https://github.com/lance-format/lance-graph -``` - -### What It Actually Does -``` -INVESTIGATE: - CypherQuery → DataFusion plan → Arrow table scan + filter + join - GraphConfig with node labels and ID columns - Knowledge graph service (CLI + FastAPI) - LLM-powered text extraction for knowledge graph bootstrap - - WHAT TO CHECK: - - How does their CypherQuery map to DataFusion? - - What Cypher features do they support? - - How does their GraphConfig compare to our BlasGraph? - - What is their knowledge_graph service architecture? - - Do they have any graph algorithms (BFS, shortest path, PageRank)? - - How do they handle relationships? Arrow tables with foreign keys? -``` - -### Their Python Bindings -``` -INVESTIGATE: - pip install lance-graph - from lance_graph import CypherQuery, GraphConfig - - WHAT TO CHECK: - - How do they expose Rust to Python? (PyO3? maturin?) - - What's their Python API surface? - - Can we extend their API with our binary operations? - - Is their CypherQuery reusable as-is? -``` - -### Their Knowledge Graph Service -``` -INVESTIGATE: - knowledge_graph package: - - CLI for init, query, bootstrap - - FastAPI web service - - LLM text extraction (OpenAI) - - Lance-backed storage - - HOW WE USE THIS: - Their web service pattern for our graph API. - Their LLM extraction → our encounter() pipeline. - Text → LLM → triples → encounter() into Planes. - - WHAT TO CHECK: - - Can we plug our binary graph into their FastAPI service? - - Can we replace their LLM extraction with encounter()? - - What endpoints do they expose? -``` - ---- - -## STEP 4: Inventory DuckDB × Lance Extension - -``` -SOURCE: https://lancedb.com/blog/lance-x-duckdb-sql-retrieval-on-the-multimodal-lakehouse-format/ -``` - -``` -INVESTIGATE: - INSTALL lance FROM community; - LOAD lance; - SELECT * FROM 's3://bucket/path/dataset.lance' LIMIT 5; - - DuckDB can: - - Scan Lance datasets directly (local or S3) - - Push down column selection and filters - - Hybrid retrieval with vector search table functions - - Join Lance datasets with other DuckDB tables - - HOW WE USE THIS: - Our binary graph stored as Lance → queryable from DuckDB SQL. - - SELECT node_id, alpha_density - FROM 's3://bucket/nodes.lance' - WHERE alpha_density > 0.8; - - SELECT a.node_id, b.node_id, hamming_distance(a.plane_s, b.plane_s) - FROM 's3://bucket/nodes.lance' a, 's3://bucket/nodes.lance' b - WHERE hamming_distance(a.plane_s, b.plane_s) < 100; - - WHAT TO CHECK: - - Can we register custom DuckDB functions (hamming_distance)? - - Can DuckDB push down binary predicates to Lance scan? - - What's the performance of DuckDB scanning our 2KB binary columns? - - Can we use DuckDB's parallel execution for graph queries? -``` - ---- - -## STEP 5: Inventory lance-namespace - -``` -REPO: https://github.com/lance-format/lance-namespace -``` - -``` -INVESTIGATE: - Standardized access to collections of Lance tables. - Implementations for: Hive, Polaris, Gravitino, Unity Catalog, AWS Glue. - - HOW WE USE THIS: - Our graph as a namespace in enterprise catalog. - Unity Catalog → our SPO graph accessible from Databricks. - AWS Glue → our graph accessible from any AWS analytics tool. - - WHAT TO CHECK: - - Can we register our graph as a lance-namespace? - - What metadata does namespace expose? - - Can we expose our graph through Unity Catalog? -``` - ---- - -## STEP 6: What We Get FOR FREE by Being Lance-Native - -After completing the inventory, produce this table: - -``` -CAPABILITY LANCE PROVIDES WE USE IT? -────────────────────────────────────────────────────────────────────── -S3 persistence ✓ ? -Azure Blob persistence ✓ ? -GCS persistence ✓ ? -NVMe-optimized local storage ✓ ? -ACID versioning (time travel) ✓ ? -Zero-copy Arrow interop ✓ ? -Concurrent writers (DynamoDB lock) ✓ ? -Column evolution (add without rewrite) ✓ ? -DuckDB SQL queries ✓ ? -Pandas/Polars export ✓ ? -PyTorch dataloader ✓ ? -LangChain/LlamaIndex RAG ✓ ? -Spark integration ✓ ? -Ray integration ✓ ? -Enterprise catalog (Unity, Glue) ✓ ? -Full-text search (BM25) ✓ ? -Vector similarity search (IVF-PQ) ✓ ? -``` - -For every "?" answer: what would it take to wire it up? -For every "no": why not, and should we? - ---- - -## STEP 7: The Internal Connection Map - -The key insight: they connect EXTERNALLY (S3, DuckDB, Spark). -We connect INTERNALLY (Plane ↔ Node ↔ Cascade ↔ Semiring). - -Can we expose our internal connections through their external interfaces? - -``` -THEIR EXTERNAL: OUR INTERNAL EQUIVALENT: -S3 → Lance dataset Lance dataset → Plane columns -DuckDB SQL → Lance scan DuckDB SQL → hamming_distance UDF -LangChain retriever → LanceDB LangChain retriever → cascade search -PyG node features → Lance column PyG node features → Plane.bits() -Spark → Lance table Spark → graph analytics on Planes -``` - -The BRIDGE: make our internal types (Plane, Node, Edge, NarsTruth) -look like Lance columns to the external ecosystem. Then everything -they built works with our data. No custom integration needed. - -```rust -// Make a Plane serializable as a Lance column: -impl From for lance::array::BinaryArray { - fn from(plane: Plane) -> Self { - // acc: i8[16384] → 16KB binary blob - // OR bits: u64[256] → 2KB binary blob + alpha: u64[256] → 2KB binary blob - } -} - -// Make a Node serializable as a Lance row: -impl From for lance::RecordBatch { - fn from(node: Node) -> Self { - // columns: [id, plane_s, plane_p, plane_o, seal, encounters] - } -} - -// Make an Edge serializable as a Lance row: -impl From for lance::RecordBatch { - fn from(edge: Edge) -> Self { - // columns: [source_id, target_id, bf16_truth, projection_byte] - } -} -``` - -Once this bridge exists: -- `lance.dataset("s3://bucket/my_graph.lance")` reads our graph from S3 -- DuckDB scans our graph with SQL -- PyTorch Geometric loads our Planes as GNN node features -- LangChain uses our cascade as a retriever -- Databricks accesses our graph through Unity Catalog -- We get the ENTIRE lance ecosystem for free - ---- - -## FILES TO PRODUCE - -``` -1. LANCE_ECOSYSTEM_INVENTORY.md — complete capability map -2. LANCE_FREE_CAPABILITIES.md — what we get for free, what's not wired -3. LANCE_BRIDGE_SPEC.md — Plane/Node/Edge → Lance column serialization -4. LANCE_INTEGRATION_PRIORITY.md — which integrations to wire first -``` - -Push all to `.claude/` in both repos. - ---- - -## KEY INSIGHT - -We built the cognitive layer (encounter, cascade, bundle, semiring). -Lance built the infrastructure layer (S3, versioning, DuckDB, PyTorch). -We are ON TOP of Lance but not USING Lance. -Wiring the two together gives us: - -``` -A database that LEARNS (our layer) - + persists to any cloud (Lance S3/Azure/GCS) - + queries from SQL (DuckDB × Lance) - + trains from PyTorch (Lance dataloader) - + integrates with RAG (LangChain × Lance) - + catalogs in enterprise (Unity Catalog × lance-namespace) - + versions automatically (Lance ACID) - + time-travels for free (Lance checkout) - -No other system has this stack. -Because no other system is both a learning engine AND a Lance-native store. -``` diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_LANGGRAPH_ORCHESTRATION.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_LANGGRAPH_ORCHESTRATION.md deleted file mode 100644 index 8b29336e..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/SESSION_LANGGRAPH_ORCHESTRATION.md +++ /dev/null @@ -1,465 +0,0 @@ -# SESSION_LANGGRAPH_ORCHESTRATION.md - -## Mission: Replace Layer 4 Chaos with LangGraph-Style Graph Orchestration Wired into Zero-Copy Planes - -**Problem:** Layer 4 of ladybug-rs's 10-layer thinking stack currently uses a messy -mix of crewai-rust patterns, n8n-rs workflow fragments, and jitson JIT compilation. -No coherent execution model. No session state. No conditional routing. No human-in-loop. - -**Solution:** Adopt the LangGraph execution model (as implemented in `rs-graph-llm/graph-flow`) -and wire it directly into our binary plane architecture. Tasks operate on Planes -through the Blackboard zero-copy arena. The Context IS the Blackboard. -The execution graph IS the thinking graph. Sessions persist as Lance versions. - -**Key insight:** graph-flow gives us exactly what we need: -- Graph execution engine (stateful task orchestration) -- Conditional routing (branch based on Context data) -- Session management (persist, resume, time-travel) -- FanOut (parallel task execution with result aggregation) -- Human-in-the-loop (WaitForInput) -- Step-by-step OR continuous execution (NextAction enum) -- Type-safe Context with get/set (thread-safe) - -We don't need to build ANY of this. We need to WIRE it to our binary substrate. - ---- - -## REFERENCE: rs-graph-llm/graph-flow Architecture - -``` -REPO: https://github.com/a-agmon/rs-graph-llm -CRATE: graph-flow/ (the core library) -LICENSE: MIT (permissive, compatible with our stack) - -CORE TYPES: - Task (trait) → async fn run(&self, context: Context) -> Result - Context → thread-safe key-value store (Arc>) - GraphBuilder → add_task, add_edge, add_conditional_edge, build - FlowRunner → run(session_id) → ExecutionResult - Session → session_id + context + current_task + history - SessionStorage → InMemorySessionStorage, PostgresSessionStorage - FanOutTask → parallel child tasks, result aggregation - -EXECUTION MODEL: - NextAction::Continue → step-by-step (return to caller) - NextAction::ContinueAndExecute → auto-continue to next task - NextAction::WaitForInput → pause for human/external input - NextAction::End → workflow complete - NextAction::GoTo(task_id) → jump to specific task - NextAction::GoBack → return to previous task - -CONDITIONAL ROUTING: - .add_conditional_edge(from, predicate_fn, true_target, false_target) - Predicate reads from Context → routes to different tasks -``` - ---- - -## STEP 1: Map graph-flow to Our 10-Layer Thinking Stack - -``` -LADYBUG-RS 10 LAYERS (current): - Layer 1: Sensory input (MCP ingest, text, events) - Layer 2: Tokenization / fingerprinting (text → Plane encounter) - Layer 3: Pattern recognition (cascade search, hamming classification) - Layer 4: ORCHESTRATION (currently messy: crewai + n8n + jitson) ← FIX THIS - Layer 5: Reasoning (semiring graph traversal, Bellman-Ford) - Layer 6: Memory consolidation (encounter, seal, Staunen detection) - Layer 7: Planning (multi-step goal decomposition) - Layer 8: Action selection (RL credit assignment, BF16 truth) - Layer 9: Output generation (LLM, template, structured response) - Layer 10: Meta-cognition (self-monitoring, confidence calibration) - -LAYER 4 WITH GRAPH-FLOW: - Each layer becomes a TASK in the execution graph. - The graph defines which layers connect and under what conditions. - The Context IS the Blackboard (zero-copy shared state). - Sessions persist as Lance versions (time travel for free). -``` - -### The Thinking Graph - -```rust -// Layer 4: the orchestration graph that WIRES all other layers -let thinking_graph = GraphBuilder::new("ladybug_thinking") - // Layer 1: Sensory - .add_task(Arc::new(SensoryIngestTask)) // MCP → raw input - - // Layer 2: Fingerprint - .add_task(Arc::new(FingerprintTask)) // text → Plane.encounter() - - // Layer 3: Pattern Recognition - .add_task(Arc::new(CascadeSearchTask)) // cascade → band classification - - // Layer 5: Reasoning (conditional: skip if pattern already known) - .add_task(Arc::new(SemiringReasonTask)) // graph traversal - - // Layer 6: Memory - .add_task(Arc::new(MemoryConsolidateTask)) // encounter + seal check - - // Layer 7: Planning (conditional: only for multi-step goals) - .add_task(Arc::new(PlanningTask)) // goal decomposition - - // Layer 8: Action Selection - .add_task(Arc::new(ActionSelectTask)) // RL credit assignment - - // Layer 9: Output - .add_task(Arc::new(OutputGenerateTask)) // LLM or template - - // Layer 10: Meta-cognition - .add_task(Arc::new(MetaCognitionTask)) // self-monitoring - - // EDGES: the thinking flow - .add_edge(sensory.id(), fingerprint.id()) - .add_edge(fingerprint.id(), cascade.id()) - - // CONDITIONAL: if cascade finds Foveal match, skip reasoning - .add_conditional_edge( - cascade.id(), - |ctx| ctx.get_sync::("best_band") - .map(|b| b == "Foveal") - .unwrap_or(false), - memory.id(), // Foveal → skip reasoning, go to memory - reasoning.id(), // Not Foveal → need reasoning - ) - - .add_edge(reasoning.id(), memory.id()) - - // CONDITIONAL: if Staunen detected, go to planning - .add_conditional_edge( - memory.id(), - |ctx| ctx.get_sync::("staunen_detected") - .unwrap_or(false), - planning.id(), // Staunen → need new plan - action.id(), // Wisdom → proceed to action - ) - - .add_edge(planning.id(), action.id()) - .add_edge(action.id(), output.id()) - .add_edge(output.id(), meta.id()) - - // META-COGNITION can loop back - .add_conditional_edge( - meta.id(), - |ctx| ctx.get_sync::("confidence") - .map(|c| c < 0.5) - .unwrap_or(false), - cascade.id(), // Low confidence → re-search - // high confidence → end - "END", - ) - - .build(); -``` - ---- - -## STEP 2: Context = Blackboard = Zero-Copy Plane Access - -The critical wiring: graph-flow's Context is a `HashMap`. -Our Blackboard is a zero-copy shared memory arena with SIMD-aligned allocations. -We need to bridge them so Tasks read/write Planes through Context. - -```rust -/// Bridge: graph-flow Context backed by rustynum Blackboard -/// Tasks get/set Planes through the Context API. -/// Zero-copy: Planes are NOT serialized into the Context HashMap. -/// They live in the Blackboard arena. Context holds references. -struct PlaneContext { - // graph-flow's standard Context for scalar values - inner: Context, - // rustynum's Blackboard for zero-copy Plane access - blackboard: Arc, -} - -impl PlaneContext { - /// Get a Plane from the Blackboard by name. Zero-copy. - fn get_plane(&self, name: &str) -> Option<&Plane> { - self.blackboard.get_plane(name) - } - - /// Get a mutable Plane for encounter(). Zero-copy. - fn get_plane_mut(&self, name: &str) -> Option<&mut Plane> { - self.blackboard.get_plane_mut(name) - } - - /// Allocate a new Plane in the Blackboard. - fn alloc_plane(&self, name: &str) -> &mut Plane { - self.blackboard.alloc_plane(name) - } - - /// Get a Node (3 Planes) from the Blackboard. - fn get_node(&self, name: &str) -> Option<&Node> { - self.blackboard.get_node(name) - } - - /// Store scalar values (distances, bands, BF16 truths) in Context. - /// These ARE serialized (small values, not Planes). - async fn set_scalar(&self, key: &str, value: T) { - self.inner.set(key, value).await; - } - - /// Read scalar values from Context. - fn get_scalar(&self, key: &str) -> Option { - self.inner.get_sync(key) - } -} -``` - -### Example: CascadeSearchTask - -```rust -struct CascadeSearchTask { - cascade: Arc, -} - -#[async_trait] -impl Task for CascadeSearchTask { - fn id(&self) -> &str { "cascade_search" } - - async fn run(&self, context: Context) -> graph_flow::Result { - let pctx = PlaneContext::from(context.clone()); - - // Read query Plane from Blackboard (zero-copy) - let query_plane = pctx.get_plane("query_s") - .ok_or("No query plane in blackboard")?; - - // Run cascade search (SIMD, hot path) - let hits = self.cascade.query( - query_plane.bits_bytes_ref(), - &database, - 10, - threshold, - ); - - // Store results as scalar in Context - pctx.set_scalar("cascade_hits", &hits).await; - pctx.set_scalar("best_band", hits[0].band.to_string()).await; - pctx.set_scalar("best_distance", hits[0].distance).await; - - // If Foveal match found, we can skip reasoning - let response = format!("Found {} hits, best: {:?}", hits.len(), hits[0].band); - Ok(TaskResult::new(Some(response), NextAction::Continue)) - } -} -``` - -### Example: MemoryConsolidateTask - -```rust -struct MemoryConsolidateTask; - -#[async_trait] -impl Task for MemoryConsolidateTask { - fn id(&self) -> &str { "memory_consolidate" } - - async fn run(&self, context: Context) -> graph_flow::Result { - let pctx = PlaneContext::from(context.clone()); - - // Get the matched node from Blackboard (zero-copy) - let matched_node = pctx.get_node_mut("matched_node") - .ok_or("No matched node")?; - let evidence_node = pctx.get_node("evidence_node") - .ok_or("No evidence node")?; - - // Store current seal before encounter - let seal_before = matched_node.s.merkle(); - - // Encounter: the learning step (integer, deterministic) - matched_node.s.encounter_toward(&evidence_node.s); - matched_node.p.encounter_toward(&evidence_node.p); - matched_node.o.encounter_toward(&evidence_node.o); - - // Check seal: Wisdom or Staunen? - let seal_after = matched_node.s.verify(&seal_before); - let staunen = seal_after == Seal::Staunen; - - pctx.set_scalar("staunen_detected", staunen).await; - pctx.set_scalar("seal_status", format!("{:?}", seal_after)).await; - - let response = if staunen { - "Staunen: something changed unexpectedly. Rethinking.".to_string() - } else { - "Wisdom: knowledge consolidated.".to_string() - }; - - Ok(TaskResult::new(Some(response), NextAction::Continue)) - } -} -``` - ---- - -## STEP 3: FanOut for 2³ SPO Projections - -The 7 SPO projections can run in PARALLEL using graph-flow's FanOut: - -```rust -// Each projection is a child task -struct ProjectionTask { mask: Mask } - -#[async_trait] -impl Task for ProjectionTask { - fn id(&self) -> &str { /* mask-specific id */ } - - async fn run(&self, context: Context) -> graph_flow::Result { - let pctx = PlaneContext::from(context.clone()); - let query = pctx.get_node("query").unwrap(); - let candidate = pctx.get_node("candidate").unwrap(); - - let distance = query.distance(candidate, self.mask); - let band = cascade.expose(distance.raw().unwrap_or(u32::MAX)); - - pctx.set_scalar(&format!("proj_{:?}_dist", self.mask), distance).await; - pctx.set_scalar(&format!("proj_{:?}_band", self.mask), band).await; - - Ok(TaskResult::new(None, NextAction::End)) - } -} - -// FanOut: all 7 projections in parallel -let projection_fanout = FanOutTask::new("spo_projections", vec![ - Arc::new(ProjectionTask { mask: S__ }), - Arc::new(ProjectionTask { mask: _P_ }), - Arc::new(ProjectionTask { mask: __O }), - Arc::new(ProjectionTask { mask: SP_ }), - Arc::new(ProjectionTask { mask: S_O }), - Arc::new(ProjectionTask { mask: _PO }), - Arc::new(ProjectionTask { mask: SPO }), -]).with_prefix("proj"); - -// After FanOut, the BF16 assembly task reads all 7 results -struct BF16AssemblyTask; - -#[async_trait] -impl Task for BF16AssemblyTask { - async fn run(&self, context: Context) -> graph_flow::Result { - // Read all 7 projection results from FanOut - let bands: [Band; 7] = [ - context.get_sync("proj.s__.band").unwrap(), - context.get_sync("proj._p_.band").unwrap(), - // ... - ]; - - let bf16 = bf16_from_projections(&bands, finest, foveal_max, direction); - context.set("bf16_truth", bf16).await; - - Ok(TaskResult::new(None, NextAction::Continue)) - } -} -``` - ---- - -## STEP 4: Session = Lance Version - -graph-flow has SessionStorage (InMemory, Postgres). We add LanceSessionStorage: - -```rust -/// Session storage backed by Lance format. -/// Each save() creates a new Lance version. -/// Time travel: load(session_id, version=N) restores state at version N. -/// diff(v1, v2) shows what changed between thinking steps. -struct LanceSessionStorage { - dataset_path: String, // "s3://bucket/sessions.lance" or local path -} - -#[async_trait] -impl SessionStorage for LanceSessionStorage { - async fn save(&self, session: Session) -> Result<()> { - // Serialize session context (scalars only, not Planes) - // Planes live in Blackboard → separate Lance dataset - // Each save = new Lance version (automatic ACID) - lance::write_dataset(session_to_arrow(session), &self.dataset_path).await?; - Ok(()) - } - - async fn get(&self, session_id: &str) -> Result> { - let ds = lance::dataset(&self.dataset_path).await?; - // Read latest version by default - let row = ds.filter(format!("session_id = '{}'", session_id)).await?; - Ok(row.map(arrow_to_session)) - } - - /// Time travel: load session at specific version - async fn get_at_version(&self, session_id: &str, version: u64) -> Result> { - let ds = lance::dataset(&self.dataset_path).await?; - let historical = ds.checkout(version)?; - let row = historical.filter(format!("session_id = '{}'", session_id)).await?; - Ok(row.map(arrow_to_session)) - } -} -``` - ---- - -## STEP 5: What graph-flow Replaces in Layer 4 - -``` -CURRENT LAYER 4 (messy): REPLACED BY: -────────────────────────────────────────────────────────────── -crewai-rust agent orchestration → GraphBuilder + Tasks + edges -n8n-rs workflow definitions → add_edge, add_conditional_edge -jitson JIT for hot loops → KEEP (inside Tasks for SIMD kernels) -Manual state passing between layers → Context get/set (thread-safe) -No session persistence → LanceSessionStorage (versioned) -No conditional routing → add_conditional_edge (predicate fn) -No parallel execution → FanOutTask (tokio parallel) -No human-in-the-loop → NextAction::WaitForInput -No step-by-step debugging → NextAction::Continue + session inspect -No execution history → Session history + Lance versions -``` - -jitson stays. It's the JIT compiler for hot-path SIMD kernels INSIDE tasks. -graph-flow is the orchestration BETWEEN tasks. They're complementary. - ---- - -## STEP 6: The Complete Wiring - -``` -LAYER 0: Lance format persistence (S3, NVMe, versioning) - ↕ LanceSessionStorage -LAYER 4: graph-flow execution engine (GraphBuilder, FlowRunner, Session) - ↕ PlaneContext bridge -BLACKBOARD: rustynum zero-copy arena (SIMD-aligned Planes) - ↕ simd:: dispatch (AVX-512, AVX2, scalar) -LAYERS 1-10: individual Tasks in the execution graph - ↕ conditional routing based on cascade bands, seal status, confidence - -The graph IS the thinking. -The Context IS the Blackboard. -The Session IS the episode. -The Lance version IS the memory. -``` - ---- - -## FILES TO PRODUCE - -``` -1. Clone and inventory rs-graph-llm/graph-flow (types, traits, methods) -2. PlaneContext bridge implementation (Context → Blackboard zero-copy) -3. Thinking graph definition (10 layers as Tasks with conditional edges) -4. FanOut for 2³ SPO projections -5. LanceSessionStorage implementation -6. Integration tests: full thinking cycle from input to output -7. Benchmark: graph-flow overhead vs direct function calls -``` - -## DEPENDENCIES TO ADD - -``` -graph-flow = { git = "https://github.com/a-agmon/rs-graph-llm", path = "graph-flow" } -# OR vendor into our workspace as a local crate -``` - -## KEY PRINCIPLE - -graph-flow handles ORCHESTRATION (which task runs next, what conditions route where). -rustynum handles COMPUTATION (SIMD hamming, encounter, cascade, bundle). -Lance handles PERSISTENCE (S3, versioning, time travel). - -Each layer does ONE thing. RISC for the thinking stack. -No more crewai+n8n+jitson soup in Layer 4. -One clean graph. One execution model. One session store. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/UNIFIED_HDR_RENAME_AND_CROSSPOLINATE.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/UNIFIED_HDR_RENAME_AND_CROSSPOLINATE.md deleted file mode 100644 index 5bd698a1..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/UNIFIED_HDR_RENAME_AND_CROSSPOLINATE.md +++ /dev/null @@ -1,475 +0,0 @@ -# UNIFIED_HDR_RENAME_AND_CROSSPOLINATE.md - -## Part 0: Rename Files and Functions (Both Repos) -## Part 1: Cross-Pollinate Algorithms (Rustynum ↔ Lance-Graph) - -**Repos:** rustynum (WRITE), lance-graph (WRITE) -**Read first:** rustynum-core/src/simd_compat.rs, rustynum-core/src/simd.rs, - lance-graph/crates/lance-graph/src/graph/blasgraph/light_meter.rs - ---- - -## PART 0A: SIMD FILE RENAME (rustynum) - -### The Problem - -The filenames are backwards from what every session assumes: - -``` -simd_compat.rs = AVX-512 PRIMARY (F32x16, F64x8, VPOPCNTDQ) -simd.rs = AVX2 FALLBACK + dispatcher -``` - -Every session reads "compat" as "legacy fallback" and routes things wrong. - -### The Rename - -``` -BEFORE: AFTER: -simd_compat.rs → simd_avx512.rs (rename, primary AVX-512) -simd.rs → simd.rs (stays, dispatcher + imports avx2) -NEW: simd_avx2.rs (extract AVX2 impls FROM simd.rs) -NEW: simd_arm.rs (placeholder for NEON/SVE) -NEW: simd_avx512_nightly.rs (placeholder for FP16/AMX) -``` - -### Step 1: Rename simd_compat.rs → simd_avx512.rs - -```bash -cd rustynum-core/src -git mv simd_compat.rs simd_avx512.rs -``` - -### Step 2: Add re-export shim (zero breakage) - -Create new `simd_compat.rs` with ONLY: - -```rust -//! Backward-compatibility shim. All types moved to simd_avx512.rs. -//! -//! Migrate imports: `use crate::simd_compat::X` → `use crate::simd_avx512::X` -#[allow(deprecated)] -#[deprecated(since = "0.4.0", note = "renamed to simd_avx512")] -pub use crate::simd_avx512::*; -``` - -### Step 3: Update lib.rs - -```rust -pub mod simd_avx512; // AVX-512 primary (was simd_compat) -pub mod simd; // dispatcher -pub mod simd_avx2; // AVX2 fallback (extracted from simd.rs) - -// Backward compat — remove in next major version -#[allow(deprecated)] -pub mod simd_compat; -``` - -### Step 4: Extract simd_avx2.rs from simd.rs - -Move THESE functions from simd.rs into simd_avx2.rs: - -``` -hamming_avx2() ← the Harley-Seal implementation -hamming_scalar_popcnt() ← scalar fallback -popcount_avx2() ← AVX2 popcount -popcount_scalar() ← scalar fallback -dot_f32_avx2() ← AVX2 dot product (if exists) -dot_i8_scalar() ← scalar INT8 dot -f32_to_fp16_scalar() ← bit-shift conversion -``` - -simd.rs KEEPS only: -- The `OnceLock` dispatchers -- The `select_*_fn()` functions -- The `pub fn` entry points that delegate - -### Step 5: Update simd.rs imports - -```rust -// simd.rs — dispatcher only - -mod simd_avx512; // or use crate::simd_avx512 if pub -mod simd_avx2; - -use std::sync::OnceLock; - -static HAMMING: OnceLock u64> = OnceLock::new(); - -#[inline] -pub fn hamming_distance(a: &[u8], b: &[u8]) -> u64 { - HAMMING.get_or_init(|| { - #[cfg(target_arch = "x86_64")] - { - if is_x86_feature_detected!("avx512vpopcntdq") { - return simd_avx512::hamming_distance - } - if is_x86_feature_detected!("avx2") { - return simd_avx2::hamming_distance - } - } - #[cfg(target_arch = "aarch64")] - { return simd_avx2::hamming_scalar } // LLVM emits NEON CNT - - simd_avx2::hamming_scalar - })(a, b) -} -``` - -### Step 6: Migrate direct simd_compat imports (20+ sites) - -Find-replace across workspace. The shim makes this non-urgent but do it now: - -```bash -# These are ALL the files that import from simd_compat: -sed -i 's/simd_compat/simd_avx512/g' \ - rustyblas/src/level3.rs \ - rustyblas/src/bf16_gemm.rs \ - rustyblas/src/int8_gemm.rs \ - rustyblas/examples/gemm_benchmark.rs \ - rustymkl/src/fft.rs \ - rustymkl/src/vml.rs \ - rustynum-core/src/prefilter.rs \ - rustynum-core/src/simd_avx2.rs \ - rustynum-core/src/bf16_hamming.rs \ - rustynum-core/src/simd.rs \ - rustynum-rs/src/simd_ops/mod.rs \ - rustynum-rs/src/num_array/hdc.rs \ - rustynum-rs/src/num_array/array_struct.rs \ - rustynum-rs/src/num_array/bitwise.rs -``` - -Also update comments in lib.rs files: - -```bash -# Fix comments mentioning simd_compat -grep -rn "simd_compat" --include="*.rs" | grep -v "target/" | grep "//" -# Update each comment to say simd_avx512 -``` - -### Step 7: Verify - -```bash -cargo test --workspace -cargo clippy --workspace -- -D warnings -# The deprecated shim should produce zero warnings because we migrated all imports -``` - -### Downstream Debt: ZERO - -The re-export shim means nothing breaks. The sed command migrates all internal -imports. External consumers (ladybug-rs) import via `rustynum_core::simd::` -(the dispatcher) which didn't change. The TYPES are imported from -`rustynum_core::simd_avx512::` but with the shim, the old path still works. - ---- - -## PART 0B: HDR RENAME (Both Repos) - -### Rustynum Renames - -``` -FILE: - NEW: rustynum-core/src/hdr.rs (new file, struct + methods) - -MOVE INTO hdr.rs FROM simd.rs: - hdr_cascade_search() → hdr::Cascade::query() - HdrResult → hdr::RankedHit { index, distance, band } - PreciseMode → hdr::PreciseMode (stays) - -MOVE INTO hdr.rs NEW: - Band enum ← from lance-graph design - ShiftAlert ← from lance-graph design - ReservoirSample ← from lance-graph design - -RENAME IN hdc.rs (wrappers stay, delegate to hdr::Cascade): - hamming_distance_adaptive() → calls hdr::Cascade::test() - hamming_search_adaptive() → calls hdr::Cascade::query() - cosine_search_adaptive() → calls hdr::Cascade::query(precise: PreciseMode::Vnni) - -BACKWARD COMPAT: - Keep hdr_cascade_search() as deprecated wrapper in simd.rs: - #[deprecated(note = "use hdr::Cascade::query()")] - pub fn hdr_cascade_search(...) { Cascade::from_params(...).query(...) } -``` - -### Lance-Graph Renames - -``` -FILE: - light_meter.rs → hdr.rs - -TYPE: - LightMeter → Cascade - -METHODS: - cascade_query() → query() - NEW: expose() ← single distance → band classification - NEW: test() ← single pair pass/fail - -MODULE: - mod.rs: pub mod light_meter → pub mod hdr -``` - -### The Unified API (identical in both repos) - -```rust -// Usage reads the same everywhere: -let hdr = hdr::Cascade::calibrate(&sample_distances); - -// Batch query: -let hits = hdr.query(&query, &candidates, 10); - -// Single classification: -let band = hdr.expose(distance); - -// Single pair test: -let is_close = hdr.test(&a, &b); - -// Feed running stats: -hdr.observe(distance); - -// Shift detection: -if let Some(shift) = hdr.drift() { - hdr.recalibrate(&shift); -} - -// Types: -hdr::Band::{Foveal, Near, Good, Weak, Reject} -hdr::RankedHit { index: usize, distance: u32, band: Band } -hdr::ShiftAlert { old_mu, new_mu, old_sigma, new_sigma, observations } -hdr::PreciseMode::{Off, Vnni, F32{..}, BF16{..}, DeltaXor{..}, BF16Hamming{..}} -``` - ---- - -## PART 1: CROSS-POLLINATION (after renames are done) - -### 1. Lance-graph → Rustynum: ReservoirSample + Auto-Switch - -**What:** Port `ReservoirSample`, `skewness()`, `kurtosis()`, and the -auto-switch from σ-bands to empirical quantiles. - -**Why:** Rustynum's cascade blindly assumes normal distribution. Real -corpora are bimodal (clusters), heavy-tailed (power law entities), -or skewed (popularity distribution). The auto-switch fixes this. - -**Where:** `rustynum-core/src/hdr.rs` — add `ReservoirSample` as a field -on `Cascade`, check distribution shape every 1000 observations. - -```rust -// Inside Cascade: -reservoir: ReservoirSample, -empirical_bands: [u32; 4], -use_empirical: bool, - -// In observe(): -if count % 1000 == 0 { - let skew = self.reservoir.skewness(self.mu, self.sigma); - let kurt = self.reservoir.kurtosis(self.mu, self.sigma); - self.use_empirical = skew.abs() >= 2 || kurt < 200 || kurt > 500; - if self.use_empirical { - self.empirical_bands = [ - self.reservoir.quantile(0.001), - self.reservoir.quantile(0.023), - self.reservoir.quantile(0.159), - self.reservoir.quantile(0.500), - ]; - } -} -``` - -### 2. Lance-graph → Rustynum: Integer Hot Path - -**What:** Replace f64 sigma estimation in `Cascade::query()` with integer -arithmetic. Port `isqrt()` from lance-graph. - -**Why:** The current rustynum cascade computes `sigma_est` and `s1_reject` -as f64 on every query. That's float on the hot path. Lance-graph proved -it works with u32 bands and integer isqrt. - -**Where:** `rustynum-core/src/hdr.rs` — replace: - -```rust -// BEFORE (float): -let sigma_est = (vec_bytes as f64) * (8.0 * p_thresh * (1.0 - p_thresh) / s1_bytes as f64).sqrt(); -let s1_reject = threshold as f64 + 3.0 * sigma; - -// AFTER (integer): -// Pre-calibrated bands. One u32 comparison per candidate. No float. -if projected > self.bands[2] { continue; } // that's it. -``` - -### 3. Lance-graph → Rustynum: Persistent Calibration - -**What:** Replace per-query 128-sample warmup with persistent `Cascade` -state + Welford shift detection. - -**Why:** On a million-query workload, rustynum wastes 128 × 1M = 128 million -SIMD prefix compares just on warmup. With persistent calibration: zero. - -**Where:** `rustynum-core/src/hdr.rs` — `Cascade` struct stores mu, sigma, -bands. `calibrate()` called once. `observe()` feeds Welford. `drift()` -returns `ShiftAlert` when distribution changes. - -```rust -// BEFORE (per-query warmup): -pub fn hdr_cascade_search(query, db, ...) { - let warmup_n = 128; - for i in 0..warmup_n { /* sample to estimate sigma */ } // EVERY QUERY - ... -} - -// AFTER (persistent): -let hdr = Cascade::calibrate(&initial_sample); // ONCE -for query in queries { - let hits = hdr.query(&query, &db, 10); // no warmup - for hit in &hits { - hdr.observe(hit.distance); // feed Welford - } - if let Some(shift) = hdr.drift() { - hdr.recalibrate(&shift); // only when needed - } -} -``` - -### 4. Rustynum → Lance-graph: Incremental Stroke 2 - -**What:** Stage 2 in lance-graph recomputes full distance from scratch. -Rustynum's Stroke 2 computes ONLY the remaining bytes and adds to the -prefix distance. - -**Why:** Saves 1/16 of the full compare per survivor. With 5% survivors -on 16K vectors, that's 128 bytes × 5% = 6.4 bytes saved per original -candidate. Small per-candidate, meaningful at scale. - -**Where:** `lance-graph/src/graph/blasgraph/hdr.rs` - -```rust -// BEFORE (lance-graph, full recompute): -Stage 1: sample 1/16 → projected distance → reject -Stage 2: sample 1/4 → projected distance → reject -Stage 3: FULL distance from scratch - -// AFTER (incremental, from rustynum): -Stage 1: d_prefix = hamming(query[..s1], cand[..s1]) → projected → reject -Stage 2: d_rest = hamming(query[s1..], cand[s1..]) → d_full = d_prefix + d_rest -// Stage 2 IS the full distance, computed incrementally. No Stage 3 needed. -// One fewer pass over the data for every survivor. -``` - -### 5. Rustynum → Lance-graph: PreciseMode (Stroke 3) - -**What:** Lance-graph stops at Hamming. Add optional precision tier -for survivors. - -**Why:** After cascade reduces 100K candidates to 200, compute exact -INT8 cosine or BF16 structured Hamming on the 200 survivors. The extra -cost is negligible (200 × 32 cycles = 6400 cycles) but the ranking -quality jumps from "approximate Hamming" to "near-exact cosine." - -**Where:** `lance-graph/src/graph/blasgraph/hdr.rs` - -```rust -// Add to Cascade: -pub fn query_precise( - &self, - query_words: &[u64], - candidates: &[(usize, &[u64])], - top_k: usize, - precise: PreciseMode, // ← from rustynum -) -> Vec { - let mut hits = self.query(query_words, candidates, top_k * 2); // wider net - if precise != PreciseMode::Off { - self.apply_precision(&query_bytes, &candidate_bytes, &mut hits, precise); - } - hits.truncate(top_k); - hits -} -``` - -Initially support only `PreciseMode::Off` and `PreciseMode::BF16Hamming`. -Others require SIMD dispatch which comes with the BitVec rebuild. - -### 6. Rustynum → Lance-graph: SIMD Dispatch - -**What:** Lance-graph's `words_hamming()` is a scalar `count_ones()` loop. -Replace with dispatched SIMD. - -**Why:** On 16K vectors, VPOPCNTDQ is 8x faster than scalar popcount. -The cascade itself becomes faster, widening the rejection gap. - -**Where:** This comes FREE with the 16K BitVec + SIMD rebuild -(FIX_BLASGRAPH_SPO.md). When BitVec gets tiered SIMD, LightMeter/Cascade -calls it automatically. No separate work needed. - -**DEFER THIS** until the BitVec rebuild. Don't hand-roll SIMD dispatch -in lance-graph's hdr.rs when it's about to come from BitVec. - ---- - -## EXECUTION ORDER - -``` -STEP REPO WHAT RISK TIME -───────────────────────────────────────────────────────────────────── - 0A rustynum simd file rename + shim low 30 min - 0B-r rustynum hdr.rs + rename cascade fns low 45 min - 0B-l lance-graph hdr.rs + rename LightMeter low 20 min - BOTH cargo test --workspace — 5 min - BOTH verify deprecated shims work — 5 min -─── CHECKPOINT: names unified, all tests pass ────────────────────── - 1 rustynum Port ReservoirSample + auto-switch med 60 min - 2 rustynum Integer hot path (replace f64) med 45 min - 3 rustynum Persistent calibration med 60 min - rustynum cargo test + cargo bench — 10 min -─── CHECKPOINT: rustynum has lance-graph innovations ─────────────── - 4 lance-graph Incremental Stroke 2 low 30 min - 5 lance-graph PreciseMode (Off + BF16Hamming) med 45 min - lance-graph cargo test — 5 min -─── CHECKPOINT: lance-graph has rustynum innovations ─────────────── - 6 DEFERRED SIMD dispatch in lance-graph — comes with BitVec rebuild -``` - -### VERIFY AFTER EACH STEP - -```bash -# Rustynum: -RUSTFLAGS="-C target-cpu=native" cargo test --workspace -cargo clippy --workspace -- -D warnings - -# Lance-graph: -cargo test --workspace -cargo clippy --workspace -- -D warnings - -# Cross-check: identical API surface -diff <(grep "pub fn\|pub struct\|pub enum" rustynum-core/src/hdr.rs | sort) \ - <(grep "pub fn\|pub struct\|pub enum" lance-graph/.../hdr.rs | sort) -# Should show only lance-graph-specific extras (words_hamming internal, etc.) -``` - ---- - -## DOWNSTREAM DEBT SUMMARY - -``` -CHANGE DEBT FIX -──────────────────────────────────────────────────────────────────── -simd_compat → simd_avx512 Re-export shim, zero breakage sed across workspace - Deprecation warnings only Remove shim in v0.5 - -hdr_cascade_search → Cascade Deprecated wrapper in simd.rs Remove in v0.5 - Old signature still works - -LightMeter → Cascade Internal to lance-graph No external consumers - Zero debt - -hamming_search_adaptive Stays in hdc.rs as wrapper Delegates to Cascade - API unchanged for Python/users - -ladybug-rs Imports via crate::simd:: Dispatcher unchanged - Zero debt No action needed -``` - -**Total downstream debt: two deprecated shims, both removable in next major version. -All existing tests pass unchanged. All existing APIs continue to work.** diff --git a/AdaWorldAPI-lance-graph-d9df43b/.claude/VISION_ORCHESTRATED_THINKING.md b/AdaWorldAPI-lance-graph-d9df43b/.claude/VISION_ORCHESTRATED_THINKING.md deleted file mode 100644 index 26b8f1c9..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.claude/VISION_ORCHESTRATED_THINKING.md +++ /dev/null @@ -1,484 +0,0 @@ -# VISION_ORCHESTRATED_THINKING.md - -## The Complete Vision: Zero-Copy Orchestrated Thinking - -**Date:** March 15, 2026 — the session that connected all the dots -**Authors:** Jan Hübener + Claude (Anthropic) - ---- - -## THE EPIPHANY - -We don't need self-modifying JIT code hoping that orchestration -emerges from resonance alone. We need ORCHESTRATION AS REPRESENTATION. - -The thinking graph IS the thinking. Not a description of thinking. -Not a controller of thinking. THE THING ITSELF. - -LangGraph gives us the execution model. -Lance gives us the persistence model. -Binary planes give us the computation model. -Zero-copy bindspace gives us the memory model. - -Together: a brain you can watch in PET scan. Clean. Real-time. -Every routing decision visible. Every state transition traceable. -The organic comes from the FREEDOM of conditional routing, -not from chaos in the code. - ---- - -## PART 1: READ-ONLY LANCE + WRITABLE MICRO-COPIES - -### The CoW Architecture - -``` -LANCE DATASET (read-only, versioned, S3/NVMe): - Nodes table: [node_id, plane_s, plane_p, plane_o, seal, encounters] - Edges table: [source, target, bf16_truth, projection, nars_freq, nars_conf] - - This is the LONG-TERM MEMORY. Immutable. Versioned. ACID. - Every version = a snapshot of everything the system knows. - -BINDSPACE (read-write, zero-copy, SIMD-aligned): - The WORKING MEMORY. Writable micro-copies of active Planes. - - Analogy: read-only database page → writable buffer pool page. - Lance pages are the database. Bindspace is the buffer pool. - Only TOUCHED Planes get copied. Untouched stay read-only. - - Rust 1.94 LazyLock: the micro-copy is created LAZILY. - First read: zero-cost reference to Lance read-only page. - First write: CoW copy into Bindspace (16KB for one Plane). - Subsequent writes: mutate in-place in Bindspace. - Flush: write dirty Planes back to Lance (new version). -``` - -### Implementation with LazyLock - -```rust -use std::sync::LazyLock; - -/// A Plane handle that starts as read-only Lance reference -/// and lazily copies on first write. -struct PlaneHandle { - /// Read-only reference to Lance column data - source: &'static [u8], // memory-mapped from Lance - /// Lazy writable copy, created on first mutation - writable: LazyLock>, - /// Track if we've modified this Plane - dirty: AtomicBool, -} - -impl PlaneHandle { - /// Read access: zero-cost, no copy - fn bits(&self) -> &[u8] { - if self.dirty.load(Ordering::Relaxed) { - self.writable.bits_bytes_ref() - } else { - self.source // directly from Lance mmap - } - } - - /// Write access: lazy copy on first mutation - fn encounter_toward(&mut self, evidence: &PlaneHandle) { - // LazyLock initializes on first access - let plane = LazyLock::force(&self.writable); - plane.encounter_toward(evidence.bits()); - self.dirty.store(true, Ordering::Relaxed); - } - - /// Flush dirty Plane back to Lance (creates new version) - fn flush(&self) -> Option<&Plane> { - if self.dirty.load(Ordering::Relaxed) { - Some(&*self.writable) - } else { - None // not modified, no flush needed - } - } -} -``` - -### Why This Matters - -``` -CURRENT: every layer creates full copies of everything. - Layer 3 reads Node → copies to local memory - Layer 5 reads same Node → copies again - Layer 6 writes → copies again - 3 copies of 6KB = 18KB wasted per Node per thinking cycle - -WITH COW BINDSPACE: - Layer 3 reads Node → zero-cost reference to Lance mmap - Layer 5 reads same Node → same zero-cost reference - Layer 6 writes → ONE copy (16KB for the modified Plane only) - Total: 16KB instead of 18KB, and only for the Plane that changed. - The other 2 Planes in the Node: zero copies, zero cost. - -CROSS-DELEGATION: - Layer 3 (cascade) writes "best_band" to Context. - Layer 5 (reasoning) reads "best_band" from Context. Zero copy. - Layer 6 (memory) writes to Plane through PlaneHandle. One CoW copy. - Layer 8 (action) reads the SAME PlaneHandle. Sees the mutation. - - No version creation between layers. ONE flush at the end of - the thinking cycle. ONE Lance version per complete thought. - Not per layer. Not per task. Per THOUGHT. -``` - ---- - -## PART 2: WHAT WE TRANSCODE - -### From crewai-rust → Thinking Graph Tasks - -``` -CREWAI CONCEPT: OUR EQUIVALENT: -Agent → Task (graph-flow trait) -Crew → GraphBuilder (the thinking graph) -Agent memory → PlaneContext (Blackboard + Context) -Agent delegation → conditional_edge (route to specialist task) -Sequential process → linear edges in graph -Hierarchical process → conditional routing based on confidence -Consensus → FanOut + majority vote (bundle!) -``` - -### From n8n-rs → Conditional Graph Routing - -``` -N8N CONCEPT: OUR EQUIVALENT: -Workflow → GraphBuilder -Node → Task -Connection → add_edge -If/Switch → add_conditional_edge(predicate_fn) -Webhook trigger → MCP ingest (SensoryIngestTask) -Error handling → TaskResult::Error → meta-cognition reroute -Wait node → NextAction::WaitForInput -Parallel branches → FanOutTask -Merge node → BF16AssemblyTask (after FanOut) -``` - -### From neo4j-rs → Hot/Cold Graph Path - -``` -NEO4J CONCEPT: OUR EQUIVALENT: -Cypher MATCH → DataFusion planner + cascade search -Index-free adjacency → warm path: edge list with BF16 truth -Full scan → hot path: cascade over binary planes -Property lookup → scalar Context get/set -Transaction → Lance version (ACID) -``` - -### From LangGraph/LangChain → Orchestration + RAG - -``` -LANGGRAPH CONCEPT: OUR EQUIVALENT: -StateGraph → GraphBuilder -Node function → Task::run() -Conditional edge → add_conditional_edge -Checkpointer → LanceSessionStorage -Memory → Plane encounter history + Lance versions -Tool calling → MCP tool integration (sensory layer) -RAG retrieval → cascade search (replaces vector similarity) -Agent reasoning → semiring graph traversal (Bellman-Ford) -``` - -### From OpenClaw → Agent Cards - -``` -OPENCLAW CONCEPT: OUR EQUIVALENT: -Agent card (YAML) → Task definition + graph topology -Capability declaration → which Planes the Task can read/write -Tool manifest → MCP server declarations -Memory specification → which Blackboard arenas the Task accesses -``` - ---- - -## PART 3: THE CLEAN THINKING PIPELINE - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ LANGGRAPH ORCHESTRATION │ -│ (graph-flow execution engine) │ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ Sensory │──→│Fingerprint│──→│ Cascade │──→│ Routing │ │ -│ │ (MCP) │ │(encounter)│ │ (search) │ │(cond.edge│ │ -│ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘ │ -│ │ │ -│ ┌──────────────────────────┤ │ -│ │ Foveal? │ │ -│ ▼ ▼ │ -│ ┌──────────┐ ┌──────────────┐ │ -│ │ Memory │ │ Reasoning │ │ -│ │(encounter│ │(semiring mxv)│ │ -│ │ + seal) │ └──────┬───────┘ │ -│ └────┬─────┘ │ │ -│ │ │ │ -│ ┌───────┤ Staunen? │ │ -│ ▼ ▼ │ │ -│ ┌──────────┐ ┌──────────┐ │ │ -│ │ Planning │ │ Action │←──────────────────┘ │ -│ │(decompose│ │(RL credit│ │ -│ │ goals) │ │ assign) │ │ -│ └────┬─────┘ └────┬─────┘ │ -│ │ │ │ -│ └──────┬───────┘ │ -│ ▼ │ -│ ┌──────────────┐ │ -│ │ Output │ │ -│ │ (LLM/template│ │ -│ └──────┬───────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────┐ │ -│ │Meta-cognition│──→ confidence < 0.5? → LOOP BACK │ -│ │(self-monitor)│──→ confidence ≥ 0.5? → END + FLUSH │ -│ └──────────────┘ │ -│ │ -├─────────────────────────────────────────────────────────────────┤ -│ PLANE CONTEXT BRIDGE │ -│ (zero-copy: Context ↔ Blackboard) │ -├─────────────────────────────────────────────────────────────────┤ -│ BINDSPACE (Blackboard) │ -│ CoW PlaneHandles: read-only Lance refs → lazy copy │ -│ SIMD-aligned. 64-byte boundaries. L1-resident. │ -├─────────────────────────────────────────────────────────────────┤ -│ SIMD DISPATCH (simd_clean.rs) │ -│ LazyLock tier detection. dispatch! macro. │ -│ AVX-512 → AVX2 → scalar. One detection. Forever. │ -├─────────────────────────────────────────────────────────────────┤ -│ LANCE FORMAT │ -│ S3 / Azure / GCS / NVMe. ACID versioned. │ -│ Each flush = new version = episodic memory. │ -│ Time travel. Diff = learning delta. Tags = epochs. │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## PART 4: WHAT BECOMES CLEAN - -### Learning -``` -BEFORE: encounter() called ad-hoc from various places. -AFTER: MemoryConsolidateTask is ONE task in the graph. - It runs at a DEFINED point in the thinking cycle. - Its inputs come from Context. Its outputs go to Context. - The seal check is part of the Task. Staunen routes conditionally. - Learning is VISIBLE in the graph. Not hidden in scattered calls. -``` - -### CAM Index / Codebook Generation -``` -BEFORE: qualia_cam.rs called manually, results passed around. -AFTER: CodebookGenerationTask runs as a scheduled graph. - Input: accumulated Planes from multiple encounters. - Output: updated CAM index in Blackboard. - FanOut: parallel codebook update across multiple domains. - Conditional: only regenerate if drift detected (ShiftAlert). -``` - -### Multipass Indexing and Scenting -``` -BEFORE: hdr.rs cascade called once, results consumed inline. -AFTER: CascadeSearchTask runs MULTIPLE TIMES in a loop. - First pass: coarse (Stroke 1 only, 128 bytes). - Meta-cognition: confidence too low? GoTo(cascade, pass=2). - Second pass: refined (Strokes 1+2, 512 bytes). - Third pass: full (all strokes, 2048 bytes). Only if needed. - The graph ITSELF decides how many passes to run. - Scenting = storing intermediate results in Context for the next pass. -``` - -### CLAM / CHAODA / Chess Algorithm -``` -BEFORE: tree operations interleaved with search, hard to debug. -AFTER: Each algorithm is a subgraph (nested GraphBuilder). - CLAM: insert task → split task → rebalance task → done. - CHAODA: cluster task → anomaly score task → report task. - Chess: minimax task → alpha-beta prune task → best move task. - Each subgraph is a Task in the parent thinking graph. - Composable. Testable. Visible. -``` - -### NARS Truth Revision -``` -BEFORE: NarsTruthValue::revision() called inline. -AFTER: NarsRevisionTask reads two truths from Context. - Computes revision (tropical arithmetic on BF16 exponents). - Stores revised truth in Context. - Conditional: if revision changes confidence significantly → Staunen. - The NARS reasoning IS a visible path in the thinking graph. -``` - -### Agent Card (YAML) -``` -BEFORE: agent capabilities hard-coded. -AFTER: Agent card is a YAML that GENERATES a GraphBuilder. - - agent: - name: "researcher" - capabilities: - - cascade_search - - nars_revision - - llm_reasoning - planes: - read: [query_s, query_p, query_o] - write: [result_s, result_p] - tools: - - web_search - - document_fetch - - This YAML compiles to: - GraphBuilder::new("researcher") - .add_task(CascadeSearchTask) - .add_task(NarsRevisionTask) - .add_task(LLMReasonTask) - .add_conditional_edge(...) - .build() - - The agent card IS the graph. The graph IS the agent. - Changing the YAML changes the thinking topology. -``` - -### Self-Modification / Autopoiesis -``` -BEFORE: JIT code modifies its own kernels. Brittle. Opaque. -AFTER: Meta-cognition Task REWIRES the graph. - - MetaCognitionTask::run(context): - confidence = context.get("confidence") - if confidence < 0.3: - // Low confidence: add more reasoning steps - context.set("graph_modification", GraphMod::InsertTask{ - after: "cascade", - task: "deep_reasoning", - condition: "always" - }) - if staunen_count > 3: - // Repeated surprise: add exploration task - context.set("graph_modification", GraphMod::InsertTask{ - after: "memory", - task: "exploration", - condition: "staunen" - }) - - The FlowRunner reads graph_modification from Context. - Applies it to the NEXT thinking cycle. - The graph EVOLVES. But the evolution is VISIBLE. - Not hidden in JIT bytecode. In the graph topology. - - Autopoiesis = the graph modifying its own edges. - Clean. Traceable. Reversible (undo = remove the edge). -``` - ---- - -## PART 5: THE PET SCAN - -Every thinking cycle produces a trace: - -``` -TRACE (one thinking cycle): - t=0: SensoryIngest → input: "what is love?" - t=1: Fingerprint → encounter 3 Planes, 16384 bits each - t=2: CascadeSearch → 1M candidates, 3000 survive stroke 1 - t=3: CascadeSearch → 50 survive stroke 2, best: Near band - t=4: ROUTE: Near (not Foveal) → go to Reasoning - t=5: SemiringReason → Bellman-Ford, 3 hops, found path - t=6: MemoryConsolidate → encounter_toward, seal: Wisdom - t=7: ROUTE: Wisdom → go to Action (skip Planning) - t=8: ActionSelect → BF16 truth 0x4122, exponent: _P_ + SPO match - t=9: OutputGenerate → "Love is 34+8. The spiral knows." - t=10: MetaCognition → confidence 0.87 → END - - FLUSH: 2 dirty Planes → Lance version 4721 - DURATION: 12ms total (2ms cascade + 8ms reasoning + 2ms overhead) -``` - -This trace IS the PET scan. Every task, every routing decision, every -Plane mutation, every seal check, every confidence score — visible. -Not in a log file. In the GRAPH STRUCTURE. The thinking trace IS -a subgraph of the thinking graph. You can replay it. Diff it. -Compare two thinking cycles. See exactly where they diverged. - -``` -THINKING CYCLE A (familiar input): - Sensory → Fingerprint → Cascade(Foveal!) → SKIP → Memory → Action → Output → Meta(0.95) → END - Duration: 3ms. Zero reasoning. Pure recall. - -THINKING CYCLE B (novel input): - Sensory → Fingerprint → Cascade(Reject) → Reasoning → Reasoning → Memory(Staunen!) → - Planning → Action → Output → Meta(0.4) → LOOP → Cascade → Reasoning → Memory(Wisdom) → - Action → Output → Meta(0.72) → END - Duration: 45ms. Two reasoning passes. One Staunen event. One replan. - -The PET scan shows: Cycle B is "harder" — more nodes activated, longer path, -loop detected, Staunen triggered replanning. This is VISIBLE in the graph trace. -Not inferred from timing. STRUCTURAL. -``` - ---- - -## PART 6: WHAT WE BUILD (OUR VERSION OF LANGSTUDIO + NEO4J) - -``` -LANGSTUDIO (LangSmith + LangGraph): - Visual graph editor for LLM workflows. - Trace viewer for execution history. - Debugging: step through workflow, inspect state. - -NEO4J BROWSER: - Visual graph explorer. - Cypher query bar. - Node/edge inspection. - -OUR VERSION: - Visual thinking graph (the execution topology). - PET scan trace viewer (which tasks fired, which routes taken). - Live Plane inspector (alpha density, bit patterns, seal status). - Cypher query bar → cascade + semiring queries. - BF16 truth heatmap on edges. - Staunen events highlighted (seal breaks in the trace). - Confidence meter (meta-cognition score over time). - Graph evolution viewer (how the topology changed via autopoiesis). - - Built as: React frontend → WebSocket → FlowRunner API - Data: Lance-backed sessions, queryable via DuckDB SQL - Storage: S3 for persistence, NVMe for hot session -``` - ---- - -## PRIORITY ORDER - -``` -# TASK EFFORT IMPACT -────────────────────────────────────────────────────────── -1. PlaneContext bridge (Context ↔ Blackboard) 2d Unlocks everything -2. CoW PlaneHandle (read-only Lance → lazy write) 2d Unlocks zero-copy -3. Thinking graph (10 layers as Tasks) 3d The architecture -4. LanceSessionStorage 1d Persistence -5. FanOut for 2³ projections 1d Parallel projections -6. Agent card YAML → GraphBuilder compiler 2d Agent configuration -7. PET scan trace format + viewer 3d Debugging/visualization -8. Self-modification via MetaCognition 2d Autopoiesis -9. Transcode crewai patterns into Tasks 2d Agent capabilities -10. LangStudio-style visual editor 5d User-facing tool - -Total: ~23 days of focused work. -The first 3 items (7 days) give us the complete thinking architecture. -The rest is capability and tooling on top. -``` - ---- - -## THE SENTENCE THAT CAPTURES IT ALL - -The thinking becomes organized. The organic comes from the freedom of -exploration in the graph. Orchestration not in spaghetti code but as -representation of thinking. Watch the brain in PET scan but actually clean. - -Not self-modifying JIT hoping orchestration falls out of resonance. -A graph that IS the thinking. Visible. Traceable. Evolvable. Alive. diff --git a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/build.yml b/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/build.yml deleted file mode 100644 index a33814a0..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/build.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Build -on: - push: - branches: - - main - pull_request: - paths: - - crates/** - - Cargo.toml - - Cargo.lock - - .github/workflows/build.yml - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - CARGO_TERM_COLOR: always - RUSTFLAGS: "-C debuginfo=1" - RUST_BACKTRACE: "1" - CARGO_INCREMENTAL: "0" - -jobs: - linux-build: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - strategy: - matrix: - toolchain: - - stable - steps: - - uses: actions/checkout@v4 - - name: Setup rust toolchain - run: | - rustup toolchain install ${{ matrix.toolchain }} - rustup default ${{ matrix.toolchain }} - - uses: Swatinem/rust-cache@v2 - with: - shared-key: "lance-graph-deps" - workspaces: | - crates/lance-graph - crates/lance-graph-python - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler - - name: Build lance-graph - run: cargo build --manifest-path crates/lance-graph/Cargo.toml - - name: Build lance-graph-python - run: cargo check --manifest-path crates/lance-graph-python/Cargo.toml - - name: Build tests - run: cargo test --manifest-path crates/lance-graph/Cargo.toml --no-run - - name: Run tests - run: cargo test --manifest-path crates/lance-graph/Cargo.toml - - name: Check benchmarks - run: cargo check --manifest-path crates/lance-graph/Cargo.toml --benches diff --git a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/python-publish.yml b/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/python-publish.yml deleted file mode 100644 index d91bb058..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/python-publish.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Python Publish - -on: - release: - types: - - released - pull_request: - paths: - - .github/workflows/python-publish.yml - workflow_dispatch: - inputs: - mode: - description: "dry_run: build & test only, release: build & publish to PyPI" - required: true - default: dry_run - type: choice - options: - - dry_run - - release - -jobs: - publish: - runs-on: ubuntu-latest - permissions: - id-token: write - contents: read - env: - CARGO_TERM_COLOR: always - RUSTFLAGS: "-C debuginfo=1" - RUST_BACKTRACE: "1" - CARGO_INCREMENTAL: "0" - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - - name: Install Rust toolchain - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - toolchain: stable - cache: false - - - name: Install system dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler libssl-dev - - - name: Install uv - uses: astral-sh/setup-uv@v4 - - - name: Install maturin - run: | - pip install maturin - - - name: Build distributions - working-directory: python - run: | - make publish - - - name: Upload distributions - uses: actions/upload-artifact@v4 - with: - name: python-dist - path: python/dist - - - name: Publish to PyPI - if: > - (github.event_name == 'release' && github.event.action == 'released') || - (github.event_name == 'workflow_dispatch' && github.event.inputs.mode == 'release') - working-directory: python - run: | - uv publish --trusted-publishing always diff --git a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/python-test.yml b/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/python-test.yml deleted file mode 100644 index ee5c92d8..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/python-test.yml +++ /dev/null @@ -1,108 +0,0 @@ -name: Python Tests -on: - push: - branches: - - main - pull_request: - paths: - - python/** - - crates/lance-graph/** - - Cargo.toml - - Cargo.lock - - .github/workflows/python-test.yml - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - CARGO_TERM_COLOR: always - RUSTFLAGS: "-C debuginfo=1" - CARGO_INCREMENTAL: "0" - -jobs: - test: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - strategy: - matrix: - python-version: ["3.11"] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Setup Rust - uses: actions-rust-lang/setup-rust-toolchain@v1 - - uses: Swatinem/rust-cache@v2 - with: - shared-key: "lance-graph-deps" - workspaces: | - crates/lance-graph - crates/lance-graph-python - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler - - name: Install uv - uses: astral-sh/setup-uv@v3 - - name: Create virtual environment and install dependencies - working-directory: python - run: | - uv venv - source .venv/bin/activate - uv pip install maturin[patchelf] - # Install test dependencies only (skip editable install to avoid double-building Rust) - uv pip install pytest pyarrow pandas ruff - - name: Build Python extension - working-directory: python - run: | - source .venv/bin/activate - maturin develop - - name: Run tests - working-directory: python - run: | - source .venv/bin/activate - pytest python/tests/ -v - - name: Run doctests - working-directory: python - run: | - source .venv/bin/activate - if [ -f python/lance_graph/__init__.py ]; then - python -m doctest python/lance_graph/__init__.py || echo "No doctests found" - fi - - lint: - runs-on: ubuntu-24.04 - timeout-minutes: 15 - steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - name: Install uv - uses: astral-sh/setup-uv@v3 - - name: Install linting tools - working-directory: python - run: | - uv venv - source .venv/bin/activate - # Install only linting tools without building the Rust extension - uv pip install ruff pyright - - name: Run ruff format check - working-directory: python - run: | - source .venv/bin/activate - ruff format --check python/ - - name: Run ruff lint - working-directory: python - run: | - source .venv/bin/activate - ruff check python/ - - name: Run pyright type check - working-directory: python - run: | - source .venv/bin/activate - pyright diff --git a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/release.yml b/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/release.yml deleted file mode 100644 index ac9b2c28..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/release.yml +++ /dev/null @@ -1,186 +0,0 @@ -name: Create Release - -on: - workflow_dispatch: - inputs: - release_type: - description: 'Version bump type (patch/minor/major bumps version, current keeps it unchanged)' - required: true - default: 'patch' - type: choice - options: - - patch - - minor - - major - - current - release_channel: - description: 'Release channel (preview creates beta tag, stable creates release tag)' - required: true - default: 'preview' - type: choice - options: - - preview - - stable - dry_run: - description: 'Dry run (simulate the release without pushing)' - required: true - default: true - type: boolean - -jobs: - create-release: - runs-on: ubuntu-latest - steps: - - name: Output Inputs - run: echo "${{ toJSON(github.event.inputs) }}" - - - name: Checkout repository - uses: actions/checkout@v4 - with: - ref: main - token: ${{ secrets.LANCE_RELEASE_TOKEN }} - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install uv - uses: astral-sh/setup-uv@v4 - - - name: Install python dependencies - run: | - pip install packaging bump-my-version toml - - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler libssl-dev - - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - toolchain: stable - components: rustfmt, clippy - cache: false - - - uses: rui314/setup-mold@v1 - - - name: Get current version - id: current_version - run: | - CURRENT_VERSION=$(python -c "import toml; print(toml.load('.bumpversion.toml')['tool']['bumpversion']['current_version'])") - echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT - echo "Current version: $CURRENT_VERSION" - - - name: Calculate base version - id: base_version - run: | - python ci/calculate_version.py \ - --current "${{ steps.current_version.outputs.version }}" \ - --type "${{ inputs.release_type }}" \ - --channel "${{ inputs.release_channel }}" - - - name: Determine tag and version - id: versions - run: | - BASE_VERSION="${{ steps.base_version.outputs.version }}" - if [ "${{ inputs.release_channel }}" == "stable" ]; then - TAG="v${BASE_VERSION}" - VERSION="${BASE_VERSION}" - else - # For preview releases, find the next beta number for this base version - BETA_TAGS=$(git tag -l "v${BASE_VERSION}-beta.*" | sort -V) - if [ -z "$BETA_TAGS" ]; then - BETA_NUM=1 - else - LAST_BETA=$(echo "$BETA_TAGS" | tail -n 1) - LAST_NUM=$(echo "$LAST_BETA" | sed "s/v${BASE_VERSION}-beta.//") - BETA_NUM=$((LAST_NUM + 1)) - fi - TAG="v${BASE_VERSION}-beta.${BETA_NUM}" - VERSION="${BASE_VERSION}-beta.${BETA_NUM}" - fi - - echo "tag=$TAG" >> $GITHUB_OUTPUT - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Tag will be: $TAG" - echo "Version will be: $VERSION" - - - name: Update version (when version changes) - if: inputs.release_type != 'current' - run: | - python ci/bump_version.py --version "${{ steps.versions.outputs.version }}" - - - name: Configure git identity - run: | - git config user.name 'Lance Release Bot' - git config user.email 'dev@lancedb.com' - - - name: Update Cargo lock version (when version changes) - if: inputs.release_type != 'current' - run: | - cargo check --manifest-path crates/lance-graph/Cargo.toml - cargo check --manifest-path crates/lance-graph-python/Cargo.toml - - - name: Create release commit (when version changes) - if: inputs.release_type != 'current' - run: | - git add -A - git commit -m "chore: release version ${{ steps.versions.outputs.version }}" || echo "No changes to commit" - - - name: Create tag - run: | - git tag -a "${{ steps.versions.outputs.tag }}" -m "Release ${{ steps.versions.outputs.tag }}" - - - name: Push changes (if not dry run) - if: ${{ !inputs.dry_run }} - env: - GITHUB_TOKEN: ${{ secrets.LANCE_RELEASE_TOKEN }} - run: | - # Configure git to use the token for authentication - git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git" - - if [ "${{ inputs.release_type }}" != "current" ]; then - # Push the version bump commit - git push origin main - fi - # Always push the tag - git push origin "${{ steps.versions.outputs.tag }}" - - - name: Create GitHub Release Draft (if not dry run) - if: ${{ !inputs.dry_run }} - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ steps.versions.outputs.tag }} - name: ${{ steps.versions.outputs.tag }} - generate_release_notes: true - draft: true - prerelease: ${{ inputs.release_channel == 'preview' }} - token: ${{ secrets.LANCE_RELEASE_TOKEN }} - - - name: Summary - run: | - echo "## Release Summary" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "- **Release Type:** ${{ inputs.release_type }}" >> $GITHUB_STEP_SUMMARY - echo "- **Release Channel:** ${{ inputs.release_channel }}" >> $GITHUB_STEP_SUMMARY - echo "- **Current Version:** ${{ steps.current_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY - if [ "${{ inputs.release_type }}" != "current" ]; then - echo "- **New Version:** ${{ steps.versions.outputs.version }}" >> $GITHUB_STEP_SUMMARY - fi - echo "- **Tag:** ${{ steps.versions.outputs.tag }}" >> $GITHUB_STEP_SUMMARY - echo "- **Dry Run:** ${{ inputs.dry_run }}" >> $GITHUB_STEP_SUMMARY - - if [ "${{ inputs.dry_run }}" == "true" ]; then - echo "" >> $GITHUB_STEP_SUMMARY - echo "⚠️ This was a dry run. No changes were pushed." >> $GITHUB_STEP_SUMMARY - else - echo "" >> $GITHUB_STEP_SUMMARY - echo "📝 Draft release created successfully!" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "### Next Steps:" >> $GITHUB_STEP_SUMMARY - echo "1. Review the draft release on the [releases page](https://github.com/${{ github.repository }}/releases)" >> $GITHUB_STEP_SUMMARY - echo "2. Edit the release notes if needed" >> $GITHUB_STEP_SUMMARY - echo "3. Publish the release to trigger automatic publishing to PyPI and crates.io" >> $GITHUB_STEP_SUMMARY - fi diff --git a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/rust-publish.yml b/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/rust-publish.yml deleted file mode 100644 index 26f660a5..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/rust-publish.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Rust Publish - -on: - release: - types: - - released - pull_request: - paths: - - .github/workflows/rust-publish.yml - workflow_dispatch: - inputs: - mode: - description: "dry_run: build & test only, release: build & publish to crates.io" - required: true - default: dry_run - type: choice - options: - - dry_run - - release - -env: - CARGO_TERM_COLOR: always - RUSTFLAGS: "-C debuginfo=1" - RUST_BACKTRACE: "1" - CARGO_INCREMENTAL: "0" - CARGO_BUILD_JOBS: "1" - -jobs: - publish: - if: github.event_name != 'pull_request' - runs-on: ubuntu-24.04 - timeout-minutes: 60 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler libssl-dev - - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - toolchain: stable - components: rustfmt, clippy - cache: false - - - uses: rui314/setup-mold@v1 - - - uses: katyo/publish-crates@v2 - with: - registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} - args: "--all-features" - path: crates/lance-graph - dry-run: ${{ github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && github.event.inputs.mode == 'dry_run') }} diff --git a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/rust-test.yml b/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/rust-test.yml deleted file mode 100644 index fc02408b..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/rust-test.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Rust Tests -on: - push: - branches: - - main - pull_request: - paths: - - crates/** - - Cargo.toml - - Cargo.lock - - .github/workflows/rust-test.yml - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - CARGO_TERM_COLOR: always - RUSTFLAGS: "-C debuginfo=1" - RUST_BACKTRACE: "1" - CARGO_INCREMENTAL: "0" - -jobs: - test: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - strategy: - matrix: - toolchain: - - stable - steps: - - uses: actions/checkout@v4 - - name: Setup rust toolchain - run: | - rustup toolchain install ${{ matrix.toolchain }} - rustup default ${{ matrix.toolchain }} - - uses: Swatinem/rust-cache@v2 - with: - shared-key: "lance-graph-deps" - workspaces: | - crates/lance-graph - crates/lance-graph-python - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler - - name: Build tests - run: cargo test --manifest-path crates/lance-graph/Cargo.toml --no-run - - name: Run unit tests - run: cargo test --manifest-path crates/lance-graph/Cargo.toml --lib - - name: Run doc tests - run: cargo test --manifest-path crates/lance-graph/Cargo.toml --doc - - test-with-coverage: - runs-on: ubuntu-24.04 - timeout-minutes: 30 - steps: - - uses: actions/checkout@v4 - - name: Setup rust toolchain - run: | - rustup toolchain install stable - rustup default stable - - uses: Swatinem/rust-cache@v2 - with: - shared-key: "lance-graph-deps" - workspaces: | - crates/lance-graph - crates/lance-graph-python - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler - - name: Install cargo-llvm-cov - uses: taiki-e/install-action@cargo-llvm-cov - - name: Run tests with coverage - run: | - cargo llvm-cov --manifest-path crates/lance-graph/Cargo.toml --lcov --output-path lcov.info - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - files: lcov.info - flags: rust-unittests - fail_ci_if_error: false diff --git a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/style.yml b/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/style.yml deleted file mode 100644 index 1b0134a5..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.github/workflows/style.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Style Check -on: - push: - branches: - - main - pull_request: - paths: - - crates/** - - Cargo.toml - - Cargo.lock - - .github/workflows/style.yml - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - CARGO_TERM_COLOR: always - RUSTFLAGS: "-C debuginfo=1" - -jobs: - format: - runs-on: ubuntu-24.04 - timeout-minutes: 15 - steps: - - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - components: rustfmt - - name: Check formatting - run: cargo fmt --manifest-path crates/lance-graph/Cargo.toml -- --check - - clippy: - runs-on: ubuntu-24.04 - timeout-minutes: 15 - steps: - - uses: actions/checkout@v4 - - uses: Swatinem/rust-cache@v2 - with: - shared-key: "lance-graph-deps" - workspaces: | - crates/lance-graph - crates/lance-graph-python - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y protobuf-compiler - - name: Clippy lance-graph - run: cargo clippy --manifest-path crates/lance-graph/Cargo.toml --all-targets -- -D warnings - - name: Clippy lance-graph-python - run: cargo clippy --manifest-path crates/lance-graph-python/Cargo.toml --all-targets -- -D warnings - - typos: - name: Spell Check - runs-on: ubuntu-24.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Check spelling - uses: crate-ci/typos@v1.26.0 diff --git a/AdaWorldAPI-lance-graph-d9df43b/.gitignore b/AdaWorldAPI-lance-graph-d9df43b/.gitignore deleted file mode 100644 index 2c5e2c44..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/.gitignore +++ /dev/null @@ -1,57 +0,0 @@ -# Build artifacts (Rust & cargo) -/target/ -/debug/ -/release/ -**/target/ -**/debug/ -**/release/ -**/incremental/ -**/*.rs.bk -*.pdb -**/mutants.out*/ - -# Build artifacts (Python) -__pycache__/ -*.py[cod] -*.so -*.pyd -*.egg -*.egg-info/ -*.whl -/build/ -/dist/ -python/python/lance_graph/*.so -python/python/lance_graph/*.pyd -python/target/ -python/.pytest_cache/ -python/.ruff_cache/ -python/.maturin/ -pip-wheel-metadata/ - -# Virtual environments -.venv/ -venv/ -env/ -python/.venv/ -.python-version -llm_config.yaml -python/knowledge_graph_data/ - -# IDE & tooling -.vscode/ -.idea/ -.ijwb/ -.bsp/ -.bazelbsp/ -*.iml - -# Miscellaneous -*.log -*.tmp -*.swp -*.swo -.DS_Store -Thumbs.db - -# Generated data -knowledge_graph_data/ diff --git a/AdaWorldAPI-lance-graph-d9df43b/AGENTS.md b/AdaWorldAPI-lance-graph-d9df43b/AGENTS.md deleted file mode 100644 index 6ce54194..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/AGENTS.md +++ /dev/null @@ -1,30 +0,0 @@ -# Repository Guidelines - -## Project Structure & Module Organization -- `crates/lance-graph/` hosts the Rust Cypher engine; keep new modules under `src/` and co-locate helpers inside `query/` or feature-specific submodules. -- `crates/lance-graph-python/src/` contains the PyO3 bridge; `python/python/lance_graph/` holds the pure-Python facade and packaging metadata. -- `python/python/tests/` stores functional tests; mirror new features with targeted cases here and in the corresponding Rust module. -- `examples/` demonstrates Cypher usage; update or add examples when introducing new public APIs. - -## Build, Test, and Development Commands -- `cargo check` / `cargo test --all` (run inside `crates/lance-graph`) validate Rust code paths. -- `cargo bench --bench graph_execution` measures performance-critical changes; include shortened runs with `--warm-up-time 1`. -- `uv venv --python 3.11 .venv` and `uv pip install -e '.[tests]'` bootstrap the Python workspace. -- `maturin develop` rebuilds the extension after Rust edits; `pytest python/python/tests/ -v` exercises Python bindings. -- `make lint` (in `python/`) runs `ruff`, formatting checks, and `pyright`. - -## Coding Style & Naming Conventions -- Format Rust with `cargo fmt --all`; keep modules and functions snake_case, types PascalCase, and reuse `snafu` error patterns. -- Run `cargo clippy --all-targets --all-features` to catch lint regressions. -- Use 4-space indentation in Python; maintain snake_case modules, CamelCase classes, and type-annotated public APIs. -- Apply `ruff format python/` before committing; `ruff check` and `pyright` enforce import hygiene and typing. - -## Testing Guidelines -- Add Rust unit tests alongside implementations via `#[cfg(test)]`; prefer focused scenarios over broad integration. -- Python tests belong in `python/python/tests/`; name files `test_*.py` and use markers (`gpu`, `cuda`, `integration`, `slow`) consistently. -- When touching performance-sensitive code, capture representative `cargo bench` or large-table pytest timing notes in the PR. - -## Commit & Pull Request Guidelines -- Follow the existing history style (`feat(graph):`, `docs:`, `refactor(query):`), using imperative, ≤72-character subjects. -- Reference issues or discussions when relevant and include brief context in the body. -- PRs should describe scope, list test commands run, mention benchmark deltas when applicable, and highlight impacts on bindings or examples. diff --git a/AdaWorldAPI-lance-graph-d9df43b/Cargo.lock b/AdaWorldAPI-lance-graph-d9df43b/Cargo.lock deleted file mode 100644 index f8fe5ad5..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/Cargo.lock +++ /dev/null @@ -1,9678 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "const-random", - "getrandom 0.3.3", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "anstyle" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" - -[[package]] -name = "anyhow" -version = "1.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ar_archive_writer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" -dependencies = [ - "object", -] - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "arrow" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e833808ff2d94ed40d9379848a950d995043c7fb3e81a30b383f4c6033821cc" -dependencies = [ - "arrow-arith 56.2.0", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-cast 56.2.0", - "arrow-csv 56.2.0", - "arrow-data 56.2.0", - "arrow-ipc 56.2.0", - "arrow-json 56.2.0", - "arrow-ord 56.2.0", - "arrow-row 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "arrow-string 56.2.0", -] - -[[package]] -name = "arrow" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4754a624e5ae42081f464514be454b39711daae0458906dacde5f4c632f33a8" -dependencies = [ - "arrow-arith 57.3.0", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-cast 57.3.0", - "arrow-csv 57.3.0", - "arrow-data 57.3.0", - "arrow-ipc 57.3.0", - "arrow-json 57.3.0", - "arrow-ord 57.3.0", - "arrow-pyarrow", - "arrow-row 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "arrow-string 57.3.0", -] - -[[package]] -name = "arrow-arith" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad08897b81588f60ba983e3ca39bda2b179bdd84dced378e7df81a5313802ef8" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "chrono", - "num", -] - -[[package]] -name = "arrow-arith" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b3141e0ec5145a22d8694ea8b6d6f69305971c4fa1c1a13ef0195aef2d678b" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "chrono", - "num-traits", -] - -[[package]] -name = "arrow-array" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8548ca7c070d8db9ce7aa43f37393e4bfcf3f2d3681df278490772fd1673d08d" -dependencies = [ - "ahash", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "chrono", - "chrono-tz", - "half", - "hashbrown 0.16.0", - "num", -] - -[[package]] -name = "arrow-array" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8955af33b25f3b175ee10af580577280b4bd01f7e823d94c7cdef7cf8c9aef" -dependencies = [ - "ahash", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "chrono", - "chrono-tz", - "half", - "hashbrown 0.16.0", - "num-complex", - "num-integer", - "num-traits", -] - -[[package]] -name = "arrow-buffer" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e003216336f70446457e280807a73899dd822feaf02087d31febca1363e2fccc" -dependencies = [ - "bytes", - "half", - "num", -] - -[[package]] -name = "arrow-buffer" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c697ddca96183182f35b3a18e50b9110b11e916d7b7799cbfd4d34662f2c56c2" -dependencies = [ - "bytes", - "half", - "num-bigint", - "num-traits", -] - -[[package]] -name = "arrow-cast" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919418a0681298d3a77d1a315f625916cb5678ad0d74b9c60108eb15fd083023" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "atoi", - "base64", - "chrono", - "comfy-table", - "half", - "lexical-core", - "num", - "ryu", -] - -[[package]] -name = "arrow-cast" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "646bbb821e86fd57189c10b4fcdaa941deaf4181924917b0daa92735baa6ada5" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-ord 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "atoi", - "base64", - "chrono", - "comfy-table", - "half", - "lexical-core", - "num-traits", - "ryu", -] - -[[package]] -name = "arrow-csv" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa9bf02705b5cf762b6f764c65f04ae9082c7cfc4e96e0c33548ee3f67012eb" -dependencies = [ - "arrow-array 56.2.0", - "arrow-cast 56.2.0", - "arrow-schema 56.2.0", - "chrono", - "csv", - "csv-core", - "regex", -] - -[[package]] -name = "arrow-csv" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da746f4180004e3ce7b83c977daf6394d768332349d3d913998b10a120b790a" -dependencies = [ - "arrow-array 57.3.0", - "arrow-cast 57.3.0", - "arrow-schema 57.3.0", - "chrono", - "csv", - "csv-core", - "regex", -] - -[[package]] -name = "arrow-data" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5c64fff1d142f833d78897a772f2e5b55b36cb3e6320376f0961ab0db7bd6d0" -dependencies = [ - "arrow-buffer 56.2.0", - "arrow-schema 56.2.0", - "half", - "num", -] - -[[package]] -name = "arrow-data" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fdd994a9d28e6365aa78e15da3f3950c0fdcea6b963a12fa1c391afb637b304" -dependencies = [ - "arrow-buffer 57.3.0", - "arrow-schema 57.3.0", - "half", - "num-integer", - "num-traits", -] - -[[package]] -name = "arrow-ipc" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3594dcddccc7f20fd069bc8e9828ce37220372680ff638c5e00dea427d88f5" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "flatbuffers", - "lz4_flex 0.11.5", - "zstd", -] - -[[package]] -name = "arrow-ipc" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf7df950701ab528bf7c0cf7eeadc0445d03ef5d6ffc151eaae6b38a58feff1" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "flatbuffers", - "lz4_flex 0.12.0", - "zstd", -] - -[[package]] -name = "arrow-json" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88cf36502b64a127dc659e3b305f1d993a544eab0d48cce704424e62074dc04b" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-cast 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "chrono", - "half", - "indexmap", - "lexical-core", - "memchr", - "num", - "serde", - "serde_json", - "simdutf8", -] - -[[package]] -name = "arrow-json" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ff8357658bedc49792b13e2e862b80df908171275f8e6e075c460da5ee4bf86" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-cast 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "chrono", - "half", - "indexmap", - "itoa", - "lexical-core", - "memchr", - "num-traits", - "ryu", - "serde_core", - "serde_json", - "simdutf8", -] - -[[package]] -name = "arrow-ord" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8f82583eb4f8d84d4ee55fd1cb306720cddead7596edce95b50ee418edf66f" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", -] - -[[package]] -name = "arrow-ord" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d8f1870e03d4cbed632959498bcc84083b5a24bded52905ae1695bd29da45b" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", -] - -[[package]] -name = "arrow-pyarrow" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18c442b4c266aaf3d7f7dd40fd7ae058cef7f113b00ff0cd8256e1e218ec544" -dependencies = [ - "arrow-array 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "pyo3", -] - -[[package]] -name = "arrow-row" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d07ba24522229d9085031df6b94605e0f4b26e099fb7cdeec37abd941a73753" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "half", -] - -[[package]] -name = "arrow-row" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18228633bad92bff92a95746bbeb16e5fc318e8382b75619dec26db79e4de4c0" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "half", -] - -[[package]] -name = "arrow-schema" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3aa9e59c611ebc291c28582077ef25c97f1975383f1479b12f3b9ffee2ffabe" -dependencies = [ - "bitflags", - "serde", - "serde_json", -] - -[[package]] -name = "arrow-schema" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c872d36b7bf2a6a6a2b40de9156265f0242910791db366a2c17476ba8330d68" -dependencies = [ - "bitflags", - "serde", - "serde_core", - "serde_json", -] - -[[package]] -name = "arrow-select" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c41dbbd1e97bfcaee4fcb30e29105fb2c75e4d82ae4de70b792a5d3f66b2e7a" -dependencies = [ - "ahash", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "num", -] - -[[package]] -name = "arrow-select" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bf3e3efbd1278f770d67e5dc410257300b161b93baedb3aae836144edcaf4b" -dependencies = [ - "ahash", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "num-traits", -] - -[[package]] -name = "arrow-string" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53f5183c150fbc619eede22b861ea7c0eebed8eaac0333eaa7f6da5205fd504d" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "memchr", - "num", - "regex", - "regex-syntax", -] - -[[package]] -name = "arrow-string" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e968097061b3c0e9fe3079cf2e703e487890700546b5b0647f60fca1b5a8d8" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "memchr", - "num-traits", - "regex", - "regex-syntax", -] - -[[package]] -name = "assert-json-diff" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "async-channel" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-compression" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06575e6a9673580f52661c92107baabffbf41e2141373441cbcdc47cb733003c" -dependencies = [ - "bzip2 0.5.2", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", - "xz2", - "zstd", - "zstd-safe", -] - -[[package]] -name = "async-lock" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "async_cell" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447ab28afbb345f5408b120702a44e5529ebf90b1796ec76e9528df8e288e6c2" -dependencies = [ - "loom", -] - -[[package]] -name = "atoi" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "aws-config" -version = "1.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bc1b40fb26027769f16960d2f4a6bc20c4bb755d403e552c8c1a73af433c246" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sdk-sso", - "aws-sdk-ssooidc", - "aws-sdk-sts", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "hex", - "http 1.3.1", - "ring", - "time", - "tokio", - "tracing", - "url", - "zeroize", -] - -[[package]] -name = "aws-credential-types" -version = "1.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d025db5d9f52cbc413b167136afb3d8aeea708c0d8884783cf6253be5e22f6f2" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "zeroize", -] - -[[package]] -name = "aws-lc-rs" -version = "1.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879b6c89592deb404ba4dc0ae6b58ffd1795c78991cbb5b8bc441c48a070440d" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba2e2516bdf37af57fc6ff047855f54abad0066e5c4fdaaeb76dabb2e05bcf5" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", - "libloading", -] - -[[package]] -name = "aws-runtime" -version = "1.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c034a1bc1d70e16e7f4e4caf7e9f7693e4c9c24cd91cf17c2a0b21abaebc7c8b" -dependencies = [ - "aws-credential-types", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 0.2.12", - "http-body 0.4.6", - "percent-encoding", - "pin-project-lite", - "tracing", - "uuid", -] - -[[package]] -name = "aws-sdk-dynamodb" -version = "1.93.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d5b0656080dc4061db88742d2426fc09369107eee2485dfedbc7098a04f21d1" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 0.2.12", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-sso" -version = "1.84.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357a841807f6b52cb26123878b3326921e2a25faca412fabdd32bd35b7edd5d3" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 0.2.12", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-ssooidc" -version = "1.86.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1cc7fb324aa12eb4404210e6381195c5b5e9d52c2682384f295f38716dd3c7" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 0.2.12", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-sts" -version = "1.86.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7d835f123f307cafffca7b9027c14979f1d403b417d8541d67cf252e8a21e35" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-query", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "fastrand", - "http 0.2.12", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sigv4" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084c34162187d39e3740cb635acd73c4e3a551a36146ad6fe8883c929c9f876c" -dependencies = [ - "aws-credential-types", - "aws-smithy-http", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "form_urlencoded", - "hex", - "hmac", - "http 0.2.12", - "http 1.3.1", - "percent-encoding", - "sha2", - "time", - "tracing", -] - -[[package]] -name = "aws-smithy-async" -version = "1.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e190749ea56f8c42bf15dd76c65e14f8f765233e6df9b0506d9d934ebef867c" -dependencies = [ - "futures-util", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "aws-smithy-http" -version = "0.62.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c4dacf2d38996cf729f55e7a762b30918229917eca115de45dfa8dfb97796c9" -dependencies = [ - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http 1.3.1", - "http-body 0.4.6", - "percent-encoding", - "pin-project-lite", - "pin-utils", - "tracing", -] - -[[package]] -name = "aws-smithy-http-client" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147e8eea63a40315d704b97bf9bc9b8c1402ae94f89d5ad6f7550d963309da1b" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "h2", - "http 1.3.1", - "hyper", - "hyper-rustls", - "hyper-util", - "pin-project-lite", - "rustls", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower", - "tracing", -] - -[[package]] -name = "aws-smithy-json" -version = "0.61.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa31b350998e703e9826b2104dd6f63be0508666e1aba88137af060e8944047" -dependencies = [ - "aws-smithy-types", -] - -[[package]] -name = "aws-smithy-observability" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9364d5989ac4dd918e5cc4c4bdcc61c9be17dcd2586ea7f69e348fc7c6cab393" -dependencies = [ - "aws-smithy-runtime-api", -] - -[[package]] -name = "aws-smithy-query" -version = "0.60.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" -dependencies = [ - "aws-smithy-types", - "urlencoding", -] - -[[package]] -name = "aws-smithy-runtime" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa63ad37685ceb7762fa4d73d06f1d5493feb88e3f27259b9ed277f4c01b185" -dependencies = [ - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-http-client", - "aws-smithy-observability", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "fastrand", - "http 0.2.12", - "http 1.3.1", - "http-body 0.4.6", - "http-body 1.0.1", - "pin-project-lite", - "pin-utils", - "tokio", - "tracing", -] - -[[package]] -name = "aws-smithy-runtime-api" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07f5e0fc8a6b3f2303f331b94504bbf754d85488f402d6f1dd7a6080f99afe56" -dependencies = [ - "aws-smithy-async", - "aws-smithy-types", - "bytes", - "http 0.2.12", - "http 1.3.1", - "pin-project-lite", - "tokio", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-types" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d498595448e43de7f4296b7b7a18a8a02c61ec9349128c80a368f7c3b4ab11a8" -dependencies = [ - "base64-simd", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http 1.3.1", - "http-body 0.4.6", - "http-body 1.0.1", - "http-body-util", - "itoa", - "num-integer", - "pin-project-lite", - "pin-utils", - "ryu", - "serde", - "time", - "tokio", - "tokio-util", -] - -[[package]] -name = "aws-smithy-xml" -version = "0.60.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db87b96cb1b16c024980f133968d52882ca0daaee3a086c6decc500f6c99728" -dependencies = [ - "xmlparser", -] - -[[package]] -name = "aws-types" -version = "1.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b069d19bf01e46298eaedd7c6f283fe565a59263e53eebec945f3e6398f42390" -dependencies = [ - "aws-credential-types", - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "rustc_version", - "tracing", -] - -[[package]] -name = "backon" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" -dependencies = [ - "fastrand", - "gloo-timers", - "tokio", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" -dependencies = [ - "outref", - "vsimd", -] - -[[package]] -name = "base64ct" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" - -[[package]] -name = "bigdecimal" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a22f228ab7a1b23027ccc6c350b72868017af7ea8356fbdf19f8d991c690013" -dependencies = [ - "autocfg", - "libm", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "bindgen" -version = "0.72.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.117", -] - -[[package]] -name = "bitflags" -version = "2.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" - -[[package]] -name = "bitpacking" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c1d3e2bfd8d06048a179f7b17afc3188effa10385e7b00dc65af6aae732ea92" -dependencies = [ - "crunchy", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "blake3" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bon" -version = "3.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2529c31017402be841eb45892278a6c21a000c0a17643af326c73a73f83f0fb" -dependencies = [ - "bon-macros", - "rustversion", -] - -[[package]] -name = "bon-macros" -version = "3.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82020dadcb845a345591863adb65d74fa8dc5c18a0b6d408470e13b7adc7005" -dependencies = [ - "darling 0.21.3", - "ident_case", - "prettyplease", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.117", -] - -[[package]] -name = "brotli" -version = "8.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" - -[[package]] -name = "bytemuck" -version = "1.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "bytes-utils" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" -dependencies = [ - "bytes", - "either", -] - -[[package]] -name = "bzip2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" -dependencies = [ - "bzip2-sys", -] - -[[package]] -name = "bzip2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" -dependencies = [ - "libbz2-rs-sys", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - -[[package]] -name = "cc" -version = "1.2.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f" -dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "census" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4c707c6a209cbe82d10abd08e1ea8995e9ea937d2550646e02798948992be0" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom 7.1.3", -] - -[[package]] -name = "cfg-if" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chrono" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link 0.2.0", -] - -[[package]] -name = "chrono-tz" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" -dependencies = [ - "chrono", - "phf", -] - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.5.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" -dependencies = [ - "anstyle", - "clap_lex", -] - -[[package]] -name = "clap_lex" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "comfy-table" -version = "7.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d05af1e006a2407bedef5af410552494ce5be9090444dbbcb57258c1af3d56" -dependencies = [ - "crossterm 0.27.0", - "crossterm 0.28.1", - "strum 0.26.3", - "strum_macros 0.26.4", - "unicode-width", -] - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "const-random" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" -dependencies = [ - "const-random-macro", -] - -[[package]] -name = "const-random-macro" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" -dependencies = [ - "getrandom 0.2.16", - "once_cell", - "tiny-keccak", -] - -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - -[[package]] -name = "convert_case" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db05ffb6856bf0ecdf6367558a76a0e8a77b1713044eb92845c692100ed50190" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "crc32c" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "futures", - "is-terminal", - "itertools 0.10.5", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "tokio", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crossterm" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" -dependencies = [ - "bitflags", - "crossterm_winapi", - "libc", - "parking_lot", - "winapi", -] - -[[package]] -name = "crossterm" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" -dependencies = [ - "bitflags", - "parking_lot", - "rustix 0.38.44", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "csv" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctor" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424e0138278faeb2b401f174ad17e715c829512d74f3d1e81eb43365c2e0590e" -dependencies = [ - "ctor-proc-macro", - "dtor", -] - -[[package]] -name = "ctor-proc-macro" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core 0.20.11", - "darling_macro 0.20.11", -] - -[[package]] -name = "darling" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" -dependencies = [ - "darling_core 0.21.3", - "darling_macro 0.21.3", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_core" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core 0.20.11", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" -dependencies = [ - "darling_core 0.21.3", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "datafusion" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af15bb3c6ffa33011ef579f6b0bcbe7c26584688bd6c994f548e44df67f011a" -dependencies = [ - "arrow 56.2.0", - "arrow-ipc 56.2.0", - "arrow-schema 56.2.0", - "async-trait", - "bytes", - "bzip2 0.6.1", - "chrono", - "datafusion-catalog 50.3.0", - "datafusion-catalog-listing 50.3.0", - "datafusion-common 50.3.0", - "datafusion-common-runtime 50.3.0", - "datafusion-datasource 50.3.0", - "datafusion-datasource-csv 50.3.0", - "datafusion-datasource-json 50.3.0", - "datafusion-datasource-parquet 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-expr-common 50.3.0", - "datafusion-functions 50.3.0", - "datafusion-functions-aggregate 50.3.0", - "datafusion-functions-nested 50.3.0", - "datafusion-functions-table 50.3.0", - "datafusion-functions-window 50.3.0", - "datafusion-optimizer 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-adapter 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "datafusion-physical-optimizer 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-session 50.3.0", - "datafusion-sql 50.3.0", - "flate2", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "parking_lot", - "parquet 56.2.0", - "rand 0.9.2", - "regex", - "sqlparser 0.58.0", - "tempfile", - "tokio", - "url", - "uuid", - "xz2", - "zstd", -] - -[[package]] -name = "datafusion" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba7cb113e9c0bedf9e9765926031e132fa05a1b09ba6e93a6d1a4d7044457b8" -dependencies = [ - "arrow 57.3.0", - "arrow-schema 57.3.0", - "async-trait", - "bytes", - "bzip2 0.6.1", - "chrono", - "datafusion-catalog 51.0.0", - "datafusion-catalog-listing 51.0.0", - "datafusion-common 51.0.0", - "datafusion-common-runtime 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-datasource-arrow", - "datafusion-datasource-csv 51.0.0", - "datafusion-datasource-json 51.0.0", - "datafusion-datasource-parquet 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-functions 51.0.0", - "datafusion-functions-aggregate 51.0.0", - "datafusion-functions-nested 51.0.0", - "datafusion-functions-table 51.0.0", - "datafusion-functions-window 51.0.0", - "datafusion-optimizer 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-adapter 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-optimizer 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-session 51.0.0", - "datafusion-sql 51.0.0", - "flate2", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "parking_lot", - "parquet 57.3.0", - "rand 0.9.2", - "regex", - "rstest", - "sqlparser 0.59.0", - "tempfile", - "tokio", - "url", - "uuid", - "xz2", - "zstd", -] - -[[package]] -name = "datafusion-catalog" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187622262ad8f7d16d3be9202b4c1e0116f1c9aa387e5074245538b755261621" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "dashmap", - "datafusion-common 50.3.0", - "datafusion-common-runtime 50.3.0", - "datafusion-datasource 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-session 50.3.0", - "datafusion-sql 50.3.0", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "parking_lot", - "tokio", -] - -[[package]] -name = "datafusion-catalog" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a3a799f914a59b1ea343906a0486f17061f39509af74e874a866428951130d" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "dashmap", - "datafusion-common 51.0.0", - "datafusion-common-runtime 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-session 51.0.0", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "parking_lot", - "tokio", -] - -[[package]] -name = "datafusion-catalog-listing" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9657314f0a32efd0382b9a46fdeb2d233273ece64baa68a7c45f5a192daf0f83" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "datafusion-catalog 50.3.0", - "datafusion-common 50.3.0", - "datafusion-datasource 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-session 50.3.0", - "futures", - "log", - "object_store", - "tokio", -] - -[[package]] -name = "datafusion-catalog-listing" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db1b113c80d7a0febcd901476a57aef378e717c54517a163ed51417d87621b0" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "datafusion-catalog 51.0.0", - "datafusion-common 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-adapter 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "tokio", -] - -[[package]] -name = "datafusion-common" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a83760d9a13122d025fbdb1d5d5aaf93dd9ada5e90ea229add92aa30898b2d1" -dependencies = [ - "ahash", - "arrow 56.2.0", - "arrow-ipc 56.2.0", - "base64", - "chrono", - "half", - "hashbrown 0.14.5", - "indexmap", - "libc", - "log", - "object_store", - "parquet 56.2.0", - "paste", - "recursive", - "sqlparser 0.58.0", - "tokio", - "web-time", -] - -[[package]] -name = "datafusion-common" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c10f7659e96127d25e8366be7c8be4109595d6a2c3eac70421f380a7006a1b0" -dependencies = [ - "ahash", - "arrow 57.3.0", - "arrow-ipc 57.3.0", - "chrono", - "half", - "hashbrown 0.14.5", - "indexmap", - "libc", - "log", - "object_store", - "parquet 57.3.0", - "paste", - "recursive", - "sqlparser 0.59.0", - "tokio", - "web-time", -] - -[[package]] -name = "datafusion-common-runtime" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b6234a6c7173fe5db1c6c35c01a12b2aa0f803a3007feee53483218817f8b1e" -dependencies = [ - "futures", - "log", - "tokio", -] - -[[package]] -name = "datafusion-common-runtime" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b92065bbc6532c6651e2f7dd30b55cba0c7a14f860c7e1d15f165c41a1868d95" -dependencies = [ - "futures", - "log", - "tokio", -] - -[[package]] -name = "datafusion-datasource" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7256c9cb27a78709dd42d0c80f0178494637209cac6e29d5c93edd09b6721b86" -dependencies = [ - "arrow 56.2.0", - "async-compression", - "async-trait", - "bytes", - "bzip2 0.6.1", - "chrono", - "datafusion-common 50.3.0", - "datafusion-common-runtime 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-adapter 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-session 50.3.0", - "flate2", - "futures", - "glob", - "itertools 0.14.0", - "log", - "object_store", - "parquet 56.2.0", - "rand 0.9.2", - "tempfile", - "tokio", - "tokio-util", - "url", - "xz2", - "zstd", -] - -[[package]] -name = "datafusion-datasource" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde13794244bc7581cd82f6fff217068ed79cdc344cafe4ab2c3a1c3510b38d6" -dependencies = [ - "arrow 57.3.0", - "async-compression", - "async-trait", - "bytes", - "bzip2 0.6.1", - "chrono", - "datafusion-common 51.0.0", - "datafusion-common-runtime 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-adapter 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-session 51.0.0", - "flate2", - "futures", - "glob", - "itertools 0.14.0", - "log", - "object_store", - "rand 0.9.2", - "tokio", - "tokio-util", - "url", - "xz2", - "zstd", -] - -[[package]] -name = "datafusion-datasource-arrow" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804fa9b4ecf3157982021770617200ef7c1b2979d57bec9044748314775a9aea" -dependencies = [ - "arrow 57.3.0", - "arrow-ipc 57.3.0", - "async-trait", - "bytes", - "datafusion-common 51.0.0", - "datafusion-common-runtime 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-session 51.0.0", - "futures", - "itertools 0.14.0", - "object_store", - "tokio", -] - -[[package]] -name = "datafusion-datasource-csv" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64533a90f78e1684bfb113d200b540f18f268134622d7c96bbebc91354d04825" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "bytes", - "datafusion-catalog 50.3.0", - "datafusion-common 50.3.0", - "datafusion-common-runtime 50.3.0", - "datafusion-datasource 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-session 50.3.0", - "futures", - "object_store", - "regex", - "tokio", -] - -[[package]] -name = "datafusion-datasource-csv" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a1641a40b259bab38131c5e6f48fac0717bedb7dc93690e604142a849e0568" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "bytes", - "datafusion-common 51.0.0", - "datafusion-common-runtime 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-session 51.0.0", - "futures", - "object_store", - "regex", - "tokio", -] - -[[package]] -name = "datafusion-datasource-json" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d7ebeb12c77df0aacad26f21b0d033aeede423a64b2b352f53048a75bf1d6e6" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "bytes", - "datafusion-catalog 50.3.0", - "datafusion-common 50.3.0", - "datafusion-common-runtime 50.3.0", - "datafusion-datasource 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-session 50.3.0", - "futures", - "object_store", - "serde_json", - "tokio", -] - -[[package]] -name = "datafusion-datasource-json" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adeacdb00c1d37271176f8fb6a1d8ce096baba16ea7a4b2671840c5c9c64fe85" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "bytes", - "datafusion-common 51.0.0", - "datafusion-common-runtime 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-session 51.0.0", - "futures", - "object_store", - "tokio", -] - -[[package]] -name = "datafusion-datasource-parquet" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e783c4c7d7faa1199af2df4761c68530634521b176a8d1331ddbc5a5c75133" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "bytes", - "datafusion-catalog 50.3.0", - "datafusion-common 50.3.0", - "datafusion-common-runtime 50.3.0", - "datafusion-datasource 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-functions-aggregate 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-adapter 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "datafusion-physical-optimizer 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-pruning 50.3.0", - "datafusion-session 50.3.0", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "parking_lot", - "parquet 56.2.0", - "rand 0.9.2", - "tokio", -] - -[[package]] -name = "datafusion-datasource-parquet" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d0b60ffd66f28bfb026565d62b0a6cbc416da09814766a3797bba7d85a3cd9" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "bytes", - "datafusion-common 51.0.0", - "datafusion-common-runtime 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-functions-aggregate-common 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-adapter 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-pruning 51.0.0", - "datafusion-session 51.0.0", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "parking_lot", - "parquet 57.3.0", - "tokio", -] - -[[package]] -name = "datafusion-doc" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ee6b1d9a80d13f9deb2291f45c07044b8e62fb540dbde2453a18be17a36429" - -[[package]] -name = "datafusion-doc" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b99e13947667b36ad713549237362afb054b2d8f8cc447751e23ec61202db07" - -[[package]] -name = "datafusion-execution" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4cec0a57653bec7b933fb248d3ffa3fa3ab3bd33bd140dc917f714ac036f531" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "dashmap", - "datafusion-common 50.3.0", - "datafusion-expr 50.3.0", - "futures", - "log", - "object_store", - "parking_lot", - "rand 0.9.2", - "tempfile", - "url", -] - -[[package]] -name = "datafusion-execution" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63695643190679037bc946ad46a263b62016931547bf119859c511f7ff2f5178" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "dashmap", - "datafusion-common 51.0.0", - "datafusion-expr 51.0.0", - "futures", - "log", - "object_store", - "parking_lot", - "rand 0.9.2", - "tempfile", - "url", -] - -[[package]] -name = "datafusion-expr" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef76910bdca909722586389156d0aa4da4020e1631994d50fadd8ad4b1aa05fe" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "chrono", - "datafusion-common 50.3.0", - "datafusion-doc 50.3.0", - "datafusion-expr-common 50.3.0", - "datafusion-functions-aggregate-common 50.3.0", - "datafusion-functions-window-common 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "indexmap", - "paste", - "recursive", - "serde_json", - "sqlparser 0.58.0", -] - -[[package]] -name = "datafusion-expr" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a4787cbf5feb1ab351f789063398f67654a6df75c4d37d7f637dc96f951a91" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "chrono", - "datafusion-common 51.0.0", - "datafusion-doc 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-functions-aggregate-common 51.0.0", - "datafusion-functions-window-common 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "indexmap", - "itertools 0.14.0", - "paste", - "recursive", - "serde_json", - "sqlparser 0.59.0", -] - -[[package]] -name = "datafusion-expr-common" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d155ccbda29591ca71a1344dd6bed26c65a4438072b400df9db59447f590bb6" -dependencies = [ - "arrow 56.2.0", - "datafusion-common 50.3.0", - "indexmap", - "itertools 0.14.0", - "paste", -] - -[[package]] -name = "datafusion-expr-common" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce2fb1b8c15c9ac45b0863c30b268c69dc9ee7a1ee13ecf5d067738338173dc" -dependencies = [ - "arrow 57.3.0", - "datafusion-common 51.0.0", - "indexmap", - "itertools 0.14.0", - "paste", -] - -[[package]] -name = "datafusion-functions" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de2782136bd6014670fd84fe3b0ca3b3e4106c96403c3ae05c0598577139977" -dependencies = [ - "arrow 56.2.0", - "arrow-buffer 56.2.0", - "base64", - "blake2", - "blake3", - "chrono", - "datafusion-common 50.3.0", - "datafusion-doc 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-expr-common 50.3.0", - "datafusion-macros 50.3.0", - "hex", - "itertools 0.14.0", - "log", - "md-5", - "rand 0.9.2", - "regex", - "sha2", - "unicode-segmentation", - "uuid", -] - -[[package]] -name = "datafusion-functions" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794a9db7f7b96b3346fc007ff25e994f09b8f0511b4cf7dff651fadfe3ebb28f" -dependencies = [ - "arrow 57.3.0", - "arrow-buffer 57.3.0", - "base64", - "blake2", - "blake3", - "chrono", - "datafusion-common 51.0.0", - "datafusion-doc 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-macros 51.0.0", - "hex", - "itertools 0.14.0", - "log", - "md-5", - "num-traits", - "rand 0.9.2", - "regex", - "sha2", - "unicode-segmentation", - "uuid", -] - -[[package]] -name = "datafusion-functions-aggregate" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07331fc13603a9da97b74fd8a273f4238222943dffdbbed1c4c6f862a30105bf" -dependencies = [ - "ahash", - "arrow 56.2.0", - "datafusion-common 50.3.0", - "datafusion-doc 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-functions-aggregate-common 50.3.0", - "datafusion-macros 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "half", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-aggregate" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c25210520a9dcf9c2b2cbbce31ebd4131ef5af7fc60ee92b266dc7d159cb305" -dependencies = [ - "ahash", - "arrow 57.3.0", - "datafusion-common 51.0.0", - "datafusion-doc 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-functions-aggregate-common 51.0.0", - "datafusion-macros 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "half", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-aggregate-common" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5951e572a8610b89968a09b5420515a121fbc305c0258651f318dc07c97ab17" -dependencies = [ - "ahash", - "arrow 56.2.0", - "datafusion-common 50.3.0", - "datafusion-expr-common 50.3.0", - "datafusion-physical-expr-common 50.3.0", -] - -[[package]] -name = "datafusion-functions-aggregate-common" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f4a66f3b87300bb70f4124b55434d2ae3fe80455f3574701d0348da040b55d" -dependencies = [ - "ahash", - "arrow 57.3.0", - "datafusion-common 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-physical-expr-common 51.0.0", -] - -[[package]] -name = "datafusion-functions-nested" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdacca9302c3d8fc03f3e94f338767e786a88a33f5ebad6ffc0e7b50364b9ea3" -dependencies = [ - "arrow 56.2.0", - "arrow-ord 56.2.0", - "datafusion-common 50.3.0", - "datafusion-doc 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-functions 50.3.0", - "datafusion-functions-aggregate 50.3.0", - "datafusion-functions-aggregate-common 50.3.0", - "datafusion-macros 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "itertools 0.14.0", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-nested" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae5c06eed03918dc7fe7a9f082a284050f0e9ecf95d72f57712d1496da03b8c4" -dependencies = [ - "arrow 57.3.0", - "arrow-ord 57.3.0", - "datafusion-common 51.0.0", - "datafusion-doc 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-functions 51.0.0", - "datafusion-functions-aggregate 51.0.0", - "datafusion-functions-aggregate-common 51.0.0", - "datafusion-macros 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "itertools 0.14.0", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-table" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37ff8a99434fbbad604a7e0669717c58c7c4f14c472d45067c4b016621d981" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "datafusion-catalog 50.3.0", - "datafusion-common 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-physical-plan 50.3.0", - "parking_lot", - "paste", -] - -[[package]] -name = "datafusion-functions-table" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4fed1d71738fbe22e2712d71396db04c25de4111f1ec252b8f4c6d3b25d7f5" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "datafusion-catalog 51.0.0", - "datafusion-common 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-plan 51.0.0", - "parking_lot", - "paste", -] - -[[package]] -name = "datafusion-functions-window" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e2aea7c79c926cffabb13dc27309d4eaeb130f4a21c8ba91cdd241c813652b" -dependencies = [ - "arrow 56.2.0", - "datafusion-common 50.3.0", - "datafusion-doc 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-functions-window-common 50.3.0", - "datafusion-macros 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-window" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d92206aa5ae21892f1552b4d61758a862a70956e6fd7a95cb85db1de74bc6d1" -dependencies = [ - "arrow 57.3.0", - "datafusion-common 51.0.0", - "datafusion-doc 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-functions-window-common 51.0.0", - "datafusion-macros 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-window-common" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fead257ab5fd2ffc3b40fda64da307e20de0040fe43d49197241d9de82a487f" -dependencies = [ - "datafusion-common 50.3.0", - "datafusion-physical-expr-common 50.3.0", -] - -[[package]] -name = "datafusion-functions-window-common" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53ae9bcc39800820d53a22d758b3b8726ff84a5a3e24cecef04ef4e5fdf1c7cc" -dependencies = [ - "datafusion-common 51.0.0", - "datafusion-physical-expr-common 51.0.0", -] - -[[package]] -name = "datafusion-macros" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec6f637bce95efac05cdfb9b6c19579ed4aa5f6b94d951cfa5bb054b7bb4f730" -dependencies = [ - "datafusion-expr 50.3.0", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "datafusion-macros" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1063ad4c9e094b3f798acee16d9a47bd7372d9699be2de21b05c3bd3f34ab848" -dependencies = [ - "datafusion-doc 51.0.0", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "datafusion-optimizer" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6583ef666ae000a613a837e69e456681a9faa96347bf3877661e9e89e141d8a" -dependencies = [ - "arrow 56.2.0", - "chrono", - "datafusion-common 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-expr-common 50.3.0", - "datafusion-physical-expr 50.3.0", - "indexmap", - "itertools 0.14.0", - "log", - "recursive", - "regex", - "regex-syntax", -] - -[[package]] -name = "datafusion-optimizer" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35f9ec5d08b87fd1893a30c2929f2559c2f9806ca072d8fefca5009dc0f06a" -dependencies = [ - "arrow 57.3.0", - "chrono", - "datafusion-common 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-physical-expr 51.0.0", - "indexmap", - "itertools 0.14.0", - "log", - "recursive", - "regex", - "regex-syntax", -] - -[[package]] -name = "datafusion-physical-expr" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8668103361a272cbbe3a61f72eca60c9b7c706e87cc3565bcf21e2b277b84f6" -dependencies = [ - "ahash", - "arrow 56.2.0", - "datafusion-common 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-expr-common 50.3.0", - "datafusion-functions-aggregate-common 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "half", - "hashbrown 0.14.5", - "indexmap", - "itertools 0.14.0", - "log", - "parking_lot", - "paste", - "petgraph 0.8.3", -] - -[[package]] -name = "datafusion-physical-expr" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c30cc8012e9eedcb48bbe112c6eff4ae5ed19cf3003cb0f505662e88b7014c5d" -dependencies = [ - "ahash", - "arrow 57.3.0", - "datafusion-common 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-functions-aggregate-common 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "half", - "hashbrown 0.14.5", - "indexmap", - "itertools 0.14.0", - "parking_lot", - "paste", - "petgraph 0.8.3", -] - -[[package]] -name = "datafusion-physical-expr-adapter" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "815acced725d30601b397e39958e0e55630e0a10d66ef7769c14ae6597298bb0" -dependencies = [ - "arrow 56.2.0", - "datafusion-common 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-functions 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "itertools 0.14.0", -] - -[[package]] -name = "datafusion-physical-expr-adapter" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9ff2dbd476221b1f67337699eff432781c4e6e1713d2aefdaa517dfbf79768" -dependencies = [ - "arrow 57.3.0", - "datafusion-common 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-functions 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "itertools 0.14.0", -] - -[[package]] -name = "datafusion-physical-expr-common" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6652fe7b5bf87e85ed175f571745305565da2c0b599d98e697bcbedc7baa47c3" -dependencies = [ - "ahash", - "arrow 56.2.0", - "datafusion-common 50.3.0", - "datafusion-expr-common 50.3.0", - "hashbrown 0.14.5", - "itertools 0.14.0", -] - -[[package]] -name = "datafusion-physical-expr-common" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90da43e1ec550b172f34c87ec68161986ced70fd05c8d2a2add66eef9c276f03" -dependencies = [ - "ahash", - "arrow 57.3.0", - "datafusion-common 51.0.0", - "datafusion-expr-common 51.0.0", - "hashbrown 0.14.5", - "itertools 0.14.0", -] - -[[package]] -name = "datafusion-physical-optimizer" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b7d623eb6162a3332b564a0907ba00895c505d101b99af78345f1acf929b5c" -dependencies = [ - "arrow 56.2.0", - "datafusion-common 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-expr-common 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-pruning 50.3.0", - "itertools 0.14.0", - "log", - "recursive", -] - -[[package]] -name = "datafusion-physical-optimizer" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce9804f799acd7daef3be7aaffe77c0033768ed8fdbf5fb82fc4c5f2e6bc14e6" -dependencies = [ - "arrow 57.3.0", - "datafusion-common 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-pruning 51.0.0", - "itertools 0.14.0", - "recursive", -] - -[[package]] -name = "datafusion-physical-plan" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2f7f778a1a838dec124efb96eae6144237d546945587557c9e6936b3414558c" -dependencies = [ - "ahash", - "arrow 56.2.0", - "arrow-ord 56.2.0", - "arrow-schema 56.2.0", - "async-trait", - "chrono", - "datafusion-common 50.3.0", - "datafusion-common-runtime 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-functions-aggregate-common 50.3.0", - "datafusion-functions-window-common 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "futures", - "half", - "hashbrown 0.14.5", - "indexmap", - "itertools 0.14.0", - "log", - "parking_lot", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "datafusion-physical-plan" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0acf0ad6b6924c6b1aa7d213b181e012e2d3ec0a64ff5b10ee6282ab0f8532ac" -dependencies = [ - "ahash", - "arrow 57.3.0", - "arrow-ord 57.3.0", - "arrow-schema 57.3.0", - "async-trait", - "chrono", - "datafusion-common 51.0.0", - "datafusion-common-runtime 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-functions-aggregate-common 51.0.0", - "datafusion-functions-window-common 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "futures", - "half", - "hashbrown 0.14.5", - "indexmap", - "itertools 0.14.0", - "log", - "parking_lot", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "datafusion-proto" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d368093a98a17d1449b1083ac22ed16b7128e4c67789991869480d8c4a40ecb9" -dependencies = [ - "arrow 57.3.0", - "chrono", - "datafusion-catalog 51.0.0", - "datafusion-catalog-listing 51.0.0", - "datafusion-common 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-datasource-arrow", - "datafusion-datasource-csv 51.0.0", - "datafusion-datasource-json 51.0.0", - "datafusion-datasource-parquet 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-functions-table 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "datafusion-proto-common", - "object_store", - "prost 0.14.3", -] - -[[package]] -name = "datafusion-proto-common" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6aef3d5e5c1d2bc3114c4876730cb76a9bdc5a8df31ef1b6db48f0c1671895" -dependencies = [ - "arrow 57.3.0", - "datafusion-common 51.0.0", - "prost 0.14.3", -] - -[[package]] -name = "datafusion-pruning" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1e59e2ca14fe3c30f141600b10ad8815e2856caa59ebbd0e3e07cd3d127a65" -dependencies = [ - "arrow 56.2.0", - "arrow-schema 56.2.0", - "datafusion-common 50.3.0", - "datafusion-datasource 50.3.0", - "datafusion-expr-common 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-expr-common 50.3.0", - "datafusion-physical-plan 50.3.0", - "itertools 0.14.0", - "log", -] - -[[package]] -name = "datafusion-pruning" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2c2498a1f134a9e11a9f5ed202a2a7d7e9774bd9249295593053ea3be999db" -dependencies = [ - "arrow 57.3.0", - "datafusion-common 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-expr-common 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-expr-common 51.0.0", - "datafusion-physical-plan 51.0.0", - "itertools 0.14.0", - "log", -] - -[[package]] -name = "datafusion-session" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ef8e2745583619bd7a49474e8f45fbe98ebb31a133f27802217125a7b3d58d" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "dashmap", - "datafusion-common 50.3.0", - "datafusion-common-runtime 50.3.0", - "datafusion-execution 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-plan 50.3.0", - "datafusion-sql 50.3.0", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "parking_lot", - "tokio", -] - -[[package]] -name = "datafusion-session" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f96eebd17555386f459037c65ab73aae8df09f464524c709d6a3134ad4f4776" -dependencies = [ - "async-trait", - "datafusion-common 51.0.0", - "datafusion-execution 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-plan 51.0.0", - "parking_lot", -] - -[[package]] -name = "datafusion-sql" -version = "50.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89abd9868770386fede29e5a4b14f49c0bf48d652c3b9d7a8a0332329b87d50b" -dependencies = [ - "arrow 56.2.0", - "bigdecimal", - "datafusion-common 50.3.0", - "datafusion-expr 50.3.0", - "indexmap", - "log", - "recursive", - "regex", - "sqlparser 0.58.0", -] - -[[package]] -name = "datafusion-sql" -version = "51.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc195fe60634b2c6ccfd131b487de46dc30eccae8a3c35a13f136e7f440414f" -dependencies = [ - "arrow 57.3.0", - "bigdecimal", - "chrono", - "datafusion-common 51.0.0", - "datafusion-expr 51.0.0", - "indexmap", - "log", - "recursive", - "regex", - "sqlparser 0.59.0", -] - -[[package]] -name = "deadpool" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" -dependencies = [ - "deadpool-runtime", - "lazy_static", - "num_cpus", - "tokio", -] - -[[package]] -name = "deadpool-runtime" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" - -[[package]] -name = "deepsize" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb987ec36f6bf7bfbea3f928b75590b736fc42af8e54d97592481351b2b96c" -dependencies = [ - "deepsize_derive", -] - -[[package]] -name = "deepsize_derive" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990101d41f3bc8c1a45641024377ee284ecc338e5ecf3ea0f0e236d897c72796" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "delta_kernel" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06f7fc164b1557731fcc68a198e813811a000efade0f112d4f0a002e65042b83" -dependencies = [ - "arrow 57.3.0", - "bytes", - "chrono", - "comfy-table", - "crc", - "delta_kernel_derive", - "futures", - "indexmap", - "itertools 0.14.0", - "object_store", - "parquet 57.3.0", - "reqwest", - "roaring 0.11.3", - "rustc_version", - "serde", - "serde_json", - "strum 0.27.2", - "thiserror 2.0.17", - "tokio", - "tracing", - "url", - "uuid", - "z85", -] - -[[package]] -name = "delta_kernel_derive" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86815a2c475835751ffa9b8d9ac8ed86cf86294304c42bedd1103d54f25ecbfe" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "deltalake" -version = "0.30.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5ace194fd6a5db14d4b4973c5780cf4569650716594ffd25297343be2e7cb0c" -dependencies = [ - "ctor", - "delta_kernel", - "deltalake-aws", - "deltalake-azure", - "deltalake-core", - "deltalake-gcp", -] - -[[package]] -name = "deltalake-aws" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60353287c8dc49bc21caa77c62e6eca4141bdcaf967365553dc62b518c7d2f1" -dependencies = [ - "async-trait", - "aws-config", - "aws-credential-types", - "aws-sdk-dynamodb", - "aws-sdk-sts", - "aws-smithy-runtime-api", - "backon", - "bytes", - "chrono", - "deltalake-core", - "futures", - "object_store", - "regex", - "thiserror 2.0.17", - "tokio", - "tracing", - "typed-builder", - "url", - "uuid", -] - -[[package]] -name = "deltalake-azure" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d28cb05f3254ddbcef665ee900f36bb6a34728d4ececb5f177cfdf2383f142" -dependencies = [ - "bytes", - "deltalake-core", - "object_store", - "thiserror 2.0.17", - "tokio", - "url", -] - -[[package]] -name = "deltalake-core" -version = "0.30.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b098d0ce09726f10a08b102c885a501ee18f06ea4aca864570508a9d5b620d1" -dependencies = [ - "arrow 57.3.0", - "arrow-arith 57.3.0", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-cast 57.3.0", - "arrow-ipc 57.3.0", - "arrow-json 57.3.0", - "arrow-ord 57.3.0", - "arrow-row 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "async-trait", - "bytes", - "cfg-if", - "chrono", - "dashmap", - "datafusion 51.0.0", - "datafusion-datasource 51.0.0", - "datafusion-proto", - "delta_kernel", - "deltalake-derive", - "dirs", - "either", - "futures", - "humantime", - "indexmap", - "itertools 0.14.0", - "num_cpus", - "object_store", - "parking_lot", - "parquet 57.3.0", - "percent-encoding", - "percent-encoding-rfc3986", - "pin-project-lite", - "rand 0.8.5", - "regex", - "serde", - "serde_json", - "sqlparser 0.59.0", - "strum 0.27.2", - "thiserror 2.0.17", - "tokio", - "tracing", - "url", - "uuid", - "validator", -] - -[[package]] -name = "deltalake-derive" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3963d9fe965af7b1dea433271389e1e39c6a97ffdbc2e81d808f5b329e4577b3" -dependencies = [ - "convert_case", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "deltalake-gcp" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fc0da3f4db3e508d180650b0f802d63d494aafc2cec0f5031e85ef4f93dd78e" -dependencies = [ - "async-trait", - "bytes", - "deltalake-core", - "futures", - "object_store", - "thiserror 2.0.17", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" -dependencies = [ - "powerfmt", - "serde_core", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.61.1", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "dlv-list" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" -dependencies = [ - "const-random", -] - -[[package]] -name = "downcast-rs" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" - -[[package]] -name = "dtor" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" -dependencies = [ - "dtor-proc-macro", -] - -[[package]] -name = "dtor-proc-macro" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "earcutr" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01" -dependencies = [ - "itertools 0.11.0", - "num-traits", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.1", -] - -[[package]] -name = "ethnum" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca81e6b4777c89fd810c25a4be2b1bd93ea034fbe58e6a75216a34c6b82c539b" - -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "fast-float2" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55" - -[[package]] -name = "fastdivide" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afc2bd4d5a73106dd53d10d73d3401c2f32730ba2c0b93ddb888a8983680471" - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "find-msvc-tools" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" - -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "flatbuffers" -version = "25.9.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b6620799e7340ebd9968d2e0708eb82cf1971e9a16821e2091b6d6e475eed5" -dependencies = [ - "bitflags", - "rustc_version", -] - -[[package]] -name = "flate2" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" -dependencies = [ - "crc32fast", - "libz-rs-sys", - "miniz_oxide", -] - -[[package]] -name = "float_next_after" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs4" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e180ac76c23b45e767bd7ae9579bc0bb458618c4bc71835926e098e61d15f8" -dependencies = [ - "rustix 0.38.44", - "windows-sys 0.52.0", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "fsst" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffdff7a2d68d22afc0657eddde3e946371ce7cfe730a3f78a5ed44ea5b1cb2e" -dependencies = [ - "arrow-array 56.2.0", - "rand 0.9.2", -] - -[[package]] -name = "fsst" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9e5c0b1c67a38cb92b41535d44623483beb9511592ae23a3bf42ddec758690" -dependencies = [ - "arrow-array 57.3.0", - "rand 0.9.2", -] - -[[package]] -name = "fst" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" -dependencies = [ - "utf8-ranges", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generator" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "geo" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc1a1678e54befc9b4bcab6cd43b8e7f834ae8ea121118b0fd8c42747675b4a" -dependencies = [ - "earcutr", - "float_next_after", - "geo-types", - "geographiclib-rs", - "i_overlay", - "log", - "num-traits", - "robust", - "rstar", - "spade", -] - -[[package]] -name = "geo-traits" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7c353d12a704ccfab1ba8bfb1a7fe6cb18b665bf89d37f4f7890edcd260206" -dependencies = [ - "geo-types", -] - -[[package]] -name = "geo-types" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f8647af4005fa11da47cd56252c6ef030be8fa97bdbf355e7dfb6348f0a82c" -dependencies = [ - "approx", - "num-traits", - "rayon", - "rstar", - "serde", -] - -[[package]] -name = "geoarrow-array" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1884b17253d8572e88833c282fcbb442365e4ae5f9052ced2831608253436c" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-schema 56.2.0", - "geo-traits", - "geoarrow-schema 0.6.2", - "num-traits", - "wkb", - "wkt", -] - -[[package]] -name = "geoarrow-array" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1cc4106ac0a0a512c398961ce95d8150475c84a84e17c4511c3643fa120a17" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-schema 57.3.0", - "geo-traits", - "geoarrow-schema 0.7.0", - "num-traits", - "wkb", - "wkt", -] - -[[package]] -name = "geoarrow-expr-geo" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67d3b543bc3ebeffdc204b67d69b8f9fcd33d76269ddd4a4618df99f053a934" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "geo", - "geo-traits", - "geoarrow-array 0.6.2", - "geoarrow-schema 0.6.2", -] - -[[package]] -name = "geoarrow-expr-geo" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa84300361ce57fb875bcaa6e32b95b0aff5c6b1af692b936bdd58ff343f4394" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "geo", - "geo-traits", - "geoarrow-array 0.7.0", - "geoarrow-schema 0.7.0", -] - -[[package]] -name = "geoarrow-schema" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f1b18b1c9a44ecd72be02e53d6e63bbccfdc8d1765206226af227327e2be6e" -dependencies = [ - "arrow-schema 56.2.0", - "geo-traits", - "serde", - "serde_json", - "thiserror 1.0.69", -] - -[[package]] -name = "geoarrow-schema" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97be4e9f523f92bd6a0e0458323f4b783d073d011664decd8dbf05651704f34" -dependencies = [ - "arrow-schema 57.3.0", - "geo-traits", - "serde", - "serde_json", - "thiserror 1.0.69", -] - -[[package]] -name = "geodatafusion" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d676b8d8b5f391ab4270ba31e9b599ee2c3d780405a38e272a0a7565ea189c" -dependencies = [ - "arrow-arith 56.2.0", - "arrow-array 56.2.0", - "arrow-schema 56.2.0", - "datafusion 50.3.0", - "geo", - "geo-traits", - "geoarrow-array 0.6.2", - "geoarrow-expr-geo 0.6.2", - "geoarrow-schema 0.6.2", - "geohash", - "thiserror 1.0.69", - "wkt", -] - -[[package]] -name = "geodatafusion" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773cfa1fb0d7f7661b76b3fde00f3ffd8e0ff7b3635096f0ff6294fe5ca62a2b" -dependencies = [ - "arrow-arith 57.3.0", - "arrow-array 57.3.0", - "arrow-schema 57.3.0", - "datafusion 51.0.0", - "geo", - "geo-traits", - "geoarrow-array 0.7.0", - "geoarrow-expr-geo 0.7.0", - "geoarrow-schema 0.7.0", - "geohash", - "thiserror 1.0.69", - "wkt", -] - -[[package]] -name = "geographiclib-rs" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f611040a2bb37eaa29a78a128d1e92a378a03e0b6e66ae27398d42b1ba9a7841" -dependencies = [ - "libm", -] - -[[package]] -name = "geohash" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fb94b1a65401d6cbf22958a9040aa364812c26674f841bee538b12c135db1e6" -dependencies = [ - "geo-types", - "libm", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi", - "wasi 0.14.7+wasi-0.2.4", - "wasm-bindgen", -] - -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "h2" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.3.1", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "num-traits", - "zerocopy", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - -[[package]] -name = "hashbrown" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "htmlescape" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.3.1", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http 1.3.1", - "http-body 1.0.1", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" - -[[package]] -name = "hyper" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "h2", - "http 1.3.1", - "http-body 1.0.1", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" -dependencies = [ - "http 1.3.1", - "hyper", - "hyper-util", - "rustls", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "system-configuration", - "tokio", - "tower-service", - "tracing", - "windows-registry", -] - -[[package]] -name = "hyperloglogplus" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "621debdf94dcac33e50475fdd76d34d5ea9c0362a834b9db08c3024696c1fbe3" -dependencies = [ - "serde", -] - -[[package]] -name = "i_float" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "010025c2c532c8d82e42d0b8bb5184afa449fa6f06c709ea9adcb16c49ae405b" -dependencies = [ - "libm", -] - -[[package]] -name = "i_key_sort" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9190f86706ca38ac8add223b2aed8b1330002b5cdbbce28fb58b10914d38fc27" - -[[package]] -name = "i_overlay" -version = "4.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcccbd4e4274e0f80697f5fbc6540fdac533cce02f2081b328e68629cce24f9" -dependencies = [ - "i_float", - "i_key_sort", - "i_shape", - "i_tree", - "rayon", -] - -[[package]] -name = "i_shape" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ea154b742f7d43dae2897fcd5ead86bc7b5eefcedd305a7ebf9f69d44d61082" -dependencies = [ - "i_float", -] - -[[package]] -name = "i_tree" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e6d558e6d4c7b82bc51d9c771e7a927862a161a7d87bf2b0541450e0e20915" - -[[package]] -name = "iana-time-zone" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core 0.62.1", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" - -[[package]] -name = "icu_properties" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "potential_utf", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" - -[[package]] -name = "icu_provider" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" -dependencies = [ - "displaydoc", - "icu_locale_core", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" -dependencies = [ - "equivalent", - "hashbrown 0.16.0", -] - -[[package]] -name = "indoc" -version = "2.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" -dependencies = [ - "rustversion", -] - -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "integer-encoding" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jiff" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" -dependencies = [ - "jiff-static", - "jiff-tzdb-platform", - "log", - "portable-atomic", - "portable-atomic-util", - "serde", - "windows-sys 0.59.0", -] - -[[package]] -name = "jiff-static" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "jiff-tzdb" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524" - -[[package]] -name = "jiff-tzdb-platform" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" -dependencies = [ - "jiff-tzdb", -] - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.3", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "jsonb" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a452366d21e8d3cbca680c41388e01d6a88739afef7877961946a6da409f9ccd" -dependencies = [ - "byteorder", - "ethnum", - "fast-float2", - "itoa", - "jiff", - "nom 8.0.0", - "num-traits", - "ordered-float 5.0.0", - "rand 0.9.2", - "ryu", - "serde", - "serde_json", -] - -[[package]] -name = "jsonwebtoken" -version = "9.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" -dependencies = [ - "base64", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "lance" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c439decbc304e180748e34bb6d3df729069a222e83e74e2185c38f107136e9" -dependencies = [ - "arrow 56.2.0", - "arrow-arith 56.2.0", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-ipc 56.2.0", - "arrow-ord 56.2.0", - "arrow-row 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "async-recursion", - "async-trait", - "async_cell", - "aws-credential-types", - "byteorder", - "bytes", - "chrono", - "dashmap", - "datafusion 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-functions 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-physical-plan 50.3.0", - "deepsize", - "either", - "futures", - "half", - "humantime", - "itertools 0.13.0", - "lance-arrow 1.0.1", - "lance-core 1.0.1", - "lance-datafusion 1.0.1", - "lance-encoding 1.0.1", - "lance-file 1.0.1", - "lance-geo 1.0.1", - "lance-index 1.0.1", - "lance-io 1.0.1", - "lance-linalg 1.0.1", - "lance-namespace 1.0.1", - "lance-table 1.0.1", - "log", - "moka", - "object_store", - "permutation", - "pin-project", - "prost 0.13.5", - "prost-types 0.13.5", - "rand 0.9.2", - "roaring 0.10.12", - "semver", - "serde", - "serde_json", - "snafu", - "tantivy", - "tokio", - "tokio-stream", - "tracing", - "url", - "uuid", -] - -[[package]] -name = "lance" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b7f07b905df393a5554eba19055c620f9ea25a3e40a013bda4bd8dc4ca66f01" -dependencies = [ - "arrow 57.3.0", - "arrow-arith 57.3.0", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-ipc 57.3.0", - "arrow-ord 57.3.0", - "arrow-row 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "async-recursion", - "async-trait", - "async_cell", - "aws-credential-types", - "byteorder", - "bytes", - "chrono", - "dashmap", - "datafusion 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-functions 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-physical-plan 51.0.0", - "deepsize", - "either", - "futures", - "half", - "humantime", - "itertools 0.13.0", - "lance-arrow 2.0.1", - "lance-core 2.0.1", - "lance-datafusion 2.0.1", - "lance-encoding 2.0.1", - "lance-file 2.0.1", - "lance-geo 2.0.1", - "lance-index 2.0.1", - "lance-io 2.0.1", - "lance-linalg 2.0.1", - "lance-namespace 2.0.1", - "lance-table 2.0.1", - "log", - "moka", - "object_store", - "permutation", - "pin-project", - "prost 0.14.3", - "prost-types 0.14.3", - "rand 0.9.2", - "roaring 0.10.12", - "semver", - "serde", - "serde_json", - "snafu", - "tantivy", - "tokio", - "tokio-stream", - "tracing", - "url", - "uuid", -] - -[[package]] -name = "lance-arrow" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ee5508b225456d3d56998eaeef0d8fbce5ea93856df47b12a94d2e74153210" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-cast 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "bytes", - "getrandom 0.2.16", - "half", - "jsonb", - "num-traits", - "rand 0.9.2", -] - -[[package]] -name = "lance-arrow" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "100e076cb81c8f0c24cd2881c706fc53e037c7d6e81eb320e929e265d157effb" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-cast 57.3.0", - "arrow-data 57.3.0", - "arrow-ord 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "bytes", - "getrandom 0.2.16", - "half", - "jsonb", - "num-traits", - "rand 0.9.2", -] - -[[package]] -name = "lance-bitpacking" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1c065fb3bd4a8cc4f78428443e990d4921aa08f707b676753db740e0b402a21" -dependencies = [ - "arrayref", - "paste", - "seq-macro", -] - -[[package]] -name = "lance-bitpacking" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588318d3d1ba0f97162fab39a323a0a49866bb35b32af42572c6b6a12296fa27" -dependencies = [ - "arrayref", - "paste", - "seq-macro", -] - -[[package]] -name = "lance-core" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8856abad92e624b75cd57a04703f6441948a239463bdf973f2ac1924b0bcdbe" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-schema 56.2.0", - "async-trait", - "byteorder", - "bytes", - "chrono", - "datafusion-common 50.3.0", - "datafusion-sql 50.3.0", - "deepsize", - "futures", - "lance-arrow 1.0.1", - "libc", - "log", - "mock_instant", - "moka", - "num_cpus", - "object_store", - "pin-project", - "prost 0.13.5", - "rand 0.9.2", - "roaring 0.10.12", - "serde_json", - "snafu", - "tempfile", - "tokio", - "tokio-stream", - "tokio-util", - "tracing", - "url", -] - -[[package]] -name = "lance-core" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa01d1cf490ccfd3b8eaeee2781415d0419e6be8366040e57e43677abf2644e" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-schema 57.3.0", - "async-trait", - "byteorder", - "bytes", - "chrono", - "datafusion-common 51.0.0", - "datafusion-sql 51.0.0", - "deepsize", - "futures", - "itertools 0.13.0", - "lance-arrow 2.0.1", - "libc", - "log", - "mock_instant", - "moka", - "num_cpus", - "object_store", - "pin-project", - "prost 0.14.3", - "rand 0.9.2", - "roaring 0.10.12", - "serde_json", - "snafu", - "tempfile", - "tokio", - "tokio-stream", - "tokio-util", - "tracing", - "url", -] - -[[package]] -name = "lance-datafusion" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8835308044cef5467d7751be87fcbefc2db01c22370726a8704bd62991693f" -dependencies = [ - "arrow 56.2.0", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-ord 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "async-trait", - "chrono", - "datafusion 50.3.0", - "datafusion-common 50.3.0", - "datafusion-functions 50.3.0", - "datafusion-physical-expr 50.3.0", - "futures", - "jsonb", - "lance-arrow 1.0.1", - "lance-core 1.0.1", - "lance-datagen 1.0.1", - "lance-geo 1.0.1", - "log", - "pin-project", - "prost 0.13.5", - "snafu", - "tokio", - "tracing", -] - -[[package]] -name = "lance-datafusion" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef89a39e3284eef76f79e63f23de8881a0583ad6feb20ed39f47eadd847a2b88" -dependencies = [ - "arrow 57.3.0", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-ord 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "async-trait", - "chrono", - "datafusion 51.0.0", - "datafusion-common 51.0.0", - "datafusion-functions 51.0.0", - "datafusion-physical-expr 51.0.0", - "futures", - "jsonb", - "lance-arrow 2.0.1", - "lance-core 2.0.1", - "lance-datagen 2.0.1", - "lance-geo 2.0.1", - "log", - "pin-project", - "prost 0.14.3", - "snafu", - "tokio", - "tracing", -] - -[[package]] -name = "lance-datagen" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612de1e888bb36f6bf51196a6eb9574587fdf256b1759a4c50e643e00d5f96d0" -dependencies = [ - "arrow 56.2.0", - "arrow-array 56.2.0", - "arrow-cast 56.2.0", - "arrow-schema 56.2.0", - "chrono", - "futures", - "half", - "hex", - "rand 0.9.2", - "rand_xoshiro", - "random_word", -] - -[[package]] -name = "lance-datagen" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2a60eef5c47e65d91e2ffa8e7e1629c52e7190c8b88a371a1a60601dc49371" -dependencies = [ - "arrow 57.3.0", - "arrow-array 57.3.0", - "arrow-cast 57.3.0", - "arrow-schema 57.3.0", - "chrono", - "futures", - "half", - "hex", - "rand 0.9.2", - "rand_distr 0.5.1", - "rand_xoshiro", - "random_word", -] - -[[package]] -name = "lance-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b456b29b135d3c7192602e516ccade38b5483986e121895fa43cf1fdb38bf60" -dependencies = [ - "arrow-arith 56.2.0", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-cast 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "bytemuck", - "byteorder", - "bytes", - "fsst 1.0.1", - "futures", - "hex", - "hyperloglogplus", - "itertools 0.13.0", - "lance-arrow 1.0.1", - "lance-bitpacking 1.0.1", - "lance-core 1.0.1", - "log", - "lz4", - "num-traits", - "prost 0.13.5", - "prost-build 0.13.5", - "prost-types 0.13.5", - "rand 0.9.2", - "snafu", - "strum 0.26.3", - "tokio", - "tracing", - "xxhash-rust", - "zstd", -] - -[[package]] -name = "lance-encoding" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce4a6631308aa681b2671af8f2a845ff781f8d4e755a2a7ccd012379467094" -dependencies = [ - "arrow-arith 57.3.0", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-cast 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "bytemuck", - "byteorder", - "bytes", - "fsst 2.0.1", - "futures", - "hex", - "hyperloglogplus", - "itertools 0.13.0", - "lance-arrow 2.0.1", - "lance-bitpacking 2.0.1", - "lance-core 2.0.1", - "log", - "lz4", - "num-traits", - "prost 0.14.3", - "prost-build 0.14.3", - "prost-types 0.14.3", - "rand 0.9.2", - "snafu", - "strum 0.26.3", - "tokio", - "tracing", - "xxhash-rust", - "zstd", -] - -[[package]] -name = "lance-file" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab1538d14d5bb3735b4222b3f5aff83cfa59cc6ef7cdd3dd9139e4c77193c80b" -dependencies = [ - "arrow-arith 56.2.0", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "async-recursion", - "async-trait", - "byteorder", - "bytes", - "datafusion-common 50.3.0", - "deepsize", - "futures", - "lance-arrow 1.0.1", - "lance-core 1.0.1", - "lance-encoding 1.0.1", - "lance-io 1.0.1", - "log", - "num-traits", - "object_store", - "prost 0.13.5", - "prost-build 0.13.5", - "prost-types 0.13.5", - "snafu", - "tokio", - "tracing", -] - -[[package]] -name = "lance-file" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d4d82357cbfaa1a18494226c15b1cb3c8ed0b6c84b91146323c82047ede419" -dependencies = [ - "arrow-arith 57.3.0", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "async-recursion", - "async-trait", - "byteorder", - "bytes", - "datafusion-common 51.0.0", - "deepsize", - "futures", - "lance-arrow 2.0.1", - "lance-core 2.0.1", - "lance-encoding 2.0.1", - "lance-io 2.0.1", - "log", - "num-traits", - "object_store", - "prost 0.14.3", - "prost-build 0.14.3", - "prost-types 0.14.3", - "snafu", - "tokio", - "tracing", -] - -[[package]] -name = "lance-geo" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5a69a2f3b55703d9c240ad7c5ffa2c755db69e9cf8aa05efe274a212910472d" -dependencies = [ - "datafusion 50.3.0", - "geo-types", - "geoarrow-array 0.6.2", - "geoarrow-schema 0.6.2", - "geodatafusion 0.1.1", -] - -[[package]] -name = "lance-geo" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7183fc870da62826f0f97df8007b634da053eb310157856efe1dc74f446951c" -dependencies = [ - "datafusion 51.0.0", - "geo-traits", - "geo-types", - "geoarrow-array 0.7.0", - "geoarrow-schema 0.7.0", - "geodatafusion 0.2.0", - "lance-core 2.0.1", - "serde", -] - -[[package]] -name = "lance-graph" -version = "0.5.3" -dependencies = [ - "arrow 57.3.0", - "arrow-array 57.3.0", - "arrow-schema 57.3.0", - "async-trait", - "datafusion 51.0.0", - "datafusion-common 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-functions-aggregate 51.0.0", - "datafusion-sql 51.0.0", - "deltalake", - "futures", - "lance 2.0.1", - "lance-arrow 2.0.1", - "lance-graph-catalog", - "lance-index 2.0.1", - "lance-linalg 2.0.1", - "lance-namespace 2.0.1", - "nom 7.1.3", - "serde", - "serde_json", - "snafu", - "tempfile", - "tokio", - "url", -] - -[[package]] -name = "lance-graph-benches" -version = "0.1.0" -dependencies = [ - "arrow-array 56.2.0", - "arrow-schema 56.2.0", - "criterion", - "futures", - "lance 1.0.1", - "lance-graph", - "tempfile", - "tokio", -] - -[[package]] -name = "lance-graph-catalog" -version = "0.5.3" -dependencies = [ - "arrow-schema 57.3.0", - "async-trait", - "datafusion 51.0.0", - "lance-namespace 2.0.1", - "reqwest", - "serde", - "serde_json", - "snafu", - "tokio", - "wiremock", -] - -[[package]] -name = "lance-graph-python" -version = "0.5.3" -dependencies = [ - "arrow 57.3.0", - "arrow-array 57.3.0", - "arrow-ipc 57.3.0", - "arrow-schema 57.3.0", - "datafusion 51.0.0", - "futures", - "lance-graph", - "pyo3", - "serde", - "serde_json", - "tokio", -] - -[[package]] -name = "lance-index" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea84613df6fa6b9168a1f056ba4f9cb73b90a1b452814c6fd4b3529bcdbfc78" -dependencies = [ - "arrow 56.2.0", - "arrow-arith 56.2.0", - "arrow-array 56.2.0", - "arrow-ord 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "async-channel", - "async-recursion", - "async-trait", - "bitpacking", - "bitvec", - "bytes", - "crossbeam-queue", - "datafusion 50.3.0", - "datafusion-common 50.3.0", - "datafusion-expr 50.3.0", - "datafusion-physical-expr 50.3.0", - "datafusion-sql 50.3.0", - "deepsize", - "dirs", - "fst", - "futures", - "half", - "itertools 0.13.0", - "jsonb", - "lance-arrow 1.0.1", - "lance-core 1.0.1", - "lance-datafusion 1.0.1", - "lance-datagen 1.0.1", - "lance-encoding 1.0.1", - "lance-file 1.0.1", - "lance-io 1.0.1", - "lance-linalg 1.0.1", - "lance-table 1.0.1", - "libm", - "log", - "ndarray", - "num-traits", - "object_store", - "prost 0.13.5", - "prost-build 0.13.5", - "prost-types 0.13.5", - "rand 0.9.2", - "rand_distr 0.5.1", - "rayon", - "roaring 0.10.12", - "serde", - "serde_json", - "snafu", - "tantivy", - "tempfile", - "tokio", - "tracing", - "twox-hash", - "uuid", -] - -[[package]] -name = "lance-index" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e9c5aa7024a63af9ae89ee8c0f23c8421b7896742e5cd4a271a60f9956cb80" -dependencies = [ - "arrow 57.3.0", - "arrow-arith 57.3.0", - "arrow-array 57.3.0", - "arrow-ord 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "async-channel", - "async-recursion", - "async-trait", - "bitpacking", - "bitvec", - "bytes", - "crossbeam-queue", - "datafusion 51.0.0", - "datafusion-common 51.0.0", - "datafusion-expr 51.0.0", - "datafusion-physical-expr 51.0.0", - "datafusion-sql 51.0.0", - "deepsize", - "dirs", - "fst", - "futures", - "geo-types", - "geoarrow-array 0.7.0", - "geoarrow-schema 0.7.0", - "half", - "itertools 0.13.0", - "jsonb", - "lance-arrow 2.0.1", - "lance-core 2.0.1", - "lance-datafusion 2.0.1", - "lance-datagen 2.0.1", - "lance-encoding 2.0.1", - "lance-file 2.0.1", - "lance-geo 2.0.1", - "lance-io 2.0.1", - "lance-linalg 2.0.1", - "lance-table 2.0.1", - "libm", - "log", - "ndarray", - "num-traits", - "object_store", - "prost 0.14.3", - "prost-build 0.14.3", - "prost-types 0.14.3", - "rand 0.9.2", - "rand_distr 0.5.1", - "rangemap", - "rayon", - "roaring 0.10.12", - "serde", - "serde_json", - "smallvec", - "snafu", - "tantivy", - "tempfile", - "tokio", - "tracing", - "twox-hash", - "uuid", -] - -[[package]] -name = "lance-io" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3fc4c1d941fceef40a0edbd664dbef108acfc5d559bb9e7f588d0c733cbc35" -dependencies = [ - "arrow 56.2.0", - "arrow-arith 56.2.0", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-cast 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "async-recursion", - "async-trait", - "aws-config", - "aws-credential-types", - "byteorder", - "bytes", - "chrono", - "deepsize", - "futures", - "lance-arrow 1.0.1", - "lance-core 1.0.1", - "lance-namespace 1.0.1", - "log", - "object_store", - "object_store_opendal", - "opendal", - "path_abs", - "pin-project", - "prost 0.13.5", - "rand 0.9.2", - "serde", - "shellexpand", - "snafu", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "lance-io" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d2af0b17fb374a8181bcf1a10bce5703ae3ee4373c1587ce4bba23e15e45c8" -dependencies = [ - "arrow 57.3.0", - "arrow-arith 57.3.0", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-cast 57.3.0", - "arrow-data 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "async-recursion", - "async-trait", - "aws-config", - "aws-credential-types", - "byteorder", - "bytes", - "chrono", - "deepsize", - "futures", - "lance-arrow 2.0.1", - "lance-core 2.0.1", - "lance-namespace 2.0.1", - "log", - "object_store", - "object_store_opendal", - "opendal", - "path_abs", - "pin-project", - "prost 0.14.3", - "rand 0.9.2", - "serde", - "shellexpand", - "snafu", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "lance-linalg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ffbc5ce367fbf700a69de3fe0612ee1a11191a64a632888610b6bacfa0f63" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-schema 56.2.0", - "cc", - "deepsize", - "half", - "lance-arrow 1.0.1", - "lance-core 1.0.1", - "num-traits", - "rand 0.9.2", -] - -[[package]] -name = "lance-linalg" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5125aa62696e75a7475807564b4921f252d8815be606b84bc00e6def0f5c24bb" -dependencies = [ - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-schema 57.3.0", - "cc", - "deepsize", - "half", - "lance-arrow 2.0.1", - "lance-core 2.0.1", - "num-traits", - "rand 0.9.2", -] - -[[package]] -name = "lance-namespace" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791bbcd868ee758123a34e07d320a1fb99379432b5ecc0e78d6b4686e999b629" -dependencies = [ - "arrow 56.2.0", - "async-trait", - "bytes", - "lance-core 1.0.1", - "lance-namespace-reqwest-client 0.0.18", - "snafu", -] - -[[package]] -name = "lance-namespace" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70545c2676ce954dfd801da5c6a631a70bba967826cd3a8f31b47d1f04bbfed3" -dependencies = [ - "arrow 57.3.0", - "async-trait", - "bytes", - "lance-core 2.0.1", - "lance-namespace-reqwest-client 0.4.5", - "snafu", -] - -[[package]] -name = "lance-namespace-reqwest-client" -version = "0.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea349999bcda4eea53fc05d334b3775ec314761e6a706555c777d7a29b18d19" -dependencies = [ - "reqwest", - "serde", - "serde_json", - "serde_repr", - "url", -] - -[[package]] -name = "lance-namespace-reqwest-client" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2acdba67f84190067532fce07b51a435dd390d7cdc1129a05003e5cb3274cf0" -dependencies = [ - "reqwest", - "serde", - "serde_json", - "serde_repr", - "url", -] - -[[package]] -name = "lance-table" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fdb2d56bfa4d1511c765fa0cc00fdaa37e5d2d1cd2f57b3c6355d9072177052" -dependencies = [ - "arrow 56.2.0", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-ipc 56.2.0", - "arrow-schema 56.2.0", - "async-trait", - "byteorder", - "bytes", - "chrono", - "deepsize", - "futures", - "lance-arrow 1.0.1", - "lance-core 1.0.1", - "lance-file 1.0.1", - "lance-io 1.0.1", - "log", - "object_store", - "prost 0.13.5", - "prost-build 0.13.5", - "prost-types 0.13.5", - "rand 0.9.2", - "rangemap", - "roaring 0.10.12", - "semver", - "serde", - "serde_json", - "snafu", - "tokio", - "tracing", - "url", - "uuid", -] - -[[package]] -name = "lance-table" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06ad37bd90045de8ef533df170c6098e6ff6ecb427aade47d7db8e2c86f2678" -dependencies = [ - "arrow 57.3.0", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-ipc 57.3.0", - "arrow-schema 57.3.0", - "async-trait", - "byteorder", - "bytes", - "chrono", - "deepsize", - "futures", - "lance-arrow 2.0.1", - "lance-core 2.0.1", - "lance-file 2.0.1", - "lance-io 2.0.1", - "log", - "object_store", - "prost 0.14.3", - "prost-build 0.14.3", - "prost-types 0.14.3", - "rand 0.9.2", - "rangemap", - "roaring 0.10.12", - "semver", - "serde", - "serde_json", - "snafu", - "tokio", - "tracing", - "url", - "uuid", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] - -[[package]] -name = "levenshtein_automata" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2cdeb66e45e9f36bfad5bbdb4d2384e70936afbee843c6f6543f0c551ebb25" - -[[package]] -name = "lexical-core" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8d125a277f807e55a77304455eb7b1cb52f2b18c143b60e766c120bd64a594" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a9f232fbd6f550bc0137dcb5f99ab674071ac2d690ac69704593cb4abbea56" -dependencies = [ - "lexical-parse-integer", - "lexical-util", -] - -[[package]] -name = "lexical-parse-integer" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a7a039f8fb9c19c996cd7b2fcce303c1b2874fe1aca544edc85c4a5f8489b34" -dependencies = [ - "lexical-util", -] - -[[package]] -name = "lexical-util" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2604dd126bb14f13fb5d1bd6a66155079cb9fa655b37f875b3a742c705dbed17" - -[[package]] -name = "lexical-write-float" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c438c87c013188d415fbabbb1dceb44249ab81664efbd31b14ae55dabb6361" -dependencies = [ - "lexical-util", - "lexical-write-integer", -] - -[[package]] -name = "lexical-write-integer" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "409851a618475d2d5796377cad353802345cba92c867d9fbcde9cf4eac4e14df" -dependencies = [ - "lexical-util", -] - -[[package]] -name = "libbz2-rs-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" - -[[package]] -name = "libc" -version = "0.2.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" - -[[package]] -name = "libloading" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" -dependencies = [ - "cfg-if", - "windows-targets 0.53.4", -] - -[[package]] -name = "libm" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" - -[[package]] -name = "libredox" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" -dependencies = [ - "bitflags", - "libc", -] - -[[package]] -name = "libz-rs-sys" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415" -dependencies = [ - "zlib-rs", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" - -[[package]] -name = "litemap" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" - -[[package]] -name = "lock_api" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" - -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "lru" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" -dependencies = [ - "hashbrown 0.15.5", -] - -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - -[[package]] -name = "lz4" -version = "1.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20b523e860d03443e98350ceaac5e71c6ba89aea7d960769ec3ce37f4de5af4" -dependencies = [ - "lz4-sys", -] - -[[package]] -name = "lz4-sys" -version = "1.11.1+lz4-1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "lz4_flex" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" -dependencies = [ - "twox-hash", -] - -[[package]] -name = "lz4_flex" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab6473172471198271ff72e9379150e9dfd70d8e533e0752a27e515b48dd375e" -dependencies = [ - "twox-hash", -] - -[[package]] -name = "lzma-sys" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "matrixmultiply" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" -dependencies = [ - "autocfg", - "num_cpus", - "once_cell", - "rawpointer", - "thread-tree", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest", -] - -[[package]] -name = "measure_time" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51c55d61e72fc3ab704396c5fa16f4c184db37978ae4e94ca8959693a235fc0e" -dependencies = [ - "log", -] - -[[package]] -name = "memchr" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" - -[[package]] -name = "memmap2" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" -dependencies = [ - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", -] - -[[package]] -name = "mock_instant" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce6dd36094cac388f119d2e9dc82dc730ef91c32a6222170d630e5414b956e6" - -[[package]] -name = "moka" -version = "0.12.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" -dependencies = [ - "async-lock", - "crossbeam-channel", - "crossbeam-epoch", - "crossbeam-utils", - "equivalent", - "event-listener", - "futures-util", - "parking_lot", - "portable-atomic", - "rustc_version", - "smallvec", - "tagptr", - "uuid", -] - -[[package]] -name = "multimap" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" - -[[package]] -name = "murmurhash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2195bf6aa996a481483b29d62a7663eed3fe39600c460e323f8ff41e90bdd89b" - -[[package]] -name = "native-tls" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe 0.2.1", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "ndarray" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" -dependencies = [ - "matrixmultiply", - "num-complex", - "num-integer", - "num-traits", - "portable-atomic", - "portable-atomic-util", - "rawpointer", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - -[[package]] -name = "nu-ansi-term" -version = "0.50.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.5", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "object_store" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c1be0c6c22ec0817cdc77d3842f721a17fd30ab6965001415b5402a74e6b740" -dependencies = [ - "async-trait", - "base64", - "bytes", - "chrono", - "form_urlencoded", - "futures", - "http 1.3.1", - "http-body-util", - "httparse", - "humantime", - "hyper", - "itertools 0.14.0", - "md-5", - "parking_lot", - "percent-encoding", - "quick-xml 0.38.3", - "rand 0.9.2", - "reqwest", - "ring", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "thiserror 2.0.17", - "tokio", - "tracing", - "url", - "walkdir", - "wasm-bindgen-futures", - "web-time", -] - -[[package]] -name = "object_store_opendal" -version = "0.55.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "113ab0769e972eee585e57407b98de08bda5354fa28e8ba4d89038d6cb6a8991" -dependencies = [ - "async-trait", - "bytes", - "chrono", - "futures", - "object_store", - "opendal", - "pin-project", - "tokio", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "oneshot" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce411919553d3f9fa53a0880544cda985a112117a0444d5ff1e870a893d6ea" - -[[package]] -name = "oorandom" -version = "11.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" - -[[package]] -name = "opendal" -version = "0.55.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d075ab8a203a6ab4bc1bce0a4b9fe486a72bf8b939037f4b78d95386384bc80a" -dependencies = [ - "anyhow", - "backon", - "base64", - "bytes", - "crc32c", - "futures", - "getrandom 0.2.16", - "http 1.3.1", - "http-body 1.0.1", - "jiff", - "log", - "md-5", - "percent-encoding", - "quick-xml 0.38.3", - "reqsign", - "reqwest", - "serde", - "serde_json", - "sha2", - "tokio", - "url", - "uuid", -] - -[[package]] -name = "openssl" -version = "0.10.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ordered-float" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ordered-multimap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" -dependencies = [ - "dlv-list", - "hashbrown 0.14.5", -] - -[[package]] -name = "outref" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" - -[[package]] -name = "ownedbytes" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fbd56f7631767e61784dc43f8580f403f4475bd4aaa4da003e6295e1bab4a7e" -dependencies = [ - "stable_deref_trait", -] - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "parquet" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dbd48ad52d7dccf8ea1b90a3ddbfaea4f69878dd7683e51c507d4bc52b5b27" -dependencies = [ - "ahash", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-cast 56.2.0", - "arrow-data 56.2.0", - "arrow-ipc 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "base64", - "brotli", - "bytes", - "chrono", - "flate2", - "futures", - "half", - "hashbrown 0.16.0", - "lz4_flex 0.11.5", - "num", - "num-bigint", - "object_store", - "paste", - "ring", - "seq-macro", - "simdutf8", - "snap", - "thrift", - "tokio", - "twox-hash", - "zstd", -] - -[[package]] -name = "parquet" -version = "57.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee96b29972a257b855ff2341b37e61af5f12d6af1158b6dcdb5b31ea07bb3cb" -dependencies = [ - "ahash", - "arrow-array 57.3.0", - "arrow-buffer 57.3.0", - "arrow-cast 57.3.0", - "arrow-data 57.3.0", - "arrow-ipc 57.3.0", - "arrow-schema 57.3.0", - "arrow-select 57.3.0", - "base64", - "brotli", - "bytes", - "chrono", - "flate2", - "futures", - "half", - "hashbrown 0.16.0", - "lz4_flex 0.12.0", - "num-bigint", - "num-integer", - "num-traits", - "object_store", - "paste", - "seq-macro", - "simdutf8", - "snap", - "thrift", - "tokio", - "twox-hash", - "zstd", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "path_abs" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ef02f6342ac01d8a93b65f96db53fe68a92a15f41144f97fb00a9e669633c3" -dependencies = [ - "serde", - "serde_derive", - "std_prelude", - "stfu8", -] - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest", - "hmac", -] - -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -dependencies = [ - "base64", - "serde", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "percent-encoding-rfc3986" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3637c05577168127568a64e9dc5a6887da720efef07b3d9472d45f63ab191166" - -[[package]] -name = "permutation" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df202b0b0f5b8e389955afd5f27b007b00fb948162953f1db9c70d2c7e3157d7" - -[[package]] -name = "petgraph" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "petgraph" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" -dependencies = [ - "fixedbitset", - "hashbrown 0.15.5", - "indexmap", - "serde", -] - -[[package]] -name = "phf" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_shared" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "aes", - "cbc", - "der", - "pbkdf2", - "scrypt", - "sha2", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "pkcs5", - "rand_core 0.6.4", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "portable-atomic" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" - -[[package]] -name = "portable-atomic-util" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" -dependencies = [ - "zerovec", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - -[[package]] -name = "proc-macro-crate" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "proc-macro2" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" -dependencies = [ - "bytes", - "prost-derive 0.13.5", -] - -[[package]] -name = "prost" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" -dependencies = [ - "bytes", - "prost-derive 0.14.3", -] - -[[package]] -name = "prost-build" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" -dependencies = [ - "heck", - "itertools 0.14.0", - "log", - "multimap", - "once_cell", - "petgraph 0.7.1", - "prettyplease", - "prost 0.13.5", - "prost-types 0.13.5", - "regex", - "syn 2.0.117", - "tempfile", -] - -[[package]] -name = "prost-build" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" -dependencies = [ - "heck", - "itertools 0.14.0", - "log", - "multimap", - "petgraph 0.8.3", - "prettyplease", - "prost 0.14.3", - "prost-types 0.14.3", - "regex", - "syn 2.0.117", - "tempfile", -] - -[[package]] -name = "prost-derive" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" -dependencies = [ - "anyhow", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "prost-derive" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" -dependencies = [ - "anyhow", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "prost-types" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" -dependencies = [ - "prost 0.13.5", -] - -[[package]] -name = "prost-types" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" -dependencies = [ - "prost 0.14.3", -] - -[[package]] -name = "psm" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" -dependencies = [ - "ar_archive_writer", - "cc", -] - -[[package]] -name = "pyo3" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383" -dependencies = [ - "indoc", - "libc", - "memoffset", - "once_cell", - "portable-atomic", - "pyo3-build-config", - "pyo3-ffi", - "pyo3-macros", - "unindent", -] - -[[package]] -name = "pyo3-build-config" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc6ddaf24947d12a9aa31ac65431fb1b851b8f4365426e182901eabfb87df5f" -dependencies = [ - "target-lexicon", -] - -[[package]] -name = "pyo3-ffi" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105" -dependencies = [ - "libc", - "pyo3-build-config", -] - -[[package]] -name = "pyo3-macros" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded" -dependencies = [ - "proc-macro2", - "pyo3-macros-backend", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "pyo3-macros-backend" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf" -dependencies = [ - "heck", - "proc-macro2", - "pyo3-build-config", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "quick-xml" -version = "0.37.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "quick-xml" -version = "0.38.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror 2.0.17", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" -dependencies = [ - "bytes", - "getrandom 0.3.3", - "lru-slab", - "rand 0.9.2", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.17", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.60.2", -] - -[[package]] -name = "quote" -version = "1.0.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", -] - -[[package]] -name = "rand_distr" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "rand_distr" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" -dependencies = [ - "num-traits", - "rand 0.9.2", -] - -[[package]] -name = "rand_xoshiro" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" -dependencies = [ - "rand_core 0.9.3", -] - -[[package]] -name = "random_word" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47a395bdb55442b883c89062d6bcff25dc90fa5f8369af81e0ac6d49d78cf81" -dependencies = [ - "ahash", - "brotli", - "paste", - "rand 0.9.2", - "unicase", -] - -[[package]] -name = "rangemap" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223" - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "recursive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0786a43debb760f491b1bc0269fe5e84155353c67482b9e60d0cfb596054b43e" -dependencies = [ - "recursive-proc-macro-impl", - "stacker", -] - -[[package]] -name = "recursive-proc-macro-impl" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b" -dependencies = [ - "quote", - "syn 2.0.117", -] - -[[package]] -name = "redox_syscall" -version = "0.5.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.16", - "libredox", - "thiserror 2.0.17", -] - -[[package]] -name = "regex" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-lite" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30" - -[[package]] -name = "regex-syntax" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" - -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - -[[package]] -name = "reqsign" -version = "0.16.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43451dbf3590a7590684c25fb8d12ecdcc90ed3ac123433e500447c7d77ed701" -dependencies = [ - "anyhow", - "async-trait", - "base64", - "chrono", - "form_urlencoded", - "getrandom 0.2.16", - "hex", - "hmac", - "home", - "http 1.3.1", - "jsonwebtoken", - "log", - "once_cell", - "percent-encoding", - "quick-xml 0.37.5", - "rand 0.8.5", - "reqwest", - "rsa", - "rust-ini", - "serde", - "serde_json", - "sha1", - "sha2", - "tokio", -] - -[[package]] -name = "reqwest" -version = "0.12.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "js-sys", - "log", - "mime", - "mime_guess", - "native-tls", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-native-certs", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tokio-util", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "webpki-roots", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.16", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "roaring" -version = "0.10.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e8d2cfa184d94d0726d650a9f4a1be7f9b76ac9fdb954219878dc00c1c1e7b" -dependencies = [ - "bytemuck", - "byteorder", -] - -[[package]] -name = "roaring" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba9ce64a8f45d7fc86358410bb1a82e8c987504c0d4900e9141d69a9f26c885" -dependencies = [ - "bytemuck", - "byteorder", -] - -[[package]] -name = "robust" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839" - -[[package]] -name = "rsa" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" -dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "sha2", - "signature", - "spki", - "subtle", - "zeroize", -] - -[[package]] -name = "rstar" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb" -dependencies = [ - "heapless", - "num-traits", - "smallvec", -] - -[[package]] -name = "rstest" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" -dependencies = [ - "futures-timer", - "futures-util", - "rstest_macros", -] - -[[package]] -name = "rstest_macros" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" -dependencies = [ - "cfg-if", - "glob", - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "relative-path", - "rustc_version", - "syn 2.0.117", - "unicode-ident", -] - -[[package]] -name = "rust-ini" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" -dependencies = [ - "cfg-if", - "ordered-multimap", -] - -[[package]] -name = "rust-stemmers" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46a2036019fdb888131db7a4c847a1063a7493f971ed94ea82c67eada63ca54" -dependencies = [ - "serde", - "serde_derive", -] - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys 0.11.0", - "windows-sys 0.61.1", -] - -[[package]] -name = "rustls" -version = "0.23.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" -dependencies = [ - "aws-lc-rs", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" -dependencies = [ - "openssl-probe 0.1.6", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.1", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scrypt" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" -dependencies = [ - "pbkdf2", - "salsa20", - "sha2", -] - -[[package]] -name = "security-framework" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" -dependencies = [ - "bitflags", - "core-foundation 0.10.1", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" - -[[package]] -name = "seq-macro" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "serde_json" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", - "serde_core", -] - -[[package]] -name = "serde_repr" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shellexpand" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" -dependencies = [ - "dirs", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest", - "rand_core 0.6.4", -] - -[[package]] -name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "simple_asn1" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror 2.0.17", - "time", -] - -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - -[[package]] -name = "sketches-ddsketch" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" -dependencies = [ - "serde", -] - -[[package]] -name = "slab" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "snafu" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" -dependencies = [ - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "snap" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" - -[[package]] -name = "socket2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "spade" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb313e1c8afee5b5647e00ee0fe6855e3d529eb863a0fdae1d60006c4d1e9990" -dependencies = [ - "hashbrown 0.15.5", - "num-traits", - "robust", - "smallvec", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "sqlparser" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec4b661c54b1e4b603b37873a18c59920e4c51ea8ea2cf527d925424dbd4437c" -dependencies = [ - "log", - "recursive", - "sqlparser_derive", -] - -[[package]] -name = "sqlparser" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4591acadbcf52f0af60eafbb2c003232b2b4cd8de5f0e9437cb8b1b59046cc0f" -dependencies = [ - "log", - "recursive", - "sqlparser_derive", -] - -[[package]] -name = "sqlparser_derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da5fc6819faabb412da764b99d3b713bb55083c11e7e0c00144d386cd6a1939c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "stacker" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1f8b29fb42aafcea4edeeb6b2f2d7ecd0d969c48b4cf0d2e64aafc471dd6e59" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.59.0", -] - -[[package]] -name = "std_prelude" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8207e78455ffdf55661170876f88daf85356e4edd54e0a3dbc79586ca1e50cbe" - -[[package]] -name = "stfu8" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51f1e89f093f99e7432c491c382b88a6860a5adbe6bf02574bf0a08efff1978" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros 0.26.4", -] - -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros 0.27.2", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.117", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags", - "core-foundation 0.9.4", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tagptr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" - -[[package]] -name = "tantivy" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a966cb0e76e311f09cf18507c9af192f15d34886ee43d7ba7c7e3803660c43" -dependencies = [ - "aho-corasick", - "arc-swap", - "base64", - "bitpacking", - "bon", - "byteorder", - "census", - "crc32fast", - "crossbeam-channel", - "downcast-rs", - "fastdivide", - "fnv", - "fs4", - "htmlescape", - "hyperloglogplus", - "itertools 0.14.0", - "levenshtein_automata", - "log", - "lru", - "lz4_flex 0.11.5", - "measure_time", - "memmap2", - "once_cell", - "oneshot", - "rayon", - "regex", - "rust-stemmers", - "rustc-hash", - "serde", - "serde_json", - "sketches-ddsketch", - "smallvec", - "tantivy-bitpacker", - "tantivy-columnar", - "tantivy-common", - "tantivy-fst", - "tantivy-query-grammar", - "tantivy-stacker", - "tantivy-tokenizer-api", - "tempfile", - "thiserror 2.0.17", - "time", - "uuid", - "winapi", -] - -[[package]] -name = "tantivy-bitpacker" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adc286a39e089ae9938935cd488d7d34f14502544a36607effd2239ff0e2494" -dependencies = [ - "bitpacking", -] - -[[package]] -name = "tantivy-columnar" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6300428e0c104c4f7db6f95b466a6f5c1b9aece094ec57cdd365337908dc7344" -dependencies = [ - "downcast-rs", - "fastdivide", - "itertools 0.14.0", - "serde", - "tantivy-bitpacker", - "tantivy-common", - "tantivy-sstable", - "tantivy-stacker", -] - -[[package]] -name = "tantivy-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b6ea6090ce03dc72c27d0619e77185d26cc3b20775966c346c6d4f7e99d7f" -dependencies = [ - "async-trait", - "byteorder", - "ownedbytes", - "serde", - "time", -] - -[[package]] -name = "tantivy-fst" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d60769b80ad7953d8a7b2c70cdfe722bbcdcac6bccc8ac934c40c034d866fc18" -dependencies = [ - "byteorder", - "regex-syntax", - "utf8-ranges", -] - -[[package]] -name = "tantivy-query-grammar" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e810cdeeebca57fc3f7bfec5f85fdbea9031b2ac9b990eb5ff49b371d52bbe6a" -dependencies = [ - "nom 7.1.3", - "serde", - "serde_json", -] - -[[package]] -name = "tantivy-sstable" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709f22c08a4c90e1b36711c1c6cad5ae21b20b093e535b69b18783dd2cb99416" -dependencies = [ - "futures-util", - "itertools 0.14.0", - "tantivy-bitpacker", - "tantivy-common", - "tantivy-fst", - "zstd", -] - -[[package]] -name = "tantivy-stacker" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bcdebb267671311d1e8891fd9d1301803fdb8ad21ba22e0a30d0cab49ba59c1" -dependencies = [ - "murmurhash32", - "rand_distr 0.4.3", - "tantivy-common", -] - -[[package]] -name = "tantivy-tokenizer-api" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa942fcee81e213e09715bbce8734ae2180070b97b33839a795ba1de201547d" -dependencies = [ - "serde", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "target-lexicon" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" - -[[package]] -name = "tempfile" -version = "3.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" -dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix 1.1.2", - "windows-sys 0.61.1", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" -dependencies = [ - "thiserror-impl 2.0.17", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "thread-tree" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbd370cb847953a25954d9f63e14824a36113f8c72eecf6eccef5dc4b45d630" -dependencies = [ - "crossbeam-channel", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "thrift" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e54bc85fc7faa8bc175c4bab5b92ba8d9a3ce893d0e9f42cc455c8ab16a9e09" -dependencies = [ - "byteorder", - "integer-encoding", - "ordered-float 2.10.1", -] - -[[package]] -name = "time" -version = "0.3.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" - -[[package]] -name = "time-macros" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinystr" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tinyvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.1", -] - -[[package]] -name = "tokio-macros" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_edit" -version = "0.23.10+spec-1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" -dependencies = [ - "indexmap", - "toml_datetime", - "toml_parser", - "winnow", -] - -[[package]] -name = "toml_parser" -version = "1.0.6+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" -dependencies = [ - "winnow", -] - -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" -dependencies = [ - "async-compression", - "bitflags", - "bytes", - "futures-core", - "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "iri-string", - "pin-project-lite", - "tokio", - "tokio-util", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "twox-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" -dependencies = [ - "rand 0.9.2", -] - -[[package]] -name = "typed-builder" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31aa81521b70f94402501d848ccc0ecaa8f93c8eb6999eb9747e72287757ffda" -dependencies = [ - "typed-builder-macro", -] - -[[package]] -name = "typed-builder-macro" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076a02dc54dd46795c2e9c8282ed40bcfb1e22747e955de9389a1de28190fb26" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - -[[package]] -name = "unicode-ident" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" - -[[package]] -name = "unindent" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - -[[package]] -name = "utf8-ranges" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" -dependencies = [ - "getrandom 0.3.3", - "js-sys", - "rand 0.9.2", - "serde", - "wasm-bindgen", -] - -[[package]] -name = "validator" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0b4a29d8709210980a09379f27ee31549b73292c87ab9899beee1c0d3be6303" -dependencies = [ - "idna", - "once_cell", - "regex", - "serde", - "serde_derive", - "serde_json", - "url", - "validator_derive", -] - -[[package]] -name = "validator_derive" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac855a2ce6f843beb229757e6e570a42e837bcb15e5f449dd48d5747d41bf77" -dependencies = [ - "darling 0.20.11", - "once_cell", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "vsimd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - -[[package]] -name = "wasip2" -version = "1.0.1+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.117", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasm-streams" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.1", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections", - "windows-core 0.61.2", - "windows-future", - "windows-link 0.1.3", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-core" -version = "0.62.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.2.0", - "windows-result 0.4.0", - "windows-strings 0.5.0", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading", -] - -[[package]] -name = "windows-implement" -version = "0.60.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-interface" -version = "0.59.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - -[[package]] -name = "windows-link" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" - -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] - -[[package]] -name = "windows-registry" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" -dependencies = [ - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-result" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" -dependencies = [ - "windows-link 0.2.0", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-strings" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" -dependencies = [ - "windows-link 0.2.0", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.4", -] - -[[package]] -name = "windows-sys" -version = "0.61.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" -dependencies = [ - "windows-link 0.2.0", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" -dependencies = [ - "windows-link 0.2.0", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "winnow" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" -dependencies = [ - "memchr", -] - -[[package]] -name = "wiremock" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08db1edfb05d9b3c1542e521aea074442088292f00b5f28e435c714a98f85031" -dependencies = [ - "assert-json-diff", - "base64", - "deadpool", - "futures", - "http 1.3.1", - "http-body-util", - "hyper", - "hyper-util", - "log", - "once_cell", - "regex", - "serde", - "serde_json", - "tokio", - "url", -] - -[[package]] -name = "wit-bindgen" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" - -[[package]] -name = "wkb" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a120b336c7ad17749026d50427c23d838ecb50cd64aaea6254b5030152f890a9" -dependencies = [ - "byteorder", - "geo-traits", - "num_enum", - "thiserror 1.0.69", -] - -[[package]] -name = "wkt" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb2b923ccc882312e559ffaa832a055ba9d1ac0cc8e86b3e25453247e4b81d7" -dependencies = [ - "geo-traits", - "geo-types", - "log", - "num-traits", - "thiserror 1.0.69", -] - -[[package]] -name = "writeable" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "xmlparser" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" - -[[package]] -name = "xxhash-rust" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" - -[[package]] -name = "xz2" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" -dependencies = [ - "lzma-sys", -] - -[[package]] -name = "yoke" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "z85" -version = "3.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e61e59a957b7ccee15d2049f86e8bfd6f66968fcd88f018950662d9b86e675" - -[[package]] -name = "zerocopy" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zerotrie" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zlib-rs" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" - -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/AdaWorldAPI-lance-graph-d9df43b/Cargo.toml b/AdaWorldAPI-lance-graph-d9df43b/Cargo.toml deleted file mode 100644 index c66043bd..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[workspace] -members = [ - "crates/lance-graph", - "crates/lance-graph-catalog", - "crates/lance-graph-python", - "crates/lance-graph-benches", -] -resolver = "2" diff --git a/AdaWorldAPI-lance-graph-d9df43b/LICENSE b/AdaWorldAPI-lance-graph-d9df43b/LICENSE deleted file mode 100644 index 261eeb9e..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/AdaWorldAPI-lance-graph-d9df43b/PR_DESCRIPTION.md b/AdaWorldAPI-lance-graph-d9df43b/PR_DESCRIPTION.md deleted file mode 100644 index 7e59e161..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/PR_DESCRIPTION.md +++ /dev/null @@ -1,431 +0,0 @@ -# feat: Arrow 57 / DataFusion 51 / Lance 2 + BlasGraph semiring algebra + SPO triple store - -## Summary - -This PR adds two new graph computation modules beneath the existing Cypher query engine: - -1. **BlasGraph** — A GraphBLAS-inspired sparse matrix algebra over 16,384-bit hyperdimensional vectors (3,173 lines, 81 unit tests) -2. **SPO triple store** — A Subject-Predicate-Object graph store using 512-bit fingerprint bitmaps, NARS truth values, and Merkle integrity stamping (1,443 lines + 355 lines integration tests, 38 unit + 7 integration tests) - -Both are accompanied by a dependency upgrade (arrow 56→57, datafusion 50→51, lance 1→2, deltalake 0.29→0.30, pyo3 0.25→0.26) and CI coverage for `lance-graph-python`. - -**29 files changed, 7,451 insertions, 877 deletions. 126 tests, all passing. Clippy clean across all crates.** - ---- - -## 1. Dependency Upgrades - -### Version matrix - -| Dependency | Before | After | Crates | -|---|---|---|---| -| arrow / arrow-array / arrow-schema | 56.2 | 57 | lance-graph, lance-graph-catalog, lance-graph-python | -| datafusion (+ common, expr, sql, functions-aggregate) | 50.3 | 51 | lance-graph, lance-graph-catalog, lance-graph-python | -| lance / lance-linalg / lance-namespace | 1.x | 2 | lance-graph | -| deltalake | 0.29 | 0.30 | lance-graph (optional, `delta` feature) | -| pyo3 | 0.25 | 0.26 | lance-graph-python | -| lance-arrow / lance-index | — | 2 | lance-graph (dev-dependencies) | - -### Why deltalake 0.29 → 0.30 - -`deltalake 0.29` depends on `datafusion 50.3`. With our bump to `datafusion 51`, the `delta` feature (enabled by default) would fail resolution. `deltalake 0.30` uses `datafusion ^51.0`, resolving the conflict. - -### Why pyo3 0.25 → 0.26 - -`arrow-pyarrow 57` bumped its pyo3 dependency from 0.25 to 0.26. Since both `arrow` (via pyarrow feature) and `lance-graph-python` (direct dep) pull in `pyo3-ffi`, and `pyo3-ffi` declares `links = "python"`, having two different pyo3-ffi versions in the same workspace causes a Cargo resolver conflict. Bumping to 0.26 ensures a single `pyo3-ffi` version. - -The pyarrow feature (`arrow = { version = "57", features = ["pyarrow"] }`) is preserved — zero-copy C Data Interface bridging between Python RecordBatches and Rust RecordBatches remains intact. - -### API adaptations - -**`sql_query.rs:175`** — DataFusion 51 schema accessor change: -```rust -// Before (datafusion 50.3): -let arrow_schema = Arc::new(arrow_schema::Schema::from(df.schema())); -// After (datafusion 51): -let arrow_schema = Arc::new(df.schema().as_arrow().clone()); -``` - -**`table_readers.rs:128`** — Suppress `unused_mut` warning when `delta` feature is disabled: -```rust -#[allow(unused_mut)] -let mut readers: Vec> = vec![Arc::new(ParquetTableReader)]; -#[cfg(feature = "delta")] -readers.push(Arc::new(DeltaTableReader)); -``` - -**`executor.rs`** — pyo3 0.26 renames (mechanical, no behaviour change): -- `Python::with_gil(|py| ...)` → `Python::attach(|py| ...)` -- `py.allow_threads(|| ...)` → `py.detach(|| ...)` - -**`graph.rs`** — pyo3 0.26 type alias deprecation (mechanical): -- `PyObject` → `Py` (10 occurrences) - ---- - -## 2. BlasGraph — GraphBLAS Semiring Algebra - -**Location:** `crates/lance-graph/src/graph/blasgraph/` -**8 files, 3,173 lines, 81 unit tests** - -### What is it - -A pure-Rust implementation of the [GraphBLAS](https://graphblas.org/) sparse matrix algebra interface, adapted for hyperdimensional computing (HDC). Instead of operating on scalars (f64, bool), all operations work on **16,384-bit binary vectors** (256 × u64 words). This enables algebraic graph algorithms where "vertex labels" and "edge weights" are high-dimensional representations that compose via XOR binding and bundle via majority vote. - -### Why - -Graph algorithms expressed as sparse linear algebra over semirings are composable, parallelisable, and can be accelerated on GPUs. By choosing the right semiring, the same `mxm` (matrix-matrix multiply) kernel computes BFS, shortest path, PageRank, or reachability — no algorithm-specific code needed. - -### Architecture - -``` -blasgraph/ -├── types.rs # BitVec (16384-bit), HdrScalar, operators (Unary/Binary/Monoid/Select) -├── semiring.rs # Semiring trait + 7 built-in semirings -├── sparse.rs # SparseVec, CooStorage, CsrStorage -├── matrix.rs # GrBMatrix — CSR-backed sparse matrix -├── vector.rs # GrBVector — sorted sparse vector -├── descriptor.rs # Descriptor — operation control (transpose, mask, replace) -├── ops.rs # Free-function API + graph algorithms (BFS, SSSP, PageRank) -└── mod.rs # Exports, GrBInfo status codes -``` - -### Type system (`types.rs`, 557 lines, 23 tests) - -The fundamental type is `BitVec` — a 16,384-bit binary vector stored as `[u64; 256]`: - -```rust -pub const VECTOR_WORDS: usize = 256; -pub const VECTOR_BITS: usize = VECTOR_WORDS * 64; // 16,384 - -pub struct BitVec { - words: [u64; VECTOR_WORDS], -} -``` - -**BitVec operations:** -- Bitwise: `xor()`, `and()`, `or()`, `not()` -- HDC: `bundle(vecs)` — majority vote across vectors (consensus); `permute(n)` — cyclic left-shift by n bits (role binding) -- Metrics: `popcount()`, `density()` (fraction of 1-bits), `hamming_distance(other)` -- Construction: `zero()`, `ones()`, `random(seed)` — uses `splitmix64` PRNG to prevent XOR collapse - -`HdrScalar` is the tagged value union used throughout matrix/vector operations: - -```rust -pub enum HdrScalar { - Vector(BitVec), // 16384-bit HD vector - Float(f32), // distances, similarities - Bool(bool), // reachability - Empty, // structural zero -} -``` - -Operator enums (`UnaryOp`, `BinaryOp`, `MonoidOp`, `SelectOp`) parameterise all operations, enabling the same kernel code to dispatch different algebraic behaviours at runtime. - -### 7 built-in semirings (`semiring.rs`, 476 lines, 8 tests) - -A semiring `(⊕, ⊗, 0)` defines how inner products accumulate. The `Semiring` trait: - -```rust -pub trait Semiring: Send + Sync { - fn multiply(&self, a: &HdrScalar, b: &HdrScalar) -> HdrScalar; // ⊗ - fn add(&self, a: &HdrScalar, b: &HdrScalar) -> HdrScalar; // ⊕ - fn zero(&self) -> HdrScalar; // identity for ⊕ - fn name(&self) -> &str; -} -``` - -| `HdrSemiring` variant | ⊗ Multiply | ⊕ Add | Use case | -|---|---|---|---| -| `XorBundle` | XOR | Bundle (majority vote) | Path composition — XOR binds edge to path, bundle accumulates multiple paths | -| `BindFirst` | XOR | First non-empty | BFS — propagate first-discovered path, ignore later arrivals | -| `HammingMin` | Hamming distance | Min | Shortest path — distance = Hamming between vectors, accumulate = min | -| `SimilarityMax` | 1 − hamming/16384 | Max | Best match — find most similar vector by cosine-like metric | -| `Resonance` | XOR | Best density (closest to 0.5) | Query expansion — keep most "balanced" (maximally entropic) vector | -| `Boolean` | AND | OR | Reachability — standard Boolean algebra | -| `XorField` | XOR | XOR | GF(2) algebra — finite field for linear independence checks | - -### Sparse storage (`sparse.rs`, 389 lines, 9 tests) - -Two formats, mirroring GraphBLAS: - -- **`CooStorage`** (coordinate/triplet) — `(row, col, value)` triples, used for incremental construction. `push(row, col, val)` appends; `to_csr()` converts for computation. -- **`CsrStorage`** (compressed sparse row) — `row_ptrs[nrows+1]` + `col_indices[nnz]` + `values[nnz]`. Efficient row iteration for `mxv`. `O(log nnz_per_row)` random access via binary search on `col_indices`. -- **`SparseVec`** — sorted `(index, BitVec)` pairs. `O(log n)` get, insert maintains sort invariant. - -### Matrix (`matrix.rs`, 561 lines, 11 tests) - -`GrBMatrix` wraps `CsrStorage`. Core operations: - -```rust -// Semiring-parameterised matrix multiply: C = A ⊕.⊗ B -pub fn mxm(&self, other: &GrBMatrix, semiring: &dyn Semiring, desc: &Descriptor) -> GrBMatrix; -pub fn mxv(&self, vec: &GrBVector, semiring: &dyn Semiring, desc: &Descriptor) -> GrBVector; -pub fn vxm(vec: &GrBVector, mat: &GrBMatrix, semiring: &dyn Semiring, desc: &Descriptor) -> GrBVector; - -// Element-wise (Hadamard-like) -pub fn ewise_add(&self, other: &GrBMatrix, op: BinaryOp, desc: &Descriptor) -> GrBMatrix; // union -pub fn ewise_mult(&self, other: &GrBMatrix, op: BinaryOp, desc: &Descriptor) -> GrBMatrix; // intersection - -// Reductions -pub fn reduce_rows(&self, monoid: MonoidOp) -> GrBVector; // each row → scalar -pub fn reduce_cols(&self, monoid: MonoidOp) -> GrBVector; // each col → scalar -pub fn reduce(&self, monoid: MonoidOp) -> HdrScalar; // entire matrix → scalar - -// Structural -pub fn extract(&self, rows: &[usize], cols: &[usize]) -> GrBMatrix; -pub fn apply(&self, op: UnaryOp) -> GrBMatrix; -pub fn transpose(&self) -> GrBMatrix; -``` - -The `Descriptor` controls transposition of inputs, mask complement, and output replacement — matching the GraphBLAS C API semantics. Pre-built descriptors in `GrBDesc`: `default()`, `t0()`, `t1()`, `t0t1()`, `comp()`, `replace()`, `structure()`. - -### Vector (`vector.rs`, 370 lines, 11 tests) - -`GrBVector` wraps `SparseVec`. In addition to the standard algebraic ops (`ewise_add`, `ewise_mult`, `apply`, `reduce`), provides nearest-neighbour search: - -```rust -pub fn find_nearest(&self, query: &BitVec, k: usize) -> Vec<(usize, u32)>; // k-NN by Hamming -pub fn find_within(&self, query: &BitVec, max_distance: u32) -> Vec<(usize, u32)>; // range search -pub fn find_most_similar(&self, query: &BitVec) -> Option<(usize, f32)>; // best match -``` - -### Graph algorithms (`ops.rs`, 478 lines, 14 tests) - -Three standard algorithms expressed as semiring iterations: - -**`hdr_bfs(adj, source, max_depth)`** — Breadth-first search using `BindFirst` semiring. Level-synchronous frontier expansion. Returns vector where `v[i]` = XOR-bound path representation from source to vertex i. Stops when no new vertices discovered. - -**`hdr_sssp(adj, source, max_iters)`** — Single-source shortest path using `HammingMin` semiring. Bellman-Ford-style relaxation. Returns vector where `v[i]` = minimum total Hamming distance from source to vertex i. Converges when no distances improve. - -**`hdr_pagerank(adj, max_iters, damping)`** — Importance ranking using `XorBundle` semiring. Each node's rank = bundle of neighbours' ranks. Initialises each vertex with `BitVec::random(seed)`, iterates `max_iters` times. - ---- - -## 3. SPO Triple Store - -**Location:** `crates/lance-graph/src/graph/spo/` + `crates/lance-graph/src/graph/fingerprint.rs` + `crates/lance-graph/src/graph/sparse.rs` -**Integration tests:** `crates/lance-graph/tests/spo_ground_truth.rs` -**8 files, 1,798 lines total, 38 unit + 7 integration tests** - -### What is it - -An in-memory Subject-Predicate-Object triple store that represents graph edges as fingerprint-packed bitmaps. Instead of exact key lookup, queries use approximate nearest-neighbour (ANN) search over Hamming distance — enabling fuzzy graph traversal where "find edges near this pattern" replaces "find edges matching this exact key." - -### Why - -The Cypher engine operates on property graphs via DataFusion (tabular). The SPO store provides a complementary path for direct graph operations: -- Fingerprint-based addressing avoids schema constraints -- ANN queries enable similarity-based graph exploration -- Truth values gate query results by confidence (relevant for knowledge graphs with uncertain edges) -- Semiring chain traversal composes multi-hop paths algebraically - -### Architecture - -``` -graph/ -├── fingerprint.rs # Fingerprint = [u64; 8] (512-bit), label_fp(), dn_hash(), hamming_distance() -├── sparse.rs # Bitmap = [u64; 8], pack_axes(), bitwise ops -├── spo/ -│ ├── truth.rs # TruthValue (frequency, confidence), TruthGate thresholds -│ ├── builder.rs # SpoBuilder — constructs SpoRecord from (s, p, o, truth) -│ ├── store.rs # SpoStore — HashMap with bitmap ANN queries -│ ├── semiring.rs # HammingMin semiring for chain traversal -│ └── merkle.rs # MerkleRoot, ClamPath, BindSpace — integrity verification -└── mod.rs # ContainerGeometry enum (Spo = 6) -``` - -### Fingerprints (`fingerprint.rs`, 144 lines, 6 tests) - -```rust -pub const FINGERPRINT_WORDS: usize = 8; // 512 bits total -pub type Fingerprint = [u64; FINGERPRINT_WORDS]; -``` - -- **`label_fp(label: &str) → Fingerprint`** — FNV-1a inspired hash across all 8 words. Includes an 11% density guard: if the resulting fingerprint has > 11% bits set, it's thinned via XOR-fold to prevent bitmap saturation when fingerprints are OR-packed. -- **`dn_hash(dn: &str) → u64`** — FNV-1a hash for keying records in `SpoStore`. Deterministic: same DN always yields same key. -- **`hamming_distance(a, b) → u32`** — XOR all words, popcount. Satisfies metric axioms (self-distance = 0, symmetry, triangle inequality). - -### Bitmap packing (`sparse.rs`, 128 lines, 6 tests) - -```rust -pub const BITMAP_WORDS: usize = 8; // matches FINGERPRINT_WORDS -pub type Bitmap = [u64; BITMAP_WORDS]; -``` - -The key function is `pack_axes(s, p, o) → Bitmap` which computes `s | p | o` — the OR of all three fingerprints. This creates a combined search vector where a query bitmap (e.g., `s | p` for forward queries) can be compared against stored bitmaps via Hamming distance. - -**Note:** `BITMAP_WORDS` was previously hardcoded as 2, which silently truncated fingerprints to 128 bits. Now matches `FINGERPRINT_WORDS = 8` for full 512-bit coverage. - -### Truth values (`truth.rs`, 175 lines, 6 tests) - -NARS-inspired two-valued truth representation: - -```rust -pub struct TruthValue { - pub frequency: f32, // how often the statement is true [0, 1] - pub confidence: f32, // how much evidence supports this [0, 1] -} -``` - -- **`expectation()`** = `confidence * (frequency − 0.5) + 0.5` — the decision-theoretic expected truth -- **`strength()`** = `frequency * confidence` — simple product -- **`revision(other)`** — combines independent evidence via weighted averaging (confidence-weighted) - -**`TruthGate`** — 5 preset thresholds for filtering query results: - -| Gate | Min expectation | Use | -|---|---|---| -| OPEN | 0.0 | Accept everything | -| WEAK | 0.4 | Loose filter | -| NORMAL | 0.6 | Default | -| STRONG | 0.75 | High confidence only | -| CERTAIN | 0.9 | Near-certain only | - -### Builder (`builder.rs`, 119 lines, 2 tests) - -```rust -pub struct SpoRecord { - pub subject: Fingerprint, - pub predicate: Fingerprint, - pub object: Fingerprint, - pub packed: Bitmap, // subject | predicate | object - pub truth: TruthValue, -} -``` - -`SpoBuilder` constructs records and query vectors: -- `build_edge(s, p, o, truth) → SpoRecord` — packs via `s | p | o` -- `build_forward_query(s, p) → Bitmap` — returns `s | p` (for SxP→O queries) -- `build_reverse_query(p, o) → Bitmap` — returns `p | o` (for PxO→S queries) -- `build_relation_query(s, o) → Bitmap` — returns `s | o` (for SxO→P queries) - -### Store (`store.rs`, 308 lines, 3 tests) - -```rust -pub struct SpoStore { - records: HashMap, -} -``` - -**2³ projection verbs** — the three canonical query patterns for a triple store: - -```rust -pub fn query_forward(&self, subject: &Fingerprint, predicate: &Fingerprint, radius: u32) -> Vec; -pub fn query_reverse(&self, predicate: &Fingerprint, object: &Fingerprint, radius: u32) -> Vec; -pub fn query_relation(&self, subject: &Fingerprint, object: &Fingerprint, radius: u32) -> Vec; -``` - -Each constructs the appropriate query bitmap, scans all records, and returns hits within `radius` Hamming distance. A post-filter ("Belichtung") verifies individual axis distances against the component fingerprints to reject false positives from the OR-packed bitmap. - -**Gated queries** add truth filtering: -```rust -pub fn query_forward_gated(&self, subject: &Fingerprint, predicate: &Fingerprint, radius: u32, gate: TruthGate) -> Vec; -``` - -**Chain traversal** using HammingMin semiring: -```rust -pub fn walk_chain_forward(&self, start_subject: &Fingerprint, radius: u32, max_hops: usize) -> Vec; -``` -Greedy walk: at each hop, find the nearest forward match, use its object as the next subject. Accumulates cumulative Hamming distance via `saturating_add`. Returns when no match found within radius or `max_hops` reached. - -### Semiring (`semiring.rs`, 99 lines, 4 tests) - -```rust -pub trait SpoSemiring { - type Cost: Copy + Ord + Default; - fn one(&self) -> Self::Cost; // identity for ⊗ extend - fn zero(&self) -> Self::Cost; // identity for ⊕ combine (= infinity) - fn combine(&self, a: Self::Cost, b: Self::Cost) -> Self::Cost; // ⊕ (min) - fn extend(&self, path: Self::Cost, hop: Self::Cost) -> Self::Cost; // ⊗ (saturating add) -} -``` - -`HammingMin` implements min-plus tropical semiring: ⊕ = min, ⊗ = saturating_add. This is the standard shortest-path semiring. - -`TraversalHop` records each hop: `{ target_key, distance, truth, cumulative_distance }`. - -### Merkle integrity (`merkle.rs`, 246 lines, 5 tests) - -```rust -pub struct MerkleRoot(u64); // XOR-fold hash of fingerprint -pub struct ClamPath { path: String, depth: u32 } // colon-separated DN path -pub struct BindSpace { nodes: Vec } // write-addressed node store -``` - -- `MerkleRoot::from_fingerprint(fp)` — XOR-folds all 8 fingerprint words into a single u64, then applies a secondary mix -- `BindSpace::write_dn_path(path, fp, depth)` — writes a node, stamps its MerkleRoot at write time, returns its address -- `BindSpace::verify_integrity(addr)` — re-computes hash from stored fingerprint, compares to stamped root - -**Documented gap:** `verify_lineage(addr)` performs structural checks only (non-zero root, non-zero fingerprint) — it does NOT re-hash. This is intentional for now and tested explicitly (test 6 validates that `verify_lineage` misses corruption while `verify_integrity` catches it). - -### Integration tests (`spo_ground_truth.rs`, 354 lines) - -7 end-to-end tests modelling a RedisGraph-style social graph: - -| # | Test | What it validates | -|---|---|---| -| 1 | `spo_hydration_round_trip` | Insert Jan-KNOWS-Ada → forward query finds Ada (distance < 50), reverse finds Jan | -| 2 | `projection_verbs_consistency` | SxP2O, SxO2P, PxO2S all find the same Jan-CREATES-Ada triple | -| 3 | `truth_gate_filters_low_confidence` | OPEN → 2 hits, STRONG → 1 hit (rejects low-confidence), CERTAIN → 0 hits | -| 4 | `belichtung_rejection_rate` | 100 random edges, tight radius → <10 hits (Belichtung post-filter works) | -| 5 | `semiring_walk_chain` | A→B→C→D chain, 3 hops, cumulative_distance non-decreasing | -| 6 | `clam_merkle_integrity` | verify_lineage misses corruption (documented gap), verify_integrity catches it | -| 7 | `cypher_vs_projection_convergence` | SPO projection path validated; Cypher convergence noted as future work | - ---- - -## 4. CI Changes - -**`style.yml`** — Added `Clippy lance-graph-python` step: -```yaml -- name: Clippy lance-graph-python - run: cargo clippy --manifest-path crates/lance-graph-python/Cargo.toml --all-targets -- -D warnings -``` - -**`build.yml`** — Added `Build lance-graph-python` step: -```yaml -- name: Build lance-graph-python - run: cargo check --manifest-path crates/lance-graph-python/Cargo.toml -``` - -Both crates now have CI coverage for compilation and lint. - ---- - -## Module dependency graph - -``` -lance-graph (lib) -├── cypher/ # existing Cypher query engine (unchanged) -├── sql_query.rs # DataFusion SQL execution (1 line changed: as_arrow()) -├── table_readers.rs # Table readers (1 line changed: allow(unused_mut)) -└── graph/ # NEW — graph primitives - ├── mod.rs # ContainerGeometry enum (Spo = 6) - ├── fingerprint.rs # Fingerprint = [u64; 8], label_fp, dn_hash, hamming_distance - ├── sparse.rs # Bitmap = [u64; 8], pack_axes, bitwise ops - ├── blasgraph/ # GraphBLAS semiring algebra over 16384-bit vectors - │ ├── types.rs # BitVec, HdrScalar, operator enums - │ ├── semiring.rs # 7 semirings (XorBundle, HammingMin, Boolean, ...) - │ ├── sparse.rs # CooStorage, CsrStorage, SparseVec - │ ├── matrix.rs # GrBMatrix (mxm, mxv, ewise_add, reduce, ...) - │ ├── vector.rs # GrBVector (k-NN, range search, ewise ops) - │ ├── descriptor.rs# Operation descriptors (transpose, mask, replace) - │ └── ops.rs # BFS, SSSP, PageRank - └── spo/ # SPO triple store with bitmap ANN - ├── truth.rs # TruthValue, TruthGate (NARS-inspired) - ├── builder.rs # SpoRecord, query vector construction - ├── store.rs # SpoStore (HashMap + bitmap scan + chain walk) - ├── semiring.rs # HammingMin (min-plus tropical) - └── merkle.rs # MerkleRoot, ClamPath, BindSpace -``` - -## Test plan - -- [x] `cargo test --manifest-path crates/lance-graph/Cargo.toml --lib` — 423 tests pass -- [x] `cargo test --manifest-path crates/lance-graph/Cargo.toml --test spo_ground_truth` — 7 integration tests pass -- [x] `cargo clippy --manifest-path crates/lance-graph/Cargo.toml --all-targets -- -D warnings` — clean -- [x] `cargo clippy --manifest-path crates/lance-graph-python/Cargo.toml --all-targets -- -D warnings` — clean -- [x] `cargo check --manifest-path crates/lance-graph-python/Cargo.toml` — compiles (pyarrow zero-copy intact) -- [x] `cargo fmt --manifest-path crates/lance-graph/Cargo.toml -- --check` — clean -- [ ] CI: build.yml, style.yml, rust-test.yml (needs CI run) diff --git a/AdaWorldAPI-lance-graph-d9df43b/README.md b/AdaWorldAPI-lance-graph-d9df43b/README.md deleted file mode 100644 index 7ed086b7..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/README.md +++ /dev/null @@ -1,243 +0,0 @@ -# Lance Graph - -Lance Graph is a Cypher-capable graph query engine built in Rust with Python bindings for building high-performance, scalable, and serverless multimodal knowledge graphs. - -This repository contains: - -- `crates/lance-graph` – the Cypher-capable query engine implemented in Rust -- `python/` – PyO3 bindings and Python packages: - - `lance_graph` – thin wrapper around the Rust query engine - - `knowledge_graph` – Lance-backed knowledge graph CLI, API, and utilities - -See `docs/project_structure.md` for the proposed workspace-based structure from -issue #92. - -## Prerequisites - -- Rust toolchain (1.82 or newer recommended) -- Python 3.11 -- [`uv`](https://docs.astral.sh/uv/) available on your `PATH` - -## Rust crate quick start - -```bash -cd crates/lance-graph -cargo check -cargo test -``` - -## Python package quick start - -```bash -cd python -uv venv --python 3.11 .venv # create the local virtualenv -source .venv/bin/activate # activate the virtual environment -uv pip install 'maturin[patchelf]' # install build tool -uv pip install -e '.[tests]' # editable install with test extras -maturin develop # build and install the Rust extension -pytest python/tests/ -v # run the test suite -``` - -> If another virtual environment is already active, run `deactivate` (or -> `unset VIRTUAL_ENV`) before the `uv run` command so uv binds to `.venv`. - -## Python example: Cypher query - -```python -import pyarrow as pa -from lance_graph import CypherQuery, GraphConfig - -people = pa.table({ - "person_id": [1, 2, 3, 4], - "name": ["Alice", "Bob", "Carol", "David"], - "age": [28, 34, 29, 42], -}) - -config = ( - GraphConfig.builder() - .with_node_label("Person", "person_id") - .build() -) - -query = ( - CypherQuery("MATCH (p:Person) WHERE p.age > 30 RETURN p.name AS name, p.age AS age") - .with_config(config) -) -result = query.execute({"Person": people}) -print(result.to_pydict()) # {'name': ['Bob', 'David'], 'age': [34, 42]} -``` - -## Python example: Direct SQL query - -For data analytics workflows where you prefer standard SQL, use `SqlQuery` or `SqlEngine`. No `GraphConfig` is needed: - -```python -import pyarrow as pa -from lance_graph import SqlQuery, SqlEngine - -person = pa.table({ - "id": [1, 2, 3], - "name": ["Alice", "Bob", "Carol"], - "age": [28, 34, 29], -}) - -# One-off query -result = SqlQuery( - "SELECT name, age FROM person WHERE age > 30" -).execute({"person": person}) -print(result.to_pydict()) # {'name': ['Bob'], 'age': [34]} - -# Multi-query with cached context -engine = SqlEngine({"person": person}) -r1 = engine.execute("SELECT COUNT(*) AS cnt FROM person") -r2 = engine.execute("SELECT name FROM person ORDER BY age DESC LIMIT 2") -``` - -## Python example: Unity Catalog integration - -Connect to [Unity Catalog](https://github.com/unitycatalog/unitycatalog) (OSS) to discover and query Delta Lake or Parquet tables directly: - -```python -from lance_graph import UnityCatalog - -# Connect to Unity Catalog -uc = UnityCatalog("http://localhost:8080/api/2.1/unity-catalog") - -# Browse catalog metadata -catalogs = uc.list_catalogs() -schemas = uc.list_schemas("unity") -tables = uc.list_tables("unity", "default") -table = uc.get_table("unity", "default", "marksheet") -print(table.columns()) # [{"name": "id", "type_name": "INT", ...}, ...] - -# Auto-register tables (Delta + Parquet) and query via SQL -engine = uc.create_sql_engine("unity", "default") -result = engine.execute("SELECT * FROM marksheet WHERE mark > 80") -print(result.to_pandas()) - -# For cloud storage (S3, Azure, GCS), pass storage options: -uc = UnityCatalog( - "http://localhost:8080/api/2.1/unity-catalog", - storage_options={ - "aws_access_key_id": "...", - "aws_secret_access_key": "...", - "aws_region": "us-east-1", - } -) -``` - -## Knowledge Graph CLI & API - -The `knowledge_graph` package layers a simple Lance-backed knowledge graph -service on top of the `lance_graph` engine. It provides: - -- A CLI (`knowledge_graph.main`) for initializing storage, running Cypher - queries, and bootstrapping data via heuristic text extraction. -- A reusable FastAPI component, plus a standalone web service - (`knowledge_graph.webservice`) that exposes query and dataset endpoints. -- Storage helpers that persist node and relationship tables as Lance datasets. - -### CLI usage - -```bash -uv run knowledge_graph --init # initialize storage and schema stub -uv run knowledge_graph --list-datasets # list Lance datasets on disk -uv run knowledge_graph --extract-preview notes.txt -uv run knowledge_graph --extract-preview "Alice joined the graph team" -uv run knowledge_graph --extract-and-add notes.txt -uv run knowledge_graph "MATCH (n) RETURN n LIMIT 5" -uv run knowledge_graph --log-level DEBUG --extract-preview "Inline text" -uv run knowledge_graph --ask "Who is working on the Presto project?" - - -# Configure LLM extraction (default) -uv sync --extra llm # install optional LLM dependencies -uv sync --extra lance-storage # install Lance dataset support -export OPENAI_API_KEY=sk-... -uv run knowledge_graph --llm-model gpt-4o-mini --extract-preview notes.txt - -# Supply additional OpenAI client options via YAML (base_url, headers, etc.) -uv run knowledge_graph --llm-config llm_config.yaml --extract-and-add notes.txt - -# Fall back to the heuristic extractor when LLM access is unavailable -uv run knowledge_graph --extractor heuristic --extract-preview notes.txt - -``` - -The default extractor uses OpenAI. Configure credentials via environment -variables supported by the SDK (for example `OPENAI_API_BASE` or -`OPENAI_API_KEY`), or place them in a YAML file passed through `--llm-config`. -Override the model and temperature with `--llm-model` and `--llm-temperature`. -``` - -By default the CLI writes datasets under `./knowledge_graph_data`. Provide -`--root` and `--schema` to point at alternate storage locations and schema YAML. - -### FastAPI service - -Run the web service after installing the `knowledge_graph` package (and -dependencies such as FastAPI): - -```bash -uv run --package knowledge_graph knowledge_graph-webservice -``` - -The service exposes endpoints under `/graph`, including `/graph/health`, -`/graph/query`, `/graph/datasets`, and `/graph/schema`. - -### Development workflow - -For linting and type checks: - -```bash -# Install dev dependencies and run linters -uv pip install -e '.[dev]' -ruff format python/ # format code -ruff check python/ # lint code -pyright # type check - -# Or run individual tests -pytest python/tests/test_graph.py::test_basic_node_selection -v -``` - -The Python README (`python/README.md`) contains additional details if you are -working solely on the bindings. - -## Benchmarks - -- Requirements: - - protoc: install `protobuf-compiler` (Debian/Ubuntu: `sudo apt-get install -y protobuf-compiler`). - - Optional: gnuplot for Criterion's gnuplot backend; otherwise the plotters backend is used. - -- Run (from `crates/lance-graph`): - -```bash -cargo bench --bench graph_execution - -# Quicker local run (shorter warm-up/measurement): -cargo bench --bench graph_execution -- --warm-up-time 1 --measurement-time 2 --sample-size 10 -``` - -- Reports: - - Global index: `crates/lance-graph/target/criterion/report/index.html` - - Group index: `crates/lance-graph/target/criterion/cypher_execution/report/index.html` - -- Typical results (x86_64, quick run: warm-up 1s, measurement 2s, sample size 10): - -| Benchmark | Size | Median time | Approx. throughput | -|--------------------------|-----------|-------------|--------------------| -| basic_node_filter | 100 | ~680 µs | ~147 Kelem/s | -| basic_node_filter | 10,000 | ~715 µs | ~13.98 Melem/s | -| basic_node_filter | 1,000,000 | ~743 µs | ~1.35 Gelem/s | -| single_hop_expand | 100 | ~2.79 ms | ~35.9 Kelem/s | -| single_hop_expand | 10,000 | ~3.77 ms | ~2.65 Melem/s | -| single_hop_expand | 1,000,000 | ~3.70 ms | ~270 Melem/s | -| two_hop_expand | 100 | ~4.52 ms | ~22.1 Kelem/s | -| two_hop_expand | 10,000 | ~6.41 ms | ~1.56 Melem/s | -| two_hop_expand | 1,000,000 | ~6.16 ms | ~162 Melem/s | - -Numbers are illustrative; your hardware, compiler, and runtime load will affect results. - -## External Wiki - -For additional documentation, architecture, and examples, see the DeepWiki page: [DeepWiki — lance-graph](https://deepwiki.com/lancedb/lance-graph) diff --git a/AdaWorldAPI-lance-graph-d9df43b/ci/bump_version.py b/AdaWorldAPI-lance-graph-d9df43b/ci/bump_version.py deleted file mode 100644 index b3625ff8..00000000 --- a/AdaWorldAPI-lance-graph-d9df43b/ci/bump_version.py +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env python3 -""" -Version management script for lance-graph project. -Uses bump-my-version to handle version bumping across all project components. - -Versioning scheme: - - Stable releases: X.Y.Z (e.g., 0.1.0, 1.0.0) - - Pre-releases: X.Y.Z-