perf: Decouple filesystem walk from git index construction
Split find_untracked_files into two phases that can run in parallel:
1. walk_candidate_files (I/O-bound): Enumerates all non-gitignored files
within scope using the ignore crate's native gitignore support. Only
needs the git root path and package prefixes — no tracked index.
2. filter_untracked_from_candidates (CPU-bound): Binary-searches each
candidate against ls_tree_hashes and status_entries to identify truly
untracked files. Runs after the tracked index is ready.
The git root is sent via a oneshot channel as soon as SCM::new() resolves
it (~5ms), while new_from_gix_index continues (~267ms). The walk starts
immediately and runs in parallel with index construction.
Benchmark (110-package monorepo, 30 runs, sandbox):
baseline: 853ms ± 19ms
improved: 619ms ± 6ms (1.38x faster)