--- argument-hint: "[format: vst3|au|aax|all] [strictness: 1-10]" description: "Run industry-standard pluginval validation tool on JUCE plugins with comprehensive tests and detailed reports" allowed-tools: Bash, Read, AskUserQuestion --- # Run Pluginval Validation This command runs pluginval, the industry-standard JUCE plugin validation tool, on your built plugins. It automatically detects plugin formats, runs comprehensive tests, and generates detailed validation reports. ## Instructions You are tasked with validating JUCE audio plugins using pluginval. Execute the following steps: ### 1. Check Pluginval Installation Verify pluginval is installed and available: ```bash if ! command -v pluginval &> /dev/null; then echo "❌ pluginval not found" echo "" echo "Install pluginval:" echo "" echo "macOS:" echo " brew install pluginval" echo "" echo "Or download from:" echo " https://github.com/Tracktion/pluginval/releases" echo "" echo "After installing, ensure pluginval is in your PATH" exit 1 fi # Verify version pluginval_version=$(pluginval --version 2>&1 | head -1 || echo "unknown") echo "✓ pluginval found: $pluginval_version" ``` ### 2. Detect Built Plugins Find all built plugin binaries: ```bash echo "" echo "🔍 Scanning for built plugins..." echo "" # Find VST3 plugins vst3_plugins=$(find build -name "*.vst3" -type d 2>/dev/null) vst3_count=$(echo "$vst3_plugins" | grep -c ".vst3" || echo "0") # Find AU plugins (macOS only) au_plugins=$(find build -name "*.component" -type d 2>/dev/null) au_count=$(echo "$au_plugins" | grep -c ".component" || echo "0") # Find AAX plugins aax_plugins=$(find build -name "*.aaxplugin" -type d 2>/dev/null) aax_count=$(echo "$aax_plugins" | grep -c ".aaxplugin" || echo "0") total_plugins=$((vst3_count + au_count + aax_count)) if [ $total_plugins -eq 0 ]; then echo "❌ No built plugins found in build/ directory" echo "" echo "Build your plugin first:" echo " /build-all-formats release" echo "" exit 1 fi echo "Found $total_plugins plugin(s):" [ $vst3_count -gt 0 ] && echo " - $vst3_count VST3" [ $au_count -gt 0 ] && echo " - $au_count AU" [ $aax_count -gt 0 ] && echo " - $aax_count AAX" ``` ### 3. Determine Validation Scope Use arguments or ask user which formats to validate: ```bash format_arg="${1:-all}" strictness="${2:-5}" if [ "$format_arg" != "all" ] && [ "$format_arg" != "vst3" ] && [ "$format_arg" != "au" ] && [ "$format_arg" != "aax" ]; then echo "Invalid format: $format_arg" echo "Valid options: vst3, au, aax, all" exit 1 fi echo "" echo "Validation Configuration:" echo " Format: $format_arg" echo " Strictness: $strictness/10 (higher = more thorough)" echo "" ``` ### 4. Configure Pluginval Options Set up validation parameters based on strictness: ```bash # Base options (always used) pluginval_opts=( "--verbose" "--validate-in-process" "--output-dir" "build/pluginval-reports" ) # Strictness-based timeout (higher strictness = longer timeout) timeout=$((strictness * 30)) # 30 seconds per level pluginval_opts+=("--timeout-ms" "$((timeout * 1000))") # Add strictness-specific tests if [ $strictness -ge 7 ]; then # Strict mode - enable all tests pluginval_opts+=("--strictness-level" "10") pluginval_opts+=("--random-seed" "42") # Reproducible random tests elif [ $strictness -ge 4 ]; then # Standard mode pluginval_opts+=("--strictness-level" "5") else # Quick validation pluginval_opts+=("--strictness-level" "1") pluginval_opts+=("--skip-gui-tests") # Skip GUI for speed fi # Create output directory mkdir -p build/pluginval-reports ``` ### 5. Run Validation on Each Plugin Execute pluginval for each detected plugin: ```bash echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "Starting Plugin Validation" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" passed=0 failed=0 skipped=0 validate_plugin() { local plugin_path="$1" local plugin_name=$(basename "$plugin_path") local format_type="$2" echo "──────────────────────────────────────────" echo "Validating: $plugin_name ($format_type)" echo "──────────────────────────────────────────" echo "" # Check if this format should be validated if [ "$format_arg" != "all" ] && [ "$format_arg" != "$format_type" ]; then echo "⊘ Skipped (format filter: $format_arg)" echo "" ((skipped++)) return fi # Run pluginval local report_file="build/pluginval-reports/${plugin_name%.${format_type}}_${format_type}_report.txt" if pluginval "${pluginval_opts[@]}" "$plugin_path" > "$report_file" 2>&1; then echo "✅ PASSED - All tests passed" ((passed++)) else echo "❌ FAILED - Validation issues detected" echo "" echo "Top issues:" grep -i "error\|fail\|warning" "$report_file" | head -10 || echo " (see full report)" ((failed++)) fi echo "" echo "Full report: $report_file" echo "" } # Validate VST3 plugins if [ -n "$vst3_plugins" ]; then while IFS= read -r plugin; do [ -n "$plugin" ] && validate_plugin "$plugin" "vst3" done <<< "$vst3_plugins" fi # Validate AU plugins if [ -n "$au_plugins" ]; then while IFS= read -r plugin; do [ -n "$plugin" ] && validate_plugin "$plugin" "au" done <<< "$au_plugins" fi # Validate AAX plugins if [ -n "$aax_plugins" ]; then while IFS= read -r plugin; do [ -n "$plugin" ] && validate_plugin "$plugin" "aax" done <<< "$aax_plugins" fi ``` ### 6. Generate Summary Report Create comprehensive validation summary: ```bash echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "Validation Summary" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" total_validated=$((passed + failed)) pass_rate=0 if [ $total_validated -gt 0 ]; then pass_rate=$(( (passed * 100) / total_validated )) fi echo "Results:" echo " ✅ Passed: $passed" echo " ❌ Failed: $failed" echo " ⊘ Skipped: $skipped" echo " ──────────────" echo " Total: $total_validated validated" echo "" echo "Pass Rate: $pass_rate%" echo "" # Create markdown summary report cat > build/pluginval-reports/SUMMARY.md << EOF # Pluginval Validation Summary **Date**: $(date '+%Y-%m-%d %H:%M:%S') **Strictness**: $strictness/10 **Format Filter**: $format_arg ## Results | Status | Count | |--------|-------| | ✅ Passed | $passed | | ❌ Failed | $failed | | ⊘ Skipped | $skipped | | **Total** | **$total_validated** | **Pass Rate**: $pass_rate% ## Validated Plugins ### VST3 $(if [ $vst3_count -gt 0 ]; then echo "$vst3_plugins" | while read plugin; do [ -n "$plugin" ] && echo "- $(basename "$plugin")" done else echo "None" fi) ### Audio Unit (AU) $(if [ $au_count -gt 0 ]; then echo "$au_plugins" | while read plugin; do [ -n "$plugin" ] && echo "- $(basename "$plugin")" done else echo "None" fi) ### AAX $(if [ $aax_count -gt 0 ]; then echo "$aax_plugins" | while read plugin; do [ -n "$plugin" ] && echo "- $(basename "$plugin")" done else echo "None" fi) ## Pluginval Configuration \`\`\` Strictness: $strictness/10 Timeout: ${timeout}s per plugin Random Seed: 42 (reproducible) \`\`\` ## Next Steps $(if [ $failed -gt 0 ]; then echo "### Failed Validation" echo "" echo "Review individual reports in \`build/pluginval-reports/\`" echo "" echo "Common issues:" echo "- Parameter ranges not normalized (0-1)" echo "- State save/load not working correctly" echo "- Audio glitches at buffer boundaries" echo "- Memory leaks or allocations in processBlock" echo "- Thread safety violations" echo "" echo "Get help:" echo "\`\`\`" echo "@daw-compatibility-engineer review pluginval failures and suggest fixes" echo "@technical-lead review plugin architecture for validation issues" echo "\`\`\`" else echo "### All Tests Passed! ✅" echo "" echo "Your plugin(s) passed validation. Next steps:" echo "" echo "1. Test in real DAWs: Load in Ableton, Logic, Pro Tools, etc." echo "2. Run stress tests: \`/stress-test\` (when available)" echo "3. Build release: \`/release-build\` (when available)" fi) --- Generated by JUCE Dev Team - Pluginval Validation EOF echo "📄 Summary report: build/pluginval-reports/SUMMARY.md" echo "" ``` ### 7. Display Detailed Failure Analysis If failures occurred, provide guidance: ```bash if [ $failed -gt 0 ]; then echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "Failure Analysis" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" echo "Common Pluginval Failures & Fixes:" echo "" echo "1. Parameter Range Issues" echo " ❌ Parameters not normalized to 0-1" echo " ✅ Fix: Use NormalisableRange and ensure getValue() returns 0-1" echo "" echo "2. State Save/Load" echo " ❌ getStateInformation/setStateInformation not working" echo " ✅ Fix: Implement proper XML/binary state serialization" echo "" echo "3. Audio Processing" echo " ❌ Glitches at buffer boundaries or sample rate changes" echo " ✅ Fix: Reset state in prepareToPlay, handle all buffer sizes" echo "" echo "4. Memory Issues" echo " ❌ Allocations in processBlock" echo " ✅ Fix: Pre-allocate in prepareToPlay, use /juce-best-practices" echo "" echo "5. Thread Safety" echo " ❌ UI calls from audio thread" echo " ✅ Fix: Use atomics/AsyncUpdater for thread communication" echo "" echo "Get Expert Help:" echo "" echo " @daw-compatibility-engineer analyze pluginval failures" echo " @technical-lead review architecture for validation issues" echo " @plugin-engineer fix state save/load implementation" echo "" fi ``` ### 8. Set Exit Code Return appropriate exit code for CI integration: ```bash if [ $failed -eq 0 ]; then echo "✅ All validations passed!" exit 0 else echo "❌ $failed plugin(s) failed validation" exit 1 fi ``` ## Strictness Levels Explained | Level | Duration | Tests | Use Case | |-------|----------|-------|----------| | 1-3 | Quick (1-3 min) | Basic | Rapid development iteration | | 4-6 | Standard (5-10 min) | Comprehensive | Pre-commit validation | | 7-9 | Thorough (15-30 min) | Extensive | Pre-release validation | | 10 | Extreme (30+ min) | All + stress | Final release validation | ## Pluginval Tests Pluginval validates: - **Parameter System**: Range, normalization, automation, smoothing - **State Management**: Save/restore, versioning, backward compatibility - **Audio Processing**: Buffer handling, sample rates, silence, DC offset - **Threading**: Realtime safety, no allocations, no locks - **MIDI**: Note on/off, CC, pitch bend, program changes - **Latency**: Reporting and compensation - **GUI**: Opening, resizing, closing without crashes - **Preset Management**: Loading, saving, initialization ## Common Issues & Solutions ### Issue: "Plugin failed to load" **Causes:** - Missing dependencies (JUCE modules, system libraries) - Incorrect bundle structure - Code signing issues (macOS) **Solutions:** ```bash # Check dependencies otool -L path/to/plugin.vst3/Contents/MacOS/plugin # macOS ldd path/to/plugin.so # Linux # Verify bundle structure find path/to/plugin.vst3 # Should match VST3 spec # Check code signature codesign -dv --verbose=4 path/to/plugin.vst3 # macOS ``` ### Issue: "Parameter range violations" **Fix:** ```cpp // WRONG auto param = std::make_unique( "gain", "Gain", 0.0f, 2.0f, 1.0f); // Range > 1.0! // CORRECT auto param = std::make_unique( "gain", "Gain", NormalisableRange(0.0f, 2.0f), // Internal range 1.0f, "dB", AudioParameterFloat::genericParameter, [](float value, int) { return String(value * 2.0f, 2) + " dB"; // Display conversion } ); ``` ### Issue: "State save/load failed" **Fix:** ```cpp void getStateInformation(MemoryBlock& destData) override { auto state = parameters.copyState(); std::unique_ptr xml(state.createXml()); copyXmlToBinary(*xml, destData); } void setStateInformation(const void* data, int sizeInBytes) override { std::unique_ptr xml(getXmlFromBinary(data, sizeInBytes)); if (xml && xml->hasTagName(parameters.state.getType())) { parameters.replaceState(ValueTree::fromXml(*xml)); } } ``` ### Issue: "Audio glitches detected" **Fix:** ```cpp void prepareToPlay(double sampleRate, int maxBlockSize) override { // Reset all DSP state dspProcessor.reset(); dspProcessor.prepare(sampleRate, maxBlockSize); // Clear buffers tempBuffer.clear(); } ``` ## CI/CD Integration Use in GitHub Actions: ```yaml - name: Validate Plugin run: /run-pluginval all 5 continue-on-error: false # Fail build if validation fails ``` ## Platform Notes ### macOS - AU validation requires macOS - Run `auval` separately for additional AU validation - Check Gatekeeper/notarization if plugins won't load ### Windows - VST3 validation on Windows requires the plugin binary be accessible - Check Visual C++ runtime dependencies ### Linux - VST3 only (AU and AAX not available) - Ensure display server running for GUI tests (`DISPLAY=:0`) ## Definition of Done - [ ] Pluginval installed and accessible - [ ] All built plugins detected - [ ] Validation executed for target formats - [ ] Reports generated in build/pluginval-reports/ - [ ] Summary markdown created - [ ] Issues flagged with troubleshooting guidance - [ ] Appropriate exit code returned - [ ] User provided with next steps ## Follow-Up Actions After validation: **If Passed:** ``` 1. Test in real DAWs manually 2. Run @qa-engineer for comprehensive DAW testing 3. Prepare for release: /release-build (when available) ``` **If Failed:** ``` 1. Review detailed reports in build/pluginval-reports/ 2. Consult @daw-compatibility-engineer for fixes 3. Apply /juce-best-practices for realtime safety 4. Fix issues and re-validate ``` ## Advanced Usage ### Validate Specific Plugin ```bash pluginval --validate-in-process path/to/MyPlugin.vst3 ``` ### Custom Strictness ```bash /run-pluginval vst3 10 # Maximum strictness, VST3 only ``` ### Skip GUI Tests Modify pluginval_opts to add: ```bash pluginval_opts+=("--skip-gui-tests") ``` ### Reproducible Random Tests Already included with `--random-seed 42` for strictness >= 7.