@@ -1078,6 +1078,69 @@ TEST(store_bfs_trail_warns_when_path_rows_are_truncated) {
10781078 PASS ();
10791079}
10801080
1081+ TEST (store_bfs_trail_preserves_deeper_match_under_hub_budget ) {
1082+ cbm_store_t * s = cbm_store_open_memory ();
1083+ cbm_store_upsert_project (s , "test" , "/tmp/test" );
1084+
1085+ cbm_node_t root = {.project = "test" ,
1086+ .label = "Function" ,
1087+ .name = "root" ,
1088+ .qualified_name = "test.root" };
1089+ cbm_node_t branch = {.project = "test" ,
1090+ .label = "Function" ,
1091+ .name = "branch" ,
1092+ .qualified_name = "test.branch" };
1093+ cbm_node_t target = {.project = "test" ,
1094+ .label = "Function" ,
1095+ .name = "target" ,
1096+ .qualified_name = "test.target" };
1097+ int64_t root_id = cbm_store_upsert_node (s , & root );
1098+ int64_t branch_id = cbm_store_upsert_node (s , & branch );
1099+ int64_t target_id = cbm_store_upsert_node (s , & target );
1100+
1101+ cbm_edge_t edge = {
1102+ .project = "test" , .source_id = root_id , .target_id = branch_id , .type = "CALLS" };
1103+ cbm_store_insert_edge (s , & edge );
1104+ edge .source_id = branch_id ;
1105+ edge .target_id = target_id ;
1106+ cbm_store_insert_edge (s , & edge );
1107+
1108+ /* A high-fanout hub must not consume the bounded CTE before a deeper path
1109+ * is considered; the depth-first queue should still surface `target`. */
1110+ enum { LEAF_COUNT = 4100 };
1111+ for (int i = 0 ; i < LEAF_COUNT ; i ++ ) {
1112+ char name [32 ];
1113+ snprintf (name , sizeof (name ), "leaf-%d" , i );
1114+ cbm_node_t leaf = {.project = "test" ,
1115+ .label = "Function" ,
1116+ .name = name ,
1117+ .qualified_name = name };
1118+ int64_t leaf_id = cbm_store_upsert_node (s , & leaf );
1119+ edge .source_id = root_id ;
1120+ edge .target_id = leaf_id ;
1121+ cbm_store_insert_edge (s , & edge );
1122+ }
1123+
1124+ const char * types [] = {"CALLS" };
1125+ cbm_traverse_result_t result = {0 };
1126+ int rc = cbm_store_bfs_trail (s , root_id , "outbound" , types , 1 , 2 , 5000 , & result );
1127+ ASSERT_EQ (rc , CBM_STORE_OK );
1128+ ASSERT_TRUE (result .truncated );
1129+
1130+ bool saw_target = false;
1131+ for (int i = 0 ; i < result .visited_count ; i ++ ) {
1132+ if (result .visited [i ].node .id == target_id ) {
1133+ saw_target = true;
1134+ break ;
1135+ }
1136+ }
1137+ ASSERT_TRUE (saw_target );
1138+
1139+ cbm_store_traverse_free (& result );
1140+ cbm_store_close (s );
1141+ PASS ();
1142+ }
1143+
10811144/* ── BFS cross-service summary ─────────────────────────────────── */
10821145
10831146TEST (store_bfs_cross_service_summary ) {
@@ -1597,6 +1660,7 @@ SUITE(store_search) {
15971660 RUN_TEST (store_bfs_with_risk_labels );
15981661 RUN_TEST (store_bfs_reachability_is_not_trail_capped );
15991662 RUN_TEST (store_bfs_trail_warns_when_path_rows_are_truncated );
1663+ RUN_TEST (store_bfs_trail_preserves_deeper_match_under_hub_budget );
16001664 RUN_TEST (store_bfs_cross_service_summary );
16011665 RUN_TEST (store_glob_to_like );
16021666 RUN_TEST (store_extract_like_hints );
0 commit comments