Add docs/inspirations.md as the durable record of the 2026-07-05/06 prior-art research — per-project learnings with source paths, canonical credit lines, and the changes each spawned — and extend the acknowledgment lists in philosophy.md/architecture.md (Organic Maps, Endurain, wanderer). New OpenSpec changes (proposal/design/specs/tasks each): - Organic Maps: elevation-profile-hardening, gpx-parser-robustness, hiking-time-estimate, poi-index, hiking-foot-profile - Endurain: account-export, activity-duplicate-review, fit-parsing-hardening, activity-locations, self-hosting-guide, activity-privacy-controls - wanderer: federation-hardening, link-share-tokens - credits-page (user-visible acknowledgments) Updated in-flight changes with wanderer prior-art sections: route-federation, route-discovery. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2.8 KiB
2.8 KiB
Why
Dedup today is per-provider only: sync_imports keys on (provider, externalWorkoutId), so re-delivery from the same provider is caught. But the same real-world ride can arrive from two sources — Wahoo webhook + Garmin backfill (pending), Komoot import + manual GPX upload — and nothing catches that: the user gets two activities, double distance in weekly stats, and a duplicated feed entry for followers. With Garmin and COROS on the roadmap this will become routine. Endurain's pattern (reviewed 2026-07-06): store the incoming activity anyway, flag it as a suspected duplicate, hide it from all surfaces, and let the user resolve — no silent auto-merge, no data loss.
What Changes
- On every activity creation from an import path (provider sync, manual upload, Komoot), a cross-source duplicate check runs: same owner + overlapping time window (
started_atwithin ±2 minutes and durations overlapping ≥ 70%, when both have times). - A suspected duplicate is stored with
suspectedDuplicateOfIdset and is excluded from feeds, listings, profile stats, federation, and follower notifications until resolved. - The owner gets a "possible duplicate import" notification and a review UI showing both activities side by side (source, time, distance, map) with two actions: keep both (clears the flag, activity becomes normal) or discard (deletes the flagged copy).
- Import batches report suspected duplicates distinctly from exact-ID duplicates (
import_batches.duplicateCountcounts exact; a new counter for suspected). - Not in scope: auto-merging data from two sources into one activity, retroactive scanning of existing activities, and route (non-activity) dedup.
Capabilities
New Capabilities
duplicate-detection: Cross-source duplicate detection on activity import — the heuristic, the quarantine semantics (hidden-from-everything until resolved), the notification, and the resolve flow.
Modified Capabilities
Impact
packages/db:activities.suspected_duplicate_of_id(nullable text, FK activities, on delete set null); new counter column onimport_batches.- All import call sites converge on the shared save path (
gpx-save.server.ts/ activity creation helper) — the check lives once, there. - Query-layer exclusion: feed, listings, profile stats, weekly distance, federation outbox, follower notifications must filter
suspected_duplicate_of_id IS NULL(single shared predicate). - New review UI (activity page banner + notification deep link), notification type, i18n strings.