Chore/infra hardening #15

Merged
dtourolle merged 3 commits from chore/infra-hardening into master 2026-08-21 17:44:48 +00:00
Owner

What and why

How it was verified

Checklist

  • bun run check, bun run test, bun run format:check, bun run lint
  • cargo fmt, cargo clippy --all-targets -- -D warnings, cargo test
  • bun run check:boundary — no Jellyfin taxonomy in the frontend
  • New requirement-implementing code carries a TRACES: comment, and every
    ID it names exists in docs/requirements.md (bun run traces:validate)
  • Bug fix: a test that reproduces it was written first and observed
    failing before the fix
  • Android source edits were made in src-tauri/android/src and synced with
    scripts/sync-android-sources.sh (never edit gen/ directly)
## What and why <!-- What changes, and the reason. The diff shows the what; the why is what the commit log is for. --> ## How it was verified <!-- What you actually ran or clicked. "Tests pass" on its own says little; "played a transcoded episode on Android, seeked twice, backgrounded it" says a lot. --> ## Checklist - [x] `bun run check`, `bun run test`, `bun run format:check`, `bun run lint` - [x] `cargo fmt`, `cargo clippy --all-targets -- -D warnings`, `cargo test` - [x] `bun run check:boundary` — no Jellyfin taxonomy in the frontend - [x] New requirement-implementing code carries a `TRACES:` comment, and every ID it names exists in `docs/requirements.md` (`bun run traces:validate`) - [x] **Bug fix:** a test that reproduces it was written *first* and observed failing before the fix - [x] Android source edits were made in `src-tauri/android/src` and synced with `scripts/sync-android-sources.sh` (never edit `gen/` directly)
dtourolle added 2 commits 2026-08-21 17:44:19 +00:00
Three corrections to the Linux native-video spike, each of which reverses
something recorded earlier in the same session:

- The crash is unexplained. It was first blamed on hwdec=auto-safe's Vulkan
  failures, on a misreading of the logs — those are two per run at start-up,
  not per-frame, and every clean run has the same two. A 300s soak on
  auto-safe survived. So did 240s of automated fullscreen toggling (~120
  transitions) and 240s of continuous resizing (~2000 reallocations). Three
  hypotheses, none reproduced. Recorded rather than dismissed: an
  intermittent fault nobody can reproduce is worse to inherit than a
  deterministic one.

- G5 drops to amber. It looked and felt smooth, but the only SIGSEGV observed
  came from the only session in which fullscreen was exercised, and the spike
  has no lifecycle handling at all — it never frees the render context. An
  implementation must bind that to the GL context's lifetime regardless of
  what caused this crash, because Android already paid for that lesson as
  DR-184.

- Finding 3's premise is in doubt. "The webview path already has real ABR via
  hls.js" was never checked against the URLs this app builds:
  get_video_stream_url requests a single rendition, the frontend has no
  level-handling code at all, and a quality switch is implemented by
  re-opening the stream. If the playlist is single-variant there is no
  adaptation to lose. The decisive test needs a live server and is recorded
  as unrun.

Also records hardware decode working through the render API (nvdec-copy
engaged), and that hwdec=vaapi silently fell back to software on this box.
docs(specs): add backend-owned stream selection
Traceability Validation / Check Requirement Traces (pull_request) Successful in 11s
1d56517f07
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.
dtourolle added 1 commit 2026-08-21 17:44:29 +00:00
Merge branch 'master' into chore/infra-hardening
Traceability Validation / Check Requirement Traces (pull_request) Successful in 11s
2e3a864ef0
dtourolle merged commit cac9afa6bd into master 2026-08-21 17:44:48 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dtourolle/jellytau#15