@@ -268,6 +268,7 @@ fn cleanup_orphan_project_projections(
268268 warnings_emitted : & mut usize ,
269269) -> bool {
270270 let mut cleaned = true ;
271+ let mut skipped = false ;
271272 let ctx = match Context :: resolve_for_project_id_with_services (
272273 project_id,
273274 quiet,
@@ -296,6 +297,7 @@ fn cleanup_orphan_project_projections(
296297 }
297298 } else {
298299 totals. graph_projects_skipped += 1 ;
300+ skipped = true ;
299301 }
300302
301303 if let Some ( qdrant) = & ctx. qdrant {
@@ -313,8 +315,15 @@ fn cleanup_orphan_project_projections(
313315 }
314316 } else {
315317 totals. vector_projects_skipped += 1 ;
318+ skipped = true ;
316319 }
317- cleaned
320+ orphan_projection_cleanup_confirmed ( cleaned, skipped)
321+ }
322+
323+ fn orphan_projection_cleanup_confirmed ( cleaned : bool , skipped : bool ) -> bool {
324+ // Keep SQL discovery rows when any projection store was skipped; they are
325+ // what lets a later prune with full service config find and clear orphans.
326+ cleaned && !skipped
318327}
319328
320329fn print_orphan_project_reconcile_totals ( totals : & OrphanProjectReconcileTotals ) {
@@ -540,6 +549,14 @@ mod tests {
540549 ) ;
541550 }
542551
552+ #[ test]
553+ fn orphan_projection_cleanup_requires_confirmed_non_skipped_cleanup ( ) {
554+ assert ! ( orphan_projection_cleanup_confirmed( true , false ) ) ;
555+ assert ! ( !orphan_projection_cleanup_confirmed( true , true ) ) ;
556+ assert ! ( !orphan_projection_cleanup_confirmed( false , false ) ) ;
557+ assert ! ( !orphan_projection_cleanup_confirmed( false , true ) ) ;
558+ }
559+
543560 #[ test]
544561 fn bounded_project_id_summary_caps_ids ( ) {
545562 let ids = ( 0 ..10 )
0 commit comments