It turns out I didn't give "convert the annotations to a canonical form while preserving aliases" enough credit for how fiddly it seems like it's going to be.
Let's see. A top-level alias might be a Subscript, which can contain Tuples, Lists, Ellipsis/Constant, and must eventually bottom out in a top-level alias which must be interpreted in the context of the uppermost alias... The fundamental constituents are Names and Attributes.
After some effort, I put together several node visitor classes in a somewhat questionable fashion. There is obvious room for improvement, but first I need to make sure it works. And for that, I think I should take a break and get some sleep first.
Although, actually, thinking about this, I noticed some big misses, so I guess it's not ready yet. ... Just bashed something together for it.
Okay, I'm too curious, I have to know how this breaks.
... Oh wow, that's brutal. Thousands of failures. I can't even read the full output.
And it looks like some of them are down to the fact that I haven't used, or written, the helper functions I knew I'd need.
So, I scribbled out some helpers, and now I'd like to put this aside for now and work on some other things for a bit.