You're not missing anything, and it's not really a bug. Grep replacements are just text replacements. You can manipulate formatting by explicitly setting it in the Find format and Change format panels, but if you leave those panels empty InDesign simply ignores formatting. InDesign's formatting is not physically attached, so to speak, to text ranges; rather there some part in the document with information that says 'apply allcaps to characters 10-30 in story 212'. That information isn't changed when you replace text, and that's why you see the effects that you see.
You can't get around that by using character styles just likie that, only by using nested or grep styles. The only other way I know of dealing with these things is to replace formatting with text tags, do your replacements, then change the text tags back to formatting. In your case you would replace allcaps with tags so that your line would read something like
<ac>book section 100—title,</ac> cont. (2)
Then do your replacements and revert the tags to allcaps formatting. Sound very cumbersome but it's quick and easy to script.
Interesting approach, Peter. I hadn't thought of text tags. It makes perfect sense that the formatting is applied to character position and not the text. As a followup, I can loop and check which characters have overrides (it's a R/O boolean property), but is it possible to determine what the specific overrides characters have applied?