my experience with ansible is that it offers a suggestion of idempotency, but there's always plenty of room to ignore the best practices.
IMHO it's better to have no guarantee than a vague suggestion that you might tend to rely on but then be bitten because there's nothing actually enforcing the guarantee.
The core builtins help you to write idempotent playbooks, but it is far from a guarantee.
One simple example would just be to use the command task, which executes an arbitrary command. You, the developer, are responsible for telling Ansible how that should be made idempotent.
Right but no configuration system can do this. Puppet straight up tends to lie about what it can do with operations named things like "ensure" which play with language to make it feel like there's not actually a procedural, stateful system there (at least based on the number of people who have gushed at me about puppet while not using it).
It's akin to "unsafe" in Rust and ansible does warn you it's a bad idea unless you really need it.