rawQuery doesn't seem to be used in beforeQuery. I assume that's passed just in case a subclass finds it useful?

Perhaps the queryPlan object should be created in doQuery and passed to beforeQuery, it might help to keep it future compatible if other parameters come along later?

queryPlan = me.beforeQuery({
    query: queryString,
    forceAll: forceAll,
    rawQuery: rawQuery,
    combo: me,
    cancel: false

beforeQuery: function(queryPlan) {
A beforeQuery method is a good start but I feel there's potentially a lot of benefit in factoring out the bits inside the local/remote bifurcation, that's where most of the patching tends to happen. Coming up with a decent API for that without exposing too many implementation details may be tricky though.

Nested 'ifs' four levels deep followed by a massive bifurcation... just the indentation waveform is enough to set alarm bells ringing, you don't even have to read the code.