Inventory

SkillDev tools

Use when deciding how much stock to hold and when to reorder it — classifying SKUs, sizing safety stock, setting reorder points and order quantities, and tracking the KPIs that keep a business from either stocking out or sitting on dead stock. NOT raising or negotiating the purchase order itself (that is `procurement`).

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Inventory skill

What this skill tells your AI

The instructions your AI receives, as published by ericrisco/rsc-harness in skills/inventory/SKILL.md and read by ahel’s review.

You are setting stock policy: how much to hold, when to reorder, how much to reorder. You are not buying it (that is procurement) and not moving it (that is logistics-ops). You decide the numbers that tell the buyer what to order and when.

Leave behind two checkable artifacts every time:

  1. Reorder-policy table — one row per SKU: sku, abc_class, avg_demand, lead_time, safety_stock, reorder_point, order_qty, review_mode. This is the standing policy.
  2. Replenishment trigger list — the subset of SKUs whose on_hand <= reorder_point right now, with a suggested order quantity. This is the action.

scripts/verify.sh checks both for shape and the structural invariants (ROP ≥ safety stock, order_qty > 0, no false triggers). Run it before you hand anything off. It validates structure, not whether the buffers are commercially smart — that judgment is yours.

Pick the job

The flow genuinely branches. Find the row that matches the ask before doing anything else.

Ask sounds likeJobYou produce
"which SKUs deserve tight control", "run ABC"ClassifyABC×XYZ class per SKU → the abc_class column + a policy posture per class
"how much safety stock", "we keep running out / sitting on dead stock"Size the buffersafety_stock per SKU, chosen Z, chosen formula
"what's my reorder point", "set up min/max", "weekly or continuous"Set policyreorder_point, order_qty, review_mode → the full policy table
"is our stock policy working", "turnover", "cut dead stock"TrackKPI panel against the business's own history + cycle-count cadence

Classify before you size, size before you set policy. A uniform policy across every SKU is the original sin (anti-patterns table).

Classify first: ABC × XYZ

Rule: never apply one uniform service level or review mode to every SKU — control is a budget, spend it where the value and the volatility are. Bad: 95% service on all 800 SKUs. Good: 99% on the high-value/stable AX items, make-to-order or near-zero buffer on the low-value/erratic CZ items.

  • ABC = Pareto split by annual consumption value (annual_demand × unit_cost), sorted descending and cumulated. A ≈ top ~80% of value (usually ~20% of SKUs), B the next band, C the long low-value tail.
  • XYZ = split by demand variability via coefficient of variation CV = σ_demand / mean_demand. X = stable (low CV), Y = fluctuating, Z = erratic.

The 9-cell matrix maps to policy: AX → tight automated min/max, highest service; CZ → manual, minimal buffer or make-to-order; AZ → high value but erratic, the candidate for DDMRP (below). Full cumulative-value worked sort, CV cut points, and the 9-cell→(review mode, service level, buffer posture) matrix are in references/abc-xyz.md.

Safety stock

Rule: match the formula to which thing actually varies. Picking the demand-only formula when the supplier's lead time swings is the most common under-buffering mistake — you buffer the wrong variance and still stock out.

demand varies, lead time stable:     SS = Z · σ_demand · √LT
both vary, independent:              SS = Z · √(LT · σ_demand² + avg_demand² · σ_LT²)
both vary, correlated (King):        SS = Z · σ_demand · √LT + Z · avg_demand · σ_LT

Z is set by your target service level, never picked by feel:

Service levelZ
90%1.28
95%1.65
97.5%1.96
99%2.33

Higher service costs disproportionately more buffer — the tail is fat, so each extra point past ~98% buys a chunk of cash you reserve for A/critical items and deny to C items. Bad→Good: supplier "usually 5 days but sometimes 12" + you used Z·σ_demand·√LT → switch to the independent or King formula so σ_LT is in the buffer. How to estimate σ_demand and σ_LT from sales/receipt history, all three formulas worked with numbers, and the diminishing-returns curve are in references/safety-stock.md.

Reorder point and order quantity

These are two separate decisions — conflating them is the classic beginner error. ROP answers when, order quantity answers how much.

ROP = (avg daily demand × lead-time days) + safety_stock        ← when to trigger
EOQ = √(2 · D · S / H)                                          ← how much to order
        D = annual demand, S = cost per order, H = annual holding cost per unit

EOQ minimizes ordering + holding cost under stable demand. It is an order-size lever and never a trigger — you do not "wait until you can order an EOQ." Keep reorder_point and order_qty as separate columns.

Continuous vs periodic review is a real branch:

ModeHow it worksUse whenCost
Continuous (min-max / s,S)Order the moment on-hand hits ROP s, bring up to SA items, perpetual stock visibilityFastest reaction, needs live counts
PeriodicCheck on a fixed cadence (e.g. every Friday), order up to targetB/C items, batched POs, no live systemNeeds a bigger buffer to cover the extra review-interval exposure

Periodic review adds Z · σ_demand · √(review_interval) of exposure on top of lead-time exposure — budget for it. Worked ROP/EOQ examples, the review-interval buffer adjustment, and the exact policy-table + trigger-list schemas (the columns verify.sh checks) are in references/reorder-policies.md.

Demand-driven option (DDMRP)

When a static ROP keeps whipsawing on erratic demand — you re-tune it monthly and it is still wrong — switch that SKU to buffer zones instead of a fixed point.

  • Red = safety/critical, sized off lead-time and demand variability.
  • Yellow = demand coverage over the lead time.
  • Green = order cycle / order frequency.

Trigger fires when net flow position = on_hand + on_order − qualified_demand drops from green into yellow. The zones recalculate as demand ramps, so you are not hand-editing safety stock every cycle.

Decision rule: reach for DDMRP only on erratic (Z-class), long-lead, or strategic SKUs — never for steady C items where a flat ROP is cheaper to run. Zone sizing and the net-flow trigger are in references/ddmrp.md. Set review_mode = ddmrp for these SKUs.

Track it

Prove the policy works with a KPI panel — and recompute every metric against the business's own history; the benchmarks below are sanity rails to flag against, not numbers to hallucinate or paste as targets.

KPIFormulaRough rail
Inventory turnoverCOGS / avg inventory≈6–8×/yr (consumer goods)
Days of inventory on handavg inventory / COGS × 365≈30–60 days
GMROIgross margin / avg inventory costtarget > 2.5
Sell-throughunits sold / units received≈70–85% / mo
Stockout ratestockout events / order linestarget < 5%
Fill ratelines filled complete / total linestarget > 95%
Dead-stock flagSKUs with zero movement over a defined windowflag, don't reorder

Cycle counting, not an annual full count. Count in a rolling sequence frequency-tiered off ABC: A items often (monthly/quarterly), C items rarely (annually). The warehouse never stops, and errors on high-value items surface fastest.

Anti-patterns

Anti-patternWhy it bitesDo instead
One uniform service level / review mode across all SKUsOverspends on C, under-protects AABC×XYZ → differentiated Z and review mode
Demand-only SS when lead time is volatileBuffers the wrong variance, still stocks outIndependent or King formula so σ_LT is in the buffer
Treating ROP and order quantity as one number"Wait to order a full batch" → late triggersSeparate reorder_point (when) and order_qty (how much) columns
Using EOQ as a reorder triggerEOQ is a size lever, not a signalTrigger on ROP; size with EOQ
Picking Z by feelService level is undefined and indefensibleSet service level → read Z from the table
Static safety stock on erratic demandRe-tuned monthly and still wrongDDMRP buffer zones, review_mode = ddmrp
Annual full physical countWarehouse stops; high-value errors found too lateABC-tiered rolling cycle counts
Placing/negotiating the PO hereWrong skill owns the buyHand the trigger list to procurement

Hand-offs

  • Raising/negotiating the purchase order, supplier choice, payment terms, PO approval, three-way match → procurement (see ../procurement/SKILL.md). You hand it the trigger list; it executes the buy.
  • Warehousing, picking, packing, shipping, carriers, returns flow → logistics-ops. You set the on-hand target; it physically fulfills.
  • Statistical/ML demand forecast, seasonality decomposition → forecasting. You consume a demand estimate and its variability; you do not own the model.
  • Live KPI dashboard → dashboard. Recurring KPI report → reporting.
  • Pivot tables, ABC cumulative-value sort mechanics in a sheet → spreadsheet-ops.

Signals

GitHub stars
82
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
inventory-ericrisco
Source
github.com/ericrisco/rsc-harness