diff --git a/.zscripts/dev.pid b/.zscripts/dev.pid
index 6e64a91..1e3b283 100755
--- a/.zscripts/dev.pid
+++ b/.zscripts/dev.pid
@@ -1 +1 @@
-1173
+1195
diff --git a/agent-ctx/2-a-music-services-framework.md b/agent-ctx/2-a-music-services-framework.md
new file mode 100755
index 0000000..c5c2eb1
--- /dev/null
+++ b/agent-ctx/2-a-music-services-framework.md
@@ -0,0 +1,105 @@
+# Task 2-a — v6.7 part A (server): resolve anti-spam semaphore + music-service framework
+
+Task ID: 2-a
+Agent: full-stack-developer
+Status: COMPLETE — lint clean, tsc clean on all four files, verified live
+against the dev server (curl) and at the process level (ps snapshots).
+
+## Scope (ONLY these files — nothing else touched)
+
+1. `src/lib/music-services.ts` (modified)
+2. `src/lib/server/music-providers.ts` (NEW)
+3. `src/app/api/resolve/route.ts` (modified)
+4. `src/components/ava/settings-tab.tsx` (modified — Music services chips only)
+
+## What was built
+
+### 1. `src/lib/music-services.ts`
+- `export type StreamStatus = 'live' | 'coming-soon'`
+- `ServiceDef` gained required `streamStatus: StreamStatus` + optional
+ `comingSoonNote?: string` (required when coming-soon).
+- youtube / soundcloud → `'live'`; spotify / apple → `'coming-soon'` with
+ notes like: "Spotify playback is coming in a later update — your saved
+ Spotify login will be used automatically the moment it ships. Meanwhile,
+ YouTube, SoundCloud and direct-file links work today."
+- All pre-existing fields/exports intact (`SERVICES`, `serviceDef`,
+ `serviceForUrl`, `isServiceId`, `ServiceId`).
+
+### 2. `src/lib/server/music-providers.ts` — exact exports
+```ts
+export type ProviderStatus = 'live' | 'coming-soon'
+
+export interface ProviderAdapter {
+ id: ServiceId | 'generic'
+ label: string
+ status: ProviderStatus
+ comingSoonNote: string
+ handlesUrl(url: string): boolean
+ // commented v6.8+ extension points:
+ // resolveTrack?(url, auth) / listPlaylist?(url, auth)
+}
+
+export const YTDLP_PROVIDER: ProviderAdapter // id 'generic', live, handlesUrl → true
+export const SPOTIFY_PROVIDER: ProviderAdapter // id 'spotify', coming-soon
+export const APPLE_PROVIDER: ProviderAdapter // id 'apple', coming-soon
+export function providerForUrl(url: string): ProviderAdapter
+```
+- Domain matching mirrors `serviceForUrl` (host/subdomain, "www." ignored)
+ scoped to the one service.
+- `providerForUrl` is status-agnostic: flip an adapter to 'live' and it
+ still owns its URLs at the route's dispatch point.
+- Big "HOW TO SHIP A NEW SERVICE (v6.8+)" header comment: 3-step recipe
+ (implement resolveTrack/listPlaylist with the exact payload shapes →
+ flip streamStatus in music-services.ts + status here → extend the marked
+ dispatch spot in the route).
+
+### 3. `src/app/api/resolve/route.ts`
+- **Coming-soon dispatch** right after `assertPublicHttpUrl`, BEFORE
+ cache/direct-audio/yt-dlp:
+ `{ ok: false, code: 'coming-soon', service: provider.id, error: provider.comingSoonNote }` (422).
+ Spotify/Apple links never spawn yt-dlp. Generic "That site is not
+ supported" 422 kept but without the DRM parenthetical.
+- **Semaphore**: `YTDLP_MAX_CONCURRENCY = 2`, `YTDLP_QUEUE_TIMEOUT_MS = 40_000`,
+ class `YtdlpSemaphore` on globalThis (`__avaYtdlpSemaphore`). FIFO
+ waiters, direct slot handoff in `release()` (active count unchanged).
+ Acquire wrapped around `runYtDlp` with a `held` flag → release exactly
+ once in the finally; busy → 503 "The resolver is busy right now — try
+ again in a moment."; timed-out waiter that was granted a slot in the same
+ tick does NOT double-release (queue membership is the single source of
+ truth). Cache hits + direct-file links bypass the gate.
+- Fixed a pre-existing strict-type bug in `buildCookieParts`
+ (`pairs: string[]` receiving `[string,string]` tuples → now
+ `[string, string][]`; no runtime change).
+
+### 4. `src/components/ava/settings-tab.tsx`
+- Coming-soon service chips get an amber "soon" badge:
+ `soon`
+ (placed between name and the check/— marker). Nothing else changed;
+ login buttons fully functional for coming-soon services.
+
+## Verification
+- `bun run lint` clean; `bunx tsc --noEmit` clean for all four files.
+- Live: spotify track/playlist + apple album → 422 coming-soon in ~6ms
+ (zero yt-dlp); SSRF gate still first (localhost → 400); direct MP3 → 200;
+ spotify+cookies → coming-soon before cookie staging; real YouTube resolve
+ still passes through (bot-wall 422 as before).
+- End-to-end anti-spam: 6 concurrent resolves of the same YouTube link —
+ ps snapshots show ≤2 top-level `bin/yt-dlp` processes at any moment
+ (extra PIDs = the onefile binary's own self-exec children, not extra
+ extractions); FIFO waves of 2; zero 503s; dev.log error-free.
+- Scratch semaphore tests (cap/FIFO/timeout/handoff/no-leak) all pass;
+ scratch dir deleted.
+
+## Notes for the lead agent
+- **apple.com is broad**: the apple ServiceDef domains include `apple.com`,
+ so ALL apple.com links (e.g. podcasts.apple.com, which yt-dlp's
+ ApplePodcasts extractor could handle) now get the Apple Music coming-soon
+ answer. Consistent with client-side matching; say the word to scope the
+ adapter to music.apple.com only.
+- Worklog has no v6.6 section (the v6.6 music-login files were committed
+ inside the v6.5 commit 8fa0eb9); my entry follows v6.5 directly.
+- Not-mine tsc errors (untouched): examples/websocket/* (missing deps),
+ api/rust-scaffold (Uint8Array vs BodyInit), ava/audio-source.ts ('never'
+ narrowing — the concurrent client agent's WIP).
+- Did NOT commit; did NOT touch version.ts / page.tsx / audio.ts / queue
+ files / link-dialog / audio-source / queue-bar.
diff --git a/bin/deno b/bin/deno
new file mode 100755
index 0000000..09ccfb7
Binary files /dev/null and b/bin/deno differ
diff --git a/bin/yt-dlp b/bin/yt-dlp
index a385dc1..83a0d2c 100755
Binary files a/bin/yt-dlp and b/bin/yt-dlp differ
diff --git a/db/custom.db b/db/custom.db
index aed7f07..f498a50 100755
Binary files a/db/custom.db and b/db/custom.db differ
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
new file mode 100755
index 0000000..802a6f1
Binary files /dev/null and b/public/apple-touch-icon.png differ
diff --git a/public/demo-track.mp3 b/public/demo-track.mp3
new file mode 100755
index 0000000..dd14078
Binary files /dev/null and b/public/demo-track.mp3 differ
diff --git a/public/favicon-16.png b/public/favicon-16.png
new file mode 100755
index 0000000..de81975
Binary files /dev/null and b/public/favicon-16.png differ
diff --git a/public/favicon-32.png b/public/favicon-32.png
new file mode 100755
index 0000000..ea6148a
Binary files /dev/null and b/public/favicon-32.png differ
diff --git a/public/logo.svg b/public/logo.svg
index d93ac8f..00e6cb3 100755
--- a/public/logo.svg
+++ b/public/logo.svg
@@ -1,29 +1,12 @@
-
-