---
id: ATS-PFM-DJE-006
scope: CAP-PFM-DJE-006
product_area: platform
module: data-job-engine
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-DJE-006-01
    title: An intervening edit survives approval
    level: api
    proves:
      - BR-CAP-PFM-DJE-006-01
    preconditions: Validate a three-contact change and then edit one contact as a colleague.
    steps:
      - do: Approve the job.
        expect: The edited contact is reported as a conflict and preserved; the others change.
        provenance: test
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#freezes
          the version of each of the three contacts on the validated job, by item position
    expected: The edited contact is reported as a conflict and preserved; the others change.
    negative: true
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-120
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#freezes
      the version of each of the three contacts on the validated job, by item position
    category: concurrency
    binding_evidence:
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#freezes
        the version of each of the three contacts on the validated job, by item position
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#skips
        the contact that changed after the validation as a named conflict
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#leaves
        the colleague’s edit as they made it
  - id: ATS-PFM-DJE-006-02
    title: The dialog supports reviewed conflict correction
    level: browser
    proves:
      - BR-CAP-PFM-DJE-006-01
      - BR-CAP-PFM-DJE-006-04
    preconditions: Select 35 contacts and edit one between preview and approval.
    steps:
      - do: 'Apply, choose Revalidate Conflicts and approve the new preview.'
        expect: >-
          The first run reports 34 applied and a named, timed conflict; the reviewed correction then
          applies.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0103.spec.ts#DJE-ACC-0103
    expected: >-
      The first run reports 34 applied and a named, timed conflict; the reviewed correction then
      applies.
    negative: false
    data_needs: A prepared contact collection.
    bound_to:
      - TST-PFM-DJE-085
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0103.spec.ts#DJE-ACC-0103
    category: interaction
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0103.spec.ts#DJE-ACC-0103
  - id: ATS-PFM-DJE-006-03
    title: Explicit expected versions govern writes
    level: api
    proves:
      - BR-CAP-PFM-DJE-006-02
    preconditions: Prepare input with an expected version older than its record.
    steps:
      - do: Process the change.
        expect: The version conflict identifies the last editor and time without exposing field values.
        provenance: proposed
        source: 'services-crm:docs/data-jobs.md#What each contact''s outcome can be'
    expected: The version conflict identifies the last editor and time without exposing field values.
    negative: true
    data_needs: No additional fixture is needed.
    bound_to: []
    provenance: proposed
    source: 'services-crm:docs/data-jobs.md#What each contact''s outcome can be'
    category: validation
    binding_evidence: []
  - id: ATS-PFM-DJE-006-04
    title: Matching values do not become conflicts
    level: api
    proves:
      - BR-CAP-PFM-DJE-006-03
    preconditions: Have a colleague set the exact value the job requests.
    steps:
      - do: Apply the saved job.
        expect: The contact reports applied with unchanged detail.
        provenance: test
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#applies
          the contact whose colleague made the very change the job asks for, rather than calling it
          a conflict
    expected: The contact reports applied with unchanged detail.
    negative: false
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-120
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#applies
      the contact whose colleague made the very change the job asks for, rather than calling it a
      conflict
    category: edge
    binding_evidence:
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#applies
        the contact whose colleague made the very change the job asks for, rather than calling it a
        conflict
  - id: ATS-PFM-DJE-006-05
    title: Conflict correction creates a separate validation
    level: api
    proves:
      - BR-CAP-PFM-DJE-006-04
    preconditions: Complete a job with one conflict.
    steps:
      - do: 'Revalidate it, attempt revalidation of the unfinished correction, and retry the original.'
        expect: The first call creates a linked single-record validation; the other calls are refused.
        provenance: test
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#makes
          the revalidation a new validation of the one conflicted contact, linked to the job it
          corrects
    expected: The first call creates a linked single-record validation; the other calls are refused.
    negative: true
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-120
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#makes
      the revalidation a new validation of the one conflicted contact, linked to the job it corrects
    category: transition
    binding_evidence:
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#makes
        the revalidation a new validation of the one conflicted contact, linked to the job it
        corrects
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#refuses
        to revalidate the revalidation itself, which has not finished, by the engine’s code
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#refuses
        a retry of the finished job rather than writing over the edit
  - id: ATS-PFM-DJE-006-06
    title: The delivery policy governs staff-edit protection
    level: api
    proves:
      - BR-CAP-PFM-DJE-006-05
    preconditions: Edit a keyed record after its previous producer delivery.
    steps:
      - do: Send new input under reject and then overwrite policies.
        expect: Reject preserves the edit as a conflict; overwrite applies the producer’s input.
        provenance: test
        source: >-
          macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#refuses
          the delivery as a conflict and leaves the record alone
    expected: Reject preserves the edit as a conflict; overwrite applies the producer’s input.
    negative: true
    data_needs: A keyed record fixture.
    bound_to:
      - TST-PFM-DJE-029
      - TST-PFM-DJE-066
    provenance: test
    source: >-
      macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#refuses
      the delivery as a conflict and leaves the record alone
    category: rule
    binding_evidence:
      - >-
        macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#refuses
        the delivery as a conflict and leaves the record alone
      - >-
        macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#applies
        the delivery over the change when the job was submitted to overwrite
      - >-
        react-console:acceptance/crm/playwright/journeys/data-operations/CRM-ACC-0667.spec.ts#CRM-ACC-0667
  - id: ATS-PFM-DJE-006-07
    title: Patch revision ordering supports a second pass
    level: api
    proves:
      - BR-CAP-PFM-DJE-006-06
    preconditions: Prepare a keyed record at producer revision 10.
    steps:
      - do: Deliver patches at revision 9 and at revision 10.
        expect: >-
          The older patch is stale; the equal-revision patch can apply another part of that
          revision.
        provenance: test
        source: >-
          macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-patches.integration.spec.ts#skips
          a late patch file whose revision is older than the one applied, and writes nothing;
          macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-patches.integration.spec.ts#applies
          a patch of the revision already applied, which is a further part of that revision (a
          second pass)
    expected: The older patch is stale; the equal-revision patch can apply another part of that revision.
    negative: true
    data_needs: A keyed record fixture.
    bound_to:
      - TST-PFM-DJE-030
    provenance: test
    source: >-
      macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-patches.integration.spec.ts#skips
      a late patch file whose revision is older than the one applied, and writes nothing;
      macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-patches.integration.spec.ts#applies
      a patch of the revision already applied, which is a further part of that revision (a second
      pass)
    category: boundary
    binding_evidence:
      - >-
        macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-patches.integration.spec.ts#skips
        a late patch file whose revision is older than the one applied, and writes nothing
      - >-
        macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-patches.integration.spec.ts#applies
        a patch of the revision already applied, which is a further part of that revision (a second
        pass)
  - id: ATS-PFM-DJE-006-08
    title: A later edit changes the approved job's result
    category: interaction
    level: api
    exercises:
      - CAP-PFM-DJE-002
      - CAP-PFM-DJE-006
    proves:
      - BR-CAP-PFM-DJE-002-01
      - BR-CAP-PFM-DJE-002-02
      - BR-CAP-PFM-DJE-006-01
    preconditions: Prepare two contacts and a validated title change.
    steps:
      - do: Edit one contact after preview and approve the original fingerprint.
        expect: >-
          The edited contact remains intact with a conflict while the other receives the saved
          title.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#changes
          nothing while it is validating;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
          an apply of the validated update whose digest is not the one the validation answered;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#skips
          the contact that changed after the validation as a named conflict;
          services-crm:modules/data-jobs/services/operations/contact-update.ts:prevalidate
    expected: The edited contact remains intact with a conflict while the other receives the saved title.
    negative: true
    data_needs: Prepare two contacts and a validated title change.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#changes
      nothing while it is validating;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
      an apply of the validated update whose digest is not the one the validation answered;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#skips
      the contact that changed after the validation as a named conflict;
      services-crm:modules/data-jobs/services/operations/contact-update.ts:prevalidate
  - id: ATS-PFM-DJE-006-09
    title: An edit after restoration planning remains protected
    category: interaction
    level: api
    exercises:
      - CAP-PFM-DJE-006
      - CAP-PFM-DJE-008
    proves:
      - BR-CAP-PFM-DJE-006-01
      - BR-CAP-PFM-DJE-008-02
      - BR-CAP-PFM-DJE-008-03
    preconditions: Complete an update and plan its restoration using current versions.
    steps:
      - do: Edit a reversible contact after planning and approve the restoration.
        expect: >-
          The later edit survives as a changed-since conflict while other reversible contacts are
          restored.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#skips
          the contact that changed after the validation as a named conflict;
          services-crm:modules/data-jobs/services/operations/contact-update.ts:prevalidate;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-rollback.integration.spec.js#says
          which field changed since the job and when, without saying what it was changed to;
          macroservice-libraries:packages/data-jobs/src/tests/integration/rollback-and-retry.integration.spec.ts#refuses
          a rollback plan with an unversioned item, and writes no rollback job
    expected: >-
      The later edit survives as a changed-since conflict while other reversible contacts are
      restored.
    negative: true
    data_needs: Complete an update and plan its restoration using current versions.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#skips
      the contact that changed after the validation as a named conflict;
      services-crm:modules/data-jobs/services/operations/contact-update.ts:prevalidate;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-rollback.integration.spec.js#says
      which field changed since the job and when, without saying what it was changed to;
      macroservice-libraries:packages/data-jobs/src/tests/integration/rollback-and-retry.integration.spec.ts#refuses
      a rollback plan with an unversioned item, and writes no rollback job
  - id: ATS-PFM-DJE-006-10
    title: Reject policy preserves a staff correction in a later delivery
    category: interaction
    level: api
    exercises:
      - CAP-PFM-DJE-006
      - CAP-PFM-DJE-012
    proves:
      - BR-CAP-PFM-DJE-006-05
      - BR-CAP-PFM-DJE-006-07
      - BR-CAP-PFM-DJE-012-01
      - BR-CAP-PFM-DJE-012-03
    preconditions: Import a revisioned keyed record and make a staff correction.
    steps:
      - do: Send a newer producer revision under reject policy and inspect its mapping and record.
        expect: >-
          The delivery conflicts and preserves the staff correction; the producer-written version
          does not adopt the staff version.
        provenance: proposed
        source: >-
          macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#refuses
          the delivery as a conflict and leaves the record alone;
          macroservice-libraries:packages/data-jobs/README.md#Keyed writes and the ID crosswalk;
          services-crm:modules/data-jobs/tests/integration/services/operations/record-imports.integration.spec.js#skips
          every record of the same file delivered a second time, rather than making a second
          organization;
          macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#writes
          no crosswalk row for an item it refused, so the corrected delivery of that key is a create
    expected: >-
      The delivery conflicts and preserves the staff correction; the producer-written version does
      not adopt the staff version.
    negative: true
    data_needs: Import a revisioned keyed record and make a staff correction.
    bound_to: []
    provenance: proposed
    source: >-
      macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#refuses
      the delivery as a conflict and leaves the record alone;
      macroservice-libraries:packages/data-jobs/README.md#Keyed writes and the ID crosswalk;
      services-crm:modules/data-jobs/tests/integration/services/operations/record-imports.integration.spec.js#skips
      every record of the same file delivered a second time, rather than making a second
      organization;
      macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#writes
      no crosswalk row for an item it refused, so the corrected delivery of that key is a create
evidence:
  - >-
    Reviewed evidence: macroservice-libraries (54536a44): README.md (Versions; Keyed writes);
    src/version-capture.ts, revalidate-data-job-conflicts.ts, keyed-item-decision.ts; tests
    version-capture.integration.spec.ts, keyed-data-jobs.integration.spec.ts,
    keyed-patches.integration.spec.ts.
  - >-
    Reviewed evidence: services-crm (a8d1364f): docs/data-jobs.md (Concurrent edits);
    services/operations/captured-versions.ts, version-conflicts.ts; tests
    contact-update-versions.integration.spec.js, organization-update-versions.integration.spec.js,
    organization-update-conflicts.integration.spec.js.
  - >-
    Reviewed evidence: react-console (baf6dae3):
    acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0103.spec.ts;
    acceptance/crm/journeys/data-operations/CRM-ACC-0651, 0667.
  - >-
    Testing back-fill: related capability rules, domain invariants, state transitions and crossing
    workflows at the pinned source revisions.
coverage:
  rule: covered
  transition: 'gap: FND-PFM-DJE-066'
  validation: covered
  permission: 'gap: FND-PFM-DJE-066'
  edge: covered
  failure: 'gap: FND-PFM-DJE-066'
  boundary: covered
  concurrency: covered
  invariant: 'gap: FND-PFM-DJE-066'
  interaction: covered
coverage_notes:
  transition: >-
    Selected lifecycle examples do not cover every applicable object and batch transition. The
    linked finding retains the remaining matrix.
  execution: >-
    Covered means a specification scenario exists. Proposed scenarios and registered suites with no
    run result do not establish executed conformance.
related:
  - CAP-PFM-DJE-002
  - CAP-PFM-DJE-008
  - CAP-PFM-DJE-012
workflows:
  - WF-PFM-DJE-002
  - WF-PFM-DJE-006
  - WF-PFM-DJE-007
coverage_evidence:
  - rule: BR-CAP-PFM-DJE-006-01
    scenarios:
      - ATS-PFM-DJE-006-01
      - ATS-PFM-DJE-006-02
      - ATS-PFM-DJE-006-08
      - ATS-PFM-DJE-006-09
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#skips
      the contact that changed after the validation as a named conflict;
      services-crm:modules/data-jobs/services/operations/contact-update.ts:prevalidate
  - rule: BR-CAP-PFM-DJE-006-02
    scenarios:
      - ATS-PFM-DJE-006-03
    provenance: proposed
    source: 'services-crm:docs/data-jobs.md#What each contact''s outcome can be'
  - rule: BR-CAP-PFM-DJE-006-03
    scenarios:
      - ATS-PFM-DJE-006-04
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#applies
      the contact whose colleague made the very change the job asks for, rather than calling it a
      conflict
  - rule: BR-CAP-PFM-DJE-006-04
    scenarios:
      - ATS-PFM-DJE-006-02
      - ATS-PFM-DJE-006-05
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#makes
      the revalidation a new validation of the one conflicted contact, linked to the job it corrects
  - rule: BR-CAP-PFM-DJE-006-05
    scenarios:
      - ATS-PFM-DJE-006-06
      - ATS-PFM-DJE-006-10
    provenance: proposed
    source: >-
      macroservice-libraries:packages/data-jobs/src/tests/integration/keyed-data-jobs.integration.spec.ts#refuses
      the delivery as a conflict and leaves the record alone
  - rule: BR-CAP-PFM-DJE-006-06
    scenarios:
      - ATS-PFM-DJE-006-07
    provenance: proposed
    source: 'macroservice-libraries:packages/data-jobs/src/keyed-item-decision.ts:decideKeyedItem'
---

# Preserve intervening edits during bulk changes: Capability Test Specification

## Coverage

The structured coverage rows link required rules to their scenarios. A covered category has a defined check; executable coverage and successful execution require separate evidence. The category map keeps incomplete lifecycle matrices and other missing checks visible as findings.

## Interactions With Related Capabilities

A later edit changes the approved job's result. An edit after restoration planning remains protected. Reject policy preserves a staff correction in a later delivery. The interaction scenarios use the related capabilities' rule references and identify the shared fixture and observable outcome.
