feat(planning): register ASAPPlanner's grouping strategy in selection - #692
Merged
Merged
Conversation
zzylol
force-pushed
the
feat/wire-all-replacement-strategies
branch
from
September 12, 2026 14:31
112a5d7 to
81caed9
Compare
Selection registered three of ASAPPlanner's context-free replacement strategies and named none of the rest, so it was not obvious which parts of the legal candidate space the backend actually consumes. Register HydraGroupingStrategy, the grouping axis: a shared multi-subpopulation grid as an alternative to one sketch instance per `by` key. The data plane can already execute it — `accumulator_spec.rs:261` maps it to `AggregationType::HydraKLL` — but no backend plan could ever propose it. Hydra candidates additionally need a shared-grid collision bound to compose a guarantee. `QueryEvidence` (compiler.rs:447) reports none today, so the strategy correctly offers nothing rather than an unbounded guarantee; the regression test pins both halves, so supplying that evidence is all that stands between registration and selection. Extract the list into `replacement_strategies` and record, in one place, why the remaining strategies are absent: - RollupStrategy, AccuracyReconciliationStrategy and TopKLimitReuseStrategy were already active and must stay out. `search_cse_workload_with` builds all three from the post-CSE sibling set and asks them on every target; only it owns that set, so registering them here would hand each an empty one and report nothing. - SharedSubtreeStrategy stays out for a Planner limitation, not a cost policy. Both of its arms are `Replacement::Rewrite`s of the target itself, and `rank_group` ranks that pair ahead of every `Replacement::Summary` in the group and returns before the sketch-family ranking runs. The winning rewrite materializes as `KeepPreAsap`, so registering it downgrades every shared aggregate from its selected sketch to raw execution. `shared_aggregates_keep_their_summary` pins that: one grouped count selects a summary, and two identical ones must still each get a summary. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
zzylol
force-pushed
the
feat/wire-all-replacement-strategies
branch
from
September 12, 2026 14:36
81caed9 to
c59ab0b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
ASAPPlanner's value at this boundary is that it enumerates the complete legal
candidate space and leaves the commitment to the deployment. Selection named
three of the five context-free replacement strategies and said nothing about the
rest, so it was not recorded anywhere which parts of that space the backend
actually consumes, or why. One axis — grouping — was genuinely missing: the data
plane can execute a shared multi-subpopulation grid (
accumulator_spec.rs:261maps
GroupingStrategy::SharedMultiSubpopulationtoAggregationType::HydraKLL)but no backend plan could ever propose one.
What
Planning-time candidate enumeration only. No change to serving, to the physical
wire contract, or to any published plan.
HydraGroupingStrategy.replacement_strategiesand state, in one place, whyeach remaining strategy is absent.
Registered:
SketchAlgorithmStrategy,HydraGroupingStrategy,ExactCompositionStrategy,SemanticEquivalentRewriteStrategy.How
RollupStrategy,AccuracyReconciliationStrategyandTopKLimitReuseStrategyare workload-dependent and were already active:
search_cse_workload_with(
replacement.rs:5186-5195) builds all three from the post-CSE sibling set andasks them on every discovered target. Only that function owns the sibling set,
so registering them here would hand each an empty one and report nothing.
SharedSubtreeStrategyis withheld, and the doc comment now says why in terms areviewer can check. Both of its arms are
Replacement::Rewrites of the targetitself;
rank_groupranks that pair (its "Shape 1") ahead of everyReplacement::Summaryin the same group and returns before the sketch-familyranking runs. The winning rewrite materializes as
KeepPreAsap. Registering ittherefore downgrades every shared aggregate from its selected sketch to raw
execution. This is a Planner limitation, not a cost policy the deployment can
express: no
CostModelhook reorders past Shape 1, and picking the other armselects a rewrite too. The fix belongs upstream — carry the selected summary
through the share rewrite — and until then canonical CSE inside
search_workload_with_targetsalready shares these subtrees structurally andcorrectly.
Before this PR
Three strategies registered, with a comment that explained only why CSE's
recompute arm was unwanted. A grouped aggregate could only ever be planned as one
independent sketch instance per
bykey. Nothing recorded that three furtherstrategies were already running inside the search, so the registered list read as
the complete picture when it was not.
After this PR
The grouping axis is enumerated, so memo groups contain the Hydra alternative
alongside the independent-instance ones and
selection_tracereports each withits strategy, provenance, rationale and selected/unselected status — once
shared-grid evidence is supplied; see Limitations.
Selection results are unchanged for every workload today: Hydra produces no
candidate without that evidence, and all 758 pre-existing control_plane lib tests
pass unmodified.
replacement_strategies' doc comment is now the single place that answers "whichstrategies does this deployment use, and why not the others" — including the two
categories that are absent for completely different reasons (already-registered
upstream vs. actively unsafe at this pin).
Evidence
Execution example — Hydra candidate generation for a grouped
Count, fromhydra_candidates_wait_for_shared_grid_evidence:Execution example — the
SharedSubtreeStrategyhazard, measured by registeringit and running
shared_aggregates_keep_their_summary(groupedCountover aschema with a unique key, so canonical CSE interns the subtree):
Performance measurement: not applicable — this changes which candidates are
enumerated at plan-compile time, not any runtime path.
Screenshot: not applicable — no visual output.
Verification
registered_strategies_are_exactly_the_supported_set— the registered listis exactly the four supported strategies, in discovery order (which is also
rank_group's tie-break order); guards against either exclusion beingundone by mistake.
hydra_candidates_wait_for_shared_grid_evidence— Hydra offers nothing underNoAccuracyEvidenceand exactly two candidates under a provider that reportsthe shared-grid bounds; pins both the wiring and the missing input.
shared_aggregates_keep_their_summary— one grouped count selects a summaryand two identical ones must each still get one; fails if
SharedSubtreeStrategyis registered at this Planner pin.cargo test -p control_plane— 800 passed, 0 failed (761 lib =758 pre-existing + 3 new, plus 31 api + 8 integration); no existing test
modified.
cargo test -p data_plane --libdoes not compile inthis checkout —
asap_sketchlibis missingaccepts_standard_updates(
univmon_accumulator.rs:48) andquantile_interpolated(
summary_executor.rs:1053). Confirmed pre-existing by reverting the changedfile to
origin/mainand reproducing the identical two errors, so it isunrelated to this change — but it does mean no data-plane evidence is offered
here.
cargo fmt -p control_plane -- --checkclean;cargo clippy -p control_plane --all-targetsreports no new warning in the changed file.Architectural decisions
Withhold
SharedSubtreeStrategyrather than try to out-rank its rewrite.Rejected alternative: register it and pin
ControlPlaneCostModel::cse_share_decisionto
Share, so only the share arm can win. That was the first shape of this PRand it is wrong: the share arm is itself a logical rewrite, so it still
materializes as
KeepPreAsapand still loses the sketch.rank_groupreturnsfrom Shape 1 before any cost hook could reorder a
Summaryahead of it, so nocost-model policy can express the intended outcome. Withholding the strategy and
pinning the behavior with a regression test is the honest option at this pin.
Do not invent a shared-grid collision bound to make Hydra selectable.
Rejected alternative: default
hydra_shared_grid_collision_boundto0.0socandidates survive. That would let a shared grid win on an accuracy claim nothing
measured, contradicting the convention this crate states for every other cost
input ("unknown values stay unknown, preventing optimistic zeroes"). Registration
and evidence stay separate, individually reviewable steps.
Leave
estimated_subpopulation_countunimplemented. It changes whichcandidate wins, not whether it is enumerated, and needs its own evidence story.
Limitations and follow-up
QueryEvidence::propagation_stats(
compiler.rs:447) fills only the TopK fields, sohydra_shared_grid_collision_bound/hydra_shared_grid_failure_probabilityare
Noneandbuild_candidate'ssatisfiescheck drops every Hydracandidate. That one function is the whole remaining gap; the test above fails
loudly if this stops being true in either direction.
hydra_kind_formapsCmsandCountSketchonly, so KLL/DDSketch quantiles have no Hydra variant at plannerpin
3be523fa.AggIntent::TopKbindsCmsWithHeap/CountSketchWithHeap,also unmapped.
ControlPlaneCostModeldoes not overrideestimated_subpopulation_count, sorank_group's grouping comparison is skipped and candidates keep discoveryorder (independent first). ERP's
observed_populationsis a plausible source;deliberately deferred.
SharedSubtreeStrategyneeds an upstream fix before it can be registered —see How. Filed as follow-up work against Planner, not worked around here.
aggregate.
HydraGroupingStrategy::matchesis!hydra_candidates().is_empty(),and
hydra_candidatesruns a fullconstruct_summary_withbind per mappedsketch kind. Because the accuracy gate above always rejects today, that work is
thrown away for every grouped
Count-shaped target compiled; once evidencelands, a matching target pays it twice (
matches, thenpropose). Plan-compiletime only and bounded by target count. Not measured — flagged rather than
quantified.
search_cse_workload_withasksRollupStrategy,AccuracyReconciliationStrategyandTopKLimitReuseStrategy(
replacement.rs:5247,:5256,:5268) was verified by reading the pinnedsource, not by a test. A future Planner bump could drop it and silently cost
the backend three strategies. A trace-level assertion would close this.
hydra_candidates_wait_for_shared_grid_evidencebuilds the strategydirectly, not through
replacement_strategies, so it does not prove theregistered instance carries the same models. Combined with the registration
test the coverage holds, but the two can drift.
Verification.
Review
Self-review only — the author performed it; not independent, per
.agents/skills/asap-code-review. It corrected two things in this PR: the doccomment and test name claimed to register "every context-free strategy" while
deliberately excluding one, and the verification counts conflated 758
pre-existing lib tests with the 761 post-change total. The three items it could
not close are recorded under Limitations.
Human review — do not complete with an agent
🤖 Generated with Claude Code