Shxiao 48bbea6df3
fix(workspace-changes): record symlink targets without the verbatim prefix (#5250)
* fix(workspace-changes): record symlink targets without the verbatim prefix

os.readlink on Windows reports absolute targets in extended-length
form (\?\C:\... or \?\UNC\server\share). The scanner stored that raw
spelling, so workspace-change events showed \?\-prefixed targets that
do not match ordinary Windows paths. Strip the prefix when recording;
POSIX readlink output is unchanged. Skills projection/review readlink
sites are untouched — they have no user-facing contract pinned on the
spelling.

* fix(workspace-changes): gate symlink target normalization to Windows

Review follow-up on #5250:

- Gate _normalize_symlink_target on os.name == "nt". readlink(2) on
  POSIX returns the literal string the link was created with, and
  backslash is a valid filename byte on Linux, so a target that starts
  with the extended-length prefix there must be recorded verbatim. The
  docstring's POSIX claim is now provably true.
- Commit the unit checks the PR body previously described as ad-hoc:
  drive and UNC prefix stripping, relative and plain POSIX targets,
  mid-string prefix left verbatim, and an off-Windows identity case, so
  the new branch has real coverage on every platform instead of relying
  on a Windows host with symlink privilege.

* test(workspace-changes): force Windows platform in prefix-strip unit tests

The os.name gate added in the previous commit makes
_normalize_symlink_target a verbatim identity off-Windows, so the two
prefix-strip assertions failed on the ubuntu-only unit CI. Force
os.name to "nt" via monkeypatch in both, mirroring the off-Windows
identity test, so every case pins exactly one platform's contract and
the suite is green on every host.

* fix(workspace-changes): strip only extended drive-letter prefixes

Review follow-up on #5250: the catch-all branch also stripped the
extended-length prefix from volume-GUID targets (\?\Volume{...}\...),
leaving a relative-looking path that loses the target's namespace.
Restrict the branch to extended drive-letter paths (letter, colon,
separator) and keep every other \?\ namespace form verbatim; add the
volume-GUID regression plus degenerate-prefix cases.
2026-09-08 14:51:57 +08:00
..