diff --git a/internal/api/library_sync_test.go b/internal/api/library_sync_test.go index 6ffc795c..4539a4a4 100644 --- a/internal/api/library_sync_test.go +++ b/internal/api/library_sync_test.go @@ -41,9 +41,8 @@ func TestLibrarySync_AfterArtistUpsert_ReturnsHydratedPayload(t *testing.T) { truncateLibrary(t, pool) u := seedUser(t, pool, "alice", "x", false) - // Seed an artist + write a change row in the same tx — that's the - // invariant the scanner wiring (Task 5) will enforce, and the - // handler relies on. + // Seed an artist + write a change row in the same tx — the invariant + // library writes keep, and the handler relies on. ctx := context.Background() tx, err := pool.Begin(ctx) if err != nil { @@ -122,8 +121,8 @@ func TestLibrarySync_DeleteIsReflected(t *testing.T) { u := seedUser(t, pool, "alice", "x", false) // Just write a delete change row directly (no underlying mutation). - // Scanner wiring (Task 5) is what couples real deletes to LogChange; - // here we test the handler reflects what's in the log. + // Library writes couple real deletes to LogChange; here we test the + // handler reflects what's in the log. ctx := context.Background() tx, _ := pool.Begin(ctx) _ = sync.LogChange(ctx, tx, sync.EntityArtist, "deadbeef-dead-beef-dead-beefdeadbeef", sync.OpDelete) diff --git a/internal/api/me_profile.go b/internal/api/me_profile.go index fb14f19e..aa7e021b 100644 --- a/internal/api/me_profile.go +++ b/internal/api/me_profile.go @@ -23,7 +23,7 @@ type updateProfileReq struct { // nil = leave unchanged; non-nil empty string = clear; non-nil // non-empty = update to that value. Note: distinguishing // omit-vs-clear at JSON-decode time requires custom unmarshaling - // or a sentinel; for v1 we use the simpler "empty string clears" + // or a sentinel; we use the simpler "empty string clears" // semantics: any field present in the JSON body is applied. DisplayName *string `json:"display_name"` Email *string `json:"email"` diff --git a/internal/coverart/provider.go b/internal/coverart/provider.go index 29068f61..f7b07e44 100644 --- a/internal/coverart/provider.go +++ b/internal/coverart/provider.go @@ -32,7 +32,7 @@ type Provider interface { RequiresAPIKey() bool // DefaultEnabled is whether a freshly-installed Minstrel ships - // with this provider on. Both v1 providers return true. + // with this provider on. Providers that need an API key ship off. DefaultEnabled() bool // Configure receives the admin's settings (api_key, enabled @@ -102,8 +102,8 @@ type ArtistArtProvider interface { // TestableProvider is an opt-in capability: providers that can answer // "is my config working?" without performing a full enrichment cycle. -// Used by the admin Test-Connection button. v1: both MBCAA and -// TheAudioDB implement this. +// Used by the admin Test-Connection button. MBCAA and TheAudioDB +// implement this. type TestableProvider interface { Provider TestConnection(ctx context.Context) error diff --git a/internal/coverart/provider_theaudiodb.go b/internal/coverart/provider_theaudiodb.go index 984502e1..2d9d8bff 100644 --- a/internal/coverart/provider_theaudiodb.go +++ b/internal/coverart/provider_theaudiodb.go @@ -23,8 +23,8 @@ const ( // theAudioDBMinPeriod enforces TheAudioDB's documented free/test // rate limit (2 req/sec). Patreon supporter keys allow higher - // rates; we don't differentiate in v1 — operators with supporter - // keys experience the conservative 2 req/sec ceiling. + // rates; we don't differentiate — supporter keys get the same + // conservative 2 req/sec ceiling. theAudioDBMinPeriod = 500 * time.Millisecond // theAudioDBMaxRetries is the number of retry attempts on 429 / diff --git a/internal/eventbus/eventbus.go b/internal/eventbus/eventbus.go index 0280e5a2..d9b42eda 100644 --- a/internal/eventbus/eventbus.go +++ b/internal/eventbus/eventbus.go @@ -1,5 +1,6 @@ // Package eventbus is an in-process publish/subscribe bus for real-time -// events the server emits to subscribed clients (today: Flutter via SSE). +// events the server emits to subscribed clients (the web and Android apps, +// over SSE). // // Writers (likes handler, requests reconciler, scanner, etc.) call Publish // to announce a state change. Each connected SSE client holds a @@ -13,9 +14,9 @@ // - No persistence. A client that connects after an event was emitted // will not see that event. SSE clients are expected to fetch a fresh // snapshot via the normal /api/* endpoints on (re)connect. -// - No cross-process broadcast. v1 runs as a single Go binary; a future -// multi-instance deployment will need a real broker (NATS / Redis -// pub-sub / etc.) but that's out of scope here. +// - No cross-process broadcast. Minstrel runs as a single Go binary; a +// multi-instance deployment would need a real broker (NATS / Redis +// pub-sub / etc.). package eventbus import ( diff --git a/internal/mailer/mailer.go b/internal/mailer/mailer.go index feea93dc..090017d5 100644 --- a/internal/mailer/mailer.go +++ b/internal/mailer/mailer.go @@ -74,8 +74,8 @@ func (s *SMTPSender) Send(ctx context.Context, to, subject, textBody, htmlBody s // We respect the use_tls flag: if true, we require STARTTLS via // smtp.SendMail's default behavior (which negotiates STARTTLS when // the server advertises it). For implicit-TLS (port 465 style), - // we'd need a custom dial — skip that complexity for v1 and rely on - // STARTTLS via port 587 (the default). + // we'd need a custom dial; instead this relies on STARTTLS via port + // 587 (the default). dialCtx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() _ = dialCtx // smtp.SendMail doesn't accept ctx; the timeout is enforced via Dialer below diff --git a/internal/recommendation/candidates.go b/internal/recommendation/candidates.go index faf67cf0..ba388f5d 100644 --- a/internal/recommendation/candidates.go +++ b/internal/recommendation/candidates.go @@ -92,7 +92,7 @@ type CandidateSourceLimits struct { UserCoplay int } -// DefaultCandidateSourceLimits returns the v1 hardcoded constants per spec. +// DefaultCandidateSourceLimits returns the hardcoded per-source limits. func DefaultCandidateSourceLimits() CandidateSourceLimits { return CandidateSourceLimits{ LBSimilar: 30, diff --git a/internal/recommendation/similarity.go b/internal/recommendation/similarity.go index b327ade0..f4505a0c 100644 --- a/internal/recommendation/similarity.go +++ b/internal/recommendation/similarity.go @@ -1,8 +1,7 @@ package recommendation // SimilarityWeights balances the per-axis contribution to the weighted Jaccard -// score. v1 hardcodes the defaults — operators cannot tune via YAML. If -// telemetry justifies it, expose under recommendation.similarity.* later. +// score. The defaults are hardcoded; there is no config key for them. type SimilarityWeights struct { TagsWeight float64 ArtistsWeight float64 diff --git a/internal/subsonic/types.go b/internal/subsonic/types.go index bbbc8f34..8775ff68 100644 --- a/internal/subsonic/types.go +++ b/internal/subsonic/types.go @@ -48,8 +48,8 @@ func parseUUID(s string) (pgtype.UUID, bool) { return u, u.Valid } -// MusicFolder matches Subsonic's /rest/getMusicFolders. v1 always reports a -// single folder because Minstrel has no multi-library concept yet. +// MusicFolder matches Subsonic's /rest/getMusicFolders. Minstrel always +// reports a single folder: it has no multi-library concept. type MusicFolder struct { XMLName xml.Name `json:"-" xml:"musicFolder"` ID int `json:"id" xml:"id,attr"` diff --git a/internal/tags/provider_test.go b/internal/tags/provider_test.go index fec124e8..aa6dd2ba 100644 --- a/internal/tags/provider_test.go +++ b/internal/tags/provider_test.go @@ -50,7 +50,7 @@ func TestRegisterDuplicatePanics(t *testing.T) { Register(&fakeProvider{id: "dup"}) } -// TestBuiltinProvidersRegister confirms the two v1 sources register with +// TestBuiltinProvidersRegister confirms the two built-in sources register with // the expected identities/defaults. Runs against a fresh registry so it is // independent of test ordering: re-register constructed instances. func TestBuiltinProvidersRegister(t *testing.T) { diff --git a/web/src/lib/api/browse.ts b/web/src/lib/api/browse.ts index 70e5ff13..b4e0fb00 100644 --- a/web/src/lib/api/browse.ts +++ b/web/src/lib/api/browse.ts @@ -7,8 +7,8 @@ export const BROWSE_PAGE_SIZE = 50; // Genres are the raw ID3 strings, split on [;,] server-side but otherwise // untouched — no case folding, no synonym mapping. So "Rock" and "rock" can -// both appear, as can "Rock/Pop" beside "Rock" and "Pop". Deliberate for v1: -// the raw spread has to be visible before anyone can judge whether it needs +// both appear, as can "Rock/Pop" beside "Rock" and "Pop". Deliberate: the +// raw spread has to be visible before anyone can judge whether it needs // normalising. export type GenreCount = { genre: string; track_count: number }; diff --git a/web/src/lib/components/SuggestionFeed.svelte b/web/src/lib/components/SuggestionFeed.svelte index e50439f1..5f00ee18 100644 --- a/web/src/lib/components/SuggestionFeed.svelte +++ b/web/src/lib/components/SuggestionFeed.svelte @@ -101,7 +101,7 @@ // The server-side filter hides this candidate on next refetch. await client.invalidateQueries({ queryKey: qk.suggestions() }); } catch { - // Swallow for v1; the SPA will refetch on next mount and the card + // Swallowed: the SPA will refetch on next mount and the card // stays requestable so the user can retry. } } diff --git a/web/src/lib/player/events.svelte.ts b/web/src/lib/player/events.svelte.ts index 99745b80..b35a4d33 100644 --- a/web/src/lib/player/events.svelte.ts +++ b/web/src/lib/player/events.svelte.ts @@ -133,7 +133,7 @@ export function useEventsDispatcher(): void { openTrackId = trackId; } } catch { - // Best-effort; missed events are OK in v1. + // Best-effort; a missed event is acceptable. } } } diff --git a/web/src/lib/player/store.test.ts b/web/src/lib/player/store.test.ts index 3984fe4f..6f125057 100644 --- a/web/src/lib/player/store.test.ts +++ b/web/src/lib/player/store.test.ts @@ -79,7 +79,7 @@ describe('player store — basic actions', () => { // play anyway — tested via report later. Here, simulate the paused state: reportTimeUpdate(0); // manually put us in paused state by calling togglePlay twice isn't clean; - // set via the state-report API in Task 2. Instead, test the simpler case: + // it is set via the state-report API. Instead, test the simpler case: // playQueue then togglePlay = still 'loading' (intent is to play). togglePlay(); // from 'loading' — inverts intent; store moves to 'paused' intent expect(player.state).toBe('paused'); diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index 18f7ab8c..e87d01a0 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -77,7 +77,7 @@ } }); - // Phase 2 prefetch: when the current track passes the halfway mark, + // Prefetch: when the current track passes the halfway mark, // start loading the next track's bytes into a hidden