livepilot 1.9.24 → 1.10.1

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.
Files changed (185) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/AGENTS.md +3 -3
  3. package/CHANGELOG.md +223 -0
  4. package/CONTRIBUTING.md +2 -2
  5. package/LICENSE +62 -21
  6. package/README.md +291 -276
  7. package/bin/livepilot.js +87 -0
  8. package/installer/codex.js +147 -0
  9. package/livepilot/.Codex-plugin/plugin.json +2 -2
  10. package/livepilot/.claude-plugin/plugin.json +2 -2
  11. package/livepilot/skills/livepilot-arrangement/SKILL.md +18 -1
  12. package/livepilot/skills/livepilot-core/SKILL.md +22 -5
  13. package/livepilot/skills/livepilot-core/references/device-knowledge/00-index.md +34 -0
  14. package/livepilot/skills/livepilot-core/references/device-knowledge/automation-as-music.md +204 -0
  15. package/livepilot/skills/livepilot-core/references/device-knowledge/chains-genre.md +173 -0
  16. package/livepilot/skills/livepilot-core/references/device-knowledge/creative-thinking.md +211 -0
  17. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-distortion.md +188 -0
  18. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-space.md +162 -0
  19. package/livepilot/skills/livepilot-core/references/device-knowledge/effects-spectral.md +229 -0
  20. package/livepilot/skills/livepilot-core/references/device-knowledge/instruments-synths.md +243 -0
  21. package/livepilot/skills/livepilot-core/references/overview.md +13 -9
  22. package/livepilot/skills/livepilot-core/references/sample-manipulation.md +724 -0
  23. package/livepilot/skills/livepilot-core/references/sound-design-deep.md +140 -0
  24. package/livepilot/skills/livepilot-devices/SKILL.md +39 -4
  25. package/livepilot/skills/livepilot-evaluation/references/capability-modes.md +1 -1
  26. package/livepilot/skills/livepilot-release/SKILL.md +23 -19
  27. package/livepilot/skills/livepilot-sample-engine/SKILL.md +105 -0
  28. package/livepilot/skills/livepilot-sample-engine/references/sample-critics.md +87 -0
  29. package/livepilot/skills/livepilot-sample-engine/references/sample-philosophy.md +51 -0
  30. package/livepilot/skills/livepilot-sample-engine/references/sample-techniques.md +131 -0
  31. package/livepilot/skills/livepilot-sound-design-engine/SKILL.md +45 -0
  32. package/livepilot/skills/livepilot-wonder/SKILL.md +17 -0
  33. package/livepilot.mcpb +0 -0
  34. package/m4l_device/livepilot_bridge.js +1 -1
  35. package/manifest.json +4 -4
  36. package/mcp_server/__init__.py +1 -1
  37. package/mcp_server/atlas/__init__.py +357 -0
  38. package/mcp_server/atlas/device_atlas.json +44067 -0
  39. package/mcp_server/atlas/enrichments/__init__.py +111 -0
  40. package/mcp_server/atlas/enrichments/audio_effects/auto_filter.yaml +162 -0
  41. package/mcp_server/atlas/enrichments/audio_effects/beat_repeat.yaml +183 -0
  42. package/mcp_server/atlas/enrichments/audio_effects/channel_eq.yaml +126 -0
  43. package/mcp_server/atlas/enrichments/audio_effects/chorus_ensemble.yaml +149 -0
  44. package/mcp_server/atlas/enrichments/audio_effects/color_limiter.yaml +109 -0
  45. package/mcp_server/atlas/enrichments/audio_effects/compressor.yaml +159 -0
  46. package/mcp_server/atlas/enrichments/audio_effects/convolution_reverb.yaml +143 -0
  47. package/mcp_server/atlas/enrichments/audio_effects/convolution_reverb_pro.yaml +178 -0
  48. package/mcp_server/atlas/enrichments/audio_effects/delay.yaml +151 -0
  49. package/mcp_server/atlas/enrichments/audio_effects/drum_buss.yaml +142 -0
  50. package/mcp_server/atlas/enrichments/audio_effects/dynamic_tube.yaml +147 -0
  51. package/mcp_server/atlas/enrichments/audio_effects/echo.yaml +167 -0
  52. package/mcp_server/atlas/enrichments/audio_effects/eq_eight.yaml +148 -0
  53. package/mcp_server/atlas/enrichments/audio_effects/eq_three.yaml +121 -0
  54. package/mcp_server/atlas/enrichments/audio_effects/erosion.yaml +103 -0
  55. package/mcp_server/atlas/enrichments/audio_effects/filter_delay.yaml +173 -0
  56. package/mcp_server/atlas/enrichments/audio_effects/gate.yaml +130 -0
  57. package/mcp_server/atlas/enrichments/audio_effects/gated_delay.yaml +133 -0
  58. package/mcp_server/atlas/enrichments/audio_effects/glue_compressor.yaml +142 -0
  59. package/mcp_server/atlas/enrichments/audio_effects/grain_delay.yaml +141 -0
  60. package/mcp_server/atlas/enrichments/audio_effects/hybrid_reverb.yaml +160 -0
  61. package/mcp_server/atlas/enrichments/audio_effects/limiter.yaml +97 -0
  62. package/mcp_server/atlas/enrichments/audio_effects/multiband_dynamics.yaml +174 -0
  63. package/mcp_server/atlas/enrichments/audio_effects/overdrive.yaml +119 -0
  64. package/mcp_server/atlas/enrichments/audio_effects/pedal.yaml +145 -0
  65. package/mcp_server/atlas/enrichments/audio_effects/phaser_flanger.yaml +161 -0
  66. package/mcp_server/atlas/enrichments/audio_effects/redux.yaml +114 -0
  67. package/mcp_server/atlas/enrichments/audio_effects/reverb.yaml +190 -0
  68. package/mcp_server/atlas/enrichments/audio_effects/roar.yaml +159 -0
  69. package/mcp_server/atlas/enrichments/audio_effects/saturator.yaml +146 -0
  70. package/mcp_server/atlas/enrichments/audio_effects/shifter.yaml +154 -0
  71. package/mcp_server/atlas/enrichments/audio_effects/spectral_resonator.yaml +141 -0
  72. package/mcp_server/atlas/enrichments/audio_effects/spectral_time.yaml +164 -0
  73. package/mcp_server/atlas/enrichments/audio_effects/vector_delay.yaml +140 -0
  74. package/mcp_server/atlas/enrichments/audio_effects/vinyl_distortion.yaml +141 -0
  75. package/mcp_server/atlas/enrichments/instruments/analog.yaml +222 -0
  76. package/mcp_server/atlas/enrichments/instruments/bass.yaml +202 -0
  77. package/mcp_server/atlas/enrichments/instruments/collision.yaml +150 -0
  78. package/mcp_server/atlas/enrichments/instruments/drift.yaml +167 -0
  79. package/mcp_server/atlas/enrichments/instruments/electric.yaml +137 -0
  80. package/mcp_server/atlas/enrichments/instruments/emit.yaml +163 -0
  81. package/mcp_server/atlas/enrichments/instruments/meld.yaml +164 -0
  82. package/mcp_server/atlas/enrichments/instruments/operator.yaml +197 -0
  83. package/mcp_server/atlas/enrichments/instruments/poli.yaml +192 -0
  84. package/mcp_server/atlas/enrichments/instruments/sampler.yaml +218 -0
  85. package/mcp_server/atlas/enrichments/instruments/simpler.yaml +217 -0
  86. package/mcp_server/atlas/enrichments/instruments/tension.yaml +156 -0
  87. package/mcp_server/atlas/enrichments/instruments/tree_tone.yaml +162 -0
  88. package/mcp_server/atlas/enrichments/instruments/vector_fm.yaml +165 -0
  89. package/mcp_server/atlas/enrichments/instruments/vector_grain.yaml +166 -0
  90. package/mcp_server/atlas/enrichments/instruments/wavetable.yaml +162 -0
  91. package/mcp_server/atlas/enrichments/midi_effects/arpeggiator.yaml +156 -0
  92. package/mcp_server/atlas/enrichments/midi_effects/bouncy_notes.yaml +93 -0
  93. package/mcp_server/atlas/enrichments/midi_effects/chord.yaml +147 -0
  94. package/mcp_server/atlas/enrichments/midi_effects/melodic_steps.yaml +97 -0
  95. package/mcp_server/atlas/enrichments/midi_effects/note_echo.yaml +108 -0
  96. package/mcp_server/atlas/enrichments/midi_effects/note_length.yaml +97 -0
  97. package/mcp_server/atlas/enrichments/midi_effects/pitch.yaml +76 -0
  98. package/mcp_server/atlas/enrichments/midi_effects/random.yaml +117 -0
  99. package/mcp_server/atlas/enrichments/midi_effects/rhythmic_steps.yaml +103 -0
  100. package/mcp_server/atlas/enrichments/midi_effects/scale.yaml +83 -0
  101. package/mcp_server/atlas/enrichments/midi_effects/step_arp.yaml +112 -0
  102. package/mcp_server/atlas/enrichments/midi_effects/velocity.yaml +119 -0
  103. package/mcp_server/atlas/enrichments/utility/amp.yaml +159 -0
  104. package/mcp_server/atlas/enrichments/utility/cabinet.yaml +109 -0
  105. package/mcp_server/atlas/enrichments/utility/corpus.yaml +150 -0
  106. package/mcp_server/atlas/enrichments/utility/resonators.yaml +131 -0
  107. package/mcp_server/atlas/enrichments/utility/spectrum.yaml +63 -0
  108. package/mcp_server/atlas/enrichments/utility/tuner.yaml +51 -0
  109. package/mcp_server/atlas/enrichments/utility/utility.yaml +136 -0
  110. package/mcp_server/atlas/enrichments/utility/vocoder.yaml +160 -0
  111. package/mcp_server/atlas/scanner.py +236 -0
  112. package/mcp_server/atlas/tools.py +224 -0
  113. package/mcp_server/composer/__init__.py +1 -0
  114. package/mcp_server/composer/engine.py +532 -0
  115. package/mcp_server/composer/layer_planner.py +427 -0
  116. package/mcp_server/composer/prompt_parser.py +329 -0
  117. package/mcp_server/composer/sample_resolver.py +153 -0
  118. package/mcp_server/composer/tools.py +211 -0
  119. package/mcp_server/connection.py +53 -8
  120. package/mcp_server/corpus/__init__.py +377 -0
  121. package/mcp_server/device_forge/__init__.py +1 -0
  122. package/mcp_server/device_forge/builder.py +377 -0
  123. package/mcp_server/device_forge/models.py +142 -0
  124. package/mcp_server/device_forge/templates.py +483 -0
  125. package/mcp_server/device_forge/tools.py +162 -0
  126. package/mcp_server/m4l_bridge.py +1 -0
  127. package/mcp_server/memory/taste_accessors.py +47 -0
  128. package/mcp_server/preview_studio/engine.py +9 -2
  129. package/mcp_server/preview_studio/tools.py +78 -35
  130. package/mcp_server/project_brain/tools.py +34 -0
  131. package/mcp_server/runtime/capability_probe.py +21 -2
  132. package/mcp_server/runtime/execution_router.py +184 -38
  133. package/mcp_server/runtime/live_version.py +102 -0
  134. package/mcp_server/runtime/mcp_dispatch.py +46 -0
  135. package/mcp_server/runtime/remote_commands.py +13 -5
  136. package/mcp_server/runtime/tools.py +66 -29
  137. package/mcp_server/sample_engine/__init__.py +1 -0
  138. package/mcp_server/sample_engine/analyzer.py +216 -0
  139. package/mcp_server/sample_engine/critics.py +390 -0
  140. package/mcp_server/sample_engine/models.py +193 -0
  141. package/mcp_server/sample_engine/moves.py +127 -0
  142. package/mcp_server/sample_engine/planner.py +186 -0
  143. package/mcp_server/sample_engine/slice_workflow.py +190 -0
  144. package/mcp_server/sample_engine/sources.py +540 -0
  145. package/mcp_server/sample_engine/techniques.py +908 -0
  146. package/mcp_server/sample_engine/tools.py +545 -0
  147. package/mcp_server/semantic_moves/__init__.py +3 -0
  148. package/mcp_server/semantic_moves/device_creation_moves.py +237 -0
  149. package/mcp_server/semantic_moves/mix_moves.py +8 -8
  150. package/mcp_server/semantic_moves/models.py +7 -7
  151. package/mcp_server/semantic_moves/performance_moves.py +4 -4
  152. package/mcp_server/semantic_moves/sample_compilers.py +377 -0
  153. package/mcp_server/semantic_moves/sound_design_moves.py +4 -4
  154. package/mcp_server/semantic_moves/tools.py +63 -10
  155. package/mcp_server/semantic_moves/transition_moves.py +4 -4
  156. package/mcp_server/server.py +71 -1
  157. package/mcp_server/session_continuity/tracker.py +4 -1
  158. package/mcp_server/sound_design/critics.py +89 -1
  159. package/mcp_server/splice_client/__init__.py +1 -0
  160. package/mcp_server/splice_client/client.py +347 -0
  161. package/mcp_server/splice_client/models.py +96 -0
  162. package/mcp_server/splice_client/protos/__init__.py +1 -0
  163. package/mcp_server/splice_client/protos/app_pb2.py +319 -0
  164. package/mcp_server/splice_client/protos/app_pb2.pyi +1153 -0
  165. package/mcp_server/splice_client/protos/app_pb2_grpc.py +1946 -0
  166. package/mcp_server/tools/_conductor.py +16 -0
  167. package/mcp_server/tools/_planner_engine.py +24 -0
  168. package/mcp_server/tools/analyzer.py +2 -0
  169. package/mcp_server/tools/arrangement.py +69 -0
  170. package/mcp_server/tools/automation.py +15 -2
  171. package/mcp_server/tools/devices.py +117 -6
  172. package/mcp_server/tools/notes.py +37 -4
  173. package/mcp_server/tools/planner.py +3 -0
  174. package/mcp_server/wonder_mode/diagnosis.py +5 -0
  175. package/mcp_server/wonder_mode/engine.py +144 -14
  176. package/mcp_server/wonder_mode/tools.py +33 -1
  177. package/package.json +14 -4
  178. package/remote_script/LivePilot/__init__.py +8 -1
  179. package/remote_script/LivePilot/arrangement.py +114 -0
  180. package/remote_script/LivePilot/browser.py +56 -1
  181. package/remote_script/LivePilot/devices.py +246 -6
  182. package/remote_script/LivePilot/mixing.py +8 -3
  183. package/remote_script/LivePilot/server.py +5 -1
  184. package/remote_script/LivePilot/transport.py +3 -0
  185. package/remote_script/LivePilot/version_detect.py +78 -0
@@ -0,0 +1,131 @@
1
+ # Sample Technique Catalog — 29 Recipes
2
+
3
+ ## Category 1: Rhythmic Sampling
4
+
5
+ ### slice_and_sequence (Surgeon)
6
+ Classic MPC workflow: load loop, slice on transients, sequence with MIDI.
7
+ **Material:** drum_loop, full_mix | **Steps:** load -> slice -> get slices -> create clip -> add notes
8
+
9
+ ### vocal_chop_rhythm (Alchemist)
10
+ Chop vocal into syllable-length slices, trigger as staccato rhythm. Burial-inspired.
11
+ **Material:** vocal | **Steps:** load -> slice by region -> MIDI staccato -> Auto Filter
12
+
13
+ ### micro_chop (Alchemist)
14
+ 1/32 slices, varied velocity, slight timing offsets. J Dilla micro-timing.
15
+ **Material:** any loop | **Steps:** load -> manual slice -> dense 1/32 MIDI
16
+
17
+ ### stab_isolation (Surgeon)
18
+ Isolate single chord stab, crop, retrigger rhythmically. DJ Premier style.
19
+ **Material:** full_mix, instrument_loop | **Steps:** load -> classic mode -> crop -> MIDI
20
+
21
+ ### euclidean_slice_trigger (Alchemist)
22
+ Map Simpler slices to Euclidean rhythm for polyrhythmic texture.
23
+ **Material:** drum_loop, vocal, instrument_loop | **Steps:** load -> slice -> Euclidean pattern
24
+
25
+ ## Category 2: Textural Transformation
26
+
27
+ ### extreme_stretch (Alchemist)
28
+ Paulstretch-style: Texture warp at 10-50x, reverb wash. Stars of the Lid territory.
29
+ **Material:** any | **Steps:** load -> warp 64 beats -> Reverb 60-80% wet
30
+
31
+ ### drum_to_pad (Alchemist)
32
+ Reverse + extreme stretch + reverb = drum hit becomes ambient pad.
33
+ **Material:** drum_loop, one_shot | **Steps:** load -> reverse -> stretch -> Reverb
34
+
35
+ ### reverse_layer (Alchemist)
36
+ Reversed sample as pre-echo swell or ghostly texture.
37
+ **Material:** vocal, instrument_loop, one_shot | **Steps:** load -> reverse -> Delay
38
+
39
+ ### granular_scatter (Alchemist)
40
+ Grain Delay as granular engine — scatter grains for cloud textures. Amon Tobin.
41
+ **Material:** vocal, instrument_loop, texture | **Steps:** load -> Grain Delay -> Reverb
42
+
43
+ ### spectral_freeze (Alchemist)
44
+ Crop to tiny region (50-200ms), extreme stretch = spectral freeze drone.
45
+ **Material:** vocal, instrument_loop, full_mix | **Steps:** load -> crop -> stretch 64 beats
46
+
47
+ ### tail_harvest (Alchemist)
48
+ Resample only the reverb/delay tail as independent texture.
49
+ **Material:** any | **Steps:** load -> Reverb 100% wet -> level for subtle layer
50
+
51
+ ## Category 3: Melodic/Harmonic
52
+
53
+ ### key_matched_layer (Surgeon)
54
+ Transpose to song key, EQ carve, blend behind existing elements.
55
+ **Material:** instrument_loop | **Steps:** load -> transpose -> EQ -> volume -6 to -10dB
56
+
57
+ ### vocal_harmony_stack (Surgeon)
58
+ Pitch-shifted vocal layers — Bon Iver Prismizer approach.
59
+ **Material:** vocal | **Steps:** load -> duplicate -> transpose +3/+5/+7 -> blend
60
+
61
+ ### counterpoint_from_chops (Alchemist)
62
+ Create countermelody from rearranged melodic fragments. Four Tet.
63
+ **Material:** instrument_loop, vocal, full_mix | **Steps:** load -> slice by beat -> program melody
64
+
65
+ ### chord_stab_extraction (Surgeon)
66
+ Isolate chord from full mix, crop, retrigger. Classic house/disco.
67
+ **Material:** full_mix, instrument_loop | **Steps:** load -> slice -> crop -> rhythmic pattern
68
+
69
+ ## Category 4: Drum Enhancement
70
+
71
+ ### break_layering (Surgeon)
72
+ Layer drum break under programmed drums. High-pass to avoid kick clash.
73
+ **Material:** drum_loop | **Steps:** load -> warp 16 beats -> EQ HP 200-400Hz -> volume -10 to -15dB
74
+
75
+ ### ghost_note_texture (Alchemist)
76
+ Heavy filter + low volume = barely audible ghost-note layer.
77
+ **Material:** drum_loop | **Steps:** load -> Auto Filter BP 1-4kHz -> volume -18 to -24dB
78
+
79
+ ### transient_replacement (Surgeon)
80
+ Layer one-shot transient over existing drums for punch.
81
+ **Material:** one_shot | **Steps:** load -> classic mode -> MIDI on kick/snare hits
82
+
83
+ ### shuffle_extract (Alchemist)
84
+ Extract groove timing from loop via slice positions, apply to MIDI.
85
+ **Material:** drum_loop | **Steps:** load -> slice by transient -> read positions
86
+
87
+ ## Category 5: Vocal Processing
88
+
89
+ ### syllable_instrument (Alchemist)
90
+ Each syllable = playable note. Vocal becomes a melodic instrument.
91
+ **Material:** vocal | **Steps:** load -> slice by region -> program melody across slices
92
+
93
+ ### formant_shift_character (Alchemist)
94
+ Shift formants for alien/robotic character. Transpose +/-12st.
95
+ **Material:** vocal | **Steps:** load -> transpose -> Corpus for resonant body
96
+
97
+ ### vocal_freeze_drone (Alchemist)
98
+ Sustain one vowel as ambient pad. Crop tiny region, extreme stretch.
99
+ **Material:** vocal | **Steps:** load -> crop 100-300ms -> stretch 64 beats -> Chorus -> Reverb
100
+
101
+ ### phone_recording_texture (Alchemist)
102
+ Burial signature: pitch down, lo-pass, ghost-level volume.
103
+ **Material:** vocal, foley | **Steps:** load -> pitch -5 to -12 -> LP 800Hz -> volume -20 to -30dB
104
+
105
+ ## Category 6: Resampling Chains
106
+
107
+ ### serial_resample (Alchemist)
108
+ Multi-pass destruction: Saturator + Grain Delay + Reverb, freeze, flatten, repeat.
109
+ **Material:** any | **Steps:** load -> Saturator -> Grain Delay -> Reverb -> freeze -> flatten
110
+
111
+ ### parallel_resample (Alchemist)
112
+ Duplicate, process one copy destructively, blend wet/dry.
113
+ **Material:** any | **Steps:** load -> duplicate -> process duplicate -> blend -6 to -12dB
114
+
115
+ ### freeze_flatten_rechop (Alchemist)
116
+ Freeze processed material, flatten to audio, re-slice the result. Recursive.
117
+ **Material:** any | **Steps:** freeze -> flatten -> re-load into Simpler -> slice again
118
+
119
+ ## Category 7: Creative Constraints
120
+
121
+ ### one_sample_challenge (Alchemist)
122
+ Build entire beat from one sample: kick, snare, hat, bass, pad all from slices.
123
+ **Material:** any | **Steps:** load -> slice -> program full beat across slice pitches
124
+
125
+ ### found_sound_only (Alchemist)
126
+ Non-musical field recordings as sole source material. Musique concrete.
127
+ **Material:** foley | **Steps:** load -> slice -> EQ to isolate musical frequencies
128
+
129
+ ### reverse_engineering (Both)
130
+ Recreate a reference track's texture by sampling and transforming similar elements.
131
+ **Material:** full_mix | **Steps:** load -> slice by beat -> analyze structure
@@ -121,3 +121,48 @@ When adding processing blocks, prefer native Ableton devices for controllability
121
121
  - **Saturator** — waveshaping with multiple curve types
122
122
 
123
123
  Always `search_browser` before loading — never guess device names.
124
+
125
+ ## Deep Sound Design Reference
126
+
127
+ Consult `references/sound-design-deep.md` for advanced techniques when working on creative requests. Key principles:
128
+
129
+ ### Making Sounds Breathe
130
+ Every static sound can become alive with modulation below conscious perception:
131
+ - **Filter breathing:** LFO at 0.1-0.5 Hz on filter cutoff, 5-15% depth
132
+ - **Oscillator drift:** ±1-3 cent detune with very slow LFO (0.05-0.2 Hz)
133
+ - **Amplitude micro-variation:** Perlin/brownian noise on volume, ±1-3 dB
134
+ - **Rule:** If the listener can hear the modulation, it's too much. The best modulation is felt, not heard.
135
+
136
+ ### Space as Composition
137
+ Reverb and delay are not decorations — in dub/minimal they ARE the composition:
138
+ - **Dub chord:** Short stab → long delay (70-80% feedback) + filter on the delay return
139
+ - **Delay throws:** Momentary send spikes (0→70% for half a beat) — the echo IS the event
140
+ - **Sidechain reverb:** Dry drums trigger sidechain compression on reverb returns — the room pulses
141
+ - **Feedback modulation:** Delay feedback at 75-85% + modulate delay time ±5-10% for warped echoes
142
+
143
+ ### Creative Sidechain (Beyond Pump)
144
+ Sidechain compression is a modulation source, not just a mix tool:
145
+ - **Sidechain filter:** Envelope follower from kick modulates pad filter cutoff — pad brightens between kicks
146
+ - **Ghost sidechain:** Muted kick as sidechain source for textures — phantom groove on non-rhythmic elements
147
+ - **Multiband sidechain:** Only duck sub frequencies from pad — shimmer stays, sub clears for kick
148
+
149
+ ### Effects as Instruments
150
+ - **Self-oscillating filter:** Push resonance until it rings, play notes by changing cutoff
151
+ - **Feedback loops:** Route output back to input through effects + compressor to control
152
+ - **Convolution as synthesis:** Load non-IR files (speech, drum break) into convolution reverb — imprints spectral character
153
+ - **Granular reverb:** Very short reverb (0.1-0.3s) high diffusion on percussion — smears transient into tonal cloud
154
+
155
+ ### The Frequency Dance
156
+ At any moment, each frequency band should have one primary element. When one opens up, another pulls back:
157
+ - Chord filter opens into highs → pull hi-hat back
158
+ - Bass drops → kick shortens
159
+ - Reverb tail fills → dry elements duck
160
+ This is mix engineering as composition.
161
+
162
+ ### When to Apply These
163
+ - User says "make it breathe" or "it sounds static" → micro-modulation
164
+ - User says "more space" or "deeper" → dub techniques (delay throws, reverb composition)
165
+ - User says "more groove" or "make it pump" → creative sidechain
166
+ - User says "more texture" or "more complex" → textural layering
167
+ - User says "surprise me" or "WTF moment" → brief textural disruption (2-8 beats max)
168
+ - User says "warmer" or "more analog" → oscillator drift + subtle saturation + filter breathing
@@ -60,3 +60,20 @@ For the recommendation, explain:
60
60
  - Why this one over the others
61
61
  - What risk it introduces
62
62
  - What sacred elements it preserves
63
+
64
+ ## Creative Intelligence (consult before generating variants)
65
+
66
+ Wonder Mode should produce musically interesting results, not just technically correct ones. Before generating or applying any variant:
67
+
68
+ 1. Read `references/device-knowledge/automation-as-music.md` for automation shapes and macro gestures
69
+ 2. Read `references/device-knowledge/creative-thinking.md` for emotional-to-technical mapping
70
+ 3. Read `references/device-knowledge/chains-genre.md` if the session has a genre identity
71
+
72
+ When reviewing Wonder variants, aim for musical depth:
73
+ - **Filter arcs** — evolving filter across sections adds movement
74
+ - **Space arcs** — reverb/delay sends breathing with density
75
+ - **Micro-modulation** — subtle LFOs on sustained sounds
76
+ - **Macro gestures** — coordinated multi-parameter moves at transitions
77
+
78
+ Note: these are agent-level guidelines, not enforced by the Wonder engine.
79
+ The engine generates variants from semantic moves; the agent adds musical polish.
package/livepilot.mcpb CHANGED
Binary file
@@ -84,7 +84,7 @@ function anything() {
84
84
  function dispatch(cmd, args) {
85
85
  switch(cmd) {
86
86
  case "ping":
87
- send_response({"ok": true, "version": "1.9.22"});
87
+ send_response({"ok": true, "version": "1.10.1"});
88
88
  break;
89
89
  case "get_params":
90
90
  cmd_get_params(args);
package/manifest.json CHANGED
@@ -2,14 +2,14 @@
2
2
  "manifest_version": "0.3",
3
3
  "name": "livepilot",
4
4
  "display_name": "LivePilot — AI for Ableton Live",
5
- "version": "1.9.24",
6
- "description": "Agentic production system for Ableton Live 12. Make beats, mix tracks, design sounds, and arrange songs with 293 AI-powered tools.",
7
- "long_description": "LivePilot is an AI production assistant that connects directly to Ableton Live 12. It can create drum patterns, program basslines, write chord progressions, design sounds, mix your tracks, analyze your audio, and arrange full songs all through natural language.\n\n**What it does:**\n- Creates MIDI clips with notes, chords, and rhythms\n- Loads instruments and effects from Ableton's browser\n- Shapes sounds by adjusting device parameters\n- Mixes with volume, panning, sends, and automation\n- Analyzes your mix with real-time spectral data\n- Remembers your production style across sessions\n\n**How it works:**\nLivePilot installs a Remote Script in Ableton that communicates with the AI over a local TCP connection. Everything runs on your machine — no audio leaves your computer.",
5
+ "version": "1.10.1",
6
+ "description": "Agentic production system for Ableton Live 12. Make beats, mix tracks, design sounds, and arrange songs with 317 AI-powered tools.",
7
+ "long_description": "LivePilot is an agentic production system for Ableton Live 12. 317 tools across 43 domains device atlas (1305 devices), sample intelligence (Splice + browser + filesystem), auto-composition, spectral perception, technique memory, and 12 creative engines.\n\n**What it does:**\n- Creates MIDI clips with notes, chords, and rhythms\n- Loads instruments and effects via Device Atlas (1305 devices indexed)\n- Searches samples across Splice, Ableton browser, and filesystem\n- Plans compositions from text prompts with genre-aware layering\n- Slices samples with intent-based MIDI generation\n- Mixes with volume, panning, sends, and automation\n- Analyzes your mix with real-time spectral data (M4L bridge)\n- Diagnoses stuck sessions and generates creative rescue variants\n- Remembers your production style across sessions\n\n**How it works:**\nLivePilot installs a Remote Script in Ableton that communicates with the AI over a local TCP connection. Everything runs on your machine — no audio leaves your computer.",
8
8
  "author": {
9
9
  "name": "Pilot Studio",
10
10
  "url": "https://github.com/dreamrec/LivePilot"
11
11
  },
12
- "license": "MIT",
12
+ "license": "BSL-1.1",
13
13
  "repository": {
14
14
  "type": "git",
15
15
  "url": "https://github.com/dreamrec/LivePilot"
@@ -1,2 +1,2 @@
1
1
  """LivePilot MCP Server — bridges MCP protocol to Ableton Live."""
2
- __version__ = "1.9.24"
2
+ __version__ = "1.10.1"
@@ -0,0 +1,357 @@
1
+ """Device Atlas v2 — indexed in-memory device knowledge base.
2
+
3
+ Loads a JSON atlas file and builds indexes for fast lookup, search,
4
+ suggestion, chain building, and device comparison.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ import os
11
+ from typing import Any, Dict, List, Optional
12
+
13
+
14
+ class AtlasManager:
15
+ """In-memory device atlas with indexed lookups."""
16
+
17
+ def __init__(self, atlas_path: str):
18
+ with open(atlas_path, "r") as f:
19
+ data = json.load(f)
20
+
21
+ self._meta = data.get("meta", {})
22
+ self._devices: List[Dict[str, Any]] = data.get("devices", [])
23
+
24
+ # ── Build indexes ───────────────────────────────────────────
25
+ self._by_id: Dict[str, Dict[str, Any]] = {}
26
+ self._by_name: Dict[str, Dict[str, Any]] = {} # lowercase key
27
+ self._by_uri: Dict[str, Dict[str, Any]] = {}
28
+ self._by_category: Dict[str, List[Dict[str, Any]]] = {}
29
+ self._by_tag: Dict[str, List[Dict[str, Any]]] = {}
30
+ self._by_genre: Dict[str, List[Dict[str, Any]]] = {}
31
+
32
+ for dev in self._devices:
33
+ dev_id = dev.get("id", "")
34
+ dev_name = dev.get("name", "")
35
+ dev_uri = dev.get("uri", "")
36
+ dev_category = dev.get("category", "")
37
+
38
+ if dev_id:
39
+ self._by_id[dev_id] = dev
40
+ if dev_name:
41
+ self._by_name[dev_name.lower()] = dev
42
+ if dev_uri:
43
+ self._by_uri[dev_uri] = dev
44
+
45
+ # Category index
46
+ if dev_category:
47
+ self._by_category.setdefault(dev_category, []).append(dev)
48
+
49
+ # Tag index
50
+ for tag in dev.get("tags", []):
51
+ self._by_tag.setdefault(tag.lower(), []).append(dev)
52
+
53
+ # Genre index (primary + secondary)
54
+ for genre in dev.get("genres", {}).get("primary", []):
55
+ self._by_genre.setdefault(genre.lower(), []).append(dev)
56
+ for genre in dev.get("genres", {}).get("secondary", []):
57
+ self._by_genre.setdefault(genre.lower(), []).append(dev)
58
+
59
+ # ── Properties ──────────────────────────────────────────────────
60
+
61
+ @property
62
+ def version(self) -> str:
63
+ return self._meta.get("version", "unknown")
64
+
65
+ @property
66
+ def device_count(self) -> int:
67
+ return len(self._devices)
68
+
69
+ @property
70
+ def stats(self) -> Dict[str, Any]:
71
+ categories: Dict[str, int] = {}
72
+ for dev in self._devices:
73
+ cat = dev.get("category", "unknown")
74
+ categories[cat] = categories.get(cat, 0) + 1
75
+ return {
76
+ "version": self.version,
77
+ "device_count": self.device_count,
78
+ "categories": categories,
79
+ "index_sizes": {
80
+ "by_id": len(self._by_id),
81
+ "by_name": len(self._by_name),
82
+ "by_uri": len(self._by_uri),
83
+ "by_category": len(self._by_category),
84
+ "by_tag": len(self._by_tag),
85
+ "by_genre": len(self._by_genre),
86
+ },
87
+ }
88
+
89
+ # ── Lookup ──────────────────────────────────────────────────────
90
+
91
+ def lookup(self, name_or_id: str) -> Optional[Dict[str, Any]]:
92
+ """Exact match by ID, name (case-insensitive), or URI. Returns None on miss."""
93
+ # Try ID first
94
+ if name_or_id in self._by_id:
95
+ return self._by_id[name_or_id]
96
+ # Try name (case-insensitive)
97
+ lower = name_or_id.lower()
98
+ if lower in self._by_name:
99
+ return self._by_name[lower]
100
+ # Try URI
101
+ if name_or_id in self._by_uri:
102
+ return self._by_uri[name_or_id]
103
+ return None
104
+
105
+ # ── Search ──────────────────────────────────────────────────────
106
+
107
+ def search(
108
+ self, query: str, category: str = "all", limit: int = 10
109
+ ) -> List[Dict[str, Any]]:
110
+ """Multi-signal search scoring across name, tags, use_cases, genre, description."""
111
+ if not query:
112
+ return []
113
+
114
+ query_lower = query.lower()
115
+ query_words = query_lower.split()
116
+ results: List[Dict[str, Any]] = []
117
+
118
+ for dev in self._devices:
119
+ # Category filter
120
+ if category != "all" and dev.get("category", "") != category:
121
+ continue
122
+
123
+ score = 0
124
+ dev_name = dev.get("name", "")
125
+ dev_name_lower = dev_name.lower()
126
+
127
+ # Name scoring: 100pts exact, 50pts substring
128
+ if dev_name_lower == query_lower:
129
+ score += 100
130
+ elif query_lower in dev_name_lower:
131
+ score += 50
132
+
133
+ # Tag scoring: 30pts per matching tag
134
+ dev_tags = [t.lower() for t in dev.get("tags", [])]
135
+ for word in query_words:
136
+ if word in dev_tags:
137
+ score += 30
138
+
139
+ # Use case scoring: 25pts per match
140
+ for use_case in dev.get("use_cases", []):
141
+ use_lower = use_case.lower()
142
+ for word in query_words:
143
+ if word in use_lower:
144
+ score += 25
145
+ break # one match per use_case
146
+
147
+ # Genre scoring: 20pts primary, 10pts secondary
148
+ genres = dev.get("genres", {})
149
+ for genre in genres.get("primary", []):
150
+ if query_lower in genre.lower() or genre.lower() in query_lower:
151
+ score += 20
152
+ for genre in genres.get("secondary", []):
153
+ if query_lower in genre.lower() or genre.lower() in query_lower:
154
+ score += 10
155
+
156
+ # Description keyword scoring: 15pts
157
+ description = dev.get("description", "").lower()
158
+ for word in query_words:
159
+ if len(word) >= 3 and word in description:
160
+ score += 15
161
+
162
+ if score > 0:
163
+ results.append({"device": dev, "score": score})
164
+
165
+ # Sort by score descending, then by name for stability
166
+ results.sort(key=lambda r: (-r["score"], r["device"].get("name", "")))
167
+ return results[:limit]
168
+
169
+ # ── Suggest ─────────────────────────────────────────────────────
170
+
171
+ def suggest(
172
+ self,
173
+ intent: str,
174
+ genre: str = "",
175
+ energy: str = "medium",
176
+ limit: int = 5,
177
+ ) -> List[Dict[str, Any]]:
178
+ """Suggest devices for an intent, returning ranked list with rationale and recipe."""
179
+ # Use search to find candidates
180
+ search_query = intent
181
+ if genre:
182
+ search_query = f"{intent} {genre}"
183
+ candidates = self.search(search_query, limit=limit * 2)
184
+
185
+ results = []
186
+ for candidate in candidates[:limit]:
187
+ dev = candidate["device"]
188
+ dev_name = dev.get("name", "")
189
+ dev_category = dev.get("category", "")
190
+ dev_tags = dev.get("tags", [])
191
+ dev_sweet_spot = dev.get("sweet_spot", "")
192
+
193
+ # Build rationale
194
+ rationale_parts = []
195
+ if dev_category:
196
+ rationale_parts.append(f"{dev_name} is a {dev_category}")
197
+ if dev_tags:
198
+ rationale_parts.append(f"suited for {', '.join(dev_tags[:3])}")
199
+ if genre:
200
+ primary_genres = dev.get("genres", {}).get("primary", [])
201
+ if any(genre.lower() in g.lower() for g in primary_genres):
202
+ rationale_parts.append(f"commonly used in {genre}")
203
+ rationale = " — ".join(rationale_parts) if rationale_parts else f"{dev_name} matches your intent"
204
+
205
+ # Build recipe
206
+ recipe = {}
207
+ if dev_sweet_spot:
208
+ recipe["sweet_spot"] = dev_sweet_spot
209
+ recipe["energy"] = energy
210
+ key_params = dev.get("key_parameters", [])
211
+ if key_params:
212
+ recipe["start_with"] = key_params[:3]
213
+
214
+ results.append({
215
+ "device": dev,
216
+ "rationale": rationale,
217
+ "recipe": recipe,
218
+ })
219
+
220
+ return results
221
+
222
+ # ── Chain Suggest ───────────────────────────────────────────────
223
+
224
+ def chain_suggest(
225
+ self, role: str, genre: str = ""
226
+ ) -> Dict[str, Any]:
227
+ """Suggest a device chain for a given role (e.g., 'bass', 'lead', 'pad')."""
228
+ chain: List[Dict[str, Any]] = []
229
+ position = 0
230
+
231
+ # Determine chain structure based on role
232
+ role_lower = role.lower()
233
+
234
+ # Stage 1: Instrument (if the role implies one)
235
+ instrument_intents = {
236
+ "bass": "bass synthesizer",
237
+ "lead": "lead synthesizer",
238
+ "pad": "pad synthesizer",
239
+ "keys": "keyboard instrument",
240
+ "drums": "drum machine",
241
+ "vocal": "vocal",
242
+ }
243
+
244
+ intent = instrument_intents.get(role_lower, role_lower)
245
+ search_q = f"{intent} {genre}" if genre else intent
246
+
247
+ # Find instrument
248
+ instrument_candidates = self.search(search_q, category="instrument", limit=3)
249
+ if instrument_candidates:
250
+ best = instrument_candidates[0]["device"]
251
+ chain.append({
252
+ "position": position,
253
+ "device": best,
254
+ "reason": f"Primary {role} instrument",
255
+ })
256
+ position += 1
257
+
258
+ # Stage 2: Effects
259
+ effect_stages = [
260
+ ("eq", f"Shape the {role} tone"),
261
+ ("compression", f"Control {role} dynamics"),
262
+ ("reverb", f"Add space to {role}"),
263
+ ]
264
+
265
+ for effect_type, reason in effect_stages:
266
+ effect_q = f"{effect_type} {genre}" if genre else effect_type
267
+ effect_candidates = self.search(effect_q, category="effect", limit=2)
268
+ if effect_candidates:
269
+ best = effect_candidates[0]["device"]
270
+ chain.append({
271
+ "position": position,
272
+ "device": best,
273
+ "reason": reason,
274
+ })
275
+ position += 1
276
+
277
+ return {
278
+ "role": role,
279
+ "genre": genre,
280
+ "chain": chain,
281
+ }
282
+
283
+ # ── Compare ─────────────────────────────────────────────────────
284
+
285
+ def compare(
286
+ self, device_a: str, device_b: str, role: str = ""
287
+ ) -> Dict[str, Any]:
288
+ """Compare two devices side-by-side with a recommendation."""
289
+ dev_a = self.lookup(device_a)
290
+ dev_b = self.lookup(device_b)
291
+
292
+ if not dev_a:
293
+ return {"error": f"Device not found: {device_a}"}
294
+ if not dev_b:
295
+ return {"error": f"Device not found: {device_b}"}
296
+
297
+ def _summarize(dev: Dict[str, Any]) -> Dict[str, Any]:
298
+ return {
299
+ "name": dev.get("name", ""),
300
+ "category": dev.get("category", ""),
301
+ "tags": dev.get("tags", []),
302
+ "genres": dev.get("genres", {}),
303
+ "use_cases": dev.get("use_cases", []),
304
+ "description": dev.get("description", ""),
305
+ "cpu_weight": dev.get("cpu_weight", "unknown"),
306
+ "sweet_spot": dev.get("sweet_spot", ""),
307
+ }
308
+
309
+ summary_a = _summarize(dev_a)
310
+ summary_b = _summarize(dev_b)
311
+
312
+ # Recommendation logic: score each for the role
313
+ score_a = 0
314
+ score_b = 0
315
+ if role:
316
+ role_lower = role.lower()
317
+ # Check use_cases
318
+ for uc in dev_a.get("use_cases", []):
319
+ if role_lower in uc.lower():
320
+ score_a += 20
321
+ for uc in dev_b.get("use_cases", []):
322
+ if role_lower in uc.lower():
323
+ score_b += 20
324
+ # Check tags
325
+ for tag in dev_a.get("tags", []):
326
+ if role_lower in tag.lower():
327
+ score_a += 10
328
+ for tag in dev_b.get("tags", []):
329
+ if role_lower in tag.lower():
330
+ score_b += 10
331
+
332
+ if score_a > score_b:
333
+ recommendation = f"{summary_a['name']} is better suited for {role}" if role else f"{summary_a['name']} scores higher"
334
+ elif score_b > score_a:
335
+ recommendation = f"{summary_b['name']} is better suited for {role}" if role else f"{summary_b['name']} scores higher"
336
+ else:
337
+ recommendation = "Both devices are equally suited" + (f" for {role}" if role else "")
338
+
339
+ return {
340
+ "device_a": summary_a,
341
+ "device_b": summary_b,
342
+ "recommendation": recommendation,
343
+ }
344
+
345
+
346
+ # ── Module-level lazy loader ───────────────────────────────────────
347
+
348
+ _atlas_instance: Optional[AtlasManager] = None
349
+
350
+
351
+ def _load_atlas() -> AtlasManager:
352
+ """Lazy-load the atlas from device_atlas.json in the same directory."""
353
+ global _atlas_instance
354
+ if _atlas_instance is None:
355
+ atlas_path = os.path.join(os.path.dirname(__file__), "device_atlas.json")
356
+ _atlas_instance = AtlasManager(atlas_path)
357
+ return _atlas_instance