Disruption cascades across supply chains
In March 2021, a container ship blocked the Suez Canal for six days. The disruption cascaded through global supply chains for months - but many companies didn't know which of their orders were affected until days after the blockage began. The information was there (which suppliers used which shipping routes, which orders depended on which suppliers), but connecting the dots across systems took time. By then, the window to reroute had passed.
The challenge isn't knowing that a port is closed. It's knowing, within milliseconds, which of your suppliers ship through that port, which orders depend on those suppliers, which of those orders have SLA penalty clauses, and which customers are about to be impacted. That's a chain of reasoning across your entire supply graph, and it needs to update every time a fact changes - a port closes, a supplier reroutes, a new order is placed.
The setup
Three suppliers. Supplier A and B ship through Shanghai. Supplier C ships through Busan. They feed four orders. Two of those orders have SLA penalty clauses.
// Suppliers and their shipping ports
+ships_via[("supplier_a", "shanghai"), ("supplier_b", "shanghai"), ("supplier_c", "busan")]
// Which suppliers feed which orders
+supplies[
("supplier_a", "order_101"), ("supplier_a", "order_102"),
("supplier_b", "order_103"), ("supplier_c", "order_104")
]
// SLA penalty clauses
+has_sla[("order_101", "globex_corp", "penalty_5pct"), ("order_103", "initech", "penalty_10pct")]
// Port status
+port_status[("shanghai", "open"), ("busan", "open")]
The rules
Three rules, each one step in the cascade. A supplier is disrupted if its port is closed. An order is at risk if its supplier is disrupted. An SLA is triggered if an at-risk order has a penalty clause.
+supplier_disrupted(Sup) <- ships_via(Sup, Port), port_status(Port, "closed")
+order_at_risk(Order) <- supplies(Sup, Order), supplier_disrupted(Sup)
+sla_triggered(Order, Customer, Penalty) <- order_at_risk(Order), has_sla(Order, Customer, Penalty)
Everything is fine
?supplier_disrupted(X)
No results.
No disruptions. All ports are open. All orders are on track.
Shanghai closes
One fact changes.
-port_status("shanghai", "open")
+port_status[("shanghai", "closed")]
The cascade propagates through the entire graph:
?supplier_disrupted(X)
┌──────────────┐
│ X │
├──────────────┤
│ "supplier_a" │
│ "supplier_b" │
└──────────────┘
2 rows
?order_at_risk(X)
┌─────────────┐
│ X │
├─────────────┤
│ "order_101" │
│ "order_102" │
│ "order_103" │
└─────────────┘
3 rows
?sla_triggered(Order, Customer, Penalty)
┌─────────────┬───────────────┬─────────────────┐
│ Order │ Customer │ Penalty │
├─────────────┼───────────────┼─────────────────┤
│ "order_101" │ "globex_corp" │ "penalty_5pct" │
│ "order_103" │ "initech" │ "penalty_10pct" │
└─────────────┴───────────────┴─────────────────┘
2 rows
One fact change. Two suppliers disrupted, three orders at risk, two SLA penalties triggered - identified across three levels of the supply graph. Supplier C and order 104 are unaffected (Busan is still open). This is the kind of fan-out that takes hours to trace manually and seconds in a dashboard query - but with InputLayer, the derived state is already current by the time you ask.
Partial recovery
Supplier A reroutes to Busan.
-ships_via("supplier_a", "shanghai")
+ships_via[("supplier_a", "busan")]
?sla_triggered(Order, Customer, Penalty)
┌─────────────┬───────────┬─────────────────┐
│ Order │ Customer │ Penalty │
├─────────────┼───────────┼─────────────────┤
│ "order_103" │ "initech" │ "penalty_10pct" │
└─────────────┴───────────┴─────────────────┘
1 rows
Supplier A recovered. Orders 101 and 102 are no longer at risk. Globex's SLA penalty retracted. But Supplier B is still disrupted (still shipping through Shanghai), so order 103 and Initech's penalty remain. Partial recovery, correctly tracked - each path is independent.
The proof trail
why ?order_at_risk("order_103")
The proof shows: order_103 is at risk because it's supplied by supplier_b, and supplier_b is disrupted because it ships via Shanghai, and Shanghai is closed. Three facts, three rules, one chain. When a procurement team needs to explain to Initech why their order is delayed, the answer is a structured trace, not a phone call to someone who might know.
Every code block on this page runs against a live InputLayer instance. Paste them into the demo to see the results yourself.