feat(#1046): phase 5c — drive commandStyle from the runtime descriptor (runtime-slash codex-check → lookup) (#1048)

formatGsdSlash now reads commandStyle from registry.runtimes[id].runtime.commandStyle
(lazy require of the committed capability-registry.cjs) instead of the hardcoded
if (rt === 'codex'). Equivalence-preserving (Codex-verified): codex (shell-var) →
$gsd- + lowercased token; all 15 others (slash-hyphen) + unknown → /gsd- +
case-preserved token. canonicalizeRuntimeName + input normalization + claude default
preserved; no circular load (mirrors 5b runtime-homes pattern).

Added a registry-parity test: 16 parametrized sub-tests derive the expected prefix +
lowercasing from each runtime's commandStyle, proving the prefix is a pure function of
the registry (catches future hardcode-vs-registry divergence).

Closes #1046

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-11 12:37:25 -04:00
committed by GitHub
parent 6968e04d8a
commit 734c56ccfe
2 changed files with 91 additions and 2 deletions

View File

@@ -55,8 +55,17 @@ export function formatGsdSlash(commandName: unknown, runtime: unknown): unknown
const runtimeText = (typeof runtime === 'string' && runtime ? runtime : 'claude').toLowerCase();
const rt = canonicalizeRuntimeName(runtimeText) || runtimeText;
if (rt === 'codex') {
// Codex skills are invoked as $gsd-<cmd> (shell-var syntax). The command
// Descriptor-driven: look up commandStyle from the capability registry.
// Mirrors the lazy-require pattern from runtime-homes.cts §getGlobalConfigDir.
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { runtimes } = require('./capability-registry.cjs') as {
runtimes: Record<string, { runtime?: { commandStyle?: string } }>;
};
const style = runtimes[rt]?.runtime?.commandStyle;
if (style === 'shell-var') {
// shell-var runtimes (currently: codex) use $gsd-<cmd> syntax. The command
// token is lowercased because shell-var identifiers are conventionally
// lowercase; matches the convertCodexSlash() projection in bin/install.js.
return `$gsd-${token.toLowerCase()}${tail}`;