fix(#997): ensure canonical ~/.claude/gsd-core path for plugin installs (#1207)

* fix(#997): ensure canonical ~/.claude/gsd-core path for plugin installs via SessionStart hook

Claude Code marketplace plugin installs unpack the package into the
version-pinned plugin cache and never run bin/install.js, so
~/.claude/gsd-core/ is never created. Agents, commands, and templates
markdown-@-include the canonical ~/.claude/gsd-core/... path (which
expands ~ but NOT ${CLAUDE_PLUGIN_ROOT}), so every include resolved to
nothing and agents (e.g. the executor) failed.

Add a SessionStart hook (hooks/gsd-ensure-canonical-path.js) that, on a
plugin install, symlinks the canonical path's immutable subdirs (bin,
contexts, references, templates, workflows) to the plugin's bundled
gsd-core/ tree. It changes zero @-references, is a no-op in classic
installs, preserves user-generated files (USER-PROFILE.md, STATE.md),
prunes stale links so it self-heals after `claude plugin update`, uses
Windows junctions, and rejects bundled/canonical paths that escape the
resolved plugin root (no traversal, no clobber).

Registered in HOOKS_TO_COPY (build-hooks), MANAGED_HOOKS, hooks.json
SessionStart (runs first, timeout 5), and BUNDLED_GSD_HOOK_FILES.
Behavioral regression tests folded into issue-766-plugin-manifest.test.cjs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(#997): backfill changeset PR number to #1207

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-14 09:37:41 -04:00
committed by GitHub
parent cd638d5a71
commit 9e5d4b266b
11 changed files with 708 additions and 10 deletions

View File

@@ -26,6 +26,13 @@ const STAGE_DIR = path.join(HOOKS_DIR, `.dist-staging-${process.pid}`);
const HOOKS_TO_COPY = [
'gsd-check-update-worker.js',
'gsd-check-update.js',
// SessionStart canonical-path bootstrap (#997). In a Claude Code marketplace
// plugin install, ~/.claude/gsd-core is never created, so every
// `@~/.claude/gsd-core/...` include in agents/commands/templates resolves to
// nothing. This hook symlinks the canonical path's immutable subdirs to the
// plugin's bundled gsd-core/ tree; no-op in classic installs. Must ship to
// dist so the installer copies it into the target hooks/ dir.
'gsd-ensure-canonical-path.js',
// Required by gsd-check-update-worker.js at runtime — must ship alongside it
// so require('./managed-hooks-registry.cjs') resolves in the installed hooks/ dir.
'managed-hooks-registry.cjs',