Skip to content

fix(skills): use junction symlinks on Windows to avoid EPERM without Developer Mode (#77958)#77971

Merged
BradGroux merged 1 commit intoopenclaw:mainfrom
hclsys:fix/plugin-skills-symlink-junction-win32-77958
May 6, 2026
Merged

fix(skills): use junction symlinks on Windows to avoid EPERM without Developer Mode (#77958)#77971
BradGroux merged 1 commit intoopenclaw:mainfrom
hclsys:fix/plugin-skills-symlink-junction-win32-77958

Conversation

@hclsys
Copy link
Copy Markdown
Contributor

@hclsys hclsys commented May 5, 2026

Fixes #77958.

Summary

  • Use Windows junction directory links when publishing plugin-provided skills into the managed plugin-skills directory.
  • Preserve the existing non-Windows dir symlink behavior.
  • Treat Windows junction-like generated directories as managed plugin-skill entries during stale cleanup.
  • Add focused regression coverage and an Unreleased changelog entry.

Verification

  • pnpm install --frozen-lockfile
  • pnpm test src/agents/skills/plugin-skills.test.ts — 22 tests passed
  • pnpm exec oxfmt --check --threads=1 src/agents/skills/plugin-skills.ts src/agents/skills/plugin-skills.test.ts CHANGELOG.md
  • git diff --check
  • pnpm check:changed

Maintainer notes

This branch was narrowed during maintainer prep to the #77958 plugin-skills Windows fix only. The unrelated Ollama changes from the original branch were dropped.

Live Windows standard-user proof was not run from this macOS maintainer workspace; the issue is source-backed by the existing fs.symlinkSync(..., "dir") call and covered by focused regression tests. A proof: override label/comment records that maintainer decision.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 5, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 5, 2026

Codex review: needs maintainer review before merge.

Summary
The branch changes plugin-skill publishing to use Windows junctions for generated plugin skill directory links, adds cleanup/idempotence tests, and adds an Unreleased changelog entry.

Reproducibility: yes. from source and reporter logs, but not from a live run here. Current main hardcodes fs.symlinkSync(..., "dir") for plugin-skill directory publishing, and #77958 includes Windows standard-user EPERM output plus a successful junction experiment.

Real behavior proof
Override: Override: the PR has a proof: override label and maintainer comment explaining that live Windows standard-user proof is unavailable, with source-backed focused tests supplied instead.

Next step before merge
No repair lane: the branch already contains the focused code, test, and changelog changes, and the remaining action is normal maintainer merge/check handling.

Security
Cleared: No concrete security or supply-chain regression found; the diff only changes managed plugin-skill link type/cleanup plus tests and changelog, with existing plugin-root containment preserved.

Review details

Best possible solution:

Land the narrowed junction fix after normal maintainer merge gates, preserving plugin-root containment and managed plugin-skills cleanup behavior.

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

Yes from source and reporter logs, but not from a live run here. Current main hardcodes fs.symlinkSync(..., "dir") for plugin-skill directory publishing, and #77958 includes Windows standard-user EPERM output plus a successful junction experiment.

Is this the best way to solve the issue?

Yes. Switching generated plugin-skill directory links to junction on win32 is the narrowest maintainable fix and matches Node's supported symlink type contract while keeping the existing plugin-root checks.

What I checked:

  • Current-main failure path: Current main still publishes plugin skill directories with fs.symlinkSync(target, linkPath, "dir"), which matches the reported Windows standard-user EPERM path for directory symlinks without Developer Mode. (src/agents/skills/plugin-skills.ts:216, 1f6ce72b8aa4)
  • Documented plugin-skill contract: The skills docs say plugins can list skill directories in openclaw.plugin.json and that plugin skills load when the plugin is enabled, so failed publishing breaks an existing behavior contract. Public docs: docs/tools/skills.md. (docs/tools/skills.md:91, 1f6ce72b8aa4)
  • Affected bundled skill surface exists: The browser and memory-wiki plugins declare "skills": ["./skills"], and the reported browser-automation, obsidian-vault-maintainer, and wiki-maintainer skill files are present. (extensions/browser/openclaw.plugin.json:12, 1f6ce72b8aa4)
  • PR uses junction on Windows: The PR adds resolvePluginSkillLinkType() returning junction on win32 and uses it in the plugin-skill fs.symlinkSync call while preserving dir elsewhere. (src/agents/skills/plugin-skills.ts:221, 2a21a3792565)
  • Regression coverage added: The PR adds focused tests for Windows link-type selection and cleanup of stale generated junction-like entries. (src/agents/skills/plugin-skills.test.ts:410, 2a21a3792565)
  • Changelog coverage added: The PR adds an Unreleased changelog entry for the Windows plugin-skill junction fix and credits the contributor and reporter. (CHANGELOG.md:9, 2a21a3792565)

Likely related people:

  • zhangguiping-xydt: The current generated ~/.openclaw/plugin-skills publishing path and associated tests were introduced through the merged plugin manifest skills fix. (role: feature-history contributor; confidence: high; commits: 1df2ac442a75; files: src/agents/skills/plugin-skills.ts, src/agents/skills/plugin-skills.test.ts, src/agents/skills/workspace.ts)
  • steipete: Recent history shows maintainer work on plugin-skill path containment and filesystem-safety refactors touching the same skill publishing code. (role: adjacent maintainer; confidence: medium; commits: 23f434f98d0f, 538605ff44d2; files: src/agents/skills/plugin-skills.ts, src/agents/skills/plugin-skills.test.ts, src/agents/skills/workspace.ts)

Remaining risk / open question:

  • No after-fix live run on a Windows standard-user account with Developer Mode off was provided; the PR has an explicit maintainer proof: override accepting source and test evidence for this case.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 981e32d05d3b.

@BradGroux BradGroux force-pushed the fix/plugin-skills-symlink-junction-win32-77958 branch from 20853ca to 2a21a37 Compare May 6, 2026 04:53
@BradGroux BradGroux added the proof: override Maintainer override for the external PR real behavior proof gate. label May 6, 2026
@BradGroux
Copy link
Copy Markdown
Member

Maintainer prep update:

Verification run locally:

  • pnpm install --frozen-lockfile
  • pnpm test src/agents/skills/plugin-skills.test.ts — 22 tests passed
  • pnpm exec oxfmt --check --threads=1 src/agents/skills/plugin-skills.ts src/agents/skills/plugin-skills.test.ts CHANGELOG.md — passed
  • git diff --check — passed
  • pnpm check:changed — passed

@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 6, 2026
@BradGroux BradGroux merged commit 5f783d7 into openclaw:main May 6, 2026
102 of 107 checks passed
@BradGroux
Copy link
Copy Markdown
Member

Merged with squash after maintainer prep and green CI.\n\nPrepared head: 2a21a37925656d4efd69b7b8c945083ed7ad8863\nMerge commit: 5f783d7ddd85cae5776f1ec14c3b48325ea9d163\nLinked issue #77958 is now closed.

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

Labels

agents Agent runtime and tooling proof: override Maintainer override for the external PR real behavior proof gate. size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plugin-skill registration uses fs.symlink (EPERM on Windows without admin/Developer Mode); junction would work without elevation

2 participants