Skip to content

fix(shell): scope file-mention walk to typed directory prefix#1403

Open
howardpen9 wants to merge 1 commit intoMoonshotAI:mainfrom
howardpen9:fix/scoped-file-mention-completion
Open

fix(shell): scope file-mention walk to typed directory prefix#1403
howardpen9 wants to merge 1 commit intoMoonshotAI:mainfrom
howardpen9:fix/scoped-file-mention-completion

Conversation

@howardpen9
Copy link
Contributor

@howardpen9 howardpen9 commented Mar 11, 2026

Summary

Fixes #1375 — In large repositories, the @ file-mention completer becomes unable to find files in directories that sort alphabetically late (e.g., src/, tests/). The root cause is that _get_deep_paths() walks the entire project tree from the root and stops at limit (default 1000), so early directories exhaust the budget before later ones are ever visited.

Changes

  • Scope the walk: When the typed fragment contains a / (e.g., @src/utils/hel), extract the directory prefix and start os.walk() from that subdirectory instead of the project root. This ensures completions always search the intended subtree regardless of repo size.
  • Scope-aware caching: The path cache now tracks which scope it was built for (_cache_scope), so switching between directories correctly invalidates stale results.
  • Include scope directory: The scoped directory itself (e.g., src/) is included in results so existing behavior (showing the directory entry) is preserved.

Test plan

  • Added test_scoped_walk_finds_deep_files_in_large_repos — regression test with 15 early directories exhausting a small limit, verifying late directories are still reachable
  • Added test_scoped_walk_with_partial_filename — verifies scoped walk works with partial filename after slash
  • All 8 existing + new tests pass

Open with Devin

…otAI#1375)

In large repositories the `@` file completer exhausts its limit while
walking early (alphabetically) directories, making files in later
directories unreachable.  Scope `os.walk()` to the directory prefix
the user has already typed so completion always searches the intended
subtree regardless of repo size.

Closes MoonshotAI#1375
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment on lines +288 to +293
if "/" in fragment:
dir_part = fragment.rsplit("/", 1)[0]
candidate = self._root / dir_part
if candidate.is_dir():
walk_root = candidate
scope_prefix = dir_part + "/"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Fragment starting with / produces empty dir_part, corrupting all completion paths with a leading / prefix

When a user types @/something, _extract_fragment returns the fragment "/something". In _get_deep_paths, fragment.rsplit("/", 1)[0] yields dir_part = "". Then self._root / "" resolves to self._root itself (which is a directory), so candidate.is_dir() is True and scope_prefix is set to "" + "/" = "/". Every path emitted by the walk is then prefixed with "/", producing completions like "/nested/" and "/file.py" instead of "nested/" and "file.py". The scope directory entry itself is also the bare string "/". These corrupted paths won't match any real relative path from the project root, so completions become unusable for this input. The old code (before this PR) had no scope_prefix logic and would have returned correct relative paths for this edge case.

Suggested change
if "/" in fragment:
dir_part = fragment.rsplit("/", 1)[0]
candidate = self._root / dir_part
if candidate.is_dir():
walk_root = candidate
scope_prefix = dir_part + "/"
if "/" in fragment:
dir_part = fragment.rsplit("/", 1)[0]
if dir_part:
candidate = self._root / dir_part
if candidate.is_dir():
walk_root = candidate
scope_prefix = dir_part + "/"
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

File mentions (@) can't find the files

1 participant