Looking like, and being like are two different things :) Mobx reminds people (rightfully) of Meteor, Knockout, Angular etc, but when working with it you will see it is quite a different best. Just like Redux will remind people of flux, but that doesn't mean people shouldn't try Redux because e.g. Facebook Flux didn't work out.
The idea is very much like knockout and meteor, but the reactivity implementation is completely different. First all it is generic and not designed for just the UI. MobX is completely glitch free and synchronous and has explicit distinction between computed values and reactions (side effects like updating the DOM). More important, MobX determines the right execution other of derivations on the fly, preventing issues with 'double runs' which were a common issue in for example Meteor. These design decision are based on research of common issues with knockout and meteor (like the ones you described) and analyzing what is the root cause of these issues. For that reason you also won't find two way binding in MobX
For your first question: nope, the important edge case is that deep changes on _non_ observable objects won't be observed. But that is no different from the edge that deep changes on (conceptually) immutable objects are not observed.
For the last question: yes exactly. Note that the observables can (should) usually be updated from a 'nice' place, for example from controller or class methods, as directly manipulating data inside event handlers (as done in the tutorial for brevity) will quickly result in your code becoming a mess. But besides that state should be updated in the most straight forward way possible :). So MobX is unopiniated from a technical perspective, but you should have some opinion about it so that code is regularly structured and easy to grasp by others.
In MobX it actually doesn't matter whether the events happen inside or outside the component. Components themselves are part of the nervous system. They react to changing observables that are used in the rendering. Regardless how those observables are changed.
MobX is still unidirectional data flow: `events / actions => state => view` (although you could create React components that are bidirectional a recommend against that). But if you mean with unidirectional data flow that there is no action dispatcher; that is up to the developer. Having an action dispatcher might still be nice for your app. Or over engineering. MobX is unopiniated about these things.
I think it is quite different, at least if I read the docs correctly mercury is much closer to Redux / OM then MobX + React. MobX doesn't work with cursors and your tree doesn't have to be a normalized tree (it can be any (mutable) graph). In MobX data is not pushed through the root (which is when working with large collections still slow!) but rather each components observes exactly its own observables (deeply). This means that children can re-render without their parents and vice versa. This is done automatically and you don't have to write any cursors for it.
I'm not sure whether this answers your question completely, so just let me know if that is the case :)
Sure, the promise of VDoms is performance. And vDOM has improved DOM performance a lot. But also not nearly enough to support the complexity of most real life applications that handle a decent amount of data (say, 1000 visible components at the same time). That is the reason why frameworks based on immutability and PureRenderMixin (such as Redux) were able to gain popularity in React in the first place. They solved largely this performance issue (and not vDOM in itself)
Data size isn't usually an issue for MobX. The reason for that is that it will automatically suspend all derivations which are not actively in use somewhere (in other words, not visible currently in the screen). We have full blown visual editors that have hunderd thousands observables in memory. Nonetheless they are fast enough to perform drag and drop actions using observables, where not only the dragged item is being moved, but also all the connectors connected to it, as they observe the item being dragged.
Exactly. Integrating many apps is something we do as well. We have a large application that handles roughly 500 different domain classes (just scan through https://apidocs.mendix.com/modelsdk/latest/ to see how vast that is).
This approach enables our partners to write plugins that are not only simple to write, because they can just work with 'plain' javascript classes and arrays (and don't need to learn the whole, for example, redux architecture), but which are also really easy to integrate in our visual tools. Our UI stays always efficiently in sync with whatever mutations plugins make. In an architecture with explicit subscriptions, events or selectors this would be a lot harder to achieve.
"With mutable data structures, it is trivial to guarantee that there is only one version of a certain domain object in memory."
That statement refers to the fact that you loose (automatic) referential integrity when you start using Immutable data.
Take the following scenario: you have an app with Users and Tasks. Tasks can be assigned to users. When you express this using immutable data you have two problems. The first one is linking tasks to users. If you would link Task1 to Person1 and after that change the name of Person1, you would get a new person, Person1v2. However Task1 would still refer to the old, unmodified Person1, so then you have suddenly two versions of the same person in memory. A fresh and a stale one. In other words, you lost referential integrity.
Now the usual way to fix is, is to not use real references, but to normalize data and store only a key to the person. The effect of this is that you have to always lookup the person related to Task1 again from the state tree. If you have a reference (variable) to that person somewhere, make sure it is short-lived because you won't know if you are still referring to the correct one.
The second problem is that when you have correctly normalized your data and always do fresh lookups, you will still not know _when_ to make these lookups. If you have a TaskView that renders the name of the related Person, and the related person changes, the TaskView will not detect this automatically. The related person is not even a prop of the TaskView component so pushing a new state tree through your app won't repaint the TaskView if you are using PureRenderMixin (which is usually the purpose of using immutable state trees in the first place). For that issue there is a solution as well; you can introduce selectors (or lenses) that query the state tree to detect if the relevant person is changed. So now we already have three new concepts (no refs, normalization, lookups, selectors) to solve a problem that mutable data doesn't have in the first place.
By using mutable data and observing it using MobX these problems are solved (imho) more elegantly: references are never stale because if you would modify Person1, Task1 would still refer to the 'latest' person1, because it is still the same object. Secondly, because it is the same object, fine grained object observers can be established automatically for you, making sure the TaskView gets updated as soon as something relevant changes. This means that you have less concepts to learn and maintain (no copy-on-write, no need to assign a unique key to everything, no data normalization, no lookups, no selectors to make sure your views are always in sync with the state). That saves a significant amount of boring yet error prone work when your application's state model becomes more complex than the average Todo app.
So that is the long story behind that short comment. I hope it clarifies the statement!
Object.observe was a bad idea. Even when it was available in chrome I didn't consider using it. However, the ES6 proposal for object proxies will hopefully become generally available as those can solve the same issue way more elegantly. Proxies will be able to address the current limitations of arrays in Mobservable.
We use both; local component state as long as nobody else (might) be interested (this usually the case for generic components that are not application specific, such as page controls, checkboxes etc). But as soon as state starts to creep upward in the component tree, we move it directly to global state and store it in observable data structures (using mobservable) so that any component interested can use the data in whatever way it was delivered (through props, global state, closures, etc) and (un)subscribe automatically.
Looking like, and being like are two different things :) Mobx reminds people (rightfully) of Meteor, Knockout, Angular etc, but when working with it you will see it is quite a different best. Just like Redux will remind people of flux, but that doesn't mean people shouldn't try Redux because e.g. Facebook Flux didn't work out.