Stock Count

The counting programme, not one count · five modes · eight session states · the count grain is (sku · location · stock_type), which is the column i2 never had · a clean count posts no ledger row and a balance_verifications row instead, because ruling L14 keeps quantity_delta <> 0

3PL_ARAMEX has never been counted and reached quarantined at 04:00 today. 411 units worth AED 96.4K are frozen for outbound allocation and drift case D-2026-0729-208 owns them. AJM is 118 days past a 90-day cadence and is overdue, so its dual-approval threshold has dropped from 5 units to 1. Nothing was zeroed, written off or hidden. Open D-2026-0729-208 →
Count adjustments are staged but not posting. GATE 0 has held 4 of 7 days and three locations are still unsigned, so a stock_count_adjust row at those locations would be an adjustment against a balance nobody has signed for. Sessions run, variances compute, approvals collect. Posting resumes the moment GATE 0 closes. Read-only until 03-08-2026. GATE 0 tracker →
Import count sheet
variance > u
16 of 64 sessions · last 30 days

Cadence policy and count debt

One row per location. Cadence, thresholds and the blind requirement are policy, copied onto a session at freeze so a later edit cannot retroactively change whether a past line needed two signatures.

3 in debt
LocationTypeFullCycleSince lastDebtBlindThresholds units / pct / valueCoverage 90d by valueNever counted keysEscalated to
HQ_319Warehouse 90d7d3d CURRENTrequired 5u · 2.0% · AED 500 94.1% 0Ramesh K. Sessions →
HQ_325Warehouse 90d14d11d CURRENTrequired 5u · 2.0% · AED 500 88.4% 0Ramesh K. Sessions →
MCCRetail 90d7d41d DUErequired 5u · 2.0% · AED 500 61.2% 14Fatima A. Sessions →
YASRetail 90d7d34d DUErequired 5u · 2.0% · AED 500 58.0% 9Mariam K. Sessions →
CCZRetail 90d7d9d CURRENTrequired 5u · 2.0% · AED 500 81.3% 0Leila R. Sessions →
AJMRetail 90d7d118d OVERDUErequired 1u · 2.0% · AED 500 22.4% 37Noura S. Schedule now →
BASRetail 90d14d16d CURRENTrequired 5u · 2.0% · AED 500 66.7% 0Hind A. Sessions →
3PL_ARAMEXThird party 180dn/anever QUARANTINEDstatement 1u · 0.0% · AED 0 0.0% 96Mahmoud F. Open batch →
TRANSITVirtual n/an/aderived DERIVEDnot countable reconciled per transfer nets to zero per closed transfer 0system Transfers →
SUPPLIER_HOLDVirtual n/an/aderived DERIVEDnot countable reconciled per RTS case 37 open RTS cases hold 187u 0system RTS →
DISCONTINUEDVirtual n/an/azero by definition SIGNEDnot countable must remain zero a non-zero balance here is a P1 0system Drift →
The four-step ladder is due at the cadence, overdue at cadence plus grace (threshold drops to 1 unit and no line may leave on a transfer without a spot count), stale at 2x cadence (provenance downgrades, the location drops out of gate arithmetic), quarantined at 3x (outbound frozen, drift case opened, escalated to the rota-effective manager). At no step is a balance zeroed, written off, hidden or deleted. Only an approved full count clears a quarantine.

Sessions

Every session carries the stock types it scoped. A session with no stock type in scope cannot post a ledger row, which is exactly why i2's count_lines never posted one.

16 shown · 64 in window
SessionLocationModeStock typesStateCounter KeysProgressVar lines Net unitsNet AEDCoverStartedAge
SC-2026-0729-HQ319-003 HQ_319 RFID SWEEP STOCK In progress RKRamesh K. +2 1,412
1046/1412
31 -84 -19,240 62% 29-07 06:10 7h 41m Open
SC-2026-0729-MCC-001 MCC BLIND CYCLE STOCK DISPLAY_GOOD In progress FAFatima A. 88
47/88
4 -11 -3,860 18% 29-07 09:15 4h 36m Open
SC-2026-0728-HQ325-002 HQ_325 BLIND STOCK QUARANTINE Adjudicating SPSanjay P. +1 214
214/214
9 -23 -8,410 11% 28-07 07:00 1d 6h Adjudicate
SC-2026-0728-YAS-001 YAS SPOT DISPLAY_GOOD Submitted 0/2 MKMariam K. 3
3/3
2 -7 -2,940 0.4% 28-07 16:40 19h 8m Sign
SC-2026-0727-CCZ-004 CCZ BLIND CYCLE STOCK DISPLAY_GOOD Under review 1/2 LRLeila R. 64
64/64
3 -5 -1,780 14% 27-07 10:20 2d 3h Sign 2/2
SC-2026-0727-HQ319-002 HQ_319 RFID SWEEP STOCK Approved 2/2 RKRamesh K. +2 1,388
1388/1388
22 -61 -14,120 58% 27-07 06:00 2d 7h Ledger
SC-2026-0726-BAS-001 BAS CYCLE STOCK Completed 2/2 HAHind A. 42
42/42
0 0 0 9% 26-07 18:05 3d View
SC-2026-0726-HQ319-001 HQ_319 BLIND non-taggable Completed 2/2 SPSanjay P. 318
318/318
6 +14 +2,180 8% 26-07 07:30 3d 8h View
SC-2026-0725-MCC-002 MCC SPOT DISPLAY_DAMAGED Completed 2/2 FAFatima A. 2
2/2
1 -3 -1,050 0.3% 25-07 14:00 4d Drift
SC-2026-0724-CCZ-003 CCZ FULL STOCK DISPLAY_GOOD RESERVED Completed 2/2 LRLeila R. +1 962
962/962
18 -29 -9,640 100% 24-07 08:00 5d View
SC-2026-0723-YAS-002 YAS BLIND CYCLE STOCK Completed 2/2 MKMariam K. 51
51/51
1 +2 +340 12% 23-07 11:00 6d View
SC-2026-0722-AJM-001 AJM CYCLE STOCK Void NSNoura S. 36
8/36
0 0 0 0% 22-07 09:00 7d abandoned
SC-2026-0721-HQ319-004 HQ_319 RFID SWEEP STOCK Completed 2/2 RKRamesh K. +2 1,341
1341/1341
27 -48 -11,880 56% 21-07 06:00 8d View
SC-2026-0720-BAS-002 BAS BLIND STOCK DISPLAY_GOOD Completed 2/2 HAHind A. 611
611/611
11 -16 -4,220 100% 20-07 07:00 9d View
SC-2026-0719-MCC-003 MCC SPOT RESERVED Completed 2/2 FAFatima A. 6
6/6
0 0 0 0.7% 19-07 13:20 10d View
SC-2026-0718-3PL-001 3PL_ARAMEX SPOT STOCK Void unassigned 96
0/96
0 0 0 0% 18-07 08:00 11d no site access
Net AED is derived from count_lines.variance_value_fils, a generated column. Nothing on this page is authored independently of the line set, which is how v2's session summary came to disagree with its own variance table. Showing 16 of 64

Variance distribution

Per-line variance across 4,912 counted lines in 90 days. The shape is the diagnosis: a tall clean spike with thin symmetric tails is a healthy programme, a leaning distribution is systematic process error and not theft.

78.4% clean
0 1.3K 2.6K 3.9K variance -20 or worse · 24 lines · AED 18,410 · 9 opened a drift case variance -10 to -19 · 41 lines · AED 12,090 variance -5 to -9 · 68 lines · AED 9,340 · all required dual approval variance -2 to -4 · 111 lines · AED 4,120 · 38 were count-window movement variance -1 · 164 lines · AED 1,860 variance 0 · 3,852 lines · 78.4% of all counted lines · these post NO ledger row, only a balance_verifications row variance +1 · 148 lines · AED 1,640 variance +2 to +4 · 96 lines · AED 3,010 · 22 tagged untagged_unit variance +5 to +9 · 54 lines · AED 6,220 · all required dual approval variance +10 to +19 · 29 lines · AED 8,470 · 14 were carton_double_count variance +20 or better · 17 lines · AED 11,240 · 11 were never-tagged units found by the sweep dual approval dual approval skew -0.34 left-leaning
-20+-10-5-2-10+1+2+5+10+20+
The tails are not symmetric: 408 shortage lines against 344 overage lines. A left-leaning distribution at this scale reads as a receiving or picking process losing units, not as theft, and it is why the 90-day cycle sample is weighted towards the fast-moving zones.

Count coverage over time

Share of inventory value by the age of its last verification. This is the count-health headline, because a programme that counts four thousand cheap lines and no expensive ones looks busy and proves nothing.

63.4% under 90d
0% 33% 66% 100% Over 180 days or never verified: 3PL_ARAMEX, AJM and the unsigned store seeds. This band is what GATE 0 has to eliminate Verified 90 to 180 days ago: still countable, not yet stale Verified 30 to 90 days ago: the working band of a healthy cycle programme Verified under 30 days ago: rises from 4% to 42% of value as the counting programme starts target 80% under 90d
AugSepOctNovDecJanFebMarAprMayJunJul
under 30d 30 to 90d 90 to 180d over 180d or never weighted by cost value, not by line count

Variance resolution · 90d

What happened to the 1,060 lines that were not clean

n=1,060
Variance resolution over ninety days Within tolerance, auto-approved: 478 lines · 45.1% Count-window movement, not a real variance: 253 lines · 23.9% Dual-approved and posted: 179 lines · 16.9% Converted to a drift case: 100 lines · 9.4% Still adjudicating: 52 lines · 4.9% 69% no real loss
  • Within tolerance478 · 45.1%
  • Count-window movement253 · 23.9%
  • Dual-approved, posted179 · 16.9%
  • Sent to drift100 · 9.4%
  • Adjudicating52 · 4.9%
253 lines, nearly a quarter of all variances, were units that legitimately moved while the counter walked the aisle. Under v2's design those were shrinkage. Under R-10.1 they are correct counts with the intervening sale attached to the line.

Recount agreement by counter

Fraction of independently second-passed lines where pass 1 equalled pass 2 exactly. Speed is recorded and deliberately not ranked.

341 second passes
target 95% Leila R. · CCZ Leila R. · 99.1% agreement over 68 second passes · 54 lines per hour 99.1% Ramesh K. · HQ_319 Ramesh K. · 97.8% agreement over 91 second passes · 128 lines per hour on the sled 97.8% Hind A. · BAS Hind A. · 96.4% agreement over 55 second passes · 47 lines per hour 96.4% Fatima A. · MCC Fatima A. · 95.1% agreement over 74 second passes · 62 lines per hour, the fastest counter and the fourth most reliable 95.1% Sanjay P. · HQ_319 Sanjay P. · 92.6% agreement over 41 second passes · 58 lines per hour 92.6% Mariam K. · YAS Mariam K. · 85.7% agreement over only 12 second passes · sample too small to act on, flagged for a higher sampling rate 85.7% n=12 too small
v2 ranked counters on agreement with the system balance. On a blind count that rewards a counter for reproducing the number they were not supposed to see. Agreement between two independent passes is computable without the system's opinion and cannot be gamed by guessing.

The count window is reconciled, never frozen

v2's scope modal offers "Lock SKUs during count window (block Shopify webhooks)". i3 refuses that option. Shopify retries a failed webhook with backoff and then stops, so blocking loses events. And it does not even solve the problem: the physical sale still happened, so the counter still sees a shelf that disagrees with the balance.

Instead every line freezes its own expectation at the instant it is served to the counter, not at session start, and the variance is computed against that watermark plus whatever legitimately moved in between:

-- R-10.1 · variance is a GENERATED column, not one the writer maintains
SELECT cl.counted_qty,
       cl.balance_at_freeze,
       cl.window_movement,     -- signed ledger deltas since frozen_at_entry_id
       cl.expected_qty,        -- GENERATED: balance_at_freeze + window_movement
       cl.variance             -- GENERATED: counted_qty - expected_qty
FROM count_lines cl
WHERE cl.session_id = 'SC-2026-0729-MCC-001'
  AND cl.window_movement <> 0;
-- 12 lines. Every one would have read as shrinkage in i2.

Ingestion is never interrupted. A line reading counted 24 · frozen 29 · window -5 · expected 24 · variance 0 is a correct count with two sales attached, and the session page shows it that way.

A clean count posts no ledger row

Ruling L14 keeps quantity_delta <> 0 on the quantity ledger. A zero-variance count moves nothing, so it cannot be a ledger row. It writes a balance_verifications row instead, and that row is what flips the key's provenance to counted.

3,852 of 4,912 lines in the last 90 days were clean. If those had needed a ledger row, 78% of all counting effort would have been invisible to provenance.

Four count engines became one

i2 counted SKUs with no stock type. rfid-app counted tags with no quantity. ops2 IWMS counted cartons and swallowed its own ledger write. ops2's picking area counted SKUs and applied variances with no approval at all. None of the four reconciled to another, and two of them counted the same physical units.

One session table. One grain. count_evidence_sources carries UNIQUE (session_id, source_kind, source_ref) so one carton cannot feed two lines.

Shortcuts C new count JK row Enter open A approve selected P print sheets / filter ⌘K palette All shortcuts ↗

Loading sessions. Active sessions continue on each counter's handheld and sync when this page recovers, because the entry loop is offline-first.

No count sessions yet

Nothing has been counted. That is not a neutral state: every balance in i3 is at best signed or unverified, because only a count can produce counted provenance. Start with the locations carrying the most value.

Review provenance Set cadence policy

No sessions match these filters

64 sessions exist in the window. The active combination is location = AJM and mode = RFID sweep, and AJM has no RFID reader assigned to it.

Could not load count sessions

The read replica timed out after 8s. No count was affected: entries are written by the counters' devices against the primary, and approvals are queued rows rather than requests. Error id sc-2026-0729-e4b1.

Ops health

You can see counts at your own locations only

Your session resolves to role = viewer with rota-effective locations MCC and YAS. Approving a variance needs role >= manager plus the count_approve feature. Personas are derived at login and cannot be granted from this page.

How access is derived Request the feature

Approval posting paused for migration 0219

The trigger that enforces distinct approvers is being installed. Counting and submission are unaffected and every queued approval will post in order when the migration completes, roughly 6 minutes. Nothing is lost, because an approval is a row and not a request.

Migration status

Counting is live. Posting is not.

GATE 0 has held 4 of 7 consecutive days. HQ_319, AJM and 3PL_ARAMEX have no signed opening balance, and a count adjustment at a location whose opening balance nobody signed is an adjustment against nothing. Sessions run, variances compute, approvals collect, and every approved session posts the moment the gate closes.

GATE 0 tracker Open a session
Connected to Count session Opening stock Bulk import Drift Drift detail Approvals Locations Location detail Live inventory Stock health Cartons RFID gates 3-way reconcile Damages Transfers Return to supplier Reports Audit log Settings