Skip to main content

batuta/oracle/cookbook/
recipes.rs

1//! Recipe registrations for the Cookbook
2//!
3//! This module contains all recipe definitions, split from mod.rs for file size compliance.
4
5use super::Recipe;
6
7/// Register all recipes in the cookbook
8pub fn register_all(cookbook: &mut super::Cookbook) {
9    register_wasm_recipes(cookbook);
10    register_ml_recipes(cookbook);
11    register_transpilation_recipes(cookbook);
12    register_distributed_recipes(cookbook);
13    register_quality_recipes(cookbook);
14    register_speech_recipes(cookbook);
15    super::recipes_more::register_training_recipes(cookbook);
16    super::recipes_more::register_data_recipes(cookbook);
17    super::recipes_more::register_registry_recipes(cookbook);
18    super::recipes_more::register_rag_recipes(cookbook);
19    super::recipes_more::register_viz_recipes(cookbook);
20    super::recipes_more::register_rlhf_recipes(cookbook);
21}
22
23// =========================================================================
24// WASM Recipes
25// =========================================================================
26
27fn register_wasm_recipes(cookbook: &mut super::Cookbook) {
28    // Zero-JS WASM Architecture
29    cookbook.add(
30            Recipe::new("wasm-zero-js", "Zero-JS WASM Application")
31                .with_problem("Build interactive web apps with pure Rust/WASM, eliminating JavaScript entirely")
32                .with_components(vec!["simular", "trueno", "web-sys", "wasm-bindgen"])
33                .with_tags(vec!["wasm", "zero-js", "web", "canvas", "animation"])
34                .with_code(r##"// Cargo.toml
35[lib]
36crate-type = ["cdylib"]
37
38[dependencies]
39wasm-bindgen = "0.2"
40web-sys = { version = "0.3", features = [
41    "Window", "Document", "HtmlCanvasElement",
42    "CanvasRenderingContext2d", "Element"
43]}
44console_error_panic_hook = "0.1"
45
46// src/lib.rs
47use std::cell::RefCell;
48use std::rc::Rc;
49use wasm_bindgen::prelude::*;
50use wasm_bindgen::JsCast;
51
52struct AppState {
53    canvas: web_sys::HtmlCanvasElement,
54    ctx: web_sys::CanvasRenderingContext2d,
55    frame: u32,
56}
57
58impl AppState {
59    fn tick(&mut self) {
60        self.frame += 1;
61        self.render();
62    }
63
64    fn render(&self) {
65        let w = self.canvas.width() as f64;
66        let h = self.canvas.height() as f64;
67
68        // Clear
69        self.ctx.set_fill_style_str("#0a0a1a");
70        self.ctx.fill_rect(0.0, 0.0, w, h);
71
72        // Draw
73        self.ctx.set_fill_style_str("#4ecdc4");
74        self.ctx.begin_path();
75        let _ = self.ctx.arc(w/2.0, h/2.0, 50.0, 0.0, std::f64::consts::PI * 2.0);
76        self.ctx.fill();
77    }
78}
79
80fn request_animation_frame(f: &Closure<dyn FnMut()>) {
81    web_sys::window().expect("no global window")
82        .request_animation_frame(f.as_ref().unchecked_ref()).expect("raf failed");
83}
84
85#[wasm_bindgen(js_name = initApp)]
86pub fn init_app() -> Result<(), JsValue> {
87    console_error_panic_hook::set_once();
88
89    let window = web_sys::window().expect("no window");
90    let document = window.document().expect("no document");
91    let canvas = document.get_element_by_id("canvas")
92        .expect("no canvas")
93        .dyn_into::<web_sys::HtmlCanvasElement>()?;
94
95    let ctx = canvas.get_context("2d")?.expect("no 2d context")
96        .dyn_into::<web_sys::CanvasRenderingContext2d>()?;
97
98    let state = Rc::new(RefCell::new(AppState { canvas, ctx, frame: 0 }));
99
100    // Animation loop
101    let f: Rc<RefCell<Option<Closure<dyn FnMut()>>>> = Rc::new(RefCell::new(None));
102    let g = Rc::clone(&f);
103    let state_clone = Rc::clone(&state);
104
105    *g.borrow_mut() = Some(Closure::new(move || {
106        state_clone.borrow_mut().tick();
107        request_animation_frame(f.borrow().as_ref().expect("closure not set"));
108    }));
109
110    request_animation_frame(g.borrow().as_ref().expect("closure not set"));
111    Ok(())
112}
113
114// index.html - ONE LINE OF JAVASCRIPT
115// <script type="module">import init, { initApp } from './pkg/app.js'; init().then(initApp);</script>
116"##)
117                .with_related(vec!["wasm-event-handling", "wasm-canvas-rendering"])
118                .with_test_code(r#"#[cfg(all(test, not(target_arch = "wasm32")))]
119mod tests {
120    #[test]
121    fn test_frame_increment() {
122        let mut frame = 0u32;
123        frame += 1;
124        assert_eq!(frame, 1);
125    }
126
127    #[test]
128    fn test_circle_radius_positive() {
129        let radius = 50.0_f64;
130        assert!(radius > 0.0);
131    }
132
133    #[test]
134    fn test_canvas_center_calculation() {
135        let w = 800_u32;
136        let h = 600_u32;
137        let center_x = (w as f64) / 2.0;
138        let center_y = (h as f64) / 2.0;
139        assert_eq!(center_x, 400.0);
140        assert_eq!(center_y, 300.0);
141    }
142}"#),
143        );
144
145    // WASM Event Handling
146    cookbook.add(
147            Recipe::new("wasm-event-handling", "WASM Event Handling")
148                .with_problem("Handle DOM events (click, input, keypress) in pure Rust")
149                .with_components(vec!["simular", "web-sys", "wasm-bindgen"])
150                .with_tags(vec!["wasm", "events", "dom", "closure"])
151                .with_code(r#"use wasm_bindgen::prelude::*;
152use wasm_bindgen::JsCast;
153
154fn setup_button<F>(document: &web_sys::Document, id: &str, mut callback: F) -> Result<(), JsValue>
155where
156    F: FnMut() + 'static,
157{
158    if let Some(btn) = document.get_element_by_id(id) {
159        let closure = Closure::wrap(Box::new(move |_: web_sys::Event| {
160            callback();
161        }) as Box<dyn FnMut(_)>);
162
163        btn.add_event_listener_with_callback("click", closure.as_ref().unchecked_ref())?;
164        closure.forget(); // Prevent closure from being dropped
165    }
166    Ok(())
167}
168
169fn setup_slider(document: &web_sys::Document, id: &str, state: Rc<RefCell<AppState>>) -> Result<(), JsValue> {
170    if let Some(slider) = document.get_element_by_id(id) {
171        let closure = Closure::wrap(Box::new(move |e: web_sys::Event| {
172            if let Some(target) = e.target() {
173                if let Some(input) = target.dyn_ref::<web_sys::HtmlInputElement>() {
174                    if let Ok(value) = input.value().parse::<u32>() {
175                        state.borrow_mut().set_speed(value);
176                    }
177                }
178            }
179        }) as Box<dyn FnMut(_)>);
180
181        slider.add_event_listener_with_callback("input", closure.as_ref().unchecked_ref())?;
182        closure.forget();
183    }
184    Ok(())
185}
186"#)
187                .with_related(vec!["wasm-zero-js", "wasm-canvas-rendering"])
188                .with_test_code(r#"#[cfg(all(test, not(target_arch = "wasm32")))]
189mod tests {
190    use std::cell::RefCell;
191    use std::rc::Rc;
192
193    #[test]
194    fn test_closure_state_capture() {
195        let counter = Rc::new(RefCell::new(0u32));
196        let counter_clone = Rc::clone(&counter);
197        let increment = move || { *counter_clone.borrow_mut() += 1; };
198        increment();
199        assert_eq!(*counter.borrow(), 1);
200    }
201
202    #[test]
203    fn test_input_value_parsing() {
204        let input_value = "42";
205        let parsed = input_value.parse::<u32>();
206        assert_eq!(parsed.expect("unexpected failure"), 42);
207    }
208
209    #[test]
210    fn test_speed_state_update() {
211        let mut speed = 0_u32;
212        let new_value = 10_u32;
213        speed = new_value;
214        assert_eq!(speed, 10);
215    }
216}"#),
217        );
218
219    // WASM Canvas Rendering
220    cookbook.add(
221        Recipe::new("wasm-canvas-rendering", "WASM Canvas 2D Rendering")
222            .with_problem("Render graphics to HTML5 Canvas from Rust/WASM")
223            .with_components(vec!["simular", "web-sys"])
224            .with_tags(vec!["wasm", "canvas", "graphics", "rendering"])
225            .with_code(
226                r##"use web_sys::CanvasRenderingContext2d;
227
228fn render(ctx: &CanvasRenderingContext2d, w: f64, h: f64, trail: &[(f64, f64)]) {
229    // Clear background
230    ctx.set_fill_style_str("#0f0f23");
231    ctx.fill_rect(0.0, 0.0, w, h);
232
233    // Draw grid
234    ctx.set_stroke_style_str("#1a1a2e");
235    ctx.set_line_width(1.0);
236    for i in 1..=10 {
237        let x = w * (i as f64) / 10.0;
238        ctx.begin_path();
239        ctx.move_to(x, 0.0);
240        ctx.line_to(x, h);
241        ctx.stroke();
242    }
243
244    // Draw circle with glow
245    ctx.set_fill_style_str("#ffd93d");
246    ctx.begin_path();
247    let _ = ctx.arc(w/2.0, h/2.0, 15.0, 0.0, std::f64::consts::PI * 2.0);
248    ctx.fill();
249
250    // Semi-transparent glow
251    ctx.set_global_alpha(0.3);
252    ctx.begin_path();
253    let _ = ctx.arc(w/2.0, h/2.0, 25.0, 0.0, std::f64::consts::PI * 2.0);
254    ctx.fill();
255    ctx.set_global_alpha(1.0);
256
257    // Draw trail with fading alpha
258    ctx.begin_path();
259    if let Some((x, y)) = trail.first() {
260        ctx.move_to(*x, *y);
261    }
262    for (i, (x, y)) in trail.iter().enumerate().skip(1) {
263        let alpha = (i as f64) / (trail.len() as f64) * 0.5;
264        ctx.set_global_alpha(alpha);
265        ctx.line_to(*x, *y);
266    }
267    ctx.set_global_alpha(1.0);
268    ctx.stroke();
269
270    // Text labels
271    ctx.set_fill_style_str("#888888");
272    ctx.set_font("12px monospace");
273    let _ = ctx.fill_text("Label", 100.0, 100.0);
274}
275"##,
276            )
277            .with_related(vec!["wasm-zero-js", "wasm-event-handling"])
278            .with_test_code(
279                r#"#[cfg(all(test, not(target_arch = "wasm32")))]
280mod tests {
281    #[test]
282    fn test_grid_spacing_calculation() {
283        let width = 800.0_f64;
284        let divisions = 10;
285        let spacing = width / (divisions as f64);
286        assert_eq!(spacing, 80.0);
287    }
288
289    #[test]
290    fn test_trail_alpha_fade() {
291        let trail_len = 10;
292        let index = 5;
293        let alpha = (index as f64) / (trail_len as f64) * 0.5;
294        assert!((alpha - 0.25).abs() < 0.001);
295    }
296
297    #[test]
298    fn test_trail_data_structure() {
299        let mut trail: Vec<(f64, f64)> = Vec::new();
300        trail.push((100.0, 200.0));
301        trail.push((150.0, 250.0));
302        assert_eq!(trail.len(), 2);
303    }
304}"#,
305            ),
306    );
307}
308
309// =========================================================================
310// ML Recipes
311// =========================================================================
312
313fn register_ml_recipes(cookbook: &mut super::Cookbook) {
314    // Random Forest Classification
315    cookbook.add(
316        Recipe::new("ml-random-forest", "Random Forest Classification")
317            .with_problem("Train a random forest classifier and export for serving")
318            .with_components(vec!["aprender", "realizar", "alimentar"])
319            .with_tags(vec!["ml", "classification", "random-forest", "supervised"])
320            .with_code(
321                r#"use aprender::prelude::*;
322use alimentar::CsvReader;
323
324// Load data
325let data = CsvReader::from_path("data.csv")?.load()?;
326let (X, y) = data.split_target("label")?;
327
328// Train-test split
329let (X_train, X_test, y_train, y_test) = train_test_split(&X, &y, 0.2, Some(42))?;
330
331// Train model
332let model = RandomForestClassifier::new()
333    .n_estimators(100)
334    .max_depth(Some(10))
335    .min_samples_split(5)
336    .fit(&X_train, &y_train)?;
337
338// Evaluate
339let predictions = model.predict(&X_test)?;
340let accuracy = accuracy_score(&y_test, &predictions);
341println!("Accuracy: {:.2}%", accuracy * 100.0);
342
343// Export for serving
344model.save_apr("model.apr")?;
345
346// Load in realizar for inference
347// realizar serve --model model.apr --port 8080
348"#,
349            )
350            .with_related(vec!["ml-serving", "ml-preprocessing"])
351            .with_test_code(
352                r#"#[cfg(test)]
353mod tests {
354    #[test]
355    fn test_random_forest_builder_config() {
356        let n_estimators = 100;
357        let max_depth = Some(10);
358        assert_eq!(n_estimators, 100);
359        assert!(max_depth.expect("unexpected failure") > 0);
360    }
361
362    #[test]
363    fn test_predictions_collection() {
364        let predictions = vec![0, 1, 1, 0, 1];
365        assert_eq!(predictions.len(), 5);
366    }
367
368    #[test]
369    fn test_accuracy_in_range() {
370        let correct = 85;
371        let total = 100;
372        let accuracy = correct as f64 / total as f64;
373        assert!(accuracy >= 0.0 && accuracy <= 1.0);
374    }
375}"#,
376            ),
377    );
378
379    // Model Serving
380    cookbook.add(
381        Recipe::new("ml-serving", "Model Serving with Realizar")
382            .with_problem("Deploy trained models as HTTP API or Lambda function")
383            .with_components(vec!["realizar", "aprender"])
384            .with_tags(vec!["ml", "serving", "inference", "api", "lambda"])
385            .with_code(
386                r#"// Command line serving
387// realizar serve --model model.apr --port 8080
388
389// Programmatic serving
390use realizar::prelude::*;
391
392let model = Model::load("model.apr")?;
393let server = Server::new(model)
394    .port(8080)
395    .batch_size(32)
396    .workers(4);
397
398server.run()?;
399
400// Lambda deployment
401// realizar package --model model.apr --output lambda.zip
402// aws lambda create-function --function-name my-model \
403//     --runtime provided.al2 --handler bootstrap \
404//     --zip-file fileb://lambda.zip
405
406// Request format
407// POST /predict
408// Content-Type: application/json
409// {"features": [1.0, 2.0, 3.0, 4.0]}
410"#,
411            )
412            .with_related(vec!["ml-random-forest", "distributed-inference"])
413            .with_test_code(
414                r"#[cfg(test)]
415mod tests {
416    #[test]
417    fn test_server_config_port() {
418        let port = 8080_u16;
419        assert!(port >= 1024);
420    }
421
422    #[test]
423    fn test_server_config_batch_and_workers() {
424        let batch_size = 32;
425        let workers = 4;
426        assert_eq!(batch_size, 32);
427        assert_eq!(workers, 4);
428    }
429
430    #[test]
431    fn test_feature_vector_format() {
432        let features: Vec<f32> = vec![1.0, 2.5, 3.7, 4.2];
433        assert_eq!(features.len(), 4);
434    }
435}",
436            ),
437    );
438}
439
440// =========================================================================
441// Transpilation Recipes
442// =========================================================================
443
444fn register_transpilation_recipes(cookbook: &mut super::Cookbook) {
445    // Python to Rust
446    cookbook.add(
447        Recipe::new("transpile-python", "Python to Rust Migration")
448            .with_problem("Convert Python ML code to Rust using depyler")
449            .with_components(vec!["depyler", "aprender", "trueno", "batuta"])
450            .with_tags(vec!["transpilation", "python", "migration"])
451            .with_code(
452                r"# Original Python code (sklearn_model.py)
453from sklearn.ensemble import RandomForestClassifier
454from sklearn.model_selection import train_test_split
455import numpy as np
456
457X = np.random.rand(100, 4)
458y = np.random.randint(0, 2, 100)
459
460X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
461model = RandomForestClassifier(n_estimators=100)
462model.fit(X_train, y_train)
463
464# Transpile with depyler
465# batuta transpile sklearn_model.py --output src/model.rs
466
467// Generated Rust code (src/model.rs)
468use aprender::prelude::*;
469use trueno::prelude::*;
470
471fn main() -> Result<(), Box<dyn std::error::Error>> {
472    let X = Tensor::rand(&[100, 4]);
473    let y = Tensor::randint(0, 2, &[100]);
474
475    let (X_train, X_test, y_train, y_test) = train_test_split(&X, &y, 0.2, None)?;
476    let model = RandomForestClassifier::new()
477        .n_estimators(100)
478        .fit(&X_train, &y_train)?;
479
480    Ok(())
481}
482",
483            )
484            .with_related(vec!["transpile-numpy", "quality-golden-trace"])
485            .with_test_code(
486                r"#[cfg(test)]
487mod tests {
488    #[test]
489    fn test_tensor_shape() {
490        let rows = 100;
491        let cols = 4;
492        let total_elements = rows * cols;
493        assert_eq!(total_elements, 400);
494    }
495
496    #[test]
497    fn test_train_test_split_ratio() {
498        let total = 100;
499        let train_ratio = 0.8;
500        let train_size = (total as f64 * train_ratio) as usize;
501        assert_eq!(train_size, 80);
502    }
503
504    #[test]
505    fn test_label_values_binary() {
506        let labels = vec![0, 1, 1, 0, 1];
507        assert!(labels.iter().all(|&l| l == 0 || l == 1));
508    }
509}",
510            ),
511    );
512
513    // NumPy to Trueno
514    cookbook.add(
515        Recipe::new("transpile-numpy", "NumPy to Trueno Conversion")
516            .with_problem("Convert NumPy operations to SIMD-accelerated Trueno")
517            .with_components(vec!["depyler", "trueno"])
518            .with_tags(vec!["transpilation", "numpy", "simd", "tensors"])
519            .with_code(
520                r"# Python NumPy
521import numpy as np
522a = np.array([1, 2, 3, 4])
523b = np.array([5, 6, 7, 8])
524dot = np.dot(a, b)
525matmul = np.matmul(X, W)
526
527// Rust Trueno (SIMD-accelerated)
528use trueno::prelude::*;
529
530let a = Tensor::from_vec(vec![1.0, 2.0, 3.0, 4.0]);
531let b = Tensor::from_vec(vec![5.0, 6.0, 7.0, 8.0]);
532let dot = a.dot(&b);  // SIMD auto-vectorized
533let matmul = X.matmul(&W);  // GPU if available
534",
535            )
536            .with_related(vec!["transpile-python"])
537            .with_test_code(
538                r"#[cfg(test)]
539mod tests {
540    #[test]
541    fn test_vector_creation() {
542        let a = vec![1.0, 2.0, 3.0, 4.0];
543        let b = vec![5.0, 6.0, 7.0, 8.0];
544        assert_eq!(a.len(), b.len());
545    }
546
547    #[test]
548    fn test_dot_product_computation() {
549        let a = vec![1.0, 2.0, 3.0, 4.0];
550        let b = vec![5.0, 6.0, 7.0, 8.0];
551        let dot: f64 = a.iter().zip(b.iter()).map(|(x, y)| x * y).sum();
552        assert_eq!(dot, 70.0);
553    }
554
555    #[test]
556    fn test_simd_element_type() {
557        let vec: Vec<f64> = vec![1.0, 2.0, 3.0];
558        assert!(vec.iter().all(|x| x.is_finite()));
559    }
560}",
561            ),
562    );
563}
564
565// =========================================================================
566// Distributed Recipes
567// =========================================================================
568
569fn register_distributed_recipes(cookbook: &mut super::Cookbook) {
570    // Work-Stealing Distribution
571    cookbook.add(
572        Recipe::new("distributed-work-stealing", "Work-Stealing Task Distribution")
573            .with_problem("Distribute computation across CPU cores with work-stealing")
574            .with_components(vec!["repartir", "trueno"])
575            .with_tags(vec!["distributed", "parallel", "work-stealing", "cpu"])
576            .with_code(
577                r"use repartir::prelude::*;
578
579// Create pool with work-stealing scheduler
580let pool = Pool::builder()
581    .num_workers(num_cpus::get())
582    .build()?;
583
584// Submit tasks
585let results: Vec<f64> = pool.map(data.chunks(1000), |chunk| {
586    // Each chunk processed by a worker
587    chunk.iter().map(|x| x * x).sum()
588})?;
589
590// Reduce results
591let total: f64 = results.iter().sum();
592",
593            )
594            .with_related(vec!["distributed-gpu", "distributed-remote"])
595            .with_test_code(
596                r"#[cfg(test)]
597mod tests {
598    #[test]
599    fn test_pool_worker_count() {
600        let workers = 8;
601        assert!(workers > 0);
602    }
603
604    #[test]
605    fn test_chunk_processing() {
606        let data = vec![1, 2, 3, 4, 5];
607        let chunks: Vec<_> = data.chunks(2).collect();
608        assert_eq!(chunks.len(), 3);
609    }
610
611    #[test]
612    fn test_result_reduction() {
613        let results = vec![10.0, 20.0, 30.0, 40.0];
614        let total: f64 = results.iter().sum();
615        assert_eq!(total, 100.0);
616    }
617}",
618            ),
619    );
620
621    // GPU Distribution
622    cookbook.add(
623        Recipe::new("distributed-gpu", "GPU Compute Distribution")
624            .with_problem("Offload computation to GPU using wgpu")
625            .with_components(vec!["repartir", "trueno"])
626            .with_tags(vec!["distributed", "gpu", "wgpu", "compute"])
627            .with_code(
628                r"use repartir::prelude::*;
629use trueno::prelude::*;
630
631// Create GPU executor
632let executor = GpuExecutor::new()?;
633
634// GPU-accelerated matrix multiplication
635let result = executor.submit(|gpu| {
636    let a = gpu.tensor(&matrix_a)?;
637    let b = gpu.tensor(&matrix_b)?;
638    a.matmul(&b)
639})?;
640
641// Hybrid CPU/GPU
642let pool = Pool::builder()
643    .add_gpu_executor(executor)
644    .add_cpu_executor(CpuExecutor::new())
645    .build()?;
646",
647            )
648            .with_related(vec!["distributed-work-stealing"])
649            .with_test_code(
650                r"#[cfg(test)]
651mod tests {
652    #[test]
653    fn test_matrix_dimensions_valid() {
654        let m = 1024;
655        let k = 512;
656        let n = 2048;
657        assert!(m > 0 && k > 0 && n > 0);
658    }
659
660    #[test]
661    fn test_hybrid_pool_worker_total() {
662        let cpu_workers = 4;
663        let gpu_workers = 2;
664        let total = cpu_workers + gpu_workers;
665        assert_eq!(total, 6);
666    }
667
668    #[test]
669    fn test_matmul_output_shape() {
670        let rows_a = 128;
671        let cols_b = 256;
672        let output_elements = rows_a * cols_b;
673        assert_eq!(output_elements, 32768);
674    }
675}",
676            ),
677    );
678}
679
680// =========================================================================
681// Quality Recipes
682// =========================================================================
683
684fn register_quality_recipes(cookbook: &mut super::Cookbook) {
685    // EDD Testing Pattern
686    cookbook.add(
687        Recipe::new("quality-edd", "Equation-Driven Development")
688            .with_problem("Implement simulations with verifiable governing equations")
689            .with_components(vec!["simular", "probar", "certeza"])
690            .with_tags(vec!["quality", "testing", "edd", "simulation", "falsification"])
691            .with_code(
692                r"use simular::prelude::*;
693
694/// EDD Demo following the complete cycle:
695/// 1. Equation - Define governing equation
696/// 2. Failing Test - Test fails without implementation
697/// 3. Implementation - Implement the simulation
698/// 4. Verification - Test passes, equation verified
699/// 5. Falsification - Demonstrate conditions that break
700
701pub trait DemoEngine {
702    /// Load from YAML configuration (YAML-first)
703    fn from_yaml(yaml: &str) -> Result<Self, DemoError> where Self: Sized;
704
705    /// Advance simulation by one timestep
706    fn step(&mut self, dt: f64) -> StepResult;
707
708    /// Verify governing equation invariants
709    fn verify_invariants(&self) -> bool;
710
711    /// Get falsification status
712    fn falsification_status(&self) -> FalsificationStatus;
713}
714
715// Example: Harmonic Oscillator
716// Governing equation: E = (1/2)kx² + (1/2)mv²
717// Falsification: Energy drift > tolerance indicates integrator failure
718
719impl DemoEngine for HarmonicOscillator {
720    fn verify_invariants(&self) -> bool {
721        let energy = self.kinetic_energy() + self.potential_energy();
722        let error = (energy - self.initial_energy).abs() / self.initial_energy;
723        error < 1e-9  // Energy conservation within tolerance
724    }
725}
726",
727            )
728            .with_related(vec!["quality-probar", "quality-golden-trace"])
729            .with_test_code(
730                r"#[cfg(test)]
731mod tests {
732    #[test]
733    fn test_energy_conservation_invariant() {
734        let kinetic = 60.0;
735        let potential = 40.0;
736        let initial_energy = 100.0;
737        assert!((kinetic + potential - initial_energy).abs() < 1e-6);
738    }
739
740    #[test]
741    fn test_timestep_positivity() {
742        let dt = 0.01_f64;
743        assert!(dt > 0.0);
744    }
745
746    #[test]
747    fn test_falsification_detection() {
748        let tolerance = 1e-9_f64;
749        let error = 1e-5;
750        assert!(error > tolerance);
751    }
752}",
753            ),
754    );
755
756    // Probar Testing
757    cookbook.add(
758        Recipe::new("quality-probar", "Probar Property-Based Testing")
759            .with_problem("Validate WASM demos with property-based and GUI coverage testing")
760            .with_components(vec!["probar", "simular", "certeza"])
761            .with_tags(vec!["quality", "testing", "probar", "property-testing", "gui-coverage"])
762            .with_code(
763                r#"use probar::prelude::*;
764
765// Property-based tests
766#[probar::property]
767fn prop_tour_length_positive(cities: Vec<City>) -> bool {
768    let tour = solve_tsp(&cities);
769    tour.length() > 0.0
770}
771
772#[probar::property]
773fn prop_energy_conserved(dt: f64) -> bool {
774    let mut sim = OrbitSimulation::new();
775    let e0 = sim.total_energy();
776    sim.step(dt);
777    let e1 = sim.total_energy();
778    (e1 - e0).abs() / e0.abs() < 1e-9
779}
780
781// Metamorphic relations
782#[probar::metamorphic]
783fn mr_scale_invariance(scale: f64, cities: Vec<City>) {
784    let tour1 = solve_tsp(&cities);
785    let scaled = cities.iter().map(|c| c * scale).collect();
786    let tour2 = solve_tsp(&scaled);
787    assert!((tour2.length() / tour1.length() - scale).abs() < 1e-6);
788}
789
790// GUI coverage
791#[probar::gui_coverage]
792fn test_canvas_coverage(app: &mut App) {
793    app.click_button("start");
794    app.wait_frames(100);
795    let coverage = app.pixel_coverage();
796    assert!(coverage > 0.8, "Must render to >80% of canvas");
797}
798"#,
799            )
800            .with_related(vec!["quality-edd", "quality-certeza"])
801            .with_test_code(
802                r"#[cfg(test)]
803mod tests {
804    #[test]
805    fn test_tour_length_positivity() {
806        let distances = vec![10.5, 20.3, 15.7, 8.2];
807        let tour_length: f64 = distances.iter().sum();
808        assert!(tour_length > 0.0);
809    }
810
811    #[test]
812    fn test_energy_conservation_property() {
813        let initial = 100.0_f64;
814        let final_energy = 100.0_f64;
815        assert!((initial - final_energy).abs() < 1e-10);
816    }
817
818    #[test]
819    fn test_coverage_threshold() {
820        let covered = 950;
821        let total = 1000;
822        let coverage = covered as f64 / total as f64;
823        assert!(coverage >= 0.95);
824    }
825}",
826            ),
827    );
828
829    // Golden Trace Comparison
830    cookbook.add(
831        Recipe::new("quality-golden-trace", "Golden Trace Validation")
832            .with_problem("Validate transpiled code produces identical behavior to original")
833            .with_components(vec!["renacer", "certeza"])
834            .with_tags(vec!["quality", "validation", "trace", "transpilation"])
835            .with_code(
836                r#"use renacer::prelude::*;
837
838// Capture golden trace from Python
839// renacer trace python sklearn_model.py --output golden.trace
840
841// Capture Rust trace
842// renacer trace ./target/release/model --output rust.trace
843
844// Compare traces
845let comparison = renacer::compare("golden.trace", "rust.trace")?;
846
847assert!(comparison.semantically_equivalent(),
848    "Transpiled code must produce identical results");
849assert!(comparison.syscall_compatible(),
850    "System calls must match (file I/O, network, etc.)");
851
852// Performance comparison
853println!("Python: {:.2}ms", comparison.baseline_time_ms());
854println!("Rust: {:.2}ms", comparison.target_time_ms());
855println!("Speedup: {:.1}x", comparison.speedup());
856"#,
857            )
858            .with_related(vec!["transpile-python", "quality-edd"])
859            .with_test_code(
860                r#"#[cfg(test)]
861mod tests {
862    #[test]
863    fn test_semantic_equivalence_check() {
864        let baseline = vec![1.0, 2.0, 3.0];
865        let candidate = vec![1.0, 2.0, 3.0];
866        assert_eq!(baseline, candidate);
867    }
868
869    #[test]
870    fn test_speedup_calculation() {
871        let baseline_ms = 1000.0_f64;
872        let optimized_ms = 250.0_f64;
873        let speedup = baseline_ms / optimized_ms;
874        assert_eq!(speedup, 4.0);
875    }
876
877    #[test]
878    fn test_trace_comparison_length() {
879        let golden = vec!["step1", "step2", "step3"];
880        let actual = vec!["step1", "step2", "step3"];
881        assert_eq!(golden.len(), actual.len());
882    }
883}"#,
884            ),
885    );
886}
887
888// =========================================================================
889// Speech Recognition Recipes
890// =========================================================================
891
892fn register_speech_recipes(cookbook: &mut super::Cookbook) {
893    // Whisper ASR
894    cookbook.add(
895        Recipe::new("speech-whisper", "Whisper Speech Recognition")
896            .with_problem("Transcribe audio to text using pure-Rust Whisper implementation")
897            .with_components(vec!["whisper-apr", "aprender", "trueno"])
898            .with_tags(vec!["speech", "asr", "whisper", "transcription", "wasm"])
899            .with_code(
900                r#"use whisper_apr::prelude::*;
901
902// Load model (downloads from HuggingFace on first run)
903let model = WhisperModel::load("tiny.en")?;
904
905// Transcribe audio file
906let audio = Audio::load("recording.wav")?;
907let result = model.transcribe(&audio)?;
908
909println!("Transcription: {}", result.text);
910
911// With timestamps
912for segment in result.segments {
913    println!("[{:.2}s - {:.2}s] {}",
914        segment.start, segment.end, segment.text);
915}
916
917// Streaming transcription (real-time)
918let mut stream = model.stream()?;
919for chunk in audio_chunks {
920    if let Some(text) = stream.process(&chunk)? {
921        print!("{}", text);
922    }
923}
924
925// WASM deployment
926// wasm-pack build --target web --features wasm
927// <script type="module">
928//   import init, { transcribe } from './pkg/whisper_apr.js';
929//   await init();
930//   const text = await transcribe(audioBuffer);
931// </script>
932"#,
933            )
934            .with_related(vec!["speech-streaming", "ml-serving"])
935            .with_test_code(
936                r#"#[cfg(test)]
937mod tests {
938    #[test]
939    fn test_model_name_validation() {
940        let model = "tiny.en";
941        let valid = vec!["tiny", "tiny.en", "base", "base.en"];
942        assert!(valid.contains(&model));
943    }
944
945    #[test]
946    fn test_transcription_result_non_empty() {
947        let text = "Hello world";
948        assert!(!text.is_empty());
949    }
950
951    #[test]
952    fn test_segment_timestamp_ordering() {
953        let start = 0.5_f64;
954        let end = 2.0_f64;
955        assert!(start < end);
956    }
957}"#,
958            ),
959    );
960
961    // Streaming Speech
962    cookbook.add(
963        Recipe::new("speech-streaming", "Real-time Speech Streaming")
964            .with_problem("Process audio in real-time with low latency")
965            .with_components(vec!["whisper-apr", "trueno"])
966            .with_tags(vec!["speech", "streaming", "real-time", "low-latency"])
967            .with_code(
968                r#"use whisper_apr::streaming::*;
969
970// Configure streaming decoder
971let config = StreamConfig {
972    chunk_size_ms: 500,      // Process every 500ms
973    overlap_ms: 100,         // Overlap for continuity
974    vad_enabled: true,       // Voice activity detection
975    language: Some("en"),
976};
977
978let mut decoder = StreamingDecoder::new(model, config)?;
979
980// Process microphone input
981let mut mic = Microphone::open()?;
982loop {
983    let samples = mic.read_chunk()?;
984
985    // VAD filters silence
986    if let Some(result) = decoder.process(&samples)? {
987        // Partial results for UI feedback
988        if result.is_partial {
989            print!("\r{}", result.text);
990        } else {
991            println!("\n[Final] {}", result.text);
992        }
993    }
994}
995"#,
996            )
997            .with_related(vec!["speech-whisper"])
998            .with_test_code(
999                r"#[cfg(test)]
1000mod tests {
1001    #[test]
1002    fn test_stream_config_chunk_size_positive() {
1003        let chunk_size_ms = 500_u32;
1004        assert!(chunk_size_ms > 0);
1005    }
1006
1007    #[test]
1008    fn test_overlap_less_than_chunk_size() {
1009        let chunk_size_ms = 500;
1010        let overlap_ms = 100;
1011        assert!(overlap_ms < chunk_size_ms);
1012    }
1013
1014    #[test]
1015    fn test_vad_enabled_flag() {
1016        let vad_enabled = true;
1017        assert!(vad_enabled);
1018    }
1019}",
1020            ),
1021    );
1022}
1023
1024// =========================================================================
1025// Training Recipes
1026// =========================================================================