Decision 1 keeps the unmodified single-key bindings, and Settings was
the only place they were written down — three of the four categories of
them, because config-page listed the categories by hand, so the autotag
keys were written down nowhere at all. `?` now opens an overlay from
anywhere the app owns the keyboard, and both surfaces read one table
(services/shortcut-meta.ts, moved out of config-page's private static).
The other half is the same explanation from the other side. Phase 1
gave the arrow keys to the grid, correctly — but all six of them, and
no list in this app moves horizontally: track-list's own handler and
utils/roving-rows both take Up/Down/Home/End and ignore Left/Right. So
seeking stopped working from a focused row and nothing gained the keys.
Reproduced in the running app: two ArrowRights on a focused track row,
zero Player.Seek calls, against one per press from the body.
A shifted character no longer reports Shift, so the binding is `?` and
not `Shift+?` — the character already carries the shift, and a layout
where it does not is a layout where "Shift+?" is wrong anyway.
The app opened on Tracks — an alphabetical list of everything, which is
the one entry point that is identical every time and therefore gives the
user nothing to start from. Home is listed first in the nav and is the
page built to answer 'what should I play' (H-8).
Two things had to be true before that was an improvement.
An album with no cover rendered as a small dim icon on a surface the
same colour as the page, so a shelf read as having holes in it, while
the Albums and Artists grids both drew a letter tile (H-9). It draws the
same tile now.
And a shelf that repeats the one above it is suppressed, the way an
empty one already is — 'On repeat' was 'Pick up where you left off'
reordered. The rule fires only when the shelf is not showing the whole
library: a repeat is a fault only if a different row was possible, and
measured against a fixed shelf size instead this let an 11-album library
keep three identical shelves while a 13-album one lost them.
The first two versions of that rule were wrong and the *existing* Go
tests caught both — it collapsed a four-album library to a single shelf.
Nine e2e specs assumed the app starts on Tracks and now navigate there,
and one new spec freezes the landing itself. Home's page-header action
is 'Shuffle suggestions': 'Shuffle' alone was two different controls
with one accessible name, which only became reachable together once a
cached Home was always in the tree.
Each was written first and watched fail first:
- `view-lifecycle` — pressing `s` on Settings must not skip an album
out of the Autotag queue, and on Autotag the same key must not also
toggle shuffle.
- `player-truth` — the elapsed clock tracks the backend through steady
playback and four keyboard seeks (the measurement that failed by
30 s), a finished queue keeps the track on the bar at 0:00, and
auto-advance skips a missing file and reaches the next track.
- `offline-icons` — blocks every non-local request and asserts on the
<svg> *inside* each icon's shadow root, since asserting the element
exists would have passed before the fix too. Verified red: 24 empty
icons.
- `failure-voice` — induces a real binding failure through /__test/sql
and asserts a sentence appears. Its first version renamed the decoy
library to its own name, which the backend accepts: it failed at the
right assertion while never inducing the failure, so it now picks the
row by the seeded library's name from /__test/health.
- `play-count` — a finished track does not refetch the library.
The queue spec now opens the panel before asserting on its rows and
waits for it to close again: the panel's width is animated and the
transport slides with it, so a click issued during the close lands on
whichever button moved under the pointer.