Hours until each plant stops, per part number. Every number on the board can be recomputed by hand from the inputs, which is what makes it usable in a war room at 2am.
Consumption is always derived, never stored:
burn_uph = plant.line_rate_uph * part.per_vehicle
Time to first stop walks the arrival timeline forward. Between arrivals stock depletes at
burn_uph; at each arrival stock steps up. The first interval in which stock would go
negative gives the exact stop hour:
stock = on_hand; t = 0
for arrival in sorted(arrivals):
gap = arrival.eta_h - t
if stock - gap * burn < 0:
return t + stock / burn # stops before this truck lands
stock -= gap * burn
t = arrival.eta_h
stock += arrival.qty
return t + stock / burn # stops after the last truck
First-stop time answers "when do we stop". It does not answer "how long are we down", and those come apart the moment a recovery truck lands after the stop. An expedite that arrives an hour late cannot prevent the stop, but it can still cut an eight hour outage to one. So the board also integrates total starved hours across the 72 hour horizon, and the re-planning demo makes every recovery decision against that number rather than against the first stop.
| Band | Hours to stop | Meaning |
|---|---|---|
| critical | under 4 | Inside a single shift. Escalate now. |
| at risk | under 12 | Recoverable today if a decision is made this shift. |
| watch | under 24 | Monitor; normal replenishment may still cover it. |
| ok | covered to 72 | No stop inside the horizon. |
| Scenario | What it models |
|---|---|
| normal | Comfortable coverage. Most parts covered to the horizon. |
| tight | Lean inventory. Several parts inside 12 hours. |
| launch | New model ramp. Sequenced parts run thin and some parts go critical. |
| peak | Line rate up 25 percent, so the same stock covers proportionally less. |
Synthetic data, tuned so the failure modes are visible. The clock makes no prediction: it reports consequences of what is already known. Whether a supplier will actually miss its release is a different question this demo does not answer.