Skip to main content

amari_gpu/
adaptive.rs

1//! Adaptive Verification Framework for Cross-Platform GPU Operations
2//!
3//! This module implements platform detection and adaptive verification
4//! strategies that automatically adjust verification approaches based on
5//! the execution environment and performance constraints.
6
7use crate::{verification::*, GpuCliffordAlgebra};
8use std::time::{Duration, Instant};
9use thiserror::Error;
10
11#[derive(Error, Debug)]
12pub enum AdaptiveVerificationError {
13    #[error("Platform detection failed: {0}")]
14    PlatformDetection(String),
15
16    #[error("GPU verification failed: {0}")]
17    GpuVerification(#[from] GpuVerificationError),
18
19    #[error("No suitable verification strategy available")]
20    NoSuitableStrategy,
21
22    #[error("Performance constraint violation: {constraint}")]
23    PerformanceConstraint { constraint: String },
24}
25
26/// Platform-specific execution environment
27#[derive(Debug, Clone, PartialEq)]
28pub enum VerificationPlatform {
29    /// Native CPU with full phantom type support
30    NativeCpu { features: CpuFeatures },
31    /// GPU with boundary verification constraints
32    Gpu {
33        backend: GpuBackend,
34        memory_mb: u64,
35        compute_units: u32,
36    },
37    /// WebAssembly with runtime verification
38    Wasm { env: WasmEnvironment },
39}
40
41#[derive(Debug, Clone, PartialEq)]
42pub struct CpuFeatures {
43    pub supports_simd: bool,
44    pub core_count: usize,
45    pub cache_size_kb: u64,
46}
47
48#[derive(Debug, Clone, PartialEq)]
49pub enum GpuBackend {
50    Vulkan,
51    Metal,
52    Dx12,
53    OpenGL,
54    WebGpu,
55}
56
57#[derive(Debug, Clone, PartialEq)]
58pub enum WasmEnvironment {
59    Browser { engine: String },
60    NodeJs { version: String },
61    Standalone,
62}
63
64/// Verification level that adapts to platform constraints
65#[derive(Debug, Clone, PartialEq)]
66pub enum AdaptiveVerificationLevel {
67    /// Maximum verification (CPU only)
68    Maximum,
69    /// High verification with performance awareness
70    High,
71    /// Balanced verification for production workloads
72    Balanced,
73    /// Minimal verification for performance-critical paths
74    Minimal,
75    /// Debug-only verification
76    Debug,
77}
78
79/// Adaptive verifier that selects optimal strategy per platform
80pub struct AdaptiveVerifier {
81    platform: VerificationPlatform,
82    verification_level: AdaptiveVerificationLevel,
83    performance_budget: Duration,
84    boundary_verifier: Option<GpuBoundaryVerifier>,
85    gpu_instance: Option<GpuCliffordAlgebra>,
86}
87
88impl AdaptiveVerifier {
89    /// Create adaptive verifier with automatic platform detection
90    pub async fn new() -> Result<Self, AdaptiveVerificationError> {
91        let platform = Self::detect_platform().await?;
92        let verification_level = Self::determine_verification_level(&platform);
93        let performance_budget = Self::determine_performance_budget(&platform);
94
95        let (boundary_verifier, gpu_instance) = match &platform {
96            VerificationPlatform::Gpu { .. } => {
97                let config = Self::create_gpu_verification_config(&platform, &verification_level);
98                let verifier = GpuBoundaryVerifier::new(config);
99                let gpu = GpuCliffordAlgebra::new::<3, 0, 0>().await.ok();
100                (Some(verifier), gpu)
101            }
102            _ => (None, None),
103        };
104
105        Ok(Self {
106            platform,
107            verification_level,
108            performance_budget,
109            boundary_verifier,
110            gpu_instance,
111        })
112    }
113
114    /// Create adaptive verifier with explicit configuration
115    pub async fn with_config(
116        level: AdaptiveVerificationLevel,
117        budget: Duration,
118    ) -> Result<Self, AdaptiveVerificationError> {
119        let platform = Self::detect_platform().await?;
120
121        let (boundary_verifier, gpu_instance) = match &platform {
122            VerificationPlatform::Gpu { .. } => {
123                let config = Self::create_gpu_verification_config(&platform, &level);
124                let verifier = GpuBoundaryVerifier::new(config);
125                let gpu = GpuCliffordAlgebra::new::<3, 0, 0>().await.ok();
126                (Some(verifier), gpu)
127            }
128            _ => (None, None),
129        };
130
131        Ok(Self {
132            platform,
133            verification_level: level,
134            performance_budget: budget,
135            boundary_verifier,
136            gpu_instance,
137        })
138    }
139
140    /// Perform verified operation with platform-appropriate strategy
141    pub async fn verified_geometric_product<const P: usize, const Q: usize, const R: usize>(
142        &mut self,
143        a: &VerifiedMultivector<P, Q, R>,
144        b: &VerifiedMultivector<P, Q, R>,
145    ) -> Result<VerifiedMultivector<P, Q, R>, AdaptiveVerificationError> {
146        let start_time = Instant::now();
147
148        let result = match &self.platform {
149            VerificationPlatform::NativeCpu { .. } => {
150                // Full phantom type verification available
151                self.cpu_verification(a, b).await?
152            }
153            VerificationPlatform::Gpu { .. } => {
154                // Single operations typically use CPU for efficiency
155                self.cpu_verification(a, b).await?
156            }
157            VerificationPlatform::Wasm { .. } => {
158                // Runtime contract verification
159                self.wasm_runtime_verification(a, b).await?
160            }
161        };
162
163        let elapsed = start_time.elapsed();
164        if elapsed > self.performance_budget {
165            return Err(AdaptiveVerificationError::PerformanceConstraint {
166                constraint: format!(
167                    "Operation exceeded budget: {:?} > {:?}",
168                    elapsed, self.performance_budget
169                ),
170            });
171        }
172
173        Ok(result)
174    }
175
176    /// Perform verified batch operation with optimal GPU/CPU dispatch
177    pub async fn verified_batch_geometric_product<
178        const P: usize,
179        const Q: usize,
180        const R: usize,
181    >(
182        &mut self,
183        a_batch: &[VerifiedMultivector<P, Q, R>],
184        b_batch: &[VerifiedMultivector<P, Q, R>],
185    ) -> Result<Vec<VerifiedMultivector<P, Q, R>>, AdaptiveVerificationError> {
186        if a_batch.len() != b_batch.len() {
187            return Err(AdaptiveVerificationError::NoSuitableStrategy);
188        }
189        if a_batch.is_empty() {
190            return Ok(Vec::new());
191        }
192
193        match &self.platform {
194            VerificationPlatform::NativeCpu { .. } => {
195                // CPU batch processing with full verification
196                self.cpu_batch_verification(a_batch, b_batch).await
197            }
198            VerificationPlatform::Gpu { .. } => {
199                // GPU boundary verification strategy
200                self.gpu_batch_verification(a_batch, b_batch).await
201            }
202            VerificationPlatform::Wasm { .. } => {
203                // WASM runtime verification with progressive enhancement
204                self.wasm_batch_verification(a_batch, b_batch).await
205            }
206        }
207    }
208
209    /// Get platform information
210    pub fn platform(&self) -> &VerificationPlatform {
211        &self.platform
212    }
213
214    /// Get current verification level
215    pub fn verification_level(&self) -> &AdaptiveVerificationLevel {
216        &self.verification_level
217    }
218
219    /// Get performance budget
220    pub fn performance_budget(&self) -> Duration {
221        self.performance_budget
222    }
223
224    /// Check if GPU acceleration should be used for given batch size
225    pub fn should_use_gpu(&self, batch_size: usize) -> bool {
226        match &self.platform {
227            VerificationPlatform::Gpu {
228                compute_units,
229                memory_mb,
230                ..
231            } => {
232                // Heuristic based on GPU capabilities and batch size
233                let min_batch_size = match &self.verification_level {
234                    AdaptiveVerificationLevel::Maximum => 500,
235                    AdaptiveVerificationLevel::High => 200,
236                    AdaptiveVerificationLevel::Balanced => 100,
237                    AdaptiveVerificationLevel::Minimal => 50,
238                    AdaptiveVerificationLevel::Debug => 1000, // Prefer CPU for debugging
239                };
240
241                // Scale threshold by GPU capabilities
242                let capability_factor = (*compute_units as f64 / 16.0).clamp(0.5, 4.0);
243                let memory_factor = (*memory_mb as f64 / 1024.0).clamp(0.5, 2.0);
244                let adjusted_threshold =
245                    (min_batch_size as f64 / (capability_factor * memory_factor)) as usize;
246
247                batch_size >= adjusted_threshold
248            }
249            _ => false,
250        }
251    }
252
253    /// Update verification level dynamically
254    pub fn set_verification_level(&mut self, level: AdaptiveVerificationLevel) {
255        // Update GPU verifier config if present
256        if let Some(ref mut verifier) = self.boundary_verifier {
257            let new_config = Self::create_gpu_verification_config(&self.platform, &level);
258            *verifier = GpuBoundaryVerifier::new(new_config);
259        }
260
261        self.verification_level = level;
262    }
263
264    // Private implementation methods
265
266    /// Detect current execution platform
267    async fn detect_platform() -> Result<VerificationPlatform, AdaptiveVerificationError> {
268        if std::env::var_os("AMARI_GPU_FORCE_CPU").is_some() {
269            let features = Self::detect_cpu_features();
270            return Ok(VerificationPlatform::NativeCpu { features });
271        }
272
273        // Try GPU detection with comprehensive error handling
274        let gpu_platform = {
275            // Use std::panic::catch_unwind to handle GPU driver panics
276            let panic_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
277                // Use pollster to handle the async call safely
278                pollster::block_on(async {
279                    // Try full GPU initialization including capabilities detection
280                    if GpuCliffordAlgebra::new::<3, 0, 0>().await.is_ok() {
281                        let backend = Self::detect_gpu_backend();
282                        let (memory_mb, compute_units) = Self::estimate_gpu_capabilities().await;
283                        Some(VerificationPlatform::Gpu {
284                            backend,
285                            memory_mb,
286                            compute_units,
287                        })
288                    } else {
289                        None
290                    }
291                })
292            }));
293
294            // GPU initialization panicked or failed - gracefully fall back to CPU
295            panic_result.unwrap_or(None)
296        };
297
298        if let Some(platform) = gpu_platform {
299            return Ok(platform);
300        }
301
302        // Check for WASM environment
303        if cfg!(target_arch = "wasm32") {
304            let env = Self::detect_wasm_environment();
305            return Ok(VerificationPlatform::Wasm { env });
306        }
307
308        // Default to native CPU
309        let features = Self::detect_cpu_features();
310        Ok(VerificationPlatform::NativeCpu { features })
311    }
312
313    /// Detect GPU backend type
314    fn detect_gpu_backend() -> GpuBackend {
315        // Platform-specific detection logic
316        if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
317            GpuBackend::Metal
318        } else if cfg!(target_os = "windows") {
319            GpuBackend::Dx12
320        } else if cfg!(target_arch = "wasm32") {
321            GpuBackend::WebGpu
322        } else {
323            GpuBackend::Vulkan
324        }
325    }
326
327    /// Estimate GPU capabilities
328    async fn estimate_gpu_capabilities() -> (u64, u32) {
329        // Conservative estimates for broad compatibility
330        // In production, these would query actual GPU capabilities
331        (1024, 16) // 1GB memory, 16 compute units
332    }
333
334    /// Detect WASM execution environment
335    fn detect_wasm_environment() -> WasmEnvironment {
336        // Simplified detection - in practice would check JavaScript globals
337        WasmEnvironment::Browser {
338            engine: "Unknown".to_string(),
339        }
340    }
341
342    /// Detect CPU features
343    fn detect_cpu_features() -> CpuFeatures {
344        CpuFeatures {
345            supports_simd: true, // Assume SIMD support
346            core_count: std::thread::available_parallelism()
347                .map(|n| n.get())
348                .unwrap_or(4),
349            cache_size_kb: 8192, // 8MB L3 cache estimate
350        }
351    }
352
353    /// Determine optimal verification level for platform
354    fn determine_verification_level(platform: &VerificationPlatform) -> AdaptiveVerificationLevel {
355        match platform {
356            VerificationPlatform::NativeCpu { features } => {
357                if features.core_count >= 8 {
358                    AdaptiveVerificationLevel::High
359                } else {
360                    AdaptiveVerificationLevel::Balanced
361                }
362            }
363            VerificationPlatform::Gpu { compute_units, .. } => {
364                if *compute_units >= 32 {
365                    AdaptiveVerificationLevel::Balanced
366                } else {
367                    AdaptiveVerificationLevel::Minimal
368                }
369            }
370            VerificationPlatform::Wasm { .. } => {
371                // WASM has limited debugging capabilities
372                AdaptiveVerificationLevel::Minimal
373            }
374        }
375    }
376
377    /// Determine performance budget for platform
378    fn determine_performance_budget(platform: &VerificationPlatform) -> Duration {
379        match platform {
380            VerificationPlatform::NativeCpu { .. } => Duration::from_millis(50),
381            VerificationPlatform::Gpu { .. } => Duration::from_millis(20),
382            VerificationPlatform::Wasm { .. } => Duration::from_millis(100),
383        }
384    }
385
386    /// Create GPU verification configuration
387    fn create_gpu_verification_config(
388        platform: &VerificationPlatform,
389        level: &AdaptiveVerificationLevel,
390    ) -> VerificationConfig {
391        let strategy = match level {
392            AdaptiveVerificationLevel::Maximum => VerificationStrategy::Strict,
393            AdaptiveVerificationLevel::High => {
394                VerificationStrategy::Statistical { sample_rate: 0.2 }
395            }
396            AdaptiveVerificationLevel::Balanced => {
397                VerificationStrategy::Statistical { sample_rate: 0.1 }
398            }
399            AdaptiveVerificationLevel::Minimal => VerificationStrategy::Boundary,
400            AdaptiveVerificationLevel::Debug => VerificationStrategy::Strict,
401        };
402
403        let budget = Self::determine_performance_budget(platform);
404
405        VerificationConfig {
406            strategy,
407            performance_budget: budget,
408            tolerance: 1e-12,
409            enable_invariant_checking: !matches!(level, AdaptiveVerificationLevel::Minimal),
410        }
411    }
412
413    /// CPU verification implementation
414    async fn cpu_verification<const P: usize, const Q: usize, const R: usize>(
415        &self,
416        a: &VerifiedMultivector<P, Q, R>,
417        b: &VerifiedMultivector<P, Q, R>,
418    ) -> Result<VerifiedMultivector<P, Q, R>, AdaptiveVerificationError> {
419        // Full verification with phantom types
420        let result = a.inner().geometric_product(b.inner());
421        let verified_result = VerifiedMultivector::new(result);
422
423        // Verify mathematical properties based on level
424        match self.verification_level {
425            AdaptiveVerificationLevel::Maximum | AdaptiveVerificationLevel::Debug => {
426                verified_result.verify_invariants()?;
427                // Additional checks for maximum verification
428                self.verify_geometric_product_properties(a, b, &verified_result)?;
429            }
430            AdaptiveVerificationLevel::High => {
431                verified_result.verify_invariants()?;
432            }
433            _ => {
434                // Minimal verification
435            }
436        }
437
438        Ok(verified_result)
439    }
440
441    /// CPU batch verification implementation
442    async fn cpu_batch_verification<const P: usize, const Q: usize, const R: usize>(
443        &self,
444        a_batch: &[VerifiedMultivector<P, Q, R>],
445        b_batch: &[VerifiedMultivector<P, Q, R>],
446    ) -> Result<Vec<VerifiedMultivector<P, Q, R>>, AdaptiveVerificationError> {
447        let mut results = Vec::with_capacity(a_batch.len());
448
449        for (a, b) in a_batch.iter().zip(b_batch.iter()) {
450            let result = self.cpu_verification(a, b).await?;
451            results.push(result);
452        }
453
454        Ok(results)
455    }
456
457    /// GPU batch verification implementation
458    async fn gpu_batch_verification<const P: usize, const Q: usize, const R: usize>(
459        &mut self,
460        a_batch: &[VerifiedMultivector<P, Q, R>],
461        b_batch: &[VerifiedMultivector<P, Q, R>],
462    ) -> Result<Vec<VerifiedMultivector<P, Q, R>>, AdaptiveVerificationError> {
463        if !self.should_use_gpu(a_batch.len()) {
464            return self.cpu_batch_verification(a_batch, b_batch).await;
465        }
466
467        if let (Some(ref mut verifier), Some(ref gpu)) =
468            (&mut self.boundary_verifier, &self.gpu_instance)
469        {
470            verifier
471                .verified_batch_geometric_product(gpu, a_batch, b_batch)
472                .await
473                .map_err(AdaptiveVerificationError::GpuVerification)
474        } else {
475            // Fallback to CPU
476            self.cpu_batch_verification(a_batch, b_batch).await
477        }
478    }
479
480    /// WASM runtime verification implementation
481    async fn wasm_runtime_verification<const P: usize, const Q: usize, const R: usize>(
482        &self,
483        a: &VerifiedMultivector<P, Q, R>,
484        b: &VerifiedMultivector<P, Q, R>,
485    ) -> Result<VerifiedMultivector<P, Q, R>, AdaptiveVerificationError> {
486        // Runtime signature verification
487        if VerifiedMultivector::<P, Q, R>::signature() != (P, Q, R) {
488            return Err(AdaptiveVerificationError::GpuVerification(
489                GpuVerificationError::SignatureMismatch {
490                    expected: (P, Q, R),
491                    actual: VerifiedMultivector::<P, Q, R>::signature(),
492                },
493            ));
494        }
495
496        // Perform operation with runtime checking
497        let result = a.inner().geometric_product(b.inner());
498        let verified_result = VerifiedMultivector::new(result);
499
500        // Basic runtime validation
501        if !verified_result.inner().magnitude().is_finite() {
502            return Err(AdaptiveVerificationError::GpuVerification(
503                GpuVerificationError::InvariantViolation {
504                    invariant: "Result magnitude must be finite".to_string(),
505                },
506            ));
507        }
508
509        Ok(verified_result)
510    }
511
512    /// WASM batch verification implementation
513    async fn wasm_batch_verification<const P: usize, const Q: usize, const R: usize>(
514        &self,
515        a_batch: &[VerifiedMultivector<P, Q, R>],
516        b_batch: &[VerifiedMultivector<P, Q, R>],
517    ) -> Result<Vec<VerifiedMultivector<P, Q, R>>, AdaptiveVerificationError> {
518        let mut results = Vec::with_capacity(a_batch.len());
519
520        for (a, b) in a_batch.iter().zip(b_batch.iter()) {
521            let result = self.wasm_runtime_verification(a, b).await?;
522            results.push(result);
523        }
524
525        Ok(results)
526    }
527
528    /// Verify geometric product mathematical properties
529    fn verify_geometric_product_properties<const P: usize, const Q: usize, const R: usize>(
530        &self,
531        a: &VerifiedMultivector<P, Q, R>,
532        b: &VerifiedMultivector<P, Q, R>,
533        result: &VerifiedMultivector<P, Q, R>,
534    ) -> Result<(), AdaptiveVerificationError> {
535        // Verify magnitude inequality: |a * b| <= |a| * |b|
536        let result_mag = result.inner().magnitude();
537        let a_mag = a.inner().magnitude();
538        let b_mag = b.inner().magnitude();
539
540        if result_mag > a_mag * b_mag + 1e-12 {
541            return Err(AdaptiveVerificationError::GpuVerification(
542                GpuVerificationError::InvariantViolation {
543                    invariant: format!(
544                        "Magnitude inequality violated: {} > {} * {}",
545                        result_mag, a_mag, b_mag
546                    ),
547                },
548            ));
549        }
550
551        Ok(())
552    }
553}
554
555/// Platform capabilities interface for adaptive optimization
556pub trait PlatformCapabilities {
557    /// Get maximum recommended batch size for the platform
558    fn max_batch_size(&self) -> usize;
559
560    /// Get optimal verification strategy for given workload
561    fn optimal_strategy(&self, workload_size: usize) -> VerificationStrategy;
562
563    /// Check if platform supports concurrent verification
564    fn supports_concurrent_verification(&self) -> bool;
565
566    /// Get platform-specific performance metrics
567    fn performance_characteristics(&self) -> PlatformPerformanceProfile;
568}
569
570#[derive(Debug, Clone)]
571pub struct PlatformPerformanceProfile {
572    pub verification_overhead_percent: f64,
573    pub memory_bandwidth_gbps: f64,
574    pub compute_throughput_gflops: f64,
575    pub latency_microseconds: f64,
576}
577
578impl PlatformCapabilities for VerificationPlatform {
579    fn max_batch_size(&self) -> usize {
580        match self {
581            VerificationPlatform::NativeCpu { features } => features.core_count * 1000,
582            VerificationPlatform::Gpu { memory_mb, .. } => {
583                (*memory_mb as usize * 1024 * 1024) / (8 * 64) // Rough estimate
584            }
585            VerificationPlatform::Wasm { .. } => {
586                10000 // Conservative for browser memory limits
587            }
588        }
589    }
590
591    fn optimal_strategy(&self, workload_size: usize) -> VerificationStrategy {
592        match self {
593            VerificationPlatform::NativeCpu { .. } => {
594                if workload_size < 100 {
595                    VerificationStrategy::Strict
596                } else {
597                    VerificationStrategy::Statistical { sample_rate: 0.1 }
598                }
599            }
600            VerificationPlatform::Gpu { .. } => {
601                if workload_size < 50 {
602                    VerificationStrategy::Boundary
603                } else {
604                    VerificationStrategy::Statistical { sample_rate: 0.05 }
605                }
606            }
607            VerificationPlatform::Wasm { .. } => {
608                VerificationStrategy::Statistical { sample_rate: 0.02 }
609            }
610        }
611    }
612
613    fn supports_concurrent_verification(&self) -> bool {
614        match self {
615            VerificationPlatform::NativeCpu { features } => features.core_count > 1,
616            VerificationPlatform::Gpu { .. } => true,
617            VerificationPlatform::Wasm { .. } => false, // Limited by JS single-threading
618        }
619    }
620
621    fn performance_characteristics(&self) -> PlatformPerformanceProfile {
622        match self {
623            VerificationPlatform::NativeCpu { features } => PlatformPerformanceProfile {
624                verification_overhead_percent: 5.0,
625                memory_bandwidth_gbps: 50.0,
626                compute_throughput_gflops: features.core_count as f64 * 100.0,
627                latency_microseconds: 1.0,
628            },
629            VerificationPlatform::Gpu { compute_units, .. } => PlatformPerformanceProfile {
630                verification_overhead_percent: 15.0,
631                memory_bandwidth_gbps: 200.0,
632                compute_throughput_gflops: *compute_units as f64 * 50.0,
633                latency_microseconds: 100.0,
634            },
635            VerificationPlatform::Wasm { .. } => PlatformPerformanceProfile {
636                verification_overhead_percent: 25.0,
637                memory_bandwidth_gbps: 10.0,
638                compute_throughput_gflops: 10.0,
639                latency_microseconds: 1000.0,
640            },
641        }
642    }
643}
644
645#[cfg(test)]
646mod tests {
647    use super::*;
648
649    #[test]
650    fn test_cpu_features_detection() {
651        let features = AdaptiveVerifier::detect_cpu_features();
652        assert!(features.core_count > 0);
653        assert!(features.cache_size_kb > 0);
654    }
655
656    #[test]
657    fn test_verification_level_determination() {
658        let cpu_platform = VerificationPlatform::NativeCpu {
659            features: CpuFeatures {
660                supports_simd: true,
661                core_count: 8,
662                cache_size_kb: 8192,
663            },
664        };
665
666        let level = AdaptiveVerifier::determine_verification_level(&cpu_platform);
667        assert_eq!(level, AdaptiveVerificationLevel::High);
668
669        let gpu_platform = VerificationPlatform::Gpu {
670            backend: GpuBackend::Vulkan,
671            memory_mb: 2048,
672            compute_units: 16,
673        };
674
675        let level = AdaptiveVerifier::determine_verification_level(&gpu_platform);
676        assert_eq!(level, AdaptiveVerificationLevel::Minimal);
677    }
678
679    #[test]
680    fn test_platform_capabilities() {
681        let platform = VerificationPlatform::NativeCpu {
682            features: CpuFeatures {
683                supports_simd: true,
684                core_count: 4,
685                cache_size_kb: 8192,
686            },
687        };
688
689        assert_eq!(platform.max_batch_size(), 4000);
690        assert!(platform.supports_concurrent_verification());
691
692        let profile = platform.performance_characteristics();
693        assert_eq!(profile.verification_overhead_percent, 5.0);
694        assert_eq!(profile.compute_throughput_gflops, 400.0);
695    }
696
697    #[tokio::test]
698    #[ignore = "GPU hardware required, may fail in CI/CD environments"]
699    async fn test_adaptive_verifier_creation() {
700        // This test may fail in environments without GPU access
701        match AdaptiveVerifier::new().await {
702            Ok(verifier) => {
703                assert!(verifier.performance_budget() > Duration::ZERO);
704            }
705            Err(AdaptiveVerificationError::PlatformDetection(_)) => {
706                // Expected in limited environments
707            }
708            Err(e) => panic!("Unexpected error: {:?}", e),
709        }
710    }
711
712    #[tokio::test]
713    async fn test_verification_with_config() {
714        // Test adaptive behavior through the robust CPU fallback path; hardware GPU
715        // probing is covered by ignored hardware tests because some headless EGL
716        // stacks panic during adapter initialization.
717        std::env::set_var("AMARI_GPU_FORCE_CPU", "1");
718        match AdaptiveVerifier::with_config(
719            AdaptiveVerificationLevel::Minimal,
720            Duration::from_millis(5),
721        )
722        .await
723        {
724            Ok(verifier) => {
725                // GPU or CPU succeeded - test functionality
726                assert_eq!(
727                    *verifier.verification_level(),
728                    AdaptiveVerificationLevel::Minimal
729                );
730                assert_eq!(verifier.performance_budget(), Duration::from_millis(5));
731
732                assert!(matches!(
733                    verifier.platform(),
734                    VerificationPlatform::NativeCpu { .. }
735                ));
736                println!("✅ CPU verification platform detected via forced fallback");
737            }
738            Err(e) => {
739                std::env::remove_var("AMARI_GPU_FORCE_CPU");
740                // Should not fail - adaptive design should always have a fallback
741                panic!("Adaptive verifier should not fail, but got: {:?}", e);
742            }
743        }
744
745        std::env::remove_var("AMARI_GPU_FORCE_CPU");
746    }
747}