@chrishamm @o_lampe thanks both for the input, but it turns out it was actually user stupidity.
I don't have a password and don't need a rr_connect but when I was connecting from a program and submitting the gcode file I was forgetting that axes aren't homed yet - so nothing (visibly) happens.
When I connect a web browser I have been hitting the 'Home All' button immediately, and then (surprise!) uploaded gcode files run, but I have spent weeks not noticing that every time I connect with a web browser I immediately hit that button!
The fix therefore was as simple as adding a G28:
curl http://192.168.53.48/rr_gcode?gcode=G28
curl --data-binary @circles.g http://192.168.53.48/rr_upload?name=/gcodes/circles.g
curl http://192.168.53.48/rr_gcode?gcode=M32/gcodes/circles.g
curl http://192.168.53.48/rr_disconnect
Actually, I have now left in a http://192.168.53.48/rr_connect?password= (but with nothing specified as password) because it gives a potentially useful confirmation of the device - {"err":0,"sessionTimeout":8000,"boardType":"STM32F4","apiLevel":1}, but it isn't required.
For posterity, I should note that without a password set on the printer a plain rr_connect without the password= appended doesn't work - it returns (in an html page) 'Your Duet rejected the HTTP request: Unknown request'.