///|
/// Backend-neutral segment execution policy. The built-in implementation
/// deterministically partitions work into lanes and executes them
/// cooperatively. A native thread-pool can preserve the same lane contract.
pub struct SegmentSearchExecutor {
  requested_parallelism : Int
  effective_parallelism : Int
}

///|
pub fn SegmentSearchExecutor::portable(
  requested_parallelism : Int,
) -> SegmentSearchExecutor {
  guard requested_parallelism > 0 else {
    abort("requested search parallelism must be positive")
  }
  { requested_parallelism, effective_parallelism: 1 }
}

///|
pub fn SegmentSearchExecutor::requested_parallelism(
  self : SegmentSearchExecutor,
) -> Int {
  self.requested_parallelism
}

///|
pub fn SegmentSearchExecutor::effective_parallelism(
  self : SegmentSearchExecutor,
) -> Int {
  self.effective_parallelism
}

///|
pub fn SegmentSearchExecutor::is_degraded(self : SegmentSearchExecutor) -> Bool {
  self.effective_parallelism < self.requested_parallelism
}

///|
/// Runs per-segment collection through the executor contract and performs a
/// deterministic global Top-K reduction. Lane-local heaps bound intermediate
/// memory and make this reduction directly reusable by a native pool.
pub fn Searcher::search_with_executor(
  self : Searcher,
  query : &Query,
  collector : TopKCollector,
  executor : SegmentSearchExecutor,
) -> ReadOnlyArray[SearchHit] {
  let weight = query.weight(self.statistics)
  let lane_count = if self.segments.length() < executor.effective_parallelism {
    self.segments.length()
  } else {
    executor.effective_parallelism
  }
  if lane_count == 0 {
    return []
  }
  let lane_heaps : Array[TopKHeap] = []
  for _ in 0..