fix(#1114): write-profile resolves the active runtime config home for USER-PROFILE.md (#1119)

Under Codex, `write-profile` wrote ~/.claude/gsd-core/USER-PROFILE.md while Codex
discuss-phase advisor-mode (installed under ~/.codex) checked the Codex home and
never found the profile, so advisor-mode silently stayed disabled. Resolve the
default output via the runtime-aware getGlobalConfigDir (GSD_RUNTIME / config.runtime),
mirroring cmdGenerateDevPreferences. Claude unchanged; --output still wins.

Closes #1114

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-12 15:54:48 -04:00
committed by GitHub
parent e837bfc1de
commit fb8e7a3a65
3 changed files with 94 additions and 2 deletions

View File

@@ -117,6 +117,73 @@ describe('write-profile command', () => {
assert.ok(out.dimensions_scored > 0, 'should have scored dimensions');
});
test('#1114: default output resolves the active runtime config home (codex)', () => {
const analysis = {
profile_version: '1.0',
dimensions: { communication_style: { rating: 'terse-direct', confidence: 'HIGH' } },
};
const analysisPath = path.join(tmpDir, 'analysis.json');
const codexHome = path.join(tmpDir, 'codex-home');
fs.writeFileSync(analysisPath, JSON.stringify(analysis));
const result = runGsdTools(
['write-profile', '--input', analysisPath, '--raw'],
tmpDir,
{ CODEX_HOME: codexHome, GSD_RUNTIME: 'codex' }
);
assert.ok(result.success, `Failed: ${result.error}`);
const out = JSON.parse(result.output);
// Must land in the Codex home (so Codex advisor-mode finds it), NOT .claude.
assert.strictEqual(out.profile_path, path.join(codexHome, 'gsd-core', 'USER-PROFILE.md'));
assert.ok(!out.profile_path.includes(`${path.sep}.claude${path.sep}`),
`codex profile must not be written under .claude; got ${out.profile_path}`);
assert.ok(fs.existsSync(out.profile_path), 'runtime-aware profile should be written to disk');
});
test('#1114: default output is the .claude config home for the claude runtime', () => {
const analysis = {
profile_version: '1.0',
dimensions: { communication_style: { rating: 'terse-direct', confidence: 'HIGH' } },
};
const analysisPath = path.join(tmpDir, 'analysis.json');
fs.writeFileSync(analysisPath, JSON.stringify(analysis));
// Clear ambient runtime vars so the test is hermetic regardless of the
// developer's shell (a stray GSD_RUNTIME/CLAUDE_CONFIG_DIR would redirect it).
const result = runGsdTools(['write-profile', '--input', analysisPath, '--raw'], tmpDir,
{ HOME: tmpDir, GSD_RUNTIME: '', CLAUDE_CONFIG_DIR: '', CODEX_HOME: '' });
assert.ok(result.success, `Failed: ${result.error}`);
const out = JSON.parse(result.output);
// os.homedir() returns HOME verbatim, so assert on the suffix to stay
// robust against macOS /var → /private/var symlink normalization.
assert.ok(
out.profile_path.endsWith(path.join('.claude', 'gsd-core', 'USER-PROFILE.md')),
`claude profile must be under .claude/gsd-core; got ${out.profile_path}`
);
assert.ok(fs.existsSync(out.profile_path), 'profile should be written to disk');
});
test('#1114: config.runtime=codex (no GSD_RUNTIME) also resolves the Codex home', () => {
const analysis = {
profile_version: '1.0',
dimensions: { communication_style: { rating: 'terse-direct', confidence: 'HIGH' } },
};
const analysisPath = path.join(tmpDir, 'analysis.json');
const codexHome = path.join(tmpDir, 'codex-home');
fs.writeFileSync(analysisPath, JSON.stringify(analysis));
fs.writeFileSync(path.join(tmpDir, '.planning', 'config.json'), JSON.stringify({ runtime: 'codex' }));
// No GSD_RUNTIME — the runtime must be read from config.runtime.
const result = runGsdTools(
['write-profile', '--input', analysisPath, '--raw'],
tmpDir,
{ CODEX_HOME: codexHome, GSD_RUNTIME: '' }
);
assert.ok(result.success, `Failed: ${result.error}`);
const out = JSON.parse(result.output);
assert.strictEqual(out.profile_path, path.join(codexHome, 'gsd-core', 'USER-PROFILE.md'));
});
test('errors when --input is missing', () => {
const result = runGsdTools('write-profile --raw', tmpDir);
assert.ok(!result.success, 'should fail without --input');