v0.0.17
What's Changed
Fixed
globandgrepmount-prefix routing — Absolute patterns and literalpathsfilters are now stripped of the mount prefix before dispatch to each mount. Previously the non-candidate fanout in_route_fanoutforwarded the full pattern to every mount, but mounts store paths mount-relative — soglob('/data/**/*.py')andgrepwithpaths=('/data/src',)silently returned empty whilereadon the same path worked. New dedicated_route_glob_fanout/_route_grep_fanoutuse exact-rewrite when provable (literal-prefix or single-segment glob consumption against the mount name) and fall back to a/**superset query plus router-side authoritative re-filter when the pattern's leading segment is**.globs_notis never silently dropped — exclusions that cannot be exactly pushed are enforced at the router after rebase.max_countis deferred to the router whenever any mount uses the post-filter fallback so it cannot truncate pre-filter candidates. Wildcard mount selectors (/*/,/d?ta/,/d[ae]ta/) and multi-hop chains (GroverAsync → router → router → leaf) work correctly. The candidate-input path (glob/grepwithcandidates=) had the same mismatch and is fixed by filtering at the router with the original absolute pattern before grouping by terminal.
Added
grover.routingmodule — Pure helpers (rewrite_glob_for_mount,rewrite_path_for_mount,first_segment,glob_segment_matches) and plan dataclasses (GlobMountPlan,GrepMountPlan) backing the new fanout strategy.
Changed
MSSQLFileSystemglob pushdown —_glob_implnow structurally decomposes glob patterns via the newdecompose_glob()helper into a literal path prefix and a trailing**/*.<ext>tail, then pushes both into SQL: the prefix becomes a sargableLIKEpredicate and the ext narrows the(ext, kind)composite index seek. When the pattern is fully expressible asprefix + **/*.<ext>the authoritativeREGEXP_LIKEresidual is dropped entirely andkindis narrowed to'file'so the planner picksix_grover_objects_ext_kindinstead of relying onext IS NULLfor directory exclusion. Caller-suppliedextandpathsremain authoritative (intersected with the decomposed values) so explicit narrowing is never broadened by the optimization. Patterns the decomposer doesn't recognize fall through to the existing regex path with no behavior change.
Full Changelog: v0.0.16...v0.0.17