* refactor(#712): replace Codex slash-command denylist lookbehind with positive-boundary match
The hyphen-style /gsd-<cmd> -> $gsd-<cmd> conversion in
convertSlashCommandsToCodexSkillMentions used a negative-lookbehind DENYLIST
enumerating characters that must NOT precede a real mention. #637 -> #704 showed
this is an unbounded treadmill: each new unanticipated preceding char (/, ., word
chars, then }, )) leaked the same path-corruption bug class, and a backtick-wrapped
path (`/gsd-core/workflows/update.md`) still leaked through.
Replace it with a POSITIVE two-boundary definition of a mention:
1. Left: opens at start-of-string, whitespace, or an inline-prose delimiter
(backtick/quote/paren/bracket).
2. Right: the command token is not followed by a path separator `/` (a path
continues, a command does not). The (?![a-z0-9/-]) lookahead also blocks
regex backtracking to a shorter command.
This closes the whole class by construction (no preceding-char denylist to
maintain) and fixes the backtick-wrapped-path corruption the #704 test
documented as a pre-existing gap, while preserving conversion of legitimate
backtick-wrapped mentions (e.g. CONTEXT.md's `/gsd-execute-phase` lists).
The colon-style /gsd: replace is intentionally left unguarded (it never appears
as a filesystem path segment) and is annotated as such.
Tests assert the regex directly (function now exported) across a convert/
don't-convert matrix plus one end-to-end pipeline assertion for the headline
backtick-path case.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore(#712): add changeset fragment for PR #747
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix(#704): exclude } and ) from Codex path-rewrite lookbehind
Shell variable expressions like \${VAR}/gsd-core/ and command-substitution
paths like \$(cmd)/gsd-local-patches were being rewritten to \$gsd-core and
\$gsd-local-patches respectively because the negative lookbehind in
convertSlashCommandsToCodexSkillMentions did not include } or ).
Add both characters to the lookbehind set:
(?<![a-zA-Z0-9./})])
Also adds regression test:
tests/bug-704-codex-launcher-path-corruption.test.cjs
Closes#704
* chore: add changeset for #704
* test: use RUNTIME_ROOT_PATH in assertion to eliminate dead-code lint warning
Replace the partial hard-coded fragment '}/gsd-core/bin/' with the
existing RUNTIME_ROOT_PATH const so the assertion both compiles clean
(no unused variable) and self-documents which canonical launcher path
must survive Codex conversion intact (#704).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: link changeset to PR #710
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>