Skip to content

fix(skills): normalize backslashes in compacted skill paths on Windows#52200

Open
chienchandler wants to merge 2 commits intoopenclaw:mainfrom
chienchandler:fix/windows-skill-path-separators
Open

fix(skills): normalize backslashes in compacted skill paths on Windows#52200
chienchandler wants to merge 2 commits intoopenclaw:mainfrom
chienchandler:fix/windows-skill-path-separators

Conversation

@chienchandler
Copy link
Copy Markdown

What

On Windows, compactSkillPaths() produces hybrid paths like ~/AppData\Roaming\npm\...\SKILL.md — the home prefix gets replaced with ~/ but remaining segments keep backslashes. Models can't resolve these and return ENOENT.

Fixes #52022

How

Added backslash-to-forward-slash normalization after the ~/ prefix replacement, gated behind path.sep === "\\" so it only runs on Windows. Same pattern as refresh.ts:81.

Testing

  • 3/3 compactSkillPaths tests pass (including new test for backslash normalization)
  • No TypeScript errors in changed files
  • Tested on Windows 11

AI-assisted (Claude Code), reviewed and tested by author.

On Windows, compactSkillPaths() replaces the home directory prefix with
~/ but leaves remaining path segments with backslashes, producing hybrid
paths like ~/AppData\Roaming\...\SKILL.md. Models fail to resolve these
malformed paths and return ENOENT errors.

Normalize all backslashes to forward slashes after path compaction on
Windows so models receive consistent POSIX-style paths.

Fixes openclaw#52022
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Mar 22, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 22, 2026

Greptile Summary

This PR fixes a Windows-only bug where compactSkillPaths() produced hybrid paths like ~/AppData\Roaming\npm\...\SKILL.md — the home prefix was replaced with ~/ but remaining path segments kept their backslashes, causing models to fail with ENOENT when trying to resolve them.

The fix is a one-liner replace(/\\/g, "/") gated on path.sep === "\\", applied after the home-prefix substitution. The approach is consistent with the existing pattern in refresh.ts:81 and correctly handles both home-directory paths and absolute paths outside the home directory.

  • workspace.ts: Clean, targeted normalization in compactSkillPaths() — no issues.
  • skills.compact-skill-paths.test.ts: New test is correct in spirit but uses a conditional if (locationMatch) guard that could silently skip the backslash assertion if the prompt output format ever changes (see inline comment).

Confidence Score: 5/5

  • Safe to merge — minimal, well-scoped fix for a real Windows bug with no risk to non-Windows environments.
  • The fix is a one-liner gated strictly behind path.sep === "\\", so it has zero impact on macOS/Linux. The logic is straightforward and correct. The only non-blocking P2 is the conditional assertion in the new test, which doesn't affect production behavior. The fix follows the established codebase pattern.
  • No files require special attention.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/skills.compact-skill-paths.test.ts
Line: 63-66

Comment:
**Conditional assertion may silently pass without testing anything**

The `if (locationMatch)` guard means the `expect` only runs when the prompt actually contains a `<location>` tag. If the prompt format changes or `buildWorkspaceSkillsPrompt` returns something unexpected, the test still reports green — providing a false sense of coverage.

Consider asserting unconditionally that a `<location>` tag exists first, then checking its content:

```suggestion
      // The prompt should contain a location tag
      const locationMatch = prompt.match(/<location>([^<]+)<\/location>/);
      expect(locationMatch).not.toBeNull();
      expect(locationMatch![1]).not.toContain("\\");
```

This way the test fails loudly if the output format ever changes, rather than silently skipping the backslash assertion.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(skills): normalize backslashes in co..." | Re-trigger Greptile

Comment thread src/agents/skills.compact-skill-paths.test.ts Outdated
Address greptile review: replace silent conditional guard with explicit
assertion so the test fails loudly if prompt format changes.
@chienchandler
Copy link
Copy Markdown
Author

CI note: Both failing checks (node test shard 2/2 and windows test shard 6/6) fail on the same unrelated test — src/plugin-sdk/subpaths.test.ts with MODULE_NOT_FOUND for dist/plugin-sdk/core.js. This is a build artifact issue in the plugin-sdk, not related to this PR's skill path normalization changes.

@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 28, 2026

Codex review: needs changes before merge.

Summary
The PR normalizes Windows backslashes in compacted prompt-facing skill paths and adds a regression assertion for rendered skill locations.

Reproducibility: yes. Source inspection gives a high-confidence path: on Windows, compactHomePath() prepends ~/ while preserving any backslash-containing suffix, and the skills prompt renderers emit that value unchanged.

Next step before merge
A narrow repair can adapt the stale source PR to current main and add the missing changelog entry without a product decision.

Security
Cleared: The diff only changes prompt-facing skill path string normalization and a focused unit test; it does not touch dependencies, CI, secrets, permissions, install hooks, or code execution surfaces.

Review findings

  • [P3] Add the required changelog entry — src/agents/skills/workspace.ts:52-60
Review details

Best possible solution:

Normalize prompt-facing Windows skill locations at the current compaction helper boundary, add focused regression coverage, add a single-line CHANGELOG.md fix entry, then merge this PR or a narrow credited replacement.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection gives a high-confidence path: on Windows, compactHomePath() prepends ~/ while preserving any backslash-containing suffix, and the skills prompt renderers emit that value unchanged.

Is this the best way to solve the issue?

No, not as-is. The normalization direction is the narrow maintainable fix, but it should be adapted to current main's compactHomePath() split and include the required changelog entry.

Full review comments:

  • [P3] Add the required changelog entry — src/agents/skills/workspace.ts:52-60
    This is a user-facing Windows fix, but the PR only changes code and tests. Repo policy requires a single-line CHANGELOG.md entry for user-facing fixes before merge.
    Confidence: 0.93

Overall correctness: patch is correct
Overall confidence: 0.86

Acceptance criteria:

  • pnpm test src/agents/skills.compact-skill-paths.test.ts
  • pnpm exec oxfmt --check --threads=1 src/agents/skills/workspace.ts src/agents/skills.compact-skill-paths.test.ts CHANGELOG.md
  • pnpm check:changed in Testbox before handoff

What I checked:

  • Current compaction still preserves Windows separators: compactHomePath() prepends ~/ to the home-relative suffix and returns the remaining filePath unchanged, so a Windows suffix containing backslashes would still be prompt-facing on current main. (src/agents/skills/workspace.ts:77, 06056926a099)
  • Compacted paths feed the final skills prompt: resolveWorkspaceSkillPromptState() maps visible skills through compactSkillPaths() before budget checks and final rendering. (src/agents/skills/workspace.ts:1002, 06056926a099)
  • Both prompt renderers emit skill.filePath directly: The full renderer writes <location>${escapeXml(skill.filePath)}</location>, and the compact renderer does the same, making the compaction result the model-visible path. (src/agents/skills/skill-contract.ts:59, 06056926a099)
  • Current tests do not cover Windows separator normalization: The current compact-path tests cover home-prefix replacement and outside-home preservation, but there is no assertion for backslash normalization on current main. (src/agents/skills.compact-skill-paths.test.ts:37, 06056926a099)
  • Docs make skill locations a prompt-facing contract: The system prompt docs state that OpenClaw injects each skill file path and instructs the model to read the listed SKILL.md location. Public docs: docs/concepts/system-prompt.md. (docs/concepts/system-prompt.md:214, 06056926a099)
  • Changelog entry is still absent: The active Unreleased fixes section exists, but searches for the related PR, issue, Windows skill-path wording, and backslash/compact-skill terms did not find a matching entry. (CHANGELOG.md:48, 06056926a099)

Likely related people:

  • mac26ai: Introduced the original home-prefix skill path compaction and the compact-path test file in feat(skills): compact skill paths with ~ to reduce prompt tokens. (role: introduced behavior; confidence: high; commits: 4f2c57eb4eb0; files: src/agents/skills/workspace.ts, src/agents/skills.compact-skill-paths.test.ts)
  • Peter Steinberger: Made repeated recent changes around compact skill prompt fixtures, compaction API drift, and skills tests, including shared compact skill prompt fixture work. (role: recent maintainer; confidence: high; commits: 59032f63b1e0, 0a207b9860a4; files: src/agents/skills.compact-skill-paths.test.ts, src/agents/skills/workspace.ts)
  • Vincent Koc: Current blame for compactSkillPaths()/compactHomePath() points to the recent helper split, and earlier work touched overridden-home handling for personal skills. (role: recent maintainer; confidence: high; commits: 03d04c243b86, 8ae6d42faabf; files: src/agents/skills/workspace.ts, src/agents/skills.compact-skill-paths.test.ts)
  • Shakker: Localized the workspace skill prompt contract into the current skill-contract.ts boundary that emits skill.filePath into <location>. (role: adjacent owner; confidence: medium; commits: 9a6dda1b6660; files: src/agents/skills/workspace.ts, src/agents/skills/skill-contract.ts)

Remaining risk / open question:

  • The source branch targets an older compactSkillPaths() shape; current main split the path handling into compactHomePath(), so the final patch needs a careful rebase or replacement PR.
  • No Windows runtime or test execution was performed in this read-only sweep; the reproduction confidence comes from source inspection and the reporter/author's Windows context.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 06056926a099.

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

Labels

agents Agent runtime and tooling size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Windows skill path compaction mixes separators and causes wrong read paths

1 participant