bevy_debugger_mcp 0.1.8

AI-assisted debugging for Bevy games through Claude Code using Model Context Protocol
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
/// Query Generators for Testing
/// 
/// Utilities for generating realistic and stress-testing queries
/// to validate caching and optimization performance.

use serde_json::{json, Value};

/// Generate realistic debugging queries that would be used in practice
pub fn generate_realistic_queries() -> Vec<(String, Value)> {
    vec![
        // Entity queries
        ("observe", json!({
            "query": "entities with Transform"
        })),
        ("observe", json!({
            "query": "entities with (Transform and Mesh)"
        })),
        ("observe", json!({
            "query": "entities with Name containing 'player'"
        })),
        ("observe", json!({
            "query": "entities with Health < 50"
        })),
        ("observe", json!({
            "query": "entities in range 10 of (0, 0, 0)"
        })),
        
        // System profiling queries
        ("experiment", json!({
            "type": "performance",
            "systems": ["movement", "physics", "rendering"],
            "duration": 1000
        })),
        ("experiment", json!({
            "type": "memory",
            "duration": 2000,
            "include_entities": true
        })),
        
        // Resource monitoring
        ("resource_metrics", json!({})),
        ("health_check", json!({})),
        
        // Complex queries
        ("observe", json!({
            "query": "entities with (Combat and Health > 80) or (Merchant and Inventory.gold > 100)",
            "sort": "health",
            "limit": 50
        })),
        ("observe", json!({
            "query": "all entities in faction 'warriors'",
            "include_relationships": true
        })),
        
        // Debugging specific queries
        ("diagnostic_report", json!({
            "action": "generate",
            "include_performance": true,
            "include_memory": true
        })),
        ("anomaly", json!({
            "metric": "frame_time",
            "threshold": 16.67,
            "window": 1000
        })),
        
        // Session management
        ("replay", json!({
            "session_id": "debug_session_001",
            "time_range": {"start": 0, "end": 30000}
        })),
        ("checkpoint", json!({
            "name": "before_optimization_test",
            "include_world_state": true
        })),
        
        // Tool orchestration
        ("orchestrate", json!({
            "tool": "observe",
            "arguments": {"query": "entities with Position.y > 10"},
            "follow_up": "experiment"
        })),
        ("pipeline", json!({
            "template": "performance_analysis",
            "parameters": {
                "duration": 5000,
                "entity_types": ["warrior", "merchant", "villager"]
            }
        })),
        
        // Stress testing
        ("stress", json!({
            "type": "entity_spawn",
            "count": 100,
            "entity_type": "complex"
        })),
        ("stress", json!({
            "type": "continuous_spawn",
            "intensity": 2,
            "duration": 30000
        })),
    ]
}

/// Generate stress-testing queries for performance validation
pub fn generate_stress_queries() -> Vec<(String, Value)> {
    vec![
        // High-frequency entity queries
        ("observe", json!({
            "query": "all entities",
            "cache_ttl": 0 // Force no caching
        })),
        ("observe", json!({
            "query": "entities with any component",
            "include_all_data": true
        })),
        
        // Complex relationship queries
        ("observe", json!({
            "query": "entities with relationships to entities with Combat > 50",
            "recursive_depth": 3,
            "include_relationship_data": true
        })),
        
        // Large data queries
        ("observe", json!({
            "query": "entities with Inventory",
            "include_inventory_contents": true,
            "expand_references": true
        })),
        
        // Expensive computation queries
        ("experiment", json!({
            "type": "pathfinding_analysis",
            "start_points": (0..20).map(|i| json!([i * 2, 0, i * 3])).collect::<Vec<_>>(),
            "end_points": (0..20).map(|i| json!([i * -2, 0, i * -3])).collect::<Vec<_>>(),
            "algorithm": "a_star"
        })),
        
        // Memory-intensive queries
        ("observe", json!({
            "query": "history of all entities over last 60 seconds",
            "include_state_changes": true,
            "resolution": "high"
        })),
        
        // Concurrent stress queries
        ("observe", json!({
            "query": format!("entities with id in range {} to {}", 0, 10000),
            "batch_size": 1000
        })),
        
        // Deep analysis queries
        ("experiment", json!({
            "type": "system_dependency_analysis",
            "include_performance_impact": true,
            "analyze_bottlenecks": true,
            "correlation_analysis": true
        })),
        
        // High-volume data export
        ("diagnostic_report", json!({
            "action": "export_all_data",
            "format": "detailed_json",
            "include_history": true,
            "compression": false
        })),
    ]
}

/// Generate queries that test specific optimization features
pub fn generate_optimization_test_queries() -> Vec<(String, Value)> {
    vec![
        // Cache effectiveness tests
        ("observe", json!({
            "query": "entities with Transform",
            "test_id": "cache_test_1"
        })),
        ("observe", json!({
            "query": "entities with Transform", // Identical to above for cache hit
            "test_id": "cache_test_1_repeat"
        })),
        
        // Pool utilization tests
        ("observe", json!({
            "query": "small dataset",
            "expected_response_size": "small"
        })),
        ("observe", json!({
            "query": "entities with detailed data",
            "include_all_components": true,
            "expected_response_size": "large"
        })),
        
        // Lazy initialization tests
        ("health_check", json!({
            "initialize_components": false
        })),
        ("observe", json!({
            "query": "first entity access",
            "force_initialization": true
        })),
        
        // Feature flag tests
        ("observe", json!({
            "query": "test basic functionality"
        })),
        ("experiment", json!({
            "type": "feature_flag_test",
            "check_enabled_features": true
        })),
    ]
}

/// Generate queries with varying complexity for performance testing
pub fn generate_complexity_queries() -> Vec<(String, Value)> {
    let mut queries = Vec::new();
    
    // Simple queries (O(n) complexity)
    for i in 0..10 {
        queries.push(("observe", json!({
            "query": format!("entities with component_type_{}", i),
            "complexity": "simple"
        })));
    }
    
    // Medium complexity queries (O(n log n))
    for i in 0..5 {
        queries.push(("observe", json!({
            "query": format!("entities with component_type_{} sorted by value", i),
            "sort": "value",
            "complexity": "medium"
        })));
    }
    
    // Complex queries (O(n²) or higher)
    queries.push(("observe", json!({
        "query": "entities with relationships to entities with relationships",
        "recursive": true,
        "max_depth": 3,
        "complexity": "high"
    })));
    
    queries.push(("experiment", json!({
        "type": "cross_reference_analysis",
        "analyze_all_relationships": true,
        "include_indirect_dependencies": true,
        "complexity": "very_high"
    })));
    
    queries
}

/// Generate queries that test edge cases and error conditions
pub fn generate_edge_case_queries() -> Vec<(String, Value)> {
    vec![
        // Empty results
        ("observe", json!({
            "query": "entities with NonExistentComponent"
        })),
        
        // Invalid queries
        ("observe", json!({
            "query": "invalid query syntax ((("
        })),
        
        // Very large limits
        ("observe", json!({
            "query": "all entities",
            "limit": 1000000
        })),
        
        // Invalid parameters
        ("experiment", json!({
            "type": "nonexistent_experiment_type"
        })),
        
        // Null/undefined values
        ("observe", json!({
            "query": null
        })),
        
        // Very long strings
        ("observe", json!({
            "query": "a".repeat(10000)
        })),
        
        // Nested complexity
        ("observe", json!({
            "query": {
                "nested": {
                    "very": {
                        "deeply": {
                            "nested": "query"
                        }
                    }
                }
            }
        })),
        
        // Circular references (in parameters)
        ("experiment", json!({
            "type": "circular_test",
            "parameters": {
                "reference": "self"
            }
        })),
    ]
}

/// Generate sequential queries to test caching patterns
pub fn generate_sequential_queries() -> Vec<Vec<(String, Value)>> {
    vec![
        // Cache warm-up sequence
        vec![
            ("health_check", json!({})), // Initialize systems
            ("resource_metrics", json!({})), // Get baseline
            ("observe", json!({"query": "entities with Transform"})), // First entity query
            ("observe", json!({"query": "entities with Transform"})), // Should hit cache
        ],
        
        // Progressive complexity sequence
        vec![
            ("observe", json!({"query": "entity count"})),
            ("observe", json!({"query": "entities with Transform"})),
            ("observe", json!({"query": "entities with (Transform and Mesh)"})),
            ("observe", json!({"query": "entities with (Transform and Mesh and Health)"})),
        ],
        
        // Cache invalidation sequence
        vec![
            ("observe", json!({"query": "all entities"})), // Cache initial state
            ("stress", json!({"type": "entity_spawn", "count": 10})), // Modify world
            ("observe", json!({"query": "all entities"})), // Should invalidate cache
        ],
        
        // Performance regression sequence
        vec![
            ("checkpoint", json!({"name": "performance_baseline"})),
            ("experiment", json!({"type": "performance", "duration": 1000})),
            ("stress", json!({"type": "continuous_spawn", "intensity": 1})),
            ("experiment", json!({"type": "performance", "duration": 1000})),
            ("diagnostic_report", json!({"action": "compare_checkpoints"})),
        ],
    ]
}

/// Generate time-based query patterns for realistic usage simulation
pub fn generate_time_based_queries(duration_seconds: u64) -> Vec<(u64, String, Value)> {
    let mut queries = Vec::new();
    let mut time_offset = 0;

    // Regular monitoring queries (every 5 seconds)
    while time_offset < duration_seconds {
        queries.push((time_offset, "health_check".to_string(), json!({})));
        queries.push((time_offset + 2, "resource_metrics".to_string(), json!({})));
        time_offset += 5;
    }

    // Entity queries (every 3 seconds)
    time_offset = 1;
    let entity_queries = [
        "entities with Transform",
        "entities with Health < 50",
        "entities in combat",
        "entities with Inventory",
    ];
    
    let mut query_index = 0;
    while time_offset < duration_seconds {
        queries.push((
            time_offset,
            "observe".to_string(),
            json!({"query": entity_queries[query_index % entity_queries.len()]}),
        ));
        query_index += 1;
        time_offset += 3;
    }

    // Periodic experiments (every 15 seconds)
    time_offset = 10;
    while time_offset < duration_seconds {
        queries.push((
            time_offset,
            "experiment".to_string(),
            json!({"type": "performance", "duration": 2000}),
        ));
        time_offset += 15;
    }

    // Sort by time
    queries.sort_by_key(|(time, _, _)| *time);
    queries
}

/// Generate workload patterns for specific test scenarios
pub fn generate_workload_pattern(pattern_type: &str) -> Vec<(String, Value)> {
    match pattern_type {
        "debugging_session" => vec![
            ("health_check", json!({})),
            ("observe", json!({"query": "all entities", "limit": 10})),
            ("observe", json!({"query": "entities with Health < 30"})),
            ("experiment", json!({"type": "performance", "duration": 3000})),
            ("observe", json!({"query": "entities in combat"})),
            ("diagnostic_report", json!({"action": "generate"})),
            ("checkpoint", json!({"name": "debug_checkpoint"})),
        ],
        
        "performance_analysis" => vec![
            ("resource_metrics", json!({})),
            ("experiment", json!({"type": "performance", "systems": ["movement", "physics"]})),
            ("observe", json!({"query": "entities with high CPU impact"})),
            ("experiment", json!({"type": "memory", "duration": 5000})),
            ("observe", json!({"query": "entities with large memory footprint"})),
            ("diagnostic_report", json!({"action": "performance_summary"})),
        ],
        
        "stress_testing" => vec![
            ("health_check", json!({})),
            ("stress", json!({"type": "entity_spawn", "count": 100})),
            ("observe", json!({"query": "entity count"})),
            ("stress", json!({"type": "continuous_spawn", "intensity": 3})),
            ("experiment", json!({"type": "performance", "duration": 10000})),
            ("stress", json!({"type": "entity_despawn", "count": 50})),
            ("diagnostic_report", json!({"action": "stress_test_report"})),
        ],
        
        "cache_warming" => {
            let mut queries = Vec::new();
            // Warm up common queries
            for query in ["entities with Transform", "entities with Health", "entities with Inventory"] {
                queries.push(("observe", json!({"query": query})));
                queries.push(("observe", json!({"query": query}))); // Immediate repeat for cache hit
            }
            queries
        },
        
        _ => generate_realistic_queries(),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generate_realistic_queries() {
        let queries = generate_realistic_queries();
        assert!(!queries.is_empty(), "Should generate some queries");
        
        // Check that we have different types of queries
        let observe_count = queries.iter().filter(|(cmd, _)| cmd == "observe").count();
        let experiment_count = queries.iter().filter(|(cmd, _)| cmd == "experiment").count();
        
        assert!(observe_count > 0, "Should have observe queries");
        assert!(experiment_count > 0, "Should have experiment queries");
    }

    #[test]
    fn test_generate_complexity_queries() {
        let queries = generate_complexity_queries();
        assert!(!queries.is_empty(), "Should generate complexity queries");
        
        // Check that we have different complexity levels
        let simple_count = queries.iter()
            .filter(|(_, args)| args.get("complexity").and_then(|c| c.as_str()) == Some("simple"))
            .count();
        let complex_count = queries.iter()
            .filter(|(_, args)| args.get("complexity").and_then(|c| c.as_str()).map_or(false, |c| c.contains("high")))
            .count();
        
        assert!(simple_count > 0, "Should have simple queries");
        assert!(complex_count > 0, "Should have complex queries");
    }

    #[test]
    fn test_generate_time_based_queries() {
        let queries = generate_time_based_queries(30);
        assert!(!queries.is_empty(), "Should generate time-based queries");
        
        // Check that times are in ascending order
        for i in 1..queries.len() {
            assert!(queries[i].0 >= queries[i-1].0, "Times should be in ascending order");
        }
        
        // Check that all times are within the specified duration
        for (time, _, _) in &queries {
            assert!(*time < 30, "All times should be within duration");
        }
    }

    #[test]
    fn test_workload_patterns() {
        let patterns = ["debugging_session", "performance_analysis", "stress_testing", "cache_warming"];
        
        for pattern in patterns {
            let queries = generate_workload_pattern(pattern);
            assert!(!queries.is_empty(), "Pattern '{}' should generate queries", pattern);
        }
    }
}