Recommendation metrics: publish the margin of error on every delta #122

Merged
bvandeusen merged 4 commits from dev into main 2026-08-06 21:50:42 -04:00
2 changed files with 8 additions and 6 deletions
Showing only changes of commit 96abb48086 - Show all commits
+3 -4
View File
@@ -428,13 +428,12 @@
<div>
<h2 class="text-lg font-semibold">Weekly trends</h2>
<p class="text-xs text-text-secondary">
<span class="font-medium">Skip and completion are the most recent week only</span>
the number after the skip rate is that week's play count, so a rate off a
handful of plays reads as what it is. Plays and Taste hit cover the whole
window.
Skip rate per surface over the last {trends?.weeks ?? 12} weeks (lower is better; all
users aggregated, rates only). Dashed ticks mark tuning changes. Taste hit is the share
of plays whose artist fits the current taste profile.
<span class="font-medium">The skip and completion columns show the most recent week
alone</span>, not the whole window — the figure after the skip rate is that week's
play count, so a rate drawn from a handful of listens reads as what it is.
</p>
</div>
{#if trendsFailed}
+5 -2
View File
@@ -210,8 +210,11 @@ describe('Admin tuning page', () => {
// The window/last-week distinction has to be visible in the headers, or the
// Plays total reads as the denominator of the skip rate. That misreading is
// what #2495 was filed over.
expect(screen.getByText(/Plays/)).toHaveTextContent('(window)');
expect(screen.getByText(/^Skip/)).toHaveTextContent('(last wk)');
//
// Queried as column headers rather than by text: the caption below also
// mentions "Plays", and matching on the word finds the prose too.
expect(screen.getByRole('columnheader', { name: /Plays/ })).toHaveTextContent('(window)');
expect(screen.getByRole('columnheader', { name: /^Skip/ })).toHaveTextContent('(last wk)');
// The knob turn is listed under the chart AND tooltipped on each
// sparkline's marker tick, hence getAllBy.
expect(