Userz

Duplicate detection

Twenty users report the same broken save button. Userz turns that into one PR — not twenty.

How it works

When Userz spots that a new report describes the same thing as an existing one, it attaches the new report as a duplicate of the original. The original (the oldest of the cluster) becomes the lead: it carries an LLM-consolidated description, a short theme, and the eventual PR. The agent runs once against the consolidated description — one PR per theme, not one PR per report.

Every member stays queryable as its own Signal row (screenshots, console logs, submitter info all preserved) — they're grouped onto one Directive rather than discarded. Opening the Directive surfaces all of its attached signals in one place, each with a back-link to where it came from.

Two modes

Pick one in App settings → Batching:

  • Incremental merge: every new submission is compared against recent feedback in real time (Jaccard token pre-filter → cosine similarity on embeddings). A match attaches immediately; no match routes the submission normally.
  • Windowed rollup: signals accumulate over a configurable window (batchWindowHours, default 24). When you click Trigger duplicate detection, Userz clusters everything in the window in one pass and promotes one Directive per cluster.

The two modes are mutually exclusive per App. Both use the helper model you've configured under Settings → AI, so you can pair a cheap helper (Haiku, GPT-4o-mini, GLM-Flash) with a powerful agent.

What the agent sees

When a cluster promotes to a Directive, the agent's prompt uses the Directive's text — an LLM-consolidated description that covers every member Signal's intent. The PR body cites the Directive id and notes how many signals were consolidated.

When a new Signal attaches to a Directive that's already opened a PR, the Directive's consolidated description is updated for future reference, but the in-flight PR is not re-run automatically — you can always trigger a fresh run from the dashboard if the new Signal adds material context.

Working with duplicates

From the dashboard you can:

  • Trigger duplicate detection (windowed mode) to cluster the current window immediately rather than wait for the next manual pass.
  • View attached duplicates on the lead's detail page, with cross-links to each duplicate's full payload.
  • Tune the similarity threshold (incremental mode) per App, between 0 and 1. The default 0.82 balances recall against false-merges.
The lead is always the oldest member — the original first submission. New duplicates attach to it; the lead is never demoted.

Surfacing the work back to your users

Each Signal keeps its own identity and provenance, so end-user-facing surfaces (your own status pages, chat-ops responses) can tell every reporter that their issue is being addressed without revealing how it was grouped. Fetch the grouped Directive with GET /v1/feedback/:id: its signalIds list every Signal rolled into the work, and primarySignalId points at the one that seeded it.