livepilot 1.18.0 → 1.18.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.
- package/CHANGELOG.md +119 -0
- package/mcp_server/__init__.py +1 -1
- package/mcp_server/composer/branch_producer.py +12 -1
- package/mcp_server/composer/layer_planner.py +13 -0
- package/mcp_server/composer/prompt_parser.py +12 -1
- package/mcp_server/experiment/tools.py +10 -6
- package/package.json +1 -1
- package/remote_script/LivePilot/__init__.py +1 -1
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,124 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.18.1 — Director HIGH-severity patches (April 23 2026)
|
|
4
|
+
|
|
5
|
+
Patch release addressing 4 of the 12 known issues documented in v1.18.0.
|
|
6
|
+
All three HIGH-severity bugs are fixed, plus 6 medium-severity items
|
|
7
|
+
(data cleanups and doc clarifications). All fixes landed with
|
|
8
|
+
regression-guard tests. 2779 project tests pass + 1 xfail (pre-existing).
|
|
9
|
+
|
|
10
|
+
### High-severity fixes
|
|
11
|
+
|
|
12
|
+
- **#1 `create_experiment` auto-proposal returned single-char move_ids.**
|
|
13
|
+
Python unpacking bug at `mcp_server/experiment/tools.py:267` —
|
|
14
|
+
`[m[0] for m, _ in scored]` indexed the first character of each
|
|
15
|
+
move_id string. Fix: `[move_id for move_id, _ in scored[:limit]]`.
|
|
16
|
+
Pre-fix, calling the director's Flow B with no explicit seeds/move_ids
|
|
17
|
+
would always fail at run_experiment with `"Move t not found"`.
|
|
18
|
+
|
|
19
|
+
- **#2 `propose_composer_branches` ignored concept-packet arrangement
|
|
20
|
+
idioms.** Dub-techno prompts (referencing Basic Channel, Gas, etc.)
|
|
21
|
+
were collapsed to the generic techno template (Intro→Build→Drop→
|
|
22
|
+
Breakdown→Drop 2→Outro with 6 standard layers). Fix: "dub techno"
|
|
23
|
+
is now its own canonical genre in `GENRE_DEFAULTS` and
|
|
24
|
+
`SECTION_TEMPLATES`, with a continuous-evolution scaffold
|
|
25
|
+
(Dawn→Pulse→Chord→Depth→Withdraw→Return, 3-5 layers, energy 0.4).
|
|
26
|
+
Removed the `dub techno → techno` alias that was causing the
|
|
27
|
+
collapse; added `dub-techno` (hyphenated) as an alias to the new
|
|
28
|
+
canonical.
|
|
29
|
+
|
|
30
|
+
- **#3 Director raw-tool-call path bypassed the action ledger.**
|
|
31
|
+
Min-effective doc fix: Phase 6 of `livepilot-creative-director`
|
|
32
|
+
now mandates `add_session_memory(category="move_executed", ...)`
|
|
33
|
+
after raw-tool execution batches, so anti-repetition detection on
|
|
34
|
+
subsequent creative turns isn't blind. Added a state-inference
|
|
35
|
+
fallback table in `anti-repetition-rules.md` for when the ledger
|
|
36
|
+
is still empty (infer recent family from loaded devices, non-default
|
|
37
|
+
mixer state, clip slot contents). Full architectural fix (route all
|
|
38
|
+
Phase 6 execution through `apply_semantic_move`/`commit_experiment`)
|
|
39
|
+
is deferred to v1.19.
|
|
40
|
+
|
|
41
|
+
### Medium-severity fixes
|
|
42
|
+
|
|
43
|
+
- **#4 Ping Pong Delay ghost packet.** `affordances/devices/ping-pong-delay.yaml`
|
|
44
|
+
previously described a standalone device that doesn't exist in
|
|
45
|
+
Live 12 (`search_browser` returned empty). Rewritten as an explicit
|
|
46
|
+
mode-alias for Echo with `Channel Mode = 1`. `echo.yaml` now prominently
|
|
47
|
+
documents the Channel Mode enum (0=Stereo, 1=Ping Pong, 2=Mid/Side).
|
|
48
|
+
|
|
49
|
+
- **#5 Auto Filter affordance used legacy 20-135 Hz ranges.** Modern
|
|
50
|
+
`AutoFilter2` class (Live 12 default) uses 0-1 normalized for
|
|
51
|
+
Frequency, Resonance, and LFO Amount. Live-verified mapping (raw
|
|
52
|
+
0.45 → display 448 Hz) is now documented in the YAML. Legacy/modern
|
|
53
|
+
distinction clarified in the notes.
|
|
54
|
+
|
|
55
|
+
- **#9 `propose_composer_branches` silent count degradation.** Explicit
|
|
56
|
+
`count=3` at `freshness<0.7` was silently returning 2 seeds because
|
|
57
|
+
`layer_contrast` was gated behind `freshness>=0.7`. Fix: explicit
|
|
58
|
+
`count>=3` now raises freshness internally to 0.7 to admit all
|
|
59
|
+
strategies. Default `count=2` (no override) still respects the
|
|
60
|
+
freshness gate — preserves the "freshness shapes default strategy
|
|
61
|
+
count" contract and the existing tests that assert it.
|
|
62
|
+
|
|
63
|
+
- **#12 Low-novelty-budget escape hatch for 3-plan diversity rule.**
|
|
64
|
+
`move-family-diversity-rule.md` gained a dedicated section: when
|
|
65
|
+
`novelty_budget < 0.35` (user prompts like "keep the vibe, just
|
|
66
|
+
cleaner"), 1-2 family plans is acceptable and honest. Prevents the
|
|
67
|
+
rule from fighting cleanup requests.
|
|
68
|
+
|
|
69
|
+
### Bonus fixes
|
|
70
|
+
|
|
71
|
+
- **`batch_set_parameters` schema gotcha documented.** Core SKILL.md
|
|
72
|
+
Rule 15 now shows the correct dict-of-dicts shape:
|
|
73
|
+
`{"ParamName": {"value": v}}`. Live verification surfaced this during
|
|
74
|
+
v1.18.0 pressure testing.
|
|
75
|
+
|
|
76
|
+
- **Convolution Reverb phantom `ir_length` already fixed in v1.18.0
|
|
77
|
+
commit 9** — regression test now guards against reintroduction.
|
|
78
|
+
|
|
79
|
+
### Tests added
|
|
80
|
+
|
|
81
|
+
- `test_create_experiment_auto_proposal_no_m0_bug` (source-pattern
|
|
82
|
+
regression guard)
|
|
83
|
+
- `test_create_experiment_auto_proposal_functional` (mirror-logic
|
|
84
|
+
integration check)
|
|
85
|
+
- `test_composer_dub_techno_prompt_avoids_drop_scaffold` (no Drop/Drop 2
|
|
86
|
+
on Basic Channel prompts)
|
|
87
|
+
- `test_propose_composer_branches_honors_explicit_count` (count=3
|
|
88
|
+
returns 3 regardless of freshness)
|
|
89
|
+
- `test_medium_freshness_count_3_unlocks_all_strategies` (renamed from
|
|
90
|
+
test encoding the pre-fix bug as desired behavior)
|
|
91
|
+
- `test_medium_freshness_default_count_gives_two` (preserves
|
|
92
|
+
default-count-respects-freshness contract)
|
|
93
|
+
- `test_ping_pong_delay_is_documented_as_echo_mode`
|
|
94
|
+
- `test_auto_filter_ranges_are_normalized_for_modern_class`
|
|
95
|
+
- `test_low_novelty_escape_hatch_documented`
|
|
96
|
+
- `test_batch_set_parameters_schema_documented`
|
|
97
|
+
- `test_director_phase6_records_ledger_marker`
|
|
98
|
+
- `test_anti_repetition_has_state_inference_fallback`
|
|
99
|
+
|
|
100
|
+
### Still open for v1.18.2 / v1.19
|
|
101
|
+
|
|
102
|
+
8 items remain from the v1.18.0 Known Issues list:
|
|
103
|
+
|
|
104
|
+
- **#7 Packet `avoid` list runtime enforcement** (currently advisory —
|
|
105
|
+
pre-flight check against tool args needed)
|
|
106
|
+
- **#8 `locked_dimensions` runtime enforcement** (same pattern as #7)
|
|
107
|
+
- **#10 Wonder Mode zero-variant degradation on empty session context**
|
|
108
|
+
- **#11 Evaluation tie-break coarseness** (3-way ties at score 0.6)
|
|
109
|
+
- **Experiment state continuity between branches** (before-snapshot
|
|
110
|
+
drift)
|
|
111
|
+
- **Hybrid-packet compilation algorithm** (union/intersection logic
|
|
112
|
+
for "Basic Channel meets Dilla")
|
|
113
|
+
- **~20 missing genre YAMLs** (downtempo, boom_bap, lo_fi, synthwave,
|
|
114
|
+
techno, etc.) — xfail test tracks this
|
|
115
|
+
- **Full architectural fix for #3** (route director Phase 6 through
|
|
116
|
+
semantic_move commits, replacing the doc-level fix shipped here)
|
|
117
|
+
|
|
118
|
+
These are each scoped for focused follow-up sessions — they need new
|
|
119
|
+
infrastructure or architectural decisions not suitable for a patch
|
|
120
|
+
release.
|
|
121
|
+
|
|
3
122
|
## 1.18.0 — Creative Director + concept packets + device affordances (April 23 2026)
|
|
4
123
|
|
|
5
124
|
A structural feature release. Addresses the "agent doesn't variate
|
package/mcp_server/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""LivePilot MCP Server — bridges MCP protocol to Ableton Live."""
|
|
2
|
-
__version__ = "1.18.
|
|
2
|
+
__version__ = "1.18.1"
|
|
@@ -124,7 +124,18 @@ def propose_composer_branches(
|
|
|
124
124
|
|
|
125
125
|
intent = parse_prompt(request_text)
|
|
126
126
|
|
|
127
|
-
#
|
|
127
|
+
# v1.18.1 #9 fix: explicit count=3 overrides the freshness default.
|
|
128
|
+
# Pre-fix, count=3 at freshness=0.6 silently returned 2 (canonical +
|
|
129
|
+
# energy_shift only; layer_contrast was gated behind freshness>=0.7).
|
|
130
|
+
# Now: caller asking for all 3 strategies gets them by internally
|
|
131
|
+
# raising freshness to 0.7. Count=2 (the default) does NOT raise
|
|
132
|
+
# freshness — the freshness gate still caps at 1 on low-freshness
|
|
133
|
+
# runs, which is the documented "freshness cautiously shapes default
|
|
134
|
+
# strategy count" contract.
|
|
135
|
+
if count >= 3:
|
|
136
|
+
freshness = max(freshness, 0.7)
|
|
137
|
+
|
|
138
|
+
# Gate high-novelty strategies on (possibly-raised) freshness.
|
|
128
139
|
if freshness < 0.4:
|
|
129
140
|
strategies = [_STRATEGIES[0]] # canonical only
|
|
130
141
|
elif freshness < 0.7:
|
|
@@ -172,6 +172,19 @@ SECTION_TEMPLATES: dict[str, list[dict]] = {
|
|
|
172
172
|
{"name": "Drop 2", "bars": 16, "layers": ["drums", "bass", "lead", "percussion", "vocal", "texture"]},
|
|
173
173
|
{"name": "Outro", "bars": 8, "layers": ["drums:-6dB", "texture", "pad"]},
|
|
174
174
|
],
|
|
175
|
+
# Dub techno — continuous-evolution aesthetic. No Drop structure, no
|
|
176
|
+
# Build/Break cycle. Section names reflect dub-techno arrangement idioms:
|
|
177
|
+
# slow reveal, subtraction before addition, return deeper not louder.
|
|
178
|
+
# Source: concepts/artists/basic-channel.yaml arrangement_idioms +
|
|
179
|
+
# live-verification finding from v1.18.0 CHANGELOG #2. v1.18.1 #2 fix.
|
|
180
|
+
"dub techno": [
|
|
181
|
+
{"name": "Dawn", "bars": 16, "layers": ["texture:-12dB"]},
|
|
182
|
+
{"name": "Pulse", "bars": 16, "layers": ["drums:-6dB", "texture"]},
|
|
183
|
+
{"name": "Chord", "bars": 32, "layers": ["drums", "bass", "pad:-6dB", "texture"]},
|
|
184
|
+
{"name": "Depth", "bars": 32, "layers": ["drums", "bass", "pad", "texture"]},
|
|
185
|
+
{"name": "Withdraw", "bars": 16, "layers": ["pad:-6dB", "texture:-6dB"]},
|
|
186
|
+
{"name": "Return", "bars": 16, "layers": ["texture:-12dB"]},
|
|
187
|
+
],
|
|
175
188
|
"house": [
|
|
176
189
|
{"name": "Intro", "bars": 8, "layers": ["drums:-6dB", "pad"]},
|
|
177
190
|
{"name": "Verse", "bars": 16, "layers": ["drums", "bass", "pad"]},
|
|
@@ -51,6 +51,13 @@ GENRE_DEFAULTS: dict[str, dict] = {
|
|
|
51
51
|
"tempo": 128, "keys": ["Am", "Cm"], "energy": 0.7,
|
|
52
52
|
"layers_min": 5, "layers_max": 7,
|
|
53
53
|
},
|
|
54
|
+
# Dub techno is its own canonical genre — continuous-evolution aesthetic
|
|
55
|
+
# referencing Basic Channel / Rhythm & Sound / Gas. Previously aliased to
|
|
56
|
+
# "techno" which defaulted to Drop-based scaffolds (v1.18.1 #2 fix).
|
|
57
|
+
"dub techno": {
|
|
58
|
+
"tempo": 125, "keys": ["Am", "Em"], "energy": 0.4,
|
|
59
|
+
"layers_min": 3, "layers_max": 5,
|
|
60
|
+
},
|
|
54
61
|
"house": {
|
|
55
62
|
"tempo": 124, "keys": ["Cm", "Fm"], "energy": 0.6,
|
|
56
63
|
"layers_min": 5, "layers_max": 6,
|
|
@@ -93,7 +100,11 @@ _GENRE_ALIASES: dict[str, str] = {
|
|
|
93
100
|
"industrial techno": "techno",
|
|
94
101
|
"minimal techno": "techno",
|
|
95
102
|
"detroit techno": "techno",
|
|
96
|
-
"dub techno"
|
|
103
|
+
# NOTE: "dub techno" is intentionally NOT aliased to "techno" —
|
|
104
|
+
# it's now its own canonical genre with dub-appropriate defaults
|
|
105
|
+
# (see GENRE_DEFAULTS above) and a non-Drop section template (see
|
|
106
|
+
# layer_planner.SECTION_TEMPLATES). v1.18.1 #2 fix.
|
|
107
|
+
"dub-techno": "dub techno",
|
|
97
108
|
}
|
|
98
109
|
|
|
99
110
|
|
|
@@ -244,18 +244,22 @@ def create_experiment(
|
|
|
244
244
|
|
|
245
245
|
# ── Mode 2/3: legacy move_ids path ──────────────────────────────────
|
|
246
246
|
if not move_ids:
|
|
247
|
-
# Auto-propose moves from the registry
|
|
247
|
+
# Auto-propose moves from the registry by keyword overlap.
|
|
248
|
+
# v1.18.1 #1 fix: the previous selector indexed the first character
|
|
249
|
+
# of each move_id (a Python unpacking trap — the variable was
|
|
250
|
+
# already the full string, the [0] subscript sliced into it).
|
|
251
|
+
# Result pre-fix: single-char move_ids like 't', 'w', 'm' that
|
|
252
|
+
# failed at run_experiment with "Move t not found". Now the whole
|
|
253
|
+
# move_id string is kept.
|
|
248
254
|
from ..semantic_moves import registry
|
|
249
|
-
from ..semantic_moves.tools import propose_next_best_move
|
|
250
|
-
# Use the propose function's logic directly
|
|
251
255
|
all_moves = list(registry._REGISTRY.values())
|
|
252
256
|
request_lower = request_text.lower()
|
|
253
|
-
|
|
257
|
+
request_words = set(request_lower.split())
|
|
258
|
+
scored: list[tuple[str, float]] = []
|
|
254
259
|
for move in all_moves:
|
|
255
260
|
score = 0.0
|
|
256
261
|
move_words = set(move.move_id.replace("_", " ").split())
|
|
257
262
|
intent_words = set(move.intent.lower().split())
|
|
258
|
-
request_words = set(request_lower.split())
|
|
259
263
|
overlap = request_words & (move_words | intent_words)
|
|
260
264
|
score += len(overlap) * 0.3
|
|
261
265
|
for dim in move.targets:
|
|
@@ -264,7 +268,7 @@ def create_experiment(
|
|
|
264
268
|
if score > 0.1:
|
|
265
269
|
scored.append((move.move_id, score))
|
|
266
270
|
scored.sort(key=lambda x: -x[1])
|
|
267
|
-
move_ids = [
|
|
271
|
+
move_ids = [move_id for move_id, _ in scored[:limit]] if scored else []
|
|
268
272
|
|
|
269
273
|
if not move_ids:
|
|
270
274
|
return {"error": "No matching semantic moves found for this request"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livepilot",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.1",
|
|
4
4
|
"mcpName": "io.github.dreamrec/livepilot",
|
|
5
5
|
"description": "Agentic production system for Ableton Live 12 — 427 tools, 52 domains. Device atlas (1305 devices), sample engine (Splice + browser + filesystem), auto-composition, spectral perception, technique memory, creative intelligence (12 engines)",
|
|
6
6
|
"author": "Pilot Studio",
|
|
@@ -5,7 +5,7 @@ Entry point for the ControlSurface. Ableton calls create_instance(c_instance)
|
|
|
5
5
|
when this script is selected in Preferences > Link, Tempo & MIDI.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "1.18.
|
|
8
|
+
__version__ = "1.18.1"
|
|
9
9
|
|
|
10
10
|
from _Framework.ControlSurface import ControlSurface
|
|
11
11
|
from . import router
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/dreamrec/LivePilot",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.18.
|
|
9
|
+
"version": "1.18.1",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "livepilot",
|
|
14
|
-
"version": "1.18.
|
|
14
|
+
"version": "1.18.1",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
}
|