This is the way the options are retrieved in the cart page. It should work for you also:
$helper = Mage::helper('catalog/product_configuration');
$items = $quote->getAllItems();
foreach ($items as $item) {
$options = $helper->getCustomOptions($item);
//do something with $options.
}
I realise this is quite old but I found this post when I came across the same problem myself, so hopefully if I'm too late for this to benefit you, it might still help someone else that comes across it.
Firstly, to find what is passed to an observer, I find it best to search through the magento code for the event name. Searching for checkout_cart_update_item_complete, we can find it is dispatched from Mage_Checkout_CartController with the following parameters:
array('item' => $item, 'request' => $this->getRequest(), 'response' => $this->getResponse())
This means to get the new quote item you can call $observer->getItem()
To get the old quote item, however, you need to do something like Mage::getSingleton('checkout/cart')->getQuote()->getItemById((int)Mage::app()->getRequest()->getParam('id'))
Now to copy across custom options from the old to the new, you can simply clone the option and add it to the new quote item. in total, this is the basic code you will need:
$newQuoteItem = $observer->getItem();
$oldQuoteItem = Mage::getSingleton('checkout/cart')->getQuote()->getItemById((int)Mage::app()->getRequest()->getParam('id'));
$newQuoteItem->addOption(clone $oldQuoteItem->getOptionByCode('CUSTOM_OPTION_CODE'));
$newQuoteItem->getOptionByCode('CUSTOM_OPTION_CODE')->save();
Just change the code in the last two lines to use your custom option code, or if you have multiple custom options, loop those last lines for each one you need to copy.
EDIT: You will also have to save the option once it has been added to the quote item, so I have added a line to the end of my example to do just that
Best Answer
You can try to replicate the way Magento shows the options in the order view page.
Here goes: