@@ -964,6 +964,36 @@ static int resp_lacks_key(const char *resp, const char *key) {
964964
965965/* ── list_projects ─────────────────────────────────────────────── */
966966
967+ TEST (incr_file_node_name_stays_basename ) {
968+ /* #994: File nodes must keep their basename NAME through an incremental
969+ * re-index (the bug renamed touched files' nodes to rel_path, diverging
970+ * from a full build). Modify a file, re-index, assert no File node name
971+ * contains a path separator. */
972+ char path [512 ];
973+ snprintf (path , sizeof (path ), "%s/fastapi/applications.py" , g_repodir );
974+ FILE * f = fopen (path , "a" );
975+ ASSERT (f != NULL );
976+ fprintf (f , "\n# incr_file_node_name_stays_basename touch\n" );
977+ fclose (f );
978+
979+ char * resp = index_repo ();
980+ ASSERT (resp != NULL );
981+ free (resp );
982+
983+ double ms ;
984+ char * r = call_tool_timed ("query_graph" , & ms ,
985+ "{\"project\":\"%s\",\"format\":\"json\","
986+ "\"query\":\"MATCH (n:File) WHERE n.name CONTAINS '/'"
987+ " RETURN n.name LIMIT 5\"}" ,
988+ g_project );
989+ TOOL_OK (r , ms );
990+ /* No File node may carry a path separator in its name; the query engine
991+ * returns an empty rows array when nothing matches. */
992+ ASSERT (strstr (r , "\"rows\":[]" ) != NULL || strstr (r , "\\\"rows\\\":[]" ) != NULL );
993+ free (r );
994+ PASS ();
995+ }
996+
967997TEST (tool_list_projects_basic ) {
968998 double ms ;
969999 char * r = call_tool_timed ("list_projects" , & ms , "{}" );
@@ -2970,6 +3000,7 @@ SUITE(incremental) {
29703000
29713001 /* Phase 3: Incremental deltas */
29723002 RUN_TEST (incr_modify_file );
3003+ RUN_TEST (incr_file_node_name_stays_basename );
29733004 RUN_TEST (incr_formatter_run );
29743005 RUN_TEST (incr_add_file );
29753006 RUN_TEST (incr_delete_file );
0 commit comments