Skip to content

Compare two users: shared watchlist, biggest gaps, closest agreement #281

Description

@ALeonard9

Story

As a druthers user, I want to compare my lists against another user's, so that we can find something to watch together and see where our taste actually diverges.

Acceptance Criteria

  • An endpoint compares the caller against another user by handle, per domain and across all domains
  • Common watchlist — titles on both users' watchlists, the "help us pick something" answer
  • Biggest gaps — titles both have ranked, ordered by the largest disagreement in position
  • Most aligned — titles both have ranked with the closest positions, plus an overall alignment score for the domain
  • Rank positions are normalized before comparison so a top-10 list and a 500-title list can be compared meaningfully, and the method is documented in the response
  • Alignment is suppressed, with an explanation, below a minimum shared-title threshold — two titles in common is noise, not agreement
  • The comparison reads only what the caller is permitted to see: their own data in full, and the other user's shelves and watchlists only at the tier that applies to this caller
  • Comparing against a user whose relevant lists are not visible to the caller returns a clear "not enough shared visibility" result rather than a misleading partial one
  • A user with no visible overlap at all is indistinguishable from one who does not exist, consistent with the public profile endpoint

Context

Raw capture:

Compare two users (friends or vs public). Common Watchlist items (Help pick something). Biggest gaps in ranking, most closely aligned.

Depends on epic #272 — specifically the visibility tiers (#274), the friend graph (#275), and the viewer-aware resolution (#277). The comparison is a consumer of that authorization work: it reads two users' data at once, which is precisely where a visibility mistake leaks the most.

Distinct from the existing taste-profile work. #184 (AI-generated taste profile) and #185 (group top-5 from matched profiles) infer preferences and apply constraints like streaming availability and content filters. This issue is deterministic: it compares the lists two users have actually built, with no inference and no AI. They are complementary — this one can ship without either — but they should not be conflated or built twice.

Companion: ALeonard9/druthers-web#126 (the comparison page).

Channel Impact

Estimate

  • Recommended model: Opus 4.8 — cross-user authorization plus a normalization scheme that has to be defensible, not just plausible.
  • Human effort: M — one product decision on the normalization method and the minimum-overlap threshold.

Notes for Implementation

Open decision: how to normalize rank positions. Comparing raw positions is wrong — being #1 of 30 is not the same achievement as #1 of 500, and raw deltas will make anyone with a long list look permanently misaligned. Percentile within each user's list is the obvious candidate, but it distorts at the top, where users care most: #1 versus #3 matters more than #250 versus #252. Whatever is chosen must be explainable in one sentence in the UI, because a comparison nobody trusts is worse than none.

The minimum-overlap threshold is a related judgment call — pick it deliberately rather than defaulting to 1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:sharingSocial sharing / share cardspriority:p2Do soonstoryUser story groomed from the Druthers Backlog (Todoist)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions