Reports

28 definitions · every one derived from the ledger, every one stamped with an as-of, a cut id and a reconciliation status. A report that cannot state all three does not render.

As of 30-07-2026 04:12 GST Ledger cut L-4,186,204 · cost cut C-118,441 Excluded per the unreconciled rule 4 keys · 118 units Reproducible 26 / 28 Run R · Export E · Close G C
July close is blocked at propose. Opening plus the movement categories comes to 133,086, closing computed independently is 133,127, so 41 units are uncategorised across two source types. A close with a non-zero residual cannot be frozen. This is the exact number the incumbent absorbs into next month's opening without telling anyone. Close pack →
Finance
Valuation by location

Owned quantity at FIFO layer cost, per location and stock type. Sums over is_owned, never over on-hand.

AED 9.61M, up AED 180K over the window
as of30-07 04:12
cutL-4,186,204
reconcile4 keys excluded
Finance · P6
Monthly close pack

Opening plus categories must equal closing exactly. Frozen against a cut id, so a re-run reproduces the same hash.

Opening 128,904 Receipts +4,182 Sales -3,918 Returns +412 Uncategorised 41, which blocks the freeze Closing 133,127
period2026-07 draft
residual41 units
reconcilecannot freeze
Finance
NetSuite reconciliation

Period and account grain. Every delta assigned to timing, costing method, scope or error. Only error opens a drift case.

Timing AED 192.8K Costing method AED 82.6K Scope AED 44.8K Error AED 12.7K, one drift case Unexplained AED 18.4K, over tolerance
as ofextract 2026-06
unexplainedAED 18.4K
reconcileno July extract
Inventory health
Turnover rate

Units sold over average owned quantity, weekly. Cover sorts no-velocity first, never as infinite.

Slow threshold 0.25x Top decile turnover, 2.91x Bottom decile, below the slow threshold all window
as of30-07 04:12
null sortfirst · 212 SKUs
reconcileclean
Inventory health
Dead stock

No movement for 90 days or more, valued at the layer the units arrived on. AED 684K across 84 SKUs.

90 to 120 days, AED 104K 120 to 150 days, AED 142K 150 to 180 days, AED 168K 180 to 240 days, AED 118K 240 to 365 days, AED 96K Over 365 days, AED 56K, write-down candidates
as of30-07 04:12
cutL-4,186,204
reconcileclean
Ops · GATE-6
Shrinkage

Loss from counts, write-offs and confirmed-lost serials. Needs the unit ledger before the number means anything.

GATE-6 · streak 0 / 7
blocked byunit_vs_qty NULL
shadow valueAED 12.7K MTD
reconcilenot authoritative
Suppliers
Supplier scorecard

OTIF, short-delivery rate, QC reject rate and lead-time drift. Joins through item codes, never a bare SKU string.

CIC Leather, 96% OTIF Al Fahad, 92% Leather Crafts, 94% Dubai Components, 78% Istanbul Jewellers, 88% Seoul Packaging, 71% Marrakech Rug, 81% Colombo Silk, 62%, one PO only so the score is thin
as of30-07 04:12
grainsupplier x quarter
reconcileclean
Compliance
Audit log export

Every actor action, flag flip and correction. Hash-chained, infinite retention, sealed with a SHA-256 on export.

248,904 events, 30-day trend Chain valid on 29 of the last 30 nightly passes
as ofon demand
rows248,904
reconcilechain valid
Two definitions are not reproducible and say so rather than hiding it: forecast_accuracy reads a third-party model with no version pin, and influencer_roi depends on a source that has never emitted an event. Both render with a not reproducible badge instead of a plausible number.

Monthly close pack · 2026-07

Closing is computed independently. The categories are a decomposition that must add up to it, and the residual is a first-class line rather than a rounding.

residual 41
Draft 01-07 Proposed residual 41 Frozen takes the cut Filed needs a NetSuite extract

Movement decomposition · HQ_319 · STOCK

opening + categories must equal closing exactly
CategoryQty deltaValue deltaEntriesSource types rolled up
Opening128,904AED 5,742,100-carried from the frozen June close
Receipt+4,182+AED 612,40014grn_receipt, rni_release
Sale-3,918-AED 498,2003,918order_sale, pos_sale, excel_sale
Refund+412+AED 52,800388refund_restock, quarantine_release
Exchange-88-AED 11,40072exchange_out, exchange_in
Transfer out-1,204-AED 158,60042transfer_ship
Transfer in+206+AED 28,10018transfer_receive
Damage-118-AED 18,90031damage_qc_fail, damage_transit, damage_display
Write-off-88-AED 18,2006drift_writeoff · finance approved
Stock count-24-AED 3,9009stock_count_adjust · variances only
Recipe transform-204-AED 26,400118recipe_transform · component rows only
Program out-42-AED 8,10028influencer_dispatch, sample_out, trial_out
Program in+18+AED 3,40014influencer_return, trial_return
Consignment-206-AED 34,20011consignment_out
RTS-64-AED 12,8004rts_ship
Opening correction+38+AED 4,9002opening_correction · signed by the location manager
Uncategorised+41+AED 6,8007consignment_partner_sale, rfid_found_unexpected
Closing · computed independently133,127AED 5,663,8004,682SUM(quantity_delta) up to the cut
Opening 128,904 plus the sixteen named categories gives 133,086. Closing is 133,127. The 41-unit gap is shown as its own line with the offending source types named. Two new source types shipped this month and nobody added them to a category, which is exactly the class of error a self-balancing category sum makes invisible.

Freeze card

Period
2026-07
State
proposed · blocked
Ledger cut
not taken
Cost cut
not taken
Unit cut
not taken
Pack hash
n/a
Proposed by
i3-worker · 29-07 23:00
Frozen by
-
Filed by
-
Blockers
residual 41 · no NetSuite extract

June, for contrast

State
filed
Ledger cut
L-4,018,882
Cost cut
C-112,044
Residual
0
Pack hash
7c4b…19ae
Frozen by
ahmad@ · 02-07 09:12
Filed by
finance@ · 03-07 14:40
Adjustments since
2 cost revisions
As-reported
AED 5,742,100
As-restated
AED 5,748,400

Two landed-cost revisions touched June layers after it was frozen. Neither modified June. Both were booked into July as adjustments naming June as their origin, split into the part that revalues stock still on hand and the part that is a COGS variance on units already sold. June's pack hash is unchanged after 27 days, which is the test that matters.

Recent runs

A run stores its as-of, its cut ids and its result hash, so any figure can be reproduced or shown to have changed.

ReportTrigger As ofCut id State Took Rows Reconcile Formats Delivered to
Valuation by locationschedule30-07 04:12L-4,186,204success4.2s1844 keys excludedxlsx pdffinance@ · #n8n-updatesOpen
Turnover rateschedule30-07 04:14L-4,186,204success2.8s2,159cleancsv xlsx#n8n-updatesOpen
Dead stockschedule30-07 04:18L-4,186,204success1.4s84cleancsvplanning@Open
Reorder planschedule30-07 05:00L-4,186,388success6.1s1,517cleancsvops@ · procurement@Open
Close pack · proposeschedule29-07 23:00not takenfailed3m 40s4,682residual 41-finance@Detail
NetSuite reconschedule30-07 06:00L-4,186,441skipped0.2s0no extract-finance@Detail
Shrinkageschedule--gate-blocked--GATE-6 0/7-pausedGate
Fulfilment SLAschedule29-07 07:00L-4,182,118delivery failed1.8s1,284cleanpdffinance@ 554 bounce x3Resend
Reverse-flow driftschedule30-07 04:40L-4,186,204success8.4s412stale: ops2 reversejson#n8n-updates · ops@Open
Supplier scorecardschedule29-07 10:00L-4,182,441success3.2s14cleanxlsx csvprocurement@Open
Stock count varianceschedule28-07 07:30L-4,180,204success2.1s188cleanxlsxwh-ops@ · retail-ops@Open
Balance verificationsschedule30-07 04:44L-4,186,204success0.9s1,204cleancsvwh-ops@Open
Cost variancemanual29-07 15:14C-118,402success1.1s42cleanxlsxahmad@Open
Customer-order ledgermanual29-07 11:04L-4,182,904success0.6s18cleancsvnamratha@Open
Forecast accuracyschedule29-07 12:00L-4,182,441not reproducible14.2s2,159model unpinnedxlsxplanning@Open
Influencer ROIschedule--failed--source never seen-marketing@Detail
Audit log exportmanual28-07 22:15A-248,904success18.4s248,904chain validjsonlegal@ · sealedOpen
stale: ops2 reverse is not a warning about the report, it is a statement about the input. The ops2 reverse topics are not emittable yet, so the reverse-flow figures are computed over a source that has produced nothing, and the run says so instead of publishing a clean zero.

Scheduled look-ahead · four weeks

48 runs planned · Asia/Dubai · dots per cadence
Mo
Tu
We
Th
Fr
Sa
Su
W31
27
28
29
30
31
1
2
W32
3
4
5
6
7
8
9
W33
10
11
12
13
14
15
16
W34
17
18
19
20
21
22
23
daily weekly monthly close window bi-weekly count close dry-run, currently failing
The close dry-run fires nightly from the 28th so a residual is found five days before the close is due, not on the morning finance asks for it.

Export and delivery

Format
FormatCarriesEst size
csvrows only · as-of in the filename184 KB
xlsxrows + a provenance sheet312 KB
pdfrows + charts + a signed footer1.1 MB
jsonrows + full run metadata248 KB
parquetrows only · archive tier64 KB

Every format stamps as-of, cut id and reconciliation status into the file itself, not only onto the page. A spreadsheet that leaves this system and loses its provenance becomes an argument six weeks later.

Delivery
Email
3 bounces pauses the subscription
Slack
via alert.raise, never direct
Archive
Tigris · 30-day lifecycle
Signed URL
15-minute TTL, minted on request

Subscriber matrix

14 recipients across 11 reports. Open rate is tracked so a dead subscription can be pruned rather than quietly bouncing forever.

subscribed bouncing open rate under 30% = prune candidate
Recipient ValuationCloseReconTurnoverDead stock ShrinkSupplierCount varSLADriftAudit Open 30d
ahmad@minimalist.ae adminYYYYYYYYYYY99%
finance@minimalist.aeYYY-YY-YB--92%
fatima@minimalist.ae ops_managerY--YYYYYYY-88%
procurement@minimalist.ae---YY-Y----81%
wh-ops@minimalist.ae---Y-Y-YYY-76%
retail-ops@minimalist.ae---YYY-Y---71%
planning@minimalist.ae---YY-Y----68%
ops@minimalist.ae------Y-YY-62%
namratha@minimalist.ae--------Y--58%
marketing@minimalist.ae---Y-------41%
legal@minimalist.ae----------Y19%
#n8n-updates slackYY-Y--Y--Y-84%
#n8n-rfid slack-----Y-Y-Y-72%
#n8n-hr slack------------
legal@ opens 19% of what it receives, which is one report a quarter, so the subscription is a prune candidate rather than a compliance control. finance@ is bouncing on Fulfilment SLA after three 554 responses and that subscription is paused, which is why the mailbox has stopped receiving a report nobody noticed it stopped receiving.

What makes a report reproducible

A number nobody can reproduce is an opinion with a timestamp. Five things make one reproducible, and a definition that cannot supply all five is marked not reproducible on its own card rather than being quietly published alongside the rest.

IngredientWhy it is load-bearing
as-of timestampthe wall-clock the figure describes, printed on the page and in the file
ledger cut idreplaying rows with id ≤ cut gives the same answer no matter what arrived since
cost cut ida later landed-cost revision cannot retroactively change a past valuation
parametersrange, location, category, brand, unit, stored with the run
null orderingstated in the column header, because a nullable measure sorts two defensible ways
exclusion disclosureunreconciled keys are dropped, and the count and quantity of what was dropped is printed

The incumbent's monthly close is stable only by accident: it prices historical rows at whatever the cost table says today, so re-running last March after a cost edit returns a different number with no record that it moved.

What a clean count produces

78% of counts find nothing wrong. A clean count moves no stock, so it cannot write a ledger row: a zero-quantity row is forbidden, and there is nothing to compensate.

The consequence, if counting only ever wrote ledger rows, would be perverse: a location that counts diligently and keeps passing would generate no evidence at all and would drift to never verified precisely because it keeps being right.

So counting produces two different artefacts, and any report that claims to count verified balances reads the second one. The Balance verifications row in the run table above returned 1,204 rows this morning. The Stock count variance row returned 188. Those are not two views of the same thing.

Count outcomeArtefactRead by
variance foundledger_entriesclose pack · shrinkage · drift
clean, no variancebalance_verificationsprovenance · verified-balance reports
a zero-delta ledger rowcannot existnothing · forbidden by constraint

No report definitions yet

The catalogue is seeded from the definition registry at migration time, so an empty catalogue means the seed has not run rather than that nobody has built a report. There are no user-authored reports in i3: a definition names its grain, its measures, its gate and its owner, and those are code, reviewed like code. Registry status →

Report runner unreachable

Job reports.daily_pack has not heartbeated since 04:44. The catalogue below is readable and every card is showing its last completed run, correctly stamped with that run's as-of, not with now. Nothing here is extrapolated forward.

Eleven of 28 reports hidden

The finance reports need role ≥ manager plus the finance feature, and the close pack needs admin to freeze. Your derived persona is store manager · MCC, so you see the 17 operational definitions and the MCC slice of each. Personas are derived at login from role, features and rota locations, never granted, so this is a feature request rather than a role change. Role mapping →

No definitions match those filters

You have Compliance and Reads value and Failing selected together, and no compliance report reads value. Nothing is wrong: the intersection is genuinely empty.

Scheduled runs paused

Postgres minor upgrade, 02:00 to 02:40 GST. Definitions are readable and cached artifacts are downloadable. Scheduled runs are queued rather than skipped, so the 04:12 valuation will fire at 02:50 with an as-of that says 02:50 and not 04:12.

Five reports are gate-blocked

Shrinkage, Serial valuation, Repair spend, Stock turn by serial and Gate compliance all need GATE-6 to have held for 7 days. It has held 0. Each renders its shadow measurement with a not authoritative stamp instead of hiding, so you can watch them converge, but none of them may be attached to a close. Gate tracker →

Connected to Cash + valuation Ops health + gates Dev console Settings Audit log Drift Stock health Counts Suppliers Cost + price Opening stock Dashboard
R re-run · E export · S schedule · P reproduce · / search · ⌘K palette Every run is logged to the audit ledger with its cut ids, so any figure that ever left this page can be reproduced or shown to have moved.