return;
}
+ // High-V abandon: once the accumulated match pool exceeds the planner's
+ // vertex budget, the shortest-path search would fall back to the greedy
+ // cover anyway (bees-plan.cc), and every further candidate only enlarges V
+ // (and the Exclusion hold time). Signal the planner to stop feeding this
+ // plan candidates; finalize()/ensure_selection() still produces the greedy
+ // best-so-far, which competes in selection against Plan B and do-nothing.
+ if (boundary_count() > m_policy.m_plan_max_vertices) {
+ m_continues = false;
+ return;
+ }
+
// Merge all accepted match dst-spans (each lies within a data region by
// construction), then require every data region to fall inside one
// merged interval. Merged intervals are maximal and gap-separated, so
bool any_continues = false;
for (auto &plan : plans) {
+ // A plan whose continues() is already false has signalled
+ // it wants no more candidates (fully covered, or its
+ // coverage search hit the vertex budget and abandoned).
+ // Honor that per-plan: stop feeding it, so its match pool —
+ // and its search's boundary count V — stop growing. Its
+ // best-so-far still enters selection via finalize() below.
+ if (!plan->continues()) {
+ continue;
+ }
// Plan-agnostic dispatch: each plan owns its own
// per-role filter check inside process_candidate
// and returns without state change on rejection.