diff --git a/commands/gsd/set-profile.md b/commands/gsd/set-profile.md index 70a01a093..66f560105 100644 --- a/commands/gsd/set-profile.md +++ b/commands/gsd/set-profile.md @@ -9,4 +9,4 @@ allowed-tools: Show the following output to the user verbatim, with no extra commentary: -!`gsd-sdk query config-set-model-profile $ARGUMENTS --raw` +!`if ! command -v gsd-sdk >/dev/null 2>&1; then printf '⚠ gsd-sdk not found in PATH — /gsd:set-profile requires it.\n\nInstall the GSD SDK:\n npm install -g @gsd-build/sdk\n\nOr update GSD to get the latest packages:\n /gsd-update\n'; exit 1; fi; gsd-sdk query config-set-model-profile $ARGUMENTS --raw` diff --git a/tests/bug-2439-set-profile-gsd-sdk-preflight.test.cjs b/tests/bug-2439-set-profile-gsd-sdk-preflight.test.cjs new file mode 100644 index 000000000..9df63d018 --- /dev/null +++ b/tests/bug-2439-set-profile-gsd-sdk-preflight.test.cjs @@ -0,0 +1,54 @@ +/** + * Regression test for bug #2439 + * + * /gsd:set-profile crashed with `command not found: gsd-sdk` when the + * gsd-sdk binary was not installed or not in PATH. The command body + * invoked `gsd-sdk query config-set-model-profile` directly with no + * pre-flight check, so missing gsd-sdk produced an opaque shell error. + * + * Fix mirrors bug #2334: guard the invocation with `command -v gsd-sdk` + * and emit an install hint when absent. + */ + +'use strict'; + +const { test, describe } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('fs'); +const path = require('path'); + +const COMMAND_PATH = path.join(__dirname, '..', 'commands', 'gsd', 'set-profile.md'); + +describe('bug #2439: /gsd:set-profile gsd-sdk pre-flight check', () => { + const content = fs.readFileSync(COMMAND_PATH, 'utf-8'); + + test('command file exists', () => { + assert.ok(fs.existsSync(COMMAND_PATH), 'commands/gsd/set-profile.md should exist'); + }); + + test('guards gsd-sdk invocation with command -v check', () => { + const sdkCall = content.indexOf('gsd-sdk query config-set-model-profile'); + assert.ok(sdkCall !== -1, 'gsd-sdk query config-set-model-profile must be present'); + + const preamble = content.slice(0, sdkCall); + assert.ok( + preamble.includes('command -v gsd-sdk') || preamble.includes('which gsd-sdk'), + 'set-profile must check for gsd-sdk in PATH before invoking it. ' + + 'Without this guard the command crashes with exit 127 when gsd-sdk ' + + 'is not installed (root cause of #2439).' + ); + }); + + test('pre-flight error message references install/update path', () => { + const sdkCall = content.indexOf('gsd-sdk query config-set-model-profile'); + const preamble = content.slice(0, sdkCall); + const hasInstallHint = + preamble.includes('@gsd-build/sdk') || + preamble.includes('gsd-update') || + preamble.includes('/gsd-update'); + assert.ok( + hasInstallHint, + 'Pre-flight error must point users at `npm install -g @gsd-build/sdk` or `/gsd-update`.' + ); + }); +});