Repository navigation
fix(server): workspace search leaves out files Git ignores outside .gitignore - #35673
juliusmarminge wants to merge 2 commits into
Conversation
…e.excludesFile Failing tests for #35587: path search and content search return files Git ignores through .git/info/exclude or core.excludesFile. AI-assisted; verified with the tests and tools listed above.
…itignore The native search index applies .gitignore files only, so files ignored through .git/info/exclude, core.excludesFile or the default global ignore file showed up in path search, the flat listing and content search. The index now lists Git's ignored paths with `git ls-files --others --ignored --exclude-standard --directory` when it is built and on each refresh, and drops matching entries and grep hits. Path searches widen their first page when hidden entries fill it. AI-assisted; verified with the tests and tools listed above.
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Workspace search now honors Git's global and repository-local exclusions as well as .gitignore. The change filters search results using bounded, read-only Git inspection without modifying files or persistent data. You can add or adjust custom eligibility rules. Learn more. |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Other scenariosAll 64 scenario measurements match All 64 scenario measurements
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
The native search index (fff-node 0.11.0, the latest stable) applies .gitignore files only: it does not read .git/info/exclude, core.excludesFile or the default global ignore file, and it reports those files with gitStatus 'clean', so its results carry no signal to filter on. WorkspaceSearchIndex.make now captures VcsProcess and loads Git's untracked ignored paths with
git -c core.fsmonitor=false ls-files --others --ignored --exclude-standard --directory -zwhen the index is built and again on each refresh (refresh already runs after every agent run and file write). list, search (file, directory and mixed) and searchContents drop any entry whose path or a parent folder is in that set. A new searchVisible helper fetches a bigger page (x4 each time, up to the existing WORKSPACE_INDEX_PAGE_SIZE cap) when ignored entries fill the first page, so they cannot crowd out real matches; it is still one call when nothing is hidden. The result mappers now take a narrow {items,totalMatched} type. If git fails, times out or its output is cut off, the set is empty and behaviour matches main. No regex or parser was added; the ignored-path check walks a path's parent folders once each, so its cost grows with folder depth. Known gap: a file created between refreshes that a non-.gitignore rule would hide can show up until the next refresh.Fixes #35587
Reproduction on main
Commit da345d2 (origin/main). 1) Ran the reporter's repro.sh unchanged against a fresh worktree after
vp i: it exits 0, meaning the defect is present. In the 'configured' fixturegit check-ignorereports gitignore-target.txt, info-exclude-target.txt and global-exclude-target.txt as ignored. WorkspaceEntries.search, flat list and searchContents all still return info-exclude-target.txt and global-exclude-target.txt; only gitignore-target.txt is excluded. The 'default' fixture (~/.config/git/ignore) shows the same for default-exclude-target.txt and info-exclude-target.txt. Directory-scoped list marks them all ignored:true, which is correct. Adding the same patterns to .gitignore (the 'workaround' fixture) excludes them. 2) Extended two existing tests in apps/server/src/workspace/WorkspaceEntries.test.ts. 'excludes gitignored paths for git repositories' gains files listed in .git/info/exclude and in a repository-local core.excludesFile. 'honors case sensitivity and gitignore rules' gains a file listed in .git/info/exclude. Both fail on main withexpected [...] to not include 'info-excluded.txt'and an extra content match. Both runs called the production WorkspaceEntries service layer, not a dev server driven through the UI.Evidence
Being captured: before and after in the real app. This section is filled in before the pull request can merge.
Tests
vp test run src/workspace/WorkspaceEntries.test.ts src/workspace/WorkspaceSearchIndex.test.ts: 31 passed (with WorkspaceSearchIndex.ts reverted to the repro base: 3 failed, the two repro cases plus the new page-growth case). vp run typecheck in apps/server: pass. vp run check:changed: pass (format, lint, knip, graphql, typecheck of 3 packages, tests of 3 files). Manual check: git ls-files --exclude-standard on a fixture lists the info/exclude, core.excludesFile and .gitignore entries.
Not in this change
AI-assisted; verified with the tests and tools listed above.