livepilot 1.9.9 → 1.9.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +92 -0
- package/CODE_OF_CONDUCT.md +27 -0
- package/CONTRIBUTING.md +131 -0
- package/README.md +112 -387
- package/SECURITY.md +48 -0
- package/bin/livepilot.js +42 -2
- package/livepilot/.Codex-plugin/plugin.json +8 -0
- package/livepilot/.claude-plugin/plugin.json +1 -1
- package/livepilot/commands/beat.md +18 -6
- package/livepilot/commands/sounddesign.md +6 -5
- package/livepilot/skills/livepilot-core/SKILL.md +36 -13
- package/livepilot/skills/livepilot-core/references/overview.md +1 -1
- package/livepilot/skills/livepilot-release/SKILL.md +11 -8
- package/m4l_device/LivePilot_Analyzer.amxd +0 -0
- package/m4l_device/LivePilot_Analyzer.maxpat +378 -4
- package/m4l_device/capture_2026_04_07_192216.wav +0 -0
- package/m4l_device/livepilot_bridge.js +487 -184
- package/mcp_server/__init__.py +1 -1
- package/mcp_server/connection.py +40 -1
- package/mcp_server/curves.py +5 -1
- package/mcp_server/m4l_bridge.py +93 -26
- package/mcp_server/server.py +26 -31
- package/mcp_server/tools/_perception_engine.py +26 -3
- package/mcp_server/tools/_theory_engine.py +36 -5
- package/mcp_server/tools/analyzer.py +74 -18
- package/mcp_server/tools/arrangement.py +20 -5
- package/mcp_server/tools/automation.py +56 -1
- package/mcp_server/tools/devices.py +201 -13
- package/mcp_server/tools/generative.py +8 -1
- package/mcp_server/tools/harmony.py +16 -3
- package/mcp_server/tools/midi_io.py +22 -4
- package/mcp_server/tools/notes.py +4 -1
- package/mcp_server/tools/perception.py +27 -1
- package/mcp_server/tools/scenes.py +4 -1
- package/mcp_server/tools/theory.py +23 -8
- package/mcp_server/tools/transport.py +16 -6
- package/package.json +1 -1
- package/remote_script/LivePilot/__init__.py +1 -1
- package/remote_script/LivePilot/arrangement.py +25 -134
- package/remote_script/LivePilot/browser.py +19 -8
- package/remote_script/LivePilot/clip_automation.py +5 -4
- package/remote_script/LivePilot/clips.py +14 -6
- package/remote_script/LivePilot/devices.py +6 -3
- package/remote_script/LivePilot/diagnostics.py +81 -5
- package/remote_script/LivePilot/router.py +22 -0
- package/remote_script/LivePilot/server.py +41 -17
- package/remote_script/LivePilot/tracks.py +7 -2
- package/remote_script/LivePilot/transport.py +3 -3
- package/requirements.txt +3 -1
package/SECURITY.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|---------|-----------|
|
|
7
|
+
| 1.9.x | Yes |
|
|
8
|
+
| < 1.9 | No |
|
|
9
|
+
|
|
10
|
+
## Architecture Security Notes
|
|
11
|
+
|
|
12
|
+
LivePilot operates through three local interfaces:
|
|
13
|
+
|
|
14
|
+
- **TCP 9878** — MCP server ↔ Ableton Remote Script (localhost only)
|
|
15
|
+
- **UDP 9880** — M4L Analyzer → MCP server (localhost only)
|
|
16
|
+
- **OSC 9881** — MCP server → M4L Analyzer (localhost only)
|
|
17
|
+
|
|
18
|
+
All communication is **local only** — no ports are exposed to the network.
|
|
19
|
+
The MCP server runs via stdio transport (stdin/stdout) and does not open HTTP endpoints.
|
|
20
|
+
|
|
21
|
+
## Reporting a Vulnerability
|
|
22
|
+
|
|
23
|
+
If you discover a security vulnerability, please report it responsibly:
|
|
24
|
+
|
|
25
|
+
1. **Do not** open a public issue
|
|
26
|
+
2. Email **security@pilotstudio.dev** with:
|
|
27
|
+
- A description of the vulnerability
|
|
28
|
+
- Steps to reproduce
|
|
29
|
+
- Potential impact
|
|
30
|
+
3. You will receive an acknowledgment within 48 hours
|
|
31
|
+
4. We will work with you to understand and address the issue before any public disclosure
|
|
32
|
+
|
|
33
|
+
If you don't have access to the email, you can use [GitHub's private vulnerability reporting](https://github.com/dreamrec/LivePilot/security/advisories/new).
|
|
34
|
+
|
|
35
|
+
## Scope
|
|
36
|
+
|
|
37
|
+
The following are in scope:
|
|
38
|
+
|
|
39
|
+
- Remote code execution through MCP tool inputs
|
|
40
|
+
- Path traversal in file-handling tools (MIDI I/O, sample loading)
|
|
41
|
+
- Unauthorized access to Ableton session data
|
|
42
|
+
- Denial of service against the MCP server or Remote Script
|
|
43
|
+
|
|
44
|
+
The following are out of scope:
|
|
45
|
+
|
|
46
|
+
- Issues requiring physical access to the machine
|
|
47
|
+
- Issues in Ableton Live itself (report to Ableton)
|
|
48
|
+
- Issues in MCP clients (report to the client maintainer)
|
package/bin/livepilot.js
CHANGED
|
@@ -55,6 +55,31 @@ function venvPython() {
|
|
|
55
55
|
return path.join(VENV_DIR, isWin ? "Scripts" : "bin", isWin ? "python.exe" : "python3");
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
function findOtherLiveClient(host, port) {
|
|
59
|
+
try {
|
|
60
|
+
const out = execFileSync("lsof", ["-nP", `-iTCP:${port}`], {
|
|
61
|
+
encoding: "utf-8",
|
|
62
|
+
timeout: 3000,
|
|
63
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
64
|
+
});
|
|
65
|
+
const target = `->${host}:${port}`;
|
|
66
|
+
const lines = out.trim().split("\n").slice(1);
|
|
67
|
+
for (const line of lines) {
|
|
68
|
+
if (!line.includes(target) || !line.includes("(ESTABLISHED)")) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const parts = line.trim().split(/\s+/);
|
|
72
|
+
const pid = parseInt(parts[1], 10);
|
|
73
|
+
if (!Number.isNaN(pid) && pid !== process.pid) {
|
|
74
|
+
return `PID ${pid} (${parts[0]})`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch {
|
|
78
|
+
// best-effort only
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
58
83
|
// ---------------------------------------------------------------------------
|
|
59
84
|
// Virtual environment bootstrap
|
|
60
85
|
// ---------------------------------------------------------------------------
|
|
@@ -70,7 +95,7 @@ function ensureVenv(systemPython, prefixArgs) {
|
|
|
70
95
|
// Check if venv already exists and has our deps
|
|
71
96
|
if (fs.existsSync(venvPy)) {
|
|
72
97
|
try {
|
|
73
|
-
execFileSync(venvPy, ["-c", "import fastmcp; import midiutil; import pretty_midi; import numpy; import pyloudnorm; import soundfile; import scipy"], {
|
|
98
|
+
execFileSync(venvPy, ["-c", "import fastmcp; import midiutil; import pretty_midi; import numpy; import pyloudnorm; import soundfile; import scipy; import mutagen"], {
|
|
74
99
|
encoding: "utf-8",
|
|
75
100
|
timeout: 10000,
|
|
76
101
|
stdio: "pipe",
|
|
@@ -133,6 +158,13 @@ function checkStatus() {
|
|
|
133
158
|
if (resp.ok === true && resp.result && resp.result.pong) {
|
|
134
159
|
console.log(" Ableton Live: connected on %s:%d", HOST, PORT);
|
|
135
160
|
ok = true;
|
|
161
|
+
} else if (resp.ok === false && resp.error && resp.error.code === "STATE_ERROR") {
|
|
162
|
+
console.log(
|
|
163
|
+
" Ableton Live: reachable, but another LivePilot client is already connected"
|
|
164
|
+
);
|
|
165
|
+
if (resp.error.message) {
|
|
166
|
+
console.log(" Detail: %s", resp.error.message);
|
|
167
|
+
}
|
|
136
168
|
} else {
|
|
137
169
|
console.log(" Ableton Live: unexpected response:", JSON.stringify(resp));
|
|
138
170
|
}
|
|
@@ -145,7 +177,15 @@ function checkStatus() {
|
|
|
145
177
|
});
|
|
146
178
|
|
|
147
179
|
sock.on("timeout", () => {
|
|
148
|
-
|
|
180
|
+
const otherClient = findOtherLiveClient(HOST, PORT);
|
|
181
|
+
if (otherClient) {
|
|
182
|
+
console.log(
|
|
183
|
+
" Ableton Live: reachable, but another LivePilot client appears connected (%s)",
|
|
184
|
+
otherClient
|
|
185
|
+
);
|
|
186
|
+
} else {
|
|
187
|
+
console.log(" Ableton Live: connection timed out");
|
|
188
|
+
}
|
|
149
189
|
sock.destroy();
|
|
150
190
|
resolve(false);
|
|
151
191
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "livepilot",
|
|
3
|
+
"version": "1.9.12",
|
|
4
|
+
"description": "Agentic production system for Ableton Live 12 — 178 tools, 17 domains, device atlas, spectral perception, technique memory, neo-Riemannian harmony, Euclidean rhythm, species counterpoint, MIDI I/O",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Pilot Studio"
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livepilot",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.12",
|
|
4
4
|
"description": "Agentic production system for Ableton Live 12 — 178 tools, 17 domains, device atlas, spectral perception, technique memory, neo-Riemannian harmony, Euclidean rhythm, species counterpoint, MIDI I/O",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Pilot Studio"
|
|
@@ -8,11 +8,23 @@ Guide the user through creating a beat from scratch. Follow these steps:
|
|
|
8
8
|
1. **Ask about the vibe** — genre, tempo range, mood, reference tracks
|
|
9
9
|
2. **Set up the session** — `set_tempo`, create tracks for drums/bass/harmony/melody with `create_midi_track`, name and color them
|
|
10
10
|
3. **Load instruments** — use `find_and_load_device` for appropriate instruments per track
|
|
11
|
-
4. **
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
4. **Verify device health** — after loading, run `get_device_info` on each loaded device. A `parameter_count` of 0 or 1 on AU/VST plugins means the plugin failed to initialize (dead plugin). If detected:
|
|
12
|
+
- Delete the dead plugin with `delete_device`
|
|
13
|
+
- Replace with a native Ableton alternative (e.g., Saturator instead of tape plugins, Operator instead of failed FM synths)
|
|
14
|
+
- Run `get_session_diagnostics` for any other issues (armed tracks, missing instruments)
|
|
15
|
+
- Inform the user which plugin failed and what replacement was used
|
|
16
|
+
5. **Program drums first** — create a clip, add kick/snare/hat patterns with `add_notes`
|
|
17
|
+
6. **Add bass** — create clip, program a bassline that locks with the kick
|
|
18
|
+
7. **Add harmony** — chords or pads that set the mood
|
|
19
|
+
8. **Add melody** — top-line or lead element
|
|
20
|
+
9. **Mix** — balance levels with `set_track_volume` and `set_track_pan`
|
|
21
|
+
10. **Pitch & tuning audit** — MANDATORY before firing. Run on every melodic track (skip drums):
|
|
22
|
+
- `identify_scale` on each track — verify all tracks agree on the same tonal center
|
|
23
|
+
- `analyze_harmony` on chordal tracks (pads, keys) — verify chord quality (no accidental augmented/diminished chords unless intentional)
|
|
24
|
+
- `detect_theory_issues` with `strict=true` on each track — check for out-of-key notes, parallel fifths, voice crossing
|
|
25
|
+
- **Interpret results against the intended scale**, not just C major. The analyzer only knows 7 standard modes — exotic scales (Hijaz, Hungarian minor, whole tone, etc.) will produce false "out of key" warnings. Cross-reference flagged notes against the intended scale manually.
|
|
26
|
+
- Report a clear tuning table to the user: which tracks are clean, which have issues, what the issues are
|
|
27
|
+
- Fix wrong notes with `modify_notes` before proceeding
|
|
28
|
+
11. **Fire the scene** to listen, iterate based on feedback
|
|
17
29
|
|
|
18
30
|
Use the livepilot-core skill for all tool calls. Verify after each step. Keep the user informed of what you're doing and why.
|
|
@@ -7,10 +7,11 @@ Guide the user through designing a sound. Follow these steps:
|
|
|
7
7
|
|
|
8
8
|
1. **Ask about the target sound** — what character? (warm pad, aggressive bass, shimmering lead, atmospheric texture, etc.)
|
|
9
9
|
2. **Choose an instrument** — pick the right synth for the job, load it with `find_and_load_device`
|
|
10
|
-
3. **
|
|
11
|
-
4. **
|
|
12
|
-
5. **
|
|
13
|
-
6. **
|
|
14
|
-
7. **
|
|
10
|
+
3. **Verify device loaded** — `get_device_info` to confirm plugin initialized (AU/VST with `parameter_count` <= 1 = dead plugin — delete and replace with native alternative)
|
|
11
|
+
4. **Get parameters** — `get_device_parameters` to see what's available
|
|
12
|
+
5. **Shape the sound** — `set_device_parameter` or `batch_set_parameters` to dial in the character
|
|
13
|
+
6. **Add effects** — load effects (reverb, delay, chorus, distortion, etc.) and tweak their parameters
|
|
14
|
+
7. **Create a test pattern** — `create_clip` + `add_notes` with a simple pattern to audition
|
|
15
|
+
8. **Fire the clip** to listen, iterate based on feedback
|
|
15
16
|
|
|
16
17
|
Explain what each parameter does as you adjust it. Use `undo` liberally if something sounds wrong.
|
|
@@ -26,6 +26,9 @@ These layers sit on top of 178 deterministic tools across 17 domains: transport,
|
|
|
26
26
|
9. **Tempo range 20-999 BPM** — validated before sending to Ableton
|
|
27
27
|
10. **Always name your tracks and clips** — organization is part of the creative process
|
|
28
28
|
11. **Respect tool speed tiers** — see below. Never call heavy tools without user consent.
|
|
29
|
+
12. **ALWAYS report tool errors to the user** — if any tool call returns an error, immediately tell the user what failed, why, and what workaround you're using. Never silently swallow errors or switch strategies without explaining. Include: the tool name, the error message, and your fallback plan. This applies to all tool errors including missing M4L analyzer, dead plugins (`parameter_count` <= 1 on AU/VST), connection timeouts, and invalid parameter responses.
|
|
30
|
+
13. **Verify plugin health after loading** — v1.9.11+ tools now return `health_flags`, `mcp_sound_design_ready`, and `plugin_host_status` on device load and info calls. Check `mcp_sound_design_ready` — if `false`, check `health_flags` for: `opaque_or_failed_plugin` (dead or untweakable AU/VST), `sample_dependent` (granular synth needing source audio). On failure: delete with `delete_device`, replace with native Ableton alternative, report to user.
|
|
31
|
+
14. **Use `C hijaz` for Hijaz/Phrygian Dominant keys** — v1.9.11+ theory tools accept `hijaz` as a key alias. Use `key="C hijaz"` in `detect_theory_issues`, `analyze_harmony`, etc. to avoid false out-of-key warnings on Hijaz, manele, or Middle Eastern scales.
|
|
29
32
|
|
|
30
33
|
## Tool Speed Tiers
|
|
31
34
|
|
|
@@ -88,6 +91,13 @@ Never skip levels. The user's question determines the entry point, but always st
|
|
|
88
91
|
2. **For Drum Racks: `get_rack_chains`** — confirm chains exist (an empty Drum Rack = silence). You need named chains like "Bass Drum", "Snare", etc.
|
|
89
92
|
3. **For synths: `get_device_parameters`** — confirm `Volume`/`Gain` parameter is not 0. Check oscillators are on.
|
|
90
93
|
4. **For effects: check `Dry/Wet` and `Drive`/key params** — a Saturator with Drive=0 or a Reverb with Dry/Wet=0 does nothing.
|
|
94
|
+
5. **For AU/VST plugins: `get_device_info`** — if `parameter_count` <= 1 and `class_name` contains "PluginDevice", the plugin is dead. Delete and replace with native alternative. Report the failure.
|
|
95
|
+
6. **CRITICAL — Sample-dependent instruments produce silence without source material.** These plugins load "successfully" (many parameters) but output nothing until a sample/audio source is provided. Since MCP tools CANNOT load samples into third-party plugin UIs, **NEVER use these as standalone instruments**:
|
|
96
|
+
- **Granular synths:** iDensity, Tardigrain, Koala Sampler, Burns Audio Granular
|
|
97
|
+
- **Samplers without presets:** bare Simpler, bare Sampler (always load a preset, never the empty shell)
|
|
98
|
+
- **Sample players:** AudioLayer, sEGments (need user to load samples via plugin GUI)
|
|
99
|
+
- **Instead use:** Wavetable, Operator, Drift, Analog, Meld, Collision, Tension — these are self-contained synthesizers that produce sound immediately from MIDI input alone.
|
|
100
|
+
- **If granular textures are needed:** Use Wavetable with aggressive wavetable position modulation, or Operator with FM feedback and short envelopes, or load a Simpler/Sampler **preset** (not the bare instrument) from the Sounds browser.
|
|
91
101
|
|
|
92
102
|
### After programming notes:
|
|
93
103
|
1. **`fire_clip` or `fire_scene`** — always listen. If the track has notes but the instrument has no samples/chains, you're playing silence.
|
|
@@ -100,11 +110,15 @@ Never skip levels. The user's question determines the entry point, but always st
|
|
|
100
110
|
|
|
101
111
|
### Quick health check pattern:
|
|
102
112
|
```
|
|
103
|
-
1.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
113
|
+
1. get_device_info(track, device) → class_name? parameter_count?
|
|
114
|
+
- PluginDevice with param_count<=1? → DEAD PLUGIN. Delete + replace.
|
|
115
|
+
- Is it a sample-dependent plugin? → SILENT. Replace with self-contained synth.
|
|
116
|
+
2. get_track_info(track_index) → has devices? has clips?
|
|
117
|
+
3. get_rack_chains (if Drum Rack) → has chains with samples?
|
|
118
|
+
4. get_device_parameters → volume > 0? key params set?
|
|
119
|
+
5. Check mixer.volume > 0 → track is audible?
|
|
120
|
+
6. fire_clip / fire_scene → sound comes out?
|
|
121
|
+
7. REPORT any issues to the user → never silently work around failures.
|
|
108
122
|
```
|
|
109
123
|
|
|
110
124
|
### Red flags (things that produce silence):
|
|
@@ -116,14 +130,16 @@ Never skip levels. The user's question determines the entry point, but always st
|
|
|
116
130
|
- Master volume at 0
|
|
117
131
|
- MIDI track with no instrument loaded
|
|
118
132
|
- Notes programmed but clip not fired
|
|
133
|
+
- **Dead AU/VST plugin** — `parameter_count` <= 1 on a PluginDevice (plugin shell loaded, DSP engine crashed)
|
|
134
|
+
- **Sample-dependent plugin with no sample** — granular synths, bare samplers, and sample players load "successfully" with many parameters but produce zero audio without source material. The sneakiest silent failure because `get_device_info` looks healthy.
|
|
119
135
|
|
|
120
136
|
## Tool Domains (178 total)
|
|
121
137
|
|
|
122
138
|
### Transport (12)
|
|
123
139
|
`get_session_info` · `set_tempo` · `set_time_signature` · `start_playback` · `stop_playback` · `continue_playback` · `toggle_metronome` · `set_session_loop` · `undo` · `redo` · `get_recent_actions` · `get_session_diagnostics`
|
|
124
140
|
|
|
125
|
-
### Tracks (
|
|
126
|
-
`get_track_info` · `create_midi_track` · `create_audio_track` · `create_return_track` · `delete_track` · `duplicate_track` · `set_track_name` · `set_track_color` · `set_track_mute` · `set_track_solo` · `set_track_arm` · `stop_track_clips` · `set_group_fold` · `set_track_input_monitoring`
|
|
141
|
+
### Tracks (17)
|
|
142
|
+
`get_track_info` · `create_midi_track` · `create_audio_track` · `create_return_track` · `delete_track` · `duplicate_track` · `set_track_name` · `set_track_color` · `set_track_mute` · `set_track_solo` · `set_track_arm` · `stop_track_clips` · `set_group_fold` · `set_track_input_monitoring` · `freeze_track` · `flatten_track` · `get_freeze_status`
|
|
127
143
|
|
|
128
144
|
### Clips (11)
|
|
129
145
|
`get_clip_info` · `create_clip` · `delete_clip` · `duplicate_clip` · `fire_clip` · `stop_clip` · `set_clip_name` · `set_clip_color` · `set_clip_loop` · `set_clip_launch` · `set_clip_warp_mode`
|
|
@@ -131,11 +147,11 @@ Never skip levels. The user's question determines the entry point, but always st
|
|
|
131
147
|
### Notes (8)
|
|
132
148
|
`add_notes` · `get_notes` · `remove_notes` · `remove_notes_by_id` · `modify_notes` · `duplicate_notes` · `transpose_notes` · `quantize_clip`
|
|
133
149
|
|
|
134
|
-
### Devices (
|
|
135
|
-
`get_device_info` · `get_device_parameters` · `set_device_parameter` · `batch_set_parameters` · `toggle_device` · `delete_device` · `load_device_by_uri` · `find_and_load_device` · `set_simpler_playback_mode` · `get_rack_chains` · `set_chain_volume` · `get_device_presets`
|
|
150
|
+
### Devices (15)
|
|
151
|
+
`get_device_info` · `get_device_parameters` · `set_device_parameter` · `batch_set_parameters` · `toggle_device` · `delete_device` · `load_device_by_uri` · `find_and_load_device` · `set_simpler_playback_mode` · `get_rack_chains` · `set_chain_volume` · `get_device_presets` · `get_plugin_parameters` · `map_plugin_parameter` · `get_plugin_presets`
|
|
136
152
|
|
|
137
|
-
### Scenes (
|
|
138
|
-
`get_scenes_info` · `create_scene` · `delete_scene` · `duplicate_scene` · `fire_scene` · `set_scene_name` · `set_scene_color` · `set_scene_tempo`
|
|
153
|
+
### Scenes (12)
|
|
154
|
+
`get_scenes_info` · `create_scene` · `delete_scene` · `duplicate_scene` · `fire_scene` · `set_scene_name` · `set_scene_color` · `set_scene_tempo` · `get_scene_matrix` · `fire_scene_clips` · `stop_all_clips` · `get_playing_clips`
|
|
139
155
|
|
|
140
156
|
### Mixing (11)
|
|
141
157
|
`set_track_volume` · `set_track_pan` · `set_track_send` · `get_return_tracks` · `get_master_track` · `set_master_volume` · `get_track_routing` · `set_track_routing` · `get_track_meters` · `get_master_meters` · `get_mix_snapshot`
|
|
@@ -246,8 +262,15 @@ MIDI file import/export — works with standard .mid files on disk.
|
|
|
246
262
|
6. `create_clip` — create clips on each track (4 beats = 1 bar at 4/4)
|
|
247
263
|
7. `add_notes` — program MIDI patterns. Each note needs `pitch`, `start_time`, `duration`
|
|
248
264
|
8. **HEALTH CHECK per track:** `get_track_info` → confirm device loaded, mixer volume > 0, not muted
|
|
249
|
-
9.
|
|
250
|
-
|
|
265
|
+
9. **PITCH & TUNING AUDIT (MANDATORY before firing):**
|
|
266
|
+
- `identify_scale` on every melodic track — verify all tracks share the same tonal center
|
|
267
|
+
- `analyze_harmony` on chordal tracks — verify chord quality (no accidental augmented/diminished)
|
|
268
|
+
- `detect_theory_issues` with `strict=true` — check out-of-key notes, parallel fifths, voice crossing
|
|
269
|
+
- **Interpret against intended scale:** The analyzer only knows 7 standard modes. Exotic scales (Hijaz, Hungarian minor, whole tone, etc.) produce false "out of key" warnings. Cross-reference flagged pitches against the intended scale manually.
|
|
270
|
+
- Report a clear tuning table to the user before proceeding
|
|
271
|
+
- Fix wrong notes with `modify_notes` before firing
|
|
272
|
+
10. `fire_scene` or `fire_clip` — listen to your work
|
|
273
|
+
11. Iterate: `get_notes` → `modify_notes` / `transpose_notes` → listen again
|
|
251
274
|
|
|
252
275
|
## Workflow: Sound Design
|
|
253
276
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# LivePilot v1.9.
|
|
1
|
+
# LivePilot v1.9.12 — Architecture & Tool Reference
|
|
2
2
|
|
|
3
3
|
Agentic production system for Ableton Live 12. 178 tools across 17 domains. Device atlas (280+ devices), spectral perception (M4L analyzer), technique memory, automation intelligence (16 curve types, 15 recipes), music theory (Krumhansl-Schmuckler, species counterpoint), generative algorithms (Euclidean rhythm, tintinnabuli, phase shift, additive process), neo-Riemannian harmony (PRL transforms, Tonnetz), MIDI file I/O.
|
|
4
4
|
|
|
@@ -12,7 +12,8 @@ Run this checklist EVERY time the user says "update everything", "push", "releas
|
|
|
12
12
|
- [ ] `package.json` → `"version"`
|
|
13
13
|
- [ ] `package-lock.json` → `"version"` (run `npm install --package-lock-only` if stale)
|
|
14
14
|
- [ ] `server.json` → `"version"` (TWO locations: top-level and package)
|
|
15
|
-
- [ ] `livepilot/.
|
|
15
|
+
- [ ] `livepilot/.Codex-plugin/plugin.json` → `"version"` (primary Codex manifest)
|
|
16
|
+
- [ ] `livepilot/.claude-plugin/plugin.json` → `"version"` (must match Codex plugin)
|
|
16
17
|
- [ ] `.claude-plugin/marketplace.json` → `"version"` in plugins array
|
|
17
18
|
- [ ] `mcp_server/__init__.py` → `__version__`
|
|
18
19
|
- [ ] `remote_script/LivePilot/__init__.py` → `__version__` (log message auto-uses it)
|
|
@@ -23,29 +24,30 @@ Run this checklist EVERY time the user says "update everything", "push", "releas
|
|
|
23
24
|
- [ ] `docs/social-banner.html` → version display
|
|
24
25
|
- [ ] `docs/M4L_BRIDGE.md` → ping response example
|
|
25
26
|
|
|
26
|
-
**How to check:** `grep -rn "1\.[0-9]\.[0-9]" package.json server.json livepilot/.claude-plugin/plugin.json .claude-plugin/marketplace.json mcp_server/__init__.py remote_script/LivePilot/__init__.py m4l_device/livepilot_bridge.js CHANGELOG.md CLAUDE.md livepilot/skills/livepilot-core/references/overview.md docs/social-banner.html docs/M4L_BRIDGE.md`
|
|
27
|
+
**How to check:** `grep -rn "1\.[0-9]\.[0-9]" package.json server.json livepilot/.Codex-plugin/plugin.json livepilot/.claude-plugin/plugin.json .claude-plugin/marketplace.json mcp_server/__init__.py remote_script/LivePilot/__init__.py m4l_device/livepilot_bridge.js CHANGELOG.md CLAUDE.md livepilot/skills/livepilot-core/references/overview.md docs/social-banner.html docs/M4L_BRIDGE.md`
|
|
27
28
|
|
|
28
29
|
## 2. Tool Count (must ALL match)
|
|
29
30
|
|
|
30
31
|
Current: **178 tools across 17 domains**.
|
|
31
|
-
Core (no M4L): **
|
|
32
|
+
Core (no M4L): **149**. Analyzer (M4L): **29**. Perception (offline): **4**.
|
|
32
33
|
|
|
33
34
|
Verify: `grep -rc "@mcp.tool" mcp_server/tools/ | grep -v ":0" | awk -F: '{sum+=$2} END{print sum}'`
|
|
34
35
|
|
|
35
36
|
Files that reference tool count:
|
|
36
|
-
- [ ] `README.md` — header, PERCEPTION section ("
|
|
37
|
+
- [ ] `README.md` — header, PERCEPTION section ("149 core...29 analyzer"), Analyzer table header "(29)", Perception table header "(4)"
|
|
37
38
|
- [ ] `package.json` → `"description"` (178 tools, 17 domains)
|
|
38
39
|
- [ ] `server.json` → `"description"`
|
|
39
|
-
- [ ] `livepilot/.
|
|
40
|
+
- [ ] `livepilot/.Codex-plugin/plugin.json` → `"description"` (primary Codex manifest)
|
|
41
|
+
- [ ] `livepilot/.claude-plugin/plugin.json` → `"description"` (must match Codex plugin)
|
|
40
42
|
- [ ] `.claude-plugin/marketplace.json` → `"description"`
|
|
41
43
|
- [ ] `CLAUDE.md` → "178 tools across 17 domains"
|
|
42
44
|
- [ ] `livepilot/skills/livepilot-core/SKILL.md` — "178 tools across 17 domains", Analyzer (29), Perception (4)
|
|
43
45
|
- [ ] `livepilot/skills/livepilot-core/references/overview.md` — "178 tools across 17 domains"
|
|
44
46
|
- [ ] `docs/manual/index.md` — domain table: Analyzer (29), Perception (4)
|
|
45
|
-
- [ ] `docs/manual/getting-started.md` — "
|
|
47
|
+
- [ ] `docs/manual/getting-started.md` — "149 core tools...29 analyzer"
|
|
46
48
|
- [ ] `docs/manual/tool-reference.md` — all domains present with correct counts
|
|
47
49
|
- [ ] `docs/TOOL_REFERENCE.md` — all domains present
|
|
48
|
-
- [ ] `docs/M4L_BRIDGE.md` — "
|
|
50
|
+
- [ ] `docs/M4L_BRIDGE.md` — "149 core tools...29 analyzer"
|
|
49
51
|
- [ ] `docs/social-banner.html`
|
|
50
52
|
- [ ] `mcp_server/tools/analyzer.py` → module docstring
|
|
51
53
|
- [ ] `tests/test_tools_contract.py` → expected total count
|
|
@@ -75,6 +77,7 @@ Current: **17 domains**: transport, tracks, clips, notes, devices, scenes, mixin
|
|
|
75
77
|
|
|
76
78
|
- [ ] `~/.claude/plugins/cache/dreamrec-LivePilot/livepilot/` has current version directory
|
|
77
79
|
- [ ] Old version directories removed
|
|
80
|
+
- [ ] `~/.claude/plugins/installed_plugins.json` → `livepilot@dreamrec-LivePilot` entry: update `version`, `installPath`, `gitCommitSha`, `lastUpdated`
|
|
78
81
|
|
|
79
82
|
## 7. Social/Promotional Assets
|
|
80
83
|
|
|
@@ -105,5 +108,5 @@ Current: **17 domains**: transport, tracks, clips, notes, devices, scenes, mixin
|
|
|
105
108
|
## Quick Verify Command
|
|
106
109
|
|
|
107
110
|
```bash
|
|
108
|
-
echo "=== Versions ===" && grep -h '"version"' package.json server.json livepilot/.claude-plugin/plugin.json .claude-plugin/marketplace.json | head -
|
|
111
|
+
echo "=== Versions ===" && grep -h '"version"' package.json server.json livepilot/.Codex-plugin/plugin.json livepilot/.claude-plugin/plugin.json .claude-plugin/marketplace.json | head -7 && grep __version__ mcp_server/__init__.py remote_script/LivePilot/__init__.py && echo "=== Tool count ===" && grep -rc "@mcp.tool" mcp_server/tools/ | grep -v ":0" | awk -F: '{sum+=$2} END{print "Total:", sum}' && echo "=== Tests ===" && python3 -m pytest tests/ -q 2>&1 | tail -1
|
|
109
112
|
```
|
|
Binary file
|