WP_User->add_role producing unexpected results

This would be best as a comment, but no reputation 🙂

In the codex they say

“If you are defining a custom role, and adding capabilities to the role using add_role(), be aware that modifying the capabilities array and re-executing add_role() will not necessarily update the role with the new capabilities list. The add_role() function short-circuits if the role already exists in the database.
The workaround in this case is to precede your add_role() call with a remove_role() call that targets the role you are adding.”

i suspect you could be inside this short-circuit

I say this cause it seems (just from your pasted code, it could be different) that your script could be running more than once (differently as it would do with plugin activation hook). But this is a guess. In this case, just hooking once (and making first remove_role() and then add_role() ) could do the trick