The spike proved compositing works on Linux, including Wayland, and left two blockers. One is now closed: DR-228 measured a single EXT-X-STREAM-INF in the server's master playlist, so there is no adaptive bitrate for mpv to lose and finding 3 of playback-backend-unification.md is false. The spike is updated to record that. The other — an unexplained SIGSEGV in a decoder thread — is carried into the spec as DR-231 rather than chased: the spike had no render-context teardown at all, which is DR-184 on Android restated, and removing the likeliest cause is worth doing whether or not it was the cause. The spec targets every desktop platform rather than Linux alone, because the maintenance argument runs the other way. Video has three renderers today. A Linux-only version makes it four, permanently — mpv on Linux, HTML5 on Windows, ExoPlayer on Android, hls.js underneath — and the webview path then survives indefinitely because something still needs it. Finishing the job leaves mpv on desktop and ExoPlayer on Android, and hls.js, html5Adapter.ts, videoLoaderFor and the <video> element are deleted in a phase that has its own acceptance criterion so it cannot quietly become "later". The load-bearing change is DR-233: the device profile stops being a compile-time platform constant and becomes a property of the renderer that will decode the stream. The measured 7% desktop direct-play rate and Android's 85% differ by nothing except which component decodes, so that one change is what converts the former toward the latter. It looks like configuration and is not — it decides whether the server re-encodes, and it fails silently when wrong. Windows is costed rather than waved at: the surface is genuinely different code (WebView2 in an HWND, not GTK), but everything else is shared, so nothing may be guarded on cfg!(target_os = "linux"). The real cost is build — libmpv is a Linux-only dependency while Windows cross-compiles via cargo-xwin, so a Windows libmpv must reach that build and ship in the NSIS bundle under the LGPL terms DR-216 already records. Allocates UR-080, DR-230..236, IR-033. No product code yet.
Specs index
Feature specs for JellyTau. Start a new one from SPEC-TEMPLATE.md and run it past SPEC-REVIEW-CHECKLIST.md before accepting it.
What lives here
Only work that has not shipped. Once a spec is fully implemented its design is folded into the architecture docs — which are the maintained description of the build — and the spec file is deleted. Git history keeps the original, including its rejected alternatives and acceptance criteria; the architecture docs keep the reasoning that a future change still needs.
So: a file in this directory is a promise, not a description. If you want to know how something works, read docs/architecture/. If you want to know what is planned, read here.
Status vocabulary
| Status | Meaning |
|---|---|
| Proposed | Written, not accepted. Nothing built. |
| Accepted | Agreed as the design; implementation not started or not finished. |
| Partially implemented | Some parts shipped; the spec names what is left. |
| Design authority | No code of its own — it records a decision later specs act on. |
Next free requirement ids (always re-check requirements.md before allocating): UR-079, IR-033, DR-231. Three specs below suggested ids that have since been taken by other work; each carries a ⚠️ note at the top.
Partially implemented
| Spec | What landed | What is left |
|---|---|---|
| frontend-domain-model.md | Catalog surface: MediaKind, from_jellyfin isolated, ticks → ms |
primaryImageTag → imageId (~30 sites); player/session/reporting tick math; stream.type |
| libmpv2-migration.md | LICENSE |
The libmpv → libmpv2 crate swap |
| read-through-media-cache.md | DR-126…128, DR-133…138 — cache entries are download rows; local playback of downloads | DR-122/124/125 — the read-through capture. DR-121 shipped as backend-owned stream selection and left this spec |
| scoped-search-boundary-implementation.md | Stage 1: SearchScope owned by Rust (DR-063…067) |
Stage 2: result-side grouping (GROUP_ITEM_TYPES still in searchScope.ts) |
Not started
| Spec | Blocked on / note |
|---|---|
| desktop-native-video.md | mpv draws video on every desktop platform, then the webview <video> path and hls.js are deleted. Converts a measured 7% direct-play rate toward Android's 85%. Stacked on backend-owned stream selection. |
| build-provenance.md | build.rs is still bare. ⚠️ suggested id DR-093 is taken. |
| player-facade-enforcement.md | ~60 commands.player* sites still outside the facade; no lint rule. ⚠️ suggested id DR-095 is taken. |
| windows-native-audio-backend.md | Blocked on the libmpv2 swap. ⚠️ suggested id IR-030 is taken. |
| linux-native-video-spike.md | Spike run 2026-08-21: compositing works on Linux, X11 and Wayland. G1-G6 green bar the Tauri default_vbox() half of G1. The adaptive-bitrate question it was waiting on is answered: the server publishes one EXT-X-STREAM-INF, so there is no ladder for mpv to lose (DR-228). StreamSelection (DR-224) is the contract to consume. |
Design authority
| Spec | Role |
|---|---|
| playback-backend-unification.md | Why video cannot unify onto one native engine and audio can. The audio half has since shipped on Android; Windows has not. |
| scoped-search-boundary.md | The boundary design the check:boundary rule came from. Stage 1 built. |
| scoped-search.md | Superseded in part — its "frontend only, no Rust changes" decision is the leak the boundary spec reversed. UX still current. |
Where the shipped specs went
Sixteen specs were folded into the architecture docs and deleted (2026-08-21). Where to look for each:
| Shipped work | Now documented in |
|---|---|
| Account menu & global chrome | 02-svelte-frontend.md — App Shell and Chrome |
| Library mosaic | 02-svelte-frontend.md — Library Mosaic |
| Series current-episode navigation | 02-svelte-frontend.md — Series and Episode Navigation |
| Downloads as an offline library | 02-svelte-frontend.md — Downloaded Browse |
| Favourites browsing | 01-rust-backend.md — Favorites System |
| Streaming bitrate cap | 01-rust-backend.md — Streaming quality ladder |
| Locally-indexed search | 03-data-flow.md — Search Flow; 01-rust-backend.md — Background workers |
| Offline downloaded-only filter | 06-downloads-and-offline.md — Offline Catalog Visibility |
| Audio equalizer · Android audio settings parity | 05-platform-backends.md — Audio settings on ExoPlayer |
| Android native video spike | 05-platform-backends.md — Native Video Compositing |
| Video background audio | 05-platform-backends.md — Background Audio Handoff |
| Traceability gate repair | traceability-ci.md |
| Boundary tripwire hardening | scripts/check-frontend-boundary.sh (its header is the spec) |
| Playback docs corrections · req-coverage script removal | Nothing to document — both were corrections that have been applied |