While I agree mostly, you can overdo the "grug". For example it is possible to underengineer (underabstract?) a software for years until realizing that simple things are still complicated, and you forget to built good abstractions once the patterns have emerged.
If you build abstractions, you need a way to correct them anyway, making breaking changes to their contract.
The point is that "underengineering" then having to tie up the abstractions when it's really needed is oftentimes (read: not always) better than overengineering and entering the domain of the complexity demon
I agree that the balance is way too often shifted in the way of overengineering, probably because of our field being skewed by "higher status" thinking.