271878bcea
The rule scan cache stored a path[] keyed by (projectRoot|startDir| skipClaudeUserRules), so two issues stacked up on every tracked tool call: - Cache hits still ran safeRealpathSync(realpathSync) and re-derived isGlobal / distance / isSingleFile for every cached path. That is a per-candidate sync syscall plus repeated string-prefix walks. - Sibling files in the same project landed under different startDir keys, so the entire walk-and-recursive-scan chain repeated even though every ancestor rule directory was identical. Store the full RuleFileCandidate[] in the per-call cache so a cache hit returns immediately with no realpath syscall. Add a separate per- directory scan cache (getDirScan/setDirScan) keyed by absolute rule directory path, so two sibling files reuse the same readdir + realpath work for every shared ancestor. Microbench (200 files / 20 modules / cached session): - single sweep: 41.8ms -> 2.5ms (16x) - 3-pass replay: 88.6ms -> 3.2ms (28x) Pin the new invariants with two new tests: - 'does not re-resolve symlinked rule path on cache hit' via a retargeted directory symlink. - 'reuses ancestor directory scan for sibling files in the same project' by deleting the source rule file between the two calls.