Regardless of who is right or wrong at the end of the day it's still broken for many people. If Microsoft and Joyent/the node & npm community care about people using node & npm on Windows then the issues needs to be resolved, period.
I don't see how this npm's problem - the language itself doesn't let you catch this problem - and the pattern itself is dangerous. I'd have to agree with IsaacSchlueter here.
If I have a library (libA) that uses fooV1 and another (libB) that uses fooV2, there is no reason I should expect those two dependencies to interop with each other (except explicitly stated by the developer).
The solution (that there should be one set of dependencies) is an even worse problem that currently afflicts the Golang community, which they have decided to solve the same way npm has decided to solve it - vendoring.
Now with Golang, if you only have 1 set of dependancies, and one of your libraries depended on an older version - your program just won't compile (unless you update the library to use fooV2) and I'm not sure how thats useful to anyone. Most people will just tell you should have have just versioned that dependency.
In the vast majority of cases, its not. But in the cases when people want to invent new globally useful abstractions, like bignum, promises, cleaner streams etc - i.e. to reshape the platform - they can't do that. For example, the overhead of adding bluebird as a dependency to every module quickly adds up, and bluebird had to fight with many issues stemming from multiple versions of it communicating with each other.
IMO while this has contributed to the growth of node the ecosystem, it also stifled the growth of node the platform.
No, it's a "bug". It is not required for loading specific versions -- those can be kept in a flat structure just as well. No need for the idiotic nesting.
Or the OS went too short, so to say. There are two problems here.
1) Windows' limit of 260 characters per path name is incredibly small for a modern OS and that was true many years ago as well.
2) Npm approach relied on well behaved OSes and file systems allowing long path names. It's not future proof because you don't know on which OS and file system you'll need to run, maybe some limited embedded device.
Ruby's rvm solved that problem with a single directory level and a gem@version naming scheme.