Thanks, @agoose77, for answering this! You made all the points I wanted to except the "why".
You can make subclasses of ak.Array and ak.Record, but you have to assign them through ak.behavior. There's a big write-up of that here:
https://awkward-array.readthedocs.io/en/latest/ak.behavior.html
When you do array manipulations, you end up creating new array objects all the time—every slice is a new array object from Python's point of view (though the data buffers themselves share a lot of memory for efficiency). The ak.behavior is a set of rules for applying your subclasses to new array objects depending on "parameters" in the array, so even if your data type is buried deeply in a data structure (and there are no Python classes associated with it), when it comes to the surface through a slice or something, it will be wrapped by the right Python class (which must be a subclass of ak.Array or ak.Record, depending on what you're doing).
This change was caused by ccd7537.
Oh, yeah, the old behavior worked by accident. Before that fix, it wasn't checking ak.behavior, which let the class be stale (and therefore wrong) in some cases and allowed your Wrapper without going through the ak.behavior mechanism, @fleble. The new version revealed unintended behavior that you were using. Switching to ak.behavior would make it more stable anyway: if you have records inside the Array that need to be interpreted a particular way, this would wrap them any time they come to the surface through a slice, not just when you explicitly call Wrapper.