suno session lab
Generate a batch, see the clusters, branch from any clip — built spec-first in four days.
Suno Session Lab generates music clips in batches, then shows where each batch landed. A text brief plus control sliders produce a batch — energy, density, and brightness at 0–1, tempo 60–180 bpm, duration 1–60 seconds. Each clip is embedded, the batch is KMeans-clustered and LLM-named, and any clip can branch. "More like this" keeps the candidates closest by cosine to the parent cluster's centroid, and the UI draws generations as rows of nodes with lineage lines. The spec, committed before any code, states the itch: batch-generation interfaces hand back clips with no grouping and no way to aim the next batch at the last good one.
Three decisions.
Providers as protocols, with deterministic fakes as the default. The fake embedding provider derives a vector from a SHA-256 of the file path, so generate, embed, cluster, name, and branch all run offline with zero API keys; real ElevenLabs, CLAP, and OpenAI naming are opt-in settings. The alternative was wiring the real APIs and mocking them in tests.
A provider swap mid-project. HuggingFace MusicGen landed in PR #10 and was deleted in PR #14 for ElevenLabs; the settings validator coerces the legacy env values to "fake" instead of erroring.
A frontend pivot with the backend frozen. The branching spec states "backend stays unchanged" and rebuilds the UI around nodes instead of clusters; the old cluster-grid components remain in the tree, unused, their tests still running.
Numbers: 47 commits in four days, 2025-12-08 to 2025-12-11, 40 of them merged PRs; 71 backend test functions and 48 frontend cases; every major change preceded by a checked-in spec file.
What is wrong with it. At HEAD the ElevenLabs provider requests
duration_sec * 500 milliseconds — half of what the slider asks for.
PR #37 fixed the math;
PR #38 reverted it
while adding the visualizer. The google-genai dependency is imported
nowhere. Sessions and centroids live in memory and die on restart. KMeans
clusters in Euclidean distance while branching filters by cosine — a metric
mismatch I shipped knowingly. And the default demo clusters hash vectors,
not audio: CLAP is off unless it is turned on.
Four days produced a working system and a half-duration bug. Both are in the history.