| # Machine Context β Verified System Info + ML Intern Workflow |
| > ML Intern (HuggingFace) writes code but CANNOT run it. |
| > Claude Code (local) CAN run code and fills this file with verified facts. |
| > |
| > **RULE:** Before ML Intern writes any platform-specific code, |
| > Claude Code fills this file and pushes it. ML Intern reads it first. |
|
|
| --- |
|
|
| ## SYSTEM INFO (Last verified: 2026-05-17) |
|
|
| **Machine:** MacBook M4, 24 GB RAM |
| **macOS:** macOS 15.x (Sequoia) |
| **Architecture:** arm64 (Apple Silicon) |
| **Xcode / CLT:** 2410+ |
| **Compiler:** `/usr/bin/cc` (Apple Clang) |
| **CMake:** 3.28 via pip (β οΈ system CMake 4.x is incompatible with JUCE 8 CMake scripts β do not use) |
|
|
| --- |
|
|
| ## KEY PATHS |
|
|
| | What | Path | |
| |---|---| |
| | Home directory | `/Volumes/T7 Shield/Users/Aditya/` (external T7 Shield SSD) | |
| | User VST3 plugins | `/Volumes/T7 Shield/Users/Aditya/Library/Audio/Plug-Ins/VST3/` | |
| | System VST3 plugins | `/Library/Audio/Plug-Ins/VST3/` | |
| | User AU plugins | `/Volumes/T7 Shield/Users/Aditya/Library/Audio/Plug-Ins/Components/` | |
| | System AU plugins | `/Library/Audio/Plug-Ins/Components/` | |
| | PluginBridge install | `~/Library/Audio/Plug-Ins/VST3/PluginBridge.vst3` | |
| | PluginBridge data | `~/Library/PluginBridge/` (safety_db.json, debug.log, blocklist.txt, scan.log) | |
| | Build dir | `/Volumes/T7 Shield/Users/Aditya/Downloads/AI MUSIC PRODUCTION/pluginbridge/build/` | |
| | Ableton log | `~/Library/Preferences/Ableton/Live 12.4/Log.txt` | |
| | Crash reports | `~/Library/Logs/DiagnosticReports/` | |
| |
| **Note:** `juce::File::getSpecialLocation(juce::File::userHomeDirectory)` returns the T7 Shield path, not `/Users/Aditya/`. |
| Both `/Library/` and `~/Library/` must be checked to find all installed plugins β most plugins install to both. |
| |
| --- |
| |
| ## CURRENT BUILD STATE (Last updated: 2026-05-17) |
| |
| **Last build:** 2026-05-17 (after folder move to AI MUSIC PRODUCTION) |
| **Result:** β
Clean β `[100%] Built target PluginBridge_VST3` |
| **Build command:** |
| ```bash |
| cd "/Volumes/T7 Shield/Users/Aditya/Downloads/AI MUSIC PRODUCTION/pluginbridge/build" |
| cmake --build . --target PluginBridge_VST3 -- -j4 |
| ``` |
| **Re-cmake needed after fresh clone:** |
| ```bash |
| cd "/Volumes/T7 Shield/Users/Aditya/Downloads/AI MUSIC PRODUCTION/pluginbridge/build" |
| /opt/homebrew/lib/python3.14/site-packages/cmake/data/bin/cmake .. -G 'Unix Makefiles' \ |
| -DCMAKE_C_COMPILER=/Library/Developer/CommandLineTools/usr/bin/clang \ |
| -DCMAKE_CXX_COMPILER=/Library/Developer/CommandLineTools/usr/bin/clang++ \ |
| -DCMAKE_OSX_SYSROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk |
| ``` |
|
|
| --- |
|
|
| ## RUNTIME STATE (Last verified: 2026-05-17) |
|
|
| **What happens when plugin loads (SAFE path):** |
| 1. Picker shows manufacturer tree, user selects plugin |
| 2. Safety DB checked β if Unknown, Helper --scan runs (waits for live Helper to exit first) |
| 3. Helper --load spawned for audio routing |
| 4. Plugin loaded in-process β `createEditor()` β embedded in PluginBridge editor window |
|
|
| **Verified working plugins (with full GUI):** |
| - FabFilter Pro-Q 4 (737 params, 761Γ405) |
| - Cradle The God Particle (11 params, 666Γ302) |
| - Little MicroShift (4 params, AU, 855Γ359) |
| - LIMITER / Mastering the Mix (13 params, 855Γ572) |
|
|
| **Audio-only (unsafe) plugins:** |
| - iZotope Ozone 12, Neutron 5, RX components β SIGABRT during scan |
| - ANIMATE, Gullfoss, ZENOLOGY, Cradle The God Particle AU version |
|
|
| **MCP server:** Running on port 16620, verified working |
| **Debug log:** `~/Library/PluginBridge/debug.log` β timestamped per-session |
|
|
| --- |
|
|
| ## VST3 BUNDLE STRUCTURE ON THIS MACHINE |
|
|
| Most third-party VST3 bundles do **NOT** include `moduleinfo.json`. Only `Info.plist` is present: |
|
|
| ``` |
| Plugin.vst3/Contents/ |
| βββ Info.plist β use this for metadata |
| βββ MacOS/ |
| βββ PkgInfo |
| βββ Resources/ |
| βββ _CodeSignature/ |
| ``` |
|
|
| **Verified Info.plist fields for manufacturer name:** |
|
|
| | Field | Example | Use | |
| |---|---|---| |
| | `NSHumanReadableCopyright` | `"Copyright Β© 2002-2025 FabFilter"` | Strip copyright prefix β `"FabFilter"` β
best source | |
| | `CFBundleGetInfoString` | `"FabFilter Pro-Q 4.02, Copyright Β© β¦"` | Before comma β first word β `"FabFilter"` β
| |
| | `CFBundleIdentifier` | `"com.fabfilter.Pro-Q.Vst3.4"` | Second segment capitalised β backup | |
| | `manufacturer` | `FabF` | 4-char code β useless for display | |
|
|
| **Known bad vendor values:** Pure version strings like `"16.7.33.200"` appear as `"vendor"` in some plugins' moduleinfo.json. Detect with `containsOnly("0123456789.")` and fall back to filename heuristic. |
|
|
| --- |
|
|
| ## API VERIFICATION TABLE |
|
|
| ### macOS Private APIs |
| | API | Works? | Notes | |
| |---|---|---| |
| | `CAContext contextWithCGSConnection:options:` | β | Compiles, runs, no error β but rendering never appears in Ableton's window. See FAILED-APPROACHES #10 | |
| | `CALayerHost` (remote layer client) | β | Same β layer attached, blank. Ableton process isolation blocks cross-process compositor sharing | |
| | `CGSMainConnectionID()` | β
compiles | Returns valid ID but CAContext still doesn't render cross-process | |
| | `NSMachBootstrapServer` | β deprecated | Not needed; use IPC socket to transfer contextId as string | |
| | `CARemoteLayerServer` | β wrong API | Does NOT share a hidden NSWindow. See FAILED-APPROACHES #10 | |
| | `posix_spawn` | β
| Reliable for spawning Helper from plugin process | |
| | `shm_open` / `mmap` | β
| Cross-process shared memory for audio β works reliably | |
| | `sem_open` | β
| Named semaphores for audio sync β works reliably | |
|
|
| ### JUCE 8 APIs |
| | API | Works? | Notes | |
| |---|---|---| |
| | `formatManager.addFormat(new juce::VST3PluginFormat())` | β
| Explicit registration required | |
| | `formatManager.addFormat(new juce::AudioUnitPluginFormat())` | β
| Explicit registration required | |
| | `addDefaultFormats()` | β | Deleted in JUCE 8 | |
| | `plugin->createEditor()` | β
| Message thread only | |
| | `juce::Thread::setCurrentThreadPriority()` | β | Removed β use native pthread | |
| | `getStringWidthFloat()` | β
| Use this; `getStringWidth()` deprecated | |
| | `getStringWidth()` | β | Deprecated β use `getStringWidthFloat()` | |
| | `juce::Rectangle::getTransformToFit()` | β | Does not exist | |
| | `juce::Array<CustomStruct>` initializer list | β | Not supported β use `std::vector<CustomStruct>` | |
| | `addChildComponent(comp)` | β
| Adds without forcing visible. Use instead of `addAndMakeVisible` when component starts hidden | |
| | `addAndMakeVisible(comp)` after `setVisible(false)` | β | `addAndMakeVisible` forces `setVisible(true)` β invisible comp sits on top eating mouse events | |
| | `juce::TreeView` + `TreeViewItem` | β
| Working; custom `LookAndFeel` needed for arrow rendering | |
| | `juce::File::getSpecialLocation(userHomeDirectory)` | β
| Returns T7 Shield path | |
|
|
| ### macOS Gotchas |
| | Issue | Notes | |
| |---|---| |
| | `MSG_NOSIGNAL` | Linux only β use `signal(SIGPIPE, SIG_IGN)` + `SO_NOSIGPIPE` | |
| | Two processes same `shm_open` name | Both crash β scanner must wait for live Helper to exit first | |
| | `NSApplicationActivationPolicyRegular` | Steals focus from DAW β use `Accessory` | |
| | `activateIgnoringOtherApps:YES` | Switches away from Ableton β use `orderFrontRegardless` | |
|
|
| --- |
|
|
| ## ABLETON LOG COMMANDS |
|
|
| ```bash |
| # PluginBridge debug log (live) |
| tail -f ~/Library/PluginBridge/debug.log |
| |
| # Crash reports |
| ls -lt ~/Library/Logs/DiagnosticReports/ | grep -i ableton | head -5 |
| |
| # Helper process |
| ps aux | grep PluginBridgeHelper |
| |
| # Blocklist |
| cat ~/Library/PluginBridge/blocklist.txt 2>/dev/null || echo "(empty)" |
| |
| # Safety DB |
| cat ~/Library/PluginBridge/safety_db.json | python3 -m json.tool | head -30 |
| |
| # Test helper manually |
| ~/Library/Audio/Plug-Ins/VST3/PluginBridge.vst3/Contents/Resources/PluginBridgeHelper.app/Contents/MacOS/PluginBridgeHelper --scan "/Library/Audio/Plug-Ins/VST3/FabFilter Pro-Q 4.vst3"; echo "EXIT: $?" |
| ``` |
|
|
| --- |
|
|
| ## ERROR REPORT TEMPLATE (Claude Code fills when something breaks) |
|
|
| ### Build Errors |
| ``` |
| [Full compiler error β not just the first line. Include file + line number + 5 lines context] |
| [What the code is trying to do at that line] |
| ``` |
|
|
| ### Runtime Errors |
| ``` |
| [Exact behavior: what user sees, what should happen instead] |
| [Relevant debug.log lines] |
| [Helper process state] |
| ``` |
|
|
| ### Claude Code's Analysis |
| ``` |
| [Root cause hypothesis] |
| [What was already tried] |
| [Verified API facts] |
| ``` |
|
|
| **DO NOT just report "it doesn't work." Always provide the above.** |
|
|
| --- |
|
|
| ## WHO DOES WHAT β READ THIS FIRST |
|
|
| ``` |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| β ML INTERN (HuggingFace) CLAUDE CODE (local Mac) β |
| β βββββββββββββββββββββββββ ββββββββββββββββββββββββββ β |
| β Writes code Runs code β |
| β Pushes to HF repo Pulls, builds, tests β |
| β Cannot run anything Fills this file with facts β |
| β Cannot see the Mac Is ML Intern's eyes + hands β |
| β Cannot check if it compiles Reports errors with full diag β |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| ``` |
|
|
| **The ML Intern has NO Mac access. It cannot:** |
| - Run a build to see if code compiles |
| - Check if an API exists in the local JUCE version |
| - Verify a macOS behavior |
| - See what's currently on screen or in the logs |
| - Know if a file was committed or is only local |
|
|
| **Claude Code is the ML Intern's eyes and hands on the Mac.** |
| Every question about "does X work on this machine?" must go through Claude Code. |
|
|
| --- |
|
|
| ## WORKFLOW |
|
|
| ``` |
| 1. ML Intern is given a task (e.g. "add audio analysis to MCP") |
| 2. If the task touches a new API or macOS behavior: |
| ML Intern asks Claude Code: "verify [API]. Fill MACHINE-CONTEXT.md" |
| Claude Code tests it, writes result here, pushes |
| ML Intern reads this file β writes code based on FACTS |
| 3. ML Intern writes ONLY the files needed for the task |
| (see SCOPE RULES below β do NOT touch other files) |
| 4. ML Intern pushes to HF repo |
| 5. Claude Code pulls, builds, tests |
| 6. If error: Claude Code fills ERROR REPORT section β full diagnostic |
| 7. ML Intern reads diagnostic β fixes based on FACTS only |
| 8. Repeat from step 4 until Claude Code confirms: β
working |
| ``` |
|
|
| --- |
|
|
| ## SCOPE RULES β CRITICAL |
|
|
| **The single most important rule:** |
| > Only modify files that are directly required for the task you were given. |
| > If a file is not listed in the task, do NOT touch it. |
|
|
| **What "touching" includes:** |
| - Rewriting the file |
| - Removing code from it |
| - Replacing its architecture |
| - Removing logging/debug calls |
|
|
| ### Concrete examples of scope violations that broke the project: |
|
|
| | Task given | Files that should be touched | Files that must NOT be touched | |
| |---|---|---| |
| | "Add AudioAnalyser to MCP" | `AudioAnalyser.h`, `McpServer.cpp/.h`, `PluginBridgeProcessor.h/.cpp` (add 3 lines) | `PluginBridgeEditor.mm`, `PluginPickerComponent.mm`, `CMakeLists.txt` | |
| | "Fix manufacturer names" | `PluginBridgeProcessor.cpp` (`getPluginManufacturer`) | Everything else | |
| | "Fix picker duplicates" | `PluginBridgeProcessor.cpp` (`getInstalledPluginFiles`) | Everything else | |
|
|
| **When in doubt: ask Claude Code which files to touch. Do not guess.** |
|
|
| --- |
|
|
| ## DO NOT REWRITE WORKING FILES |
|
|
| If a file is currently working (confirmed by Claude Code in RUNTIME STATE), do not rewrite it. |
| Work around it, extend it, or add to it. Never replace it. |
|
|
| Files that are locked unless explicitly told to change them: |
| - `Source/Plugin/PluginBridgeEditor.mm` β in-process GUI embedding, took 3 sprints to get right |
| - `Source/Plugin/PluginPickerComponent.mm` β Ableton-style TreeView picker |
| - `Source/Helper/HelperPluginHost.mm` β Helper audio routing + process lifecycle |
| - `Source/Plugin/HelperConnection.cpp` β IPC + shared memory protocol |
|
|
| --- |
|
|
| ## DO NOT REMOVE LOGGING |
|
|
| `PBLOG(...)` calls in the processor and editor are how Claude Code diagnoses runtime errors. |
| **Never remove PBLOG calls.** If you don't understand a log line, leave it. |
|
|
| --- |
|
|
| ## WHAT TO DO WHEN YOU ARE UNSURE |
|
|
| Stop. Write a message to Claude Code in this format: |
|
|
| ``` |
| QUESTION FOR CLAUDE CODE: |
| Task: [what you're trying to do] |
| Uncertainty: [what you don't know] |
| Files you plan to touch: [list] |
| Please verify and update MACHINE-CONTEXT.md before I proceed. |
| ``` |
|
|
| Claude Code will test it on the Mac and write the answer here. |
|
|
| --- |
|
|
| ## ARCHITECTURE β DO NOT CHANGE WITHOUT DISCUSSION |
|
|
| Current architecture is v0.5.2 β hybrid safety-scan: |
|
|
| ``` |
| Safe plugin β in-process load β createEditor() β GUI embedded in Ableton window β
|
| Unsafe plugin β Helper-only β audio routing only, no GUI (MCP still works) β
|
| ``` |
|
|
| This took 4 sprints to reach. The following are DEAD ENDS β do not revisit: |
|
|
| | Approach | Why it failed | Documented in | |
| |---|---|---| |
| | CAContext + CALayerHost | Ableton process isolation blocks cross-process compositor | FAILED-APPROACHES #10 | |
| | Floating window from Helper | Opens in separate Space in fullscreen Ableton | FAILED-APPROACHES #1 | |
| | PluginDirectoryScanner | Executes plugin code during scan β crashes | FAILED-APPROACHES #5 | |
| | Helper-only load (no in-process) | Plugin GUI never appears β no createEditor() called | This session (2026-05-17) | |
|
|
| --- |
|
|
| ## WORKFLOW (detailed steps) |
|
|
| ``` |
| 1. ML Intern wants to use [API/approach] |
| 2. ML Intern asks: "Claude Code β verify [API] works. Fill MACHINE-CONTEXT.md" |
| 3. Claude Code: writes test, runs it, fills verified API table, pushes |
| 4. ML Intern: reads this file, writes ONLY the required files |
| 5. ML Intern: pushes to HF repo |
| 6. Claude Code: pulls, builds, tests, updates BUILD STATE + RUNTIME STATE sections |
| 7. If error: Claude Code fills ERROR REPORT section with full diagnostic |
| 8. ML Intern reads diagnostic, writes fix based on FACTS |
| 9. Repeat until Claude Code confirms β
working |
| ``` |
|
|
| --- |
|
|
| ## NOTES FOR ML INTERN |
|
|
| - **Never assume an API works** β always ask Claude Code to verify first via this file |
| - **Never use deprecated macOS APIs** without Claude Code confirming they still function |
| - **ObjC++ (.mm) files** β only use if Claude Code confirms the ObjC API is available in current SDK |
| - **JUCE version matters** β APIs change between JUCE 7 and 8. Claude Code can check `JUCE/modules/` headers |
| - **Never push more than ONE conceptual change at a time** β if it breaks, you know exactly what caused it |
| - **If you don't know why something failed, DON'T GUESS** β ask Claude Code to investigate and fill the error report |
| - **CAContext/CALayerHost is a dead end** β already tried, documented in FAILED-APPROACHES #10. Do not revisit. |
| - **If you add a new .cpp or .mm file, tell Claude Code** β it needs to add it to CMakeLists.txt. You cannot do this yourself (you can't verify the build). |
|
|