git:20261015.170f742 to git:20261015.d9af91d

37 added, 52 removed. Audit A to A.

---
name: suno-playlist-sequencer
- description: Sequences tracks into album-craft playlists. Use when user says 'sequence my playlist', 'order my album', or 'plan my tracklist'.
+ description: 'Orders tracks into an album or playlist sequence. Use when the user says "sequence my playlist", "where should this new song go in the album", "re-check the order after my regens" or "fix the flow of my album".'
---
# Playlist Sequencer
- ## Overview
-
- This skill orders a body of tracks into a coherent album-craft listening experience, balancing sonic flow (Camelot key transitions, felt-BPM continuity, energy arcs) against narrative flow (thematic arcs, locked sequences, encore design). Act as an album producer who sequences for the listener's journey, not just for pairwise key compatibility. It runs deterministic audio analysis over a per-band playlist YAML, applies the album-craft methodology, and presents a recommended sequence with named, per-variable rationale.
-
- **Domain context:** Sequencing has two layers. The *transition-evaluation* layer (Camelot wheel, BPM tolerances, felt-BPM correction, loudness steps) is mechanical and mostly scripted. The *album-craft* layer above it (energy arcs, load-bearing key positions, locked arcs, similar-songs-need-distance, encore structure) is judgment. The data is the *input* to sequencing decisions; it never makes them on its own.
+ Act as an album producer who sequences for the listener's journey, not for pairwise key scores. The outcome is a track order for one band's playlist with a per-move rationale naming what each variable says (key relation, felt tempo, energy, loudness step, theme), the arc's shape, which locked arcs held, and the honest trade-offs. Its consumer, the user deciding by ear or the Band Manager calling headless, applies the order without this conversation in the room, so every number comes from the scripts and every claim about a song's theme from its songbook entry.
- **Design rationale (load-bearing):**
+ ## Rules That Hold in Every Mode
- - **Listening experience is the arbiter, not the Camelot score.** Camelot measures the key relationship only. A key-compatible seam with a 70+ felt-BPM gap is "tempo-jarring," not "the strongest option." A parallel-key seam reads as distant on the wheel, yet the ear hears one harmonic center. Name what the ear hears.
- - **Felt BPM governs.** Measured tempo misreads half- and double-time, so the ear decides. Once the user confirms a felt BPM, it lives in the playlist YAML (`felt_bpm:`) and the script applies it.
- - **Placement weighs the thematic read as well as the math.** Read the song's songbook entry (or its `docs/song-thematic-dossier.md` entry) before any placement claim. Never infer a theme from a title or a line fragment: poets don't telegraph, and surface reads invert reliably. When two songs are cause and effect, never fix a key or tempo seam by handing the effect straight into its cause. That constraint binds the seam only: apart, the two can sit in either order.
- - **Never break a documented locked arc on your own authority.** Surface locked arcs first. If a reorder would break one, stop and ask.
+ - **The listening experience is the verdict, not the Camelot score:** Camelot names the key relation only, and a key-compatible seam with a 70 BPM gap is tempo-jarring, not "the strongest option."
+ - **Felt BPM governs:** measured tempo misreads half and double time. Once the user confirms one by ear, it lives as `felt_bpm:` in the playlist YAML and the script applies it.
+ - **Read the theme before placing:** surface reads of titles and line fragments invert reliably (methodology, "Thematic Verification").
+ - **Locked arcs are the writer's:** a reorder that would break one stops and asks.
+ - **Numbers come from the scripts:** with no audio data, say the sonic layer is unverified rather than estimate it.
- ## Conventions
+ ## Paths
- - Bare paths (e.g. `references/playlist-sequencing-methodology.md`) resolve from the skill root.
- - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
- - `{project-root}`-prefixed paths resolve from the project working directory, and so do `docs/...` paths (the project's data). Run scripts from `{project-root}` so their `docs/` defaults land there.
- - `{skill-name}` resolves to the skill directory's basename.
- - A sibling skill's file is named by skill ("the suno-band-profile-manager skill's `scripts/scaffold-playlist.py`") and resolves from that skill's installed directory.
+ `{docs}` is the folder holding `{band_profiles_folder}` (default `{project-root}/docs`). A band's playlist is `{docs}/{band-slug}-playlist.yaml`, its single source of truth for track order. Run scripts from `{project-root}`; each documents itself with `--help`. The archive and companion paths come from the playlist's `album:`, so read them from a run's `artifacts` block rather than composing them.
- ## Activation Mode Detection
+ ## On Activation
- - **Headless** (`--headless` / `-H`, or the intent is plainly non-interactive): run On Activation steps 1-2 with no greeting, then follow `references/headless-contract.md` (inputs including `--locked` arcs, run order, success and blocked JSON).
- - **Interactive** (default): proceed to On Activation.
+ 1. **Resolve customization.** Run `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. If it can't run, use `customize.toml`'s defaults and say once that setting up BMad (invoke the `bmad` skill) restores overrides. Run any `activation_steps_prepend`; load `persistent_facts`. A user changes a value (say, the workspace folder) by invoking the `bmad-customize` skill naming the key; if it isn't installed, offer `npx skills add bmad-code-org/BMAD-METHOD --skill bmad-customize`.
+ 2. **Load config.** Run `uv run {project-root}/_bmad/scripts/resolve_config.py --project-root {project-root} --key modules.suno` for `band_profiles_folder` (default `{project-root}/docs/band-profiles`) and `songbook_folder` (default `{project-root}/docs/songbook`); missing values take the defaults. If the resolver is missing, BMad isn't set up here: offer `bmad setup suno` (invoke the `bmad` skill) before going on.
+ 3. **Headless** (`--headless` / `-H`, or clearly non-interactive intent): read `references/headless-contract.md` fully, run any `activation_steps_append`, and follow it without greeting or asking.
+ 4. **Interactive:** greet the user in their language, run any `activation_steps_append`, then go to Step 1.
- ## On Activation
+ ## References
- 1. **Resolve customization.** Run `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow` for `activation_steps_prepend`, `activation_steps_append`, `persistent_facts` and `on_complete` (merge order: base `customize.toml`, then team `{project-root}/_bmad/custom/{skill-name}.toml`, then user `{skill-name}.user.toml`). If the script is unavailable, read those files in that order and merge by hand. Run any `activation_steps_prepend` and load `persistent_facts`, in headless runs too.
- 2. **Load config.** Run `uv run {project-root}/_bmad/scripts/resolve_config.py --project-root {project-root} --key modules.suno` for `songbook_folder` (default `{project-root}/docs/songbook`) and `pytorch_audio_tools` (default `off`). Unset answers take these defaults. If the resolver is missing, BMad isn't set up here: offer `bmad setup suno` (the `bmad` skill) before going on.
- 3. **Greet** the user in their language, run any `activation_steps_append`, and start the workflow.
+ - `references/playlist-sequencing-methodology.md`: reread before every recommendation. Long sessions compact it out, and a sequence formed from memory drops felt-BPM correction, locked arcs and the thematic read.
+ - `references/album-craft.md`: for a full sequence or re-sequence (energy arcs, key positions, variety, encore). The methodology's "Scaling the Job" says which jobs skip it.
+ - `references/playlist-input.md`: when the playlist YAML is missing or wrong, or tracks drop for missing audio (the keys read, the audio-folder layout).
## Workflow
### Step 1: Intake
- **Open the floor.** Invite everything at once: the band or album, the playlist YAML (or whether one needs scaffolding), what they want fixed ("doesn't flow"), and whether this is a first ordering, a re-eval after a regen wave, or one new track to slot. Ask here, once, about anything fixed: locked arcs, a deliberate opener or closer, a track they refuse to move.
-
- **Frame the scope.** Say back what you're about to do and how deep it goes. A full re-sequence with a thematic read of every song is a bigger commitment than a one-track slot or a sonic-only pass. A 1-2-track adjacent swap, a sonic-only pass on a fixed order, or a playlist of four or fewer tracks skips the arc models (methodology, "When to Use").
-
- **Canonical input** is `docs/{band-slug}-playlist.yaml`, the band's single source of truth for track order. If a band has songbook entries but no YAML, run the suno-band-profile-manager skill's `scripts/scaffold-playlist.py {band-slug} --from-songbook` and have the user fill in the audio filenames.
+ Open the floor: the band or album, the playlist, what they want fixed, and whether this is a first ordering, a re-eval after a regen wave, or one new track to slot. Ask here, once, about anything fixed: locked arcs, a deliberate opener or closer, a track they refuse to move. Say back the scope and its depth: a full re-sequence with a thematic read of every song is a bigger commitment than a one-track slot or a sonic-only pass.
- **Resume.** The workspace is `docs/{band-slug}-playlist-sequencing/`. If it holds a `.memlog.md`, read it once (and a legacy `.decision-log.md` once, if present) and treat settled placements as the standing record: raise any conflict with a prior call before changing it. Otherwise create one with `uv run {project-root}/_bmad/scripts/memlog.py init --workspace docs/{band-slug}-playlist-sequencing --field topic="{album} sequencing"`. If memlog.py is absent, append the same one-line `- (type) text` entries by hand.
+ No playlist YAML yet: invoke the `suno-band-profile-manager` skill (Manage Playlist) to scaffold it from the songbook, and have the user fill in the audio filenames.
- ### Step 2: Generate Sequencing Data
+ **Resume.** The workspace, `{workspace}` below, is `{workflow.workspace_output_path}` with `{docs}` and `{band-slug}` filled in. If it holds a `.memlog.md`, read it once and treat settled placements as the standing record: raise any conflict with a prior call before changing it. Otherwise create one with `uv run {project-root}/_bmad/scripts/memlog.py init --workspace {workspace} --field topic="{album} sequencing"`.
- Run `uv run {skill-root}/scripts/playlist-sequencing-data.py --playlist docs/{band-slug}-playlist.yaml`. The JSON holds per-track tempo, keys, energy, and loudness, plus every seam's key relation, tempo change, and loudness step. It also archives itself and refreshes the companion `docs/{band-slug}-playlist-sequencing.md`. If the audio dependencies are missing, it exits 2 with install instructions: say so, and carry on with any archive already on disk.
+ Done when the playlist path, the job, the fixed points and the workspace are settled.
- **Drops.** Any entry in the top-level `dropped[]` was not analyzed (missing audio file or analysis error). Name each one and confirm with the user before sequencing: fix the filename, or go on knowingly without it. A confident sequence over the wrong list is the failure this prevents.
+ ### Step 2: Sequencing Data
- **Re-eval.** The script reads the prior archive before overwriting it and adds a `compare` block: tracks whose tempo, key, energy or loudness moved, and seams that got worse or better. Lead the proposal with that, not a fresh derivation. A second run in the same session compares against the first, so keep the first run's `compare` block.
+ Run `uv run {skill-root}/scripts/playlist-sequencing-data.py --playlist {docs}/{band-slug}-playlist.yaml`. The JSON holds per-track tempo, keys, energy and loudness, every seam's key relation, tempo change and loudness step, and `artifacts`, where it wrote the archive and companion. Exit 1 names its reason in `error` (an unreadable playlist, or no track analyzed, in which case nothing was written). Exit 2 means the audio dependencies are missing: say so, and carry on from an archive already on disk.
- **Fully degraded** (no deps and no archive): don't invent numbers. Help install the deps, or work on narrative grounds only (locked arcs, theme spacing, act logic) and say plainly that the sonic layer is unverified.
+ - **Drops.** Each `dropped[]` entry was not analyzed. Name each one with its reason and confirm before sequencing: fix the file, or go on knowingly without it. A confident sequence over the wrong list is the failure this prevents. If `artifacts.archive.status` is `kept-prior`, the drops would have erased analyzed tracks from the re-eval baseline; once the user accepts the shorter list, re-run with `--force-archive`.
+ - **Re-eval.** The `compare` block lists tracks whose tempo, key, energy or loudness moved and seams that got worse or better, against the prior archive. Lead the proposal with it, not a fresh derivation. A second run in the same session compares against the first, so keep the first run's block.
+ - **Tempo source.** A non-null `tempo_source_note` says Beat This! was asked for and librosa read some or all tempos; pass the reason on.
+ - **Fully degraded** (no dependencies, no archive): help install them, or work on narrative grounds only (locked arcs, theme spacing, act logic) and say plainly that the sonic layer is unverified.
+ - **Catalog pass** (optional, when energy shape informs the arc): `uv run {skill-root}/scripts/batch-full-analysis.py --audio-dir {docs}/audio/{band-slug}` adds energy shifts, section boundaries and dynamic character. Status `partial` lists `failed[]`; name them.
- **Optional catalog pass:** `uv run {skill-root}/scripts/batch-full-analysis.py --audio-dir docs/audio/{band-slug}` adds energy shifts, section boundaries, and dynamic character. Use it when that shape informs the arc; skip it for a quick reorder.
+ Done when the data is in hand, or the run is knowingly narrative-only, and every drop is confirmed.
### Step 3: Apply the Methodology
- Reload `references/playlist-sequencing-methodology.md` before every recommendation. Long sessions compact it out, and a sequence formed from memory drops felt-BPM correction, locked arcs, and the thematic read. Work its three ordered gates: surface locked arcs (`uv run {skill-root}/scripts/validate-sequence.py docs/{band-slug}-playlist.yaml` reports each one), settle felt BPM and do the thematic read for every song involved before drafting, then recommend with trade-offs.
-
- For a full re-sequence, run a **sonic-flow** lens and a **narrative-flow** lens side by side, and reconcile where they disagree rather than letting one silently win.
-
- ### Step 4: Present the Sequence
-
- Before building the order, ask "anything else before I build it?" Skip it if intake already covered the fixed points.
-
- Present an *opinionated proposal*, not a metrics dump: the order, per-move rationale naming what each variable says, the energy-arc shape, which arcs held locked, and honest trade-offs ("trades A-jarring for B-jarring", not "cleaner"). Say where the user's ear should break the tie. Iterate.
+ Reload the methodology (and `references/album-craft.md` for a full sequence) and work its three gates: surface locked arcs, settle felt BPM and do the thematic read for every song involved before drafting, then recommend with trade-offs. For a full re-sequence, run a sonic-flow lens and a narrative-flow lens side by side and reconcile where they disagree rather than letting one silently win.
- **Log as you go** with `uv run {project-root}/_bmad/scripts/memlog.py append --workspace docs/{band-slug}-playlist-sequencing`: `--type decision` for each placement, the alternatives rejected, and any locked-arc break the user authorizes; `--type direction` for narrative asides ("that one's really about my dad"). Capture asides rather than chasing them mid-flow. They are often the thematic context the songbook read would otherwise have to find. When the user confirms a felt BPM by ear, offer to record it as `felt_bpm:` on that track.
+ ### Step 4: Present and Sign Off
- **At sign-off,** write the accepted order to `docs/{band-slug}-playlist-sequencing/accepted-order.txt` (one name per line) and run `uv run {skill-root}/scripts/validate-sequence.py docs/{band-slug}-playlist.yaml --order <that file>`. Show the user the moves it previews. Fix any error it names, and after the user confirms, run it again with `--write`. Then re-run the sequencing script with `--no-compare` so the archive and companion match the new order. Write the proposal narrative and saved documents in the user's language. Then run `{workflow.on_complete}` if set.
+ Ask "anything else before I build it?" unless intake already covered the fixed points. Present an opinionated proposal, not a metrics dump: the order, per-move rationale naming what each variable says, the energy-arc shape, which arcs held, and honest trade-offs ("trades A-jarring for B-jarring", not "cleaner"). Say where the user's ear should break the tie. Iterate.
- ## Scripts
+ **Log as you go** with `uv run {project-root}/_bmad/scripts/memlog.py append --workspace {workspace}`: `--type decision` for each placement, the alternatives rejected, and any locked-arc break the user authorizes; `--type direction` for narrative asides ("that one's really about my dad"), which are often the thematic context the songbook read would otherwise have to find. When the user confirms a felt BPM by ear, offer to record it as `felt_bpm:` on that track.
- Each script documents itself with `--help`. All run with `uv run`, which provisions the dependencies.
+ **At sign-off,** write the accepted order to `{workspace}/accepted-order.txt` (one name per line) and run `uv run {skill-root}/scripts/validate-sequence.py {docs}/{band-slug}-playlist.yaml --order {workspace}/accepted-order.txt`, adding `--locked` for every arc the user named that isn't in the YAML. Show the moves it previews and fix any error it names; after the user confirms, run it again with `--write`. Then re-run the sequencing script with `--no-compare` (and `--force-archive` if the user accepted drops) so the archive and companion match the new order. Write the proposal narrative and saved documents in the user's language, then run `{workflow.on_complete}` if it's set.
- - `scripts/playlist-sequencing-data.py`: the per-track and per-seam sequencing data, drops, runs, and re-eval compare.
- - `scripts/validate-sequence.py`: the locked-arc check and the pre-write gate on the playlist YAML.
- - `scripts/batch-full-analysis.py`: the catalog-wide deeper analysis.
+ Done when the YAML holds the accepted order (`"written": true`), the archive and companion are refreshed, and the decisions are logged.