Skip to content

Resolve the search bundle so a symlinked root works - #86

Merged
RichardHightower merged 1 commit into
mainfrom
fix/issue-85-symlinked-bundle
Sep 19, 2026
Merged

RichardHightower merged 1 commit into
mainfrom
fix/issue-85-symlinked-bundle

Conversation

@RichardHightower

Copy link
Copy Markdown
Contributor

Closes #85.

Why

rg prints resolved paths. search() built each hit's display path against the bundle the caller passed, so when that bundle still held a symlink the two did not match and relative_to raised. Search failed outright.

This is not macOS-only. /var is a symlink to /private/var there, so every temporary bundle reproduces it. A symlinked checkout or a container bind mount is the same shape on Linux. CI has neither, which is why it shipped.

What

One line. The root cause is the bundle, not the line that raised. Every engine derives its paths from the bundle it is handed, so resolving once at the top of search() makes candidate_files and the display loop agree. One syscall per call, not one per file, which is the property _filter_rg_hits already protects.

candidate_files keeps taking the bundle as given. Tests call it directly and expect paths under the bundle they passed, and _filter_rg_hits already resolves for its own comparison, so that path was never broken. Resolving there instead broke test_index_candidates_honor_prefix_without_scan, which is how the narrower placement was chosen.

Verification

New test_symlinked_bundle_agrees_across_engines searches through a real symlink on all three engines (scan, rg, index) and asserts they return the same path.

State tests/test_pkc.py
fix reverted ERROR: test_symlinked_bundle_agrees_across_engines
fix applied Ran 112 tests, OK

tools/ci-local.sh reports 27 passed, 0 failed. It was red on macOS before this.

🤖 Generated with Claude Code

rg prints resolved paths. search() built each hit's display path against
the bundle the caller passed, so when that bundle still held a symlink the
two did not match and relative_to raised. Search failed outright.

Root cause is the bundle, not the line that raised. Every engine derives
its paths from the bundle it is handed, so resolving once at the top of
search() makes candidate_files and the display loop agree. One syscall per
call, not one per file, which is the property _filter_rg_hits already
protects.

candidate_files keeps taking the bundle as given. Tests call it directly
and expect paths under the bundle they passed, and _filter_rg_hits already
resolves for its own comparison, so that path was never broken.

Not macOS-only. /var -> /private/var makes every temporary bundle
reproduce it there; a symlinked checkout or a container bind mount is the
same shape on Linux. CI has neither, which is why this shipped.

Adds test_symlinked_bundle_agrees_across_engines, which searches through a
real symlink on all three engines. Verified it fails with the one-line fix
reverted and passes with it. tools/ci-local.sh reports 27 passed, 0 failed.

Closes #85. Item 01M2XWFX063T5QMJ7SC5ZE2R6Q.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@RichardHightower
RichardHightower merged commit a9157c3 into main Sep 19, 2026
4 checks passed
@RichardHightower
RichardHightower deleted the fix/issue-85-symlinked-bundle branch September 19, 2026 22:28
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.

_rel() raises when the bundle root is a symlink: test_titleless_stem_match fails on macOS

1 participant