# AI Duplicate Record Matching

## Objective

Surface records that probably describe the same thing, with the evidence for each match.

A duplicate detection pass combining deterministic keys with semantic similarity, producing reviewable candidate pairs.

## Before You Begin

This feature is being added to an application that already exists and already
works. Do not scaffold a new project, and do not assume a blank slate.

Inspect the codebase first and establish:

- The existing application structure and where code of this kind already lives.
- The framework and version in use.
- The existing design system — colours, spacing, typography, and component conventions.
- Existing UI components you can reuse instead of writing new ones.
- The existing database structure, if this feature needs to persist anything.
- The existing authentication and authorization system, if this feature is user-scoped.
- Dependencies already installed, so you don't add a library that duplicates one.
- The existing test setup and conventions.

Only start writing code once you understand the above. If the application
already implements part of this feature, extend it rather than replacing it.

## Implementation Instructions

1. Run deterministic matching first on the identifiers the domain already trusts — email, tax number, external system ID, normalized phone — and settle those cases before any model is involved. Semantic similarity is for what deterministic rules miss, not a replacement for them.
2. Use similarity to generate candidates, then score each pair on a field-by-field basis and store which fields agreed, which conflicted, and by how much.
3. Present matches as a review queue showing the two records side by side with the contributing fields highlighted, and make dismissal permanent so the same pair does not resurface every run.
4. Scope every comparison to a single tenant and to records the reviewer may see. A duplicate finder that reaches across a workspace boundary is a data leak with a helpful interface.
5. Make merges reversible for a defined window: keep the pre-merge state, record which record absorbed which, and preserve references from both so links elsewhere in the app do not break.

## UI and UX Requirements

Match the application's existing design system exactly. Reuse its components,
spacing, and typography. This feature should look like it was always there.

## Responsive Requirements

Works on mobile, tablet, and desktop. Touch targets are large enough to hit on a
phone, and nothing overflows horizontally at 320px.

## Accessibility Requirements

- Fully keyboard navigable.
- Correct semantic elements and ARIA roles.
- Visible focus states.
- Meets WCAG AA contrast.
- Dynamic changes are announced to screen readers.
- Respects prefers-reduced-motion.

## Edge Cases

- Neither signal is sufficient alone. Deterministic identifiers catch the obvious cases, similarity catches the messy ones, and a pair should surface only when the combined evidence holds up field by field.
- Common names, shared support addresses, and generic descriptions produce large false-positive clusters. Require corroboration on a second independent field before proposing a merge on a name alone.
- Every candidate must show why it was proposed. A confidence percentage with no visible evidence gives a reviewer nothing to reason about and trains them to approve everything.
- Comparison must never cross tenant, workspace, or permission boundaries, and the review queue must exclude pairs where the reviewer cannot see both sides.
- Merges must be confirmed by a person or governed by rules narrow enough to be safe, and must be reversible. An automatic merge on a wrong pair destroys two records and the history that explains them.
- Field-level conflicts need an explicit resolution step. When two records disagree on an address or a phone number, the reviewer chooses rather than the newer record silently winning.
- Duplicate detection over a large table is expensive. Block candidates on cheap keys before scoring, cap the work per run, and process through the app's existing background-job system rather than during a request.
- Dismissals and merges must be recorded in an audit trail with who acted and when, since a merge is one of the least recoverable operations in the app.

## Testing

Exercise the feature end to end in the running application. Cover every edge case
above, then run the existing test suite and confirm nothing regressed.

## Acceptance Criteria

- [ ] Deterministic identifier matches are resolved before semantic scoring runs.
- [ ] Every candidate pair records the fields that agreed and the fields that conflicted.
- [ ] The review interface shows both records with the matching evidence highlighted.
- [ ] Comparisons and the review queue respect tenant and permission boundaries.
- [ ] Merges require confirmation, resolve field conflicts explicitly, and are reversible within a defined window.
- [ ] Dismissed pairs do not reappear in later runs.
- [ ] Detection runs in the background with a bounded cost per run.
- [ ] The feature matches the existing design system.
- [ ] No existing functionality is broken.

## Adaptation Rules

- Match the existing design system. Do not introduce a new colour palette,
  spacing scale, or component library.
- Reuse existing components and utilities wherever they fit.
- Follow the naming, file layout, and code style already present.
- Do not upgrade, replace, or remove existing dependencies to make this
  feature fit. Adapt the feature to the app, not the app to the feature.
- Do not break existing functionality. If a change is genuinely required in
  existing code, make the smallest one that works and say so.
- If something in these instructions conflicts with how the application is
  built, follow the application and explain the deviation.

## Final Verification

Before you report the work as done:

1. Re-read the acceptance criteria above and check each one against what you
   actually built.
2. Run the application and exercise the feature end to end.
3. Run the existing test suite and confirm you have broken nothing.
4. Check the feature on mobile, tablet, and desktop widths.
5. Check keyboard navigation and focus handling.
6. Summarize what changed: files added, files modified, and anything you
   deliberately did differently because of how this application is built.

If any acceptance criterion is unmet, fix it before reporting completion.
