I think you're right regarding padding bits being observable, albeit only at run-time. We have some wording that specifies values of padding bits (e.g. zero-initialization says padding bits are zero), and so there are some cases where padding bits are not indeterminate. I was operating under the assumption that padding bits are indeterminate in all cases, but they're not.
However, there is nothing that guarantees you that your test function is well-defined. If d1 has dynamic storage duration or is marked [[indeterminate]], padding bytes have indeterminate value, so you're just reading uninitialized memory, and the function has undefined behavior. In most other cases (e.g. local variables), d1 has padding bits with erroneous value. This is a huge footgun, and encouraging users to modify and access padding is exactly the wrong design direction.
Even in the few cases where padding bits have specified value, that value is very easily lost through lvalue-to-rvalue conversion or any kind of arithmetic operation.
I have yet to hear any attempt at an argument for why we would want a clear_padding utility rather than a bit_cast_zero_padding utility. As I've said, padding bits are very easily lost. It also requires expert-level knowledge to understand when padding bits have some specified value and when they revert back to indeterminate or erroneous value. A clear_padding utility also would not work for constant evaluation.
That being said, I'm not strongly opposed to making bit_cast preserve the values of padding bits at run-time. However, that doesn't really solve the problem that I set out to fix here. Those padding bits are almost certainly going to be erroneous or indeterminate if the user doesn't use clear_padding, and clear_padding doesn't really work during constant evaluation without substantial changes to implementations.
The clear_padding + bit_cast idiom encourages the user to write the wrong kind of code. If you forget clear_padding, you may get undefined behavior, and what is currently a degenerate form of bit_cast that we could reject at compile time (because it always produces UB) becomes undiagnosable; the user could have run bit_cast expecting the padding bits to be copied, and the compiler has no way of knowing whether that's the intent. Very sharp edge!