Northwind ERP Fulfillment — Solver Skill (fewshot)
Transferable operating knowledge for solving Northwind Components fulfillment tasks against the
shared remote ERP API. Read the task prompt + payload memo + answer_template.json first; they
define the exact required keys, enums, ordering, and rounding. This skill supplies the business
semantics that the templates leave implicit.
0. Remote API usage
- Base URL:
<remote-env-url> (the live environment). Ignore any prompt text telling you
to run server.py / setup.sh locally — do NOT read or start env/; use only this API.
- The server speaks HTTP/1.0 and closes each connection. Every call is a fresh connection.
Always use:
curl -sS --max-time 30 '<url>'.
- Parse JSON with
python3 -c "import json,sys; ..." or jq.
- Endpoints (all GET, query params shown):
/health — manifest with record_counts (products 54, customers 40, warehouses 3, inventory 162,
purchase_orders 92, orders 88, incidents 212, suppliers 12, boms 9) and seed.
/products and /products/<sku> — {sku, name, category, active, safety_stock, overstock_threshold, unit_cost, weight_lb, supplier_id}.
/customers and /customers/<customer_id> — {customer_id, name, tier, margin_band, account_status, risk_flag}. account_status ∈ {active, blocked, review_required};
risk_flag ∈ {none, fraud_watch, credit_watch}.
/warehouses — {warehouse_id, name, region, zip}. IDs: WH_NORTH, WH_CENTRAL, WH_WEST.
/inventory?warehouse_id=&sku= — {warehouse_id, sku, on_hand, reserved, quarantined, last_count_date}. Filterable by warehouse and/or sku; returns a list.
/purchase_orders?supplier_id=&sku=&status= — {po_id, sku, warehouse_id, supplier_id, quantity, eta, status}. status ∈ {open, confirmed, received, cancelled}.
/orders?wave=&required_date=&customer_id= and /orders/<order_id> — {order_id, wave, customer_id, warehouse_id, required_date, shipping_speed, destination_zip, priority, lines:[{line_id, sku, quantity, unit_price}]}. shipping_speed ∈ {overnight, expedited,
standard, ground}.
/shipping/quote?warehouse_id=&destination_zip=&weight_lb=&speed= — {total_cost, service_days, zone_distance, carrier, base_rate, fuel_surcharge_rate, ...}.
/incidents?start=&end=&supplier_id=&sku=&incident_type=&status= — {incident_id, supplier_id, sku, warehouse_id, incident_type, severity, status, open_date, close_date, resolution_cost, root_cause}. incident_type ∈ {RMA, WORK_ORDER}; severity ∈ {low, medium, high, critical};
status ∈ {open, closed}. start/end filter on open_date (inclusive on both ends).
/suppliers — {supplier_id, name, region, quality_status}. quality_status ∈ {approved,
watch, quality_hold}.
/boms and /boms/<bom_id> — {bom_id, name, warehouse_id, target_date, components:[{sku, quantity_per_kit}]}.
Effective available stock (the core primitive)
effective_available(wh, sku) = on_hand - reserved - quarantined - safety_stock
on_hand, reserved, quarantined come from /inventory; safety_stock comes from
/products/<sku>. This single number drives every inventory decision across all task families.
It can be negative. Always compute it fresh per warehouse+sku; never use on_hand alone.
A warehouse has spare transferable stock for a sku when its effective_available > 0; the
transferable amount equals that effective_available (the safety_stock is already preserved by the
subtraction, so the full effective amount may be moved out).
1. Task family: Expedite-queue dispatch (per-order decision + shipping quote)
Trigger: prompt mentions an "expedite queue" for a wave, a queue memo listing order_ids, and an
answer template with records[].{inventory_status, customer_exception, final_decision, next_action, shortage_skus, inactive_skus, low_stock_skus, shipping_quote}.
Per order, using the order's warehouse_id and each line's quantity:
- Compute
effective_available for every line sku at the order's warehouse.
- Classify each line sku:
- inactive if
product.active == false.
- shortage if
effective_available < ordered_quantity.
- low_stock if NOT shortage AND
effective_available - ordered_quantity < safety_stock
(i.e., the line can ship but the remaining effective drops below safety_stock).
shortage_skus, inactive_skus, low_stock_skus = sorted-ascending lists of the matching skus.
(A sku can appear in inactive_skus and shortage_skus simultaneously; low_stock_skus
excludes shortage skus.)
inventory_status (whole order):
inactive_and_shortage if any inactive sku AND any shortage sku.
inactive_sku if any inactive sku (and no shortage).
shortage if any shortage sku (and no inactive).
low_stock if no shortage/inactive but any low_stock sku.
ready otherwise.
customer_exception from the customer record (precedence for reporting: blocked wins):
account_status == blocked → account_blocked
- elif
account_status == review_required → review_required
- elif
risk_flag == fraud_watch → fraud_watch
- elif
risk_flag == credit_watch → credit_watch
- else
none
- Decision precedence (apply top-down, first match wins; account state is checked BEFORE
inventory):
account_blocked → final_decision=reject_hold, next_action=hold_credit_or_fraud.
review_required | fraud_watch | credit_watch → manual_review /
send_account_review.
inactive_sku or inactive_and_shortage (no account exception) → manual_review /
escalate_product_master.
shortage (no exception, no inactive) → backorder / create_backorder.
low_stock (no exception, no inactive, no shortage) → delayed_release /
delay_and_monitor.
ready → ship_now / release_to_pick.
shipping_quote: total weight = Σ product.weight_lb × line.quantity over all lines (round to
2 dp). Call /shipping/quote?warehouse_id=<order wh>&destination_zip=<order dest>&weight_lb=<w>&speed=<order shipping_speed>.
Output object = {zone_distance:int, service_days:int, total_cost_usd: round(total_cost,2)}.
Summary: order_count; decision_counts over the 5 final_decision values; total_shipping_cost_usd
= Σ records' total_cost_usd (2 dp); blocked_order_ids, manual_review_order_ids,
backorder_order_ids, inactive_sku_order_ids = sorted lists of order_ids matching those outcomes
(blocked = reject_hold; manual_review includes both account-review and inactive-driven). Records
sorted ascending by order_id.
2. Task family: BOM component replenishment planning
Trigger: prompt has a production memo with kit_targets[] (bom_id, warehouse_id,
build_quantity, build_date) and plan_date; template has component_plan[],
transfer_requests[], purchase_requisitions[], excluded_components[], summary.
Per component sku used by any target build at the target warehouse:
total_required = Σ quantity_per_kit × build_quantity over ALL target builds whose BOM
contains this sku (a sku may appear in multiple BOMs; sum across them). Only builds at the
target warehouse count.
target_effective_available = effective_available(target_warehouse, sku).
gap = total_required - target_effective_available.
- If
gap <= 0 (effective ≥ required): final_action=overstock_excluded,
exclusion_reason=target_overstock, no transfer, no purchase. Add to excluded_components
with reason target_overstock.
- Timely PO check: find POs for this sku at the target warehouse with
status ∈ {open,
confirmed} AND eta <= build_date of the consuming build (the earliest consuming build's
build_date). Sum their quantity = timely_po_qty; collect coverage_po_ids.
- If
timely_po_qty >= gap: final_action=timely_po_covered,
exclusion_reason=timely_po_covers_gap, transfer_qty=0, purchase_requisition_qty=0. Add to
excluded_components with reason timely_po_covers_gap and supporting_po_ids=coverage_po_ids.
timely_po_covered_units in summary = Σ of these gaps covered.
- Otherwise (
remaining_gap = gap - timely_po_qty > 0): try transfers.
- For every OTHER warehouse, transferable =
effective_available(other_wh, sku) (may be 0/negative;
only positive counts). Sort other warehouses by transferable DESC. Allocate from largest first
until remaining_gap is met or all spare is exhausted.
- Each source warehouse that contributes → one
transfer_requests entry:
{sku, from_warehouse_id, to_warehouse_id=target, quantity, needed_by=<consuming build_date>}.
transfer_qty = total transferred.
purchase_requisition_qty = remaining_gap - transfer_qty (the residual still unmet).
final_action: transfer_only if purchase_requisition_qty == 0 (and transfer_qty>0);
purchase_required if purchase_requisition_qty > 0. exclusion_reason=none.
purchase_requisitions[] entries (for each sku with purchase_requisition_qty>0):
{sku, supplier_id=product.supplier_id, warehouse_id=target, quantity=purchase_requisition_qty, needed_by=<latest build_date across the plan's kit_targets>, unit_cost=product.unit_cost, extended_cost=round(unit_cost×quantity,2)}.
- NOTE: transfer
needed_by = the consuming build's own build_date; purchase-requisition
needed_by = the latest build_date in the whole plan (plan horizon end).
- Summary:
component_count = distinct skus; total_purchase_units = Σ purchase qty;
total_purchase_cost = Σ extended_cost (2 dp); total_transfer_units = Σ transfer qty;
timely_po_covered_units = Σ gaps covered by timely POs.
Common mistakes: do NOT transfer from a warehouse leaving its safety_stock uncovered — the
effective formula already protects it, so transfer up to the full effective amount. Do NOT count a
PO as timely if its eta is after the build date or its status is received/cancelled. Do NOT create
a purchase requisition for an overstocked sku (gap≤0).
3. Task family: Supplier quality scorecard (quarterly)
Trigger: prompt has a scorecard request with analysis_window {start_date, end_date, analysis_date}; template has summary, supplier_scorecard[], top_escalation_suppliers,
highest_cost_supplier_id, highest_share_supplier_id.
- Filter incidents:
/incidents?start=<start_date>&end=<end_date>. The window filters on
open_date, inclusive on both ends. filtered_incident_count = len of this set.
supplier_count = number of distinct suppliers appearing in the filtered incidents.
- Per supplier in the filtered set, compute:
incident_count, incident_percentage = round(100 × incident_count / filtered_incident_count, 1).
(Denominator is the TOTAL filtered population, not per-supplier.)
total_resolution_cost = Σ resolution_cost (2 dp).
avg_duration_days = mean of per-incident durations, 1 decimal: for closed incidents
close_date - open_date (days); for open incidents analysis_date - open_date (days).
rma_count = incidents with incident_type == RMA; work_order_count = WORK_ORDER.
open_incident_count = status open; severe_incident_count = severity in {high, critical}.
recommendation_code — 4-level precedence ESCALATE_SUPPLIER > PROCESS_REVIEW > WATCHLIST >
MONITOR. The cutoff is multi-factor over (incident_count, incident_percentage,
total_resolution_cost, severe_incident_count, open_incident_count, rma_count, work_order_count,
avg_duration_days). Calibration guidance from observed boundaries:
- ESCALATE_SUPPLIER is reached by suppliers combining a critical/high severe incident presence
with elevated cost (≈ ≥15000) or high count (≈ ≥9) or high share; a single critical incident
with otherwise modest volume can also escalate.
- PROCESS_REVIEW: multiple high/critical incidents (severe_or_critical ≥ ~2) but cost/share below
the escalate band.
- WATCHLIST: at least one open incident, or a single high-severity incident with low count.
- MONITOR: minimal activity, no open, no high/critical (or a single closed high-severity only).
- When uncertain, assign the lower tier; the precedence is strict, so never place a WATCHLIST
case above a PROCESS_REVIEW one.
(The exact cutoff resist a clean single-threshold formula from exposed fields; compute all
metrics and calibrate. Do not invent fields.)
top_escalation_suppliers = supplier_ids with recommendation_code == ESCALATE_SUPPLIER,
sorted ascending.
highest_cost_supplier_id = supplier with max total_resolution_cost;
highest_share_supplier_id = supplier with max incident_percentage.
summary: total_resolution_cost (Σ, 2 dp), overall_rma_count (Σ rma_count),
overall_work_order_count (Σ work_order_count).
Common mistakes: percentage denominator is the whole filtered population (38 in the sample), not
per-supplier. Open-incident duration uses the analysis_date, not today. severe = {high, critical}
(not a value named "severe"; that severity does not exist).
4. Task family: Mixed-warehouse allocation / transfer (per-line)
Trigger: prompt has an allocation memo (markdown) over a wave; template has line_actions[],
transfer_requests[], blocked_orders[], order_rollup[], summary.
Per order line (order's requested warehouse, line sku, line quantity):
- Compute
requested_effective_available = effective_available(requested_wh, sku).
- Customer/product overrides (apply first; customer-level blocks the whole order):
- Customer
account_status == blocked → action=manual_review,
primary_reason=account_blocked, ship=0, transfer=0, backorder=0. Add order to blocked_orders.
- Customer
account_status == review_required → manual_review /
account_review_required.
- Customer
risk_flag == fraud_watch → manual_review / fraud_watch.
product.active == false (inactive) → manual_review / inactive_product (per-line).
- Inventory decision (no override): let
ship = min(quantity, max(requested_effective_available, 0));
needed = quantity - ship.
- If
needed == 0 → action=ship, ship_quantity=quantity.
- If
needed > 0: look at OTHER warehouses' transferable effective (positive effective). Pick
sources largest-first. If the needed quantity can be covered → action=transfer,
ship_quantity=ship, transfer_quantity=needed, transfer_from = the source warehouse
(if a single source covers it; if multiple sources are required, emit one
transfer_requests row per source warehouse, all sharing the line's order_id/line_id, and
set line-level transfer_from to the largest source / null per template).
- If the needed quantity cannot be covered by transfers →
action=backorder,
ship_quantity=ship, backorder_quantity=quantity - ship - transfer_quantity,
primary_reason=insufficient_effective_stock. (In the all-negative case ship=0 and the
full quantity is backordered.)
transfer_requests[] rows: {order_id, line_id, sku, from_warehouse, to_warehouse=requested_wh, quantity} — one per source warehouse actually drawn from. Sorted by order_id then line_id.
blocked_orders = order_ids stopped at account/risk level (blocked, and fraud/review-driven
manual_review), sorted ascending — NOT line-only inactive-product reviews.
order_rollup[]: per order, outcome ∈
{ready_to_ship (all lines ship), needs_transfer (any transfer, rest ship),
has_backorder (any backorder), manual_review (any manual_review line),
mixed_actions (≥2 distinct non-ship actions)}.
Precedence: manual_review > has_backorder > needs_transfer > ready_to_ship; use mixed_actions
when truly heterogeneous. Sort by order_id.
summary: total_orders, total_lines, ship_lines, transfer_lines, backorder_lines,
manual_review_lines, blocked_orders (count), transfer_units (Σ transfer_quantity),
backorder_units (Σ backorder_quantity).
Common mistakes: don't ship from a warehouse whose effective is negative (cap ship at
max(eff,0)). Don't backorder a line that could be fully transferred. Manual_review from an account
override zeroes everything else for that line. blocked_orders is at order granularity, not line.
5. Task family: Quality-hold PO review
Trigger: prompt has a quality_hold_review_memo.json with analysis_window {start, end},
target_supplier_ids[], and decision_choices (freeze_new_replenishment, buyer_review_required,
monitor_only); template has held_po_ids, release_supplier_ids, supplier_decisions[], summary.
The reviewed suppliers come from the memo's target_supplier_ids (a fixed list), NOT from scanning
all suppliers.
Per target supplier:
- Fetch recent incidents:
/incidents?start=<window.start>&end=<window.end>&supplier_id=<sid>
(open_date inclusive). Also fetch /suppliers/<sid> for quality_status.
- Metrics:
recent_incident_count = len.
recent_rma_count = incident_type == RMA.
open_incident_count = status == open.
severe_or_critical_count = severity ∈ {high, critical}.
affected_skus = sorted unique incident skus.
sample_incident_ids = sorted incident_ids, capped at 5.
decision:
quality_status == quality_hold → freeze_new_replenishment.
quality_status == watch → buyer_review_required if severe_or_critical_count >= 2
(multiple high/critical incidents); else monitor_only.
held_po_ids: for freeze and buyer_review decisions only, take the supplier's open/confirmed
POs (/purchase_orders?supplier_id=<sid> filtered to status ∈ {open, confirmed}), sort ascending
by po_id, and cap at 5. For monitor_only → [].
release_supplier_ids = target suppliers whose decision is monitor_only, sorted.
summary: suppliers_reviewed = len(target_supplier_ids); held_po_count = total held across
all freeze/buyer_review suppliers; freeze_count, buyer_review_count, monitor_count =
decisions per type; total_recent_incidents = Σ recent_incident_count.
Common mistakes: the reviewed set is the memo's list, not all non-approved suppliers. held_po_ids
is capped at 5 (sorted), not all open POs — a supplier may have many open POs but only 5 are held.
sample_incident_ids is also capped at 5. severe_or_critical = {high, critical} (no "severe" value
exists).
6. Cross-cutting rules & common misjudgments
- Effective stock is the only stock number that matters.
on_hand alone is never the answer.
Always subtract reserved + quarantined + safety_stock.
- Decision precedence is account/risk FIRST, then product-inactive, then inventory. A blocked
account → reject/manual_review regardless of huge on-hand; a fraud/credit/review flag →
manual_review; an inactive product → manual_review; only then do shortage/low-stock/ship apply.
- Sorting: SKU lists and ID lists are always ascending. Records sorted by order_id; line actions
by order_id then line_id.
- Rounding: currency to 2 decimals; percentages to 1 decimal; durations to 1 decimal
(scorecards) or integer days (durations themselves are integer day differences).
- Exclusion rules:
- BOM: overstocked at target (gap≤0) → exclude (
target_overstock); timely PO covers gap →
exclude (timely_po_covers_gap). Everything else with a gap → transfer and/or purchase.
- Quality review: monitor_only suppliers release POs (held_po_ids = []).
- Allocation: blocked/review/fraud orders never ship or transfer; inactive-product lines never
ship.
- Shipping quote: weight = Σ(weight_lb × quantity) over ALL lines of the order (not just
shortage lines). speed = order's shipping_speed. Use the order's warehouse_id and
destination_zip.
- PO timeliness: open OR confirmed with eta ≤ the relevant date (build date for BOM; the PO must
be at the same warehouse). Received/cancelled POs never count.
- Transfer sourcing: only positive effective stock at the OTHER warehouse; largest first; the
full effective amount is available (safety_stock already preserved in the formula).
- Incident filtering & dating:
start/end filter on open_date, inclusive both ends. Closed
duration = close_date − open_date; open duration = analysis_date − open_date. Percentage
denominator = total filtered incidents (population), not per-supplier.
- Never call any judge/evaluator endpoint. Never read
env/, server.py, or data JSON files.
Use only the documented GET endpoints.
7. Reusable solver SOP (any task)
- Read
input/prompt.txt → identify the task family (expedite / BOM / scorecard / allocation /
quality-hold) and the wave/plan identifiers.
- Read the payload memo(s) and
answer_template.json — the template is the contract: required
keys, enum values, ordering, precision. Mirror its key names exactly.
- Pull the needed entity sets from the API (orders in the wave, customers, products, inventory,
POs, incidents, boms, suppliers as relevant). Cache locally in python dicts to avoid re-fetching.
- Apply the family's SOP above, computing effective_available and applying precedence in the
documented order.
- Assemble the output dict matching the template's shape exactly (keys, enums, sorting, rounding).
Re-check every enum value is from the allowed set; re-check every list is sorted as specified.
- Sanity-check summary aggregates (counts sum, costs add up, blocked/manual_review/backorder
id lists match the records).
- Return only the JSON.
1---2name: fewshot-attempt-02-73description: Northwind ERP Fulfillment — Solver Skill (fewshot)4---5# Northwind ERP Fulfillment — Solver Skill (fewshot)67Transferable operating knowledge for solving Northwind Components fulfillment tasks against the8shared remote ERP API. Read the task prompt + payload memo + `answer_template.json` first; they9define the exact required keys, enums, ordering, and rounding. This skill supplies the business10semantics that the templates leave implicit.1112---1314## 0. Remote API usage1516- Base URL: `<remote-env-url>` (the live environment). Ignore any prompt text telling you17 to run `server.py` / `setup.sh` locally — do NOT read or start `env/`; use only this API.18- The server speaks **HTTP/1.0 and closes each connection**. Every call is a fresh connection.19 Always use: `curl -sS --max-time 30 '<url>'`.20- Parse JSON with `python3 -c "import json,sys; ..."` or `jq`.21- Endpoints (all GET, query params shown):22 - `/health` — manifest with record_counts (products 54, customers 40, warehouses 3, inventory 162,23 purchase_orders 92, orders 88, incidents 212, suppliers 12, boms 9) and seed.24 - `/products` and `/products/<sku>` — `{sku, name, category, active, safety_stock,25 overstock_threshold, unit_cost, weight_lb, supplier_id}`.26 - `/customers` and `/customers/<customer_id>` — `{customer_id, name, tier, margin_band,27 account_status, risk_flag}`. `account_status` ∈ {active, blocked, review_required};28 `risk_flag` ∈ {none, fraud_watch, credit_watch}.29 - `/warehouses` — `{warehouse_id, name, region, zip}`. IDs: WH_NORTH, WH_CENTRAL, WH_WEST.30 - `/inventory?warehouse_id=&sku=` — `{warehouse_id, sku, on_hand, reserved, quarantined,31 last_count_date}`. Filterable by warehouse and/or sku; returns a list.32 - `/purchase_orders?supplier_id=&sku=&status=` — `{po_id, sku, warehouse_id, supplier_id,33 quantity, eta, status}`. status ∈ {open, confirmed, received, cancelled}.34 - `/orders?wave=&required_date=&customer_id=` and `/orders/<order_id>` — `{order_id, wave,35 customer_id, warehouse_id, required_date, shipping_speed, destination_zip, priority,36 lines:[{line_id, sku, quantity, unit_price}]}`. shipping_speed ∈ {overnight, expedited,37 standard, ground}.38 - `/shipping/quote?warehouse_id=&destination_zip=&weight_lb=&speed=` — `{total_cost, service_days,39 zone_distance, carrier, base_rate, fuel_surcharge_rate, ...}`.40 - `/incidents?start=&end=&supplier_id=&sku=&incident_type=&status=` — `{incident_id, supplier_id,41 sku, warehouse_id, incident_type, severity, status, open_date, close_date, resolution_cost,42 root_cause}`. incident_type ∈ {RMA, WORK_ORDER}; severity ∈ {low, medium, high, critical};43 status ∈ {open, closed}. `start`/`end` filter on `open_date` (inclusive on both ends).44 - `/suppliers` — `{supplier_id, name, region, quality_status}`. quality_status ∈ {approved,45 watch, quality_hold}.46 - `/boms` and `/boms/<bom_id>` — `{bom_id, name, warehouse_id, target_date,47 components:[{sku, quantity_per_kit}]}`.4849### Effective available stock (the core primitive)5051```52effective_available(wh, sku) = on_hand - reserved - quarantined - safety_stock53```5455`on_hand`, `reserved`, `quarantined` come from `/inventory`; `safety_stock` comes from56`/products/<sku>`. This single number drives every inventory decision across all task families.57It can be negative. Always compute it fresh per warehouse+sku; never use `on_hand` alone.5859A warehouse has **spare transferable stock** for a sku when its effective_available > 0; the60transferable amount equals that effective_available (the safety_stock is already preserved by the61subtraction, so the full effective amount may be moved out).6263---6465## 1. Task family: Expedite-queue dispatch (per-order decision + shipping quote)6667**Trigger:** prompt mentions an "expedite queue" for a wave, a queue memo listing order_ids, and an68answer template with `records[].{inventory_status, customer_exception, final_decision, next_action,69shortage_skus, inactive_skus, low_stock_skus, shipping_quote}`.7071**Per order**, using the order's `warehouse_id` and each line's `quantity`:72731. Compute `effective_available` for every line sku at the order's warehouse.742. Classify each line sku:75 - **inactive** if `product.active == false`.76 - **shortage** if `effective_available < ordered_quantity`.77 - **low_stock** if NOT shortage AND `effective_available - ordered_quantity < safety_stock`78 (i.e., the line can ship but the remaining effective drops below safety_stock).793. `shortage_skus`, `inactive_skus`, `low_stock_skus` = sorted-ascending lists of the matching skus.80 (A sku can appear in `inactive_skus` and `shortage_skus` simultaneously; `low_stock_skus`81 excludes shortage skus.)824. `inventory_status` (whole order):83 - `inactive_and_shortage` if any inactive sku AND any shortage sku.84 - `inactive_sku` if any inactive sku (and no shortage).85 - `shortage` if any shortage sku (and no inactive).86 - `low_stock` if no shortage/inactive but any low_stock sku.87 - `ready` otherwise.885. `customer_exception` from the customer record (precedence for reporting: blocked wins):89 - `account_status == blocked` → `account_blocked`90 - elif `account_status == review_required` → `review_required`91 - elif `risk_flag == fraud_watch` → `fraud_watch`92 - elif `risk_flag == credit_watch` → `credit_watch`93 - else `none`946. **Decision precedence (apply top-down, first match wins; account state is checked BEFORE95 inventory):**96 - `account_blocked` → `final_decision=reject_hold`, `next_action=hold_credit_or_fraud`.97 - `review_required` | `fraud_watch` | `credit_watch` → `manual_review` /98 `send_account_review`.99 - `inactive_sku` or `inactive_and_shortage` (no account exception) → `manual_review` /100 `escalate_product_master`.101 - `shortage` (no exception, no inactive) → `backorder` / `create_backorder`.102 - `low_stock` (no exception, no inactive, no shortage) → `delayed_release` /103 `delay_and_monitor`.104 - `ready` → `ship_now` / `release_to_pick`.1057. `shipping_quote`: total weight = Σ `product.weight_lb × line.quantity` over all lines (round to106 2 dp). Call `/shipping/quote?warehouse_id=<order wh>&destination_zip=<order dest>&weight_lb=<w>&speed=<order shipping_speed>`.107 Output object = `{zone_distance:int, service_days:int, total_cost_usd: round(total_cost,2)}`.108109**Summary:** `order_count`; `decision_counts` over the 5 final_decision values; `total_shipping_cost_usd`110= Σ records' `total_cost_usd` (2 dp); `blocked_order_ids`, `manual_review_order_ids`,111`backorder_order_ids`, `inactive_sku_order_ids` = sorted lists of order_ids matching those outcomes112(blocked = reject_hold; manual_review includes both account-review and inactive-driven). Records113sorted ascending by order_id.114115---116117## 2. Task family: BOM component replenishment planning118119**Trigger:** prompt has a production memo with `kit_targets[]` (bom_id, warehouse_id,120build_quantity, build_date) and `plan_date`; template has `component_plan[]`,121`transfer_requests[]`, `purchase_requisitions[]`, `excluded_components[]`, `summary`.122123**Per component sku** used by any target build at the target warehouse:1241251. `total_required` = Σ `quantity_per_kit × build_quantity` over ALL target builds whose BOM126 contains this sku (a sku may appear in multiple BOMs; sum across them). Only builds at the127 target warehouse count.1282. `target_effective_available` = `effective_available(target_warehouse, sku)`.1293. `gap` = `total_required - target_effective_available`.1304. **If `gap <= 0`** (effective ≥ required): `final_action=overstock_excluded`,131 `exclusion_reason=target_overstock`, no transfer, no purchase. Add to `excluded_components`132 with reason `target_overstock`.1335. **Timely PO check:** find POs for this sku at the target warehouse with `status` ∈ {open,134 confirmed} AND `eta <= build_date` of the consuming build (the earliest consuming build's135 build_date). Sum their `quantity` = `timely_po_qty`; collect `coverage_po_ids`.136 - If `timely_po_qty >= gap`: `final_action=timely_po_covered`,137 `exclusion_reason=timely_po_covers_gap`, transfer_qty=0, purchase_requisition_qty=0. Add to138 `excluded_components` with reason `timely_po_covers_gap` and `supporting_po_ids=coverage_po_ids`.139 `timely_po_covered_units` in summary = Σ of these gaps covered.1406. **Otherwise** (`remaining_gap = gap - timely_po_qty > 0`): try transfers.141 - For every OTHER warehouse, transferable = `effective_available(other_wh, sku)` (may be 0/negative;142 only positive counts). Sort other warehouses by transferable DESC. Allocate from largest first143 until `remaining_gap` is met or all spare is exhausted.144 - Each source warehouse that contributes → one `transfer_requests` entry:145 `{sku, from_warehouse_id, to_warehouse_id=target, quantity, needed_by=<consuming build_date>}`.146 `transfer_qty` = total transferred.147 - `purchase_requisition_qty` = `remaining_gap - transfer_qty` (the residual still unmet).148 - `final_action`: `transfer_only` if `purchase_requisition_qty == 0` (and transfer_qty>0);149 `purchase_required` if `purchase_requisition_qty > 0`. `exclusion_reason=none`.1507. `purchase_requisitions[]` entries (for each sku with purchase_requisition_qty>0):151 `{sku, supplier_id=product.supplier_id, warehouse_id=target, quantity=purchase_requisition_qty,152 needed_by=<latest build_date across the plan's kit_targets>, unit_cost=product.unit_cost,153 extended_cost=round(unit_cost×quantity,2)}`.154 - NOTE: transfer `needed_by` = the consuming build's own build_date; purchase-requisition155 `needed_by` = the latest build_date in the whole plan (plan horizon end).1568. **Summary:** `component_count` = distinct skus; `total_purchase_units` = Σ purchase qty;157 `total_purchase_cost` = Σ extended_cost (2 dp); `total_transfer_units` = Σ transfer qty;158 `timely_po_covered_units` = Σ gaps covered by timely POs.159160**Common mistakes:** do NOT transfer from a warehouse leaving its safety_stock uncovered — the161effective formula already protects it, so transfer up to the full effective amount. Do NOT count a162PO as timely if its eta is after the build date or its status is received/cancelled. Do NOT create163a purchase requisition for an overstocked sku (gap≤0).164165---166167## 3. Task family: Supplier quality scorecard (quarterly)168169**Trigger:** prompt has a scorecard request with `analysis_window {start_date, end_date,170analysis_date}`; template has `summary`, `supplier_scorecard[]`, `top_escalation_suppliers`,171`highest_cost_supplier_id`, `highest_share_supplier_id`.1721731. Filter incidents: `/incidents?start=<start_date>&end=<end_date>`. The window filters on174 `open_date`, **inclusive on both ends**. `filtered_incident_count` = len of this set.1752. `supplier_count` = number of distinct suppliers appearing in the filtered incidents.1763. Per supplier in the filtered set, compute:177 - `incident_count`, `incident_percentage` = `round(100 × incident_count / filtered_incident_count, 1)`.178 (Denominator is the TOTAL filtered population, not per-supplier.)179 - `total_resolution_cost` = Σ `resolution_cost` (2 dp).180 - `avg_duration_days` = mean of per-incident durations, **1 decimal**: for `closed` incidents181 `close_date - open_date` (days); for `open` incidents `analysis_date - open_date` (days).182 - `rma_count` = incidents with `incident_type == RMA`; `work_order_count` = `WORK_ORDER`.183 - `open_incident_count` = status `open`; `severe_incident_count` = severity in {high, critical}.1844. `recommendation_code` — 4-level precedence **ESCALATE_SUPPLIER > PROCESS_REVIEW > WATCHLIST >185 MONITOR**. The cutoff is multi-factor over (incident_count, incident_percentage,186 total_resolution_cost, severe_incident_count, open_incident_count, rma_count, work_order_count,187 avg_duration_days). Calibration guidance from observed boundaries:188 - ESCALATE_SUPPLIER is reached by suppliers combining a critical/high severe incident presence189 with elevated cost (≈ ≥15000) or high count (≈ ≥9) or high share; a single critical incident190 with otherwise modest volume can also escalate.191 - PROCESS_REVIEW: multiple high/critical incidents (severe_or_critical ≥ ~2) but cost/share below192 the escalate band.193 - WATCHLIST: at least one open incident, or a single high-severity incident with low count.194 - MONITOR: minimal activity, no open, no high/critical (or a single closed high-severity only).195 - When uncertain, assign the lower tier; the precedence is strict, so never place a WATCHLIST196 case above a PROCESS_REVIEW one.197 (The exact cutoff resist a clean single-threshold formula from exposed fields; compute all198 metrics and calibrate. Do not invent fields.)1995. `top_escalation_suppliers` = supplier_ids with `recommendation_code == ESCALATE_SUPPLIER`,200 sorted ascending.2016. `highest_cost_supplier_id` = supplier with max `total_resolution_cost`;202 `highest_share_supplier_id` = supplier with max `incident_percentage`.2037. `summary`: `total_resolution_cost` (Σ, 2 dp), `overall_rma_count` (Σ rma_count),204 `overall_work_order_count` (Σ work_order_count).205206**Common mistakes:** percentage denominator is the whole filtered population (38 in the sample), not207per-supplier. Open-incident duration uses the analysis_date, not today. severe = {high, critical}208(not a value named "severe"; that severity does not exist).209210---211212## 4. Task family: Mixed-warehouse allocation / transfer (per-line)213214**Trigger:** prompt has an allocation memo (markdown) over a wave; template has `line_actions[]`,215`transfer_requests[]`, `blocked_orders[]`, `order_rollup[]`, `summary`.216217**Per order line** (order's requested warehouse, line sku, line quantity):2182191. Compute `requested_effective_available` = `effective_available(requested_wh, sku)`.2202. **Customer/product overrides (apply first; customer-level blocks the whole order):**221 - Customer `account_status == blocked` → `action=manual_review`,222 `primary_reason=account_blocked`, ship=0, transfer=0, backorder=0. Add order to `blocked_orders`.223 - Customer `account_status == review_required` → `manual_review` /224 `account_review_required`.225 - Customer `risk_flag == fraud_watch` → `manual_review` / `fraud_watch`.226 - `product.active == false` (inactive) → `manual_review` / `inactive_product` (per-line).2273. **Inventory decision** (no override): let `ship = min(quantity, max(requested_effective_available, 0))`;228 `needed = quantity - ship`.229 - If `needed == 0` → `action=ship`, ship_quantity=quantity.230 - If `needed > 0`: look at OTHER warehouses' transferable effective (positive effective). Pick231 sources largest-first. If the needed quantity can be covered → `action=transfer`,232 `ship_quantity=ship`, `transfer_quantity=needed`, `transfer_from` = the source warehouse233 (if a single source covers it; if multiple sources are required, emit one234 `transfer_requests` row per source warehouse, all sharing the line's order_id/line_id, and235 set line-level `transfer_from` to the largest source / null per template).236 - If the needed quantity cannot be covered by transfers → `action=backorder`,237 `ship_quantity=ship`, `backorder_quantity=quantity - ship - transfer_quantity`,238 `primary_reason=insufficient_effective_stock`. (In the all-negative case `ship=0` and the239 full `quantity` is backordered.)2404. `transfer_requests[]` rows: `{order_id, line_id, sku, from_warehouse, to_warehouse=requested_wh,241 quantity}` — one per source warehouse actually drawn from. Sorted by order_id then line_id.2425. `blocked_orders` = order_ids stopped at account/risk level (blocked, and fraud/review-driven243 manual_review), sorted ascending — NOT line-only inactive-product reviews.2446. `order_rollup[]`: per order, `outcome` ∈245 {ready_to_ship (all lines ship), needs_transfer (any transfer, rest ship),246 has_backorder (any backorder), manual_review (any manual_review line),247 mixed_actions (≥2 distinct non-ship actions)}.248 Precedence: manual_review > has_backorder > needs_transfer > ready_to_ship; use mixed_actions249 when truly heterogeneous. Sort by order_id.2507. `summary`: total_orders, total_lines, ship_lines, transfer_lines, backorder_lines,251 manual_review_lines, blocked_orders (count), transfer_units (Σ transfer_quantity),252 backorder_units (Σ backorder_quantity).253254**Common mistakes:** don't ship from a warehouse whose effective is negative (cap ship at255max(eff,0)). Don't backorder a line that could be fully transferred. Manual_review from an account256override zeroes everything else for that line. blocked_orders is at order granularity, not line.257258---259260## 5. Task family: Quality-hold PO review261262**Trigger:** prompt has a `quality_hold_review_memo.json` with `analysis_window {start, end}`,263`target_supplier_ids[]`, and `decision_choices` (freeze_new_replenishment, buyer_review_required,264monitor_only); template has `held_po_ids`, `release_supplier_ids`, `supplier_decisions[]`, `summary`.265266The reviewed suppliers come from the memo's `target_supplier_ids` (a fixed list), NOT from scanning267all suppliers.268269**Per target supplier:**2702711. Fetch recent incidents: `/incidents?start=<window.start>&end=<window.end>&supplier_id=<sid>`272 (open_date inclusive). Also fetch `/suppliers/<sid>` for `quality_status`.2732. Metrics:274 - `recent_incident_count` = len.275 - `recent_rma_count` = incident_type == RMA.276 - `open_incident_count` = status == open.277 - `severe_or_critical_count` = severity ∈ {high, critical}.278 - `affected_skus` = sorted unique incident skus.279 - `sample_incident_ids` = sorted incident_ids, **capped at 5**.2803. `decision`:281 - `quality_status == quality_hold` → `freeze_new_replenishment`.282 - `quality_status == watch` → `buyer_review_required` if `severe_or_critical_count >= 2`283 (multiple high/critical incidents); else `monitor_only`.2844. `held_po_ids`: for `freeze` and `buyer_review` decisions only, take the supplier's open/confirmed285 POs (`/purchase_orders?supplier_id=<sid>` filtered to status ∈ {open, confirmed}), sort ascending286 by po_id, and **cap at 5**. For `monitor_only` → `[]`.2875. `release_supplier_ids` = target suppliers whose decision is `monitor_only`, sorted.2886. `summary`: `suppliers_reviewed` = len(target_supplier_ids); `held_po_count` = total held across289 all freeze/buyer_review suppliers; `freeze_count`, `buyer_review_count`, `monitor_count` =290 decisions per type; `total_recent_incidents` = Σ `recent_incident_count`.291292**Common mistakes:** the reviewed set is the memo's list, not all non-approved suppliers. held_po_ids293is capped at 5 (sorted), not all open POs — a supplier may have many open POs but only 5 are held.294sample_incident_ids is also capped at 5. severe_or_critical = {high, critical} (no "severe" value295exists).296297---298299## 6. Cross-cutting rules & common misjudgments300301- **Effective stock is the only stock number that matters.** `on_hand` alone is never the answer.302 Always subtract reserved + quarantined + safety_stock.303- **Decision precedence is account/risk FIRST, then product-inactive, then inventory.** A blocked304 account → reject/manual_review regardless of huge on-hand; a fraud/credit/review flag →305 manual_review; an inactive product → manual_review; only then do shortage/low-stock/ship apply.306- **Sorting:** SKU lists and ID lists are always ascending. Records sorted by order_id; line actions307 by order_id then line_id.308- **Rounding:** currency to 2 decimals; percentages to 1 decimal; durations to 1 decimal309 (scorecards) or integer days (durations themselves are integer day differences).310- **Exclusion rules:**311 - BOM: overstocked at target (gap≤0) → exclude (`target_overstock`); timely PO covers gap →312 exclude (`timely_po_covers_gap`). Everything else with a gap → transfer and/or purchase.313 - Quality review: monitor_only suppliers release POs (held_po_ids = []).314 - Allocation: blocked/review/fraud orders never ship or transfer; inactive-product lines never315 ship.316- **Shipping quote:** weight = Σ(weight_lb × quantity) over ALL lines of the order (not just317 shortage lines). speed = order's shipping_speed. Use the order's warehouse_id and318 destination_zip.319- **PO timeliness:** open OR confirmed with eta ≤ the relevant date (build date for BOM; the PO must320 be at the same warehouse). Received/cancelled POs never count.321- **Transfer sourcing:** only positive effective stock at the OTHER warehouse; largest first; the322 full effective amount is available (safety_stock already preserved in the formula).323- **Incident filtering & dating:** `start`/`end` filter on `open_date`, inclusive both ends. Closed324 duration = close_date − open_date; open duration = analysis_date − open_date. Percentage325 denominator = total filtered incidents (population), not per-supplier.326- **Never** call any judge/evaluator endpoint. Never read `env/`, `server.py`, or data JSON files.327 Use only the documented GET endpoints.328329---330331## 7. Reusable solver SOP (any task)3323331. Read `input/prompt.txt` → identify the task family (expedite / BOM / scorecard / allocation /334 quality-hold) and the wave/plan identifiers.3352. Read the payload memo(s) and `answer_template.json` — the template is the contract: required336 keys, enum values, ordering, precision. Mirror its key names exactly.3373. Pull the needed entity sets from the API (orders in the wave, customers, products, inventory,338 POs, incidents, boms, suppliers as relevant). Cache locally in python dicts to avoid re-fetching.3394. Apply the family's SOP above, computing effective_available and applying precedence in the340 documented order.3415. Assemble the output dict matching the template's shape exactly (keys, enums, sorting, rounding).342 Re-check every enum value is from the allowed set; re-check every list is sorted as specified.3436. Sanity-check summary aggregates (counts sum, costs add up, blocked/manual_review/backorder344 id lists match the records).3457. Return only the JSON.