Using the batch campaign method ... seems the content exhausted flag isn't working for me. I had to add evaluation steps to the campaign that checked whether each email was sent to a contact.
As a test I created a campaign targeting 1 member of a stream (screenshot below). Program goal is to move contacts w/ expired content from mid to late stage. As configured in the screenshot, the Schedule tab says the campaign will affect "0" contacts. If I remove the last evaluation step in this screenshot (was sent email), the Schedule tab says the campaign will affect "1" contact. If I run the campaign this contact is, in fact, moved to the late stage despite them not receiveing all content from their current (mid) stage.