Skip to content

workspaceindex.ShouldSkipDir denylist misses common build-cache dirs (target/, __pycache__/, .venv/, ...) — scan budget burned on build artifacts, not .gitignore #1108

Description

@FabioLeitao

What happens

internal/workspaceindex.ShouldSkipDir is a fixed, hardcoded denylist of directory
names to skip while scanning (used by repo-map, repo-info, and anything else built
on workspaceindex.Scan). It does not consult the scanned repo's own .gitignore
(Scan has no git dependency at all), and the denylist itself is missing several
directory names that are build output or cache in virtually every ecosystem:

// internal/workspaceindex/workspaceindex.go
func ShouldSkipDir(name string) bool {
	switch strings.ToLower(strings.TrimSpace(name)) {
	case ".cache", ".git", ".next", ".worktrees", ".zero", "build", "coverage", "dist", "node_modules", "vendor":
		return true
	default:
		return false
	}
}

Missing (non-exhaustive, found by reproducing against a real multi-language repo):
target (Cargo/Rust), __pycache__, .venv/venv, .pytest_cache, .terraform,
.mypy_cache, .ruff_cache.

Impact

Scan has a fixed MaxFiles budget (DefaultMaxFiles = 2000). Against a real repo
with several small Rust crates, rust/*/target/debug/.fingerprint/ alone produced
308 files (.d/.rlib/.rmeta/.timestamp) that counted toward that budget before
real source did. repo-map --json against that repo reported "truncated": true at
2000 files, and a repo-map --query ranking run returned 15 results, all of them
build-cache/fingerprint files, zero real source
— the query terms matched path
fragments inside target/debug/.fingerprint/* ahead of the actual source file the
query was looking for.

This repo's own .gitignore already excludes target/; the scanner just never looks
at it.

Repro

$ git clone <any repo with a sizeable target/ or __pycache__/ dir>
$ zero repo-map --json | head -5
# fileCount near/at MaxFiles, "truncated": true, driven by target/debug/.fingerprint/*
$ zero repo-map --query "<term that matches a real source file>" --max-files 15
# ranked results dominated by target/**/*.{d,rlib,rmeta,timestamp}, score identical (1000) for all, no real source in the top 15

Proposed fix (narrow, ready as a draft PR on my fork)

Extend the ShouldSkipDir switch with the missing common build-cache directory names
(same pattern already used for node_modules/vendor/dist/build/coverage). I have
this implemented + a regression test (both a ShouldSkipDir unit case and an end-to-end
Scan case reproducing the target/debug/.fingerprint/* scenario) ready on
FabioLeitao/zero, branch to be pushed once I can rebuild/verify locally (hit an
unrelated full-disk condition on my own machine mid-verification, not a repo issue).

Separate, bigger question for maintainers (not proposing this now)

The narrow fix above is whack-a-mole against an ever-growing list of ecosystem-specific
build-cache names. The more durable fix would be for Scan to actually honor the
target repo's .gitignore (and .git/info/exclude) when the root is a git repo,
falling back to the current denylist otherwise. That's a bigger, dependency-adding
change per AGENTS.md §1 ("discuss ... major dependency changes ... before
implementation"), so I'm flagging it here for discussion rather than attempting it
unasked. Happy to take either direction once a maintainer weighs in — the narrow fix
is independently correct and small either way.

I'll follow CONTRIBUTING.md's community-PR process (parent issue + issue-approved
label) before opening a PR against this repo; the fix is staged on my fork in the
meantime.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    issue-approvedReviewed and approved by the core team; community PRs may implement this issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions