| name | build-automation |
| description | Build coordination wrapper for VCV Rack modules using Makefile |
| allowed-tools | Bash, Read, Task |
| preconditions | Module must exist, RACK_DIR must be set |
build-automation Skill
Purpose: Orchestrates VCV Rack module builds using Makefile-based build system with comprehensive failure handling.
Integration Points
This skill is invoked by:
- module-workflow: After each stage completion (Stages 2-6) to build and verify changes
- module-improve: After implementation changes to rebuild with modifications
- module-lifecycle: During installation verification to ensure modules are buildable
This skill invokes:
- Makefile: VCV Rack's standard Makefile-based build system
- troubleshooter agent: Deep research agent (via Task tool) when user chooses "Investigate" option
Build Workflow
When invoked, the build-automation skill follows this workflow:
1. Input Validation
- Verify module name provided
- Check module directory exists:
test -d "modules/$MODULE_NAME" - Validate Makefile present:
test -f "modules/$MODULE_NAME/Makefile" - Validate RACK_DIR environment variable is set
2. Determine Build Target
Context-aware target selection:
- Stage 2 (Foundation): Always use clean build to verify compilation (
make clean && make) - Stages 3-6 (Implementation Stages): Full build with dist target (
make dist) - module-improve: Full build with dist target (
make dist) - User manual invocation: Ask if they want specific target (clean, all, dist, install)
3. Validate RACK_DIR
# Check RACK_DIR is set
if [[ -z "$RACK_DIR" ]]; then
echo "⚠️ RACK_DIR environment variable not set"
echo ""
echo "RACK_DIR must point to your VCV Rack SDK directory."
echo ""
echo "What would you like to do?"
echo "1. Run /setup to configure environment"
echo "2. Set RACK_DIR manually"
echo "3. Exit"
echo ""
read -p "Choose (1-3): " choice
case "$choice" in
1)
# Invoke system-setup skill
exit 2 # Signal to orchestrator to run /setup
;;
2)
echo "Enter RACK_DIR path:"
read -p "> " RACK_DIR_PATH
export RACK_DIR="$RACK_DIR_PATH"
;;
3)
exit 1
;;
esac
fi
# Verify RACK_DIR exists and contains SDK
if [[ ! -f "$RACK_DIR/include/rack.hpp" ]]; then
echo "⚠️ RACK_DIR doesn't contain VCV Rack SDK"
echo "Expected: $RACK_DIR/include/rack.hpp"
echo ""
echo "Run /setup to configure environment"
exit 1
fi
4. Platform Detection
# Determine platform for build target
PLATFORM=$(uname -s)
ARCH=$(uname -m)
case "$PLATFORM" in
Darwin)
if [[ "$ARCH" == "arm64" ]]; then
RACK_PLATFORM="mac-arm64"
else
RACK_PLATFORM="mac-x64"
fi
;;
Linux)
RACK_PLATFORM="linux-x64"
;;
MINGW*|MSYS*|CYGWIN*)
RACK_PLATFORM="win-x64"
;;
*)
echo "Unknown platform: $PLATFORM"
exit 1
;;
esac
echo "Building for platform: $RACK_PLATFORM"
5. Invoke Make
Execute build with appropriate target:
cd "modules/$MODULE_NAME"
# Create logs directory
mkdir -p "../../logs/$MODULE_NAME"
LOG_FILE="../../logs/$MODULE_NAME/build_$(date +%Y%m%d_%H%M%S).log"
# Run make with logging
make $BUILD_TARGET 2>&1 | tee "$LOG_FILE"
BUILD_EXIT_CODE=${PIPESTATUS[0]}
# Return to root directory
cd ../..
# Check exit code
if [[ $BUILD_EXIT_CODE -eq 0 ]]; then
echo "✓ Build successful"
else
echo "✗ Build failed (exit code: $BUILD_EXIT_CODE)"
fi
Build targets:
make clean- Clean build artifactsmakeormake all- Compile module (creates plugin.so/.dylib/.dll)make dist- Create distributable plugin archive (.vcvplugin)make install- Copy plugin to VCV Rack plugins directorymake clean all- Clean build from scratch
6. Monitor Build Output
- Capture stdout and stderr
- Display progress messages to user
- Watch for error indicators
- Track build duration
7. Capture Exit Code
Check build exit code:
- Exit 0: Build succeeded → proceed to Success Protocol
- Exit non-zero: Build failed → proceed to Failure Protocol
8. Log File Location
Always show log file path after build attempt:
Build log: logs/[ModuleName]/build_TIMESTAMP.log
User can review full build output from log file if needed.
Failure Protocol
When build fails (non-zero exit code), present this structured decision menu:
⚠️ Build failed
What would you like to do?
1. Investigate - Run troubleshooter agent to research the error (recommended)
2. Show me the build log - Display full build output for manual review
3. Show me the code - Open relevant source files where error occurred
4. Wait - I'll fix it manually and tell you to resume
5. Other
Choose (1-5): _
Option 1: Investigate (Recommended)
Purpose: Automated diagnosis using troubleshooter agent
Implementation:
Extract error from build log (last 50 lines or first error indicator)
Parse error for key information:
- Error message (exact text)
- File/line reference (if available)
- Error type (Make error, compilation, linker, etc.)
Invoke troubleshooter agent via Task tool:
Invoke troubleshooter agent to research this build error: Error: [extracted error message] Context: Building VCV Rack module "[ModuleName]" with Make VCV Rack SDK: [RACK_DIR path] Platform: [mac-arm64 | mac-x64 | linux-x64 | win-x64] File: [file path:line number if available] Please investigate using the graduated depth protocol and provide a structured report.Wait for troubleshooter report (structured markdown)
Display report to user with findings and recommended solution
Ask: "Should I apply this solution?" (Yes/No/Modify)
- Yes: Apply solution, then ask "Retry build now?"
- No: Return to failure menu
- Modify: Accept user modifications, then ask "Retry build now?"
IMPORTANT: NEVER auto-retry without explicit user confirmation.
Option 2: Show Build Log
Purpose: Display full build output for manual analysis
Implementation:
- Read log file:
logs/[ModuleName]/build_TIMESTAMP.log - Display last 100 lines (or full log if < 100 lines)
- Format for readability (preserve colors if possible)
- After display, re-present decision menu (iterative debugging)
Option 3: Show Code
Purpose: Display source files where error occurred
Implementation:
- Parse build error for file/line reference
- Make errors: Extract from Makefile references
- Compilation errors: Extract from compiler output (e.g., "src/ModuleName.cpp:42")
- Linker errors: Show relevant Makefile and header files
- Read relevant source file using Read tool
- Display file with context (±10 lines around error line if line number available)
- If no file reference parseable: "Error location not found in build output. Try Option 2 (Show build log)."
- After display, re-present decision menu (iterative debugging)
Option 4: Wait (Manual Fix)
Purpose: User will fix issue manually outside workflow
Implementation:
Display exit message:
Pausing workflow. Please fix the issue manually. When ready to retry the build, say: - "resume build" or "retry build" - Retry build with same target - "continue workflow" - Skip build and continue to next stage (not recommended) Build log: logs/[ModuleName]/build_TIMESTAMP.log Module directory: modules/[ModuleName]/Exit skill, return control to invoking skill/workflow
Await user continuation command
Option 5: Other
Purpose: Accept free-form user input for custom actions
Implementation:
- Prompt: "What would you like to do?"
- Accept free-text response
- Interpret request and act accordingly:
- Build-related: Execute custom build command
- Code-related: Read/display requested files
- Investigation: Perform custom research
- Continue: Proceed as requested
Success Protocol
When build succeeds (exit code 0), follow this workflow:
1. Verify Success
- Confirm build exit code 0
- Check that expected artifacts were created
- Extract output locations from build log
Expected artifacts by target:
make all:build/plugin.so(macOS),build/plugin.dll(Windows),build/plugin.so(Linux)make dist:dist/[ModuleName]-[version]-[platform].vcvplugin
2. Display Success Message
Use this template:
For Stage 2 (compilation verification):
✓ Build successful (compilation verified)
Module: [ModuleName]
Platform: [mac-arm64 | mac-x64 | linux-x64 | win-x64]
Output: build/plugin.[so|dylib|dll]
Build time: [duration]
Log: logs/[ModuleName]/build_TIMESTAMP.log
For full dist build (Stages 3-6, module-improve):
✓ Build successful
Module: [ModuleName]
Platform: [mac-arm64 | mac-x64 | linux-x64 | win-x64]
Plugin: dist/[ModuleName]-[version]-[platform].vcvplugin
Build time: [duration]
Log: logs/[ModuleName]/build_TIMESTAMP.log
Ready to install to VCV Rack.
3. Context-Aware Decision Menu
Present menu based on invoking context:
From Stage 2 (Foundation)
Foundation verified. What's next?
1. Continue to Stage 3 (Shell/Parameters)
2. Review generated code
3. Pause workflow
From Stage 3 (Shell)
Shell built successfully. What's next?
1. Continue to Stage 4 (DSP)
2. Test in VCV Rack now
3. Review parameter code
4. Pause workflow
From Stage 4 (DSP)
DSP built successfully. What's next?
1. Run manual tests (recommended)
2. Continue to Stage 5 (GUI)
3. Test in VCV Rack now
4. Pause workflow
From Stage 5 (GUI)
GUI built successfully. What's next?
1. Run manual tests (recommended)
2. Continue to Stage 6 (Validation)
3. Test in VCV Rack now
4. Pause workflow
From Stage 6 (Validation)
Module complete! What's next?
1. Test in VCV Rack (recommended)
2. Install to VCV Rack (/install-module)
3. Make improvements (/improve)
From module-improve
Update built successfully. What's next?
1. Test changes in VCV Rack
2. Continue improving
3. Done (commit changes)
4. Return to Invoking Skill
After user makes decision, return control to the skill that invoked build-automation:
- module-workflow: Returns to stage dispatcher to continue or pause
- module-improve: Returns to improvement workflow to continue or finalize
- Manual invocation: Exits skill, displays final status
IMPORTANT: Always return control to invoking skill after success. Don't continue workflow autonomously.
Integration Examples
Example 1: module-workflow Stage 2 (Foundation)
Scenario: foundation-agent completes, module-workflow needs to verify compilation
Invocation:
- Skill: module-workflow
- Stage: 2 (Foundation)
- Action: Invoke build-automation with clean build
Success Path:
- build-automation invokes:
make clean && makeinmodules/[ModuleName]/ - Build succeeds (compilation verified)
- Displays success message with artifact location
- Presents Stage 2 completion menu
- Returns to module-workflow with status: SUCCESS
Failure Path:
- Build fails (likely missing includes or API misuse)
- build-automation presents 4-option failure menu
- User chooses "Investigate"
- troubleshooter diagnoses: "Missing rack.hpp include"
- User confirms: "Apply solution"
- Source file updated to include rack.hpp
- User confirms: "Retry build"
- Build succeeds
- Returns to module-workflow with status: SUCCESS
Example 2: module-workflow Stages 3-6 (Implementation Stages)
Scenario: dsp-agent completes Phase 4.2, module-workflow needs full dist build
Invocation:
- Skill: module-workflow
- Stage: 4 (DSP), Phase: 2
- Action: Invoke build-automation with dist target
Success Path:
- build-automation invokes:
make distinmodules/[ModuleName]/ - Build succeeds, creates distributable plugin
- Displays success message with .vcvplugin location
- Presents Stage 4 completion menu: "Run manual tests / Continue to Stage 5 / Test in VCV Rack / Pause"
- Returns to module-workflow with status: SUCCESS
- module-workflow auto-invokes module-testing skill (if user chose "Run tests")
Failure Path:
- Build fails (compilation error in DSP code)
- Error: "modules/TestModule/src/TestModule.cpp:87: error: 'params' was not declared in this scope"
- build-automation presents 4-option failure menu
- User chooses "Show me the code"
- Displays TestModule.cpp lines 77-97 with error highlighted
- User sees issue: used 'params' instead of 'params[PARAM_ID]'
- User says: "Wait" (will fix manually)
- build-automation exits with: "When ready, say 'retry build'"
- User fixes code manually
- User says: "retry build"
- module-workflow re-invokes build-automation
- Build succeeds
- Returns to module-workflow with status: SUCCESS
Example 3: module-improve (Bug Fix or Feature Addition)
Scenario: module-improve applies bug fix to existing module, needs to rebuild
Invocation:
- Skill: module-improve
- Phase: 5 (Build & Test)
- Action: Invoke build-automation with dist target
Success Path:
- build-automation invokes:
make distinmodules/[ModuleName]/ - Build succeeds
- Displays success message
- Presents improvement completion menu: "Test changes / Continue improving / Done"
- Returns to module-improve with status: SUCCESS
- module-improve continues to Phase 6 (CHANGELOG update)
Failure Path:
Build fails (regression from bug fix)
Error: "modules/MyModule/src/MyModule.cpp:142: error: cannot convert 'int' to 'float' in assignment"
build-automation presents 4-option failure menu
User chooses "Investigate"
troubleshooter agent invoked:
Error: cannot convert 'int' to 'float' in assignment Context: Building VCV Rack module "MyModule" after bug fix File: src/MyModule.cpp:142troubleshooter returns report:
## Research Report: Type Conversion Error ### Problem Identified - **Error:** cannot convert 'int' to 'float' in assignment - **Context:** Line 142 attempts to assign integer result to float voltage output - **Root Cause:** Changed return type of helper function but didn't update assignment ### Research Path Level 0 (Quick Assessment) ### Confidence Assessment - **Confidence Level:** HIGH - **Reasoning:** Error message is explicit, solution straightforward ### Recommended Solution Cast result to float: `outputs[OUTPUT_ID].setVoltage(static_cast<float>(calculateValue()));` Or change calculateValue() return type to float. **Why This Works:** Explicit type conversion satisfies compiler type checker.User reviews report: "Apply solution"
Code updated with cast
User confirms: "Retry build"
Build succeeds
Returns to module-improve with status: SUCCESS
Error Handling Rules
Never Auto-Retry
CRITICAL: build-automation must NEVER automatically retry a failed build without explicit user decision. Always present failure menu and await user choice.
Bad (DON'T DO):
Build failed. Retrying with different flags...
Good (DO THIS):
⚠️ Build failed
What would you like to do?
1. Investigate...
Preserve Context Between Retries
When user says "retry build" after manual fixes:
- Use same build target as original build attempt
- Preserve same invoking context (Stage 2, module-improve, etc.)
- Return to same decision point after success/failure
Handle Missing Dependencies
If build fails with dependency errors (RACK_DIR not set, SDK not found):
- Display specific missing dependency
- Provide configuration command (e.g., "Run /setup to configure environment")
- After user configures, offer: "Retry build now?"
Parse Errors Intelligently
Extract meaningful error information for troubleshooter:
- Make errors: Configuration issues, missing files, path problems
- Compilation errors: Syntax, type mismatches, missing declarations, API misuse
- Linker errors: Missing symbols, library issues
- RACK_DIR errors: SDK not found, wrong version
Pass full context to troubleshooter, not just error message.
Performance Considerations
Build Duration Tracking
Always display build duration in success/failure messages:
- Start timer before invoking make
- Stop timer after exit
- Format as "Build time: 2m 34s" or "Build time: 45s"
Log File Management
- Build logs accumulate in
logs/[ModuleName]/ - Each build creates timestamped log:
build_20251112_143022.log - No automatic cleanup (user can manually delete old logs)
- Always reference most recent log file
Parallel Builds
Makefile can use parallel compilation:
# Use all available cores
make -j$(nproc)
# Or specify core count
make -j4
build-automation can pass -j flag to make for faster builds.
Common Build Issues
Issue: "RACK_DIR not set"
Cause: Environment variable missing
Solution: Run /setup to configure environment
Issue: "rack.hpp not found"
Cause: RACK_DIR points to wrong location or SDK not installed
Solution: Verify RACK_DIR points to VCV Rack SDK directory containing include/rack.hpp
Issue: "plugin.json not found"
Cause: Module directory structure incorrect
Solution: Verify plugin.json exists in module root
Issue: "Undefined symbols during linking"
Cause: Missing VCV Rack API symbols
Solution: Verify Makefile includes proper LDFLAGS from RACK_DIR
Issue: "Make command not found"
Cause: Make not installed
Solution: Install build tools (macOS: Xcode CLI tools, Linux: build-essential, Windows: MinGW)
VCV Rack-Specific Build Notes
Makefile Structure
VCV Rack modules use standardized Makefile:
# Standard Rack plugin Makefile
RACK_DIR ?= ../.. # Path to VCV Rack SDK
FLAGS +=
SOURCES += src/plugin.cpp
SOURCES += src/ModuleName.cpp
DISTRIBUTABLES += res
include $(RACK_DIR)/plugin.mk
Build Targets
make clean- Remove build artifactsmake dep- Build dependenciesmake- Compile module (default target)make dist- Create distributable .vcvplugin archivemake install- Copy to VCV Rack plugins directory
Platform-Specific Output
- macOS:
build/plugin.dylib - Linux:
build/plugin.so - Windows:
build/plugin.dll
Distributable Plugin
make dist creates platform-specific archive:
- Format:
dist/[ModuleName]-[version]-[platform].vcvplugin - Contents: ZIP archive containing plugin.json, plugin binary, and res/ folder
- Platform string:
mac-arm64,mac-x64,linux-x64,win-x64
Testing & Debugging
Manual Invocation
Skill can be invoked manually for testing:
Please invoke the build-automation skill to build TestModule.
Context: Manual test of build system.
Expected: Full dist build.
Simulated Failures
To test failure protocol:
- Introduce intentional syntax error in module source
- Invoke build-automation
- Verify 4-option menu appears
- Test each option (Investigate, Show log, Show code, Wait)
- Verify troubleshooter integration works
- Fix error and retry
- Verify success path works
Integration Testing
To test workflow integration:
- Start new module workflow:
/implement TestModule - Progress to Stage 2 (Foundation)
- Verify build-automation invoked with clean build
- Verify success returns to workflow
- Progress to Stage 3+ and verify dist build invoked
- Introduce failure and verify handling
- Verify workflow resumes after fix
Skill Status: Ready for integration Last Updated: 2025-11-12 Dependencies: Makefile (per module), RACK_DIR environment, .claude/agents/troubleshooter.md