Files
msd-core/.changeset/amber-foxes-leap.md
Tom Boucher bf127b7d25 fix(#2565): route generate-claude-profile target through runtime policy (#2659)
* test(#2565): add failing regression for generate-claude-profile runtime target

cmdGenerateClaudeProfile hardcodes .claude/CLAUDE.md (project + global),
ignoring the runtime policy that #3163 wired into the sibling
cmdGenerateClaudeMd handler. These tests pin the parity contract for
project scope (codex -> AGENTS.md, env precedence, --output override,
claude preserved), global scope (codex -> <CODEX_HOME>/AGENTS.md, claude
preserved), and a divergence guard asserting both handlers agree on the
project instruction path for the same runtime.

Failing-first: all seven tests reproduce the bug on unmodified next.

* fix(#2565): route generate-claude-profile target through runtime policy

cmdGenerateClaudeProfile hardcoded .claude/CLAUDE.md for both project and
global scope, ignoring the runtime-aware resolution that #3163 wired into
the sibling cmdGenerateClaudeMd handler. The #3163 fix diverged when it did
not propagate here, so /gsd-profile-user kept writing Claude instruction
files on Codex installs (and other AGENTS-native runtimes: opencode, kilo,
kimi, antigravity, copilot).

Fix mirrors the proven #3163 pattern using existing policy primitives:
- Project scope resolves through getProjectInstructionFile(runtime) and a
  non-claude runtime wins over a stale claude_md_path (AGENTS-native
  projects must never write to CLAUDE.md).
- Global scope derives ~/.<config-home>/<instruction-basename> via
  getGlobalConfigDir + basename(getProjectInstructionFile), so codex lands
  at ~/.codex/AGENTS.md. Claude global is preserved byte-for-byte (no
  env-var drift beyond the prior hardcoded path).
- GSD_RUNTIME env var takes precedence over config.runtime.

A parity test asserts both handlers agree on the project instruction path
for the same runtime, guarding against future re-divergence
(CLAUDE.md 'Generative Fix Divergence' rule).

* docs(#2565): add changeset fragment for generate-claude-profile runtime fix

* docs(#2565): remove parenthetical product description from changeset

The product-name purity guard (#1777) flags 'ProductName (description)'
patterns in changeset fragments because the prose renders verbatim into
CHANGELOG.md at release time. The original fragment had 'Codex (and other
AGENTS-native runtimes)' in the bold header, which matched the banned
pattern. Reworded to drop the parenthetical; also trimmed the per-runtime
mapping (belongs in code comments, not changelog prose).

* docs(#2565): backfill PR number in changeset fragment

* test(#2565): isolate os.homedir() cross-platform in claude global test

The 'global scope: claude runtime writes to ~/.claude/CLAUDE.md' test set
only HOME to redirect os.homedir() at a tmpDir. On Windows, Node's
os.homedir() reads USERPROFILE (not HOME), so the child process still
resolved the real user profile and the path assertion failed (#2659 CI).
Set USERPROFILE alongside HOME so the isolation holds on both POSIX and
Windows. Production code is unchanged — it uses os.homedir() exactly as
the prior hardcoded path did.
2026-07-26 01:06:35 -04:00

891 B

type, pr
type pr
Fixed 2659

/gsd-profile-user now writes the runtime-native instruction file on Codex and other AGENTS-native runtimes — generate-claude-profile hardcoded .claude/CLAUDE.md for both project and global scope, ignoring the runtime-aware resolution that #3163 wired into the sibling generate-claude-md handler. The #3163 fix diverged when it didn't propagate here, so running $gsd-profile-user --refresh on a Codex install created/modified Claude configuration instead of producing a Codex AGENTS.md profile. The command now resolves its target through the shared runtime policy: project scope uses getProjectInstructionFile(runtime) and global scope derives ~/.<config-home>/<instruction-basename>, so codex lands at ~/.codex/AGENTS.md. Claude behaviour is preserved. A parity test guards against future re-divergence between the two handlers. (#2659)