@@ -16,6 +16,7 @@ const { output, error, loadConfig } = require('./core.cjs');
|
||||
const { platformReadSync: safeReadFile, platformWriteSync, platformEnsureDir } = require('./shell-command-projection.cjs');
|
||||
const { getGlobalSkillDir } = require('./runtime-homes.cjs');
|
||||
const { formatGsdSlash, resolveRuntime } = require('./runtime-slash.cjs');
|
||||
const { resolveRuntimeNameFromCandidates } = require('./runtime-name-policy.cjs');
|
||||
|
||||
// ─── Constants ────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -811,9 +812,16 @@ function cmdGenerateDevPreferences(cwd, options, raw) {
|
||||
let effectiveRuntime = 'claude';
|
||||
try {
|
||||
const config = loadConfig(cwd);
|
||||
effectiveRuntime = process.env.GSD_RUNTIME || config.runtime || 'claude';
|
||||
effectiveRuntime = resolveRuntimeNameFromCandidates(
|
||||
process.env.GSD_RUNTIME,
|
||||
config.runtime,
|
||||
'claude'
|
||||
) || 'claude';
|
||||
} catch {
|
||||
effectiveRuntime = process.env.GSD_RUNTIME || 'claude';
|
||||
effectiveRuntime = resolveRuntimeNameFromCandidates(
|
||||
process.env.GSD_RUNTIME,
|
||||
'claude'
|
||||
) || 'claude';
|
||||
}
|
||||
const skillDir = getGlobalSkillDir(effectiveRuntime, 'gsd-dev-preferences');
|
||||
if (!skillDir) {
|
||||
@@ -1003,7 +1011,10 @@ function cmdGenerateClaudeMd(cwd, options, raw) {
|
||||
// #3163: When runtime is codex, override the output target to AGENTS.md
|
||||
// regardless of claude_md_path, so Codex projects never write to CLAUDE.md.
|
||||
// GSD_RUNTIME env var takes precedence over config.runtime, mirroring detectRuntime().
|
||||
const effectiveRuntime = process.env.GSD_RUNTIME || config.runtime || null;
|
||||
const effectiveRuntime = resolveRuntimeNameFromCandidates(
|
||||
process.env.GSD_RUNTIME,
|
||||
config.runtime
|
||||
);
|
||||
if (!options.output && effectiveRuntime === 'codex') {
|
||||
configClaudeMdPath = './AGENTS.md';
|
||||
}
|
||||
|
||||
@@ -57,6 +57,27 @@ function canonicalizeRuntimeName(value) {
|
||||
return aliasToCanonical.get(normalizeRuntimeToken(value)) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve runtime from a precedence list of candidate values.
|
||||
*
|
||||
* - First non-empty string candidate wins.
|
||||
* - Known aliases are canonicalized (codex-cli -> codex).
|
||||
* - Unknown values are normalized and returned (future-runtime tolerance).
|
||||
*
|
||||
* @param {...string} candidates
|
||||
* @returns {string|null}
|
||||
*/
|
||||
function resolveRuntimeNameFromCandidates(...candidates) {
|
||||
for (const candidate of candidates) {
|
||||
if (typeof candidate !== 'string') continue;
|
||||
const normalized = normalizeRuntimeToken(candidate);
|
||||
if (!normalized) continue;
|
||||
return canonicalizeRuntimeName(normalized) || normalized;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
canonicalizeRuntimeName,
|
||||
resolveRuntimeNameFromCandidates,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const { canonicalizeRuntimeName } = require('./runtime-name-policy.cjs');
|
||||
const { canonicalizeRuntimeName, resolveRuntimeNameFromCandidates } = require('./runtime-name-policy.cjs');
|
||||
|
||||
/**
|
||||
* runtime-slash.cjs — single source of truth for emitting GSD slash-command
|
||||
@@ -69,10 +69,8 @@ function formatGsdSlash(commandName, runtime) {
|
||||
* @returns {string}
|
||||
*/
|
||||
function resolveRuntime(projectDir) {
|
||||
if (process.env.GSD_RUNTIME) {
|
||||
const rawRuntime = String(process.env.GSD_RUNTIME).toLowerCase();
|
||||
return canonicalizeRuntimeName(rawRuntime) || rawRuntime;
|
||||
}
|
||||
const envRuntime = resolveRuntimeNameFromCandidates(process.env.GSD_RUNTIME);
|
||||
if (envRuntime) return envRuntime;
|
||||
if (projectDir) {
|
||||
try {
|
||||
// Read config.json directly (not via loadConfig). loadConfig has a side
|
||||
@@ -87,8 +85,8 @@ function resolveRuntime(projectDir) {
|
||||
const raw = fs.readFileSync(configPath, 'utf-8');
|
||||
const parsed = JSON.parse(raw);
|
||||
if (parsed && typeof parsed === 'object' && parsed.runtime) {
|
||||
const rawRuntime = String(parsed.runtime).toLowerCase();
|
||||
return canonicalizeRuntimeName(rawRuntime) || rawRuntime;
|
||||
const configRuntime = resolveRuntimeNameFromCandidates(parsed.runtime);
|
||||
if (configRuntime) return configRuntime;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user