Like many other answers here, Outline [0] has eventually landed on a plugin architecture with a private fork for EE – the paid edition has many extra plugins providing functionality such as extra importers, auth methods, search functionality etc. The interface itself has evolved several times and we're still adding new hooks to enable plugins to integrate with different areas of the product.
This approach has really made the private fork much more maintanable.
Is the public repo the main branch? When you want develop something: you create a PR in the public repo, review, wait for CI, merge to main, wait for CI, finally merge to the fork, wait for CI?
I'm always unsatisfied with the number of steps to achieve that (and the total CI time required), but maybe it's unavoidable.
It is, CI times are fairly fast – in reality it's not been too much of a bottleneck but I'd imagine if you had a team working on the private fork you'd probably want to automate the merges from public at the least.
This approach has really made the private fork much more maintanable.
[0] https://www.getoutline.com
[0] https://github.com/outline/outline