OP, I have one like this. He is diagnosed with ADHD, we suspect autism as well although the testing for that was inconclusive, so it is paused until he is older. I'm not saying this to suggest this kind of pattern ONLY happens with A(u)DHD, just to provide some possibly relevant info.
There was an incident at Kindergarten, which where we live is not really school, it is more like a hybrid of nursery and preschool/reception class without learning to read, although it goes up to age 6/7. He was about 6.5. It wasn't violence but it was similarly unacceptable, he absolutely knew he was not allowed to do it and I was very angry/embarrassed about it, and similarly said no when he wanted to get ice cream on the way home, which turned into a whole thing where he was indignant and couldn't understand why I was saying no. It kind of scared me, if I'm honest. Although neither DH or I will get seriously cross very often, our other children will recognise if they have crossed a line and the fact DS2 didn't freaked me out a bit.
FWIW I think it was an entirely normal thing to do, to cancel non-essential fun plans immediately after a serious behaviour incident. People saying there is an issue with the consequence are missing the point IMO. You're right that it would have sent a really strange message, and it was important to show him you were displeased straight away, not pretend to be fine and then suddenly give a punishment later!
Anyway that was probably about a year ago. I've learnt a lot more about the way his mind works since then. The incident also hasn't repeated
Absolutely everything you've described to me about your approach sounds spot on. So keep doing what you're doing.
Happy to expand more but if I don't send the reply now, while the thread is bumped anyway, it will die down in a couple of hours and then I'll bump it again with my long post
I can see you want it to stay finished so happy to leave it there too. You can also PM if you prefer.