fix(#813): apply per-runtime skill path rewrites in applySurface (#817)

* fix(#813): apply per-runtime skill path rewrites in applySurface

applySurface() re-staged skill artifacts but, unlike installRuntimeArtifacts(),
never applied the per-runtime path rewrites. So /gsd:surface
(profile/enable/disable/reset) overwrote installed SKILL.md bodies with the
converter's default ~/.claude paths instead of the install target (pathPrefix),
silently regressing skill path references for every skillsKind runtime until
the next reinstall.

applySurface now mirrors installRuntimeArtifacts: for kind.kind === 'skills' it
derives pathPrefix the same way and applies applyRuntimeContentRewritesInPlace
on the staged dir before syncing.

- bin/install.js: export applyRuntimeContentRewritesInPlace
- runtime-artifact-layout.cts: carry resolved scope on Layout; export
  getInstallExports; type computePathPrefix/applyRuntimeContentRewritesInPlace
  on InstallExports
- surface.cts: lazily derive pathPrefix (only when a skills kind exists) and
  apply the rewrite via the shared getInstallExports accessor — single source of
  truth with install, only skills kinds rewritten (matches install)
- tests: regression test parameterized over cursor + codex asserting
  post-applySurface bodies carry the install pathPrefix, not ~/.claude
- CONTEXT.md: glossary updated for the applySurface rewrite parity + scope seam

Closes #813

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#813): add changeset fragment for PR #817

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(#813): normalize configDir prefix to forward slashes for Windows CI

The #813 regression assertion compared skill bodies against a raw
${configDir}/ prefix, but production derives pathPrefix via
path.resolve(configDir).replace(/\\/g, '/'). On Windows, mkdtempSync
returns backslash paths while the rewritten body uses forward slashes,
so the assertion would fail Windows-only (not covered by local gsd-test).
Normalize the expected prefix the same way production does.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-07 16:26:14 -04:00
committed by GitHub
parent ea0d8f09b1
commit 907cd01aa3
6 changed files with 119 additions and 4 deletions

View File

@@ -33,6 +33,8 @@ const _require: NodeRequire = require;
interface InstallExports {
readGsdCommandNames: () => string[];
computePathPrefix: (opts: { isGlobal: boolean; isOpencode: boolean; isWindowsHost: boolean; resolvedTarget: string; homeDir: string }) => string;
applyRuntimeContentRewritesInPlace: (stagedDir: string, runtime: string, pathPrefix: string) => void;
[converterName: string]: unknown;
}
@@ -84,6 +86,7 @@ interface ArtifactKind {
interface Layout {
runtime: string;
configDir: string;
scope?: 'local' | 'global';
kinds: ArtifactKind[];
}
@@ -371,7 +374,7 @@ function resolveRuntimeArtifactLayout(runtime: string, configDir: string, scope:
throw new TypeError(`Unknown runtime: '${runtime}' — add to runtime-artifact-layout.cjs table`);
}
return { runtime, configDir, kinds };
return { runtime, configDir, scope, kinds };
}
export = { resolveRuntimeArtifactLayout, findInstallSourceRoot };
export = { resolveRuntimeArtifactLayout, findInstallSourceRoot, getInstallExports };