Duplicate auto-detection — how it works
Citizens often report the same pothole, dead streetlight, or downed tree multiple times. The platform auto-detects these so triage staff don't waste cycles on the same hole twice.
Every new submission is checked against existing reports in the same primary jurisdiction + same category submitted in the last 30 days. The check uses haversine distance against each candidate's geo point:
- **Within 15 meters AND submitted within the last 7 days** → **auto-merged**. The new report is set to `duplicate` status, `duplicateOfReportId` points at the canonical (older) report, and the canonical's upvote count is bumped by 1. The reporter still gets a permanent link to their submission, which now redirects to the canonical report's resolution timeline.
- **Within 75 meters AND submitted within the last 30 days** (but outside the auto-merge band) → **suggested as duplicate**. `suggestedDuplicateOfReportId` is stamped on the new report and it lands in your `/civicreports` → **Duplicates** tab queue.
In the Duplicates tab:
- **Confirm duplicate** — accepts the suggestion. The new report is merged into the canonical (status → `duplicate`, votes transferred + 1).
- **Not a duplicate** — clears the suggestion fields. The report stays in your normal triage flow.
The auto-detector only triggers on submission. If staff want to merge two reports that *both* already exist in your workspace (e.g. they sat in your queue for weeks before someone noticed they're the same hole), use `/report/<id>` → "Merge as duplicate" or call the merge tool from chat.
Citizens whose reports were auto-merged see a banner on the public detail page linking to the canonical report so they can still track resolution. The reverse-geocoded address on the report is preserved either way.