GET /app/clients now returns up to 8 Gitea releases per OS so users can download older installers while they still exist after prune.
Co-authored-by: Cursor <cursoragent@cursor.com>
Search hits omit album covers and artist images. The worker now reads the full song and artist, stores the description, and leaves Genius image URLs unchanged on mobile.
Co-authored-by: Cursor <cursoragent@cursor.com>
Serve desktop and Android builds from the latest Gitea release on /download, and fix the desktop compile and CI flakes that blocked v1.3.0.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced a new warning for users uploading non-FLAC or WAV formats, indicating that these formats should only be used as a last resort.
- Added functionality to highlight files needing format attention in the upload queue.
- Updated the UI to provide clearer guidance on acceptable audio formats during uploads.
- Improved documentation to reflect changes in upload requirements and user interface updates.
Reviewing the upload queue is now a per-user flag (reviews_uploads), not part
of the admin role: several people can hold it, a moderator can have it, and an
admin may not. Only admins grant or revoke it; existing admins keep it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Quality upgrades, batch covers, staging preview, and resume after reload are in the queue. Loudness and crossfade work on web and Android, and the documented checks now have suites.
Co-authored-by: Cursor <cursoragent@cursor.com>
- POST /admin/users/{id}/reset-recommendations clears the taste profile
(onboarding, CF vector, bandit), play stats and wave impressions; likes,
dislikes and history stay, wave sessions stay so a playing wave keeps going
- moderators may reset plain users, admins anyone including themselves;
the reset is written to the audit log
- users panel gets the menu action with a confirmation; docs updated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- appearance settings get "collapse search" (off keeps the field always open)
and separate switches for the activity and mood pickers on the home page;
stored in ui_prefs (search_collapse, home_activities, home_moods)
- Collection and Admin headers in the sidebar fold their items; the state is
remembered in the browser, a folded Admin shows the review queue badge;
icon-only and phone layouts always show every item
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The server kept the git.example.lan placeholder from .env.example, so the
/android page and in-app updates had no release. install.sh and update.sh now
fill GITEA_URL and GITEA_REPO from the clone's origin (https, ssh and scp
forms, credentials stripped) when they are empty or still the placeholder,
and the API treats the placeholder as not configured.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- settings get a search position (left, center by default, right); the top bar
is three zones and the suggestions open towards the free space
- buttons, chips, tabs, menu items and the home screen controls are not
text-selectable, so clicks and double clicks no longer highlight labels
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /android is a public page with the latest APK, the server address to copy
and three install steps; linked from the sign-in screen and the profile menu
- failed audio analysis can be retried from the library page, which also shows
the most common error; the analyzer no longer burns attempts on files that
are missing because the disk is not mounted
- the top bar search folds into a round button and slides open on click, "/"
or Ctrl+K
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the test server the host music folder was not mounted, so every stream and
fingerprint failed with no such file, and a scan of the empty folder would have
marked the whole library missing and purged it after 30 days.
- a scan of an empty source folder with known files aborts with a clear error
- fingerprinting skips such a source with one warning instead of one per file
- LIBRARY_HOST mounts use rslave, so a disk mounted after start shows up
- update.sh refuses to deploy with an empty LIBRARY_HOST
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The library page compares listen-through, early-skip and like rates per
impression model version, so v1 and the trained ranker can be compared online.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Suggest fetches three times as many candidates and reranks them in the API:
what the user plays, finishes and likes moves up a few positions and what they
dislike moves down, with Meilisearch relevance still the base order.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deleting a missing <uid>_next index is accepted with 202 and fails inside the
task with index_not_found. That error was not treated as not-found, so the first
reindex aborted and search stayed unavailable until indexes existed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The wave logs each served candidate's feature vector to rec_impression_features.
Nightly training joins them with impression outcomes, validates on the last week
and activates the model only when it beats the v1 order and the active model.
The service loads the active ranker and uses its order in place of the v1 score.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- GET /onboarding offers the library's top artists (with album covers)
and genres and says whether to show it (not done and < 10 plays);
PUT /me/onboarding stores the choice or a skip (migration 00009).
- The recommender seeds the taste from it while the user has fewer than
30 scored tracks: chosen artists' tracks +1, chosen genres +0.5.
- Web: onboarding replaces the wave on the home page until done or
skipped; artist grid with covers, genre chips, at least 3 artists.
- e2e journey and the recommender DB test cover it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Imported tracks are created directly under their final name with
O_EXCL (never overwriting; " (2)" on conflict), fsync'ed and checked
against SHA-256 — no hidden .pipu-tmp file next to them any more.
- On any failure the agent removes its own partial file and the empty
directories it created for it.
- The write check uses access(W_OK) and the read-only mount flag instead
of creating and deleting .pipu-write-test in the storage root.
- Tests assert the storage tree holds only audio files after successful
and failed writes and after the write check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- newApp (extracted from main) is the exact production wiring; the
`ci / db` job now also runs it on PostgreSQL, Redis and Meilisearch
and walks the main user flows over HTTP: first admin sign-in and
credential change, local source and scan, search, album / artist /
top tracks, signed stream, events and history, likes, fallback wave,
playback state, upload queue up to review.
- ALS on a small library produced fewer than 64 factors and the insert
into vector(64) failed; vectors are now zero-padded to the column size.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New `ci / db` job with a pgvector service: Go applies all migrations,
rolls them back to zero and applies them again, then runs the scanner,
fingerprint, write-template, top-tracks and upload-queue store queries;
Python runs the analysis worker, catalog / profile loading and a full
ALS training run against the same schema. Until now this SQL ran
nowhere before reaching a real server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>