Example flows¶
Three end-to-end flows that exercise the full contract: outbound picking, inbound receiving, and poll-mode dispatch. Each flow uses the recommended webhook transport for dispatch except where noted.
Outbound picking¶
The planner releases a shipper. The executor expands it into floor tasks, executes them, posts realtime feedback, and posts an authoritative shift summary at close.
Planner Executor
│ │
│ 1. Release shipper SH-2026-000183 │
├─────────────────────────────────────────────►│
│ POST <executor>/webhooks/dispatch │
│ { kind: SHIPPER_RELEASED, routing: …, │
│ correlation_id: cid-101 } │
│ │
│ 2. Expand to tasks; │
│ assign workers │
│ │
│ 3. PICK movement (SKU x12, A.12.3.1) │
│◄─────────────────────────────────────────────┤
│ POST /wes/v1/realtime/movements │
│ { kind: PICK, qty: 12, …, │
│ correlation_id: cid-201 } │
│ │
│ 4. EXCEPTION short-pick (3 short) │
│◄─────────────────────────────────────────────┤
│ POST /wes/v1/realtime/exceptions │
│ { code: SHORT_PICK, severity: HIGH } │
│ │
│ 5. SHIP movement │
│◄─────────────────────────────────────────────┤
│ │
│ 14:00 — shift │
│ close. │
│ │
│ 6. Shift summary for window 06:00–14:00 │
│◄─────────────────────────────────────────────┤
│ POST /wes/v1/confirmation/shift-summary │
│ │
│ 7. Reconcile: sum(realtime) vs summary. │
│ If equal → RECONCILED. If not → │
│ DISCREPANCY queued for supervisor. │
│ │
Key invariants:
cid-101(dispatch) is generated by the planner; the executor stores it for idempotency.cid-201(realtime) and the confirmationcorrelation_idare generated by the executor.The exception’s
correlation_idis independent — exceptions are separate events, not metadata on the movement.
Inbound receiving¶
Planner Executor
│ │
│ 1. Create receiver RCV-2026-005512 from PO │
│ │
│ 2. RECEIVER_EXPECTED dispatch │
├─────────────────────────────────────────────►│
│ │
│ 3. Orchestrate dock arrival,│
│ inspection, putaway │
│ │
│ 4. RECEIVE movements (per pallet) │
│◄─────────────────────────────────────────────┤
│ │
│ 5. PUT movements (to bin) │
│◄─────────────────────────────────────────────┤
│ │
│ 6. Shift summary or inventory snapshot │
│◄─────────────────────────────────────────────┤
│ │
│ 7. Reconcile │
│ │
For ASN-driven receiving, the dispatch payload includes the expected lines[] with SKUs and quantities; the executor compares actuals against expected and emits EXCEPTION records for any mismatch (WRONG_SKU, DAMAGE, missing quantity).
Poll-mode dispatch¶
Used when the executor cannot accept inbound webhooks and cannot reach a shared Kafka — typically when the executor sits behind a strict egress-only firewall.
Executor Planner
│ │
│ 1. GET /wes/v1/dispatch/pending? │
│ since=cur-100&limit=100 │
├─────────────────────────────────────────────►│
│ │
│ ◄── 200 OK │
│ [event-101, event-102, ..., event-145] │
│ next_cursor: cur-145 │
│ │
│ 2. Durably store all 45 events; │
│ expand to tasks; assign work │
│ │
│ 3. POST /wes/v1/dispatch/ack │
│ { cursor: cur-145 } │
├─────────────────────────────────────────────►│
│ │
│ 4. Repeat in a steady loop │
│ │
Important properties:
Step 2 must complete (durably persist) before Step 3. An ack before durable storage means lost events on a crash.
An
ackis a no-op if the cursor is earlier than the planner’s last acked cursor. Cursors are monotone.The executor should run this pull loop at a cadence appropriate to dispatch volume — typical: every 5–30 seconds. Higher rates are fine but produce more idle round-trips.
Discrepancy resolution¶
A supervisor workflow, not a contract endpoint, but worth illustrating because it is the most common operational path after rollout:
Confirmation arrives at the planner; reconciler finds the realtime sum and the confirmation summary disagree.
Planner marks the window
DISCREPANCY. A supervisor queue entry is created.Planner fires an
URGENTnotification (NovaBell on the FG.AI WMS side; vendor’s equivalent elsewhere).The supervisor opens the queue entry. The planner UI shows: confirmation totals, realtime sum, per-SKU breakdown, exceptions logged in the window.
The supervisor selects one of:
Accept confirmation — planner overwrites the realtime contribution with the confirmation totals.
Accept realtime — planner discards the confirmation deltas.
Manual adjustment — planner creates compensating
ADJUSTmovements and re-runs reconciliation.
Window moves to
RECONCILED.wes.window.reconciled.v1is emitted withresolved_by: <supervisor_id>andresolution_reason: <text>.
The reconciler does not retry. A window stays in DISCREPANCY until a supervisor acts. Auto-resolution is not in scope for the contract.