what EXACTLY does not work?
You may find that Locker Service will filter out some or all of the data you're trying to work with, even within your own namespace. For this reason, the two related methods for using Aura.Action, $A.run and Action.run, have been deprecated in favor of event handling.
Previously, these methods would allow you to pass in parameters, but Locker Service ends up converting those parameters to Proxy objects, and may ultimately cause you to lose access to the data in the parent component, even within the same namespace. With the run functions having been deprecated, the only other alternative is $A.enqueueAction, which does work, but...
You have no event to work with. No parameters. While it works in your super-simple example, in the Real World, we like having parameters in our events so we can tell the parent about what's going on (e.g. aura:valueChange tells the handler what the old and new values are). Not having this capability is frustrating for most non-trivial events. Also, note that
evt in your example is undefined. Developers assuming that
evt will have a value are in for a rude awakening.
What exactly is so dangerous to use this pattern?
As above, Locker Service can make data randomly inaccessible. There's no way to predict ahead of time what scenarios will trigger it, and it might even be a moving target as they continue to refine Locker Service and Aura in general. That's also part of the Haunted House effect they mentioned. Your code can appear to be haunted, randomly causing crashes for no good reason.
What I can not do? What will fail?
I think this is pretty well covered, but you can't use the
run methods (the only way to get parameters to your method), $A.enqueueAction won't have an event or parameters for you to work with, and you can't reset the Aura.Action attribute later with a new handler for any reason, which can come back later to haunt you if you're using a lot of dynamic component generation. In fact, I don't think you even get access to the correct component with $A
If it is so bad, why it is there at all?
Backwards compatibility, for the moment. This method was pre-Locker-Service. Before LS could be properly implemented, they knew they were going to have to get rid of Action.run and $A.run because of security access problems. If you want a secure component and proper access to your data, you won't use this method.
How did Salesforce wire-up their components which are providing onchange attributes such as lightning:input?
It's currently a mix of SecureEvent/aura:registerEvent and a system-only method Action.runDeprecated. I expect that they'll eventually convert the rest over, remove runDeprecated, and never look back. Aura.Action itself might eventually be deprecated, since it serves no purpose in a world where we have to do everything via SecureEvent instead.
are there any alternatives which can provide such a nice notation for the child-compo like
<c:child onchange="c.onChildChange"/> without the event-pattern verbosity? Quick and clean?
Honestly, except for the fact that you need an event (which you could just use one or a handful of generic events with generic data types), it is already just as clean.
<aura:registerEvent ... />
<aura:attribute type="Aura.Action" ... />
// Cannot set any parameters, sorry...
Note that in both of the above examples, the parent doesn't care about the underlying complexity, as, except for the missing event parameters, it looks identical in markup.