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> <div>
<h2 class="text-lg font-semibold">Weekly trends</h2> <h2 class="text-lg font-semibold">Weekly trends</h2>
<p class="text-xs text-text-secondary"> <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 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 users aggregated, rates only). Dashed ticks mark tuning changes. Taste hit is the share
of plays whose artist fits the current taste profile. 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> </p>
</div> </div>
{#if trendsFailed} {#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 // 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 // Plays total reads as the denominator of the skip rate. That misreading is
// what #2495 was filed over. // 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 // The knob turn is listed under the chart AND tooltipped on each
// sparkline's marker tick, hence getAllBy. // sparkline's marker tick, hence getAllBy.
expect( expect(