---
id: ATS-CRM-DQ-002
scope: CAP-CRM-DQ-002
product_area: crm
module: data-quality
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-DQ-002-01
    title: Contact evidence uses the fixed point schedule
    level: unit
    proves:
      - BR-CAP-CRM-DQ-002-01
    preconditions: Build contact pairs representing every supported evidence item.
    steps: Score each fixture.
    expected: Each evidence item contributes its specified number of points.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#declares
        the weight of every row of §5.1
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#gives
        an e-mail address primary on both records 40
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#takes
        40 off for dates of birth that are both present and different
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#declares
      the weight of every row of §5.1
    category: rule
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#declares
        the weight of every row of §5.1
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#gives
        an e-mail address primary on both records 40
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#takes
        40 off for dates of birth that are both present and different
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-02
    title: Contradictions limit contact confidence
    level: unit
    proves:
      - BR-CAP-CRM-DQ-002-02
      - BR-CAP-CRM-DQ-002-12
    preconditions: >-
      Prepare conflicting names, birth dates and suffixes alongside household
      and spouse examples.
    steps: Evaluate each pair.
    expected: >-
      The conflicts apply ceilings of 49, 49 and 35 with the lowest prevailing;
      household confidence is low and the spouse example falls below storage.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#holds
        a pair whose names both disagree to 49
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#holds
        a pair to the lowest cap when two of them fire
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#scores
        a household sharing one e-mail address low, not high
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#scores
        a spouse pair below the band floor, which is what fixes 1.0’s “spouses
        score 94”
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#holds
      a pair whose names both disagree to 49
    category: edge
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#holds
        a pair whose names both disagree to 49
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#holds
        a pair to the lowest cap when two of them fire
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#scores
        a household sharing one e-mail address low, not high
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#scores
        a spouse pair below the band floor, which is what fixes 1.0’s “spouses
        score 94”
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-03
    title: Organization evidence applies its weights and ceilings
    level: unit
    proves:
      - BR-CAP-CRM-DQ-002-03
    preconditions: >-
      Prepare each organization evidence type, a domain-only resemblance and an
      ancestor pair.
    steps: Score the fixtures.
    expected: >-
      Points follow the schedule, domain-only resemblance caps at 69 and
      ancestry at 35.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#declares
        the weight of every row of §5.2
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/organization-scoring.spec.js#holds
        such a pair to 69
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/organization-scoring.spec.js#holds
        a parent and its child to 35, however alike they read
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#declares
      the weight of every row of §5.2
    category: rule
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#declares
        the weight of every row of §5.2
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/organization-scoring.spec.js#holds
        such a pair to 69
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/organization-scoring.spec.js#holds
        a parent and its child to 35, however alike they read
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-04
    title: Band boundaries distinguish stored suggestions
    level: unit
    proves:
      - BR-CAP-CRM-DQ-002-04
    preconditions: 'Use scores 0, 34, 35, 49, 50, 69, 70, 89, 90 and 100.'
    steps: Resolve the confidence band for each score.
    expected: >-
      Values below 35 have no band; the remaining boundaries produce low,
      medium, high and very high correctly.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
        34 no band at all, so the pair is not stored
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
        35 the low band
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
        90 the very high band
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
      34 no band at all, so the pair is not stored
    category: boundary
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
        34 no band at all, so the pair is not stored
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
        35 the low band
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
        90 the very high band
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-05
    title: Reasons explain points before score ceilings
    level: unit
    proves:
      - BR-CAP-CRM-DQ-002-05
    preconditions: A pair contains several evidence contributions and a score limit.
    steps: Render the explanation.
    expected: >-
      Reasons follow scoring order with their points, followed by the ceiling
      explanation.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#renders
        one sentence per piece of evidence, in the order the scorer found it
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#renders
        the caps after the evidence
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#says
        what the cap was and what it holds the score to
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#renders
      one sentence per piece of evidence, in the order the scorer found it
    category: rule
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#renders
        one sentence per piece of evidence, in the order the scorer found it
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#renders
        the caps after the evidence
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#says
        what the cap was and what it holds the score to
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-06
    title: Explanations mask private matching values
    level: unit
    proves:
      - BR-CAP-CRM-DQ-002-06
    preconditions: 'A pair agrees on e-mail, phone and birth date.'
    steps: Generate the masked evidence explanation.
    expected: >-
      E-mail retains only its first character and domain, phone its last four
      digits and no full birth date appears.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#never
        carries a full e-mail address into a sentence
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#never
        carries a full phone number into a sentence
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#never
        carries a date of birth into a sentence
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#never
      carries a full e-mail address into a sentence
    category: invariant
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#never
        carries a full e-mail address into a sentence
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#never
        carries a full phone number into a sentence
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/explanation.spec.js#never
        carries a date of birth into a sentence
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-07
    title: Scoring does not depend on record order
    level: unit
    proves:
      - BR-CAP-CRM-DQ-002-08
    preconditions: Prepare one contact pair.
    steps: Score twice and reverse the participants.
    expected: 'Score, reasons and ceilings remain identical.'
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#answers
        the same reasons and caps whichever record is first
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/organization-scoring.spec.js#answers
        the same result twice for one pair
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#answers
      the same reasons and caps whichever record is first
    category: invariant
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#answers
        the same reasons and caps whichever record is first
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/organization-scoring.spec.js#answers
        the same result twice for one pair
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-08
    title: Queue confidence is explained for member variants
    level: browser
    proves:
      - BR-CAP-CRM-DQ-002-01
      - BR-CAP-CRM-DQ-002-04
      - BR-CAP-CRM-DQ-002-05
    preconditions: Create five variants of a member through the console.
    steps: Review their Data Quality suggestions.
    expected: >-
      Evidence explains the displayed bands, private values are masked and
      sub-threshold pairs are absent.
    negative: false
    data_needs: Provide fixtures for create five variants of a member through the console.
    bound_to:
      - TST-CRM-DQ-176
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0230.spec.ts#CRM-ACC-0230
    category: interaction
    execution_sources:
      - >-
        react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0230.spec.ts#CRM-ACC-0230
  - id: ATS-CRM-DQ-002-09
    title: Evidence totals remain bounded
    level: unit
    proves:
      - BR-CAP-CRM-DQ-002-13
    preconditions: Prepare pairs with excess positive evidence and conflicting evidence.
    steps: Score each pair and inspect the final total and applied ceilings.
    expected: Totals remain between zero and 100 and respect the lowest ceiling.
    negative: false
    data_needs: Use the records and caller described in this scenario.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#clamps
        a sum above 100 to 100
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#clamps
        a sum below 0 to 0
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#holds
        a pair to the lowest cap when two of them fire
    provenance: test
    source: 'services-crm:modules/duplicates/services/matching/scoring.ts:scoreOf'
    category: boundary
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#clamps
        a sum above 100 to 100
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#clamps
        a sum below 0 to 0
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js#holds
        a pair to the lowest cap when two of them fire
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-10
    title: The confidence floor separates two adjacent scores
    category: invariant
    level: unit
    proves:
      - INV-DOM-CRM-DQ-001-02
    preconditions: Pairs with computed scores of thirty-four and thirty-five.
    steps: Assign a confidence band to each score.
    expected: The lower score has no band; the higher score receives the low band.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
        34 no band at all, so the pair is not stored
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
      34 no band at all, so the pair is not stored
    design_sources:
      - DOM-CRM-DQ-001
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/bands.spec.js#gives
        34 no band at all, so the pair is not stored
    provenance: test
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-002-11
    title: Confidence controls both creation advice and review visibility
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-DQ-002-01
      - BR-CAP-CRM-DQ-002-02
      - BR-CAP-CRM-DQ-002-12
      - BR-CAP-CRM-DQ-002-03
      - BR-CAP-CRM-DQ-002-04
      - BR-CAP-CRM-DQ-002-05
      - BR-CAP-CRM-DQ-002-06
      - BR-CAP-CRM-DQ-002-08
      - BR-CAP-CRM-DQ-002-13
    exercises:
      - CAP-CRM-DQ-002
      - CAP-CRM-DQ-003
      - CAP-CRM-DQ-007
    workflow_sources:
      - WF-CRM-DQ-001
    preconditions: >-
      Run-owned contact and organization records, the relevant staff permissions
      and the related state described by the sequence.
    steps: >-
      Score matching and contradictory contact variants, evaluate the configured
      action for each, and open their queue explanations.
    expected: >-
      The configured response and queue evidence use the same scored outcome and
      mask the private values.
    negative: false
    data_needs: >-
      An isolated workspace with related records and fixed timestamps; owned
      participant failure injection where requested.
    source: CAP-CRM-DQ-002; CAP-CRM-DQ-003; CAP-CRM-DQ-007; WF-CRM-DQ-001
    note: >-
      This cumulative seam scenario remains proposed until one executable
      sequence establishes all of its outcomes.
    bound_to: []
    provenance: proposed
    workflow_coverage_note: >-
      The workflows identify the handoffs under review. Separate assertions
      leave recovery and failure ordering unproved; the capability coverage
      finding records that limit.
    execution_sources: []
evidence:
  - repository: services-crm
    source_sha: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
    paths:
      - modules/duplicates/services/matching/scoring.ts
      - modules/duplicates/tests/unit/services/matching/bands.spec.js
      - modules/duplicates/tests/unit/services/matching/contact-scoring.spec.js
      - modules/duplicates/tests/unit/services/matching/explanation.spec.js
      - >-
        modules/duplicates/tests/unit/services/matching/organization-scoring.spec.js
    note: >-
      Bindings identify authored proof; empty bindings remain proposed and
      findings record known limitations.
  - repository: react-console
    source_sha: baf6dae382d6f41dce976c7f848667ccc37e076f
    paths:
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0230.spec.ts
    note: >-
      Bindings identify authored proof; empty bindings remain proposed and
      findings record known limitations.
coverage:
  rule: covered
  transition: 'gap: FND-CRM-DQ-053'
  validation: 'gap: FND-CRM-DQ-053'
  permission: 'gap: FND-CRM-DQ-053'
  edge: covered
  failure: 'gap: FND-CRM-DQ-053'
  boundary: covered
  concurrency: 'gap: FND-CRM-DQ-053'
  invariant: covered
  interaction: covered
coverage_notes:
  transition: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  validation: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  permission: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  failure: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  concurrency: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
permission_coverage:
  - key: crm.duplicates.read
    scenario_ids: []
    finding: FND-CRM-DQ-053
proof_matrix:
  - rule: BR-CAP-CRM-DQ-002-01
    scenarios:
      - ATS-CRM-DQ-002-01
      - ATS-CRM-DQ-002-08
      - ATS-CRM-DQ-002-11
  - rule: BR-CAP-CRM-DQ-002-02
    scenarios:
      - ATS-CRM-DQ-002-02
      - ATS-CRM-DQ-002-11
  - rule: BR-CAP-CRM-DQ-002-03
    scenarios:
      - ATS-CRM-DQ-002-03
      - ATS-CRM-DQ-002-11
  - rule: BR-CAP-CRM-DQ-002-04
    scenarios:
      - ATS-CRM-DQ-002-04
      - ATS-CRM-DQ-002-08
      - ATS-CRM-DQ-002-11
  - rule: BR-CAP-CRM-DQ-002-05
    scenarios:
      - ATS-CRM-DQ-002-05
      - ATS-CRM-DQ-002-08
      - ATS-CRM-DQ-002-11
  - rule: BR-CAP-CRM-DQ-002-06
    scenarios:
      - ATS-CRM-DQ-002-06
      - ATS-CRM-DQ-002-11
  - rule: BR-CAP-CRM-DQ-002-08
    scenarios:
      - ATS-CRM-DQ-002-07
      - ATS-CRM-DQ-002-11
  - rule: BR-CAP-CRM-DQ-002-12
    scenarios:
      - ATS-CRM-DQ-002-02
      - ATS-CRM-DQ-002-11
  - rule: BR-CAP-CRM-DQ-002-13
    scenarios:
      - ATS-CRM-DQ-002-09
      - ATS-CRM-DQ-002-11
interaction_coverage:
  related:
    - CAP-CRM-DQ-003
    - CAP-CRM-DQ-007
  workflow_sources:
    - WF-CRM-DQ-001
  scenarios:
    - ATS-CRM-DQ-002-08
    - ATS-CRM-DQ-002-11
---

# Explain the strength of a duplicate suggestion: Capability Test Specification

## Coverage

The rule matrix names the authored checks. A covered category means that a scenario exists; it does not report a passing execution. The coverage notes and findings identify missing checks, while execution sources retain the exact assertions inspected.

| Required Rule | Scenarios |
|---|---|
| `BR-CAP-CRM-DQ-002-01` | `ATS-CRM-DQ-002-01`, `ATS-CRM-DQ-002-08`, `ATS-CRM-DQ-002-11` |
| `BR-CAP-CRM-DQ-002-02` | `ATS-CRM-DQ-002-02`, `ATS-CRM-DQ-002-11` |
| `BR-CAP-CRM-DQ-002-03` | `ATS-CRM-DQ-002-03`, `ATS-CRM-DQ-002-11` |
| `BR-CAP-CRM-DQ-002-04` | `ATS-CRM-DQ-002-04`, `ATS-CRM-DQ-002-08`, `ATS-CRM-DQ-002-11` |
| `BR-CAP-CRM-DQ-002-05` | `ATS-CRM-DQ-002-05`, `ATS-CRM-DQ-002-08`, `ATS-CRM-DQ-002-11` |
| `BR-CAP-CRM-DQ-002-06` | `ATS-CRM-DQ-002-06`, `ATS-CRM-DQ-002-11` |
| `BR-CAP-CRM-DQ-002-08` | `ATS-CRM-DQ-002-07`, `ATS-CRM-DQ-002-11` |
| `BR-CAP-CRM-DQ-002-12` | `ATS-CRM-DQ-002-02`, `ATS-CRM-DQ-002-11` |
| `BR-CAP-CRM-DQ-002-13` | `ATS-CRM-DQ-002-09`, `ATS-CRM-DQ-002-11` |

## Interactions With Related Capabilities

Review their Data Quality suggestions. Score matching and contradictory contact variants, evaluate the configured action for each, and open their queue explanations.

These sequences test the handoffs named in the interaction coverage record. A proposed sequence remains unbound until an executable run checks its combined outcome; component assertions alone leave that obligation open.
