@@ -10540,6 +10540,105 @@ TEST(mcp_auto_watch_false_skips_watcher_on_connect) {
1054010540 PASS ();
1054110541}
1054210542
10543+ /* ══════════════════════════════════════════════════════════════════
10544+ * #1466 — autoindex.skip must report the effective numeric limit
10545+ * ══════════════════════════════════════════════════════════════════ */
10546+
10547+ static char autoindex_skip_log [1024 ];
10548+
10549+ /* Keeps only the too_many_files skip line, so later lines cannot displace it. */
10550+ static void autoindex_skip_capture_log (const char * line ) {
10551+ if (line && strstr (line , "msg=autoindex.skip" ) && strstr (line , "reason=too_many_files" )) {
10552+ snprintf (autoindex_skip_log , sizeof (autoindex_skip_log ), "%s" , line );
10553+ }
10554+ }
10555+
10556+ /* Drive initialize → maybe_auto_index over a fresh project holding more tracked
10557+ * files than auto_index_limit, and capture the resulting skip warning.
10558+ * Returns false on fixture setup failure. */
10559+ static bool autoindex_skip_warning (char * out , size_t out_size ) {
10560+ char cache [256 ];
10561+ snprintf (cache , sizeof (cache ), "%s/cbm-autoindex-limit-XXXXXX" , cbm_tmpdir ());
10562+ if (!cbm_mkdtemp (cache )) {
10563+ return false;
10564+ }
10565+
10566+ char repodir [512 ];
10567+ snprintf (repodir , sizeof (repodir ), "%s/repo" , cache );
10568+ char file_a [640 ];
10569+ char file_b [640 ];
10570+ snprintf (file_a , sizeof (file_a ), "%s/a.py" , repodir );
10571+ snprintf (file_b , sizeof (file_b ), "%s/b.py" , repodir );
10572+ if (th_mkdir_p (repodir ) != 0 || th_write_file (file_a , "def a():\n return 1\n" ) != 0 ||
10573+ th_write_file (file_b , "def b():\n return 2\n" ) != 0 ) {
10574+ th_rmtree (cache );
10575+ return false;
10576+ }
10577+
10578+ const char * saved = getenv ("CBM_CACHE_DIR" );
10579+ char * saved_copy = saved ? strdup (saved ) : NULL ;
10580+ cbm_setenv ("CBM_CACHE_DIR" , cache , 1 );
10581+
10582+ char old_cwd [1024 ];
10583+ if (!cbm_getcwd (old_cwd , sizeof (old_cwd )) || cbm_chdir (repodir ) != 0 ) {
10584+ restore_cache_dir (saved_copy );
10585+ free (saved_copy );
10586+ th_rmtree (cache );
10587+ return false;
10588+ }
10589+
10590+ bool ok = false;
10591+ cbm_config_t * cfg = cbm_config_open (cache );
10592+ if (cfg ) {
10593+ cbm_config_set (cfg , CBM_CONFIG_AUTO_INDEX , "true" );
10594+ cbm_config_set (cfg , CBM_CONFIG_AUTO_INDEX_LIMIT , "1" );
10595+
10596+ cbm_mcp_server_t * srv = cbm_mcp_server_new (NULL );
10597+ if (srv ) {
10598+ autoindex_skip_log [0 ] = '\0' ;
10599+ CBMLogLevel prev_level = cbm_log_get_level ();
10600+ cbm_log_set_level (CBM_LOG_WARN );
10601+ cbm_log_set_format (CBM_LOG_FORMAT_TEXT );
10602+ cbm_log_set_sink_ex (autoindex_skip_capture_log , CBM_LOG_SINK_REPLACE );
10603+
10604+ cbm_mcp_server_set_config (srv , cfg );
10605+ char * resp = cbm_mcp_server_handle (
10606+ srv , "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{}}" );
10607+ free (resp );
10608+ cbm_mcp_server_free (srv );
10609+
10610+ cbm_log_set_sink (NULL );
10611+ cbm_log_set_level (prev_level );
10612+
10613+ snprintf (out , out_size , "%s" , autoindex_skip_log );
10614+ ok = true;
10615+ }
10616+ cbm_config_close (cfg );
10617+ }
10618+
10619+ (void )cbm_chdir (old_cwd );
10620+ restore_cache_dir (saved_copy );
10621+ free (saved_copy );
10622+ th_rmtree (cache );
10623+ return ok ;
10624+ }
10625+
10626+ /* RED before the fix: the warning carries `limit=auto_index_limit`, the config
10627+ * key constant, instead of the configured value. */
10628+ TEST (autoindex_skip_reports_numeric_limit_issue1466 ) {
10629+ char warning [1024 ];
10630+ if (!autoindex_skip_warning (warning , sizeof (warning ))) {
10631+ PASS (); /* fixture setup failed (tmpdir/cwd unavailable) — skip */
10632+ }
10633+ /* Not vacuous: the skip path must actually have been taken. */
10634+ ASSERT_NOT_NULL (strstr (warning , "msg=autoindex.skip" ));
10635+ ASSERT_NOT_NULL (strstr (warning , "reason=too_many_files" ));
10636+ ASSERT_NOT_NULL (strstr (warning , "files=2" ));
10637+ ASSERT_NOT_NULL (strstr (warning , "limit=1" ));
10638+ ASSERT_NULL (strstr (warning , "limit=auto_index_limit" ));
10639+ PASS ();
10640+ }
10641+
1054310642/* ══════════════════════════════════════════════════════════════════
1054410643 * #853 — auto_watch=false must ALSO gate the SUPERVISED fresh-index
1054510644 * watcher registration (keystone × #849 merge interaction)
@@ -11472,6 +11571,7 @@ SUITE(mcp) {
1147211571 RUN_TEST (mcp_auto_watch_default_registers_watcher_on_connect );
1147311572 RUN_TEST (mcp_auto_watch_false_skips_watcher_on_connect );
1147411573 RUN_TEST (mcp_auto_watch_false_skips_supervised_autoindex_issue853 );
11574+ RUN_TEST (autoindex_skip_reports_numeric_limit_issue1466 );
1147511575}
1147611576
1147711577/* Kept separate so daemon-coordination regressions can be iterated without
0 commit comments