Opening Stock · Phase 0

The founding balances every later number derives from, and the permanent home of balance provenance · every non-zero balance in i3 traces to exactly one signed opening line and a chain of verifications · this is the step i2 skipped, and skipping it is mechanically how sellable reached minus 140,753

GATE 0 is failing on predicate P1 and P2. Three of eleven balance-bearing locations have no posted opening batch (HQ_319 at 62% swept, 3PL_ARAMEX with no statement, AJM seeded but unsigned) and 110 keys are NEVER_VERIFIED with stock on them. The 7-day streak reset to 0 at 04:00 today when the 3PL_ARAMEX quarantine fired. P3 and P4 both hold: the total is +0.88% against Shopify and every posted batch's hash still covers its signatures. Tracker ↓
Every downstream phase is blocked on this page. GATE 1 through GATE 8 each re-evaluate R-10.16 for the locations in their scope, so an unverified opening balance does not merely look untidy, it structurally prevents a phase from advancing. Sales ingest can run in shadow, and nothing posts to a location whose opening balance is unsigned.

GATE 0 tracker

Four predicates, evaluated daily at 04:00 Dubai. All four must hold for seven consecutive days. A single failing day resets the streak to zero, and the page says which predicate did it rather than showing a silent gap.

0 of 7 · reset today
29 JulFAILP1 · P2 · 3PL_ARAMEX quarantined at 04:00, 96 keys became never_verified 28 JulPASSall four held · diff +0.91% 27 JulPASSall four held · diff +0.86% 26 JulPASSall four held · diff +0.79% 25 JulPASSall four held · diff +0.74% 24 JulFAILP3 · diff was +1.12% before the CCZ recount landed 23 JulFAILP4 · a staged row was appended to OB-2026-BAS-01 after signature 1
✗ P1 · Every balance-bearing location has a posted, signed opening batch.
Currently failing for HQ_319 (sweep at 62%), 3PL_ARAMEX (no statement obtained) and AJM (Shopify seed staged, never signed). MCC and YAS are seeded and diffed but not signed.
5 of 11
✗ P2 · No key anywhere is never_verified, chain_mismatch or stale with stock on it.
110 never_verified (96 at 3PL_ARAMEX, 14 orphans found by the HQ_319 sweep), 412 stale at AJM, 3 chain_mismatch that module 02 has dropped from every total until a compensating row closes them.
525 keys
✓ P3 · Total sellable is within 1% of Shopify at comparable locations.
161,185 i3 against 159,772 Shopify at the seven Shopify-mapped locations. TRANSIT and SUPPLIER_HOLD are excluded because Shopify does not hold them.
+0.88%
✓ P4 · Every posted batch's hash chain verifies and every signature still covers its content.
Each signature stores hash_at_signing, keys_at_signing and units_at_signing. Appending a staged row after a signature invalidates it and names the signer who must re-sign, which is what caught the 23 July failure.
5 of 5
The master plan's GATE 0 is "opening balances signed off per location by the responsible manager; hash chain verifies; total units within 1% of Shopify total". P2 is the addition: a location can be fully signed and still contain keys nobody ever opened, and those keys are precisely the ones that went to minus 140,753 in i2.

Opening batch per location

All eleven balance-bearing locations, including the three virtual ones and 3PL_ARAMEX. A virtual location that is silently absent is exactly the gap that lets stock exist nowhere.

LocationTypeBatchSourceStateKeysUnitsValue AEDShopifyDiffvs i2ProvenanceSignature 1Signature 2
HQ_319Warehouse OB-2026-HQ319-01 RFID MASS-TAG Staged 12,847139,56134,206,400 138,204+0.98%-2,914 UNVERIFIED blocked · sweep 62% blocked Staging ↓
HQ_325Warehouse OB-2026-HQ325-01 BLIND COUNT Posted 1,9048,3182,104,880 8,290+0.34%-118 SIGNED Ramesh K. · 26-07 09:41 Mahmoud F. · 26-07 11:02 Trace
MCCRetail OB-2026-MCC-01 SHOPIFY SEED Diffed 1,7823,8841,339,150 3,8840.00%-241 UNVERIFIED Fatima A. · awaiting blocked Sign ↓
YASRetail OB-2026-YAS-01 SHOPIFY SEED Staged 1,1093,1021,018,440 3,1020.00%-96 UNVERIFIED diff not computed blocked Compute diff
CCZRetail OB-2026-CCZ-01 BLIND COUNT Posted 9622,349812,400 2,318+1.34%-64 COUNTED Leila R. · 28-07 17:12 Mahmoud F. · 28-07 18:40 Trace
AJMRetail OB-2026-AJM-01 SHOPIFY SEED Staged 8742,088682,140 2,0880.00%-312 STALE Noura S. · 118d unsigned blocked Schedule count
BASRetail OB-2026-BAS-01 BLIND COUNT Posted 6111,472498,220 1,461+0.75%-38 COUNTED Hind A. · 26-07 19:04 re-signed Mahmoud F. · 26-07 19:22 Trace
3PL_ARAMEXThird party OB-2026-3PL-01 PARTNER STATEMENT Draft 9641196,440 not mappedn/an/a NEVER_VERIFIED no statement obtained blocked D-2026-0729-208
TRANSITVirtual OB-2026-TRANSIT-01 OPEN AWB SEED Posted 268946267,180 n/an/an/a SIGNED Ramesh K. · 25-07 08:20 Mahmoud F. · 25-07 09:11 11 open AWBs
SUPPLIER_HOLDVirtual OB-2026-SUPHOLD-01 OPEN RTS SEED Posted 4118752,140 n/an/an/a SIGNED Sara H. · 25-07 10:02 Mahmoud F. · 25-07 10:44 37 open cases
DISCONTINUEDVirtual OB-2026-DISC-01 ZERO BY DEFINITION Posted 000 n/an/an/a SIGNED Sara H. · 25-07 10:05 Mahmoud F. · 25-07 10:45 Must stay zero
Total across all eleven 19,187162,31839,439,390 159,772+0.88%-3,783 Shopify comparison excludes TRANSIT and SUPPLIER_HOLD, which Shopify does not hold
vs i2 is not an error bar, it is a measurement of how far i2 drifted: every one of those numbers is negative because i2 deducted sales from zero for two years. Its final balances are recorded for the audit trail and are never replayed as an opening balance (R-10.19).

Staging area

Five sources, five different provenance outcomes. The source is a per-line property, not a per-batch one, because HQ_319's batch legitimately mixes an RFID sweep with a manual count of everything the sweep cannot see.

HQ_319RFID MASS-TAGMIN-2159 campaign86,904 / 139,561
62% swept. Zones A1 and A2 saturated (two consecutive passes each added under 0.5% new distinct EPCs). A3 is on pass 1. B1 to B4 are queued. 3 staff, 2 weeks, roughly 500 tags per hour on the ZT411R.
A1 saturated 0.22% A2 saturated 0.41% A3 pass 1 · 68% B1-B4 queued
Blocked on the non-taggable subset. 318 SKUs (consumables and jewellery under 20mm) cannot carry a UHF inlay, roughly 11,240 units. Session SC-2026-0726-HQ319-001 counted them by hand into this same batch with method = blind_count on the line. Without that parallel count, signing HQ_319 from the sweep alone would sign those 318 keys at zero, permanently. The master plan's "one operation produces both the tags and the signed opening balance" is true for the taggable subset only.
Sweep monitorManual session
MCCSHOPIFY SEEDunverified until counted1,782 keys · 3,884u
Staged from Inventory_Sync_2026.xlsx sheet MCC via job IMP-2026-0729-014, cross-checked against live Shopify levels. Diff computed. 74 rows carry a warning, 6 were rejected as non-virgin, 31 errored, 7 legacy rows quarantined.
A Shopify seed is accepted as unverified and stays that way until a physical count. It is not hidden and it is not excluded from on-hand, but under R-10.16 it cannot let any phase gate advance. Blind count SC-2026-0729-MCC-001 is running now and covers 88 of the 1,782 keys; a full count is scheduled for 05-08.
Location manager FAFatima A. Awaiting signature notified 29-07 13:58 · expires in 23h 12m
Finance MFMahmoud F. Blocked until signature 1 D8 in the master plan is still open on who signs finance for a store
The statement each signer agrees to is stored verbatim: "I have reviewed the staged opening balance for MCC as at 01-08-2026, comprising 1,782 keys and 3,884 units at AED 1,339,150, and its differences against Shopify and against i2. I accept these as the opening position from which every later balance at this location derives."
3PL_ARAMEXPARTNER STATEMENTquarantined96 keys · 411u
Shopify location id 18370396195 is live and holds stock. The location appears in no PRD list, no v2 mockup and no planning document (defect D9). Module 04 registered it as third_party; nobody has ever counted it or reconciled it to anything.
Three honest options, and no fourth. Obtain a monthly partner statement and stage it at confidence 0.60. Send someone to count it physically. Or deactivate the Shopify location so it stops accruing. What i3 will not do is quietly zero it, quietly write it off, or quietly leave it out of the totals, because all three are how a stock system loses AED 96,440 without anyone noticing.
Schedule a countDeactivate location
TRANSITOPEN AWB SEEDposted268 keys · 946u
Derived from ops2's open AWBs at the cutover instant: 11 transfers and 257 customer parcels in flight, held as IN_TRANSIT_CUSTOMER and IN_TRANSIT_RETURN against TRANSIT.
Why a virtual location needs an opening balance at all. A parcel that was already in flight at cutover will be delivered or returned afterwards. If TRANSIT starts at zero, that arrival credits a balance that was never debited, and the phantom stock is untraceable because the debit happened before i3 existed. Seeding TRANSIT is the only way the first month of deliveries reconciles.
Warehouse manager RKRamesh K. Ramesh K. 25-07-2026 08:20:14 GST · TOTP verified · ip 10.0.14.19
268 keys · 946 units · hash 6b2d91fe
Finance MFMahmoud F. Mahmoud F. 25-07-2026 09:11:38 GST · TOTP verified · ip 10.0.14.44
268 keys · 946 units · hash 6b2d91fe

Three-way diff · MCC

Staged against Shopify against i2's final balance. A batch cannot be signed while the diff is uncomputed (R-10.17), because signing a bootstrap without comparing it to the only external source available is precisely the omission this module exists to prevent.

SKUStock typeMethodStagedShopifyi2 finalvs Shopifyvs i2Note requiredNote
MSR31-07STOCKSEED1414-310+45noi2 deducted from zero for 22 months
MSR31-07DISPLAY_GOODSEED3300+3noi2 had no display bucket at stores
MSR31-12STOCKSEED77-140+21no
MST-CRM-42-BLKDISPLAY_GOODCOUNT614-2-8+8yesBlind count 29-07 found 6. Six units unaccounted, reason theft, drift case open.
LTC07-02DISPLAY_GOODSEED170-6+1yesnote missing · blocks sign-off
LTC04-03STOCKSEED1111-80+19no
LTC01-01STOCKSEED142142-2040+346nothe single worst i2 drift at MCC
MIN-CNDL-007STOCKSEED184184-960+280no
MIN-DIF-004STOCKCOUNT00-40+4nocounted zero · a verification, no ledger row · INV1 could not store this at all
STRAP-MSK05STOCKSEED152152-410+193no
JB_PEARL_03DISPLAY_GOODCOUNT290-7+2yesTwo passes disagreed 0 against 2. Adjudicated to 2 by Sara H.
MST-CRM-38-TANSTOCKSEED6868-220+90no
MIN-VAS-005DISPLAY_GOODSEED38380+38+38noi2 had no key here at all
LTC09-01STOCKSEED4444-120+56no
GIFTBOX_LUX_02STOCKCOMPOSITE040-40noa composite never holds stock (L2) · Shopify's 4 is a derived set availability
MSK05-BRNSTOCKSEED77-30+10no
Showing 16 of 1,782 · the 5-unit note threshold comes from INV1's parity_checker.DEFAULT_THRESHOLD, which is the one part of that pipeline that was already right. Notes are stored on the line and are covered by the signature hash, so a note added after signing invalidates the signature.

Provenance register

Eight classes over 19,187 balance keys. Provenance is a property of the key, not of a row, and it decays: a key is COUNTED only until the next movement, after which it is DERIVED_FROM_COUNT. This module populates module 02's v_balance_provenance.

110 never verified
counted: 3,241 keys · verified and nothing has moved since · 16.9% derived_from_count: 5,908 keys · verified, then movements happened · 30.8% signed: 2,904 keys · opening balance signed, never independently counted · 15.1% unverified: 3,765 keys · shopify_seed, partner_statement, open_awb_seed or accepted_i2 · 19.6% · these cannot pass a phase gate stale: 412 keys · last verification older than twice the location cadence · 2.1% never_verified: 110 keys · non-zero balance with no opening row at all · this is how i2 reached minus 140,753 chain_mismatch: 3 keys · the cache disagrees with balance_after · dropped from every total until a compensating row closes them (L8) derived: 2,844 keys · zero balance with no history · the benign default · 14.8% 19,187 balance keys 525 keys block GATE 0
counted 3,241 derived_from_count 5,908 signed 2,904 unverified 3,765 stale 412 never_verified 110 chain_mismatch 3 derived 2,844
SKULocationStock typeQtyValue AEDClassOpening sourceSigned byLast verifiedDaysConfidence
LTC02-053PL_ARAMEXSTOCK8419,740NEVER_VERIFIEDnonenobodynever-0.00D-208
MSR31-043PL_ARAMEXSTOCK6115,982NEVER_VERIFIEDnonenobodynever-0.00D-208
MST-CRM-42-TANHQ_319STOCK174,896NEVER_VERIFIEDnonenobody29-07 sweep found EPCs00.98Adjudicate
MIN-VAS-012AJMDISPLAY_GOOD226,820STALESEEDunsigned02-04-20261180.30Count
LTC01-01AJMSTOCK968,448STALESEEDunsigned02-04-20261180.30Count
MSR31-12YASSTOCK319,455UNVERIFIEDSEEDunsignednever counted-0.30Sign batch
MST-CRM-38-TANMCCSTOCK6819,584UNVERIFIEDSEEDawaitingnever counted-0.30Sign batch
MIN-CNDL-018HQ_325QUARANTINE14868CHAIN_MISMATCHCOUNTRamesh K.26-07-202631.00Correct
MSR31-07CCZSTOCK185,490COUNTEDCOUNTLeila R.28-07-202611.00Session
LTC04-03BASSTOCK426,300DERIVED_FROM_COUNTCOUNTHind A.20-07-202691.0014 movements since
MSK05-BRNTRANSITIN_TRANSIT_CUSTOMER6840SIGNEDAWB SEEDRamesh K.25-07-202640.50AWB
STRAP-MSK05HQ_325STOCK20415,300COUNTEDCOUNTRamesh K.26-07-202631.00Session
Confidence by method: signed physical count 1.00 · RFID sweep at saturation 0.98 · RFID sweep unsaturated 0.80 · manual entry during a device outage 0.85 · partner statement 0.60 · open-AWB derivation 0.50 · Shopify seed 0.30 · nothing at all 0.00. Confidence is published rather than implied, so a valuation built on Shopify seeds can be labelled as such.

Provenance mix over 8 weeks

The Phase 0 objective drawn as a picture: the orange and red bands shrink to nothing, and until they do, no gate advances.

19.6% unverified
0% 33% 66% 100% Week 1 · never_verified and stale: 11.4% of keys Week 1 · unverified: 63.8% Week 1 · signed: 13.1% Week 1 · counted or derived_from_count: 11.7% Week 2 · never_verified and stale: 10.9% Week 2 · unverified: 58.0% Week 2 · signed: 15.2% Week 2 · counted: 15.9% Week 3 · never_verified and stale: 10.1% Week 3 · unverified: 50.7% Week 3 · signed: 17.4% Week 3 · counted: 21.8% Week 4 · never_verified and stale: 9.4% Week 4 · unverified: 44.2% Week 4 · signed: 18.8% Week 4 · counted: 27.6% Week 5 · never_verified and stale: 8.0% Week 5 · unverified: 37.7% Week 5 · signed: 20.3% Week 5 · counted: 34.0% Week 6 · never_verified and stale: 7.2% Week 6 · unverified: 31.9% Week 6 · signed: 19.6% Week 6 · counted: 41.3% Week 7 · never_verified and stale: 6.5% Week 7 · unverified: 27.5% Week 7 · signed: 17.4% Week 7 · counted: 48.6% Week 8 (now) · never_verified 110 keys plus stale 412 plus 3 chain_mismatch: 2.7% of keys but 100% of the GATE 0 blockage Week 8 (now) · unverified: 3,765 keys · 19.6% Week 8 (now) · signed: 2,904 keys · 15.1% Week 8 (now) · counted plus derived_from_count: 9,149 keys · 47.7% GATE 0 needs this band at zero
W1W2W3W4W5W6W7now
never_verified · stale · chain_mismatch unverified signed counted and derived_from_count

Diff vs Shopify by location

Predicate P3 drawn per location. The gate is on the total, but a single location outside 1% is where to look first.

total +0.88%
0% +2% -2% The 1% band. Predicate P3 requires the TOTAL to sit inside it. +1.00% HQ_319 · +0.98% · +1,357 units · the sweep is finding untagged stock the system never knew about HQ_325 · +0.34% · +28 units MCC · 0.00% · a Shopify seed matches Shopify by construction, which is exactly why a seed proves nothing YAS · 0.00% · seeded from Shopify CCZ · +1.34% · +31 units · a physical count found more than Shopify believed · outside the band but the total still holds AJM · 0.00% · seeded from Shopify, stale for 118 days BAS · +0.75% · +11 units 3PL_ARAMEX · not mapped to a Shopify location comparison · 411 units invisible to P3 HQ_319 HQ_325 MCC YAS CCZ AJM BAS 3PL
The three flat bars are the point. MCC, YAS and AJM were seeded from Shopify, so their diff against Shopify is zero by construction and tells you nothing at all. That is why a seed carries provenance UNVERIFIED and confidence 0.30 no matter how good its diff looks.

What happens to a location nobody counts

Four published steps derived from the location's own cadence policy. At no step is a balance zeroed, written off, hidden or deleted.

1 quarantined
1 · DUEat the cadence · 90dAmber on the locations page and an alert.raise at severity low. Nothing else changes. MCC 41d · YAS 34d 2 · OVERDUEcadence plus grace · 104dThe dual-approval threshold at that location drops from 5 units to 1, and no line may leave on a transfer without a spot count first. AJM 118d 3 · STALEtwice the cadence · 180dEvery key's provenance downgrades to STALE. The location drops out of gate arithmetic and out of valuation confidence. Reports render its cells hatched. 412 keys at AJM 4 · QUARANTINEDthree times the cadence, or 180d after sign-off with no verificationOutbound allocation freezes, a drift case opens, and the rota-effective manager is named. Only an approved full count clears it. 3PL_ARAMEX · 411u · AED 96.4K
i2's answer to an uncounted location was to have no answer, which is how ONLINE showed 118,733 units while BAS showed minus 3,764 on the same dashboard. A published ladder with named consequences is the difference between a stock system that degrades visibly and one that degrades silently.

What i2 did instead, and exactly how it failed

i2 built an opening-stock uploader and never ran it with real data. Sales then deducted from zero for 22 months. Sellable reached minus 140,753 and 410 reported stockouts were meaningless, because a stockout against a balance that was never established is not information.

The mechanism has three parts and i3 closes all three:

-- 1. No opening row, so the balance is never_verified from day one.
SELECT sku_id, location_id, stock_type_id, qty, provenance
FROM v_balance_provenance
WHERE qty <> 0 AND provenance = 'never_verified';
-- i3 today: 110 rows, all named on this page. i2: no such query existed.

-- 2. No self-check on the cache, so drift was undetectable (defect D6, ruling L8).
--    i2's inventory_balance stored qty and last_event_id and never
--    compared either to balance_after.

-- 3. INV1's "opening balance" was a constant (defect G7):
for p in products:
    post_entry(product_id=pid, location_id=hq_id, qty_delta=100,
               source_type='opening_balance',
               idempotency_key="opening-baseline:" + sku)
-- Every active product. 100 units. No date in the key, so it can
-- never be superseded by a real count. R-10.19 quarantines these.

The master plan's section 4 proposes replaying i2's 587K rows into i3. That replay explicitly excludes source_type = 'opening_balance'. History replays; opening balances do not. Anything with that source type lands in import_rows as quarantined and can enter the ledger only by being re-signed as an i3 batch.

An unverified balance cannot pass a gate

R-10.16: gate_eligible(location, phase) is false while any key at that location is UNVERIFIED, NEVER_VERIFIED, STALE or CHAIN_MISMATCH with stock on it.

The balances still render, still count towards on_hand, and still appear in every list. They are not hidden, because hiding is how i2 lost track. What they cannot do is let a phase advance. GATE 1 through GATE 8 each re-evaluate the predicate for their own scope.

A signature covers a content hash

opening_signoffs stores hash_at_signing, keys_at_signing and units_at_signing. Appending one staged row after the first signature invalidates it, and the page names the signer who must re-sign and what changed.

That is what caught the 23 July gate failure on BAS. INV1's opening_balance_snapshots.taken_by is a free-text name on a snapshot that can change afterwards, which cannot express this at all.

A counted zero is a fact

INV1's opening_balance_lines carries CHECK (quantity > 0). i2's count_lines.actual_qty is nullable with nothing separating "not counted" from "counted, found none".

So in both systems every zero is either an inference or an absence and there is no way to tell which, which is exactly the question provenance is asked. i3 stores qty_counted = 0 as a real observation with a verification row and no ledger row.

Shortcuts G jump to GATE 0 S sign the focused batch D recompute diff P provenance register I import / filter ⌘K palette All shortcuts ↗

Evaluating the four GATE 0 predicates across 19,187 balance keys and 11 locations. The provenance classification is a view, not a cache, so it is always current and never quietly repaired.

No opening batches exist

This is the state i2 shipped in and never left. Until a batch is staged and signed for a location, every balance at that location is NEVER_VERIFIED, every sale deducts from zero, and every stockout report is meaningless. Nothing else in i3 should be built on top of this page being empty.

Import from the sheet Schedule the counts

No keys match this provenance filter

You are filtered to COUNTED at 3PL_ARAMEX. That location has never been counted, so the set is empty by definition. All 96 of its keys are NEVER_VERIFIED.

Shopify is unreachable, so no batch can be signed

Predicate P3 and rule R-10.17 both need a live comparison against Shopify inventory levels. The API has returned 503 for 14 minutes. Staging, diffing against i2, and counting all continue. Signing waits, deliberately: signing a bootstrap without comparing it to the only external source available is exactly the omission this module exists to prevent. Error id ob-2026-0729-s503.

Shopify status Event feed

You can read the register but not sign

Signing an opening balance needs role >= manager plus the opening_sign feature, and the signer must be the location's responsible manager or hold the finance role. You resolve to role = manager at MCC and YAS without that feature.

Master plan decision D8 is still open on who signs finance. Until it is answered, every batch has one eligible second signer and that is a single point of failure for GATE 0.

How signing works Request the feature

The nightly provenance rebuild is running

Reclassifying 19,187 keys and recomputing count_debt for 11 locations. Roughly 4 minutes. The register below is showing yesterday's 04:00 classification, which is stated rather than silently served. Signing is unaffected.

Job status

GATE 0 is open and everything downstream is waiting

Streak 0 of 7. Predicates P1 and P2 are failing. Phase 1 sales ingest can run in shadow, and no phase advances and nothing posts to an unsigned location. The shortest route to closing the gate is: obtain the 3PL_ARAMEX statement (96 keys), finish the HQ_319 sweep (38% left), and collect four signatures on MCC, YAS and AJM.

Tracker Schedule the counts Stage a batch
Connected to Stock count Count session Bulk import Live inventory Classic table Stock health Locations Location detail SKU detail Drift Drift detail Approvals Ledger corrections RFID gates 3-way reconcile Transfers Return to supplier Shopify events Reports Audit log Settings