Simulation · Supply Chain Risk
Supply Chain Hazard Risk Simulator
A supply chain disruption simulator built for a supply chain working group, with three rules that shape everything else. The simulation is deterministic and model-free: no language model touches the numeric path, and the same config with the same seed produces byte-identical output, which a determinism test pins with seeded run hashes. The AI briefing layer is grounded or silent: it receives structured simulation output and hazard records and nothing else, every claim it makes has to carry an evidence identifier, and if the data does not support a conclusion it has to say so. That is enforced as a schema requirement, not a prompt suggestion. And it uses federal and free data sources only, with every hazard record attributable by URL and retrieval timestamp. Two parts were genuinely hard. When orders exceed origin capacity, naive proportional rationing strands throughput because it ignores per-lane caps, so I wrote an iterative re-pooling loop that fills to the constraint and redistributes the remainder; in the bottleneck case it lifts units dispatched from 55 to 95, and the pathological case is pinned by tests. Matching hazards to shipping routes across thousands of kilometers breaks under naive planar buffering, so I chunk each corridor into segments, reproject each segment into an azimuthal-equidistant projection centered on it, and unwrap antimeridian crossings that would otherwise produce world-spanning polygons that match every asset on Earth. It is 3,259 lines across 20 Python modules with 64 test functions, a FastAPI service, and a Next.js operations console.
What it does
Deterministic, model-free simulation: the same config and seed produce byte-identical output, pinned by a determinism test with seeded run hashes
AI briefing layer is grounded or silent: every claim carries an evidence identifier, enforced as a schema requirement rather than a prompt
Federal and free data sources only, each hazard record attributable by URL and retrieval timestamp
Water-fill allocation: an iterative re-pooling loop that respects per-lane caps, lifting units dispatched from 55 to 95 in the bottleneck case
Geodesic corridor buffering: per-segment azimuthal-equidistant reprojection with antimeridian unwrapping to avoid world-spanning match polygons
3,259 lines across 20 Python modules, 64 test functions
Tech stack