From af6ed6130f14cf58a1d064db56499eda34bd125c Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Fri, 5 Jun 2026 17:57:11 -0400 Subject: [PATCH] docs: log WaveformSeeker W3 completion in COMPLETED.md --- COMPLETED.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/COMPLETED.md b/COMPLETED.md index 7c356c5..7d6bb3d 100644 --- a/COMPLETED.md +++ b/COMPLETED.md @@ -6,6 +6,41 @@ Newest entries at the top. Group by phase/wave header (mirroring `PLAN.md` / `CM --- +## WaveformSeeker Wave 3 — CMS PreProcessing panel + +**Status:** W3 (CMS track-preprocessing panel) landed on 2026-06-05 (branch `waveform-w3-cms`, pending merge to dev). + +### W3 — CMS PreProcessing panel + +**Landed 2026-06-05.** + +Implemented the CMS surface for on-demand waveform profile generation: a new `/tracks/preprocessing` page (table view of all tracks with profile status) and two API endpoints for querying and triggering profile generation. + +**API endpoints (`DeepDrftAPI`):** +- New `GET api/track/waveform-status` (ApiKey) — returns `WaveformStatusDto[]` with per-track profile existence (one entry per track in the database, indicating whether a profile sidecar exists in the vault). +- New `POST api/track/{trackId}/waveform` (ApiKey) — triggers on-demand profile compute and store for an existing track. Skips if profile already exists; errors surface gracefully (no profile → HTTP 404, track not found → HTTP 400). + +**Models (`DeepDrftModels`):** +- `WaveformStatusDto` — carries `TrackId`, `EntryKey`, `TrackName`, `HasProfile` boolean, and metadata for display/sorting. + +**CMS service (`ICmsTrackService` / `CmsTrackService` in `DeepDrftManager`):** +- `GetWaveformStatusAsync()` — service method wrapping the `api/track/waveform-status` call; returns `Result` for error handling. +- `GenerateWaveformProfileAsync(entryKey)` — service method wrapping the per-track generation endpoint; returns `Result` (success → true, profile already exists → true, error → false with result code). + +**CMS UI (`DeepDrftManager/Components/Pages/Tracks/TrackPreProcessing.razor`):** +- New page mounted at `/tracks/preprocessing` (guarded by CMS auth). +- Table layout: track name, artist, "Profile Status" indicator (✓ or ○), with a per-row `Generate` button. +- Sequential "Generate All Missing" bulk action button — iterates tracks with `HasProfile == false`, calls `GenerateWaveformProfileAsync`, shows progress. On completion, refreshes the table. +- Nav link added to `TrackList.razor` and `CmsLayout.razor` / `Index.razor` so the page is discoverable from the track management surface. + +**Architecture notes:** +- Waveform generation on-demand (not automatic on upload like in W1) is intentional: Wave 1 profiles were computed for all future-uploaded tracks; Wave 3 adds a retroactive tool to populate profiles for existing tracks uploaded before Wave 1. The bulk action supports batching. +- Service calls are fire-and-forget-result, not throw-on-error — `GenerateWaveformProfileAsync` returns a `Result` for the caller to inspect. This matches the FileDatabase philosophy (errors in compute/store are swallowed at the service boundary, callers check return values). +- Profile endpoint uses the same `WaveformProfileService` that computes profiles during upload — no new algorithm or storage path introduced. CMS can only trigger on-demand what the upload path does automatically. +- HTTP cache headers are deferred (same as W1-T2). Each `api/track/waveform-status` call lists all tracks and their current state; this is acceptable for the admin surface where refreshes are infrequent. + +--- + ## WaveformSeeker Wave 2 — DOM seekbar + Interop module **Status:** W2 (WaveformSeeker component) landed on 2026-06-05 (branch `waveform-w2-seeker`, pending merge to dev).