livepilot 1.21.4 → 1.22.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 +171 -0
- package/README.md +1 -1
- package/m4l_device/LivePilot_Analyzer.amxd +0 -0
- package/mcp_server/__init__.py +1 -1
- package/mcp_server/atlas/__init__.py +52 -5
- package/mcp_server/atlas/tools.py +8 -2
- 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,176 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.22.1 — Bundled enrichment coverage gate (April 25 2026)
|
|
4
|
+
|
|
5
|
+
Closes the one item carried from v1.22.0's atlas-separation work: a
|
|
6
|
+
visibility + soft-gate for the drift between the atlas file's
|
|
7
|
+
self-reported enrichment count and the YAML files on disk.
|
|
8
|
+
|
|
9
|
+
### What changed
|
|
10
|
+
|
|
11
|
+
Two enrichment numbers now surface in `sync_metadata --check`:
|
|
12
|
+
|
|
13
|
+
- **`enriched=N`** (existing) — YAML profiles authored in `mcp_server/atlas/enrichments/`. Measures "what's available for merge."
|
|
14
|
+
- **`bundled_enriched=N`** (new) — `stats.enriched_devices` from the shipped `mcp_server/atlas/device_atlas.json`. Measures "what the last scan_full_library run actually applied at build time."
|
|
15
|
+
|
|
16
|
+
These measure different things. YAML count is authoring effort; bundled
|
|
17
|
+
count is runtime coverage as of the atlas's last regeneration. They
|
|
18
|
+
drift naturally (someone adds a YAML without re-scanning) — but until
|
|
19
|
+
v1.22.1 the drift was invisible to CI.
|
|
20
|
+
|
|
21
|
+
### Soft gate
|
|
22
|
+
|
|
23
|
+
Warns (doesn't fail) on two conditions:
|
|
24
|
+
|
|
25
|
+
1. **`bundled_enriched == 0`** with YAMLs on disk — scanner never ran
|
|
26
|
+
or failed completely. Most likely the repo's bundled atlas got
|
|
27
|
+
accidentally emptied or mis-committed.
|
|
28
|
+
2. **`bundled_enriched / yaml_count < 50%`** — scanner truncated or had
|
|
29
|
+
severe pack-coverage failures. Current shipped atlas is 87/120 = 72%
|
|
30
|
+
coverage (healthy — the 33 orphan gap is the miditool-domain YAMLs
|
|
31
|
+
that Live's browser scanner can't see).
|
|
32
|
+
|
|
33
|
+
Why soft: the relationship `yaml >= bundled` is only true in
|
|
34
|
+
single-pack-scan scenarios. Multi-category duplication (native +
|
|
35
|
+
max_for_live + user_library for the same device_id) can push
|
|
36
|
+
`bundled > yaml`. Strict equality would produce false alarms. The soft
|
|
37
|
+
gate catches the two real failure modes while staying silent on healthy
|
|
38
|
+
cases.
|
|
39
|
+
|
|
40
|
+
### Output format
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Source of truth: version=1.22.1, tools=430, domains=53, bridge_cmds=31,
|
|
44
|
+
enriched=120, bundled_enriched=87, genres=4, moves=44,
|
|
45
|
+
analyzer_tools=38, atlas_devices=5264
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Warnings (if any) print above the fail/pass line with a ⚠️ header,
|
|
49
|
+
separate from the issue list. The exit code is unchanged — warnings
|
|
50
|
+
don't fail CI.
|
|
51
|
+
|
|
52
|
+
### Tests
|
|
53
|
+
|
|
54
|
+
7 new TDD tests in `tests/test_claim_consistency.py`. Full suite: 3143
|
|
55
|
+
pass (3136 prior + 7 new), 1 skipped.
|
|
56
|
+
|
|
57
|
+
### Why this is a patch, not a feature
|
|
58
|
+
|
|
59
|
+
Pure CI-gate tightening. Zero user-visible runtime behavior change;
|
|
60
|
+
the only observable delta is one additional field in the banner plus
|
|
61
|
+
the possibility of a soft-warning line during `sync_metadata --check`.
|
|
62
|
+
No new tools, no atlas behavior change. The v1.22.0 user/bundled split
|
|
63
|
+
is the feature release; v1.22.1 is its mechanical follow-through.
|
|
64
|
+
|
|
65
|
+
## 1.22.0 — User atlas separation: ~/.livepilot/atlas/ (April 25 2026)
|
|
66
|
+
|
|
67
|
+
First v1.22 release. Splits the device atlas into two files that serve
|
|
68
|
+
different roles — a long-standing ambiguity that finally bit hard enough
|
|
69
|
+
to be worth fixing at minor-version scope.
|
|
70
|
+
|
|
71
|
+
### What changed
|
|
72
|
+
|
|
73
|
+
**New: `~/.livepilot/atlas/device_atlas.json`** — the **user atlas**.
|
|
74
|
+
Written by `scan_full_library` on your machine. Reflects YOUR installed
|
|
75
|
+
packs, User Library, and plugins. Lives in the user-data directory
|
|
76
|
+
(same convention as `~/.livepilot/memory/`) so `npm install livepilot`
|
|
77
|
+
upgrades can't blow it away.
|
|
78
|
+
|
|
79
|
+
**Unchanged: `mcp_server/atlas/device_atlas.json`** — the **bundled
|
|
80
|
+
baseline**. Ships with the package (still 5264 devices, 120 enriched
|
|
81
|
+
— stock Ableton 12 Suite inventory). Gives fresh installs a functional
|
|
82
|
+
atlas before any personalized scan has run.
|
|
83
|
+
|
|
84
|
+
**Resolution** at load time: user atlas wins if present, else bundled
|
|
85
|
+
baseline falls through. Writes **always** go to the user path; the
|
|
86
|
+
bundled path is read-only from the scanner's perspective.
|
|
87
|
+
|
|
88
|
+
### Why this matters
|
|
89
|
+
|
|
90
|
+
Prior to v1.22.0, the single `mcp_server/atlas/device_atlas.json` file
|
|
91
|
+
served three conflicting roles — repo seed, personal scan cache, and
|
|
92
|
+
runtime index. Three bugs resulted:
|
|
93
|
+
|
|
94
|
+
1. **`npm install livepilot` wiped personal scans.** Every package
|
|
95
|
+
update overwrote the installed atlas with the bundled baseline. Users
|
|
96
|
+
who had carefully scanned their library (30-90 seconds per scan) lost
|
|
97
|
+
that work on every upgrade with no warning.
|
|
98
|
+
2. **Dev installs polluted the repo.** Contributors running
|
|
99
|
+
LivePilot from a git checkout would scan their library (to test atlas
|
|
100
|
+
tools against live Ableton) and accidentally commit their personal
|
|
101
|
+
scan — pack names, user-library previews — to the public repo. This
|
|
102
|
+
happened once in the v1.21.x cycle and was the proximate trigger for
|
|
103
|
+
v1.22.
|
|
104
|
+
3. **The "enriched" count ambiguity.** A single atlas file couldn't
|
|
105
|
+
honestly answer "how many devices are enriched?" — the right number
|
|
106
|
+
differed depending on whether you meant the bundled baseline (87 per
|
|
107
|
+
the scanner's last truncated pass), YAML files authored on disk (120),
|
|
108
|
+
or runtime coverage including native/M4L duplicates (137+ on a
|
|
109
|
+
fully-scanned install). The user/bundled split clarifies this by
|
|
110
|
+
letting each file carry its own honest count.
|
|
111
|
+
|
|
112
|
+
### Migration for existing users
|
|
113
|
+
|
|
114
|
+
Users with a personalized scan in `mcp_server/atlas/device_atlas.json`
|
|
115
|
+
(most dev-install contributors) can migrate in one command:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
mkdir -p ~/.livepilot/atlas
|
|
119
|
+
cp "$(python3 -c 'import mcp_server.atlas; print(mcp_server.atlas.BUNDLED_ATLAS_PATH)')" \
|
|
120
|
+
~/.livepilot/atlas/device_atlas.json
|
|
121
|
+
# Then optionally restore the bundled baseline to its shipped state:
|
|
122
|
+
git -C $(python3 -c 'import mcp_server.atlas, pathlib; print(pathlib.Path(mcp_server.atlas.__file__).parents[2])') \
|
|
123
|
+
checkout mcp_server/atlas/device_atlas.json
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Users on the npm-installed path (no personalized scan yet) need nothing
|
|
127
|
+
— the next `scan_full_library` call will write to the new user path
|
|
128
|
+
automatically.
|
|
129
|
+
|
|
130
|
+
### Code changes
|
|
131
|
+
|
|
132
|
+
- `mcp_server/atlas/__init__.py` — new module-level constants
|
|
133
|
+
`BUNDLED_ATLAS_PATH`, `USER_ATLAS_DIR`, `USER_ATLAS_PATH`, and
|
|
134
|
+
function `_resolve_atlas_path()`. Existing `ATLAS_PATH` kept as a
|
|
135
|
+
backward-compat alias pointing at the resolved value.
|
|
136
|
+
- `mcp_server/atlas/tools.py::scan_full_library` — writes to
|
|
137
|
+
`USER_ATLAS_PATH` and creates the user-data directory on demand.
|
|
138
|
+
Enrichments still read from the bundled package (they're authored
|
|
139
|
+
in-repo under `mcp_server/atlas/enrichments/`).
|
|
140
|
+
|
|
141
|
+
### Tests
|
|
142
|
+
|
|
143
|
+
8 new TDD regression tests in `tests/test_atlas_user_override.py`:
|
|
144
|
+
|
|
145
|
+
- `test_bundled_path_is_in_package_dir`
|
|
146
|
+
- `test_user_path_is_in_home_dir`
|
|
147
|
+
- `test_resolver_returns_user_path_when_present`
|
|
148
|
+
- `test_resolver_falls_back_to_bundled_when_user_atlas_missing`
|
|
149
|
+
- `test_atlas_manager_loads_from_user_path_when_present`
|
|
150
|
+
- `test_atlas_manager_falls_back_to_bundled_when_user_atlas_missing`
|
|
151
|
+
- `test_scan_full_library_writes_to_user_path`
|
|
152
|
+
- `test_user_atlas_dir_created_if_missing`
|
|
153
|
+
|
|
154
|
+
Full suite: 3136 pass (3128 prior + 8 new), 1 skipped.
|
|
155
|
+
|
|
156
|
+
### Documentation
|
|
157
|
+
|
|
158
|
+
- `docs/manual/getting-started.md` — new "Step 5 (optional): Personalize
|
|
159
|
+
the device atlas" section.
|
|
160
|
+
- `docs/manual/dev-install.md` — new "3a. User atlas vs bundled atlas"
|
|
161
|
+
subsection, critical for contributors.
|
|
162
|
+
- `docs/manual/device-atlas.md` — header callout on the two-file split.
|
|
163
|
+
- `CLAUDE.md` + `README.md` — short pointers to the new resolver.
|
|
164
|
+
|
|
165
|
+
### Carried to future releases
|
|
166
|
+
|
|
167
|
+
The atlas schema-canonicalization originally deferred from the v1.21.2
|
|
168
|
+
audit is now **partially closed**: the user/bundled split makes the
|
|
169
|
+
"which number counts as enriched?" question honest per-file, but the
|
|
170
|
+
sync_metadata gate for `stats.enriched_devices` vs YAML file count
|
|
171
|
+
hasn't been added. Deferred to a future patch because it's orthogonal
|
|
172
|
+
to the user-atlas split.
|
|
173
|
+
|
|
3
174
|
## 1.21.4 — v1.21.2 audit carry-over: slashed-compound filler + dev-install runbook (April 25 2026)
|
|
4
175
|
|
|
5
176
|
Ships two items the v1.21.2 audit #2 deferred to v1.22 but that turned
|
package/README.md
CHANGED
|
@@ -105,7 +105,7 @@ Most MCP servers are tool collections — they execute commands. LivePilot is an
|
|
|
105
105
|
|
|
106
106
|
**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 38 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 31 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.
|
|
107
107
|
|
|
108
|
-
**Device Atlas** (`mcp_server/atlas/`) — In-memory indexed JSON database. 5264 devices with browser URIs, 120 enriched with YAML sonic intelligence profiles (mood, genre, texture, recommended chains). 7 indexes: by_id, by_name, by_uri, by_category, by_tag, by_genre, by_pack. Reverse-index `device_techniques_index.json` powers `atlas_techniques_for_device` (146 cross-references across 58 devices). The AI never hallucinates a device name or preset — it always resolves against the atlas first.
|
|
108
|
+
**Device Atlas** (`mcp_server/atlas/`) — In-memory indexed JSON database. 5264 devices with browser URIs (bundled baseline), 120 enriched with YAML sonic intelligence profiles (mood, genre, texture, recommended chains). 7 indexes: by_id, by_name, by_uri, by_category, by_tag, by_genre, by_pack. Reverse-index `device_techniques_index.json` powers `atlas_techniques_for_device` (146 cross-references across 58 devices). The AI never hallucinates a device name or preset — it always resolves against the atlas first. **v1.22.0+**: run `scan_full_library` after install to index YOUR packs + User Library + plugins into `~/.livepilot/atlas/device_atlas.json` — your personal atlas overrides the baseline and survives npm updates.
|
|
109
109
|
|
|
110
110
|
**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.
|
|
111
111
|
|
|
Binary file
|
package/mcp_server/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""LivePilot MCP Server — bridges MCP protocol to Ableton Live."""
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.22.1"
|
|
@@ -519,28 +519,75 @@ class AtlasManager:
|
|
|
519
519
|
from pathlib import Path
|
|
520
520
|
from ..services.singletons import Singleton
|
|
521
521
|
|
|
522
|
-
|
|
522
|
+
# v1.22.0: the atlas now has TWO possible homes —
|
|
523
|
+
#
|
|
524
|
+
# BUNDLED_ATLAS_PATH — mcp_server/atlas/device_atlas.json
|
|
525
|
+
# Ships with the package. Gives fresh installs a functional
|
|
526
|
+
# baseline device index before any personalized scan has run.
|
|
527
|
+
# Updated only when the repo's canonical baseline is regenerated.
|
|
528
|
+
#
|
|
529
|
+
# USER_ATLAS_PATH — ~/.livepilot/atlas/device_atlas.json
|
|
530
|
+
# Written by scan_full_library on the user's machine. Reflects
|
|
531
|
+
# their actual installed packs, User Library, and plugins. Lives
|
|
532
|
+
# in the user-data directory (same convention as
|
|
533
|
+
# ~/.livepilot/memory/) so npm updates can't blow it away.
|
|
534
|
+
#
|
|
535
|
+
# Resolution order at load time: user atlas wins if present, else
|
|
536
|
+
# bundled baseline. Written scans ALWAYS go to the user path — never
|
|
537
|
+
# the bundled path — so the repo/npm package stays clean regardless of
|
|
538
|
+
# where a user runs scan_full_library from. This split lands in v1.22.0
|
|
539
|
+
# and solves three prior issues (see tests/test_atlas_user_override.py
|
|
540
|
+
# for the full rationale).
|
|
541
|
+
BUNDLED_ATLAS_PATH = Path(__file__).parent / "device_atlas.json"
|
|
542
|
+
USER_ATLAS_DIR = Path.home() / ".livepilot" / "atlas"
|
|
543
|
+
USER_ATLAS_PATH = USER_ATLAS_DIR / "device_atlas.json"
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def _resolve_atlas_path() -> Path:
|
|
547
|
+
"""Return the effective atlas path — user if present, bundled if not.
|
|
548
|
+
|
|
549
|
+
Called from _build_atlas and get_atlas. Kept as a module-level
|
|
550
|
+
function (rather than inlined) so tests can monkeypatch HOME and
|
|
551
|
+
reimport the module to re-evaluate USER_ATLAS_PATH cleanly.
|
|
552
|
+
"""
|
|
553
|
+
if USER_ATLAS_PATH.exists():
|
|
554
|
+
return USER_ATLAS_PATH
|
|
555
|
+
return BUNDLED_ATLAS_PATH
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
# Backward-compat alias. External code that imported ATLAS_PATH before
|
|
559
|
+
# v1.22.0 (e.g. pre-existing scripts outside this repo) gets the
|
|
560
|
+
# resolved path. Internal code should call _resolve_atlas_path() so the
|
|
561
|
+
# value is re-evaluated after the user first runs scan_full_library.
|
|
562
|
+
ATLAS_PATH = _resolve_atlas_path()
|
|
523
563
|
|
|
524
564
|
_atlas_instance: Optional[AtlasManager] = None # kept for legacy imports
|
|
525
565
|
|
|
526
566
|
|
|
527
567
|
def _build_atlas() -> AtlasManager:
|
|
528
|
-
return AtlasManager(str(
|
|
568
|
+
return AtlasManager(str(_resolve_atlas_path()))
|
|
529
569
|
|
|
530
570
|
|
|
531
571
|
_atlas_holder = Singleton(_build_atlas)
|
|
532
572
|
|
|
533
573
|
|
|
534
574
|
def get_atlas() -> AtlasManager:
|
|
535
|
-
"""Thread-safe accessor. Re-reads
|
|
575
|
+
"""Thread-safe accessor. Re-reads the resolved atlas path if its
|
|
576
|
+
mtime advanced. Uses the resolver, so if the user's first
|
|
577
|
+
scan_full_library call runs mid-session, the next get_atlas()
|
|
578
|
+
picks up the new user path (via invalidate_atlas, which
|
|
579
|
+
scan_full_library already calls on success)."""
|
|
536
580
|
global _atlas_instance
|
|
537
|
-
instance = _atlas_holder.get(reload_if_newer=
|
|
581
|
+
instance = _atlas_holder.get(reload_if_newer=_resolve_atlas_path())
|
|
538
582
|
_atlas_instance = instance # keep legacy attribute in sync
|
|
539
583
|
return instance
|
|
540
584
|
|
|
541
585
|
|
|
542
586
|
def invalidate_atlas() -> None:
|
|
543
|
-
"""Force the next get_atlas() to re-read
|
|
587
|
+
"""Force the next get_atlas() to re-read the resolved atlas path
|
|
588
|
+
from disk. Called by scan_full_library after writing a fresh
|
|
589
|
+
user atlas so subsequent tool calls see the new data without
|
|
590
|
+
an MCP server restart."""
|
|
544
591
|
global _atlas_instance
|
|
545
592
|
_atlas_holder.invalidate()
|
|
546
593
|
_atlas_instance = None
|
|
@@ -466,11 +466,17 @@ def scan_full_library(
|
|
|
466
466
|
"""
|
|
467
467
|
from .scanner import normalize_scan_results
|
|
468
468
|
from .enrichments import load_enrichments, merge_enrichments
|
|
469
|
-
from . import AtlasManager
|
|
469
|
+
from . import AtlasManager, USER_ATLAS_DIR, USER_ATLAS_PATH
|
|
470
470
|
|
|
471
|
+
# v1.22.0: scans always write to the user atlas path, never the
|
|
472
|
+
# bundled baseline. The user-data directory is created on demand
|
|
473
|
+
# so a brand-new install (no ~/.livepilot/ at all) still works.
|
|
474
|
+
# Enrichments are read from the bundled package (same as before —
|
|
475
|
+
# they're authored in-repo).
|
|
471
476
|
atlas_dir = os.path.dirname(os.path.abspath(__file__))
|
|
472
|
-
atlas_path = os.path.join(atlas_dir, "device_atlas.json")
|
|
473
477
|
enrichments_dir = os.path.join(atlas_dir, "enrichments")
|
|
478
|
+
USER_ATLAS_DIR.mkdir(parents=True, exist_ok=True)
|
|
479
|
+
atlas_path = str(USER_ATLAS_PATH)
|
|
474
480
|
|
|
475
481
|
if not force and os.path.exists(atlas_path):
|
|
476
482
|
age = time.time() - os.path.getmtime(atlas_path)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livepilot",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.1",
|
|
4
4
|
"mcpName": "io.github.dreamrec/livepilot",
|
|
5
5
|
"description": "Agentic production system for Ableton Live 12 — 430 tools, 53 domains, 44 semantic moves. Device atlas (5264 devices, 120 enriched, 7 indexes), Splice intelligence (gRPC + GraphQL describe-a-sound + preview + collections + presets), 9-band spectral perception auto-loaded via ensure_analyzer_on_master, Creative Director skill, technique memory, 12 creative intelligence 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.
|
|
8
|
+
__version__ = "1.22.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.
|
|
9
|
+
"version": "1.22.1",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "livepilot",
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.22.1",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
}
|