v0.15.2 — ast_search ranking + dead-code --json empty contract
User-driven QA pass exercising every MCP tool + CLI subcommand surfaced two bugs whose contract violations were silent — both regressions guard against recurrence.
Fixes
src/storage/queries.rs—get_nodes_with_files_by_filters(the SQL backingast_search/ast-search) ordered byf.path ASConly, so theLIMITclause silently truncated alphabetically-late files (src/storage/queries.rsitself, with 54Result-returning fns) out of the top-N. New ordering iscaller_count DESC, path ASC, line ASCso high-value symbols surface first regardless of file path.src/cli.rs:2655—dead-code --jsonreturned only stderr (no stdout) when all results were filtered by--ignore, breaking JSON consumers piping stdout. Now emits[]to stdout before the human stderr message, matching the established empty-result contract used bysearch/grep/callgraph/show/trace/overview.
New regression tests
test_get_nodes_with_files_by_filters_ranks_by_caller_count(src/storage/queries.rs) — alphabetically-first low-caller fn must not outrank alphabetically-last high-caller fn at anyLIMIT.test_cli_json_empty_dead_code(tests/cli_e2e.rs) — stdout must be[]and stderr must still surface "No dead code" when --ignore filters all results.
371 tests pass (was 369). Clippy 1.95 clean on both feature combos.
Full Changelog: v0.15.1...v0.15.2