Files
jellytau/docs/specs/README.md
T
dtourolle 1d56517f07
Traceability Validation / Check Requirement Traces (pull_request) Successful in 11s
docs(specs): add backend-owned stream selection
Rust becomes the single owner of which stream to play — direct play or
transcode, at what ceiling, over what transport — and hands every player
backend a self-describing StreamSelection instead of a bare URL. mpv,
ExoPlayer and the HTML5/hls.js path all consume one decision rather than
three places re-deriving it.

The motivating leak is concrete. VideoPlayer.svelte determines transport with
`currentStreamUrl.includes(".m3u8")`, in two places, for a URL Rust
constructed and therefore already knows the shape of. That is the boundary
rule in miniature: not item-type taxonomy, but the same error of
reconstructing a domain fact in the presentation layer because the wire shape
did not carry it. A tagged Transport enum deletes it.

The design line, which ExoPlayer forces: Rust decides *what stream*, the
player decides *how to deliver it*. ExoPlayer has genuine adaptive track
selection; this spec must not reimplement or fight it. Rust only adapts where
the player cannot (mpv) and the server actually offers a ladder.

Six phases, and phase 1 stands alone as pure ownership movement with no
behaviour change. Phase 4 (direct-play negotiation) is what removes the
transcode and unblocks the Linux native-video work. Phase 5 (adaptation) is
gated on counting EXT-X-STREAM-INF entries in a real playlist — the
acceptance criteria require that count be recorded before it is either
started or dropped.

Takes DR-121 from read-through-media-cache.md, which specced Rust-owned
quality reporting but never built it; that spec keeps its capture half.
2026-08-21 19:41:32 +02:00

82 lines
5.6 KiB
Markdown

# Specs index
Feature specs for JellyTau. Start a new one from
[SPEC-TEMPLATE.md](SPEC-TEMPLATE.md) and run it past
[SPEC-REVIEW-CHECKLIST.md](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/](../architecture/README.md). 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](../requirements.md) before allocating): **UR-079**,
**IR-033**, **DR-219**. 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](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](libmpv2-migration.md) | `LICENSE` | The `libmpv``libmpv2` crate swap |
| [read-through-media-cache.md](read-through-media-cache.md) | DR-126…128, DR-133…138 — cache entries *are* download rows; local playback of downloads | DR-121/122/124/125 — the player quality selector and the read-through capture |
| [scoped-search-boundary-implementation.md](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 |
|---|---|
| [backend-owned-stream-selection.md](backend-owned-stream-selection.md) | Rust owns direct-play-vs-transcode, transport and quality; players consume one `StreamSelection`. Phase 1 (delete the `.m3u8` sniff) stands alone. Unblocks Linux native video. |
| [build-provenance.md](build-provenance.md) | `build.rs` is still bare. ⚠️ suggested id DR-093 is taken. |
| [player-facade-enforcement.md](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](windows-native-audio-backend.md) | Blocked on the libmpv2 swap. ⚠️ suggested id IR-030 is taken. |
| [linux-native-video-spike.md](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. Needs an implementation spec that answers adaptive bitrate. |
## Design authority
| Spec | Role |
|---|---|
| [playback-backend-unification.md](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](scoped-search-boundary.md) | The boundary design the `check:boundary` rule came from. Stage 1 built. |
| [scoped-search.md](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](../architecture/02-svelte-frontend.md) — App Shell and Chrome |
| Library mosaic | [02-svelte-frontend.md](../architecture/02-svelte-frontend.md) — Library Mosaic |
| Series current-episode navigation | [02-svelte-frontend.md](../architecture/02-svelte-frontend.md) — Series and Episode Navigation |
| Downloads as an offline library | [02-svelte-frontend.md](../architecture/02-svelte-frontend.md) — Downloaded Browse |
| Favourites browsing | [01-rust-backend.md](../architecture/01-rust-backend.md) — Favorites System |
| Streaming bitrate cap | [01-rust-backend.md](../architecture/01-rust-backend.md) — Streaming quality ladder |
| Locally-indexed search | [03-data-flow.md](../architecture/03-data-flow.md) — Search Flow; [01-rust-backend.md](../architecture/01-rust-backend.md) — Background workers |
| Offline downloaded-only filter | [06-downloads-and-offline.md](../architecture/06-downloads-and-offline.md) — Offline Catalog Visibility |
| Audio equalizer · Android audio settings parity | [05-platform-backends.md](../architecture/05-platform-backends.md) — Audio settings on ExoPlayer |
| Android native video spike | [05-platform-backends.md](../architecture/05-platform-backends.md) — Native Video Compositing |
| Video background audio | [05-platform-backends.md](../architecture/05-platform-backends.md) — Background Audio Handoff |
| Traceability gate repair | [traceability-ci.md](../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 |