Skip to content

[codex] Fix path-like filename search#2

Draft
future3OOO wants to merge 1 commit into
mainfrom
codex/fix-path-like-search
Draft

[codex] Fix path-like filename search#2
future3OOO wants to merge 1 commit into
mainfrom
codex/fix-path-like-search

Conversation

@future3OOO

@future3OOO future3OOO commented May 4, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fix WSL filename search for WSL UNC paths, exact path-like queries, directories, hidden dot paths, slashes, and hyphens.
  • Fix Windows filename search for hidden/path-like queries by routing those searches through the filesystem scanner and matching normalized full paths.
  • Add regression coverage for WSL and Windows path-like filename search behavior.

Root Cause

Filename search treated path-like input as ordinary name fragments. WSL also only enumerated files and had a direct-path command escaping issue through wsl.exe; Windows profile filename search relied on indexed filename matching for queries that need literal full-path matching.

Validation

  • npm test passed: 85/85.
  • Live Windows smoke found C:\Users\Property Partner\Downloads\tdd-seam-and-deep-modules-prd-final.md.
  • Live WSL smoke found /home/prop_/.codex in OpenCockLab.

Summary by cubic

Fixes filename search when queries look like paths on Windows and WSL. Supports exact file and directory paths, WSL UNC inputs, hidden dot paths, slashes, and hyphens for more reliable results.

  • Bug Fixes
    • Windows: match against System.ItemPathDisplay (full path) and detect path-like queries; route those to a filesystem scan with hidden files enabled and noisy dirs pruned.
    • Windows: normalize path comparisons and allow direct-path resolution for files and directories within the selected root.
    • WSL: accept UNC inputs like \\wsl.localhost\<distro>\..., infer distro/path, and escape $ in shell args.
    • WSL: include directories in filename search and short‑circuit when an exact candidate path under the root exists.
    • Tests: add regression coverage for WSL and Windows path-like filename searches, UNC handling, hidden dot paths, and directory results.

Written for commit cc0abd7. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Windows filename search accuracy with better path matching
    • Fixed special character handling in WSL search commands
    • Enhanced directory inclusion in search results
  • New Features

    • Added support for WSL UNC path queries in searches
    • Optimized WSL filename search performance with direct path checking

@coderabbitai

coderabbitai Bot commented May 4, 2026

Copy link
Copy Markdown

Walkthrough

Windows and WSL filename search adapters were refactored to improve path-like query handling and normalize path comparisons. Windows searches now match against full item paths (System.ItemPathDisplay) and include directories. WSL searches gain UNC path parsing, shell-safe argument escaping, and rebuilt command generation for faster path-prefix matching. Test cases were updated and expanded to verify new behavior.

Changes

Cross-Platform Filename Search Improvements

Layer / File(s) Summary
Data/Helper Shapes
src/search/windowsSearchAdapter.js, src/search/wslSearchAdapter.js
New normalization and detection helpers: normalizeFilenameComparable(), isPathLikeFilenameQuery(), parseWslUncPath(), normalizeWslRoot(), escapeWslCommandArgument(), and specialized find-command builders.
Core Search Command Building
src/search/windowsSearchAdapter.js
Windows filename search now generates System.ItemPathDisplay LIKE clauses (with /\ normalization) instead of System.FileName, removes file/folder exclusion filters, and allows directories in results via updated directFilePathResult type check.
WSL Search Command Generation
src/search/wslSearchAdapter.js
WSL search input validation extracts distro and path from UNC-style queries. Filename-mode command building now uses dedicated "fast" (ripgrep + find) and "fallback" (path discovery) pipelines with buildDirectPathPrefix() conditional handling. Final commands are wrapped with escapeWslCommandArgument() for safe $ escaping in bash -lc execution.
Ripgrep & Search Execution
src/search/windowsSearchAdapter.js, src/search/wslSearchAdapter.js
Path-like queries (/ or .-prefixed) are now recognized via isPathLikeFilenameQuery() to trigger filesystem search directly. Windows runFilenameSearch spawn call was reformatted to use expanded argument list; WSL respects mtime filtering only on the fast candidate list.
Tests & Validation
test/search.test.js, test/windowsSearch.test.js
Updated assertions to expect System.ItemPathDisplay, directory inclusion, grep -z -i -F literal matching, and python3 -c os.path.getmtime filtering. Added new tests for UNC path resolution, path-like query detection, and safe shell-character escaping.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • future3OOO/wsl-search-tool#2: Modifies the same Windows adapter filename-search code path and ripgrep invocation introduced in that PR.
  • future3OOO/wsl-search-tool#1: Overlaps on Windows path handling, direct-file-path detection, and path normalization/resolution logic for path-like queries.

Poem

🐰 Hops through Windows paths with glee,
WSL escapes set queries free!
Paths and folders unite at last,
Normalization swift and fast!
Backslashes dance, dollar signs tamed,
Search adapters evolved, refined!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[codex] Fix path-like filename search' directly and concisely captures the main objective of the PR: fixing filename search behavior for path-like queries across both WSL and Windows.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-path-like-search

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented May 4, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds WSL UNC-path parsing, direct-path fast-path logic for exact WSL path queries, hidden-file and directory support in both WSL and Windows filename scans, and routes path-like Windows profile searches through the filesystem scanner instead of the Windows Search index.

Two issues worth addressing before merge:

  • buildDirectPathPrefix is dead code. escapeWslCommandArgument escapes every $ in the already-single-quoted script body, turning $root_path / $candidate / $under_root into \\$root_path etc. In the inner bash, \\$ in double-quoted contexts is a literal $ character, not a variable reference. The [ -e \"$candidate\" ] guard always fails, and the exit 0 fast-path never fires. The test asserting \\$candidate in command[6] validates the broken state as correct.
  • OleDb semantics silently changed for simple queries. Replacing System.FileName LIKE with System.ItemPathDisplay LIKE makes all OleDb-backed profile filename searches match the full path hierarchy, not just the filename. A search for photos now returns every file under C:\\Users\\Me\\Photos\\, not only files named *photos*.

Confidence Score: 3/5

Two confirmed defects on the changed paths: the WSL direct-path fast-path is non-functional due to dollar-sign over-escaping, and OleDb filename searches now silently do full-path matching for all queries including simple word searches.

The buildDirectPathPrefix function, introduced specifically to short-circuit exact WSL path queries, never fires because escapeWslCommandArgument escapes the variable references inside the already-single-quoted script body. Additionally, the OleDb query semantic shift from System.FileName to System.ItemPathDisplay affects every profile-root filename search, not only the path-like case it was intended to fix.

src/search/wslSearchAdapter.js (escaping interaction between escapeWslCommandArgument and buildDirectPathPrefix) and src/search/windowsSearchAdapter.js (OleDb query column change and its effect on simple-word searches).

Important Files Changed

Filename Overview
src/search/wslSearchAdapter.js Adds escapeWslCommandArgument, parseWslUncPath, normalizeWslRoot, and buildDirectPathPrefix; the escapeWslCommandArgument call on the fully-quoted script body breaks every $var reference in buildDirectPathPrefix, making the fast-path dead code.
src/search/windowsSearchAdapter.js Adds isPathLikeFilenameQuery routing, normalizeFilenameComparable backslash normalisation, directory support in directFilePathResult, --hidden in rg invocation; System.FileName to System.ItemPathDisplay silently changes OleDb semantics to full-path matching for all profile-root queries.
test/search.test.js Updated and extended WSL search command assertions; the new $candidate assertion validates the broken escaping as correct behavior rather than catching the bug.
test/windowsSearch.test.js Adds well-scoped integration and unit tests for path-like profile filename searches, hidden-dot paths, and directory resolution; coverage is thorough for the Windows-side changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[WSL filename search input] --> B{parseWslUncPath?}
    B -- yes --> C[Extract distro + path from UNC]
    B -- no --> D[Use raw query + input distro]
    C --> E[validateSearchInput]
    D --> E
    E --> F[buildDirectPathPrefix BROKEN]
    F --> G{rg available?}
    G -- yes --> H[rg files + find dirs piped through grep]
    G -- no --> I[find files+dirs piped through grep]
    H --> J[head results]
    I --> J
    K[Windows filename search input] --> L[validateWindowsSearchInput]
    L --> M{directFilePathResult now includes dirs}
    M -- exact path hit --> N[Return result]
    M -- no hit --> O{shouldUseFilesystemFilenameSearch}
    O -- all-drives OR path-like OR non-profile --> P[runFilenameSearch via rg full-path match]
    O -- profile root simple query --> Q[OleDb ItemPathDisplay LIKE full-path match ALL queries]
    P --> R[parseWindowsSearchOutput]
    Q --> R
Loading

Fix All in Codex

Reviews (12): Last reviewed commit: "Fix path-like filename search" | Re-trigger Greptile

Comment on lines +18 to +20
function escapeWslCommandArgument(value) {
return String(value).replace(/\$/g, "\\$");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 escapeWslCommandArgument breaks buildDirectPathPrefix variable expansion

escapeWslCommandArgument replaces every $ in the already-shellQuoted script — including the $root_path, $candidate, and $under_root references inside the single-quoted inner-bash script body. Those references end up as \$root_path / \$candidate. Inside single quotes, they are passed literally to the inner bash. In double-quoted contexts like [ "\$root_path" = "/" ], bash interprets \$ as a literal $ character, not a variable. root_path and candidate are assigned but never read. The [ -e "$candidate" ] guard tests for a file literally named $candidate, which never exists, so the fast-path exit 0 never fires and every path-like WSL query falls through to a full rg/find scan.

Smallest correct fix: apply escapeWslCommandArgument only before shellQuote on user-controlled input if needed, not on the entire already-quoted script. The outer script's own $var references must remain as unexpanded dollar signs reaching the inner bash.

Fix in Codex

Comment on lines 140 to 143
"foreach ($term in $terms) {",
" $whereClauses += \"System.FileName LIKE '%\" + (Escape-LikeLiteral $term) + \"%'\"",
" $pathTerm = $term.Replace('/', [string][char]92)",
" $whereClauses += \"System.ItemPathDisplay LIKE '%\" + (Escape-LikeLiteral $pathTerm) + \"%'\"",
"}",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 System.ItemPathDisplay expands result set for simple word searches

Switching from System.FileName LIKE '%term%' to System.ItemPathDisplay LIKE '%term%' for all OleDb-backed filename searches causes full-path matching for every term, including simple non-path-like queries (e.g. photos, budget). Before this change, searching for photos returned files whose name contained photos. Now it returns every file whose full path contains photos — for example, every file under C:\Users\Me\Photos\ — which can produce a large false-positive set.

Path-like queries are now routed to runFilenameSearch (rg), so System.ItemPathDisplay is only reached for simple, non-path-like, profile-root queries. rg's matchesFilenameSearch also does full-path matching, so the two branches are now consistent — but users who expect filename-only matching for simple terms will see significantly more results. If full-path matching for all queries is intentional, a comment explaining the deliberate semantic shift would prevent future regressions back to System.FileName.

Fix in Codex

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/search/wslSearchAdapter.js`:
- Around line 18-20: The wrapper currently double-escapes dollar signs in
escapeWslCommandArgument which alters what the inner bash -lc sees and prevents
expansion of variables like $root_path and $candidate; remove the post-quoting
replacement of `$` (i.e., stop turning $ into \$) so that searchCommand—already
protected by shellQuote(...)—is passed through intact to the bash -lc wrapper;
update the escapeWslCommandArgument function (and any similar escaping in the
WSL script wrapper) to no longer escape `$`, ensuring variable expansion and
literal dollar-containing filenames/queries work correctly.

In `@test/windowsSearch.test.js`:
- Around line 272-304: The test "runSearch uses filename filesystem search for
path-like profile filename searches" is only guarded by HAS_USERPROFILE but
should also require IS_WINDOWS because adapter.runSearch validates Windows
absolute paths; update the test's skip condition to skip when not
(HAS_USERPROFILE && IS_WINDOWS) (or equivalent) so it only runs on Windows
environments; locate the test by its title and the symbols HAS_USERPROFILE,
IS_WINDOWS, and createWindowsSearchAdapter/adapter.runSearch to modify the skip
flag accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 27ca5f93-45d0-490f-b87e-8dc4ac1bf1d4

📥 Commits

Reviewing files that changed from the base of the PR and between e687663 and cc0abd7.

📒 Files selected for processing (4)
  • src/search/windowsSearchAdapter.js
  • src/search/wslSearchAdapter.js
  • test/search.test.js
  • test/windowsSearch.test.js

Comment on lines +397 to +418
const child = spawn(
resolveRipgrepPath(),
[
"--files",
"-0",
"--hidden",
"--glob",
"!.git",
"--glob",
"!node_modules",
"--glob",
"!.cache",
"--glob",
"!.venv",
"--glob",
"!__pycache__",
"--glob",
"!dist",
...roots,
],
{ windowsHide: true }
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Filesystem fallback still drops directory matches.

shouldUseFilesystemFilenameSearch() now sends .codex/foo/bar filename queries through runFilenameSearch(), but this helper still shells out to rg --files, which never emits directory entries. That means a relative directory query like .codex/plans under %USERPROFILE% still can't return the directory itself unless the caller provides an exact absolute path and hits directFilePathResult(). The new Windows path-like flow is therefore still incomplete for directory searches.

Also applies to: 481-485

Comment on lines +18 to +20
function escapeWslCommandArgument(value) {
return String(value).replace(/\$/g, "\\$");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

search_command='candidate=/tmp/demo; query='\''price$list.txt'\''; printf "candidate=%s\nquery=%s\n" "$candidate" "$query"'
wrapped_without_escape="timeout 1s bash -lc '$search_command'"
wrapped_with_escape="timeout 1s bash -lc '${search_command//$/\\$}'"

echo "without post-escape:"
bash -lc "$wrapped_without_escape"

echo
echo "with post-escape:"
bash -lc "$wrapped_with_escape"

Repository: future3OOO/wsl-search-tool

Length of output: 251


🏁 Script executed:

# First, locate and examine the file
find . -name "wslSearchAdapter.js" -type f

Repository: future3OOO/wsl-search-tool

Length of output: 103


🏁 Script executed:

# Read the entire file to understand the context
wc -l ./src/search/wslSearchAdapter.js

Repository: future3OOO/wsl-search-tool

Length of output: 107


🏁 Script executed:

# Read the critical sections
echo "=== Lines 15-25 (function definition) ==="
sed -n '15,25p' ./src/search/wslSearchAdapter.js

echo
echo "=== Lines 139-160 (buildDirectPathPrefix and variable references) ==="
sed -n '139,160p' ./src/search/wslSearchAdapter.js

echo
echo "=== Lines 185-200 (call sites) ==="
sed -n '185,200p' ./src/search/wslSearchAdapter.js

Repository: future3OOO/wsl-search-tool

Length of output: 2933


🏁 Script executed:

# Check how buildSearchScript is used (where it's called)
echo "=== Searching for buildSearchScript calls ==="
rg "buildSearchScript" ./src/search/wslSearchAdapter.js -B 2 -A 2

echo
echo "=== Check for execSync or similar execution ==="
rg "execSync|spawn|exec" ./src/search/wslSearchAdapter.js -B 2 -A 2

Repository: future3OOO/wsl-search-tool

Length of output: 1018


🏁 Script executed:

# Check how the result of buildSearchScript is used
echo "=== Full buildSearchCommand function ==="
sed -n '173,180p' ./src/search/wslSearchAdapter.js

echo
echo "=== Look for test files ==="
find . -name "*test*" -o -name "*.test.js" -o -name "*.spec.js" | head -20

Repository: future3OOO/wsl-search-tool

Length of output: 685


🏁 Script executed:

# Get the complete buildSearchCommand function
sed -n '160,205p' ./src/search/wslSearchAdapter.js

Repository: future3OOO/wsl-search-tool

Length of output: 2698


🏁 Script executed:

# Check if there are tests for the functions being modified
grep -r "buildSearchScript\|buildSearchCommand\|escapeWslCommandArgument" ./test/ -l

Repository: future3OOO/wsl-search-tool

Length of output: 92


🏁 Script executed:

# Check the search test file for relevant tests
grep -n "buildSearchScript\|buildSearchCommand\|escapeWslCommandArgument" ./test/search.test.js -B 2 -A 5

Repository: future3OOO/wsl-search-tool

Length of output: 2929


🏁 Script executed:

# Read test cases to understand expected behavior
sed -n '36,51p' ./test/search.test.js
echo "---"
sed -n '104,116p' ./test/search.test.js
echo "---"
sed -n '145,157p' ./test/search.test.js

Repository: future3OOO/wsl-search-tool

Length of output: 1590


🏁 Script executed:

# Let's verify what the current output actually produces
# Look at the full test for the exact-path scenario
sed -n '145,157p' ./test/search.test.js

echo "---"
echo "Let's examine what escapeWslCommandArgument is actually doing to the shell command:"
echo "Looking at lines 18-20 again:"
sed -n '18,20p' ./src/search/wslSearchAdapter.js

Repository: future3OOO/wsl-search-tool

Length of output: 778


🏁 Script executed:

# Check if there are any tests that actually execute the shell commands
grep -n "spawn\|execSync\|exec" ./test/search.test.js

echo "---"
echo "Let's understand the quoting flow:"
echo "The test expects escaped dollars. Let's trace what buildSearchScript actually produces."
echo "---"

# Let's run a Node snippet to see what buildSearchScript produces
node <<'EOF'
const { buildSearchCommand } = require('./src/search/wslSearch');

const command = buildSearchCommand({
  distro: "OpenCockLab",
  root: "/home",
  query: "/home/test.txt",
  mode: "filename",
  maxResults: 10,
});

console.log("Full command array:");
command.forEach((arg, i) => {
  if (arg.length > 100) {
    console.log(`[${i}]: ${arg.substring(0, 100)}...`);
  } else {
    console.log(`[${i}]: ${arg}`);
  }
});

console.log("\n=== Command[6] (the bash script) ===");
console.log(command[6]);
console.log("\n=== Looking for $candidate or \\$candidate ===");
if (command[6].includes('$candidate')) {
  console.log("Found: $candidate (unescaped)");
}
if (command[6].includes('\\$candidate')) {
  console.log("Found: \\$candidate (escaped)");
}
EOF

Repository: future3OOO/wsl-search-tool

Length of output: 1090


🏁 Script executed:

# Check what's exported from wslSearchAdapter
grep -n "^module.exports\|^exports" ./src/search/wslSearchAdapter.js

echo "---"
echo "Check if there's a wslSearch.js file:"
find . -name "wslSearch.js" -type f

echo "---"
echo "Check the test imports:"
head -20 ./test/search.test.js

Repository: future3OOO/wsl-search-tool

Length of output: 682


🏁 Script executed:

# Check the root wslSearch.js file to understand exports
head -30 ./wslSearch.js

echo "---"
echo "Now let's run the actual test to see if it passes or fails"
cd ./test && npm test -- search.test.js 2>&1 | head -100

Repository: future3OOO/wsl-search-tool

Length of output: 284


🏁 Script executed:

# Run the test from the root
npm test 2>&1 | grep -A 50 "search.test.js\|buildSearchCommand"

Repository: future3OOO/wsl-search-tool

Length of output: 4563


🏁 Script executed:

# Let's manually trace through what buildSearchScript produces with the exact-path query
node <<'EOF'
const fs = require('fs');
const path = require('path');

// Read and eval the adapter to get the functions
const adapterCode = fs.readFileSync('./src/search/wslSearchAdapter.js', 'utf8');

// Create a context with necessary functions
const module = { exports: {} };
const require_local = (name) => {
  if (name === 'node:child_process') return {};
  return {};
};

// Execute only the relevant parts
eval(adapterCode.replace('require("node:child_process")', '{}'));

const functions = module.exports;

// Test the exact-path scenario
const result = functions.buildSearchCommand({
  distro: "OpenCockLab",
  root: "/home",
  query: "/home/test.txt",
  mode: "filename",
  maxResults: 10,
});

console.log("=== buildSearchCommand result ===");
console.log("Command[6] (the bash -lc argument):");
const bashArg = result[6];
console.log(bashArg.substring(0, 200) + "...");

console.log("\n=== Checking for variable references ===");
if (bashArg.includes('$candidate')) {
  console.log("✓ Found unescaped: $candidate");
} else if (bashArg.includes('\\$candidate')) {
  console.log("✗ Found escaped: \\$candidate");
} else {
  console.log("? Neither found");
}

if (bashArg.includes('$root_path')) {
  console.log("✓ Found unescaped: $root_path");
} else if (bashArg.includes('\\$root_path')) {
  console.log("✗ Found escaped: \\$root_path");
}
EOF

Repository: future3OOO/wsl-search-tool

Length of output: 446


🏁 Script executed:

# Let's check the complete bash script to understand the variable expansion issue
node <<'EOF'
const fs = require('fs');

const adapterCode = fs.readFileSync('./src/search/wslSearchAdapter.js', 'utf8');

const module = { exports: {} };
eval(adapterCode.replace('require("node:child_process")', '{}'));

const functions = module.exports;

// Test the exact-path scenario
const result = functions.buildSearchCommand({
  distro: "OpenCockLab",
  root: "/home",
  query: "/home/test.txt",
  mode: "filename",
  maxResults: 10,
});

const bashArg = result[6];
console.log("=== Full bash -lc argument ===");
console.log(bashArg);

console.log("\n=== Key observation ===");
console.log("In bash, \\$root_path means literal $root_path (backslash escapes the dollar)");
console.log("So when bash interprets the command, [ \"\\$root_path\" = \"/\" ] compares");
console.log("the literal string '$root_path' instead of expanding the variable.");
EOF

Repository: future3OOO/wsl-search-tool

Length of output: 1430


Remove the post-quoting $ escaping from the WSL script wrapper.

searchCommand is already protected by shellQuote(...). Escaping every $ afterwards changes what the inner bash -lc sees: Line 153's variable references like $root_path and $candidate stop expanding (bash interprets \$ as a literal dollar sign within double quotes), and literal queries or paths containing $ are matched as \$... instead of the original text. This breaks the exact-path fast path and any filename/content search for dollar-containing names.

Suggested fix
-function escapeWslCommandArgument(value) {
-  return String(value).replace(/\$/g, "\\$");
-}
-
 ...
-    return escapeWslCommandArgument(`timeout ${WSL_SEARCH_TIMEOUT_SECONDS}s bash -lc ${shellQuote(searchCommand)}`);
+    return `timeout ${WSL_SEARCH_TIMEOUT_SECONDS}s bash -lc ${shellQuote(searchCommand)}`;
 ...
-    return escapeWslCommandArgument(`timeout ${WSL_SEARCH_TIMEOUT_SECONDS}s bash -lc ${shellQuote(searchCommand)}`);
+    return `timeout ${WSL_SEARCH_TIMEOUT_SECONDS}s bash -lc ${shellQuote(searchCommand)}`;
 ...
-  return escapeWslCommandArgument(`timeout ${WSL_SEARCH_TIMEOUT_SECONDS}s bash -lc ${shellQuote(searchCommand)}`);
+  return `timeout ${WSL_SEARCH_TIMEOUT_SECONDS}s bash -lc ${shellQuote(searchCommand)}`;

Also applies to: Lines 139–154, 188–198

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/search/wslSearchAdapter.js` around lines 18 - 20, The wrapper currently
double-escapes dollar signs in escapeWslCommandArgument which alters what the
inner bash -lc sees and prevents expansion of variables like $root_path and
$candidate; remove the post-quoting replacement of `$` (i.e., stop turning $
into \$) so that searchCommand—already protected by shellQuote(...)—is passed
through intact to the bash -lc wrapper; update the escapeWslCommandArgument
function (and any similar escaping in the WSL script wrapper) to no longer
escape `$`, ensuring variable expansion and literal dollar-containing
filenames/queries work correctly.

Comment on lines +272 to +304
test("runSearch uses filename filesystem search for path-like profile filename searches", { skip: !HAS_USERPROFILE }, async () => {
const commandCalls = [];
const filenameCalls = [];
const profileRoot = process.env.USERPROFILE.replace(/\//g, "\\");
const adapter = createWindowsSearchAdapter({
runCommand: async (command) => {
commandCalls.push(command);
return "indexed search should not run";
},
runFilenameSearch: async (search) => {
filenameCalls.push(search);
return `${profileRoot}\\.codex\\plans\\tdd-seam-and-deep-modules-prd-v2.md\0`;
},
});

assert.deepEqual(
await adapter.runSearch({
query: ".codex/plans/tdd-seam-and-deep-modules-prd-v2.md",
mode: "filename",
root: profileRoot,
maxResults: "10",
}),
[
{
source: "windows",
target: driveTargetForTestPath(profileRoot),
path: `${profileRoot}\\.codex\\plans\\tdd-seam-and-deep-modules-prd-v2.md`,
},
]
);
assert.deepEqual(commandCalls, []);
assert.deepEqual(filenameCalls[0].roots, [profileRoot]);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Guard this test on IS_WINDOWS too.

This case currently only checks HAS_USERPROFILE, but runSearch() still validates root as a Windows absolute path. If a non-Windows environment happens to set USERPROFILE, the test will fail before it reaches the routing behavior you're trying to assert.

🧪 Suggested fix
-test("runSearch uses filename filesystem search for path-like profile filename searches", { skip: !HAS_USERPROFILE }, async () => {
+test(
+  "runSearch uses filename filesystem search for path-like profile filename searches",
+  { skip: !(IS_WINDOWS && HAS_USERPROFILE) },
+  async () => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/windowsSearch.test.js` around lines 272 - 304, The test "runSearch uses
filename filesystem search for path-like profile filename searches" is only
guarded by HAS_USERPROFILE but should also require IS_WINDOWS because
adapter.runSearch validates Windows absolute paths; update the test's skip
condition to skip when not (HAS_USERPROFILE && IS_WINDOWS) (or equivalent) so it
only runs on Windows environments; locate the test by its title and the symbols
HAS_USERPROFILE, IS_WINDOWS, and createWindowsSearchAdapter/adapter.runSearch to
modify the skip flag accordingly.

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.

1 participant