Looking at the fastcgi code, it seems like the excepted paths are checked exactly, which the docs imply but don’t outright state.
One neat workaround would be to define another site block in your Caddyfile so requests for /wp-content never make it to fastcgi at all. It will require you to copy over the other relevant configuration. You could share them between the two with a snippet.
Thanks @matt and @Whitestrake. I’ve got this working for now - I had to change the root of the wp-content site block - I think paths are relative to the prefix that defines the block (so it needs root to be /var/www/example.com/wp-content instead of /var/www/example.com), but that’s definitely good enough for my needs.
In future, having the except directive match prefixes rather than exact paths makes sense to me though, so if that’s doable that’d be awesome .