One interesting feature that's coming online a bit here and there is the ability to hook some panics and some errors.
The way the hook is done is that there are native PANIC and FAIL functions which have trivial implementations. C code calls out to these natives by using the evaluator. Then, early in the bootstrap process these natives are HIJACK'd with usermode implementations. If your app then desires, it can further HIJACK those hijackings with adaptations that augment or replace the functionality with additional code.
In the case of panics, I say only "some" are hookable, because panics originating from the core need to terminate the executable. (They're a sort of "blue screen of death", implying that continuing to run Rebol code would be unwise due to some fundamental corruption or problem.) But there are also panics which could be safely recovered from, or have things write to log files before exiting, e.g. direct calls to the PANIC or PANIC-VALUE natives from usermode code.
(It may be that extensions using the rebPanic() API would mean the "softer" form of panic, or maybe they too have some kind of corruption of their state they don't want you to recover from. Maybe there need to be two different APIs...what's more serious than a failure, but less serious than a panic? rebProblem()?)
In the case of errors, I say only "some" are hookable because there must be a way to invoke an error without it being hooked. Consider today's implementation of FAIL, which will construct an error object out of whatever you pass it (if it isn't an ERROR! in the first place) and calls DO on it. If that DO turned around and called into the fail hook again, you'd have an infinite regress.
One simple answer is to say that DO of an ERROR! is an unhookable failure. That would mean no longer casually writing do make error! .... But if we assume those people are willing to change that to fail make error! ... then this seems the easiest way to get the baseline unhookable error. And since there's no appearance of FAIL at the callsite, people wouldn't be too surprised that hijacking FAIL wouldn't find out about these particular errors.
At one point, I'd made DO not accept ERROR!s, because FAIL seemed much better at the callsite. But I realized the only thing taking the ERROR! parameter away would be doing would be raising an "invalid type" error, obscuring what the error was. :-/ So when that was combined ultimately with the idea that FAIL needed some way to invoke the errors that it was building, I put it back.
So is this a good answer? That DO of an ERROR! is the low level mechanic for error delivery used in functions like FAIL which you will not get hooked when you HIJACK fail? It makes some sense to me, but it means that almost no one should be using DO of an ERROR!, unless you are writing a FAIL implementation.
What worries me is if people don't get on board with this, or find it too hard to understand that DO of an ERROR! is not how you should be error'ing, then someone who wants to hook just FAIL would start hooking DO "just to be sure" in case it was passed an ERROR!. :-/