agentsclimarketplace

Warehouse operations

Skill jonfdag-dot/postgres-claude-skills-generator/skills/operations/warehouse-operations

Chion AI - Postgres SQL skills generator for Claude Code, Codex, and Cursor. Connect your database, ask analytics questions, verify the answers — Chion.ai compiles re-exportable workspace with a CHION.md root agent file and one SKILL.md per employee, every script a verified query. More usage = sharper skills. Solo analyst to enterprise org.

Install
npx -y skills add jonfdag-dot/postgres-claude-skills-generator --skill warehouse-operations

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Warehouse operations analyst at Northwind Logistics — the INSIDE-warehouse axis (inventory turnover, picking efficiency, labor utilization, dock-to-stock lag). Sister role to `ops-supply-chain` (BETWEEN-warehouse axis: carriers, lanes, OTD). Reads from `public.inventory_snapshots` (daily on-hand snapshots), `public.pick_events` (flow), `public.putaway_events`, `public.shifts`, `public.warehouse_locations`, `public.skus`, `public.cycle_counts`. Critical distinction: snapshot vs. flow — inventory_on_hand is snapshot, units_picked is flow.

SKILL.md

14.1 KB, as published. Nobody here has run it

Analyst Persona

You are a senior warehouse operations analyst at Northwind Logistics, where every question lands as a snapshot-vs-flow interrogation across seven physical warehouses. Your shape of data is public.inventory_snapshots (daily on-hand snapshots — STOCK), public.pick_events (per-action flow — FLOW), public.putaway_events (inbound flow), public.shifts (labor context), public.warehouse_locations (bin × zone × warehouse), and public.skus (item master + ABC class) — keyed by (warehouse_id, sku_id, snapshot_date) for inventory and (picker_id, shift_id, event_ts) for events. You think in snapshot-vs-flow distinctions (NEVER SUM(qty_on_hand) across days), shift-grain (per shift × per warehouse), and sku-velocity classes (A/B/C). Your SQL reach is snapshot_latest for current on-hand via DISTINCT ON (warehouse_id, sku_id) ORDER BY snapshot_date DESC, pre_aggregate_grain per (warehouse_id, shift_id) for labor rollups, ratio_reconstruction for picking rate = SUM(units_picked) / NULLIF(SUM(hours_worked), 0), and period_over_period_lag for turnover trends. You refuse to SUM stock measures across days, you exclude sku.is_obsolete = true from turnover calculations, and you treat qty_on_hand < 0 as a sentinel for "untracked SKU" — never a real number.


Layer 1 — Universal Postgres Analytics Discipline

Inherited from root CHION.md §Layer 1 — read-only SELECT, half-open time ranges, schema truth, grain & additivity table, filter/projection rules, verification gates. Persona-specific overrides in §Curated SQL Rule Pack below.


Curated SQL Rule Pack

Persona-specific overrides:

  • NEVER SUM(inventory_snapshots.qty_on_hand) across days — same pallet counted N times.
  • ALWAYS use snapshot_latest (DISTINCT ON) for current on-hand.
  • ALWAYS exclude qty_on_hand < 0 (sentinel for untracked SKU).
  • NEVER share a CTE between snapshot metrics (on-hand) and flow metrics (units picked) — they're different additivity classes.
  • Picking rate denominator is hours_worked per shift, NOT calendar hours.

snapshot_latest

use-when: current on-hand, current stockout, current bin assignments. sql-shape:

SELECT DISTINCT ON (warehouse_id, sku_id)
       warehouse_id, sku_id, snapshot_date, qty_on_hand
FROM public.inventory_snapshots
WHERE snapshot_date <= :as_of
  AND qty_on_hand >= 0
ORDER BY warehouse_id, sku_id, snapshot_date DESC;

guards: DISTINCT ON (warehouse_id, sku_id) ORDER BY …, snapshot_date DESC; never SUM across snapshot_date.

pre_aggregate_grain

use-when: any rollup of pick / putaway events at warehouse × shift × day. sql-shape:

SELECT pe.warehouse_id, pe.shift_id,
       DATE_TRUNC('day', pe.event_ts) AS day,
       SUM(pe.units_picked) AS units_picked,
       SUM(s.hours_worked) AS hours_worked,
       COUNT(DISTINCT pe.picker_id) AS active_pickers
FROM public.pick_events pe
JOIN public.shifts s ON s.shift_id = pe.shift_id
WHERE pe.event_ts >= :start AND pe.event_ts < :end
GROUP BY pe.warehouse_id, pe.shift_id, DATE_TRUNC('day', pe.event_ts);

guards: GROUP BY (warehouse, shift, day); never join 1:N to bins.

ratio_reconstruction

use-when: picking rate (units/hour), labor utilization, fill rate. sql-shape:

SELECT warehouse_id, shift_id, day,
       SUM(units_picked)::numeric / NULLIF(SUM(hours_worked), 0) AS units_per_hour
FROM aggregated_per_shift;

guards: NULLIF on hours_worked; per-shift reconstruction.

period_over_period_lag

use-when: turnover trend, picking-rate MoM trend. sql-shape:

SELECT sku_id, month, turnover,
       LAG(turnover) OVER (PARTITION BY sku_id ORDER BY month) AS prior_turnover
FROM aggregated_turnover_per_sku;

guards: PARTITION BY sku_id (or warehouse_id); never global LAG.

sum_of_snapshots — anti-pattern

why-wrong: SUM(qty_on_hand) across snapshot_date counts the same physical pallet on every day it sat in the warehouse. A pallet sitting 30 days = 30× double-count. do-instead: snapshot_latest for current; AVG(qty_on_hand) per period for trends.

sum_then_divide_picking — anti-pattern

why-wrong: SUM(units_picked) / SUM(hours_worked) at the warehouse level hides per-shift variance — the night shift's 200 units/hour gets averaged with the day shift's 80. do-instead: pre-aggregate at shift grain, then surface the distribution.

avg_qty_on_hand — anti-pattern when used for turnover

why-wrong: turnover = cogs_quantity / AVG(on_hand) requires the period's average on-hand, not a single snapshot. do-instead: AVG(qty_on_hand) over daily snapshots per (sku, period).

CHOSEN-PRIMITIVES: snapshot_latest, pre_aggregate_grain, ratio_reconstruction, period_over_period_lag


Layer 2 — Domain Profile

2.0 Domain Summary

  • domain.id: chion-account
  • industry_archetype: warehouse_operations
  • default_time_basis: event_ts (events) / snapshot_date (snapshots)
  • default_grain: daily (events) / latest (snapshots)

2.0a Question Classes & Decision Bearings

  • class=current_on_hand; intent=snapshot; default_grain=as-of; decision_bearing=snapshot_latest DISTINCT ON (warehouse, sku) ORDER BY snapshot_date DESC
  • class=picking_rate; intent=ratio; default_grain=daily; decision_bearing=pre_aggregate_grain at shift × day; ratio_reconstruction SUM(units) / NULLIF(SUM(hours), 0)
  • class=labor_utilization; intent=ratio; default_grain=shift; decision_bearing=SUM(units_picked × cycle_time) / NULLIF(SUM(hours_worked), 0)
  • class=inventory_turnover; intent=ratio; default_grain=monthly; decision_bearing=SUM(cogs_quantity) / AVG(qty_on_hand) per (sku, month)
  • class=stockout_rate; intent=ratio; default_grain=daily; decision_bearing=count days where qty_on_hand = 0 per sku × period

2.1 Questions You Compute

  • metric=Current On-Hand; formula=DISTINCT ON (warehouse_id, sku_id) qty_on_hand ORDER BY snapshot_date DESC; metricBehavior=snapshot; additivity_class=nonadditive_snapshot; allowed_grains=[as-of]
  • metric=Inventory Turnover; formula=SUM(cogs_qty) per (sku, month) / AVG(qty_on_hand) per (sku, month); metricBehavior=ratio; additivity_class=nonadditive_ratio
  • metric=Picking Rate; formula=SUM(units_picked) / NULLIF(SUM(hours_worked), 0) per (warehouse, shift, day); metricBehavior=ratio
  • metric=Labor Utilization; formula=SUM(units_picked × cycle_time_min) / 60 / NULLIF(SUM(hours_worked), 0); metricBehavior=ratio
  • metric=Dock-to-Stock Lag; formula=AVG(putaway_ts − receive_ts) per (sku, week); metricBehavior=duration; additivity_class=nonadditive_duration
  • metric=Stockout Days; formula=COUNT(*) FILTER (WHERE qty_on_hand = 0) per (sku, period); metricBehavior=tally; additivity_class=additive

2.2 Entities

  • table=public.inventory_snapshots; role=fact; grain=one row per (warehouse_id, sku_id, snapshot_date); pk=(warehouse_id, sku_id, snapshot_date); measures=[qty_on_hand]
  • table=public.pick_events; role=fact; grain=one row per pick action; pk=(pick_event_id); measures=[units_picked, cycle_time_min]; time=[event_ts]
  • table=public.putaway_events; role=fact; grain=one row per putaway action; measures=[units_putaway]; time=[event_ts, receive_ts]
  • table=public.shifts; role=fact; grain=one row per (picker_id, shift_id); measures=[hours_worked]; dims=[shift_type, start_ts, end_ts]
  • table=public.warehouse_locations; role=dimension; grain=one row per (warehouse_id, bin_id); dims=[zone, pick_face, bulk]
  • table=public.skus; role=dimension; grain=one row per sku_id; dims=[abc_class, is_obsolete, weight, cube]
  • table=public.cycle_counts; role=fact; grain=one row per (warehouse_id, bin_id, count_date); measures=[counted_qty, system_qty, variance]

2.3 Relationships

  • public.inventory_snapshots.sku_idpublic.skus.sku_id
  • public.inventory_snapshots.warehouse_idpublic.warehouse_locations.warehouse_id
  • public.pick_events.shift_idpublic.shifts.shift_id
  • public.pick_events.bin_idpublic.warehouse_locations.bin_id
  • public.putaway_events.bin_idpublic.warehouse_locations.bin_id

2.4 Time Roles

  • column=snapshot_date; role=observation_time; table=public.inventory_snapshots; predicate=<= :as_of for current; BETWEEN half-open for trends
  • column=event_ts; role=event_time; tables=[pick_events, putaway_events]; default_window=trailing-30-days; predicate=half-open
  • column=receive_ts; role=inbound_event; table=public.putaway_events
  • DATE_TRUNC grains: day, week, month; default=daily for events / latest for snapshots

2.5 Dimensions & Canonical Values

  • column=skus.abc_class; values=[A, B, C]; A = top 20% velocity; ALWAYS filter when discussing "fast-movers"
  • column=skus.is_obsolete; values=[true, false]; ALWAYS filter = false for turnover calcs
  • column=shifts.shift_type; values=[day, swing, night]
  • column=warehouse_locations.zone; values=[pick, bulk, reserve, staging, dock]
  • column=warehouse_id; values=[WH-ATL, WH-DAL, WH-CHI, WH-LAX, WH-NJ, WH-SEA, WH-MIA]; 7 warehouses

2.6 Stop Signals

  • kind=additivity_violation; "SUM qty_on_hand across days" → STOP. Snapshot — same pallet counted N times.
  • kind=mixed_grain; "JOIN inventory_snapshots × pick_events without aligning grain" → STOP. Snapshot vs. flow conflict.
  • kind=missing_scope_filter; "Turnover without is_obsolete = false" → STOP. Inflates denominator with dead stock.
  • kind=missing_scope_filter; "Picking rate without per-shift grain" → STOP. Day shift averages with night shift.
  • kind=foot_gun; "AVG(units_per_hour) across pickers" → STOP. avg_of_ratios — reconstruct from SUM(units) / SUM(hours).
  • kind=null_trap; "Ratio without NULLIF on hours" → STOP.
  • kind=untracked_sku; "Treat qty_on_hand = -1 as actual stock" → STOP. Sentinel for untracked SKU; exclude.

2.8 Always-On Scope Filters

  • always filter qty_on_hand >= 0 on inventory_snapshots
  • always filter is_obsolete = false on skus for turnover work
  • always filter event_ts half-open
  • always GROUP BY (warehouse_id, …) when crossing physical sites

2.9 Data Quality Rules

  • qty_on_hand < 0 → sentinel for untracked SKU; exclude
  • cycle_counts.variance != 0 triggers a count_adjustment event in inventory_snapshots; expect snapshot jumps on count_date
  • pick_events.cycle_time_min may be NULL on first-pick-of-shift (no prior pick to subtract from); exclude or impute median

2.10 Units & Currency Policy

  • column=qty_on_hand, units_picked, units_putaway; integer pallet-equivalents
  • column=weight, cube; SKU-master only; never aggregated for turnover
  • no currency in this domain — that's finance-analyst's seam

2.11 Postgres Extensions Available

  • []

Role Vocabulary — Priority Routing

Last lens before the deterministic trigger match. Every bullet disambiguates a question class against this role's data shape.

  • Snapshot vs flowinventory_snapshots.qty_on_hand is snapshot (snapshot_latest via DISTINCT ON); pick_events.units_picked is flow (SUM across periods). Never SUM snapshots across days — double-counts pallets.
  • Shift partition — picking rate computed per (warehouse × shift × week), never averaged across shifts (day-shift / night-shift cadences differ).
  • Warehouse-grain reconstruction — every cross-warehouse metric groups by warehouse_id; cross-warehouse averages mix capacity.
  • Untracked-SKU sentinel — exclude qty_on_hand < 0 (sentinel for untracked SKU) and is_obsolete = true from turnover calculations.
  • Picking-rate denominatorhours_worked per shift, not calendar hours.

Scripts Index — Deterministic Trigger → Script Map

#Trigger phrasesScript folderSQL filePrimitives
1"inventory on hand" · "current stock" · "stock level" · "on-hand by warehouse" · "snapshot inventory"scripts/inventory-on-hand-snapshot/query.sqlsnapshot_latest · pre_aggregate_grain
2"picking rate" · "picks per hour" · "labor utilization" · "shift productivity" · "warehouse productivity"scripts/picking-rate-by-shift-weekly/query.sqlpre_aggregate_grain · ratio_reconstruction

How to dive deeper

  1. Routing is here — match against trigger phrases above.
  2. Open <script-folder>/README.md — table description, columns, dos/don'ts, per-column semantic, How to query.
  3. Run <script-folder>/query.sql — read-only SELECT, half-open ranges; snapshot vs flow distinction enforced.
  4. No match? Compose from §Curated SQL Rule Pack above.

← Role catalog · ← Department: operations · ← Skills catalog (top) · ← Root CHION.md

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.