Those are some very good thoughts and questions. As I tried to touch on in the article, the own mental model has to shift slightly away from the typical inheritance tree. I have built products in which I use inheritance over behaviour, and it was fine. However, I also experienced that it does make the code tightly coupled, and this leads also to what you describe, as it got messy fast. All of a sudden, I added edge cases here and there. Certainly, the abstraction could have been improved, but the point remains. It would have aged even worse with multiple devs on the product and different libraries. Large inheritance trees tend to become brittle. That was my point with the machine learning models. With behaviour and static protocols, it has been so much easier to integrate different approaches.
Having said that, I read (I think also from Luciana Ramalho) that inheritance can make sense when developing a library/package itself. Nevertheless, I would try to use static protocols as long as it seems possible. Inheritance for code reuse is an implementation detail. It can often be replaced by composition and delegation.
I hope this gives you a bit more context to the article and idea of using behaviour over inheritance.