Demand-to-Schedule: Building the Per-Unit Labor and Prep Pipeline
Demand-to-Schedule: Building the Per-Unit Labor and Prep Pipeline
It is Friday at unit 214. The forecast says a 7pm rush. The schedule has to seat a closing line that honors a 30-minute meal break before hour five, work around the part-timer who blocked out availability after 9, and keep a sixteen-year-old off the close entirely. And somebody has to thaw the right number of protein portions by 4pm so the line isn’t waiting on a walk-in at peak. Get the cover count wrong and you’re slammed and short. Get the prep math wrong and you’ve either 86’d the bestseller or thrown out forty portions. Get the break timing wrong and you’ve created a predictability-pay liability the COO finds in next month’s labor variance.
That is the build this paper is about: the pipeline that turns a per-unit demand forecast into a compliant labor schedule and a prep sheet a GM doesn’t throw out — and then keeps adjusting both as Friday actually unfolds. If you own restaurant ops systems or you’re the engineer who has to make labor planning real across a fleet of units, this is your reference design: the forecast model, the compliance guardrails wired in as constraints, the prep-quantity math tied to the same cover curve, and the intraday loop that re-forecasts when the 7pm rush shows up at 6:15.
The pipeline, end to end
A daily sales number cannot schedule a kitchen, and a generic “AI scheduling” toggle cannot keep one legal. What a multi-unit operator needs is a deterministic pipeline that runs per unit, stage by stage, with the POS as the input of record and a compliant schedule plus a prep sheet as the output. The stages are simple to name and the whole design lives in keeping them clean:
- 01Daypart forecastcovers per 15-min interval, per unit
- 02Labor requirementcovers → positions by station and interval
- 03Compliant schedulepositions → named shifts inside labor law
- 04Prep sheetsame covers → portions and thaw times
- 05Intraday re-forecastactuals diverge → auto-adjust or GM flag
The architectural rule that makes this safe is the same one that makes it cheap to change: your POS, your KDS, and your timekeeping system hold the truth, and this pipeline only reads them. It proposes a schedule and a prep sheet; it never rewrites a punch or a sale. That boundary is what lets you swap the forecasting model, retune the labor-requirement curve, or update a state’s scheduling rule without touching the systems your payroll and your audit trail depend on. The leverage is in the pipeline; the record sits behind glass.
Forecasting the daypart at the unit
Everything downstream is only as good as stage one, and stage one has to be local. A grill line and a front register do not peak at the same minute; a dine-in dinner rush and a delivery dinner rush stack on the same clock with different prep consequences. So the forecaster predicts covers per 15-minute interval, per daypart, per station-group, per unit — not a store-day total divided by a productivity target, which is exactly the average that dissolves the lunch wave you’re trying to staff.
The signal is mostly already in your four walls. POS transaction history gives the intraday shape and the day-of-week and seasonal pattern. Layer in the things that bend the curve and aren’t in the transaction log: weather (a 38-degree rain kills patio covers and triples delivery), the local events calendar (a high-school graduation, a stadium night, a convention two blocks over), and the school calendar that governs your minor availability and your after-school rush. A unit-level model beats a chain-wide one here because the elasticity is local — the same rainstorm that empties a downtown lunch fills a suburban drive-thru — and the cold-start path for a new unit is to borrow a similar unit’s curve until the new one has its own POS history to learn from.
The forecaster’s accuracy at the quarter-hour is the leading indicator for the whole pipeline. If it’s right, the schedule and the prep sheet are right by construction. If it drifts, you’ll see it in the intraday loop before you see it in the P&L — which is the point of measuring it directly rather than inferring it from labor cost after the fact.
Generating a schedule that’s legal by construction
Here is where most labor tools quietly fail: they produce a schedule and then run a compliance check, which means the violating schedule existed, got flagged, and — at an understaffed unit at 11pm — sometimes shipped anyway because the GM needed bodies on the floor. Invert it. Labor law is not a filter the schedule passes through afterward; it is the boundary the scheduler is allowed to search inside. An assignment that would skip a mandated meal break or close a minor is never assembled, so there is nothing to flag.
The labor-requirement stage converts the cover curve into positions-by-interval; the scheduling stage packs real people into those positions as an optimization confined to hard constraints:
SCHEDULE unit=214 day=Fri
INPUT labor_req[station][quarter_hour] // from the cover forecast
PACK employees -> shifts
GOAL minimize labor_cost
subject to coverage >= labor_req AND speed_of_service_target
HARD CONSTRAINTS (the feasible region — never relaxed):
shift_len >= 6.0h => meal_break 30min unpaid, started in hours 2..5
weekly_hours > 40 => overtime_pay; block if budget_ot == false
employee.is_minor => daily_hours <= 8 AND end_time <= 22:00 AND not close_shift
employee.availability => assign only within blocked windows
jurisdiction.fair_workweek
=> post_schedule >= 14d_ahead
AND change_inside_14d => predictability_pay accrues
clopening => rest_between_shifts >= 10h
DECISION: emit named_schedule
IF infeasible THEN relax SOFT goals only (cost, ideal coverage),
never a HARD constraint; flag gap -> route "LaborPlanning"
The infeasible branch matters as much as the happy path. When the only legal way to cover the 7pm peak would breach a constraint — you’re short a qualified closer, or covering would force overtime the budget blocks — the scheduler does not silently produce an illegal schedule and does not silently leave the floor short. It surfaces a named coverage gap and routes it to the human who owns labor planning, with the reason attached. Legal-by-construction beats legal-by-review precisely because the review step is where short-staffed units cut the corner.
Prep quantities from the same cover curve
The prep sheet is not a separate forecast; it is the other read of the one you already made. The interval cover curve that says you need a second cook on the grill at 6:45 is the same curve that says you need sixty more protein portions staged by 6:30 and a walk-in pulled to thaw by 4. Drive both from one demand signal and waste and stockout stop trading blindly against each other — you over-thaw less and run out less, because both are anchored to the same predicted covers rather than to a line cook’s gut and last week’s number.
Mechanically: map forecasted covers to menu mix (which items those covers buy, by daypart), map mix to ingredient portions through the recipe yields, then subtract on-hand and net against lead time — a protein that needs a four-hour thaw has to be pulled against the 4pm state of the 7pm forecast, not the 6:45 one. The prep sheet the unit prints is portions-by-station-by-time with the thaw and par-build clock already computed. Because it’s anchored to covers, the intraday loop can revise it: if 5pm actuals are running hot, the engine can bump the par and tell the kitchen to pull more while there’s still thaw time left to act on it.
The intraday loop: auto-adjust inside the lines, flag the rest
A forecast made Tuesday for Friday is a starting position, not a verdict. The pipeline re-forecasts through the day as real covers land, compares actual-to-forecast per interval, and decides — automatically — whether the divergence is small enough to absorb or large enough to escalate. The governing principle is that the cost of being wrong is not symmetric, so the gate isn’t either: over-prepping forty portions costs the food cost of the waste, while under-staffing the dinner peak costs speed-of-service and the refunds it triggers across every delivery channel at once. The engine adjusts the cheap, reversible things on its own and reserves the expensive, hard-to-reverse things for the GM.
Every adjustment and every flag is one logged, replayable record — both the audit trail a labor dispute needs and the labeled data the forecaster trains on:
{
"eventType": "IntradayReforecast",
"unit": "HOU-214",
"daypart": "Dinner",
"interval": "2026-02-24T18:45:00-06:00",
"station": "Grill",
"forecastCovers": 88,
"actualCoversToDate": 71,
"projectedPeakCovers": 96,
"action": "auto_adjust",
"laborChange": { "redeploy": "+1 from prep", "addPay": false },
"prepChange": { "protein_portions": "+12", "thaw_window_ok": true },
"complianceCheck": "pass",
"gmFlag": null,
"policyVersion": "rest.schedule.v4",
"modelVersion": "daypart-forecast-2.2.0",
"correlationId": "rst-6b77c0",
"evaluatedAt": "2026-02-24T17:55:02-06:00"
}
Note addPay: false and thaw_window_ok: true: the engine auto-acts only because the move costs no predictability pay and there’s still thaw time to honor. Flip either, and action becomes flag_gm and the record carries the reason. The gmFlag block, when present, is the asset — it captures exactly what the data couldn’t see.
Closing the loop: actuals and overrides re-train the unit
The GM is the sensor for the world the POS can’t reach. A closed road, a bus tour in the lot, a competitor dark for a remodel — none of that is in the transaction history, and all of it moves Friday’s covers. When the GM accepts a flag and adds two to the close because she knows about the graduation, that decision is a labeled example the forecast didn’t have. So the overnight retrain folds two things back into each unit’s model: the actual covers by interval (did the 7pm rush land at 7, or at 6:15?) and the GM’s reasons on every override and accepted flag.
Two metrics tell you the loop is healthy. Interval forecast accuracy — predicted versus actual covers per quarter-hour — is the leading indicator the whole pipeline rides on. Override-and-flag rate is your conscience: a rate that falls week over week means the model is absorbing the floor’s local knowledge; a rate that stays high or climbs means the forecaster is systematically blind to something — a recurring event, a seasonal break, a bad station baseline — and the logged reasons point straight at it. The library of those reasons, accumulated unit by unit, is the part a competitor can’t buy: they can license the same POS and rent the same forecasting model tomorrow, but not your encoded knowledge of which units spike on which local events.
- Interval forecast accuracy55–78%82–94%Leading indicator
- Schedules a GM rebuilds by hand30–60%5–15%Adoption / trust
- Prep waste vs. 86'd itemsboth highboth fall togetherCost / sales
- Labor minutes per order4.5–11 min3.0–7.0 minProductivity
- Compliance violationsflagged afternone generatedLegal risk
Runbook: onboard a unit, survive a special event
Two procedures cover most of operating this thing.
Onboarding a new unit. Wire the POS, KDS, and timekeeping feeds read-only and confirm the punch and sales reconcile against payroll before trusting anything. Load the jurisdiction’s compliance ruleset — break law, overtime trigger, minor-hour limits, and any fair-workweek ordinance the city imposes — and have the Labor Compliance Lead sign off; these are versioned like code, so a new city is a config load, not a rewrite. Seed the forecaster from a similar-profile unit’s curve, run two to four weeks in review-only mode with the GM-override log on, then let prep pars start auto-pushing once interval accuracy clears your bar. Hold labor auto-adjust behind the GM until the override rate proves the forecast earned it.
Handling a special event. Anything the POS can’t see — a graduation, a stadium night, a road closure, a viral day — gets entered as an event override before the schedule posts, ideally outside the fair-workweek window so the staffing change doesn’t accrue predictability pay. The override sets an expected cover lift on the affected dayparts; the pipeline re-runs labor and prep against the bumped curve, still inside the same hard constraints. The reason is logged, so the next graduation week the model already knows.
Ownership keeps the loop from drifting. One condensed RACI:
| Role | RACI | Responsibility |
|---|---|---|
| Operations Director | A | Owns interval accuracy, speed-of-service, and labor-minute targets |
| General Manager | R | Reviews schedule + prep, overrides with a logged reason, posts the schedule |
| Labor Compliance Lead | C | Maintains break / OT / minor-hour / fair-workweek rules, versioned |
| Platform Engineering | C | Integrates POS / KDS / timekeeping read-only; runs the unit-local pipeline |
| CFO / COO | I | Reviews labor cost, predictability-pay exposure, and waste/sales |
A note on where the pipeline runs: keep it close to the unit. A store cannot lose the ability to schedule and prep because a WAN link dropped, so the optimizer runs on a small footprint at or near the unit against a cached forecast and the local ruleset; forecasts sync down and overrides sync up when the link is healthy. It’s also the cheaper path — re-forecasting every quarter-hour across hundreds of units is not something you want to pay a per-call cloud-inference tax on, and your labor detail is not something you want shipped to an outside model. Reserve central compute for the overnight retrain.
What we covered
The schedule the GM keeps is the one that was already legal, already prepped against the right covers, and already adjusting before the 7pm rush walked in the door — so the only thing left for the floor to decide is the thing the data never could.
References: predictive-scheduling (fair-workweek) ordinances · FLSA minor-hour and overtime rules · POS / KDS intraday demand controls · off-premise margin management · NIST AI RMF · NIST Privacy Framework · NIST CSF 2.0 · GDPR · CISA Secure by Design.