Where is it documented that a StatefulKnowledgeSession is not thread-safe? (It is sad that the string "thread" doesn't occur more than once in the "Expert" manual, disregarding case.)
Batch insertion of facts followed by a single fireAllRules() that contain data that is semantically ordered in any way is not advisable. Conflict resultion may actually reverse processing order as compared to insert order. (It's defined, but I wouldn't rely on this.)
It is not true that the Engine's behaviour w.r.t. insertion of "identequal" objects is undefined. Search the "Expert" manual for "assertion mode".
There are excellent reasons for inserting facts in addition to events. One Application Design Pattern I present in my lecture is based on what I call the "Factory Floor" model. Imagine several gadgets of different kind being in your factory, and you process events, inquire about state and update the configuration. With the session running in fireUntilHalt(), you not only insert events happening with the gadgets, but also facts such as ReportRequest or Gadget, which aren't events. (Of course, about anything can be made into an event, if you really want to.)
Running fireUntilHalt() after each insertion of events arriving over time might also one way to go, but notice that the engine will not react to timeouts while it is idling.