Skip to content

Design: recommendations for ID — similar objects and similar users, across all object types #5732

Open

Description

@dezren39

Design: recommendations for ID — similar objects and similar users, across all object types

Extends #5675 (querying / discovery). Related: #5677 (notes / boards / multiplayer editing), #5678 (knowledge layer), #5683 (residency & boundaries — sensitivity rules below lean on it), #5669 (staging tier — computation placement).

The gap

#5675 covers finding things in ID when you know what you're looking for (search, local and remote). It does not cover being shown things you didn't ask for: "worlds like this one", "documents people in your position read next", "users working on similar things". Search answers intent; recommendations create discovery. Drew (2026-11-04): file this for ID across all object types, not just worlds, and take similar-user view metrics into account.

Scope — all object types

The recommender treats every first-class ID object type uniformly:

  • worlds, documents, notes, boards, chats / message threads, programs, and users themselves ("people working on similar things").
  • Every recommendation is a typed edge: (subject object, recommended object, signal, score, computed_at) — so any surface (a world's sidebar, a document's "read next", a home/discovery feed, a board's header) renders the same underlying data.

Signals (v1 is arithmetic, not a trained model)

  1. Item–item co-occurrence (Jaccard over interaction sets). Two objects are similar when the sets of users who viewed / joined / edited them overlap. Jaccard similarity over those sets is the score. This is the classic collaborative signal and needs no ML infrastructure — set arithmetic over interaction logs.
  2. User–user similarity ("similar users viewed"). Users are similar when their view / interaction histories overlap (Jaccard or cosine over each user's object-interaction set). A user's recommendations then include objects that similar users engaged with and the user has not seen. Drew's requirement (2026-11-04): this signal is in scope from v1, not a later phase — weighted alongside item–item, not replacing it.
  3. Content-based cold start. A new object has no interactions to overlap. Fall back to the embedding scan (the atlas machinery: dense cosine over descriptions / content) until interaction data accrues; a new user starts from content similarity of the objects they first touch. Cold-start edges are labeled with their signal so surfaces can present them differently if wanted.

Sensitivity rules (hard constraints, from #5683 / #5675)

  • A recommendation never crosses a sensitivity boundary: an object is only ever recommended to users who could already access it. The recommender filters by the requester's visibility before ranking, not after.
  • Similar-user metrics are computed only over interactions with objects visible to the requester. ("People like you read X" must never leak the existence of a private X, nor that a specific user read anything.)
  • No per-user reading history is ever surfaced to another user — only aggregate similarity outcomes ("similar users viewed"), never identities or histories. An opt-out from contributing interaction data to similarity computation should exist and be cheap to honor.

Computation placement (staging tier pattern, #5669)

  • Recommendations are computed periodically into tables, not per request: interaction aggregates accumulate in a staging DB; a batch pass computes similarity edges and promotes them into the core tier keyed by object, so reads are simple lookups.
  • Recency decay: interactions age — a view from a year ago should weigh less than one from this week (decay function is an open question below).
  • Recompute cost is bounded by the interaction graph's active slice, not the whole history.

Open questions for the design pass

  • Decay + diversity: pure similarity collapses into an echo of what's already popular — what diversity / serendipity term keeps suggestions non-obvious? (At minimum: cap how many recommendations one very popular object can occupy.)
  • Freshness vs stability: how often to recompute so suggestions feel alive without churning between visits?
  • Feedback loop accounting: when a user follows a recommendation, that interaction itself becomes similarity data — how do we keep the system from amplifying its own suggestions into fake consensus?
  • Evaluation: what do we measure — follow-through rate (clicked / joined / read), and against what baseline (recency-ordered, popularity-ordered)?

Non-goals for v1

  • No trained ranking model / matrix factorization — revisit only if the arithmetic signals measurably plateau.
  • No cross-server recommendation federation until id: design: Querying local and remote ID servers v1 #5675's remote querying settles its sensitivity story; v1 is per-server (or per-owner-data) only.

Activity

  1. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor
  2. added
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    work/assignedQueue worker lifecycle state
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  3. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  4. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 5, 2026
  5. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  6. 118 remaining items

  7. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  8. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    queue/claimedQueue worker lifecycle state
    and removed
    queue/claimedQueue worker lifecycle state
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

queue/parkedQueue task is parked (waiting on CI, time, or an event)status/parkedDeliberately paused with a recorded resume conditiontask/triageQueue packet kind: verify, reproduce, and route this itemwork/assignedQueue worker lifecycle state

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions