---
id: ATS-CRM-DQ-012
scope: CAP-CRM-DQ-012
product_area: crm
module: data-quality
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-DQ-012-01
    title: Participant validation prevents invalid plans
    level: api
    proves:
      - BR-CAP-CRM-DQ-012-01
    preconditions: Prepare workspace records and an absorbed identity.
    steps: >-
      Try one participant, eleven, a repeat, an outside survivor and the
      absorbed record.
    expected: Invalid selections fail and the absorbed participant reports its survivor.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/persistence/record-merge-plans.integration.spec.js#refuses
      a plan of one record, which is not a merge, as ObjectInvalid naming the
      field
    category: boundary
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/record-merge-plans.integration.spec.js#refuses
        a plan of one record, which is not a merge, as ObjectInvalid naming the
        field
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/record-merge-plans.integration.spec.js#refuses
        more records than a merge takes
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/record-merge-plans.integration.spec.js#refuses
        the same record named twice
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/record-merge-plans.integration.spec.js#refuses
        a survivor that is not one of the records being merged
      - >-
        services-crm:modules/merges/tests/integration/services/merges/merge-execution.integration.spec.js#refuses
        to plan a merge of an id it has merged away, naming the merged record
  - id: ATS-CRM-DQ-012-02
    title: Plan authority requires the type's complete permission pair
    level: api
    proves:
      - BR-CAP-CRM-DQ-012-02
    preconditions: >-
      Prepare contact-only authority, organization merge-only, read-only and
      merge-without-read callers.
    steps: Request contact and organization plans.
    expected: Every incomplete type-specific read-and-merge pair is refused.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-183
    provenance: test
    source: >-
      services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#refuses the plan
      to a caller who may merge contacts but not organizations
    category: permission
    execution_sources:
      - >-
        services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#refuses the
        plan to a caller who may merge contacts but not organizations
      - >-
        services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#refuses the
        plan of contacts to a caller who may merge organizations alone
      - >-
        services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#refuses an
        organization plan to a caller who may read organizations but not merge
        them
      - >-
        services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#refuses every
        plan route to a caller who may read contacts but not merge them
  - id: ATS-CRM-DQ-012-03
    title: Survivor ranking explains the winning signal
    level: unit
    proves:
      - BR-CAP-CRM-DQ-012-03
      - BR-CAP-CRM-DQ-012-05
    preconditions: >-
      Prepare participants distinguished by login, integration identity, inbound
      references and creation age.
    steps: Compute the recommendation.
    expected: >-
      Signals apply in that order, reasons use record names, age-only ranking is
      weak and recency or completeness does not win.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
        the only participant a portal login names
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
        the only participant an integration addresses, when no login separates
        them
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
        the participant the most rows outside the merge name, when no identity
        separates them
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
        the record created first, when nothing else separates them
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#is
        not decisive when the top two are still level after the references rule
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#never
        keeps the newest record, whatever it holds beyond the rules
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#never
        hands a reader a record id, the records being named by their names
        instead
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
      the only participant a portal login names
    category: rule
    execution_sources:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
        the only participant a portal login names
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
        the only participant an integration addresses, when no login separates
        them
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
        the participant the most rows outside the merge name, when no identity
        separates them
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#keeps
        the record created first, when nothing else separates them
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#is
        not decisive when the top two are still level after the references rule
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#never
        keeps the newest record, whatever it holds beyond the rules
      - >-
        services-crm:modules/merges/tests/unit/services/planning/survivor-recommendation.spec.js#never
        hands a reader a record id, the records being named by their names
        instead
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-012-04
    title: Administrators can override the survivor suggestion
    level: api
    proves:
      - BR-CAP-CRM-DQ-012-04
    preconditions: A named participant differs from the recommendation.
    steps: Create plans with and without an explicit survivor.
    expected: 'The named selection remains, while omission uses the recommendation.'
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/survivor-recommendation.integration.spec.js#leaves
      the survivor the request named alone, the recommendation being advisory
    category: rule
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/merges/survivor-recommendation.integration.spec.js#leaves
        the survivor the request named alone, the recommendation being advisory
      - >-
        services-crm:modules/merges/tests/integration/services/merges/survivor-recommendation.integration.spec.js#is
        the survivor of a plan that named none, the default being the
        recommendation
  - id: ATS-CRM-DQ-012-05
    title: Participant changes preserve only applicable decisions
    level: api
    proves:
      - BR-CAP-CRM-DQ-012-08
    preconditions: A three-record plan holds decisions.
    steps: Remove one participant and read again after data changes.
    expected: >-
      Two participants remain and invalidated decisions are removed with
      explanations.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-183
    provenance: test
    source: >-
      services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#answers the
      change with the two records that are left, in record_ids and in records
    category: transition
    execution_sources:
      - >-
        services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#answers the
        change with the two records that are left, in record_ids and in records
      - >-
        services-crm:modules/merges/tests/unit/services/planning/merge-decisions.spec.js#is
        dropped and reported when the plan is simply read again after the data
        moved on
  - id: ATS-CRM-DQ-012-06
    title: The expiry sweep respects stored deadlines
    level: api
    proves:
      - BR-CAP-CRM-DQ-012-10
    preconditions: >-
      Create overdue undecided and blocked plans, a completed plan and a ready
      plan whose stored deadline is later.
    steps: Run the sweep at a fixed time and repeat it.
    expected: >-
      The overdue undecided and blocked plans are expired; the completed and
      not-yet-due plans retain their standing; repetition expires nothing.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/merge-plan-expiry.integration.spec.js#expires
      the plan whose seven days are up, which is what takes it off the reader’s
      list
    category: transition
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/merges/merge-plan-expiry.integration.spec.js#expires
        the plan whose seven days are up, which is what takes it off the
        reader’s list
      - >-
        services-crm:modules/merges/tests/integration/services/merges/merge-plan-expiry.integration.spec.js#expires
        a blocked plan too, a plan nobody cleared being as abandoned as one
        nobody decided
      - >-
        services-crm:modules/merges/tests/integration/services/merges/merge-plan-expiry.integration.spec.js#leaves
        a plan that has been executed, whose merge happened and is nothing to
        close out
      - >-
        services-crm:modules/merges/tests/integration/services/persistence/record-merge-plans.integration.spec.js#gives
        it the seven days a plan lives for when nobody states another
    proof_limitations:
      - Renewal after editing is not established.
      - An executing plan can also be expired; the rule and design disagree.
  - id: ATS-CRM-DQ-012-07
    title: Queue launch displays survivor reasoning
    level: browser
    proves:
      - BR-CAP-CRM-DQ-012-03
      - BR-CAP-CRM-DQ-012-04
    preconditions: >-
      Prepare groups with login, external-identity, reference and age
      distinctions.
    steps: Launch their plans from the queue.
    expected: The displayed recommendation and explanation follow the recorded ranking.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-176
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0248.spec.ts#CRM-ACC-0248
    category: interaction
    execution_sources:
      - >-
        react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0248.spec.ts#CRM-ACC-0248
      - >-
        react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0285.spec.ts#CRM-ACC-0285
  - id: ATS-CRM-DQ-012-08
    title: >-
      Observe needs_decisions becoming expired after the expiry sweep finds an
      overdue working preview
    category: transition
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-12
    transition:
      model: STATE-CRM-DQ-004
      index: 11
      from: needs_decisions
      to: expired
      guard: Only executed and already-expired plans are excluded.
      side_effects:
        - mark expiry and advance the version
    preconditions: >-
      Arrange needs_decisions standing with the transition guard satisfied: Only
      executed and already-expired plans are excluded.
    steps: The expiry sweep finds an overdue working preview.
    expected: >-
      Read the expired standing and inspect the associated changes: mark expiry
      and advance the version.
    negative: false
    data_needs: >-
      Fixtures for needs_decisions, the guard and the affected records; a fixed
      clock for time-dependent changes.
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/merge-plan-expiry.integration.spec.js#expires
      a blocked plan too, a plan nobody cleared being as abandoned as one nobody
      decided
    design_sources:
      - STATE-CRM-DQ-004
    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
    intent_alignment: >-
      The scenario records stored-deadline expiry in the design, including
      executing standing. It does not prove the capability rule’s last-change
      lifetime; the existing contradiction remains open.
    finding: FND-CRM-DQ-006
    execution_sources: []
  - id: ATS-CRM-DQ-012-09
    title: >-
      Observe ready becoming expired after the expiry sweep finds an overdue
      ready preview
    category: transition
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-12
    transition:
      model: STATE-CRM-DQ-004
      index: 12
      from: ready
      to: expired
      guard: Only executed and already-expired plans are excluded.
      side_effects:
        - mark expiry
    preconditions: >-
      Arrange ready standing with the transition guard satisfied: Only executed
      and already-expired plans are excluded.
    steps: The expiry sweep finds an overdue ready preview.
    expected: 'Read the expired standing and inspect the associated changes: mark expiry.'
    negative: false
    data_needs: >-
      Fixtures for ready, the guard and the affected records; a fixed clock for
      time-dependent changes.
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/merge-plan-expiry.integration.spec.js#expires
      a blocked plan too, a plan nobody cleared being as abandoned as one nobody
      decided
    design_sources:
      - STATE-CRM-DQ-004
    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
    intent_alignment: >-
      The scenario records stored-deadline expiry in the design, including
      executing standing. It does not prove the capability rule’s last-change
      lifetime; the existing contradiction remains open.
    finding: FND-CRM-DQ-006
    execution_sources: []
  - id: ATS-CRM-DQ-012-10
    title: >-
      Observe blocked becoming expired after the expiry sweep finds an overdue
      blocked preview
    category: transition
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-12
    transition:
      model: STATE-CRM-DQ-004
      index: 13
      from: blocked
      to: expired
      guard: Only executed and already-expired plans are excluded.
      side_effects:
        - mark expiry
    preconditions: >-
      Arrange blocked standing with the transition guard satisfied: Only
      executed and already-expired plans are excluded.
    steps: The expiry sweep finds an overdue blocked preview.
    expected: 'Read the expired standing and inspect the associated changes: mark expiry.'
    negative: false
    data_needs: >-
      Fixtures for blocked, the guard and the affected records; a fixed clock
      for time-dependent changes.
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/merge-plan-expiry.integration.spec.js#expires
      a blocked plan too, a plan nobody cleared being as abandoned as one nobody
      decided
    design_sources:
      - STATE-CRM-DQ-004
    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
    intent_alignment: >-
      The scenario records stored-deadline expiry in the design, including
      executing standing. It does not prove the capability rule’s last-change
      lifetime; the existing contradiction remains open.
    finding: FND-CRM-DQ-006
    execution_sources: []
  - id: ATS-CRM-DQ-012-11
    title: >-
      Observe executing becoming expired after the expiry sweep finds an overdue
      active attempt’s plan
    category: transition
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-12
    transition:
      model: STATE-CRM-DQ-004
      index: 14
      from: executing
      to: expired
      guard: Executing standing is not excluded by the sweep.
      side_effects:
        - mark expiry while the attempt may still execute
    preconditions: >-
      Arrange executing standing with the transition guard satisfied: Executing
      standing is not excluded by the sweep.
    steps: The expiry sweep finds an overdue active attempt’s plan.
    expected: >-
      Read the expired standing and inspect the associated changes: mark expiry
      while the attempt may still execute.
    negative: false
    data_needs: >-
      Fixtures for executing, the guard and the affected records; a fixed clock
      for time-dependent changes.
    source: >-
      services-crm:modules/merges/services/persistence/record-merge-plans.ts:expireRecordMergePlans
    design_sources:
      - STATE-CRM-DQ-004
    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
    intent_alignment: >-
      The scenario records stored-deadline expiry in the design, including
      executing standing. It does not prove the capability rule’s last-change
      lifetime; the existing contradiction remains open.
    finding: FND-CRM-DQ-006
    execution_sources: []
  - id: ATS-CRM-DQ-012-12
    title: Invalid participant lists cannot create a preview
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-01
    preconditions: >-
      Lists of one and eleven records, a repeated record and an outside
      survivor.
    steps: Create each proposed plan and inspect saved previews.
    expected: Every invalid list is refused without a saved plan.
    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/merges/services/persistence/record-merge-plans.ts:createRecordMergePlan;
      modules/merges/db/record-merge-plans.table.ts:record_merge_plans_record_ids_check
    design_sources:
      - DOM-CRM-DQ-003
    execution_sources: []
    provenance: proposed
  - id: ATS-CRM-DQ-012-13
    title: A preview and its material hash cannot be stored separately
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-02
    preconditions: Direct plan rows containing only a computed preview or only its hash.
    steps: Attempt each incomplete database insert.
    expected: Both inserts are refused by the database.
    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/merges/db/record-merge-plans.table.ts:record_merge_plans_plan_hash_check
    design_sources:
      - DOM-CRM-DQ-003
    execution_sources: []
    provenance: proposed
  - id: ATS-CRM-DQ-012-14
    title: A settled preview refuses another edit
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-06
    preconditions: 'Plans in executing, executed and expired standing.'
    steps: Try an answer or participant edit at the current version of each plan.
    expected: Every edit is refused and the stored preview stays unchanged.
    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/merges/services/merges/merge-plans.ts:assertPlanIsOpen
    design_sources:
      - DOM-CRM-DQ-003
    execution_sources: []
    provenance: proposed
  - id: ATS-CRM-DQ-012-15
    title: Editing does not renew the stored expiry deadline
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-12
    preconditions: A plan near its stored creation-based expiry deadline.
    steps: 'Edit the plan, read its deadline and sweep after that stored instant.'
    expected: The deadline is unchanged and the sweep expires the edited plan.
    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/merges/services/persistence/record-merge-plans.ts:defaultExpiry,
      updateRecordMergePlan, expireRecordMergePlans
    design_sources:
      - DOM-CRM-DQ-003
    execution_sources: []
    provenance: proposed
  - id: ATS-CRM-DQ-012-16
    title: Authority for only the other record type cannot create a plan
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-13
    preconditions: >-
      A context qualified for contact merging and an organization participant
      list.
    steps: Create the organization plan with the contact context.
    expected: The route refuses the plan before saving it.
    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-183
    source: >-
      services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#refuses the plan
      to a caller who may merge contacts but not organizations
    design_sources:
      - DOM-CRM-DQ-003
    execution_sources:
      - >-
        services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#refuses the
        plan to a caller who may merge contacts but not organizations
    provenance: test
  - id: ATS-CRM-DQ-012-17
    title: A preview remains inaccessible in another workspace
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-DQ-003-14
    preconditions: >-
      A saved plan and a current-version edit attempted through a different
      workspace.
    steps: Read and update the plan using the other workspace context.
    expected: The plan is unavailable and its records remain unchanged.
    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:db/row-level-security.ts (record_merge_plans forced workspace
      policy)
    design_sources:
      - DOM-CRM-DQ-003
    execution_sources: []
    provenance: proposed
  - id: ATS-CRM-DQ-012-18
    title: Participant selection changes preview decisions before execution
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-DQ-012-01
      - BR-CAP-CRM-DQ-012-02
      - BR-CAP-CRM-DQ-012-03
      - BR-CAP-CRM-DQ-012-05
      - BR-CAP-CRM-DQ-012-04
      - BR-CAP-CRM-DQ-012-08
      - BR-CAP-CRM-DQ-012-10
    exercises:
      - CAP-CRM-DQ-012
      - CAP-CRM-DQ-010
      - CAP-CRM-DQ-013
      - CAP-CRM-DQ-016
    workflow_sources:
      - WF-CRM-DQ-005
      - WF-CRM-DQ-007
    preconditions: >-
      Run-owned contact and organization records, the relevant staff permissions
      and the related state described by the sequence.
    steps: >-
      Launch from a record, choose a different survivor, answer a conflict,
      remove a participant and execute the refreshed preview.
    expected: >-
      The plan retains only applicable decisions and execution uses the latest
      reviewed participants.
    negative: false
    data_needs: >-
      An isolated workspace with related records and fixed timestamps; owned
      participant failure injection where requested.
    source: >-
      CAP-CRM-DQ-012; CAP-CRM-DQ-010; CAP-CRM-DQ-013; CAP-CRM-DQ-016;
      WF-CRM-DQ-005; WF-CRM-DQ-007
    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/merges/tests/e2e/merges.e2e.spec.js
      - >-
        modules/merges/tests/integration/services/merges/merge-execution.integration.spec.js
      - >-
        modules/merges/tests/integration/services/merges/merge-plan-expiry.integration.spec.js
      - >-
        modules/merges/tests/integration/services/merges/survivor-recommendation.integration.spec.js
      - >-
        modules/merges/tests/integration/services/persistence/record-merge-plans.integration.spec.js
      - modules/merges/tests/unit/services/planning/merge-decisions.spec.js
      - >-
        modules/merges/tests/unit/services/planning/survivor-recommendation.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-0248.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0285.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-063'
  permission: covered
  edge: 'gap: FND-CRM-DQ-063'
  failure: 'gap: FND-CRM-DQ-063'
  boundary: covered
  concurrency: 'gap: FND-CRM-DQ-063'
  invariant: covered
  interaction: covered
coverage_notes:
  validation: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  edge: >-
    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.contacts.merge
    scenario_ids:
      - ATS-CRM-DQ-012-02
    finding: FND-CRM-DQ-063
  - key: crm.contacts.read
    scenario_ids:
      - ATS-CRM-DQ-012-02
    finding: FND-CRM-DQ-063
  - key: crm.organizations.merge
    scenario_ids:
      - ATS-CRM-DQ-012-02
    finding: FND-CRM-DQ-063
  - key: crm.organizations.read
    scenario_ids:
      - ATS-CRM-DQ-012-02
    finding: FND-CRM-DQ-063
proof_matrix:
  - rule: BR-CAP-CRM-DQ-012-01
    scenarios:
      - ATS-CRM-DQ-012-01
      - ATS-CRM-DQ-012-18
  - rule: BR-CAP-CRM-DQ-012-02
    scenarios:
      - ATS-CRM-DQ-012-02
      - ATS-CRM-DQ-012-18
  - rule: BR-CAP-CRM-DQ-012-03
    scenarios:
      - ATS-CRM-DQ-012-03
      - ATS-CRM-DQ-012-07
      - ATS-CRM-DQ-012-18
  - rule: BR-CAP-CRM-DQ-012-04
    scenarios:
      - ATS-CRM-DQ-012-04
      - ATS-CRM-DQ-012-07
      - ATS-CRM-DQ-012-18
  - rule: BR-CAP-CRM-DQ-012-05
    scenarios:
      - ATS-CRM-DQ-012-03
      - ATS-CRM-DQ-012-18
  - rule: BR-CAP-CRM-DQ-012-08
    scenarios:
      - ATS-CRM-DQ-012-05
      - ATS-CRM-DQ-012-18
  - rule: BR-CAP-CRM-DQ-012-10
    scenarios:
      - ATS-CRM-DQ-012-06
      - ATS-CRM-DQ-012-18
interaction_coverage:
  related:
    - CAP-CRM-DQ-010
    - CAP-CRM-DQ-013
    - CAP-CRM-DQ-016
  workflow_sources:
    - WF-CRM-DQ-005
    - WF-CRM-DQ-007
  scenarios:
    - ATS-CRM-DQ-012-07
    - ATS-CRM-DQ-012-18
---

# Prepare a merge and choose its survivor: 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-012-01` | `ATS-CRM-DQ-012-01`, `ATS-CRM-DQ-012-18` |
| `BR-CAP-CRM-DQ-012-02` | `ATS-CRM-DQ-012-02`, `ATS-CRM-DQ-012-18` |
| `BR-CAP-CRM-DQ-012-03` | `ATS-CRM-DQ-012-03`, `ATS-CRM-DQ-012-07`, `ATS-CRM-DQ-012-18` |
| `BR-CAP-CRM-DQ-012-04` | `ATS-CRM-DQ-012-04`, `ATS-CRM-DQ-012-07`, `ATS-CRM-DQ-012-18` |
| `BR-CAP-CRM-DQ-012-05` | `ATS-CRM-DQ-012-03`, `ATS-CRM-DQ-012-18` |
| `BR-CAP-CRM-DQ-012-08` | `ATS-CRM-DQ-012-05`, `ATS-CRM-DQ-012-18` |
| `BR-CAP-CRM-DQ-012-10` | `ATS-CRM-DQ-012-06`, `ATS-CRM-DQ-012-18` |

## Interactions With Related Capabilities

Launch their plans from the queue. Launch from a record, choose a different survivor, answer a conflict, remove a participant and execute the refreshed preview.

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.
