Skip to main content

inventory

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`).

Jump to install

Source facts

Repository
ericrisco/rsc-harness
Last source activity
July 29, 2026 at 23:15
Detected SKILL.md language
English
Stars
110
Forks
9

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
8 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
inventory
description
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`).
tags
["reorder-point","safety-stock","eoq","abc-xyz","replenishment","inventory-kpis","ddmrp","min-max"]
recommends
["procurement","logistics-ops","forecasting","dashboard","reporting","spreadsheet-ops"]
origin
risco
# Inventory 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 like | Job | You produce | |---|---|---| | "which SKUs deserve tight control", "run ABC" | **Classify** | ABC×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 buffer** | `safety_stock` per SKU, chosen Z, chosen formula | | "what's my reorder point", "set up min/max", "weekly or continuous" | **Set policy** | `reorder_point`, `order_qty`, `review_mode` → the full policy table | | "is our stock policy working", "turnover", "cut dead stock" | **Track** | KPI 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. ```text 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 level | Z | |---|---| | 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*. ```text 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: | Mode | How it works | Use when | Cost | |---|---|---|---| | Continuous (min-max / s,S) | Order the moment on-hand hits ROP `s`, bring up to `S` | A items, perpetual stock visibility | Fastest reaction, needs live counts | | Periodic | Check on a fixed cadence (e.g. every Friday), order up to target | B/C items, batched POs, no live system | Needs 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. | KPI | Formula | Rough rail | |---|---|---| | Inventory turnover | COGS / avg inventory | ≈6–8×/yr (consumer goods) | | Days of inventory on hand | avg inventory / COGS × 365 | ≈30–60 days | | GMROI | gross margin / avg inventory cost | target > 2.5 | | Sell-through | units sold / units received | ≈70–85% / mo | | Stockout rate | stockout events / order lines | target < 5% | | Fill rate | lines filled complete / total lines | target > 95% | | Dead-stock flag | SKUs with zero movement over a defined window | flag, 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-pattern | Why it bites | Do instead | |---|---|---| | One uniform service level / review mode across all SKUs | Overspends on C, under-protects A | ABC×XYZ → differentiated Z and review mode | | Demand-only SS when lead time is volatile | Buffers the wrong variance, still stocks out | Independent or King formula so `σ_LT` is in the buffer | | Treating ROP and order quantity as one number | "Wait to order a full batch" → late triggers | Separate `reorder_point` (when) and `order_qty` (how much) columns | | Using EOQ as a reorder trigger | EOQ is a size lever, not a signal | Trigger on ROP; size with EOQ | | Picking Z by feel | Service level is undefined and indefensible | Set service level → read Z from the table | | Static safety stock on erratic demand | Re-tuned monthly and still wrong | DDMRP buffer zones, `review_mode = ddmrp` | | Annual full physical count | Warehouse stops; high-value errors found too late | ABC-tiered rolling cycle counts | | Placing/negotiating the PO here | Wrong skill owns the buy | Hand 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.
View on GitHub