A locked screen drops the radio, changes network or dozes, and one
request fails. Both halves of an advance treated that as the session's
fault. The outbox kept the failed event at its head with the comment
that a later retry would pick it up, but nothing ever triggered one, so
it sat there while the caller was rejected. advanceVibe then cleared the
prefetched future and paused, destroying a plan that was still valid.
Transient failures now hold the outbox entry unsettled and resend the
same event id on a backoff, so no duplicate feedback reaches the
director. The retry around the serve sits on the serve alone: serving a
version is idempotent, while replaying the whole advance would report a
second outcome for a track heard once. Each wait ends early when the
browser says the network is back, which is the moment that matters when
a screen unlocks. A drop that outlives every retry leaves the future
intact to carry on from.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A pass over the whole app against the Ethos laws, then a focused pass on
Vibe with the operator reviewing each change.
Across the app:
- The player bar restores the last track it played, paused at zero, so a
fresh tab opens on where the listener was instead of "nothing playing".
- Track titles link to their album, matching the artist links beside them.
Playback stays on the artwork tile; a title that played was the surprise.
- The search field is bg-bg2. Tailwind cannot alpha-modify these var()
colors, so bg-surface0/70 emitted no rule at all and the input fell back
to the UA's white.
- Row hover is light falling off to the right, not a flat slab.
- The artwork placeholder can drop its note glyph, so TrackRow no longer
layers a play icon on top of one.
Vibe:
- A seeded Vibe plays its seed first. The seed sits in front of the durable
plan without being part of it, so the first advance consumes it locally
and reports no plan feedback.
- The queue drops a second recording of a song it already holds — same
title, different track id, which id-based dedup let through.
- Up next is read from the queue rather than the plan preview, since the
seed is not a plan item.
- The header carries the live profile (energy, discovery, goal) and both
verbs. Keep is gone: letting a track finish already reports `completed`,
which the director weighs the same.
- The aura is one warm diffuse blob in the page background, warm-hued only
and quieter on mobile.
- Compact artwork is 32px. It was h-8 w-8, which this remapped spacing
scale renders as 64px inside a 44px row, and that overflow was the
"stacked" look.
Verified by render at 1440x900 and 390x844, no horizontal overflow at
either. 26 frontend and 122 backend tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>