I think you're partly right, but ultimately runtime dynamism has failed; even in Python, the costs of being truly dynamic are higher than the benefits.
Objects communicate messages and status and when something crashes it's up to the object to do something, often restart, but either way it's a matter of interpretation.
It's the static typing that couples because it introduces global behaviour through its types, which impose meaning from the top. In a truly dynamic system, nobody needs to understand the entire system.
I admit it's a fairly theoritcal point because I don't think many people even embrace this paradigm any more, and ironically if they do it's in functional languages. But to say it's failed I think is not right, because nowadays people write dynamic languages basically like they'd write Java, they don't embrace the dynamic aspects.
I don't think that's true; static typing on a local scale or at interface boundaries is useful precisely because it enables local reasoning. Without those constraints you have no chance of understanding any part of the system without understanding the whole thing. If you go so far as to expose all state manipulation in the type system then that becomes sort of global, but even then I'd argue what you're actually doing is not introducing global coupling but rather exposing the global coupling that was already there.
> But to say it's failed I think is not right, because nowadays people write dynamic languages basically like they'd write Java, they don't embrace the dynamic aspects.
I think that very fact is the proof that it has failed; even in languages that were designed for it, people prefer not to follow that paradigm.
I've always disliked the idea of using static code-evaluation tools on dynamic object oriented languages, it kind of defeats the point, which is runtime dynamism.