---
id: CAP-COM-FUL-019
title: Reconcile shelf counts and stock findings
feature: FEAT-COM-FUL-04
product_area: commerce
module: fulfillment
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes:
  - CAP-COM-INV-016
  - CAP-COM-INV-017
  - CAP-COM-INV-018
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
intent_sources:
  - >-
    services-commerce:docs/migrations/inventory/README.md#D-P8I-24 (Q08, Andrew
    2026-10-19)
purpose: >-
  Warehouse staff compare physical counts and ledger records and investigate
  discrepancies.
outcomes:
  - Counts provide accountable shelf-balance corrections.
  - Replenishment findings identify stock at its configured threshold.
concepts:
  - CON-COM-FUL-005
actors:
  - ACT-COM-010
  - ACT-COM-009
  - ACT-COM-013
surfaces:
  - api
  - job
preconditions: []
postconditions: []
permissions:
  - key: commerce.inventory.read
    where_checked: api
    scope: tenant
  - key: commerce.inventory.create
    where_checked: api
    scope: tenant
  - key: commerce.inventory.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-COM-FUL-019-01
    proved_by: [ATS-COM-FUL-019-01, TST-COM-FUL-057, TST-COM-FUL-066]
    statement: >-
      A warehouse or location count starts without lines, records each item's
      on-hand expectation when counted, rejects items outside its scope and
      replaces a line's earlier count on recount.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#opens
      the count open with no lines, records the lines with what the shelf
      expected, and completes it with one correction for the variance
    origin: none
  - id: BR-CAP-COM-FUL-019-02
    proved_by: [ATS-COM-FUL-017-11, ATS-COM-FUL-018-14, ATS-COM-FUL-019-01, ATS-COM-FUL-019-07, TST-COM-FUL-057, TST-COM-FUL-066]
    statement: >-
      Count completion writes keyed corrections for differences from on-hand at
      completion and stamps counted items, while rejecting later line edits and
      repeated completion; cancellation writes no corrections.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#refuses
      lines on a completed count and a second completion (409), and the
      cancelled count wrote nothing
    origin: none
  - id: BR-CAP-COM-FUL-019-03
    proved_by: [ATS-COM-FUL-008-12, ATS-COM-FUL-019-02, ATS-COM-FUL-019-09, TST-COM-FUL-057, TST-COM-FUL-059, TST-COM-FUL-066]
    statement: >-
      Each subject has one open stock finding per kind, repeats increase
      occurrences, resolution requires its result and cannot repeat, and later
      recurrence can open a new finding.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#is
      raised open, acknowledged, resolved with its resolution, and raised again
      as a new row once resolved
    origin: none
  - id: BR-CAP-COM-FUL-019-04
    proved_by: [ATS-COM-FUL-018-15, ATS-COM-FUL-019-03, ATS-COM-FUL-019-08, TST-COM-FUL-063]
    statement: >-
      The daily check releases expired holds with an expiry reason and raises an
      expired-hold finding for each, without automatically correcting other
      discrepancies.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#releases
      the expired hold (reason expiry) and raises expired_hold on it, giving the
      unit back
    origin: none
  - id: BR-CAP-COM-FUL-019-05
    proved_by: [ATS-COM-FUL-019-03, TST-COM-FUL-063]
    statement: >-
      Balance reconciliation compares stored balances with ledger derivation and
      reports both sets of figures without silently replacing them.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
      balance_mismatch on the item knocked out of line, with what was kept and
      what the ledgers say, and corrects nothing
    origin: none
  - id: BR-CAP-COM-FUL-019-06
    proved_by: [ATS-COM-FUL-019-03, TST-COM-FUL-063]
    statement: >-
      A committed or picked allocation linked to a terminal delivery obligation
      produces a stale-allocation finding.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
      stale_allocation on the committed unit whose obligation is cancelled
    origin: none
  - id: BR-CAP-COM-FUL-019-07
    proved_by: [ATS-COM-FUL-019-03, TST-COM-FUL-063]
    statement: >-
      Tracked SKUs at or below their variant or fallback product reorder point
      produce low-stock findings carrying the applicable reorder quantity.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
      low_stock on shirt L at its own reorder point with the product’s reorder
      quantity, and nothing on the cap above its point
    origin: none
  - id: BR-CAP-COM-FUL-019-08
    proved_by: [ATS-COM-FUL-019-04, TST-COM-FUL-062]
    statement: >-
      Inventory and tracked-product scans follow all pages when time permits,
      report incomplete work on early stopping and restart from the beginning on
      the next run.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#checks
      every tracked SKU with a reorder point and raises each one at or below it,
      the last page’s included
    origin: >-
      Q08, Andrew 2026-10-19:
      services-commerce:docs/migrations/inventory/README.md#D-P8I-24
  - id: BR-CAP-COM-FUL-019-09
    proved_by: []
    statement: >-
      The cost reconciliation pass reports on-hand versus open-layer
      disagreement and recent outgoing shipment or transfer movements lacking
      relief.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
      valuation_mismatch on each item whose on-hand is not Σ its layers (the
      bare receipts made none), the cost stream’s finding
    origin: none
  - id: BR-CAP-COM-FUL-019-10
    proved_by: [ATS-COM-FUL-019-03, TST-COM-FUL-063]
    statement: >-
      Repeated nightly checks increment existing open findings rather than
      creating duplicates.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#finds
      the same on a second run and adds an occurrence to each open finding
      rather than another row
    origin: none
  - id: BR-CAP-COM-FUL-019-11
    proved_by: [ATS-COM-FUL-019-05, TST-COM-FUL-063]
    statement: >-
      Stock-workspace discovery requires sweep authority and rejects an existing
      transaction, while all resulting findings are stored within the relevant
      workspace.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#finds
      the tenants that hold stock across tenants, under the sweep policy, this
      one among them, and refuses that read inside another transaction
    origin: none
  - id: BR-CAP-COM-FUL-019-12
    proved_by: [ATS-COM-FUL-019-06, TST-COM-FUL-057]
    statement: >-
      Count creation, recording and completion and finding acknowledgement or
      resolution require administrator inventory permissions.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: observed
    source: 'services-commerce:modules/inventory/aws/api/inventory.routes.ts'
    origin: none
scenarios:
  - id: SC-CAP-COM-FUL-019-01
    given: The shelf contains nine units but on-hand records show ten.
    when: Record and complete the shelf count.
    then: >-
      One negative count correction aligns the balance and stamps the count
      time.
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#opens
      a count, records what was counted, completes it with one correction, and
      cancels another; lines on a completed count 409
edge_cases:
  - id: SC-CAP-COM-FUL-019-02
    given: Tracked merchandise spans several pages.
    when: Run the full nightly scan.
    then: Low-stock evaluation reaches qualifying SKUs on the final page as well.
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#checks
      every tracked SKU with a reorder point and raises each one at or below it,
      the last page’s included
constraints: []
depends_on:
  - CAP-COM-FUL-017
related:
  - CAP-COM-FUL-018
  - CAP-COM-FUL-008
journeys: []
open_questions:
  - OQ-COM-FUL-004
evidence:
  - repository: services-commerce
    paths:
      - >-
        modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js
      - >-
        modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js
      - >-
        modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js
      - modules/inventory/aws/api/inventory.routes.ts
controls: [TC-IAM-006, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-CRY-001, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-LOG-004, TC-LOG-005, TC-AVL-004, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002]
exercised_by: [FAS-COM-FUL-04-02, FAS-COM-FUL-04-03, FAS-COM-FUL-04-04]
suites: [TST-COM-FUL-057, TST-COM-FUL-059, TST-COM-FUL-062, TST-COM-FUL-063, TST-COM-FUL-066]
---

# Reconcile shelf counts and stock findings

## Purpose

Warehouse staff compare physical counts and ledger records and investigate discrepancies.

## How It Works

Staff open a count for a warehouse or location and record observed quantities. Completion creates the necessary ledger corrections and retains the count record. Separate stock findings support acknowledgement and resolution of recurring problems. The nightly check compares balances, allocations, replenishment thresholds and cost evidence. It releases expired holds but leaves other discrepancies for investigation. Large scans can stop early and report incomplete coverage. The product should make incomplete runs and unresolved stock findings visible to the staff responsible for them.

## Relationships

- Keep stock movements and transfers accountable supplies or consumes related delivery records.
- Allocate stock and explain what buyers can obtain supplies or consumes related delivery records.
- Review and resolve operations findings supplies or consumes related delivery records.
