---
id: ATS-PFM-NOT-005
scope: CAP-PFM-NOT-005
product_area: platform
module: notifications
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-NOT-005-01
    title: Collapse matching bursts while separating other events
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-01
    preconditions: Prepare a definition with the default window.
    steps: >-
      Assign the identical responsibility to Jane five times within two minutes;
      repeat with another record, another person and a zero window.
    expected: >-
      Five contributions share one item and its count; unmatched records and
      recipients receive separate items.
    negative: false
    data_needs: Use only records created and owned by this suite.
    bound_to:
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
        five requests into one notification carrying the latest data and the
        count
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#does
        not fold a request about another record
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#does
        not fold a request for another person
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#does
        not fold when the definition switches collapsing off
      - >-
        services-platform:modules/notifications/tests/unit/collapsing.spec.js#takes
        in an instance created within the definition’s window
      - >-
        react-console:acceptance/notifications/playwright/journeys/pipeline/NT-ACC-0205.spec.ts#NT-ACC-0205
      - TST-PFM-NOT-016
      - TST-PFM-NOT-077
      - TST-PFM-NOT-106
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
      five requests into one notification carrying the latest data and the count
    category: rule
    binding_scope: >-
      Each binding supplies its own assertions; the aggregate references do not
      imply that one executable file proves every step.
  - id: ATS-PFM-NOT-005-02
    title: Create a fresh item after reading or archiving
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-02
    preconditions: Prepare a earlier notice inside the window.
    steps: >-
      Retrieve it, next repeat; archive it, next repeat; supersede it, next
      repeat.
    expected: >-
      Each subsequent request creates another unread notice rather than changing
      the old item.
    negative: false
    data_needs: Use only records created and owned by this suite.
    bound_to:
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#makes
        a new, unread notification when the one it would fold into was read
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#makes
        a new notification when the one it would fold into was archived
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#does
        not fold a request into an instance that was superseded
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#still
        folds into a notification that is unread and unarchived
      - TST-PFM-NOT-077
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#makes
      a new, unread notification when the one it would fold into was read
    category: edge
    binding_scope: >-
      Each binding supplies its own assertions; the aggregate references do not
      imply that one executable file proves every step.
  - id: ATS-PFM-NOT-005-03
    title: Separate explicit resource scopes
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-03
    preconditions: Use matching responsibility assignments scoped to two distinct units.
    steps: Submit both assignments before the collapse interval ends.
    expected: >-
      Each unit has its own notice; an unscoped contribution can join a
      compatible scoped item.
    negative: false
    data_needs: Use only records created and owned by this suite.
    bound_to:
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
        requests of the same scope and keeps requests of another scope apart
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
        a request that names no scope into one that does, and the other way
      - TST-PFM-NOT-077
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
      requests of the same scope and keeps requests of another scope apart
    category: boundary
    binding_scope: >-
      Each binding supplies its own assertions; the aggregate references do not
      imply that one executable file proves every step.
  - id: ATS-PFM-NOT-005-04
    title: Retain latest contribution details and bounded lineage
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-04
    preconditions: Prepare a notice that folded requests.
    steps: >-
      Add more contributions, replaying one and exceeding fifty distinct
      requests overall.
    expected: >-
      The item uses the latest data, retains each contribution once and keeps
      only the latest fifty references.
    negative: false
    data_needs: Use only records created and owned by this suite.
    bound_to:
      - >-
        services-platform:modules/notifications/tests/unit/collapsing.spec.js#remembers
        the requests an instance took in, oldest first
      - >-
        services-platform:modules/notifications/tests/unit/collapsing.spec.js#remembers
        a request once, however often it is folded in
      - >-
        services-platform:modules/notifications/tests/unit/collapsing.spec.js#keeps
        the newest fifty and drops the oldest
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
        five requests into one notification carrying the latest data and the
        count
      - TST-PFM-NOT-077
      - TST-PFM-NOT-106
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/unit/collapsing.spec.js#remembers
      the requests an instance took in, oldest first
    category: boundary
    binding_scope: >-
      Each binding supplies its own assertions; the aggregate references do not
      imply that one executable file proves every step.
  - id: ATS-PFM-NOT-005-05
    title: Serialize matching collapse identities
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-05
      - INV-DOM-PFM-NOT-003-12
    preconditions: >-
      Prepare ten matching identity requests and a request with a different
      collapse identity.
    steps: Dispatch them at the identical moment.
    expected: >-
      Nine matching contributions share one item; a distinct identity acquires a
      separate transaction lock.
    negative: false
    data_needs: Use only records created and owned by this suite.
    bound_to:
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
        ten requests dispatched at the same moment into one notification of
        collapsed count nine
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#does
        not make one identity wait for the lock another holds
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#makes
        a request for the identity another transaction holds wait until it
        commits
      - TST-PFM-NOT-077
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
      ten requests dispatched at the same moment into one notification of
      collapsed count nine
    category: concurrency
    binding_scope: >-
      Each binding supplies its own assertions; the aggregate references do not
      imply that one executable file proves every step.
    invariant_source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
      ten requests dispatched at the same moment into one notification of
      collapsed count nine
  - id: ATS-PFM-NOT-005-06
    title: Withdraw contributions without losing remaining work
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-06
    preconditions: Prepare a notice that folded three requests.
    steps: Cancel the first; next the newest; next the rest.
    expected: >-
      The count decreases, remaining renderable content replaces the newest
      withdrawn content, and removing the final contribution supersedes the
      item.
    negative: false
    data_needs: Use only records created and owned by this suite.
    bound_to:
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#keeps
        the notification when the first of its requests ends, handing it to the
        next and dropping the count
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#renders
        the message again from the newest request left when the newest ends
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#keeps
        the notification when a request it only folded ends, and supersedes it
        when the last one ends
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#withdraws
        only the notice of the assignment that ended when two units were told
        apart
      - TST-PFM-NOT-077
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#keeps
      the notification when the first of its requests ends, handing it to the
      next and dropping the count
    category: transition
    binding_scope: >-
      Each binding supplies its own assertions; the aggregate references do not
      imply that one executable file proves every step.
  - id: ATS-PFM-NOT-005-07
    title: Deduplicate occurrence notices
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-07
      - INV-DOM-PFM-NOT-003-03
    preconditions: >-
      Prepare two independently submitted requests identifying the same
      occurrence.
    steps: Process both occurrence requests.
    expected: Every recipient has at most one notice for the occurrence.
    negative: false
    data_needs: Use only records created and owned by this suite.
    bound_to:
      - >-
        services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js#makes
        one instance for one occurrence however many requests name it
      - >-
        services-platform:modules/notifications/tests/integration/db/notification-instances.table.integration.spec.js#holds
        one key per tenant across months: the key table conflicts on the same
        key in two months
      - TST-PFM-NOT-070
      - TST-PFM-NOT-079
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js#makes
      one instance for one occurrence however many requests name it
    category: invariant
    binding_scope: >-
      Each binding supplies its own assertions; the aggregate references do not
      imply that one executable file proves every step.
    invariant_source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js#makes
      one instance for one occurrence however many requests name it
  - id: ATS-PFM-NOT-005-08
    title: Collapse a burst through the pipeline
    level: api
    proves:
      - AS-JNY-PFM-NOT-005-03
    preconditions: Use five assignment events occurring within a two-minute interval.
    steps: Execute the full notification processing path.
    expected: The burst produces one notice displaying its contribution count.
    negative: false
    data_needs: The journey's own personas and Northeast unit.
    bound_to:
      - >-
        react-console:acceptance/notifications/playwright/journeys/pipeline/NT-ACC-0205.spec.ts#NT-ACC-0205
      - TST-PFM-NOT-016
    provenance: test
    source: >-
      react-console:acceptance/notifications/playwright/journeys/pipeline/NT-ACC-0205.spec.ts#NT-ACC-0205
    category: interaction
    binding_scope: >-
      Each binding supplies its own assertions; the aggregate references do not
      imply that one executable file proves every step.
  - id: ATS-PFM-NOT-005-09
    title: Retain content when replacement rendering is unavailable
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-08
    preconditions: >-
      Prepare a live folded notice whose definition has a link field, and
      another whose recipient loses eligibility.
    steps: Withdraw the newest contributing request from each notice.
    expected: >-
      Contribution count and ownership change while the existing rendered
      wording remains visible.
    negative: false
    data_needs: >-
      A live folded notice whose definition has a link field, and another whose
      recipient loses eligibility.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/notifications/services/orchestration/orchestrate-request.ts:rerenderMessage
    category: edge
  - id: ATS-PFM-NOT-005-10
    title: Read and withdrawal actions change subsequent folding
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-NOT-005-06
    exercises:
      - CAP-PFM-NOT-005
      - CAP-PFM-NOT-006
      - CAP-PFM-NOT-009
    preconditions: Give Jane two same-record contributions and one notice in another scope.
    steps: >-
      Process the burst, read its folded item, publish another contribution and
      withdraw the original requests one at a time.
    expected: >-
      The read item does not absorb the later event. Withdrawal removes only
      unsupported contributions; the other scope remains visible and counted.
    negative: false
    data_needs: >-
      A suite-owned workspace, named staff accounts and unique occurrence keys;
      external adapters record attempts without shared writes.
    bound_to: []
    provenance: proposed
    source:
      - >-
        rhythm-v2-docs:specs/platform/notifications/planning/capabilities/CAP-PFM-NOT-005-fold-quick-repeats-into-one-notice.md#frontmatter
      - >-
        rhythm-v2-docs:specs/platform/notifications/planning/capabilities/CAP-PFM-NOT-006-withdraw-or-expire-a-notice-that-no-longer-applies.md#frontmatter
      - >-
        rhythm-v2-docs:specs/platform/notifications/planning/capabilities/CAP-PFM-NOT-009-work-through-my-own-notifications.md#frontmatter
    interaction_with:
      - CAP-PFM-NOT-006
      - CAP-PFM-NOT-009
evidence:
  - >-
    Pinned evidence inventory 1:
    services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js;
    react-console:acceptance/notifications/playwright/journeys/pipeline/NT-ACC-0205.spec.ts;
    services-platform:modules/notifications/tests/integration/db/notification-instances.table.integration.spec.js
  - >-
    Pinned evidence inventory 2:
    services-platform:modules/notifications/tests/unit/collapsing.spec.js;
    services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js;
    services-platform:modules/notifications/services/orchestration/orchestrate-request.ts
coverage:
  rule: covered
  transition: covered
  validation: 'gap: FND-PFM-NOT-066'
  permission: not-applicable
  edge: covered
  failure: 'gap: FND-PFM-NOT-066'
  boundary: covered
  concurrency: covered
  invariant: covered
  interaction: covered
coverage_notes:
  permission: >-
    This capability declares no independent access key; callers enter through
    the producing or reading capability.
  validation: Malformed input is not isolated in a dedicated category scenario.
  failure: The suite lacks an isolated dependency failure and recovery case.
findings:
  - FND-PFM-NOT-066
transition_coverage: []
workflow_coverage:
  - workflow: WF-PFM-NOT-003
    capabilities:
      - CAP-PFM-NOT-003
      - CAP-PFM-NOT-004
      - CAP-PFM-NOT-005
      - CAP-PFM-NOT-006
      - CAP-PFM-NOT-007
      - CAP-PFM-NOT-008
    scenario_candidate: ATS-PFM-NOT-005-10
    coverage: 'gap: FND-PFM-NOT-084'
    reason: >-
      The proposed related-capability sequence does not independently isolate
      every workflow hop, failure seam and interleaving.
  - workflow: WF-PFM-NOT-004
    capabilities:
      - CAP-PFM-NOT-006
      - CAP-PFM-NOT-005
      - CAP-PFM-NOT-014
    scenario_candidate: ATS-PFM-NOT-005-10
    coverage: 'gap: FND-PFM-NOT-084'
    reason: >-
      The proposed related-capability sequence does not independently isolate
      every workflow hop, failure seam and interleaving.
domain_invariant_coverage:
  - invariant: INV-DOM-PFM-NOT-003-03
    scenarios:
      - ATS-PFM-NOT-005-07
    coverage: specified
    source: >-
      rhythm-v2-docs:specs/platform/notifications/design/objects/DOM-PFM-NOT-003-staff-notification.md
    verification_note: >-
      The candidate supplies the fixture outcome; individual binding limits
      remain applicable.
  - invariant: INV-DOM-PFM-NOT-003-12
    scenarios:
      - ATS-PFM-NOT-005-05
    coverage: specified
    source: >-
      rhythm-v2-docs:specs/platform/notifications/design/objects/DOM-PFM-NOT-003-staff-notification.md
    verification_note: >-
      The candidate supplies the fixture outcome; individual binding limits
      remain applicable.
---

# Combine repeated events into one notice: Capability Test Specification

## Coverage

Each scenario names the guarantee it proves. Category coverage describes specified cases; executable bindings retain their narrower assertion boundaries. Lifecycle coverage remains a gap wherever guards and effects lack independent verification.

| Rule | Proof |
|---|---|
| `BR-CAP-PFM-NOT-005-01` | `ATS-PFM-NOT-005-01`, `ATS-PFM-NOT-005-10` |
| `BR-CAP-PFM-NOT-005-02` | `ATS-PFM-NOT-005-02` |
| `BR-CAP-PFM-NOT-005-03` | `ATS-PFM-NOT-005-03` |
| `BR-CAP-PFM-NOT-005-04` | `ATS-PFM-NOT-005-04` |
| `BR-CAP-PFM-NOT-005-05` | `ATS-PFM-NOT-005-05` |
| `BR-CAP-PFM-NOT-005-06` | `ATS-PFM-NOT-005-06` |
| `BR-CAP-PFM-NOT-005-07` | `ATS-PFM-NOT-005-07` |
| `BR-CAP-PFM-NOT-005-08` | `ATS-PFM-NOT-005-09` |

## Interactions With Related Capabilities

Give Jane two same-record contributions and one notice in another scope. Process the burst, read its folded item, publish another contribution and withdraw the original requests one at a time.

The interaction case combines the producing, processing and reading outcomes named in its frontmatter. It remains proposed until an executable suite performs that complete sequence.
