graph shipmentPlanning {

  node fetchOrder : FetchOrderOperator {
    input {
      orderId = ctx.orderId
    }
    timeout = 3s
  }

  node lookupWarehouse : LookupWarehouseOperator {
    depends_on = [fetchOrder]
    input {
      origin = fetchOrder.output.origin
    }
    timeout = 2s
  }

  node selectCarrier : SelectCarrierOperator {
    depends_on = [fetchOrder]
    input {
      destination = fetchOrder.output.destination
      weight      = fetchOrder.output.weight
    }
    retry = { attempts: 2, backoff: 200ms, strategy: exponential }
    fallback = { carrierId: "DEFAULT", name: "Standard Post", baseRate: 15.0, estimatedDays: 7 }
  }

  node optimizeRoute : OptimizeRouteOperator {
    depends_on = [fetchOrder]
    input {
      origin      = fetchOrder.output.origin
      destination = fetchOrder.output.destination
    }
    timeout = 5s
  }

  node calculateCost : CalculateCostOperator {
    depends_on = [lookupWarehouse, selectCarrier, optimizeRoute]
    input {
      warehouse = lookupWarehouse.output
      carrier   = selectCarrier.output
      route     = optimizeRoute.output
    }
  }

  node decideShipMode : DecideShipModeOperator {
    depends_on = [calculateCost]
    input {
      cost  = calculateCost.output
      order = fetchOrder.output
    }
  }

  branch on decideShipMode.output.mode {
    "express"  -> dispatchExpress
    "standard" -> dispatchStandard
    otherwise  -> dispatchConsolidated
  }

  node dispatchExpress : DispatchExpressOperator {
    depends_on = [decideShipMode]
    input {
      orderId = fetchOrder.output.orderId
      mode    = "express"
    }
  }

  node dispatchStandard : DispatchStandardOperator {
    depends_on = [decideShipMode]
    input {
      orderId = fetchOrder.output.orderId
      mode    = "standard"
    }
  }

  node dispatchConsolidated : DispatchConsolidatedOperator {
    depends_on = [decideShipMode]
    input {
      orderId = fetchOrder.output.orderId
      mode    = "consolidated"
    }
  }
}
