{pageTitle('Tuning')}

Recommendation tuning

The defaults-discovery lab. Changes apply live — radio on the next request, daily mixes on the next rebuild — and every change is recorded so the metrics page can tie outcome shifts to knob turns. Found-good values get baked into shipped defaults; a dot marks knobs that currently deviate from them.

{#if loadFailed}

Couldn't load tuning settings.

{:else if !snapshot}

Loading…

{:else}
{#each profileScopes as p (p.scope)}

{p.label}

{p.blurb}

{#each weightFields as f (f.key)}
{/each}
{/each}

Taste profile build

How plays become the learned taste profile: the influence half-life and the completion→engagement curve (must stay ordered: hard-skip < neutral < full).

{#each tasteFields as f (f.key)}
{/each}

Discover requests

How the Discover suggestion deck ranks out-of-library artists. Tag coverage for artists you don't own is partial by nature, so an untagged candidate keeps its similarity score rather than being pushed down.

{#each discoverFields as f (f.key)}
{/each}
{/if}

Weekly trends

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. The skip and completion columns show the most recent week alone, 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.

{#if trendsFailed}

Couldn't load trends.

{:else if !trends}

Loading…

{:else if trends.series.length === 0}

No plays recorded yet — trends appear once listening accumulates.

{:else} {#each trends.series as s (s.key)} {/each}
Surface Skip rate by week Plays (window) Skip (last wk) Completion (last wk) Taste hit (window)
{s.label} {#each trends.markers as m, i (i)} {markerSummary(m)} {/each} {#if s.points.length > 1} {:else if s.points.length === 1} {/if} {s.plays} {pct(latest(s).skip)} /{latest(s).plays} {pct(latest(s).completion)} {pct(windowTasteHitRate(s))}
{#if trends.markers.length > 0}

Tuning changes in this window

    {#each trends.markers as m, i (i)}
  • {markerSummary(m)}
  • {/each}
{/if} {/if}