1. 22 Jun, 2026 19 commits
    • feat(bridge): midistream groundwork for the live MIDI dashboard panel · 270a01d6
      MidiStream fans one aseqdump subprocess out to N web subscribers (SSE), reusing
      midimon.parse_line + enrich (one parsing source of truth); reader runs only
      while watched (lazy start / stop on last unsubscribe, so no MIDI port held idle).
      parse_ports is pure + tested. NOT yet wired into server/UI — see resume task.
      
      Parked mid-feature: server SSE endpoint + dashboard panel still to do.
      PLN (Algolia) authored
    • fix(bridge): Armada launches into the catalog viz, not a dir listing · 55660a2c
      Clicking L'Armada served armada/ root → a file listing (felt broken). Point it
      at armada/tide-table (where the viz lives) and open /triangle.html — same as
      `tide.py serve`. Verified: /triangle.html → 200.
      
      Also lands midimon.enrich() (note/velocity/controller→structured) + tests, the
      parsing groundwork for the live MIDI dashboard panel.
      PLN (Algolia) authored
    • feat(bridge): fleet launchers + MIDI monitor + unified tray · 1eba89fc
      The hub was dead links (clicking Foundry 404'd — its server wasn't running).
      Now it's a real control center, with one shared registry driving both faces.
      
      - launchers.py: allow-listed registry. Web tools (Foundry/Armada) = start-or-open
        via port-check (spawn the server if down, then open); native apps
        (Pulsar/Ardour/qjackctl) launch detached with running + availability state.
        Wayland has no portable focus → running apps report 'already-running'.
      - midimon.py: 'aseqdump | tr' done right — parses each event, renders aligned &
        colourised with note names (C4) and velocity bars. parse_line is pure/tested.
      - Bridge UI: hub shows live running dots; start-or-open opens a blank tab within
        the click gesture then navigates once the server binds (no popup block).
      - perf-tray: 'Open Bridge' + 'Launch ▸' submenu off the SAME launchers.py — the
        tray is now the unified ParVagues tray (DRY with the web hub).
      - 17 tests (launcher registry/state + MIDI parser). Verified: Foundry card boots
        the server → :8765 200.
      PLN (Algolia) authored
    • feat(bridge): desktop launcher entry + ParVagues wave icon · ba1cb149
      So 'parvagues' is findable in the KDE app menu (the Bridge runs headless as a
      systemd service → had no .desktop, nothing to index). Entry opens the dashboard;
      ParVagues two-tone wave SVG as the icon. Installed via symlink into
      ~/.local/share/applications + kbuildsycoca.
      PLN (Algolia) authored
    • feat(tide-table): GT corpus wave 2 (→60, quadrant-balanced) + V/A calibrator · 0dcd2f10
      Corpus 22→60 tracks, all 4 V/A quadrants now ≥13 (was +-:4, --:2 thin), 50 genres,
      all 12 emotions — chosen for confident, balanced priors (quality of pseudo-GT > raw
      count for calibration). Added the sad/dark-calm + calm/pleasant fillers (Portishead,
      Mazzy Star, Satie, Debussy, Coltrane, Bon Iver…) the gaps report flagged.
      
      emotion_calibrate.py: fits per-axis affine gt≈a·pred+b over analyzed∩GT to DE-COMPRESS
      the center-biased CLAP read (learns the scale-up from data, not a guessed tau).
      Reports leave-one-out CV error (honest generalization, not in-sample) + re-derives the
      label from calibrated V/A (nearest anchor) so we see if labels improve too. Pragmatic
      call: scale corpus = whole-mix analysis (demucs doesn't scale to 100s/1k; stems didn't
      beat mix on accuracy) — stems reserved for the hexa lane.
      PLN (Algolia) authored
    • refactor(perf-tray): fold onto shared tools/bridge/perf.py (DRY) + wave icon · ce3da569
      - perf-tray.py drops its duplicated Thermals/detect_mode/_read*/MODES/SCRIPT
        and imports them from tools/bridge/perf.py — the tray is now just the Qt face
        of the same logic the web Bridge serves (one source of truth)
      - tray icon restyled with the ParVagues signature wave (drawn in Qt, no asset)
        under the heat-coloured temp badge
      - parvagues-bridge.service → WantedBy=default.target so it boots headless with
        linger (always-on dashboard, no login needed); tray stays graphical-session
      - deployed: bridge enabled+active on :8773, tray restarted, linger enabled
      PLN (Algolia) authored
    • feat(tide-table): emotion GT corpus + grader — training-knowledge priors vs CLAP · 3afc4309
      PLN's validation idea: famous tracks whose feeling/structure/genre the model already
      knows = pseudo-ground-truth to grade the emotion engine, disagreements driving tuning +
      coverage (self-correcting 30→100→300). emotion_corpus_gt.json: wave-1 22 tracks spanning
      all 12 emotions + V/A quadrants + genres + structural archetypes (steady / quiet-loud /
      long-build); GT = emotion labels + V/A centre + approx fractional section structure +
      genre. emotion_corpus.py: fetch (yt-dlp android+bestaudio 403 workaround) → analyze
      (demucs+stem-aware or --mix) → grade (emotion-hit, V/A error, quadrant, vocal-presence) →
      gaps (coverage histogram → next wave).
      
      BASELINE (whole-mix, 5 tracks): 40% emotion-hit, 40% quadrant-hit, mean V/A err 0.75 —
      honest verdict: NOT yet trustworthy. Three systematic biases surfaced: (1) center/positive
      compression (extremes pulled to mild +V/+A), (2) 'playful' over-fires (3/5), (3) whole-mix
      misses aggression entirely (Prodigy Firestarter→playful +V) — the exact case stem-aware
      (drums/bass arousal) should fix. Corpus now drives calibration before the #90 hexa handoff.
      gaps: +- and -- quadrants thin, fill at wave 30.
      PLN (Algolia) authored
    • feat(tide-table): stem-aware emotion_timeline — fuse per-stem CLAP reads · 59fb2a11
      Adds analyze_stems(): separates via foundry_stems (vocals/bass/drums/other), scores
      each stem on a shared window grid, fuses V/A by stem role (valence rides vocals+other,
      arousal rides drums+bass+mix), and flags vocal presence per window as a structure cue.
      Refactor: shared _finalize (smooth→relabel→section→summary) now serves both whole-mix
      analyze() and analyze_stems(); embed_at/window_grid/windows helpers extracted.
      
      FINDING (Bohemian Rhapsody, mix vs 4-stem): stem-aware gives a cleaner valence track +
      vocal-presence sections (88% vocal; outro correctly reads calm, not 'cold'), BUT the
      current arousal fusion UNDER-weights the mix and softened the hard-rock peak that the
      whole-mix caught (tense A+0.77 → hypnotic A+0.55) — that section's intensity is a
      full-mix gestalt isolated stems lose. So fusion weights need empirical tuning; the
      ground-truth corpus (next) drives it. Both modes run end-to-end (#89).
      PLN (Algolia) authored
    • feat(bridge): The Bridge — always-on ParVagues web dashboard + perf toolbar · 63ce1034
      Answers 'is there a ParVagues web service running a dashboard?' — now yes.
      Folds perf-tray's function into a web toolbar + extensible fleet hub.
      
      - perf.py: rootless Thermals (hwmon) + detect_mode + sudo-backed set_mode,
        ported from perf-tray.py with Qt dropped (DRY-able with the tray later)
      - server.py: stdlib http.server (Foundry lineage); GET/POST /api/perf, /api/hub.
        Binds 127.0.0.1 by default — mode-switch flips the CPU governor via sudo, so
        not LAN-triggerable unless --host 0.0.0.0
      - ui/index.html: Ship's Bridge toolbar (live temp badge 55/70/85, mode switch,
        freq/fan/throttle) + hub cards (Foundry :8765, Armada :8731)
      - bridge.py CLI (serve/status/perf); parvagues-bridge.service (systemd --user)
      - 6 tests on pure perf logic; README incl. deploy + security notes
      
      Smoke-tested: tests green, API live, mode detect + thermals reading correctly.
      PLN (Algolia) authored
    • feat(tide-table): foundry_stems — bridge to the Foundry demucs engine · 607c408d
      Stem-aware emotion needs the voice isolated: the full mix is muddy for CLAP, but
      the VOCALS carry valence, DRUMS+BASS carry arousal, and vocal presence is itself a
      section/structure cue. ensure_stems(file, slug) consumes the Foundry's in-process
      Python API (tools/foundry, the shared separation engine) → {mix,vocals,bass,drums,
      other} absolute paths, idempotent via catch.json (re-runs free). Validated: 4-stem
      demucs separation of a 6-min track (Bohemian Rhapsody) lands all four stems clean.
      Feeds emotion_timeline's stem-aware analysis (#89) and the hexa lane (#90).
      PLN (Algolia) authored
    • docs(foundry): API integration guide + phase-2 synthesis & research · ecfa108c
      - README: 'Use as an API' — Python import / CLI subprocess / HTTP API, the
        path+catch.json contract, env overrides (for sibling tools e.g. the #89
        emotional-arc tool that consumes the demucs engine for stems)
      - README: add 'link' to CLI reference
      - research/{A,B,C}_*.md: the three strand reports (empirical profile,
        fundamentals rulebook, prior-art + recommended zero-dep stack)
      - research/PHASE2_FINDINGS.md: strand-D synthesis — corrected per-stem model
        (loops cut per stem, often-but-not-always time-aligned), loopability rubric,
        Take/StemSlice model, correlation engine (§5·0 GT-at-scale), Hall of Fame
        tierlist, section-label grounding ( #89), 80/20 build order
      - PHASE2_LOOPFINDER.md charter: grounded in the real flow + ground-truth pairs
      PLN (Algolia) authored
    • feat(tide-table): emotion_timeline — slide CLAP emotion kernel over a track → arc · 20bc875e
      Windows a master (~12s/50% hop), CLAP-embeds each window (new sample_semantics.
      embed_audio_arrays seam), runs the emotion_ontology kernel per window → (valence,
      arousal, top-emotion) series; median-smooths, relabels from the smoothed circumplex
      point, fuses short runs into emotion SECTIONS. Emits frames+sections+summary JSON —
      the continuous-V/A + discrete-scene lane hexa wants. Validated on Bohemian Rhapsody:
      caught the warm-intro → energetic-middle → tense rock-peak (A+0.77) → calm-outro arc.
      PLN (Algolia) authored
    • feat(tide-table): CLAP emotion ontology — synonym clusters on the V/A circumplex · cc0dc274
      Each emotion is a CLUSTER of angle prompts (adjective pairs + scene metaphors +
      bodily framings, EN+FR) marginalized to one robust per-emotion score (mean cosine,
      size-invariant) — the synonym→emotion fold mirrors the resolver's descriptor→family.
      12 emotions × 6 angles, each placed on Russell's valence/arousal circumplex, so the
      distribution yields a continuous V/A point + a discrete top-emotion label.
      
      Per-window kernel: score(ae_row) takes one CLAP audio embed → {scores, dist, top,
      valence, arousal, confidence}. Validated: probe archetypes land correctly (melancholic
      0.76, aggressive 0.94, hypnotic 0.94, cold 0.72); real-audio path confirmed (pad→
      dreamy/melancholic calm). Feeds the planned per-track emotion timeline (hexa lane).
      PLN (Algolia) authored
    • feat(foundry): close-the-loop publish + phase-2 loop-finder charter · 56c81e57
      - engine/publish.py: link_kit() symlinks Samples/<kit> → Dirt-Samples/<kit>
        so a freshly-cut kit loads as s "<kit>" (325/508 Dirt-Samples entries are
        this pattern). Idempotent; repoints stale links; refuses to clobber real dirs.
      - foundry.py link <kit> CLI; 5 new tests (15 total, all green)
      - PHASE2_LOOPFINDER.md: research charter for the loop-finder (Sonnet-agent
        deep-research pass) — grounded in the REAL flow (yt → separated/htdemucs →
        hand-cut → Work/Sound/Samples → ln → Dirt-Samples → .tidal), with the
        crimewave/diams_dj/humpty stem→loop pairs as free ground truth
      - README: export target corrected to Work/Sound/Samples + link step
      PLN (Algolia) authored
    • feat(foundry): engine1 sample foundry — URL → audio → stems (CLI + GUI) · 9eb2e66f
      The Sample Foundry: turns a track URL into separated stems ready for
      sampling, replacing the manual yt-dlp → demucs → Audacity dance.
      
      - engine/ — pure-ish, importable steps (model/fetch/separate); heavy work
        shells out to dedicated venvs so the engine runs under system python3
      - separate.py = pluggable backend REGISTRY: demucs (engine1, live) +
        roformer (engine2, stubbed) behind one --backend interface
      - foundry.py — CLI driver (fetch/sep/catch/list/backends/serve), tide.py-style
      - server.py — stdlib GUI backend with job-progress + HTTP Range (audio seek)
      - ui/index.html — self-contained GUI in the armada Ship's Bridge tokens;
        stems colour-coded by role (bass/drums/other/vocals)
      - tests/ — 10 unit tests on the pure parts (slug, info-parse, argv, registry)
      - README — workflow, engine1→engine2 roadmap incl. Roformer hyperparams +
        6GB VRAM caveat, phase-2 loop-finder charter, UX surface
      
      Validated end-to-end on the Loituma test catch.
      PLN (Algolia) authored
    • fix(armada/serve): swallow client-disconnect on media Range seek · d70c3ee7
      copyfile() threw BrokenPipeError/ConnectionResetError (Errno 104) when a
      browser aborts/seeks a Range request mid-stream — normal for <audio>
      scrubbing, but it spammed a traceback. Wrap both copy branches and close
      the file handle in a finally. Verified: mid-stream abort leaves no
      traceback and the server keeps serving (206 follow-up OK).
      PLN (Algolia) authored
    • feat(sextant): Freedom & control matrix + UPDATE cost bucket · 5e3b0ad2
      Adds the edit/remaster/pull/permanence axis the cost model was missing:
      
      - 4th cost bucket UPDATE: re-mastering an already-live release. Free on
        RouteNote; a new paid release on CD Baby; forces DistroKid to the Ultimate
        tier ($89.99/yr) for an in-place Audio Swap. Driven by a Remasters/year slider.
      - Freedom & control matrix: per-option remaster / edit-metadata / takedown /
        if-you-stop-paying, glyph+text+colour (never hue alone). Surfaces the key fact
        that no DSP distributor swaps audio in place (a store rule), with Bandcamp the
        free-replace outlier.
      - Ownership reframed: all options are non-exclusive (you keep 100% of masters);
        what differs is permanence, edit-freedom, portability.
      - Softened the unverified RouteNote freeze-risk claim; flagged Premium pricing
        as contested pending verification.
      PLN (Algolia) authored
    • update :D · 5f3f4d21
      PLN (Algolia) authored
  2. 10 Jun, 2026 1 commit
    • fix(perf): keep CPU turbo ENABLED in perf mode (was capping at base clock) · f627f6ca
      Both --extreme and --optimize disabled intel_pstate turbo on the theory
      that frequency changes cause jitter. On HWP-capable CPUs (i7-10875H) the
      performance governor already holds clocks steady at the top; disabling
      turbo only caps all cores at the 2.3GHz base (~64% of clock headroom
      thrown away), starving SuperDirt's DSP and causing the very xruns/crackle
      it was meant to prevent. Now pins min/max_perf_pct=100 with turbo on.
      PLN (Algolia) authored
  3. 07 Jun, 2026 20 commits
    • docs(tasks): archive 42 completed board tasks pre-compact · 070a86d0
      Snapshot resolved tasks (foundation/distro, Ardour/boundaries, Judge UI, triangle
      DRY, fleet colour, the sample-grounding fun-sprint, and the dataviz epic #64) so
      the active board stays lean. Active board now = pending/in-progress only.
      PLN (Algolia) authored
    • feat(unwrapped): de-mud the field + zoom/pan to dive in · 8a61a415
      Field: per-cell DOMINANT family colour (was a mean of all overlapping hues →
      brown mud); mixed/overlap zones now fade by 'purity' instead of muddying.
      Tuned colourful-but-subtle behind the dots (desaturate 0.40 + slight lift to
      white, maxα 0.44) — dots stay the stars.
      Zoom/pan: wheel to zoom at cursor, drag to pan when zoomed, +/−/reset controls
      (top-left) + double-click reset; dots grow with zoom; field & hit-testing follow
      the view transform, clipped to the plot rect.
      PLN (Algolia) authored
    • data(resolve): ground all 1485 corpus samples — fill the per-folder gap · d69e0aa0
      sample_families.json was built at a smaller per-folder cap → only 831 per-index
      entries (825 of the 1485 plotted samples labelled). Re-ran the resolver at
      --max-files 12 (same clap:fine method) over 150 folders → 1501 per-index entries,
      1490 labelled. unwrapped.json now 100% family-coloured (was ~56%): no more grey
      'unlabelled' dots, the density field reads everywhere.
      PLN (Algolia) authored
    • feat(unwrapped): density colour-field behind the scatter (timbral regions) · 1729689b
      Low-res IDW of dot colours (72x46 Gaussian-weighted, σ≈3.1), desaturated 50% and
      faded by local density, bilinear-upscaled behind the dots → pink kick region,
      blue keys region, purple bass / yellow hat pockets emerge as a slow gradient.
      Cached offscreen, rebuilt only when colours/axes/filter change (never on hover);
      'regions' toggle in the controls; auto-off in vibe-search mode.
      PLN (Algolia) authored
    • fix(vibe): warm-up runs a real text forward (absorb torch lazy-init) · cec9dec3
      Loading weights wasn't enough — the first forward still cost ~30s on torch's
      one-time graph/thread init. Warm now runs a throwaway _embed_texts() so the first
      USER query is ~1.5s, not 30s.
      PLN (Algolia) authored
    • fix(vibe): warm CLAP at server startup + honest UI feedback/timeout · e3b1fecc
      The first /vibe hit cold-loaded CLAP (~16s) with the UI stuck on 'searching…',
      reading as hung. Now serve.py warms the model in a daemon thread at startup (when
      semantics_embeds.npz is present) so the first query is instant; the client shows
      'first search loads the model, ~15s' on a cold start and aborts after 90s with a
      retry hint instead of spinning forever.
      PLN (Algolia) authored
    • feat(landing): dataviz front door + honest style cloud (#63,#88) · c122e7a5
      index.html ties the corpus dataviz together (By the numbers · Unwrapped · The
      Triangle) and opens with a typographic style cloud sized by TRACK count — read
      from PLN's own gig metadata (catalog_view metas[].style via models.norm_style),
      never per-sample CLAP genre. dnb 18 · breaks 17 · techno 14 · nujazz 12 = the
      TechnoJazz spine. build_landing.py bakes landing.json (cloud + corpus stats).
      Ship's Bridge; magenta only on the live-dot + cloud hover.
      PLN (Algolia) authored
    • feat(unwrapped): seeded vibe-search + find-similar + semantic vibe-map (#82,#87) · 6351e0ae
      - build_unwrapped: 2D PCA of the CLAP embeds → per-sample 'vibe map' coords +
        16 seed-vibe chips (PLN's own words — the on-ramp, since users don't know what
        to type). vibe0/vibe1 join the axis picker as a semantic-space lens.
      - unwrapped.html: VIBE SEARCH box (free text → /vibe) + clickable seed chips;
        results highlight on the map (dim misses, size hits by similarity, ring the top,
        faint-violet→magenta ramp) and auto-reveal the vibe map; result strip auditions.
        Shift-click any dot → /similar (nearest neighbours in embedding space). Null-safe
        plotting for vibe/raw axes. Graceful banner when the endpoint is absent.
      PLN (Algolia) authored
    • feat(semantics): validated CLAP vibe-search + live /vibe endpoint (#82,#86) · ac4643d0
      Katana-first finding: per-one-shot CLAP genre/mood tags are unreliable (every
      hit → boom-bap/euphoric — a 0.3s sound has no genre), but the audio EMBEDDINGS
      are gold for RELATIVE similarity. 'warm dusty rhodes' → suns_keys gold-keys +
      west-coast electric; 'jazzy upright bass' → no_sunshine/come_bass loops; a kick's
      nearest neighbours are other kicks (0.96 cross-folder). So we ship similarity,
      not fake absolute labels (Principle 1: trust the instrument).
      
      - sample_semantics.py validated on real audio; semantics_embeds.npz = 1490×512-d.
      - serve.py: lazy CLAP /vibe?q= (embed any phrase → rank) + /similar?name= (by
        audio-embed cosine). 503 if unbuilt, 400/404 on bad input; static serving
        untouched. Single-user LAN, torch loads once on first hit.
      PLN (Algolia) authored
    • feat(unwrapped): explorable feature-space map of the sample corpus (#81) · b7adc89e
      ParVagues Unwrapped — a Ship's Bridge dark explorable over unwrapped.json:
      - The map: canvas scatter of all 1,485 samples; pick any 2 of the 5 named
        superfeature axes (or raw features); colour by family / audio-cluster /
        folder-kind / folder-agreement; hover to identify, CLICK TO AUDITION the .wav.
      - The five axes: PCA loading bars (what composes each superfeature) + RF
        family-discriminator importances (centroid + temporal-centroid on top).
      - Family fingerprints: per-family beeswarm on a switchable feature — the
        kick-punchy / bass-sustained split made visible.
      - Folders are loose: family x audio-cluster contingency grid (ARI 0.25) — the
        timbre-not-label story, the data behind 'a folder is a loose grouping'.
      Zero npm deps; fleet family colours; magenta reserved for the audition pulse.
      PLN (Algolia) authored
    • feat(unwrapped): bake explorable per-sample feature dataset (#81) · c2d6eedb
      Joins per-file features × resolver family/kind × standardized PCA projection
      (PC1-5) × KMeans timbral cluster × audition .wav path into one unwrapped.json
      the browser explores without recomputing. Reuses feature_eda.load_matrix so the
      matrix matches the MDA exactly. Names the 5 leading PCs as superfeature axes
      (Brightness / Timbre / Loudness / Envelope kick-bass / Tonal-noisy), orienting
      coords by a stable anchor so poles read right. Contract tests green.
      PLN (Algolia) authored
    • fix(resolve): a folder is loose — kits read as kits, not a 'dominant' verdict · 9134398c
      PLN: each SAMPLE is classified individually; a folder is a loose grouping, often a
      heterogeneous KIT. Added kind=single|dominant|kit; for kits folder_agrees=None and
      the run shows KIT [fam+fam] not a misleading dominant+flag. Folder-name flag now fires
      only for folders claiming ~one family (cpluck->synth still flagged). Regenerated palette.
      PLN (Algolia) authored
    • feat(feature_eda): MDA over 1485 samples → the superfeature axes · 01b88ed5
      sample_features.py overfetched 36 L0/L1 features × 1485 corpus samples; feature_eda
      mines them three ways:
      - correlation: only 2 redundant pairs ≥0.9 (duration~temporal_centroid 0.97,
        bandwidth~rolloff 0.91) → the overfetch was lean, 34/36 independent.
      - PCA: intrinsic dim 19 (90%) / 24 (95%) — genuinely high-D. The 5 leading PCs are
        interpretable SUPERFEATURE AXES: PC1 brightness (rolloff/centroid), PC2 timbre
        (mfcc5-8), PC3 loudness (rms/peak/flux), PC4 envelope/time (temporal_centroid,
        decay_slope, attack — the kickbass axis), PC5 tonal-vs-noisy (kurtosis/chroma_entropy).
      - clustering: KMeans(12) vs resolver families ARI=0.25 NMI=0.40 (timbral clusters
        partly orthogonal to semantic family — consistent with 'folders are loose').
        RF importance: spectral_centroid + temporal_centroid are the #1/#2 family
        discriminators → validates productizing the kickbass tiebreaker (#80).
      TDD: 3 synthetic invariants (redundancy/dim/separation) + real-data load guard.
      PLN (Algolia) authored
    • data(step1): grounded sample palette — 149 corpus folders (clap:fine) · a93c47af
      Layered resolver (L1 filename -> L3 batched CLAP audio -> L2 folder cross-check).
      116 homogeneous, 33 kit-like, 20 folder-name disagreements flagged (cpluck->synth,
      amencutup->snare, sunny_brass->pad, nujazz_keys125->lead...) — audio overrides the
      name, flags surface for review not silent override. max_files=6, ~7min.
      PLN (Algolia) authored
    • perf(clap): encode the text tower once, audio-only forward per folder · 96854679
      The ~88 fine descriptors were re-encoded through RoBERTa on every folder's
      forward — a fixed cost that made batch size irrelevant. Now cache the normalized
      text embeddings + logit scale at load; per-folder forwards run only the audio
      tower (get_audio_features) and a matmul against the cached text embeds. ~1.8x
      (14s->7.7s/folder; text was ~45% of per-folder cost).
      
      API note (transformers 5.10.2): get_text/audio_features return a model-output
      object whose .pooler_output IS the projected 512-d joint embedding — verified
      identical to a full ClapModel forward to 1.6e-7. No classification change.
      PLN (Algolia) authored
    • feat(resolve): --max-files knob to trade CLAP cost vs kit per-index detail · 3250dcbb
      Opaque folders send every file through a batched HTSAT forward; --max-files N
      caps that. Defaults to CLF.MAX_FILES (12). Use 6 for fast dominant-family
      grounding when full per-index kit detail isn't needed.
      PLN (Algolia) authored
    • data(eda): ground all 61 local takes (Stage-1 corner-B coverage) · 04cbf307
      Per-take per-orbit level/register/activity from local Ardour interchange stems
      via the optimized build_eda. 61/61 grounded (~8min, warm cache 12-19s on the
      big SET takes). 2 empties correctly flagged (Take28 0.6s, Take63 8.6s sketches);
      kick orbit (d1) sub-register on all 57 active (centroid never >300Hz).
      PLN (Algolia) authored
    • perf(resolve): batch the resolver's audio path into one CLAP forward/folder · c32db821
      resolve_folder looped classify_file per file -> one CLAP forward per opaque
      file. Now: run L1 (filename) for all files first, then classify ONLY the opaque
      ones in a single batched forward. Extracted classify_files() as the one place
      per-file audio prediction lives (CLAP batched, PANNs per-file); classify_file
      and classify_folder both route through it so batching can't be lost by accident.
      Validated on the jazz kit (per-index BD/HH/SN via filename, CB/P1/P2 via audio).
      PLN (Algolia) authored