After some thought, I believe the way to fix the implementation is what I suggested at first: reset fold to 0 before calling utcoffset() in __hash__. A rare hash collision is a small price to pay for having datetimes with different timezones in the same dictionary.
Ya, I can live with that. In effect, we give up on converting to UTC correctly for purposes of computing hash(), but only in rare cases. hash() doesn't really care, and it remains true that datetime equality (which does care) still implies hash equality. The later and earlier of ambiguous times will simply land on the same hash chain.
Now, please, can we not start discussing how __hash__ should behave if utcoffset() raises a MissingTimeError?
__hash__ is a tail. I still want to get people thinking about the dog. Really. Let's give people some space to look at it from a higher level? Implementation details aren't users' problems, and I want to be (more) sure we can live with the high-level model.