---
id: CAP-CRM-DQ-010
title: Review and merge from a record page
feature: FEAT-CRM-DQ-02
product_area: crm
module: data-quality
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes:
  - CAP-CRM-MRG-010
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    services-crm:docs/merging/experience/functional-requirements.md#IND-1 to IND-7, MAN-1, MAN-2 (package
    approved by Andrew 2026-10-13)
  - 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.md#D-03'
purpose: Staff can investigate duplicate suggestions without leaving the record they are reading.
outcomes:
  - Record-page review reveals suggestions in the current work context.
  - Manual or detected counterparts can join a plan with the current record.
concepts:
  - CON-CRM-DQ-001
actors:
  - ACT-CRM-008
  - ACT-CRM-009
  - ACT-CRM-002
surfaces:
  - console
  - api
permissions:
  - key: crm.duplicates.read
    where_checked: api
    scope: record
  - key: crm.contacts.merge
    where_checked: console
    scope: tenant
  - key: crm.organizations.merge
    where_checked: console
    scope: tenant
rules:
  - id: BR-CAP-CRM-DQ-010-01
    proved_by: [ATS-CRM-DQ-010-01, ATS-CRM-DQ-010-07, TST-CRM-DQ-182]
    statement: >-
      Per-record candidate reads include every status unless filtered, return at most 100 without pagination
      and return no group for an empty candidate list.
    kind: policy
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/e2e/duplicates.e2e.spec.js#answers nothing for a record in no pair
      at all
    origin: none
  - id: BR-CAP-CRM-DQ-010-02
    proved_by: [ATS-CRM-DQ-010-02, ATS-CRM-DQ-010-07, TST-CRM-DQ-180]
    statement: >-
      The response includes the connected group's records, including those related only through another
      candidate, for whole-group merge launch.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/services/candidates/duplicate-candidate-view.integration.spec.js#answers
      the four records of that group, which is the banner a record page shows
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#IND-5'
  - id: BR-CAP-CRM-DQ-010-03
    proved_by: [ATS-CRM-DQ-010-03, ATS-CRM-DQ-010-07, TST-CRM-DQ-183]
    statement: >-
      Reading candidates under an absorbed identity returns a merged-record response naming its survivor
      instead of an empty list.
    kind: policy
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/merges/tests/e2e/merged-records.e2e.spec.js#answers 410 to the old id’s duplicate
      candidates, rather than an empty list
    origin: 'services-crm:docs/milestones/CRM-M4-duplicates-and-merge.md#D-20'
  - id: BR-CAP-CRM-DQ-010-04
    proved_by: [ATS-CRM-DQ-010-04, ATS-CRM-DQ-010-07]
    statement: >-
      The page indicator includes open medium, high and very-high candidates, distinguishes likely
      high-or-above matches from medium possibilities and shows no alert for low-only or empty results.
    kind: policy
    enforced_at:
      - console
    must_prove: true
    provenance: observed
    source: 'react-console:components/duplicates/indicator/use-record-duplicates.ts:useRecordDuplicates'
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#IND-2'
  - id: BR-CAP-CRM-DQ-010-05
    proved_by: [ATS-CRM-DQ-010-05, ATS-CRM-DQ-010-07, TST-CRM-DQ-176]
    statement: Duplicate information on a record page is visible only with duplicate-read authority.
    kind: permission
    enforced_at:
      - console
      - api
    must_prove: true
    provenance: test
    source: 'react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0239.spec.ts#CRM-ACC-0239'
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#IND-7'
  - id: BR-CAP-CRM-DQ-010-06
    proved_by: [ATS-CRM-DQ-010-06, ATS-CRM-DQ-010-07, TST-CRM-DQ-176]
    statement: >-
      Merge-authorized staff launch a plan from selected indicator records, including the current record
      without choosing it as survivor.
    kind: policy
    enforced_at:
      - console
    must_prove: true
    provenance: test
    source: 'react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0286.spec.ts#CRM-ACC-0286'
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#MAN-2'
  - id: BR-CAP-CRM-DQ-010-07
    proved_by: []
    statement: >-
      Merge-authorized staff receive a Merge action and additional-record picker on contact and organization
      pages even without detected candidates.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: test
    source: 'react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0286.spec.ts#CRM-ACC-0286'
    origin: 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.md#D-03'
  - id: BR-CAP-CRM-DQ-010-08
    proved_by: []
    statement: >-
      Reviewers can dismiss an indicator candidate and see the changed decision reflected wherever that pair
      is displayed.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:components/duplicates/indicator/use-record-duplicates.ts:useRecordDuplicates'
    origin: 'services-crm:docs/merging/experience/functional-requirements.md#DIS-1'
scenarios:
  - id: SC-CAP-CRM-DQ-010-01
    given: 'A contact belongs to a three-record connection, including one indirect match.'
    when: An administrator launches Merge With Selected from its page.
    then: All three join the plan and the current record is not forced to survive.
    provenance: test
    source: 'react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0286.spec.ts#CRM-ACC-0286'
  - id: SC-CAP-CRM-DQ-010-02
    given: An organization has a candidate based on its name and domain.
    when: A reviewer dismisses the suggestion on its page.
    then: The alert clears and the pair appears among dismissed work.
    provenance: test
    source: 'react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0238.spec.ts#CRM-ACC-0238'
edge_cases: []
constraints: []
depends_on:
  - CAP-CRM-DQ-007
related:
  - CAP-CRM-DQ-008
  - CAP-CRM-DQ-012
  - CAP-CRM-ENT-003
journeys:
  - JNY-CRM-DQ-002
open_questions: []
evidence:
  - repository: services-crm
    source_sha: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
    paths:
      - docs/merging/experience/functional-requirements.md
      - docs/milestones/CRM-M1-contacts-and-organizations.md
      - docs/milestones/CRM-M4-duplicates-and-merge.md
      - modules/duplicates/aws/api/duplicates.routes.ts
      - modules/duplicates/tests/e2e/duplicates.e2e.spec.js
      - modules/duplicates/tests/integration/services/candidates/duplicate-candidate-view.integration.spec.js
      - modules/merges/tests/e2e/merged-records.e2e.spec.js
    note: 'Static examination connects rule claims to implementation, declared checks and the cited tests.'
  - repository: react-console
    source_sha: baf6dae382d6f41dce976c7f848667ccc37e076f
    paths:
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0238.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0239.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0286.spec.ts
      - components/duplicates/indicator/use-record-duplicates.ts
    note: 'Static examination connects rule claims to implementation, declared checks and the cited tests.'
preconditions: []
postconditions: []
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004]
exercised_by: [FAS-CRM-DQ-02-02, FAS-CRM-DQ-02-05]
suites: [TST-CRM-DQ-176, TST-CRM-DQ-180, TST-CRM-DQ-182, TST-CRM-DQ-183]
---

# Review and merge from a record page

## Purpose

Staff can investigate duplicate suggestions without leaving the record they are reading.

## How It Works

A record page requests its open medium-or-stronger suggestions when the reader has duplicate-read permission. The indicator distinguishes likely matches from medium-confidence possibilities. Weak suggestions do not produce a page alert. The response can include the whole connected group, including records reached through another candidate. An authorized merger selects records and starts a plan. The current record joins the participants without automatically becoming the survivor. A Merge action also allows manual selection when detection found nothing. Reviewers can dismiss suggestions from the indicator. A request under a merged-away identity reports the survivor rather than returning an empty candidate list. The same interaction applies to contacts and organizations.

## Relationships

Queue review and record-page review share candidates and dismissals. Merge planning owns the choice of participants and survivor once the page launches a plan.
