Method & data

This dashboard shows saved results from the Spotify review-analysis pipeline. The pipeline is in the GitHub repository.

  1. Ingest (code): every row is hashed, empty texts are quarantined, and identical texts are classified once. The final run classifies a seeded random sample of 100,000 of the 660,622 rows; the other rows are counted as out of scope (they are not stored here, so looking one up by ID finds nothing).
  2. Enrich: Jev (jev-1.13.0) picks topic, intent, severity and sentiment. Texts where Jev is unsure (confidence below 0.5) are re-labelled blind by Claude under a declared 20% cap: claude-haiku-4-5 through the Batch API in the final run (17.2% of texts), claude-sonnet-5 in the development runs. Evidence quotes are exact substrings checked by code.
  3. Verify: claude-sonnet-5 blind-labels a declared random sample (1,000 reviews in the final run), and code compares the results.
  4. Group: Claude proposes subtopics from a sample of complaint quotes, and Jev assigns each complaint to one issue.
  5. Rank (code): priority = complaint count × mean severity = severity sum.
  6. Recommend: Claude writes the memo from the aggregates only. Code checks every number, ID and quote.

Architecture of this site: the pipeline publishes a finished run into Neon Postgres (python -m pipeline publish). This app's API routes (/api/*) read it with a SELECT-only role and serve JSON to these pages. Viewing the dashboard never calls a model.

Limits: these are self-selected, historical Play Store reviews. There is no revenue, plan or confirmed-churn data, and cancellation intent is not churn. Verifier agreement is between two models, not accuracy; it is lower on the hard texts the fallback re-labelled (49% all-three agreement) than on texts Jev labelled alone (75%).