Using ropes is a tradeoff. A gapped buffer is viable for the reasons you state, but I think ropes come out ahead for what I'm trying to do. It's not so much the cost of filling the gap, as that ropes really facilitate parallel, incremental, and asynchronous computation. For example, I want the "save" operation to write a snapshot of the current buffer to disk, while still being fully editable. The snapshot operation is trivially easy and fast with immutable ropes, but if you tried to hack something like that on top of a gapped buffer, it would increase complexity dramatically.
If you look at the implementation of my Unicode line breaking algorithm, you'll see that the indirection cost of the rope abstraction is minimal. In fact, it _flies_ - in my tests, it's about 3x faster than ICU working on a contiguous string. This is because it's able to work on a leaf at a time. The same can be done for search, etc. Yes, it'll require some reimplementation of string basics, but I personally find that kind of thing fun.
I'm still working out the plugin story. Quick answers to your questions though. A syntax highlighting plugin sees a window of the source buffer (effectively a cache, with invalidation by RPC). I'm thinking a contiguous buffer for the window, not a rope - it'd be bounded by a few megs. For a huge file, computing the syntax highlight of what's off screen can be slow. In no case does it block typing, worst case there's a lag before the colors resolve. The plugin sends the annotations back as rich-text spans, which are stored in the core. Scrolling is instant and doesn't inform the plugin. The autocomplete plugin will almost certainly be separate from the syntax highlighting one (but presumably an author could create a combo plugin if it had advantages).
This doesn't address everything you brought up, but hope it helps illuminate some of my thinking.