diff --git a/.changeset/quick-rams-greet.md b/.changeset/quick-rams-greet.md new file mode 100644 index 000000000..5bad0882c --- /dev/null +++ b/.changeset/quick-rams-greet.md @@ -0,0 +1,5 @@ +--- +type: Fixed +pr: 3460 +--- +Windows/Claude Code: /gsd-update and re-running the installer now migrate stale `.sh` managed hook commands (gsd-validate-commit, gsd-graphify-update, gsd-session-state, gsd-phase-boundary) in settings.json/settings.local.json to the current bash-runner-omission format — removing the redundant nested bash that the pre-#580/#3393 shape spawns on every hook fire. Custom user hooks are never touched. diff --git a/bin/install.js b/bin/install.js index bd5e98a95..3008f1ed2 100755 --- a/bin/install.js +++ b/bin/install.js @@ -1106,6 +1106,15 @@ function rewriteLegacyManagedNodeHookCommands(settings, absoluteRunner, opts) { return hooksSurface.rewriteLegacyManagedNodeHookCommands(settings, absoluteRunner, opts); } +// #3329: rewrite already-registered managed `.sh` hook commands to the shape +// the current installer would generate (the #580/#3393 bash-runner-omission +// migration the register-only-if-absent path never applied to existing +// entries). Invoked inside applySettingsJsonHooks in the compiled surface +// module; re-bound here for tests/consumers, mirroring the #2979 rewriter. +function reconcileManagedShellHookCommands(settings, expected, opts) { + return hooksSurface.reconcileManagedShellHookCommands(settings, expected, opts); +} + /** * Build the GSD-managed Codex SessionStart hook block for config.toml. * @@ -13784,6 +13793,7 @@ module.exports = { referencesHook, applySettingsJsonHooks, rewriteLegacyManagedNodeHookCommands, + reconcileManagedShellHookCommands, buildCodexHookBlock, rewriteLegacyCodexHookBlock, buildCodexHookWindowsShimIR, diff --git a/src/runtime-hooks-surface.cts b/src/runtime-hooks-surface.cts index 3f1d9f7b5..f398893d8 100644 --- a/src/runtime-hooks-surface.cts +++ b/src/runtime-hooks-surface.cts @@ -568,6 +568,95 @@ function rewriteLegacyManagedNodeHookCommands(settings: Settings, absoluteRunner return changed; } +// --------------------------------------------------------------------------- +// Shared: reconcileManagedShellHookCommands (#3329) +// --------------------------------------------------------------------------- + +/** + * Rewrite already-registered managed `.sh` hook `command` strings to the shape + * the current installer would generate (#3329). + * + * applySettingsJsonHooks registers the four `.sh` managed hooks only-if-absent, + * so an entry registered by an older installer keeps its old command forever — + * `/gsd-update` (which re-invokes the installer) never re-derived it. On + * Claude/win32 that left the pre-#580/#3393 bash-runner-prefixed commands + * (`bash "