Duplicate Detection
When a tenant reports the same problem twice ("my shower was cold again"), you don't want to dispatch a second plumber. You want to reopen last week's work order and escalate.
PMFriend's duplicate detector runs on every NEW and TRIAGED request and
raises a yellow banner in the request drawer if a likely duplicate exists.
How it finds them
Two passes:
- Semantic (Claude): the incoming request text + candidate texts (last 14 days at the same property) go to Claude. Claude returns a confidence score + one-sentence reasoning. Example: "cold showers" and "no hot water again" get flagged as near-duplicates even though they share no keywords.
- Heuristic (Jaccard fallback): if Claude is unavailable, we tokenise both texts, strip stopwords, and compute Jaccard overlap. Anything ≥ 0.35 raises the banner.
What the banner looks like
⚠ Likely duplicate of request #MR-2189 (94% confidence)
"Shower ran cold on Saturday night" — submitted 8 days ago, status IN_PROGRESS.
Reasoning: Both describe intermittent hot water; same bathroom context.
[Open request] [Mark as duplicate] [Dismiss]
Mark as duplicate links the two requests (audit-logged) and closes the new one. Dismiss hides the banner for this session.
Scope
- Same property only — we never cross-match between properties.
- 14-day window — older requests aren't candidates. Configurable per-agency (not exposed in UI yet).
- Excludes COMPLETED + CANCELLED by default — we match against open work only.
API
POST /api/v1/maintenance-requests/{id}/detect-duplicate
No body. Returns:
{
"candidates": [
{
"requestId": "MR-2189",
"confidence": 0.94,
"reasoning": "Both describe intermittent hot water; same bathroom context.",
"sourceText": "Shower ran cold on Saturday night"
}
],
"modelVersion": "claude-haiku-4-5@prompt-v1"
}
Empty candidates[] means no likely duplicates — banner doesn't show.
Why this matters commercially
Duplicate dispatches are one of the most common owner complaints we've heard. "I paid $340 to have a plumber come out and they told me the same thing they told me last month" — owner churn risk. This feature turns that into a two-click "oh, this is the same issue, let me reopen the other WO" flow.
See also
- AI Triage
- Duplicate Detection (AI deep dive) — prompt, fallback, confidence calibration