Skip to content

fix: sanitize colons in skill/agent names for Windows path compatibility#398

Merged
tmchow merged 5 commits intomainfrom
feat/fix-resolve-pr-feedback
Mar 26, 2026
Merged

fix: sanitize colons in skill/agent names for Windows path compatibility#398
tmchow merged 5 commits intomainfrom
feat/fix-resolve-pr-feedback

Conversation

@tmchow
Copy link
Collaborator

@tmchow tmchow commented Mar 26, 2026

Summary

Colon-namespaced skill names like ce:brainstorm were used directly as directory names across all target writers, sync paths, and converter manifests. Colons are illegal in Windows filenames, so bun convert and bun install failed with ENOTDIR on Windows.

Fixes this by adding sanitizePathName() that replaces colons with hyphens, applied at three layers:

  1. Target writers (all 10) and sync paths (3 files) — wrap names with sanitizePathName() when constructing output paths
  2. Converter dedupe sets (Copilot, Windsurf) — reserve sanitized names so generated skills detect collisions that would occur on disk
  3. OpenClaw manifest — emit sanitized paths matching what the writer creates, so skills are discoverable at runtime

Also fixes a pre-existing bug where syncOpenCodeCommands bypassed resolveCommandPath, producing colon paths for namespaced commands.

Key decisions

  • Hyphens over nested directories: Initially used / as the replacement (turning ce:brainstorm into ce/brainstorm/), but switched to - because the source directories already use hyphens, validatePathSafe rejects /, and nesting adds unnecessary structure.
  • Sanitize at the boundary: Names keep colons in data structures and frontmatter; only filesystem paths use hyphens. This preserves the namespace semantics while staying cross-platform safe.
  • resolveCommandPath left as-is: Commands use a different pattern (colons to nested dirs) which is intentional — commands and skills have different resolution semantics across target platforms.

Test plan

  • 405 tests pass (up from 397), including new collision detection tests that load the real compound-engineering plugin
  • Verified bun convert --to opencode produces zero colon paths in output
  • Regression tests for Copilot/Windsurf dedupe collision and OpenClaw manifest consistency

Fixes #366 #307


Compound Engineering v2.54.1
🤖 Generated with Claude Opus 4.6 (1M context, extended thinking) via Claude Code

tmchow added 4 commits March 26, 2026 12:55
Colons in namespaced skill names (e.g. ce:brainstorm) are illegal in
Windows filenames, causing ENOTDIR errors during convert/install.

Add sanitizePathName() that replaces colons with hyphens, applied across
all 10 target writers and 3 sync files. Output paths now match source
directory names (e.g. skills/ce-brainstorm/).

Closes #366
The OpenCode command sync path used raw command names directly in
path.join, bypassing resolveCommandPath — so namespaced commands like
workflows:plan produced colon paths instead of nested directories.

Also adds sanitizePathName unit tests and collision detection tests
that load the real compound-engineering plugin and verify no two
skill or agent names collide after sanitization.
Three issues where converters didn't account for filesystem sanitization:

1. OpenClaw manifest advertised colon paths (skills/cmd-ce:plan) while
   the writer created hyphenated dirs (skills/cmd-ce-plan), making
   namespaced skills undiscoverable.

2. Copilot reserved raw skill names (ce:plan) in the dedupe set, so a
   generated skill normalizing to ce-plan didn't detect the collision
   and both wrote to skills/ce-plan/, with pass-through overwriting.

3. Windsurf same pattern — agent skill dedupe used unsanitized names.

Fix: use sanitizePathName when building dedupe sets and manifest paths.
Add regression tests for all three cases.
…ance

Document the colon-in-path sanitization fix as a solution under
integrations/ (not developer-experience/), and add guidance to
AGENTS.md explaining the distinction: developer-experience/ is for
repo contributor friction, integrations/ is for end-user platform issues.
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c418f4d016

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Warn and skip when two names collapse to the same path after
sanitization (e.g. ce:plan and ce-plan both becoming ce-plan).

Defense-in-depth alongside the converter-level dedupe and test-level
collision detection already in place.
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 109cdfd856

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@tmchow tmchow merged commit b25480a into main Mar 26, 2026
2 checks passed
@github-actions github-actions bot mentioned this pull request Mar 26, 2026
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.

fs.mkdir attempts to place a colon in a folder name

1 participant