Even in the run-once case, though, I think there's a benefit to Ansible's role-based approach to modularization. And again for the dev scenario, it's much easier to run only portions of a playbook than it is to run portions of a shell script.
And finally, the diagnostics and overall failure story are obviously way better for Ansible, too.
Now, all this said, I do still go back and forth. For example, literally right now in another window I'm working a small wrapper that prepares clean environments to build patched Ubuntu kernels in— and it's all just debootstrap, systemd-nspawn, and a bunch of shell script glue.
I still use it as it allows more portability across OS releases and families (as in easier migration), but it also increases the complexity when creating a new task/role/playbook.
In that sense, Dockerfiles with shell-based RUN commands are much easier to manage.
Another advantage of config management over shell might be a better integration with the underlying cloud provider. For instance Ansible supports AWS SSM parameter store, which allows me to use dynamic definitions of some configuration data (RDS database endpoints, for instance) or secrets (no need for Ansible vault)