---
id: ATS-CRM-DQ-001
scope: CAP-CRM-DQ-001
product_area: crm
module: data-quality
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-DQ-001-01
    title: Detection failure leaves saving independent
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-01
      - BR-CAP-CRM-DQ-001-10
    preconditions: Arrange a contact save whose later detection pass fails.
    steps: Save the record and allow background detection to fail.
    expected: >-
      The save succeeds independently; failed processing is redelivered and keys
      are established only by a successful pass.
    negative: true
    data_needs: >-
      Provide fixtures for arrange a contact save whose later detection pass
      fails.
    bound_to: []
    provenance: proposed
    source: FND-CRM-DQ-027
    category: failure
    execution_sources: []
  - id: ATS-CRM-DQ-001-02
    title: Matching edits trigger refresh
    level: unit
    proves:
      - BR-CAP-CRM-DQ-001-02
    preconditions: Supply surname and job-title change events.
    steps: Apply the event filter and handler to both.
    expected: 'Surname processing proceeds, while the job-title event writes no keys.'
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/detection/duplicate-change-events.spec.js#is
      not touched by a changed job title, which changes no key and no evidence
    category: rule
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/detection/duplicate-change-events.spec.js#is
        not touched by a changed job title, which changes no key and no evidence
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-change-events.integration.spec.js#wrote
        no key, a job title changing no key and no evidence
  - id: ATS-CRM-DQ-001-03
    title: Contact and organization keys cover their supported evidence
    level: unit
    proves:
      - BR-CAP-CRM-DQ-001-03
    preconditions: Prepare both types with values for every key kind.
    steps: Generate their match keys.
    expected: >-
      Six contact and five organization kinds appear, excluding free-mail
      domains.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/match-keys.spec.js#names
        the six contact key types of §3
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/match-keys.spec.js#names
        the five organization key types of §3
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/unit/services/matching/match-keys.spec.js#names
      the six contact key types of §3
    category: rule
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/match-keys.spec.js#names
        the six contact key types of §3
      - >-
        services-crm:modules/duplicates/tests/unit/services/matching/match-keys.spec.js#names
        the five organization key types of §3
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-001-04
    title: Rare evidence still joins a pair when common keys are excluded
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-04
    preconditions: >-
      Three contacts share name and birth date; only two share a phone, with the
      test cap set to two.
    steps: Detect the contacts together.
    expected: >-
      The common name keys are skipped, the phone connects its pair and skipped
      evidence contributes zero points.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#still
      found the two records a rarer key joins, which is the telephone number
      only they hold
    category: boundary
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#still
        found the two records a rarer key joins, which is the telephone number
        only they hold
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#gives
        that reason no points, it being the absence of a lookup and not evidence
  - id: ATS-CRM-DQ-001-05
    title: Excessively common evidence retires suggestions without undoing decisions
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-05
    preconditions: >-
      Prepare phone-supported pairs, an independently e-mail-supported pair and
      a dismissed phone pair.
    steps: Add enough phone holders to exceed the cap and detect another holder.
    expected: >-
      The phone-only open pair disappears, the e-mail pair receives updated
      zero-point evidence and dismissal remains untouched.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#retired
      the pair the number alone joined, its only evidence being disqualified
    category: transition
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#retired
        the pair the number alone joined, its only evidence being disqualified
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#kept
        the pair that also shares an e-mail address, by its id
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#left
        the dismissed pair the number joined as it was: a decision is never
        retired by evidence moving
  - id: ATS-CRM-DQ-001-06
    title: Records created together become one candidate
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-06
    preconditions: Create two matching contacts in a single batch.
    steps: Run detection for the complete batch.
    expected: Keys precede comparison and one candidate connects the contacts.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#found
      the two records of the batch in each other, which no lookup outside the
      batch could have done
    category: edge
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#found
        the two records of the batch in each other, which no lookup outside the
        batch could have done
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-change-events.integration.spec.js#found
        the two records in each other, which only a batch whose keys are written
        first can do
  - id: ATS-CRM-DQ-001-07
    title: Lost resemblance removes only open detected suggestions
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-07
    preconditions: 'A contact has open detected, dismissed and confirmed pairs.'
    steps: Remove its matching evidence and run detection.
    expected: Only its open detected pair disappears.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#removes
      exactly the pairs whose other record no longer scores
    category: transition
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#removes
        exactly the pairs whose other record no longer scores
      - >-
        services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#leaves
        the dismissed pair where it is: a dismissal does not expire because the
        evidence moved
      - >-
        services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#leaves
        the confirmed pair where it is, for the same reason
  - id: ATS-CRM-DQ-001-08
    title: Refreshing evidence preserves pair identity and review decisions
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-08
    preconditions: Prepare an existing pair and a dismissed variant.
    steps: Score them again using changed evidence.
    expected: >-
      Identity and initial detection time remain; score and band update while
      dismissal and its fingerprint persist.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#is
      the same row, with the same id: one pair is one candidate however often it
      is scored
    category: invariant
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#is
        the same row, with the same id: one pair is one candidate however often
        it is scored
      - >-
        services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#keeps
        the moment the pair was first detected, which no re-score owns
      - >-
        services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#leaves
        the pair dismissed: a decision is not undone by the evidence moving
  - id: ATS-CRM-DQ-001-09
    title: Linked employer details do not pair employees
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-09
    preconditions: Two contacts link their work phone and address from one organization.
    steps: Run detection for both contacts.
    expected: The linked details create no matching keys or candidate.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#keys
      neither the linked number nor the linked address’s postal code, which are
      the organization’s
    category: edge
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#keys
        neither the linked number nor the linked address’s postal code, which
        are the organization’s
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#pairs
        the two people on nothing their organization supplies
  - id: ATS-CRM-DQ-001-10
    title: Another workspace remains outside detection
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-12
    preconditions: Prepare a contact owned by a different workspace.
    steps: Request detection of that identity in the current workspace.
    expected: The pass returns and stores no matching record or pair.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#answers
      a pass over a record of ANOTHER tenant with nothing, the tenant being the
      execution’s
    category: boundary
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#answers
        a pass over a record of ANOTHER tenant with nothing, the tenant being
        the execution’s
  - id: ATS-CRM-DQ-001-11
    title: Imported duplicates reach the queue without delaying saves
    level: browser
    proves:
      - BR-CAP-CRM-DQ-001-01
      - BR-CAP-CRM-DQ-001-02
      - BR-CAP-CRM-DQ-001-07
    preconditions: Prepare a 500-person import containing fifty duplicates.
    steps: Import the records and monitor group creation.
    expected: >-
      Import timing remains acceptable and the resulting group totals match the
      fixture.
    negative: false
    data_needs: >-
      Provide fixtures for prepare a 500-person import containing fifty
      duplicates.
    bound_to:
      - TST-CRM-DQ-176
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0276.spec.ts#CRM-ACC-0276
    category: interaction
    execution_sources:
      - >-
        react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0276.spec.ts#CRM-ACC-0276
      - >-
        react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0231.spec.ts#CRM-ACC-0231
  - id: ATS-CRM-DQ-001-12
    title: >-
      Observe absent becoming open after qualifying detection or declined portal
      registration creates a pair
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-06
      - INV-DOM-CRM-DQ-001-07
    transition:
      model: STATE-CRM-DQ-001
      index: 1
      from: absent
      to: open
      guard: >-
        The records share an eligible key, or registration supplies a declined
        candidate.
      side_effects:
        - persist scored evidence and its fingerprint
        - refresh grouping with the pair write
    preconditions: >-
      Arrange absent standing with the transition guard satisfied: The records
      share an eligible key, or registration supplies a declined candidate.
    steps: Qualifying detection or declined portal registration creates a pair.
    expected: >-
      Read the open standing and inspect the associated changes: persist scored
      evidence and its fingerprint; refresh grouping with the pair write.
    negative: false
    data_needs: >-
      Fixtures for absent, the guard and the affected records; a fixed clock for
      time-dependent changes.
    source: >-
      services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#found
      the two records of the batch in each other, which no lookup outside the
      batch could have done
    design_sources:
      - STATE-CRM-DQ-001
    note: >-
      The design supplies this transition obligation. A runtime binding requires
      assertions for its guard, destination and associated writes in one
      sequence.
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-001-13
    title: >-
      Observe open becoming open after another detection pass finds the pair
      again
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-08
    transition:
      model: STATE-CRM-DQ-001
      index: 2
      from: open
      to: open
      guard: Shared eligible evidence still reaches the storage floor.
      side_effects:
        - replace scoring fields and evaluation time
        - 'preserve identity, origin and initial detection'
    preconditions: >-
      Arrange open standing with the transition guard satisfied: Shared eligible
      evidence still reaches the storage floor.
    steps: Another detection pass finds the pair again.
    expected: >-
      Read the open standing and inspect the associated changes: replace scoring
      fields and evaluation time; preserve identity, origin and initial
      detection.
    negative: false
    data_needs: >-
      Fixtures for open, the guard and the affected records; a fixed clock for
      time-dependent changes.
    source: >-
      services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#keeps
      the moment the pair was first detected, which no re-score owns
    design_sources:
      - STATE-CRM-DQ-001
    note: >-
      The design supplies this transition obligation. A runtime binding requires
      assertions for its guard, destination and associated writes in one
      sequence.
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-001-14
    title: >-
      Observe open becoming absent after detection no longer finds a qualifying
      comparison
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-07
    transition:
      model: STATE-CRM-DQ-001
      index: 3
      from: open
      to: absent
      guard: Only an open pair originating from detection can be retired.
      side_effects:
        - remove the pair
        - refresh affected groups and remove undersized components
    preconditions: >-
      Arrange open standing with the transition guard satisfied: Only an open
      pair originating from detection can be retired.
    steps: Detection no longer finds a qualifying comparison.
    expected: >-
      Read the absent standing and inspect the associated changes: remove the
      pair; refresh affected groups and remove undersized components.
    negative: false
    data_needs: >-
      Fixtures for open, the guard and the affected records; a fixed clock for
      time-dependent changes.
    source: >-
      services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#retired
      the pair the number alone joined, its only evidence being disqualified
    design_sources:
      - STATE-CRM-DQ-001
    note: >-
      The design supplies this transition obligation. A runtime binding requires
      assertions for its guard, destination and associated writes in one
      sequence.
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-001-15
    title: Reversed comparison input cannot create another pair
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-001-01
    preconditions: >-
      Two same-workspace contacts with reversed ordering and a duplicate
      comparison payload.
    steps: >-
      Insert the pair in both orders and attempt a duplicate direct database
      row.
    expected: One canonical pair is stored; duplicate direct insertion is refused.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to: []
    source: >-
      services-crm:modules/duplicates/db/duplicate-candidates.table.ts:candidateConstraints
    design_sources:
      - DOM-CRM-DQ-001
    execution_sources: []
    provenance: proposed
  - id: ATS-CRM-DQ-001-16
    title: Rescoring keeps the comparison’s original identity
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-001-04
    preconditions: 'A scored pair with recorded identity, origin and first-detection time.'
    steps: Score it again with different evidence and read its identity fields.
    expected: >-
      The original identity fields remain unchanged while the new scoring data
      is visible.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to: []
    source: >-
      services-crm:modules/duplicates/services/persistence/duplicate-candidates.ts:upsertDuplicateCandidates
    design_sources:
      - DOM-CRM-DQ-001
    execution_sources: []
    provenance: proposed
  - id: ATS-CRM-DQ-001-17
    title: Lost resemblance removes only the undecided detected pair
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-001-05
    preconditions: >-
      Three comparisons for a record: open detected, dismissed and manually
      confirmed.
    steps: >-
      Remove the other record from the set of qualifying scores and inspect all
      three comparisons.
    expected: Only the open detected comparison disappears.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to:
      - TST-CRM-DQ-180
    source: >-
      services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#removes
      exactly the pairs whose other record no longer scores
    design_sources:
      - DOM-CRM-DQ-001
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js#removes
        exactly the pairs whose other record no longer scores
    provenance: test
  - id: ATS-CRM-DQ-001-18
    title: A record in another workspace contributes no comparisons
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-001-14
    preconditions: A contact identity belonging only to another workspace.
    steps: Run detection under the current workspace context for that identity.
    expected: The pass returns no local matching work or comparison.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to:
      - TST-CRM-DQ-180
    source: >-
      services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#answers
      a pass over a record of ANOTHER tenant with nothing, the tenant being the
      execution’s
    design_sources:
      - DOM-CRM-DQ-001
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js#answers
        a pass over a record of ANOTHER tenant with nothing, the tenant being
        the execution’s
    provenance: test
  - id: ATS-CRM-DQ-001-19
    title: Duplicate-processing records do not acquire custom-value state
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-001-15
    preconditions: The declared matching and review record models.
    steps: >-
      Inspect their storage and registration declarations for a custom-value
      facet.
    expected: No custom-value state is declared for those processing records.
    negative: false
    data_needs: >-
      Records, versions and caller contexts owned by the run; transaction
      failure injection when the invariant concerns rollback.
    bound_to: []
    source: >-
      services-crm:modules/duplicates (no metadata object registration;
      db/*.table.ts declares no custom-value table)
    design_sources:
      - DOM-CRM-DQ-001
    execution_sources: []
    provenance: proposed
  - id: ATS-CRM-DQ-001-20
    title: Refresh a reviewed pair through scoring and re-checking
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-DQ-001-01
      - BR-CAP-CRM-DQ-001-10
      - BR-CAP-CRM-DQ-001-02
      - BR-CAP-CRM-DQ-001-03
      - BR-CAP-CRM-DQ-001-04
      - BR-CAP-CRM-DQ-001-05
      - BR-CAP-CRM-DQ-001-06
      - BR-CAP-CRM-DQ-001-07
      - BR-CAP-CRM-DQ-001-08
      - BR-CAP-CRM-DQ-001-09
      - BR-CAP-CRM-DQ-001-12
    exercises:
      - CAP-CRM-DQ-001
      - CAP-CRM-DQ-002
      - CAP-CRM-DQ-003
      - CAP-CRM-DQ-005
      - CAP-CRM-DQ-008
    workflow_sources:
      - WF-CRM-DQ-001
      - WF-CRM-DQ-002
    preconditions: >-
      Run-owned contact and organization records, the relevant staff permissions
      and the related state described by the sequence.
    steps: >-
      Create two comparable contacts, dismiss their pair, edit only a name, then
      re-check and add shared strong evidence. Read scores, standing and group
      membership after each pass.
    expected: >-
      The observed scores, reopening decision and review membership agree with
      the named rules.
    negative: false
    data_needs: >-
      An isolated workspace with related records and fixed timestamps; owned
      participant failure injection where requested.
    source: >-
      CAP-CRM-DQ-001; CAP-CRM-DQ-002; CAP-CRM-DQ-003; CAP-CRM-DQ-005;
      CAP-CRM-DQ-008; WF-CRM-DQ-001; WF-CRM-DQ-002
    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/tests/integration/services/detection/duplicate-change-events.integration.spec.js
      - >-
        modules/duplicates/tests/integration/services/detection/duplicate-detection.integration.spec.js
      - >-
        modules/duplicates/tests/integration/services/persistence/duplicate-candidates.integration.spec.js
      - >-
        modules/duplicates/tests/unit/services/detection/duplicate-change-events.spec.js
      - modules/duplicates/tests/unit/services/matching/match-keys.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-0231.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0276.spec.ts
    note: >-
      Bindings identify authored proof; empty bindings remain proposed and
      findings record known limitations.
coverage:
  rule: covered
  transition: covered
  validation: 'gap: FND-CRM-DQ-052'
  permission: not-applicable
  edge: covered
  failure: covered
  boundary: covered
  concurrency: 'gap: FND-CRM-DQ-052'
  invariant: covered
  interaction: covered
coverage_notes:
  validation: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  permission: >-
    This capability has no caller-facing permission; it runs within the
    authorized owner workflow.
  concurrency: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
permission_coverage: []
proof_matrix:
  - rule: BR-CAP-CRM-DQ-001-01
    scenarios:
      - ATS-CRM-DQ-001-01
      - ATS-CRM-DQ-001-11
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-02
    scenarios:
      - ATS-CRM-DQ-001-02
      - ATS-CRM-DQ-001-11
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-03
    scenarios:
      - ATS-CRM-DQ-001-03
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-04
    scenarios:
      - ATS-CRM-DQ-001-04
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-05
    scenarios:
      - ATS-CRM-DQ-001-05
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-06
    scenarios:
      - ATS-CRM-DQ-001-06
      - ATS-CRM-DQ-001-12
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-07
    scenarios:
      - ATS-CRM-DQ-001-07
      - ATS-CRM-DQ-001-11
      - ATS-CRM-DQ-001-14
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-08
    scenarios:
      - ATS-CRM-DQ-001-08
      - ATS-CRM-DQ-001-13
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-09
    scenarios:
      - ATS-CRM-DQ-001-09
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-10
    scenarios:
      - ATS-CRM-DQ-001-01
      - ATS-CRM-DQ-001-20
  - rule: BR-CAP-CRM-DQ-001-12
    scenarios:
      - ATS-CRM-DQ-001-10
      - ATS-CRM-DQ-001-20
interaction_coverage:
  related:
    - CAP-CRM-DQ-002
    - CAP-CRM-DQ-003
    - CAP-CRM-DQ-005
    - CAP-CRM-DQ-008
  workflow_sources:
    - WF-CRM-DQ-001
    - WF-CRM-DQ-002
  scenarios:
    - ATS-CRM-DQ-001-11
    - ATS-CRM-DQ-001-20
---

# Detect duplicate records after changes: 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-001-01` | `ATS-CRM-DQ-001-01`, `ATS-CRM-DQ-001-11`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-02` | `ATS-CRM-DQ-001-02`, `ATS-CRM-DQ-001-11`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-03` | `ATS-CRM-DQ-001-03`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-04` | `ATS-CRM-DQ-001-04`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-05` | `ATS-CRM-DQ-001-05`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-06` | `ATS-CRM-DQ-001-06`, `ATS-CRM-DQ-001-12`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-07` | `ATS-CRM-DQ-001-07`, `ATS-CRM-DQ-001-11`, `ATS-CRM-DQ-001-14`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-08` | `ATS-CRM-DQ-001-08`, `ATS-CRM-DQ-001-13`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-09` | `ATS-CRM-DQ-001-09`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-10` | `ATS-CRM-DQ-001-01`, `ATS-CRM-DQ-001-20` |
| `BR-CAP-CRM-DQ-001-12` | `ATS-CRM-DQ-001-10`, `ATS-CRM-DQ-001-20` |

## Interactions With Related Capabilities

Import the records and monitor group creation. Create two comparable contacts, dismiss their pair, edit only a name, then re-check and add shared strong evidence. Read scores, standing and group membership after each pass.

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.
