Skip to content

fix(tools): keep tool labels workspace-relative on Windows - #207

Open
dajiaohuang wants to merge 2 commits into
vastsa:mainfrom
dajiaohuang:fix/hostcore-relative-display-windows
Open

fix(tools): keep tool labels workspace-relative on Windows#207
dajiaohuang wants to merge 2 commits into
vastsa:mainfrom
dajiaohuang:fix/hostcore-relative-display-windows

Conversation

@dajiaohuang

Copy link
Copy Markdown

Problem

On Windows, workspace-relative tool labels silently render as absolute paths. Read window headers come back as [C:\Users\...\project\big.txt#a1b2] instead of [big.txt#a1b2], and Write reports an absolute path instead of the workspace-relative one.

Root cause

Two different canonical spellings of the same directory never compare equal.

  • The resolver (workspace::resolve_with_existing_ancestor) spells every path it returns with the crate's simple_canonicalize, which strips the Windows extended-length prefix — \?\C:\... becomes C:\.... That stripping is deliberate and documented: shell APIs such as ShellExecuteW reject \?\.
  • tools::relative_display canonicalized the root with std Path::canonicalize, which keeps the prefix.

Path::strip_prefix compares components, and VerbatimDisk('C') is not Disk('C'), so path.strip_prefix(&canonical_root) failed on Windows for every contained path. The .or_else(|_| path.strip_prefix(root)) fallback only helps when the caller passes a root whose raw spelling matches the resolved one, which is not the case for roots that reach the host through a short (8.3) or differently-cased spelling. The result: unwrap_or(path) — an absolute path.

This is invisible to CI because .github/workflows/ci.yml runs cargo test -p host-core --locked on ubuntu-latest only, where Path::canonicalize and simple_canonicalize agree.

Fix

Canonicalize the root with simple_canonicalize so both sides of the comparison use one spelling, and expose that helper as pub(crate). Two lines of behavior change plus the visibility.

Validation

cargo test -p host-core --locked --bin pi-desktop-host-core --no-fail-fast on Windows (Node/Rust toolchain per rust-toolchain stable, cargo 1.98.1):

passed failed
before 339 17
after 342 14

The three that flip are the production-behavior assertions this change targets, and they already encoded the intended behavior — they were simply never exercised on Windows:

  • tools::tests::workspace_write_reports_workspace_root (expects path == "a.txt")
  • tools::tests::read_paginates_instead_of_refusing_large_files (expects header [big.txt#)
  • tools::tests::read_does_not_mark_a_filled_window_truncated (expects header [notes.txt#)

cargo check -p host-core --locked is clean (only pre-existing never used warnings). No E2E suites were run, per the local E2E execution policy.

Spec sync

R3: docs/spec/06-delivery/04-e2e-test-plan.md scenario E2E-019e already required "Search results use workspace-relative paths inside the project and absolute paths only for approved external locations" — this change makes host-core conform to it on Windows. Its Status note now records the constraint, in both locales.

Scope note

The remaining 14 Windows failures in this suite are separate defects with different root causes and are not addressed here — most compare against std Path::canonicalize() in the test expectation itself (workspace::tests::*, rpc::tests::project_create_*, sessions::tests::create_session_*, mcp_servers::tests::*, user_skills::tests::*), and tools::tests::bash_stderr_keeps_the_tail assumes a POSIX shell although the resolved shell on Windows is PowerShell. I am reporting those separately rather than widening this change.

🤖 Generated with Claude Code

dajiaohuang and others added 2 commits September 10, 2026 19:47
`relative_display` canonicalized the workspace root with std
`Path::canonicalize`, which keeps the Windows `\?\` extended-length
prefix, while the resolver spells every path it returns with
`simple_canonicalize` (prefix stripped). The two spellings can never
match, so `strip_prefix` failed and each Read window header and Write
result fell back to an absolute path on Windows.

Canonicalize the root with the resolver's own helper so both sides
share one spelling, and expose that helper crate-internally.

Verified on Windows: `cargo test -p host-core` moves from
339 passed / 17 failed to 342 passed / 14 failed, repairing
`tools::tests::workspace_write_reports_workspace_root`,
`tools::tests::read_paginates_instead_of_refusing_large_files`, and
`tools::tests::read_does_not_mark_a_filled_window_truncated`. Those
assertions already encoded the intended behavior on Linux, where std
`canonicalize` and `simple_canonicalize` agree.

Co-Authored-By: Claude Code <noreply@anthropic.com>
R3 sync for the `relative_display` fix. The scenario already required
workspace-relative results inside the project; note the Windows
constraint that makes its unit coverage real, in both locales.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 10, 2026

Copy link
Copy Markdown

@dajiaohuang is attempting to deploy a commit to the vastsa's projects Team on Vercel.

A member of the Team first needs to authorize it.

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