Per the owner's testing bar: a Playwright spec registers an admin,
seeds one fixture per write-capable type (EPUB, PDF, CBZ, MP3, FLAC,
M4A, M4B — generated at runtime, no binary media in git), drives the
REAL metadata-editor flow (Edit → change title → in-app dialog →
Save & write) for each, and then reads every artifact back
INDEPENDENTLY of the app — EPUB/CBZ/sidecar via python zip+XML parse,
audio via ffprobe — asserting the written title landed in the FILE and
the old one is gone.
Writing the e2e exposed a real bug: atomicWrite left server-written
sidecars at 0600 root (os.CreateTemp's default), so host-side tools
sharing the volume — Calibre reading metadata.opf — were locked out.
The temp file is now chmod'd 0644 before the rename, matching the
scanner's cover-file convention; the e2e's host-side reads prove it.
Toolbar feedback round: the series search box now matches whatever the
main search matches for a group — series NAME, any book's AUTHOR, and
any book's TITLE inside the series (WHERE EXISTS per group-row, so
counts stay true); the separate author input is gone from the toolbar
(the author= param stays live for the JSON API and deep links). The
sort control becomes a base-key select (Date added/Name/Author/Books/
Progress/Last read) plus a chevron direction toggle that flips and
resubmits; sort/dir compose through ResolveSeriesSort (full registry
keys keep working for back-compat, unknown base keys fall to recent).
The search/apply button moved next to the search box as requested, and
default URLs stay clean (sort/dir only emitted once the user chooses).