The last split package issue that we have between server and lucene is LazySoftDeletesDirectoryReaderWrapper. This was added early in 2021, so not one of the legacy hangovers from years gone by.

By inspecting the code, the three package-private member dependencies in `org.apache.lucene.index` become clear:
1. access to field SegmentReader.isNRT, 
2. CacheKey::new, and 
3. PendingSoftDeletes::applySoftDeletes.

First, LazySoftDeletesDirectoryReaderWrapper is only useful for read-only indices that are lazily loaded (a.k.a. frozen tier), so it  is doubtful that Lucene would find it generally useful.

A note on each of the specific package-private API points:
1. Access to field SegmentReader.isNRT is only for assertion code, and exposing an accessor from Lucene for this seems like it could be reasonable.
2. The CacheKey constructor is deliberately non-accessible from outside the package. There were past issues where problems arose with short-lived reader wrappers that would not reuse caches across queries. Maybe there's a way to make DelegatingCacheHelper only work with a DirectoryReader, since directory readers would generally not be short-lived. Or otherwise exposing DelegatingCacheHelper as a more generally useful API in Lucene itself.
3. For PendingSoftDeletes::applySoftDeletes one possibility is to just duplicate the code in ES. There are additional package-private issues when this is attempted, but maybe they are more straightforward to resolve.

[ the above notes are a summary of a discussion that included @romseygeek @jpountz, and @ywelsch ]

see #78166
server/src/main/java/org/elasticsearch/index/engine/ReadOnlyEngine.java
private final boolean requireCompleteHistory;
    final boolean lazilyLoadSoftDeletes;
    protected volatile TranslogStats translogStats;
    private final String commitId;
    /**
     * Creates a new ReadOnlyEngine. This ctor can also be used to open a read-only engine on top of an already opened
     * read-write engine. It allows to optionally obtain the writer locks for the shard which would time-out if another
     * engine is still open.
     *
     * @param config the engine configuration
     * @param seqNoStats sequence number statistics for this engine or null if not provided
     * @param translogStats translog stats for this engine or null if not provided
     * @param obtainLock if <code>true</code> this engine will try to obtain the {@link IndexWriter#WRITE_LOCK_NAME} lock. Otherwise
     *                   the lock won't be obtained
     * @param readerWrapperFunction allows to wrap the index-reader for this engine.
     * @param requireCompleteHistory indicates whether this engine permits an incomplete history (i.e. LCP &lt; MSN)
     * @param lazilyLoadSoftDeletes indicates whether this engine should load the soft-delete based liveDocs eagerly, or on first access
     */
    public ReadOnlyEngine(
        EngineConfig config,
        SeqNoStats seqNoStats,
        TranslogStats translogStats,
        boolean obtainLock,
        Function<DirectoryReader, DirectoryReader> readerWrapperFunction,
        boolean requireCompleteHistory,
        boolean lazilyLoadSoftDeletes
    ) {
        super(config);
        this.requireCompleteHistory = requireCompleteHistory;
        try {