From 40e325b91f05815d6d54e29dad1370d03960b804 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sun, 17 May 2026 00:44:53 -0400 Subject: [PATCH] fix(3663): pass runtime+cmdNames to Claude converter for Hermes/Qwen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit convertClaudeCommandToClaudeSkill(content, skillName, runtime, cmdNames) uses the runtime arg to gate Hermes/Qwen branding and version: frontmatter emission (#2808, #3583). Previously the layout module called it with only 2 args so the runtime-specific formatting was never applied. Changes: - skillsKind() gains a runtime param (5th arg after converterName). - stage() computes cmdNames = readGsdCommandNames() once per call (perf: avoids repeated fs.readdirSync in the converter) and wraps the real converter so all 4 args are forwarded. - readGsdCommandNames added to bin/install.js GSD_TEST_MODE exports block so the stage closure can call it without requiring the script separately. - All switch arms updated to pass the canonical runtime string. Converters that do not inspect runtime/cmdNames (Cursor, Codex, Copilot, etc.) accept and ignore the extra arguments — no behaviour change for those runtimes. Co-Authored-By: Claude Sonnet 4.6 --- bin/install.js | 1 + .../bin/lib/runtime-artifact-layout.cjs | 35 +++++++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/bin/install.js b/bin/install.js index 6f50db6eb..ea070b47b 100755 --- a/bin/install.js +++ b/bin/install.js @@ -11436,6 +11436,7 @@ if (process.env.GSD_TEST_MODE) { rewriteLegacyManagedNodeHookCommands, buildCodexHookBlock, rewriteLegacyCodexHookBlock, + readGsdCommandNames, }; } else { diff --git a/get-shit-done/bin/lib/runtime-artifact-layout.cjs b/get-shit-done/bin/lib/runtime-artifact-layout.cjs index 238f22716..f87eb4cdd 100644 --- a/get-shit-done/bin/lib/runtime-artifact-layout.cjs +++ b/get-shit-done/bin/lib/runtime-artifact-layout.cjs @@ -178,16 +178,23 @@ function agentsKind(destSubpath, prefix, configDir) { * @param {string} destSubpath * @param {string} prefix * @param {string} converterName name of converter function in bin/install.js exports + * @param {string} runtime canonical runtime ID (gates Hermes/Qwen branding in converter) * @param {string} configDir runtime config dir (for .gsd-source marker resolution) */ -function skillsKind(destSubpath, prefix, converterName, configDir) { +function skillsKind(destSubpath, prefix, converterName, runtime, configDir) { return { kind: 'skills', destSubpath, prefix, stage: (resolved) => { - const converter = getInstallExports()[converterName]; - return stageSkillsForRuntimeAsSkills(findInstallSourceRoot(configDir), resolved, converter, prefix); + const installExports = getInstallExports(); + const realConverter = installExports[converterName]; + // Compute cmdNames once per stage call for performance (#3583). + // Extra args are ignored by converters that don't need runtime/cmdNames. + const cmdNames = installExports.readGsdCommandNames(); + const wrappedConverter = (content, skillName) => + realConverter(content, skillName, runtime, cmdNames); + return stageSkillsForRuntimeAsSkills(findInstallSourceRoot(configDir), resolved, wrappedConverter, prefix); }, }; } @@ -224,12 +231,12 @@ function resolveRuntimeArtifactLayout(runtime, configDir, scope = 'global') { agentsKind('agents', 'gsd-', configDir), ]; } else { - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToClaudeSkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToClaudeSkill', 'claude', configDir)]; } break; case 'cursor': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCursorSkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCursorSkill', 'cursor', configDir)]; break; case 'gemini': @@ -237,39 +244,39 @@ function resolveRuntimeArtifactLayout(runtime, configDir, scope = 'global') { break; case 'codex': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCodexSkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCodexSkill', 'codex', configDir)]; break; case 'copilot': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCopilotSkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCopilotSkill', 'copilot', configDir)]; break; case 'antigravity': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToAntigravitySkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToAntigravitySkill', 'antigravity', configDir)]; break; case 'windsurf': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToWindsurfSkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToWindsurfSkill', 'windsurf', configDir)]; break; case 'augment': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToAugmentSkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToAugmentSkill', 'augment', configDir)]; break; case 'trae': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToTraeSkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToTraeSkill', 'trae', configDir)]; break; case 'qwen': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToClaudeSkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToClaudeSkill', 'qwen', configDir)]; break; case 'hermes': - kinds = [skillsKind('skills/gsd', '', 'convertClaudeCommandToClaudeSkill', configDir)]; + kinds = [skillsKind('skills/gsd', '', 'convertClaudeCommandToClaudeSkill', 'hermes', configDir)]; break; case 'codebuddy': - kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCodebuddySkill', configDir)]; + kinds = [skillsKind('skills', 'gsd-', 'convertClaudeCommandToCodebuddySkill', 'codebuddy', configDir)]; break; case 'cline':