Disclaimler: I'm only taking my first steps in the CQRS world, but I can offer my current understanding of the matter and we'll see if others confirm. All I write below has an underlying "as I see it" theme, and is not authoritative.
The 80% case
To answer your question, commands are indeed a point-to-point affair. When a command enters a controller (MVC webapp), that controller then asks a command dispatcher to find one and only one apropriate command handler, and delegates the work to that handler.
Why not publish?
It's a question of responsibility. If something sends a command, it entails expectation that it will be fulfilled. If you simply publish and hope that something somewhere picks it up and acts on it, there is no guarantee that this will be the case. By extrapolation, you also don't know if multiple handlers don't decide to act on a command, possibly resulting in the same change being applied more than once.
Events, on the other hand, are informative in nature, and it's reasonable to expect zero, two, or more components to be interested in a particular event. We don't really care in the scope of making the requested change.
Example
This could be compared to real life. If you have three children, walk into a room and simply shout "Clean the bathroom," you have no guarantee that someone will, and perhaphs if it won't be done twice (if you have obedient children that is ;-) You should fare better if you assign a specific child to do what you want done.
When that child finishes its job however, it's convenient if it shouts out "bathroom has been cleaned," so that everyone who wants to brush their teeth knows they can now do so.
While this is a large and involved topic and hardly answerable as such, let me give you few pointers for your main questions:
What would be the format of the ruleset file and a parser for the rules - lexical parsing alone is easy enough but what would it produce?
The parser entirely depends on your events. Do you have access to in-memory events? do you have to parse the resulting log files? In either case, you can consider this a preparation of input for the algorithm.
The most precise would be in-memory access to the running software/events, but from what you described, this may probably be impossible due to real-time requirements. On the other hand, if you have to parse the log-files and then derive some meaning from them, you ought to ensure that the logfiles are meaningfully parseable, i.e. developers should know that the log-files will be parsed by a tool and how the log messages should look like. If you want to support arbitrary log messages, you'll get into deep trouble.
Also take care not to bind yourself too close to the actual log message. Keep in mind the amount of change required if someone changes the spelling/wording of a log messages and how that affects your tool. Just think: "Oh btw, there was a typo in the message and I fixed it." - "Oh thanks.. so that's why we're getting the RCA wrong". You don't wanna go there.
How to represent a rule internally? As some kind of object probably, but how would that object look like? How to chain the rules together in a decision tree?
Why reinent the wheel? There are several industry-strength rule engines available, which have that already covered pretty well (f.ex. JBoss' Drools Expert). Of course, you still need to do the usual evaluation-cycle to find out if a rule engine is suitable for your project's specific needs.
A completely different approach would be to use a programming language that is already based on rules. However, this requires that you/your team/your organisation is open-minded towards polyglot programming. Also bear in mind, that these languages are not exactly mainstream. We're talking about things like Prolog, Datalog, or CHR here.
processing black box data through these rules. Seems an awful lot like running data through a script, but the data contains a lot of of noise. How to assure obtaining some results?
First off, rule engines are not the most performant things. They are supposed to work on a very high abstraction level, so it makes sense to filter the input first. As mentioned above, you shouldn't work with black box data, because it simply is way too complex (think: full blown natural language processing!). There needs to be some order or structure to the data you have to process.
It will be part of the input preparation to ensure that you filter out ineligible or otherwise uninteresting parts of the data. You may also want to consider an intermediate language where the log message / event data is represented in a standardized way that is fully under your control. In that case, changes to the original data only need to be adapted in the original parser and your tool's core remains unaffected.
Best Answer
Seems to me like you can get away with a single type
If you just have generic errors to deal with, but I would go further and remove Error events for UI stuff.
If the user is waiting to see if something erred you can pass the error back from the function they called and only write the event on success.
So, just
EmailUpdated
instead ofEmailUpdateRequest
EmailUpdateFailed
EmailUpdated
etc etcYou can see how going fully event driven can explode the number of types you need. If they are all internal to a thick client, then you have compile time checking to handle it all, but if you have to pass them over a distributed system it becomes ridiculous