@@ -155,7 +155,10 @@ fn promql_binary_arithmetic_never_relabels_approximate_children_as_exact() {
155155}
156156
157157#[ test]
158- fn temporal_topk_binds_constant_one_and_sample_value_weight_projections ( ) {
158+ fn planner_only_e2e_temporal_topk_preserves_query_update_and_readout_contract ( ) {
159+ // Self-contained Planner E2E: each case starts from PromQL text and ends
160+ // at the executable post-ASAP summary DAG. No controller/backend types,
161+ // fixtures, configuration, or runtime are involved.
159162 let cases = [
160163 (
161164 "topk by (service) (5, count_over_time(requests[1m]))" ,
@@ -199,19 +202,34 @@ fn temporal_topk_binds_constant_one_and_sample_value_weight_projections() {
199202 . expect ( "heap-backed temporal Top-K candidate" ) ;
200203 let SummaryExpr :: SummaryEstimate {
201204 summary_input,
202- query : SketchQuery :: TopK { .. } ,
205+ query : SketchQuery :: TopK { k , .. } ,
203206 } = & candidate. expr
204207 else {
205208 panic ! ( "expected Top-K estimate, got {:?}" , candidate. expr)
206209 } ;
210+ assert_eq ! (
211+ * k, 5 ,
212+ "the requested Top-K cardinality must survive binding"
213+ ) ;
207214 let SummaryExpr :: SummaryAgg {
208215 input : state_input,
216+ family,
209217 child,
210218 ..
211219 } = & summary_input. expr
212220 else {
213221 panic ! ( "expected structured Top-K state input" )
214222 } ;
223+ let SummaryFamilyType :: Sketch ( kind, _) = family else {
224+ panic ! ( "expected a heap-backed sketch family, got {family:?}" )
225+ } ;
226+ assert_eq ! ( format!( "{:?}" , kind. algorithm( ) ) , expected_family) ;
227+ let heap_size = match kind. params ( ) {
228+ SketchParams :: CmsWithHeap { heap_size, .. }
229+ | SketchParams :: CountSketchWithHeap { heap_size, .. } => * heap_size,
230+ params => panic ! ( "expected heap-bearing Top-K parameters, got {params:?}" ) ,
231+ } ;
232+ assert_eq ! ( heap_size, * k as u32 ) ;
215233 assert_eq ! (
216234 state_input. item. as_ref( ) ,
217235 Some ( & SummaryInputExpr :: EntityIdentity (
0 commit comments