livepilot 1.10.8 → 1.12.2

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 (49) hide show
  1. package/CHANGELOG.md +373 -0
  2. package/README.md +16 -16
  3. package/m4l_device/LivePilot_Analyzer.amxd +0 -0
  4. package/m4l_device/livepilot_bridge.js +1 -1
  5. package/mcp_server/__init__.py +1 -1
  6. package/mcp_server/evaluation/fabric.py +62 -1
  7. package/mcp_server/m4l_bridge.py +503 -18
  8. package/mcp_server/project_brain/automation_graph.py +23 -1
  9. package/mcp_server/project_brain/builder.py +2 -0
  10. package/mcp_server/project_brain/models.py +20 -1
  11. package/mcp_server/project_brain/tools.py +10 -3
  12. package/mcp_server/runtime/execution_router.py +7 -0
  13. package/mcp_server/runtime/mcp_dispatch.py +32 -0
  14. package/mcp_server/runtime/remote_commands.py +54 -0
  15. package/mcp_server/sample_engine/slice_classifier.py +169 -0
  16. package/mcp_server/semantic_moves/tools.py +139 -31
  17. package/mcp_server/server.py +151 -17
  18. package/mcp_server/session_continuity/models.py +13 -0
  19. package/mcp_server/session_continuity/tools.py +2 -0
  20. package/mcp_server/session_continuity/tracker.py +93 -0
  21. package/mcp_server/tools/_analyzer_engine/__init__.py +39 -0
  22. package/mcp_server/tools/_analyzer_engine/context.py +103 -0
  23. package/mcp_server/tools/_analyzer_engine/flucoma.py +23 -0
  24. package/mcp_server/tools/_analyzer_engine/sample.py +122 -0
  25. package/mcp_server/tools/_motif_engine.py +19 -4
  26. package/mcp_server/tools/analyzer.py +204 -180
  27. package/mcp_server/tools/clips.py +304 -1
  28. package/mcp_server/tools/devices.py +517 -5
  29. package/mcp_server/tools/diagnostics.py +42 -0
  30. package/mcp_server/tools/follow_actions.py +202 -0
  31. package/mcp_server/tools/grooves.py +142 -0
  32. package/mcp_server/tools/miditool.py +280 -0
  33. package/mcp_server/tools/scales.py +126 -0
  34. package/mcp_server/tools/take_lanes.py +135 -0
  35. package/mcp_server/tools/tracks.py +46 -3
  36. package/mcp_server/tools/transport.py +120 -4
  37. package/package.json +2 -2
  38. package/remote_script/LivePilot/__init__.py +15 -4
  39. package/remote_script/LivePilot/clips.py +62 -0
  40. package/remote_script/LivePilot/devices.py +444 -0
  41. package/remote_script/LivePilot/diagnostics.py +52 -1
  42. package/remote_script/LivePilot/follow_actions.py +235 -0
  43. package/remote_script/LivePilot/grooves.py +185 -0
  44. package/remote_script/LivePilot/scales.py +138 -0
  45. package/remote_script/LivePilot/take_lanes.py +175 -0
  46. package/remote_script/LivePilot/tracks.py +59 -1
  47. package/remote_script/LivePilot/transport.py +90 -1
  48. package/remote_script/LivePilot/version_detect.py +9 -0
  49. package/server.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,378 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.12.2 — Post-release audit reliability fixes (April 18 2026)
4
+
5
+ Six issues surfaced by an immediate post-v1.12.0 deep audit (parallel
6
+ code-reviewer subagents + manual verification). All fixed TDD-style —
7
+ every bug now has a named regression guard in the test suite.
8
+
9
+ **No tool count change** (still 398). **+11 regression tests**
10
+ (2195 → 2206 passing, 1 skipped, 0 failed).
11
+
12
+ ### Critical fixes (reliability in hot paths)
13
+
14
+ - **`send_capture` no longer blocks `send_command`** (BUG-audit-C1).
15
+ The M4L bridge shared `_cmd_lock` between `send_capture` and
16
+ `send_command`, so any concurrent MCP tool invocation during a
17
+ recording was blocked for the full capture duration (up to 35s).
18
+ The two operations use independent receiver state
19
+ (`_capture_future` vs `_response_callback`) and now use
20
+ independent locks (`_capture_lock` + `_cmd_lock`).
21
+ [`mcp_server/m4l_bridge.py:780-790, 912-913`](mcp_server/m4l_bridge.py).
22
+ - **`_parse_osc` no longer crashes on malformed packets**
23
+ (BUG-audit-C2). `data.index(b'\x00')` raised `ValueError` when a
24
+ packet had no null byte — on UDP port 9880 collision with
25
+ non-OSC traffic, every incoming packet logged a noisy stack
26
+ trace. Replaced with `data.find(...)` + bounds checks on every
27
+ offset; malformed packets drop silently.
28
+ [`mcp_server/m4l_bridge.py:513-565`](mcp_server/m4l_bridge.py).
29
+ - **`classify_simpler_slices` returns structured error on bad WAV**
30
+ (BUG-audit-C3). `sf.read()` was unguarded — corrupt or missing
31
+ files raised `soundfile.LibsndfileError` through the MCP
32
+ framework as an internal server error. Every other tool in the
33
+ module returns `{"error": ...}` dicts. Now wrapped in
34
+ `try/except` for consistent error shape.
35
+ [`mcp_server/tools/analyzer.py:571-581`](mcp_server/tools/analyzer.py).
36
+
37
+ ### High-severity fixes (API consistency)
38
+
39
+ - **`batch_set_parameters` rejects negative `parameter_index`**
40
+ (BUG-audit-H3). `set_device_parameter` validates this at the MCP
41
+ layer; `batch_set_parameters` didn't, leaking an unstructured
42
+ `IndexError` from the Remote Script. Now rejected with a clear
43
+ ValueError at normalisation time.
44
+ [`mcp_server/tools/devices.py:318-328`](mcp_server/tools/devices.py).
45
+
46
+ ### Medium-severity fixes
47
+
48
+ - **`_enrich_slice_response` uses positional fallback for missing
49
+ `index` field** (BUG-audit-M2). Direct `s["index"]` access in a
50
+ list comprehension raised `KeyError` on bridge version skew.
51
+ Now uses `s.get("index", i)` with `enumerate` fallback.
52
+ [`mcp_server/tools/analyzer.py:57-62`](mcp_server/tools/analyzer.py).
53
+ - **`test_identify_returns_none_for_free_port` is no longer flaky**
54
+ (BUG-audit-M4). The test hardcoded port 59999 as "almost
55
+ certainly free"; when another process on the machine held it
56
+ (hitting Claude Desktop during the audit), the test failed
57
+ without diagnosing a real code bug. Now uses
58
+ `socket.bind(("127.0.0.1", 0))` to get a kernel-assigned free
59
+ port, releases it, then verifies.
60
+ [`tests/test_startup_safety.py:50-70`](tests/test_startup_safety.py).
61
+
62
+ ### .amxd binary patched in place
63
+
64
+ - `m4l_device/LivePilot_Analyzer.amxd` had the `ping` response
65
+ version string patched from `"1.12.0"` → `"1.12.2"` via direct
66
+ byte replacement (same-length delta, size preserved). No Max
67
+ re-export needed.
68
+ - `m4l_device/livepilot_bridge.js` source version also updated for
69
+ the next full rebuild.
70
+
71
+ ---
72
+
73
+ ## 1.12.1 — Silent-failure fixes + slice classifier (April 18 2026)
74
+
75
+ Reconciles the "separate git stash" called out under v1.12.0's Known
76
+ limitations — the 2026-04-18 Villalobos-groove session surfaced four
77
+ silent-failure bugs and the need for a drum-slice spectral classifier.
78
+
79
+ **+1 tool (397 → 398): `classify_simpler_slices`.** +43 regression
80
+ guards (pure-Python, run without a live Ableton).
81
+
82
+ ### Ship-stoppers fixed
83
+
84
+ - **`get_master_rms.pitch.midi_note` clamped** (BUG-F1) — polyphonic
85
+ pitch detector emitted values up to 319.15 with amplitude 0. Now
86
+ drops readings with zero amplitude or out-of-range MIDI.
87
+ [`mcp_server/tools/analyzer.py:128-147`](mcp_server/tools/analyzer.py).
88
+ - **`get_simpler_slices` discloses base MIDI pitch** (BUG-F2) — Simpler
89
+ Slice mode uses C1 (MIDI 36) as slice 0, NOT C3. Response now
90
+ includes `base_midi_pitch` at top level and `midi_pitch` per slice.
91
+ Prevents the class of silent-audio bugs where MIDI notes at pitch
92
+ 60+ trigger nothing. Docstring updated to mandate using the
93
+ returned `midi_pitch`.
94
+ [`mcp_server/tools/analyzer.py:37-62, 462-487`](mcp_server/tools/analyzer.py).
95
+ - **`delete_track` last-track error message** (BUG-F3) — Ableton's
96
+ default rejection message was unrelated to the real cause ("you
97
+ can't add notes to a clip that doesn't exist yet"). Now pre-checks
98
+ `track_count` and raises a clear ValueError.
99
+ [`mcp_server/tools/tracks.py:93-112`](mcp_server/tools/tracks.py).
100
+ - **`batch_set_parameters` accepts aligned schema** (BUG-F4) — supports
101
+ `parameter_index` / `parameter_name` (matching `set_device_parameter`)
102
+ in addition to the legacy `name_or_index`. Rejects ambiguous entries
103
+ with clear errors.
104
+ [`mcp_server/tools/devices.py:292-328`](mcp_server/tools/devices.py).
105
+
106
+ ### New tool
107
+
108
+ - **`classify_simpler_slices(track, device, file_path?)`** — runs
109
+ FFT-based spectral analysis on a Simpler's slice boundaries, returns
110
+ each slice labeled as KICK / SNARE / HAT / ghost plus feature
111
+ breakdown (peak, rms, band %). Validated thresholds from the
112
+ 2026-04-18 Villalobos-groove session on "Break Ghosts 90 bpm":
113
+ - KICK: sub+low ≥ 45%, high < 40%
114
+ - HAT: high ≥ 70% AND mid < 25%
115
+ - SNARE: mid ≥ 25% AND high ≥ 40% AND peak ≥ 0.6
116
+ - ghost: peak < 0.35
117
+ Eliminates the "assume slice 0 = kick" class of bug.
118
+
119
+ ### New module
120
+
121
+ - **`mcp_server/sample_engine/slice_classifier.py`** — pure-Python
122
+ band-energy + peak classifier. Testable without Ableton
123
+ (`tests/test_slice_classifier.py` uses synthesized drum hits).
124
+ Exported `classify_segment()` and `classify_slices()` for direct
125
+ use outside MCP as well.
126
+
127
+ ### Documented bug entries
128
+
129
+ - `BUGS.md` gains a new **"F. 2026-04-18 Villalobos-groove creative
130
+ session"** section: F1-F4 fixed here, F5-F7 scoped to v1.13+, F8
131
+ wontfix (workaround documented).
132
+
133
+ ### Not included in this release
134
+
135
+ - `package.json` / `server.json` / plugin manifests / skill tool-count
136
+ sync — release-discipline is a separate task per CLAUDE.md's
137
+ "Version Bump" section. Run `python3 scripts/sync_metadata.py --fix`
138
+ before the next release.
139
+ - Registering `classify_simpler_slices` in
140
+ `tests/test_tools_contract.py::test_analyzer_tools_registered` — the
141
+ total-count assertion there already passes if regenerated; the
142
+ registration list is additive and can land with the metadata sync.
143
+
144
+ ---
145
+
146
+ ## 1.12.0 — Live 12 LOM completeness (April 18 2026)
147
+
148
+ Thirteen chunks closing the gap between LivePilot and Ableton Live 12.3.6's
149
+ Live Object Model. **325 → 397 tools (+72). 45 → 51 domains (+6).** Every
150
+ addition is hasattr-probed where the underlying API varies by Live version
151
+ — Core (12.0+), Enhanced (12.1.10+), and Full Intelligence (12.3+) tiers
152
+ keep their graceful degradation contract.
153
+
154
+ ### New tools by chunk
155
+
156
+ - **Chunk 1 — Song scale awareness (4 tools):** `get_song_scale`,
157
+ `set_song_scale`, `set_song_scale_mode`, `list_available_scales` — exposes
158
+ Live 12.0's Scale Mode at the song level. Remote Script probes
159
+ `song.scale_name` / `song.root_note`; missing on pre-12 falls back to
160
+ "Scale awareness unavailable".
161
+ - **Chunk 2 — Per-clip scale override (3 tools):** `get_clip_scale`,
162
+ `set_clip_scale`, `set_clip_scale_mode` — Live 12.0 MIDI clip-level override
163
+ for the song scale. Honors `clip.scale_name` and `clip.scale_mode`.
164
+ - **Chunk 3 — Tuning System (4 tools):** `get_tuning_system`,
165
+ `set_tuning_reference_pitch`, `set_tuning_note`, `reset_tuning_system` —
166
+ Live 12.1 microtonal tuning. Writes to `song.tuning_system`,
167
+ `tuning.reference_pitch`, and individual tuning-note cents.
168
+ - **Chunk 4 — Follow Actions (8 tools):** Clip-level Live 12.0 revamp
169
+ (multi-action enum, `follow_action_time`, `follow_action_enabled`) +
170
+ scene-level Live 12.2+ (`scene.follow_action`, `scene.follow_action_time`)
171
+ + preset wrapper for "A→B→C chain" common shapes.
172
+ - **Chunk 5 — Groove Pool (7 tools):** Pool enumeration, per-clip assignment,
173
+ master groove dial. Exposes Live 11+ `song.groove_pool` and the swing /
174
+ timing / random / velocity amount on each groove.
175
+ - **Chunk 6 — Take Lanes (6 tools):** Enumeration, creation, per-lane clip
176
+ creation. Live 12.0 read surface + 12.2 write surface — both paths handled
177
+ with `hasattr` probes so older hosts degrade cleanly.
178
+ - **Chunk 7 — Rack Variations + Macro CRUD (8 tools):** Variation
179
+ store/recall/delete + macro add/remove/randomize on Instrument/Audio-Effect
180
+ Racks (Live 11+).
181
+ - **Chunk 8 — Sample Slice CRUD (6 tools):** `insert_slice`, `move_slice`,
182
+ `remove_slice`, `clear_slices`, `reset_slices`, `import_slices_from_onsets`.
183
+ Writes to `SimplerDevice.sample.slices` (Live 11+).
184
+ - **Chunk 9 — Wavetable Modulation Matrix (5 tools):** Targets,
185
+ routing, amounts — completes the Wavetable surface alongside the existing
186
+ parameter tools (Live 11+).
187
+ - **Chunk 10 — Song/Track long-tail primitives (12 tools):** `tap_tempo`,
188
+ `nudge_tempo_down/up`, exclusive arm/solo, `capture_and_insert_scene`,
189
+ `count_in`, Ableton Link state, `jump_in_session_clip`, performance-impact
190
+ read, `appointed_device`.
191
+ - **Chunk 11 — Device A/B Compare (3 tools):** State read, toggle, copy
192
+ direction. Uses Live 12.3+ `Device.is_ab_state_enabled` / `ab_state`
193
+ where available; all three tools hasattr-probe so they return a clear
194
+ "unsupported on this Live build" error on 12.2 and older.
195
+ - **Chunk 12 — ControlSurface enumeration (2 tools):** `list_control_surfaces`,
196
+ `get_control_surface_info`. Always-available diagnostic for multi-surface
197
+ setups.
198
+ - **Chunk 13 — MIDI Tool bridge (4 tools):** `install_miditool_device`,
199
+ `set_miditool_target`, `get_miditool_context`, `list_miditool_generators`.
200
+ Exposes Live 12 MIDI Tools (Generators + Transformations) backed by
201
+ LivePilot generators (euclidean_rhythm, humanize, tintinnabuli). Ships
202
+ with both `.amxd` files pre-built from Live's factory templates — install
203
+ via `install_miditool_device()` which copies to the correct User Library
204
+ subfolders. **Note**: end-to-end Max-side integration is a known
205
+ follow-up; Max's `[js]` object may not locate `miditool_bridge.js` on
206
+ every machine without the folder being added to Max's File Preferences →
207
+ File Search Path. Server-side tools and config dispatch work standalone;
208
+ full round-trip notes-in-clip requires that Max path setup. Hence:
209
+ server shipped, Max-side user-setup step documented.
210
+
211
+ ### New domains (45 → 51)
212
+
213
+ Source of truth is module layout — six new files registered @mcp.tool()
214
+ decorators:
215
+
216
+ - `mcp_server/tools/scales.py` — serves both scales (Chunks 1–2) AND tuning
217
+ (Chunk 3) since both live on the Song object.
218
+ - `mcp_server/tools/follow_actions.py` — Chunk 4.
219
+ - `mcp_server/tools/grooves.py` — Chunk 5.
220
+ - `mcp_server/tools/take_lanes.py` — Chunk 6.
221
+ - `mcp_server/tools/diagnostics.py` — Chunk 12.
222
+ - `mcp_server/tools/miditool.py` — Chunk 13.
223
+
224
+ Chunks 7–11 extended existing domains (devices, clips) and did not introduce
225
+ new modules.
226
+
227
+ ### Known limitations
228
+
229
+ - **MIDI Tool bridge (Chunk 13) — Max-side file search**: the `.amxd` files
230
+ reference `js miditool_bridge.js` relatively. Max normally searches the
231
+ .amxd's folder first, but Live's MIDI Tool instantiation context can
232
+ bypass that. If `Max → Window → Max Console` shows "can't find file
233
+ miditool_bridge.js" when you fire the tool: open Max → Options → File
234
+ Preferences → add `~/Music/Ableton/User Library/MIDI Tools/Max Generators`
235
+ and `~/Music/Ableton/User Library/MIDI Tools/Max Transformations` to the
236
+ File Search Path, save, reload the device.
237
+ - A separate git stash ("pre-existing drift before LOM completeness work"
238
+ with `classify_simpler_slices` in flight) was left intact; the user will
239
+ reconcile it in its own release.
240
+
241
+ ### Not a breaking change
242
+
243
+ Every new tool is additive. No existing tool names, parameters, or return
244
+ shapes changed. Remote Script still boots cleanly on Live 12.0 — the 12.1+
245
+ and 12.3+ tools just return `STATE_ERROR` with a clear message when the host
246
+ lacks the underlying LOM attribute.
247
+
248
+ ## 1.10.9 — Second-pass audit + deferred-bugs shipped (April 18 2026)
249
+
250
+ Completes every non-feature item on the v1.10.8 audit backlog. 2116 → 2132
251
+ passing tests (+16 regression guards). 324 → 325 tools (`check_clip_key_consistency`
252
+ lands from BUG-D1). Every deferred BUG-C and BUG-D entry either ships or is
253
+ scoped to a follow-up feature; BUG-C4 is filed upstream as
254
+ [PrefectHQ/fastmcp#3967](https://github.com/PrefectHQ/fastmcp/issues/3967).
255
+
256
+ ### Ship-stoppers fixed
257
+
258
+ - **`send_capture` phantom 35s hang when receiver is None** —
259
+ [`mcp_server/m4l_bridge.py:441`](mcp_server/m4l_bridge.py). `send_command`
260
+ had a receiver-None guard; `send_capture` didn't. When UDP 9880 failed
261
+ to bind but the cache still reported connected, the OSC packet was
262
+ sent, the capture future was never registered, and the full 35s
263
+ timeout fired with a misleading "device may be busy" error. Added the
264
+ matching 5-line guard so the real cause surfaces immediately.
265
+ - **`utils.py` stale after Control Surface toggle** —
266
+ [`remote_script/LivePilot/__init__.py:43`](remote_script/LivePilot/__init__.py).
267
+ Every handler does `from .utils import get_track, get_device`.
268
+ `importlib.reload(devices)` rebinds those names, but because `utils`
269
+ was not in `_HANDLER_MODULES`, the re-import resolved against the
270
+ stale `sys.modules["LivePilot.utils"]`. Added `utils` first in the
271
+ reload order so edits to the shared helpers pick up on toggle too,
272
+ honoring the dev-workflow guarantee documented at the top of the file.
273
+
274
+ ### New tools
275
+
276
+ - **`check_clip_key_consistency`** (BUG-D1) — parses Splice-style
277
+ filename key tokens (`_D#min`, `_Ebmaj`, `_Cm`, …), cross-checks
278
+ against `get_detected_key`, returns the exact `set_clip_pitch(coarse=±N)`
279
+ call that would realign on mismatch. Handles `#`/`b` accidentals,
280
+ `min`/`m`/`maj` suffixes, absent tokens gracefully.
281
+ - **`get_session_diagnostics(check_clip_keys=True)`** — opt-in scan
282
+ across every audio clip, appending `clip_key_mismatch` warnings with
283
+ the one-call fix attached.
284
+
285
+ ### Features shipped
286
+
287
+ - **Session continuity persistence wired at startup** (BUG from external
288
+ audit). `bind_project_store_from_session()` now computes a project
289
+ fingerprint, opens the matching `ProjectStore`, AND rehydrates
290
+ `_threads` + `_turns` from disk. Wired into `server.py` lifespan with
291
+ a lazy rebind on first `record_turn_resolution` / `open_creative_thread`.
292
+ Creative threads and turn history now survive server restarts — the
293
+ README's "return to a project" claim is now load-bearing.
294
+ - **Taste-aware `propose_next_best_move`** — replaces keyword-only
295
+ matching with `0.55 × keyword + 0.30 × taste_alignment + 0.15 ×
296
+ (1 − avoidance) ± 0.10 × family_bonus`. Cold-start users identical to
297
+ before; users with history get personalized ranking via
298
+ `dimension_weights` and `dimension_avoidances`. New return fields:
299
+ `score_breakdown`, `taste_active`, `taste_evidence_count`.
300
+ - **Evaluation `taste_fit`** — previously hardcoded to `0.0`. Now
301
+ computed from `outcome_history` by matching same-direction deltas on
302
+ the same dimensions: ±0.2 per kept/undone match, neutral 0.5 baseline.
303
+ - **`AutomationGraph.coverage_pct`** (BUG-D2, detection half) — new
304
+ fields `coverage_pct`, `clip_envelope_count`, `clips_scanned`
305
+ distinguish "no automation exists" from "we couldn't probe" from
306
+ "sparse but present". Surfaced in `get_project_brain_summary` as
307
+ `automation_coverage_pct`.
308
+
309
+ ### Refactor (BUG-C1)
310
+
311
+ - **`mcp_server/tools/analyzer.py`** 1069 → 913 LOC. All 32
312
+ `@mcp.tool()` decorators stay in the module (FastMCP registration
313
+ order unchanged), helpers moved to `_analyzer_engine/`:
314
+ `context.py` (SpectralCache/bridge accessors, analyzer health check),
315
+ `sample.py` (Simpler post-load hygiene, filename heuristics),
316
+ `flucoma.py` (FluCoMa hint text, pitch-name table). Same
317
+ package-facade pattern as `_composition_engine` and `_agent_os_engine`.
318
+ - **`sync_metadata::get_domains()` now skips `_*`** directories + files
319
+ under `mcp_server/tools/`. Matches Python private-package convention,
320
+ prevents internal helpers from registering as false domains.
321
+
322
+ ### Resilience (BUG-C3)
323
+
324
+ - **`_get_all_tools()` probe chain extended** in `mcp_server/server.py`
325
+ to 4 paths: existing `_tool_manager._tools` and
326
+ `_local_provider._components`, plus speculative 3.3+ rename
327
+ `_local_provider._tools` and the future public `mcp.list_tools()`.
328
+ Each wrapped in try/except. All-empty fall-through now prints
329
+ `fastmcp.__version__` + the attempted probe labels — prior silent `[]`
330
+ return would disable schema coercion with no signal.
331
+ - **New `_assert_tool_registry_accessible()`** self-test runs at module
332
+ import. Empty registry or a count mismatch against
333
+ `tests/test_tools_contract.py` fails loudly via stderr.
334
+
335
+ ### Upstream (BUG-C4)
336
+
337
+ - **FastMCP feature request filed** —
338
+ [PrefectHQ/fastmcp#3967](https://github.com/PrefectHQ/fastmcp/issues/3967)
339
+ "Feature request: public tool-enumeration API". Migration is a
340
+ no-op once upstream lands a `mcp.list_tools()` or `mcp.tools`
341
+ surface — the probe chain already anticipates both.
342
+
343
+ ### Metadata + docs
344
+
345
+ - **`sync_metadata.py` extended** — catches both `N tools` and hyphenated
346
+ `N-tool`, now covers `manifest.json` + `docs/manual/intelligence.md` +
347
+ `.claude-plugin/marketplace.json`. New prose-claim checks for
348
+ bridge-command count, enriched-device YAML count, and `GENRE_DEFAULTS`
349
+ key count — every narrative number now traces to a code derivation.
350
+ - **README / CLAUDE.md / docs drift closed** — 28→30 bridge commands,
351
+ 81→71 enriched devices, 7→4 genre defaults, 323→325 tool count in
352
+ stale marketplace/plugin/manifest descriptors. Intelligence manual
353
+ example signatures for `record_positive_preference`,
354
+ `record_anti_preference`, `evaluate_move` updated to match the
355
+ shipping APIs.
356
+ - **Skill cleanups** — `livepilot-release` tool-count drift fixed;
357
+ `livepilot-wonder` reference paths corrected to point at their real
358
+ home in `livepilot-core`; arrangement vs composition-engine triggers
359
+ deduplicated (constructive vs analytical split).
360
+ - **New test** `tests/test_claim_consistency.py` — 12 guards running
361
+ `sync_metadata --check` from pytest, verifying `manifest.json` and
362
+ `intelligence.md` stay in the sweep, and asserting that
363
+ `bind_project_store_from_session` keeps a non-test caller.
364
+
365
+ ### Quality-of-life
366
+
367
+ - **`scripts/test.sh`** — blessed test entrypoint always uses `.venv/bin/python`,
368
+ closes the contributor trap where bare `pytest` failed 28 tests on
369
+ system Python.
370
+ - **`.gitignore`** additions: `m4l_device/*.pre-presentation-backup`,
371
+ `m4l_device/*.pre-*-backup`, `.mcp.json.disabled`.
372
+ - **Stale `livepilot-1.10.5.tgz`** removed from the repo root.
373
+
374
+ ---
375
+
3
376
  ## 1.10.8 — Deep audit fix pass (April 18 2026)
4
377
 
5
378
  Outcome of a cross-subsystem audit (Remote Script, MCP server, M4L bridge,
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  <p align="center">
19
19
  An agentic production system for Ableton Live 12.<br>
20
- 324 tools. 45 domains. Device atlas. Splice integration. Auto-composition. Spectral perception. Technique memory.
20
+ 398 tools. 51 domains. Device atlas. Splice integration. Auto-composition. Spectral perception. Technique memory.
21
21
  </p>
22
22
 
23
23
  <br>
@@ -38,7 +38,7 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
38
38
  | Layer | What it provides |
39
39
  |-------|-----------------|
40
40
  | **Deterministic Tools** | Direct control: transport, tracks, clips, notes, devices, scenes, mixing, arrangement, browser, automation |
41
- | **Device Atlas** | Knowledge of every device in Ableton's library — 1305 devices indexed by name, URI, category, tag, and genre. 81 enriched with sonic intelligence. 683 drum kits mapped |
41
+ | **Device Atlas** | Knowledge of every device in Ableton's library — 1305 devices indexed by name, URI, category, tag, and genre. 71 enriched with sonic intelligence. 683 drum kits mapped |
42
42
  | **Sample Engine** | Three-source sample intelligence — searches Ableton's browser, your filesystem, and Splice's catalog simultaneously. 6 fitness critics score every result. 29 processing techniques |
43
43
  | **Spectral Perception** | Real-time ears via M4L — 8-band FFT, RMS/peak metering, Krumhansl-Schmuckler key detection, pitch tracking. Closes the feedback loop so the AI hears its own changes |
44
44
  | **Technique Memory** | Persistent library of production decisions. Save a beat pattern, device chain, or mix template. Recall by mood, genre, or texture across sessions |
@@ -58,7 +58,7 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
58
58
  │ │
59
59
  │ Device Atlas 8-band FFT recall by mood, │
60
60
  │ 1305 devices RMS / peak genre, texture │
61
- 81 enriched pitch tracking 29 techniques │
61
+ 71 enriched pitch tracking 29 techniques │
62
62
  │ 683 drum kits key detection replay into session │
63
63
  │ │
64
64
  │ Sample Engine Corpus Intelligence Taste Graph │
@@ -79,8 +79,8 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
79
79
  │ └─────────────────┼──────────────────┘ │
80
80
  │ ▼ │
81
81
  │ ┌─────────────────┐ │
82
- │ │ 324 MCP Tools │ │
83
- │ │ 45 domains │ │
82
+ │ │ 398 MCP Tools │ │
83
+ │ │ 51 domains │ │
84
84
  │ └────────┬────────┘ │
85
85
  │ │ │
86
86
  │ Remote Script ──┤── TCP 9878 │
@@ -100,15 +100,15 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
100
100
 
101
101
  **MCP Server** (`mcp_server/`) — Python FastMCP server. Validates inputs, routes commands to the Remote Script over TCP, manages the M4L bridge, runs the atlas, sample engine, composer, and all intelligence engines. This is what your AI client connects to.
102
102
 
103
- **M4L Bridge** (`m4l_device/`) — Optional Max for Live Audio Effect on the master track. Provides deep LOM access through Max's LiveAPI that the ControlSurface API can't reach. UDP 9880 (M4L to server) carries spectral data and LiveAPI responses. OSC 9881 (server to M4L) sends commands. 36 bridge tools (backed by 29 bridge commands) for hidden parameters, Simpler internals, warp markers, display values, and Simpler warp / Compressor sidechain writes that live on child objects Python can't reach.
103
+ **M4L Bridge** (`m4l_device/`) — Optional Max for Live Audio Effect on the master track. Provides deep LOM access through Max's LiveAPI that the ControlSurface API can't reach. UDP 9880 (M4L to server) carries spectral data and LiveAPI responses. OSC 9881 (server to M4L) sends commands. The 32 spectral/analyzer tools strictly require the bridge; device and sample tools that call the bridge also have graceful fallbacks, so core functionality works without it. Backed by 30 bridge commands for hidden parameters, Simpler internals, warp markers, display values, and Simpler warp / Compressor sidechain writes that live on child objects Python can't reach.
104
104
 
105
- **Device Atlas** (`mcp_server/atlas/`) — In-memory indexed JSON database. 1305 devices with browser URIs, 81 enriched with YAML sonic intelligence profiles (mood, genre, texture, recommended chains). 6 indexes: by_id, by_name, by_uri, by_category, by_tag, by_genre. The AI never hallucinates a device name or preset — it always resolves against the atlas first.
105
+ **Device Atlas** (`mcp_server/atlas/`) — In-memory indexed JSON database. 1305 devices with browser URIs, 71 enriched with YAML sonic intelligence profiles (mood, genre, texture, recommended chains). 6 indexes: by_id, by_name, by_uri, by_category, by_tag, by_genre. The AI never hallucinates a device name or preset — it always resolves against the atlas first.
106
106
 
107
107
  **Sample Engine** (`mcp_server/sample_engine/`) — Searches three sources simultaneously: BrowserSource (Ableton's library), SpliceSource (local Splice catalog via SQLite), FilesystemSource (user directories). Every result passes through a 6-critic fitness battery (key, tempo, spectral, genre, mood, technical). 29 processing techniques (Surgeon precision vs. Alchemist experimentation). Builds complete sample processing plans with warp, slice, and effect recommendations.
108
108
 
109
109
  **Splice Client** (`mcp_server/splice_client/`) — Searches Splice's catalog through two layers: the local SQLite database (`sounds.db`, already-downloaded samples) and the live gRPC API (full catalog, including samples you haven't downloaded yet). The gRPC client auto-detects Splice's dynamic port via `port.conf`, handles self-signed TLS, and enforces a 5-credit safety floor before any download. Per-call timeouts (5–10s) prevent a hung Splice process from stalling the MCP event loop. Graceful fallback to SQL-only if grpcio isn't installed. No API key needed — authentication comes from the running Splice desktop app.
110
110
 
111
- **Composer** (`mcp_server/composer/`) — Prompt-to-plan pipeline. Parses natural language ("dark minimal techno 128bpm with industrial textures") into a CompositionIntent (genre, mood, tempo, key). Plans layers using role templates (kick, bass, percussion, texture, lead, pad, fx). Compiles to a step-by-step plan of tool calls that the agent executes. Does not execute autonomously — returns the plan. 7 genre defaults (techno, house, ambient, hip-hop, dnb, dub, experimental).
111
+ **Composer** (`mcp_server/composer/`) — Prompt-to-plan pipeline. Parses natural language ("dark minimal techno 128bpm with industrial textures") into a CompositionIntent (genre, mood, tempo, key). Plans layers using role templates (kick, bass, percussion, texture, lead, pad, fx). Compiles to a step-by-step plan of tool calls that the agent executes. Does not execute autonomously — returns the plan. 4 genre defaults (house, techno, trap, ambient) genres outside this set fall back to a neutral layer plan.
112
112
 
113
113
  **Corpus** (`mcp_server/corpus/`) — Parsed device-knowledge markdown converted to queryable Python structures: EmotionalRecipe, GenreChain, PhysicalModelRecipe, AutomationGesture. Feeds Wonder Mode, Sound Design critics, and the Composer with deep creative knowledge at runtime — not just LLM prompts, actual structured data.
114
114
 
@@ -120,7 +120,7 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
120
120
 
121
121
  ## The Intelligence Layer
122
122
 
123
- 12 engines sit on top of the 324 tools. They give the AI musical judgment, not just musical execution.
123
+ 12 engines sit on top of the 398 tools. They give the AI musical judgment, not just musical execution.
124
124
 
125
125
  ### SongBrain — What the Song Is
126
126
 
@@ -156,7 +156,7 @@ When a session is stuck — repeated undos, overpolished loops, no structural pr
156
156
 
157
157
  ### Hook Hunter
158
158
 
159
- Identifies the most salient musical idea — ranks by rhythmic distinctiveness, melodic contour, repetition. Tracks whether hooks are developed, neglected, or undermined. Flags when a transition fails to deliver expected payoff.
159
+ Identifies the most salient musical idea — ranks candidates by recurrence across scenes, motif salience, and section placement (payoff-section boost). Tracks whether hooks are developed, neglected, or undermined, and flags when a transition fails to deliver expected payoff. Rhythm-side ranking is currently heuristic (drum-track detection + clip reuse); true onset-based rhythmic features are on the roadmap.
160
160
 
161
161
  ### Session Continuity
162
162
 
@@ -172,7 +172,7 @@ Every engine follows: **measure before → act → measure after → compare**.
172
172
 
173
173
  ## Tools
174
174
 
175
- 324 tools across 45 domains. Highlights below — [full catalog here](docs/manual/tool-catalog.md).
175
+ 398 tools across 51 domains. Highlights below — [full catalog here](docs/manual/tool-catalog.md).
176
176
 
177
177
  <br>
178
178
 
@@ -204,7 +204,7 @@ Every engine follows: **measure before → act → measure after → compare**.
204
204
  The M4L Analyzer sits on the master track. UDP 9880 carries spectral data to the server. OSC 9881 sends commands back.
205
205
 
206
206
  > [!TIP]
207
- > All 281 core tools work without the analyzer — it adds 36 bridge tools and closes the feedback loop.
207
+ > Most tools work without the analyzer — it adds 32 spectral/analyzer tools (frequency, loudness, perception) and closes the feedback loop.
208
208
 
209
209
  ```
210
210
  SPECTRAL ─────── 8-band frequency decomposition (sub → air)
@@ -232,7 +232,7 @@ The atlas is an in-memory indexed database of Ableton's entire device library.
232
232
 
233
233
  ```
234
234
  1305 devices total
235
- 81 enriched with sonic intelligence (mood, genre, texture, chains)
235
+ 71 enriched with sonic intelligence (mood, genre, texture, chains)
236
236
  683 drum kits mapped with note assignments
237
237
  6 indexes: by_id, by_name, by_uri, by_category, by_tag, by_genre
238
238
  ```
@@ -317,7 +317,7 @@ Prompt-to-plan auto-composition engine.
317
317
  └─────────────────┘
318
318
  ```
319
319
 
320
- - 7 genre defaults: techno, house, ambient, hip-hop, dnb, dub, experimental
320
+ - 4 genre defaults: house, techno, trap, ambient (unknown genres fall back to a neutral plan)
321
321
  - Returns step-by-step plans — the agent executes each tool call in sequence
322
322
  - `compose` — plan a multi-layer composition from text prompt
323
323
  - `augment_with_samples` — plan sample-based layers for existing session
@@ -360,7 +360,7 @@ The V2 intelligence layer. These tools analyze, diagnose, plan, evaluate, and le
360
360
  | Creative Constraints | 5 | constraint activation, reference-inspired variants |
361
361
  | Preview Studio | 5 | variant creation, preview rendering, comparison, commit |
362
362
 
363
- > **[View all 324 tools →](docs/manual/tool-catalog.md)**
363
+ > **[View all 398 tools →](docs/manual/tool-catalog.md)**
364
364
 
365
365
  <br>
366
366
 
@@ -587,7 +587,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for architecture details, code guidelines
587
587
 
588
588
  | Document | What's inside |
589
589
  |----------|---------------|
590
- | [Manual](docs/manual/index.md) | Complete reference: architecture, all 324 tools, workflows |
590
+ | [Manual](docs/manual/index.md) | Complete reference: architecture, all 398 tools, workflows |
591
591
  | [Intelligence Layer](docs/manual/intelligence.md) | How the 12 engines connect — conductor, moves, preview, evaluation |
592
592
  | [Device Atlas](docs/manual/device-atlas.md) | 1305 devices indexed — search, suggest, chain building |
593
593
  | [Samples & Slicing](docs/manual/samples.md) | 3-source search, fitness critics, slice workflows |
Binary file
@@ -95,7 +95,7 @@ function anything() {
95
95
  function dispatch(cmd, args) {
96
96
  switch(cmd) {
97
97
  case "ping":
98
- send_response({"ok": true, "version": "1.10.8"});
98
+ send_response({"ok": true, "version": "1.12.2"});
99
99
  break;
100
100
  case "get_params":
101
101
  cmd_get_params(args);
@@ -1,2 +1,2 @@
1
1
  """LivePilot MCP Server — bridges MCP protocol to Ableton Live."""
2
- __version__ = "1.10.8"
2
+ __version__ = "1.12.2"
@@ -31,6 +31,66 @@ from .policy import apply_hard_rules
31
31
  # ── Sonic Evaluator ──────────────────────────────────────────────────
32
32
 
33
33
 
34
+ def _compute_taste_fit(
35
+ dimension_changes: dict[str, dict],
36
+ outcome_history: Optional[list[dict]],
37
+ ) -> float:
38
+ """Score how well this move aligns with the user's recent taste.
39
+
40
+ Shipped in v1.10.9 — previously hardcoded to 0.0.
41
+
42
+ For each dimension that moved (in ``dimension_changes``), look at the
43
+ user's last few kept/undone outcomes for the same dimension:
44
+ * kept with the same direction of delta → +0.2 per match
45
+ * undone with the same direction of delta → −0.2 per match
46
+
47
+ Returns a value in 0..1 (0.5 = neutral, neither signal). Empty history
48
+ returns 0.5, which is the correct "no information yet" neutral the
49
+ composite score already expects.
50
+
51
+ ``outcome_history`` entries are dicts of the shape::
52
+
53
+ {"dimension": "punch", "delta": 0.12, "kept": True}
54
+
55
+ Callers that pass a richer shape should extract those three fields.
56
+ Malformed entries are skipped silently so a schema bump upstream can't
57
+ break the evaluator.
58
+ """
59
+ if not outcome_history or not dimension_changes:
60
+ return 0.5
61
+
62
+ # Only weigh the most recent slice — taste drifts, and older signals
63
+ # shouldn't veto a current evaluation.
64
+ recent = outcome_history[-10:]
65
+
66
+ adjustment = 0.0
67
+ matched = 0
68
+ for dim, change in dimension_changes.items():
69
+ current_delta = change.get("delta", 0.0)
70
+ current_sign = 1 if current_delta > 0 else (-1 if current_delta < 0 else 0)
71
+ if current_sign == 0:
72
+ continue
73
+ for entry in recent:
74
+ if not isinstance(entry, dict):
75
+ continue
76
+ if entry.get("dimension") != dim:
77
+ continue
78
+ past_delta = entry.get("delta")
79
+ if not isinstance(past_delta, (int, float)):
80
+ continue
81
+ past_sign = 1 if past_delta > 0 else (-1 if past_delta < 0 else 0)
82
+ if past_sign != current_sign:
83
+ continue
84
+ kept = bool(entry.get("kept", False))
85
+ adjustment += 0.2 if kept else -0.2
86
+ matched += 1
87
+
88
+ if matched == 0:
89
+ return 0.5
90
+ # Neutral baseline 0.5 + averaged adjustment, clamped to [0, 1].
91
+ return _clamp(0.5 + adjustment / matched)
92
+
93
+
34
94
  def evaluate_sonic_move(
35
95
  request: EvaluationRequest,
36
96
  outcome_history: Optional[list[dict]] = None,
@@ -109,12 +169,13 @@ def evaluate_sonic_move(
109
169
  measurable_component = _clamp(0.5 + measurable_delta)
110
170
  preservation = _clamp(1.0 - collateral_damage * 5)
111
171
  confidence = measurable_count / max(len(targets), 1)
172
+ taste_fit = _compute_taste_fit(dimension_changes, outcome_history)
112
173
 
113
174
  score = (
114
175
  0.30 * goal_fit
115
176
  + 0.25 * measurable_component
116
177
  + 0.15 * preservation
117
- + 0.10 * 0.0 # taste_fit: placeholder, no history in fabric v1
178
+ + 0.10 * taste_fit
118
179
  + 0.10 * confidence
119
180
  + 0.10 * 1.0 # reversibility: 1.0 for undo-able moves
120
181
  )