livepilot 1.23.6 → 1.25.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/README.md +60 -14
  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/atlas/__init__.py +17 -3
  7. package/mcp_server/atlas/explore_tools.py +332 -0
  8. package/mcp_server/atlas/tools.py +161 -0
  9. package/mcp_server/audit/__init__.py +6 -0
  10. package/mcp_server/audit/checks.py +618 -0
  11. package/mcp_server/audit/tools.py +232 -0
  12. package/mcp_server/composer/branch_producer.py +5 -2
  13. package/mcp_server/composer/develop/__init__.py +19 -0
  14. package/mcp_server/composer/develop/apply.py +217 -0
  15. package/mcp_server/composer/develop/brief_builder.py +269 -0
  16. package/mcp_server/composer/develop/seed_introspector.py +195 -0
  17. package/mcp_server/composer/engine.py +15 -521
  18. package/mcp_server/composer/fast/__init__.py +62 -0
  19. package/mcp_server/composer/fast/apply.py +533 -0
  20. package/mcp_server/composer/fast/brief_builder.py +1479 -0
  21. package/mcp_server/composer/fast/tier_classification.py +159 -0
  22. package/mcp_server/composer/framework/__init__.py +0 -0
  23. package/mcp_server/composer/framework/applier.py +179 -0
  24. package/mcp_server/composer/framework/artist_loader.py +63 -0
  25. package/mcp_server/composer/framework/atlas_resolver.py +554 -0
  26. package/mcp_server/composer/framework/brief.py +79 -0
  27. package/mcp_server/composer/framework/event_lexicon.py +71 -0
  28. package/mcp_server/composer/framework/genre_loader.py +77 -0
  29. package/mcp_server/composer/framework/intent_source.py +137 -0
  30. package/mcp_server/composer/framework/knowledge_pack.py +140 -0
  31. package/mcp_server/composer/framework/plan_compiler.py +10 -0
  32. package/mcp_server/composer/full/__init__.py +10 -0
  33. package/mcp_server/composer/full/apply.py +1139 -0
  34. package/mcp_server/composer/full/brief_builder.py +227 -0
  35. package/mcp_server/composer/full/engine.py +541 -0
  36. package/mcp_server/composer/full/layer_planner.py +491 -0
  37. package/mcp_server/composer/layer_planner.py +19 -465
  38. package/mcp_server/composer/sample_resolver.py +80 -7
  39. package/mcp_server/composer/tools.py +626 -28
  40. package/mcp_server/server.py +1 -0
  41. package/mcp_server/splice_client/client.py +7 -0
  42. package/mcp_server/tools/_analyzer_engine/sample.py +172 -7
  43. package/mcp_server/tools/_planner_engine.py +25 -63
  44. package/mcp_server/tools/analyzer.py +10 -4
  45. package/mcp_server/tools/browser.py +102 -19
  46. package/package.json +2 -2
  47. package/remote_script/LivePilot/__init__.py +1 -1
  48. package/server.json +3 -3
@@ -1656,3 +1656,164 @@ def atlas_cross_pack_chain(
1656
1656
  target_track_index=target_track_index,
1657
1657
  customize_aesthetic=customize_aesthetic or {},
1658
1658
  )
1659
+
1660
+
1661
+ # ── v1.25 Hybrid Knowledge Surface ─────────────────────────────────
1662
+
1663
+
1664
+ @mcp.tool()
1665
+ def atlas_explore(
1666
+ ctx: Context,
1667
+ role: str,
1668
+ mood: str = "",
1669
+ genre: str = "",
1670
+ artists: list[str] | None = None,
1671
+ n: int = 5,
1672
+ avoid_uris: list[str] | None = None,
1673
+ cohort_constraint: list[str] | None = None,
1674
+ ) -> dict:
1675
+ """v1.25 — Refined per-role atlas candidate query (hybrid surface Layer B).
1676
+
1677
+ Use during compose-full plan design when the brief's `atlas_anchors`
1678
+ don't fit the section's purpose, or when you need siblings of a role
1679
+ pick that the resolver hasn't surfaced yet.
1680
+
1681
+ Each candidate carries a reasoning trail describing WHY it matches
1682
+ (signature_technique mood overlap, curated .adg presence, taste profile,
1683
+ §1 banned-default penalty, anti-repeat penalty). Pick the one whose
1684
+ reasoning best matches the section's intent.
1685
+
1686
+ Parameters
1687
+ ----------
1688
+ role : str
1689
+ Brief role: "kick", "snare", "hat", "perc", "bass", "lead", "pad",
1690
+ "atmos", "vocal_chop", "fx", "spectral".
1691
+ mood : str, optional
1692
+ Free-text mood — token-matched against signature_techniques for boost.
1693
+ Examples: "spectral warped", "warm dusty", "dreamy sublime".
1694
+ genre : str, optional
1695
+ Genre slug used for genre_affinity boost. Examples: "dub_techno", "ambient".
1696
+ artists : list[str], optional
1697
+ Producer references. Currently used as vocab passthrough; ranking
1698
+ integration is v1.25.x.
1699
+ n : int, default 5
1700
+ Maximum candidates to return.
1701
+ avoid_uris : list[str], optional
1702
+ URIs to exclude (already-used picks within this session/plan).
1703
+ cohort_constraint : list[str], optional
1704
+ If provided, return ONLY candidates whose pack is in this list.
1705
+
1706
+ Returns
1707
+ -------
1708
+ {
1709
+ candidates: list[AtlasCandidate dict],
1710
+ cohort_hint: str | None, # most-frequent pack across results
1711
+ reasoning: str,
1712
+ }
1713
+
1714
+ Each candidate dict has: uri, name, source, score, character_tags,
1715
+ signature_techniques, in_pack, has_curated_adg, reasoning.
1716
+ """
1717
+ from . import get_atlas
1718
+ try:
1719
+ atlas = get_atlas()
1720
+ except FileNotFoundError:
1721
+ atlas = None
1722
+ from .explore_tools import explore as _explore
1723
+ return _explore(
1724
+ atlas=atlas,
1725
+ role=role,
1726
+ mood=mood,
1727
+ genre=genre,
1728
+ artists=artists,
1729
+ n=n,
1730
+ avoid_uris=avoid_uris,
1731
+ cohort_constraint=cohort_constraint,
1732
+ )
1733
+
1734
+
1735
+ @mcp.tool()
1736
+ def atlas_audition(ctx: Context, uri: str) -> dict:
1737
+ """v1.25 — Full sidecar dump for one atlas URI (hybrid surface Layer B).
1738
+
1739
+ Joins the device record with `device_techniques_index.json`
1740
+ (signature_techniques) and `preset_resolver` (curated .adg sidecar +
1741
+ producer-assigned macro names). Use BEFORE committing to a candidate
1742
+ when its character_tags alone aren't enough to know if it fits.
1743
+
1744
+ Parameters
1745
+ ----------
1746
+ uri : str
1747
+ Atlas URI (e.g. "atlas://pitchloop89") OR device name OR device id.
1748
+
1749
+ Returns
1750
+ -------
1751
+ {
1752
+ uri, name, id, pack, category,
1753
+ character_tags: list[str],
1754
+ signature_techniques: list[{technique, description, aesthetic, kind}],
1755
+ producer_macros: list[{index, name, source_preset}],
1756
+ curated_adg_paths: list[str],
1757
+ enriched: bool,
1758
+ related_demos: list, # placeholder for v1.25.x reverse-index
1759
+ }
1760
+ """
1761
+ from . import get_atlas
1762
+ try:
1763
+ atlas = get_atlas()
1764
+ except FileNotFoundError:
1765
+ atlas = None
1766
+ from .explore_tools import audition as _audition
1767
+ return _audition(atlas=atlas, uri=uri)
1768
+
1769
+
1770
+ @mcp.tool()
1771
+ def atlas_substitute(
1772
+ ctx: Context,
1773
+ current_uri: str,
1774
+ anti_tag: str,
1775
+ n: int = 3,
1776
+ ) -> dict:
1777
+ """v1.25 — Anti-tag-driven swap for a chosen candidate (hybrid surface Layer B).
1778
+
1779
+ Use AFTER `analyze_sound_design` or `analyze_mix` flags an issue with
1780
+ a layer you've loaded. The `anti_tag` is a free-text descriptor of
1781
+ what you want LESS of: "too bright", "too aggressive", "too sparse",
1782
+ "muddy", "static", "generic" — substring-matched against the anti-tag
1783
+ map (see _ANTI_TAG_MAP for the full key list).
1784
+
1785
+ Returns up to N alternatives that share the current device's role tag
1786
+ but do NOT carry any of the excluded character_tags.
1787
+
1788
+ Parameters
1789
+ ----------
1790
+ current_uri : str
1791
+ URI of the layer you want to swap out.
1792
+ anti_tag : str
1793
+ Descriptor of the unwanted property (substring-matched).
1794
+ n : int, default 3
1795
+ Maximum alternatives to return.
1796
+
1797
+ Returns
1798
+ -------
1799
+ {
1800
+ current_uri, current_name, anti_tag,
1801
+ excluded_tags: list[str], # what was filtered out
1802
+ preferred_tags: list[str], # what got boosted
1803
+ alternatives: list[AtlasCandidate dict],
1804
+ reasoning: str,
1805
+ }
1806
+
1807
+ Errors
1808
+ ------
1809
+ Returns {error, supported_anti_tags} when `anti_tag` doesn't substring-
1810
+ match any key in the anti-tag map. Returns {error, current_uri} when
1811
+ `current_uri` isn't found in the atlas.
1812
+ """
1813
+ from . import get_atlas
1814
+ try:
1815
+ atlas = get_atlas()
1816
+ except FileNotFoundError:
1817
+ atlas = None
1818
+ from .explore_tools import substitute as _substitute
1819
+ return _substitute(atlas=atlas, current_uri=current_uri, anti_tag=anti_tag, n=n)
@@ -0,0 +1,6 @@
1
+ """Layer + session audit aggregation.
2
+
3
+ Replaces the §5 layer-precision and §9 end-of-session checklist (each a
4
+ multi-call manual sequence) with single tool calls that run the checks
5
+ server-side and return one structured report.
6
+ """