Is it possible to check whether or not the merge has happened using a smart contract? Preferably completely on-chain, but some trustworthy decentralized oracle that tells me could work too.
I would say that one way would be to look the difficulty bomb. It is not 100% reliable, but the merge will occur once the PoW on the execution layer reach the
TERMINAL_TOTAL_DIFFICULTY (see https://github.com/ethereum/consensus-specs/tree/dev/specs/bellatrix).
Edit: I found this video which answers your question. I recommend listening to the whole, but the part that interests you is at 12:30. Tim Beiko explains that the diffulty value will become the randao going thus from a 64 bits value to a 256 one.
Here is a visual representation: (source: https://blog.ethereum.org/2021/11/29/how-the-merge-impacts-app-layer/)