For the specific problem you put forward (Merkle roots changing), a cool solution is what’s been called “witness auto-update”. I first saw the idea in the stateless client post :
by the time a transaction propagates through the network, the state of the accounts it accesses, and thus the correct Merkle branches to provide as a witness, may well be different from the correct data when the transaction was created. To solve this, we put the witness outside the signed data in the transaction, and allow the miner that includes the transaction to adjust the witness as needed before including the transaction.
Basically witness updating can be done offchain by validators, and incentives align. See also the post on auto-updating in the context of account abstraction .