LOADING…
0%
Build history

Every step,
from the first commit.

A complete build timeline of Grainstash taking shape—from early sequencer experiments to the product it is today.

Commits
1,543
Since
2024
Through
2026

Showing 51–100 of 1,543

Page 2 of 31

5 commits
  1. Remove unwired duplicate-detection feature and Mollie migration columns

    Claude c57e9340

    Commit notes

    Follow-up dead-code removal now that nothing is deployed: Duplicate detection (server side worked, but no UI ever called it): - Delete POST /uploads/check-duplicates, the frontend calculateFileFingerprint/checkForDuplicates helpers, the worker's quick-fingerprint computation and Redis quickhash cache, the computeQuickFingerprint util + its tests, and the samples.quick_hash column (migration 0030 reverted outright — it only ever existed on this branch). The content hash stays: the analysis worker still uses it to dedup identical files. Mollie (replaced by Stripe before launch; backend/src was already Mollie-free): - Strip the mollie_* columns and indexes from migrations 0003, 0004 and 0007, and turn 0015 (Mollie Connect onboarding columns) into a kept-for-sequence no-op. The Stripe migration (0021) adds its columns fresh with no reference to the Mollie ones, so fresh databases now come up without stray payment-provider columns. Checked but intentionally NOT removed: auth/password.ts has no legacy hash fallback — its "legacy" mention is a defensive catch that maps malformed hashes to a failed login instead of a 500. Co-Authored-By: Claude Fable 5 <[email redacted]> Claude-Session: [private session redacted]

    Files
    13
    Added
    +18
    Removed
    −455
  2. Remove dead and legacy code (chunked uploads, dead endpoints, unused exports)

    Claude 53e86392

    Commit notes

    The app is not live, so disabled/legacy systems and unreferenced code are deleted outright instead of being kept for compatibility. Chunked/resumable upload system (disabled since the move to direct presigned uploads): - Delete the legacy /uploads/chunked/* routes, the chunk-assembly queue and its worker handler, chunk session state (Lua scripts, chunk-set tracking, progress/missing-chunk helpers, chunk-size heuristics), the chunk upload rate limit, and the orphaned-chunk cleanup stubs. - Delete the cleanup queue entirely — its only producer was the chunk-assembly handler. - UploadSession is now a minimal direct-upload record (no uploadMode, chunk counts, status machine, storagePrefix, or jobId); staleness is purely presigned-URL-expiry age. The completion lock is renamed accordingly (lockSessionForCompletion). Upload endpoints with no consumers: - Remove GET /uploads (list), GET /uploads/:id/status, GET /uploads/:id/job, POST /uploads/batch/status, POST /uploads/cleanup, and DELETE /uploads/sessions. The kept surface is initiate, batch initiate, complete, abort, and check-duplicates. - Remove the matching frontend API functions, the five unconsumed upload hooks (single-file mutation, folder-as-pack mutation, session list/cleanup/force-delete), the uploads query keys, and the resumable-upload localStorage cleanup (nothing writes those keys). Dead exports: - clap-client: embedText / embedAudioFromS3Key / embedAudioBytes (the classify endpoints are the live path). - similarity-search: cosineSimilarity / isPgVectorAvailable. - storage: the unused storage object + Storage interface, getProxyUrl, uploadParallel, the 5GB MAX_FILE_SIZE (the 500MB audio limit at initiate is the real gate), and unused config getters. Docs updated to match (worker job list, uploads route description). Deliberately kept: calculateFileFingerprint / checkForDuplicates and the /uploads/check-duplicates endpoint — the duplicate-detection feature is functional server-side and awaiting UI wiring. Co-Authored-By: Claude Fable 5 <[email redacted]> Claude-Session: [private session redacted]

    Files
    22
    Added
    +234
    Removed
    −2768
  3. Fix upload, analysis, and search pipeline issues from review

    Claude ba7236aa

    Commit notes

    Uploads: - Stop the stale-session auto-cleanup from deleting in-flight direct uploads (and their storage objects): direct sessions never report chunk progress, so they are now only reaped after the presigned URL expires (45 min), in both the route-level and worker-level cleanup. The triplicated route cleanup block is factored into one helper. - Verify the actual uploaded object size at /complete (presigned PUTs don't enforce one): reject oversized files, re-check the storage quota when the real size exceeds the declared size, and record the real size on the sample. - Enforce MAX_AUDIO_FILE_SIZE (500MB) at initiate instead of failing after the user has uploaded the whole file. - Key batch-initiated upload sessions by request index instead of file name: duplicate basenames across pack folders (Kicks/01.wav, Snares/01.wav) previously shared one session and storage key, silently losing a file. - Never persist a session for a request that is about to be rejected. Duplicate detection: - Store the browser-style quick fingerprint (first 1MB + last 1MB + size) on samples (new quick_hash column, migration 0030) and in the Redis cache; the pre-upload check only ever had this fingerprint, so matching it against the full content hash silently never fired for files over 2MB. - Scope /uploads/check-duplicates to the requesting user (it leaked other users' sample and pack names via content-hash probing) and replace its per-fingerprint queries with one DB query, one pack query, and one Redis MGET. - Let the analysis job fall back to the sample's stored content hash so analysis dedup can actually fire (jobs are enqueued before the hash is computed). Analysis worker: - Stop wiping folder-derived tags and genre when analysis completes (and stop copying the other sample's tags on the dedup path). - Recover stale CLAP embedding jobs at startup; they were the only queue omitted, so crashed embedding jobs stayed stuck forever. AI search / CLAP: - Map the query planner's drum-type vocabulary onto the CLAP taxonomy labels it filters ("perc"/"rim" -> percussion, bass -> bass+808, vocal -> vocal+vocal_chop); the mismatch guaranteed zero-result searches. Keep all requested types instead of only the first. - Add a 2.5s timeout + reduced retries to the planner LLM call and cache plans in Redis so search doesn't hang on a slow provider. - Stop caching a rejected facet-embedding promise, which permanently broke AI search after one transient CLAP outage. - Cache the structural pgvector readiness checks (three catalog queries per search) and capture the pgvector version; run the vector query with a raised hnsw.ef_search and iterative scans (pgvector >= 0.8) so scoped searches stop under-returning. - Cache CLAP text embeddings in Redis (they're deterministic), which also removes the double embedding of every AI-search query. - Decode only the model's 10s input window in the CLAP service instead of relying on the HF processor's rand_trunc: embeddings for clips longer than 10s were a random crop and differed on every run. Library: - Restrict full-text search to user-meaningful text fields; it previously built a per-row tsvector over ~60 columns, matching queries like "true" or "120" against internal state. - Move UMAP computation to a background worker queue (it blocked the API event loop), batch the projection writes, and use a seeded PRNG so layouts are reproducible. - Remove the dead LLM categorization pass (no callers; the worker nulls its outputs). Frontend: - Fix the similar-samples bar color ramp so higher similarity always reads as better. Co-Authored-By: Claude Fable 5 <[email redacted]> Claude-Session: [private session redacted]

    Files
    21
    Added
    +949
    Removed
    −496
  4. Integrate beat maker with pack pages and fix marketplace UX gotchas

    Claude 1db933cd

    Commit notes

    Sequencer <-> storefront integration: - Pack pages get a "Try these sounds in the beat maker" card linking to /studio?creator=<slug>&pack=<slug> - The studio loads a published pack's preview samples (up to 8) as sequencer tracks via the public preview endpoint, so guests can jam with a pack before buying, and shows a dismissible banner linking back to the pack with a buy CTA UX fixes: - Add /auth/signup and /auth/login pages (email/password via existing backend endpoints plus Google), fixing three checkout-flow links that 404'd; guest emails are carried over via ?email= so purchases link up - Replace two dead /settings/subscription upgrade CTAs with buttons that open the global subscription drawer (drawer state moved into the subscription store) - Fix /dashboard bouncing signed-in users to a bogus /auth/callback URL on hard refresh: wait for the auth check, show an inline sign-in prompt when logged out - Point the reset-password success CTA at the new sign-in page - Make the header logo link home; add a sign-in button to the library's signed-out state - Allow http/ws localhost in the CSP during dev only: the enforced https:-only connect-src blocked every browser call to the local backend, breaking the app in local development Co-Authored-By: Claude Fable 5 <[email redacted]> Claude-Session: [private session redacted]

    Files
    14
    Added
    +515
    Removed
    −99
1 commit
3 commits
  1. Use existing WaveSurfer player and melt-ui sliders in tag generator

    Claude bd88bc34

    Commit notes

    Refactor the producer tag generator UI to reuse the project's existing audio/UX components instead of bespoke ones, for a consistent experience: - Playback and waveform display now go through the shared Waveform (WaveSurfer) component. Each FX change re-renders the tag to a WAV blob URL that WaveSurfer loads, so the waveform and playback always reflect the applied effects — and the global audio coordinator ensures only one tag plays at a time, like the rest of the app. - FX controls now use a melt-ui Slider builder via a small reusable FxSlider component, matching how the rest of the app builds interactive primitives. - Aligned button/card/input styling with app conventions (hover:bg-brand-500, rounded-lg cards, neutral surfaces). Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    2
    Added
    +198
    Removed
    −154
  2. Add free producer tag generator lead-gen tool

    Claude 9556a436

    Commit notes

    A public, no-auth page (/tag-generator) that synthesizes five distinct AI voice tags from a producer's phrase and captures their email as a lead — modeled on plugmytag.com. Reuses the existing OpenAI integration. Backend: - producer-tag service generates 5 hand-tuned voice presets via OpenAI TTS (gpt-4o-mini-tts) using the configured OPENAI_API_KEY / ENABLE_LLM_ANALYSIS. - producer-tag-generator routes: generate (email capture + synthesis), fetch batch, stream dry audio, and MP3/WAV export. IP rate-limited, fails open if Redis is down. - New tables (producer_tag_leads / _batches / _voices) + migration 0029; batches expire after 7 days with an hourly cleanup task, like guest packs. - transcodeToMp3 ffmpeg helper for delivering FX-applied audio as MP3. Frontend: - /tag-generator page: lead form, five playable voice cards, full FX library (reverb, delay, stutter, pitch-shift, distortion) with presets + sliders, and royalty-free MP3/WAV downloads. - tag-fx engine applies effects entirely in-browser via OfflineAudioContext and encodes WAV client-side; MP3 export is transcoded server-side. - Discoverable CTA added to the marketing landing page. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    13
    Added
    +1630
    Removed
    −1
1 commit
8 commits
1 commit
  1. docs(plans): add cycle-4 production-readiness audit plans (008-013)

    Claude b547d1b1

    Commit notes

    Reconcile cycle-3 (all DONE, in main) and add six new handoff plans: test clean-skip, public pack pattern cap, folder N+1, admin regen bound, CSP enforcing, and SSE token cleanup. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    7
    Added
    +1580
    Removed
    −10
10 commits
  1. Stop CLAP-search route test from leaking a divergent module mock

    Claude 1ccb564b

    Commit notes

    library.ai-search.error.test.ts mock.module-replaced ../services/clap-search with a getSafeClapSearchFailure re-implemented around a local error subclass. bun's mock.module is global and persists across files, so that divergent implementation leaked into clap-search.test.ts and made it classify a real ClapSearchNotReadyError as a generic 503 (expected 200) — the intermittent CI failure. Reuse the real pure helpers from clap-search-policy in the mock and throw the real error class, so the mock can't diverge from production. Co-Authored-By: Claude Opus 4.8 <[email redacted]>

    Files
    1
    Added
    +13
    Removed
    −35
  2. Harden CLAP-search not-ready error classification against instanceof

    Claude f8b60417

    Commit notes

    The full backend test suite intermittently failed "clap-search public failures > maps not-ready states to safe 200 responses": getSafeClapSearchFailure returned 503 instead of 200 because its instanceof ClapSearchNotReadyError check can see a different class instance than the error when this module is loaded more than once (bun's cross-file mock.module pollution in the full suite). Add a duck-typed fallback (name + readiness shape) so genuine not-ready errors are always mapped to a safe 200, regardless of module identity. Co-Authored-By: Claude Opus 4.8 <[email redacted]>

    Files
    1
    Added
    +14
    Removed
    −1
  3. Include Team plans in dashboard fee/upsell logic

    Claude b17029c1

    Commit notes

    The creator dashboard computed hasProSubscription from only the two Pro plans, so Team/Label subscribers saw the full 15% platform fee and a bogus "Upgrade to Pro" upsell. Use the shared isPaidSubscriptionPlan helper so all paid plans get the reduced fee, matching the fee shown in the subscription drawer. Co-Authored-By: Claude Opus 4.8 <[email redacted]>

    Files
    1
    Added
    +5
    Removed
    −2
  4. Add structured sample-pack license terms and delivery

    Claude db9c1484

    Commit notes

    Introduce versioned, BeatStars-style license templates (royalty-free standard + exclusive) as a backend source of truth, let sellers pick a license per pack, disclose the buyer's rights at the point of sale, snapshot the granted license immutably onto each purchase, and deliver a personalized LICENSE.txt inside every download zip. Adds a public /legal/licensing page. Migration 0028 adds sample_packs.license_type and the purchases license snapshot columns (hand-written + journal entry, matching the 0024-0027 convention; snapshots intentionally stop at 0023 in this repo). Co-Authored-By: Claude Opus 4.8 <[email redacted]>

    Files
    14
    Added
    +916
    Removed
    −21
  5. Fix PackClapRow type to satisfy drizzle db.execute constraint

    Claude 2d0b32cf

    Commit notes

    PackClapRow was an interface, which lacks the implicit index signature that drizzle's db.execute<T extends Record<string, unknown>> requires, breaking the backend typecheck gate. Convert it to a type alias. Co-Authored-By: Claude Opus 4.8 <[email redacted]>

    Files
    1
    Added
    +4
    Removed
    −2
  6. Unify subscription & marketing copy across screens

    Claude ff7e7a21

    Commit notes

    Sources subscription/pricing/marketing copy from a single source of truth and fixes factual + plan-handling inconsistencies that drifted between the landing page, subscription drawer, dashboard, and library. - Add frontend source of truth `frontend/src/lib/config/plans.ts` (typed, `as const`) for plan ids/names/prices/fees/storage/seats/savings/taglines + the competitor-comparison line, with a note to keep it in sync with backend config / PRICING.md. - Landing page (`routes/+page.svelte`) now consumes `plans.ts` instead of hardcoded tier literals; correct the competitor claim (was "Beatstars (12%)"; PRICING.md says BeatStars takes 30% commission) and reframe to the "lower fee + more storage" story. - Fix SubscriptionDrawer plan-name bug: `team_monthly`/`team_yearly` wrongly displayed as "Free". Introduce shared `formatPlanName` helper (covers Free, Pro, Team) and a current-plan fee summary; make cancel/expiry/upgrade copy plan-agnostic ("reduced fee and extra storage" rather than "Pro features"). - StorageUsage upgrade prices, savings, and storage allowance now read live from the subscription API instead of hardcoded €9/€89/€19/100GB. - Library upgrade toasts use `formatPlanName` + live storage quota and drop the inaccurate "100GB / all Pro features" wording (was wrong for Team plans). - Fix the inaccurate competitor comment in `backend/src/config/index.ts` (BeatStars 30% commission, per PRICING.md). Co-Authored-By: Claude Opus 4.8 <[email redacted]>

    Files
    7
    Added
    +164
    Removed
    −60
  7. Ignore Claude Code transient agent worktrees

    Claude 7e7e694a

    Commit notes

    The .claude/worktrees/ directory holds isolated git worktrees created for parallel subagents. It is transient and auto-cleaned, and must never be committed (it contains nested worktree git state). Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    1
    Added
    +4
    Removed
    −1
18 commits
  1. test(creators): assert displayType in public pack detail response

    Claude 84e734b2

    Commit notes

    The public pack detail endpoint now returns `displayType`; update the DB-backed test's expected shape (toEqual) accordingly and set instrument/sampleType on the fixture so it validates the instrument-preferred display label ("kick"). Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    1
    Added
    +4
    Removed
    −0
  2. fix(studio): show displayType in the sequencer sample selector

    Claude ca4a5b72

    Commit notes

    Render and search the consistent displayType (instrument, else structural sample type) in SampleSelector instead of the raw category family, matching the library grid and public pack pages. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    1
    Added
    +6
    Removed
    −3
  3. fix(classification): consistent type on public pack + guest serializers

    Claude 17388427

    Commit notes

    Extend the displayType treatment to the remaining UI surfaces that show a sample "Type" so it stays consistent everywhere, not just the library grid: - Public creator pack page (creators.ts + /u/[slug]/pack/[packSlug]) rendered raw `drumType` (CLAP instrument), which is null until CLAP runs. Now it surfaces and renders `displayType` (instrument, else Essentia's structural sample type), so it is populated for any analyzed sample. - Pack-generator (guest samples) serializer now exposes sampleType/displayType; guest samples have no CLAP instrument, so it derives from the Essentia structural type / loop detection. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    3
    Added
    +20
    Removed
    −2
  4. fix(classification): consistent sample types + sharper key detection

    Claude 7acd0cc0

    Commit notes

    The library "Type" column was inconsistent: it rendered a value that depended on CLAP fields, so when CLAP hadn't classified a sample only Essentia's isLoop survived — loops showed "loop" and everything else showed "—". The sample_type and instrument columns were also never surfaced by the API. Clean Essentia/CLAP split (each does what it's good at): - Essentia (always runs, DSP) now owns the STRUCTURAL sample_type (loop/one_shot/phrase), derived deterministically from loop detection + duration + onsets. This guarantees the Type column is never empty. - CLAP (semantic) owns the INSTRUMENT label (kick/808/vocal) and the coarse category family; it no longer clobbers Essentia's structural type (sample_type via COALESCE). - Surface sampleType/instrument/instrumentConfidence + a derived displayType ("instrument, else structural type") from both library and samples routes and the similar-samples row; the grid renders displayType. - Shared deriveDisplayType/deriveSampleType helpers (+ unit tests). - Backfill sample_type for existing analyzed rows in SQL so the column populates immediately without re-analysis; add sample_type to guest_samples. Key detection accuracy: - Add SpectralWhitening before HPCP in the tonal pipeline — the step Essentia's reference KeyExtractor uses. It flattens the spectral envelope so percussion bleed / a dominant fundamental no longer biases the chroma, which materially improves key accuracy on full-mix loops. Falls back safely if unavailable. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    16
    Added
    +359
    Removed
    −28
  5. fix(audio): correct Essentia DSP and make CLAP the sole embedding authority

    Claude b53cf72a

    Commit notes

    Essentia service (Python): - Fix spectral centroid/rolloff to emit Hz directly (Centroid range=Nyquist, RollOff sampleRate) and drop the fragile normalized-position heuristic. - Fix bandwidth: was always 0 (wrong CentralMoments index + single frame). Now the per-frame spectral spread via CentralMoments(range=Nyquist)+DistributionShape. - Fix temporal centroid units (normalized position * envelope duration -> seconds). - Fix BPM alternatives: use the two peak-BPM indices (0, 3), not a weight. - Implement true peak (dBTP) via chunked 4x oversampling instead of sample peak. - Reset reused stateful algorithms between files so prior audio can't leak. - Remove the dead HarmonicPercussiveSourceSeparation scaffolding (not an Essentia algorithm; it was always a no-op) and run rhythm/tonal on the full signal. - Remove the hand-built 64-dim MFCC embedding; CLAP owns the audio embedding. - Remove dead code: unused loaders, thread pool, and the LFI-prone /analyze (path) and /analyze/batch endpoints; add spectral/rhythm/temporal regression tests. Backend (CLAP owns embeddings): - Drop the 64-dim Essentia embedding everywhere (AudioFeatures, worker writes, client mapper, unused path/batch/stats client fns). - Repoint similarity search and UMAP onto samples.clap_embedding (512-dim). - Derive pack audio character from real Essentia feature columns. - Enqueue CLAP for deduplicated samples so they still get an embedding/classification. - Migration 0026 drops the embedding column, embedding_vector mirror, sync trigger, and legacy indexes. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    18
    Added
    +510
    Removed
    −923
  6. fix(ci): split pure CLAP-search policy out of the DB query module

    Claude 3abce888

    Commit notes

    CI intermittently failed to link `clap-search.test.ts` with "Export named 'CLAP_DEFAULT_MIN_SIMILARITY' not found in module clap-search.ts" — a Bun module-link flake: that pure unit test dragged in the heavy `clap-search.ts` graph (drizzle, ../db, ./clap-client) just to reach a handful of dependency-free helpers. Extract the pure pieces (relevance-cutoff resolution, readiness/failure classification, the not-ready error type) into `clap-search-policy.ts`, which has no DB/CLAP-client imports. `clap-search.ts` re-exports them (`export *`) so the library route and other importers are unchanged, and the unit test now imports the light policy module directly — removing the fragile load. typecheck + lint clean; clap-search test passes in isolation and the full local suite is green (0 fail). Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    3
    Added
    +112
    Removed
    −94
  7. refactor(audio): prune the orphaned TypeScript DSP modules

    Claude 67d9ea94

    Commit notes

    Verified that key-detection.ts, loop-detection.ts, superflux.ts, and cqt.ts form a closed, dead cluster: they reference only each other, nothing outside src/audio/ imports them, and the audio barrel's real consumers (worker, admin, pack-generator) only use ffmpeg/essentia-client symbols. The test suite uses its own local copies, not these modules. These were the standalone DSP helpers behind the in-process analyzer removed in the previous commit, so they are now unreachable. Remove the four modules (~1730 lines), trim the audio barrel to ffmpeg + essentia-client, and drop the now-unused meyda / @types/meyda dependencies (loop-detection was the only user), refreshing the lockfile. typecheck + lint clean; 68 audio/mapper unit tests pass; frozen-lockfile install verified. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    7
    Added
    +1
    Removed
    −1785
  8. refactor(audio): remove the dead in-process TypeScript DSP engine

    Claude 05fe4c5e

    Commit notes

    The legacy TypeScript analysis path (analyzeAudioWithTypeScript / analyzeAudioWithTypeScriptFromFile) and its entire DSP stack — BPM/beat tracking, key detection, LUFS, spectral features, loop detection, transients, the heuristic drum classifier, and MFCC embedding — were fully superseded by the Essentia microservice and CLAP zero-shot classification. They were unreferenced by every live entry point (which delegate to Essentia), so this was pure dead code: ~3150 lines. audio-analysis.ts now just delegates analysis to Essentia and layers the optional LLM categorization pass on top. Removed the orphaned imports (meyda, bun $, key-detection/loop-detection/superflux helpers) and refreshed the module header. No behavior change: the live paths (analyzeAudio, analyzeAudioFromFile, analyzeAudioFromFileWorker, analyzeAudioFromS3Key, analyzeAudioFull, categorizeWithLLM) are untouched, and all unit tests pass. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    1
    Added
    +8
    Removed
    −3177
  9. refactor(essentia): retire the heuristic classification rules engine

    Claude 66e9980c

    Commit notes

    CLAP zero-shot now owns sample type/instrument/tonality, so the hand-tuned spectral/envelope classifier and the duplicated key-gating policy are dead weight. Remove them and let measurement + CLAP speak for themselves. Essentia service: - Delete classification_rules.py (is_unclassified_percussive + key_is_reliable) - Delete analyze_classification (the ~250-line if/elif drum ladder) and its now-orphaned helpers (_band_energy_ratios, _normalize_entropy) - Drop DrumClassification model + classification from the response, and the extract_classification toggle - Replace the percussion/loop/duration-aware key_is_reliable gate with a small intrinsic floor in analyze(): analyze_tonal already nulls atonal keys; we now only drop a surviving key when BOTH its confidence and tonality are weak. Sample-type-aware key suppression is the CLAP tonality signal's job downstream. - Remove the obsolete classification unit tests Backend: - essentia-client.ts: drop ClassificationFeatures + classification from the contract; the mapper no longer derives drumType (always null now) — CLAP owns sample_type/instrument - worker.ts: the CLAP job now also writes the legacy drum_type/drum_type_confidence from the CLAP instrument so that column stays populated and consistent - Update essentia-client tests to assert the mapper leaves type to CLAP Note: the unrelated *dead* TypeScript classifier (classifyDrumType + analyzeAudioWithTypeScript* in audio-analysis.ts) is unreferenced and left for a separate cleanup. Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    14
    Added
    +46
    Removed
    −925
  10. feat(clap): zero-shot sample type + instrument classification

    Claude 08903d0b

    Commit notes

    Use CLAP's shared text/audio space to classify samples instead of the heuristic spectral/envelope rules engine. The audio embedding already computed for semantic search is now also compared against a versioned bank of text prompts (taxonomy.py) and softmaxed per group to label each sample's sample type (one-shot/loop/phrase), instrument (kick, 808, vocal, ...) and tonality (tonal vs percussive). No training and no model files required. CLAP service: - taxonomy.py: versioned prompt bank + instrument->family map - classifier.py: dependency-free cosine/softmax scoring (unit-tested) - clap_model.py: cache label-prompt embeddings, embed_and_classify() - main.py: /classify and /classify-s3 return embedding + classification from a single forward pass; warm label cache on startup - tests/test_classifier.py: 17 tests covering taxonomy + scoring Backend: - clap-client.ts: typed classifyAudioBytes / classifyAudioFromS3Key - worker.ts: CLAP job now persists clap_embedding + sample_type, instrument, instrument_confidence, classification_source, and fills category when empty - schema + migration 0025: additive sample_type/instrument columns + indexes - clap-search.ts: filter by instrument / sample_type - backfill script: also enqueues rows missing classification Co-Authored-By: Claude Opus 4.8 <[email redacted]> Claude-Session: [private session redacted]

    Files
    14
    Added
    +931
    Removed
    −28
3 commits