For posterity I want to link to these discussions where are exactly about how to obtain this kind of “local” behaviour directly in IO without a separate “effect system”.
https://discourse.haskell.org/t/fork-fragile-reader-like-operations-in-haskell
https://discourse.haskell.org/t/a-reference-implementation-of-ioscopedref