livepilot 1.20.3 → 1.21.0

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.
@@ -76,6 +76,51 @@ EMERGENCY_SIMPLIFY = SemanticMove(
76
76
  ],
77
77
  )
78
78
 
79
+ # v1.21: configure_record_readiness — closes the tech_debt entry from
80
+ # v1.20 live test 6 (raw set_track_arm without a semantic-move wrapper).
81
+ # seed_args: {track_index: int, armed: bool, exclusive?: bool = False}.
82
+ # Note: `armed` here is the *ergonomic* seed_arg name — the compiler
83
+ # translates it to the wire-format key `arm` per remote_script/LivePilot/
84
+ # tracks.py:263. See _compile_configure_record_readiness.
85
+ CONFIGURE_RECORD_READINESS = SemanticMove(
86
+ move_id="configure_record_readiness",
87
+ family="performance",
88
+ intent=(
89
+ "Arm or disarm a track for recording. When exclusive=True, disarms "
90
+ "all other regular tracks then arms the target — the standard "
91
+ "one-take recording setup (Live 12.4's `song.exclusive_arm` toggle "
92
+ "is read-only from Python, so the compiler emulates the mode via "
93
+ "a manual disarm loop)."
94
+ ),
95
+ targets={},
96
+ protect={"signal_integrity": 0.7},
97
+ risk_level="low",
98
+ required_capabilities=["session"],
99
+ plan_template=[
100
+ # Informational — compiler builds concrete steps from seed_args.
101
+ {
102
+ "tool": "set_track_arm",
103
+ "params": {"description": "Arm or disarm the target track"},
104
+ "description": "Toggle track arm",
105
+ "backend": "remote_command",
106
+ },
107
+ ],
108
+ verification_plan=[
109
+ {
110
+ "tool": "get_track_info",
111
+ "check": "track's arm field matches requested value",
112
+ "backend": "remote_command",
113
+ },
114
+ ],
115
+ )
116
+
117
+
79
118
  # Register all performance moves
80
- for _move in [RECOVER_ENERGY, DECOMPRESS_TENSION, SAFE_SPOTLIGHT, EMERGENCY_SIMPLIFY]:
119
+ for _move in [
120
+ RECOVER_ENERGY,
121
+ DECOMPRESS_TENSION,
122
+ SAFE_SPOTLIGHT,
123
+ EMERGENCY_SIMPLIFY,
124
+ CONFIGURE_RECORD_READINESS, # v1.21
125
+ ]:
81
126
  register(_move)
@@ -397,11 +397,14 @@ async def apply_semantic_move(
397
397
  success_count = sum(1 for s in executed_steps if s["ok"])
398
398
  failure_count = sum(1 for s in executed_steps if not s["ok"])
399
399
 
400
- # v1.20: write the executed move to the SessionLedger so
401
- # get_last_move / memory_list / anti-repetition-rules can see it
402
- # WITHOUT requiring the director to call add_session_memory
403
- # manually. Best-effort a ledger write failure must not fail
404
- # the overall move.
400
+ # store_purpose: writer
401
+ # v1.20: apply_semantic_move is the canonical semantic-moves writer
402
+ # to the SessionLedger. Downstream anti-repetition / stuckness /
403
+ # song-brain readers (annotated store_purpose: anti_repetition) consume
404
+ # entries this block writes. commit_experiment (v1.21) mirrors this
405
+ # pattern with a "composer|experiment" engine tag instead of
406
+ # "semantic_moves". Best-effort — a ledger write failure must not
407
+ # fail the overall move.
405
408
  ledger_entry_id: Optional[str] = None
406
409
  try:
407
410
  from ..runtime.action_ledger import SessionLedger
@@ -139,6 +139,12 @@ def _fetch_session_data(ctx: Context) -> dict:
139
139
  except Exception as exc:
140
140
  logger.debug("_fetch_session_data failed: %s", exc)
141
141
 
142
+ # store_purpose: anti_repetition
143
+ # song_brain's _fetch_session_data surfaces recent moves into the
144
+ # brain's context so section analysis can detect repeated work
145
+ # patterns. Recency signal — NOT the persistent technique library.
146
+ # Correct store: SessionLedger.get_recent_moves (v1.20 director SKILL
147
+ # previously pointed at memory_list for this, which was wrong).
142
148
  # Recent moves — from session-scoped action ledger
143
149
  try:
144
150
  from ..runtime.action_ledger import SessionLedger
@@ -27,6 +27,10 @@ def _get_action_history(ctx: Context) -> list[dict]:
27
27
  repeated undos, local-tweaking, loop-without-structure detection.
28
28
  Falls back to empty list when no ledger data exists (graceful degradation).
29
29
  """
30
+ # store_purpose: anti_repetition
31
+ # Stuckness detection reads recent_moves to spot repeated undos,
32
+ # local-tweaking loops, and loop-without-structure patterns.
33
+ # Recency signal — NOT the persistent technique library.
30
34
  try:
31
35
  from ..runtime.action_ledger import SessionLedger
32
36
  ledger = ctx.lifespan_context.get("action_ledger")
@@ -14,6 +14,12 @@ from typing import Any, Optional
14
14
  from .models import QUALITY_DIMENSIONS, _clamp
15
15
 
16
16
 
17
+ # store_purpose: technique_library
18
+ # analyze_outcome_history consumes payloads from the persistent
19
+ # technique library (memory_list(type="outcome")) — NOT recency data.
20
+ # Taste-inference work reads accumulated outcome records, unlike
21
+ # anti-repetition which reads SessionLedger.get_recent_moves.
22
+
17
23
  # ── Outcome Memory Analysis (Round 1) ────────────────────────────────
18
24
  def analyze_outcome_history(outcomes: list[dict]) -> dict:
19
25
  """Analyze accumulated outcome memories to identify user taste patterns.
@@ -150,6 +150,13 @@ def _generate_replay_steps(technique: dict) -> list[str]:
150
150
  return ["Replay the technique from the stored payload"]
151
151
 
152
152
 
153
+ # store_purpose: mcp_tool_definition
154
+ # memory_list is the MCP tool for browsing the persistent technique
155
+ # library (memory_learn-populated). Callers that use its output for
156
+ # anti-repetition recency have the v1.20 store-confusion BUG: correct
157
+ # pattern is SessionLedger.get_recent_moves or get_action_ledger_summary.
158
+ # The test tests/test_ledger_readers.py::TestAntiRepetitionUsesLedgerNotMemoryList
159
+ # enforces this invariant across the codebase.
153
160
  @mcp.tool()
154
161
  def memory_list(
155
162
  ctx: Context,
@@ -148,6 +148,10 @@ def _get_active_constraints():
148
148
 
149
149
  def _get_ledger_entries(ctx: Context) -> list[dict]:
150
150
  """Get recent action ledger entries as dicts."""
151
+ # store_purpose: anti_repetition
152
+ # Wonder Mode's rescue trigger reads recent_moves to feed the
153
+ # stuckness detector — classic recency signal, NOT the persistent
154
+ # technique library. Correct store: SessionLedger.get_recent_moves.
151
155
  try:
152
156
  from ..runtime.action_ledger import SessionLedger
153
157
  ledger: SessionLedger = ctx.lifespan_context.setdefault(
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "livepilot",
3
- "version": "1.20.3",
3
+ "version": "1.21.0",
4
4
  "mcpName": "io.github.dreamrec/livepilot",
5
- "description": "Agentic production system for Ableton Live 12 — 430 tools, 53 domains. Device atlas (1305 devices), sample engine (Splice + browser + filesystem), auto-composition, spectral perception, technique memory, creative intelligence (12 engines)",
5
+ "description": "Agentic production system for Ableton Live 12 — 430 tools, 53 domains, 43 semantic moves. Device atlas (1305 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",
7
7
  "license": "BSL-1.1",
8
8
  "type": "commonjs",
@@ -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.20.3"
8
+ __version__ = "1.21.0"
9
9
 
10
10
  from _Framework.ControlSurface import ControlSurface
11
11
  from . import router
package/server.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.dreamrec/livepilot",
4
- "description": "430-tool agentic MCP production system for Ableton Live 12 — device atlas, sample engine, composer",
4
+ "description": "430-tool agentic MCP production system for Ableton Live 12 — 53 domains, 43 semantic moves, device atlas (1305 devices), Splice intelligence (gRPC + GraphQL), 9-band spectral perception auto-loaded, Creative Director skill, technique memory, 12 creative engines",
5
5
  "repository": {
6
6
  "url": "https://github.com/dreamrec/LivePilot",
7
7
  "source": "github"
8
8
  },
9
- "version": "1.20.3",
9
+ "version": "1.21.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "livepilot",
14
- "version": "1.20.3",
14
+ "version": "1.21.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  }