* test(#4324): prove colon tokens the installer cannot convert leak
Failing-first regression coverage for #4324. The install rewrite
(transformContentToHyphen) is gated on an exact match against the
commands/gsd stem list, so any /gsd:<token> whose token is not a
registered stem survives the install and reaches the user as the
deprecated colon form.
The gate is load-bearing -- it is the only thing protecting the
workflow DSL marker family (gsd:section, gsd:protected, gsd:loop-host,
gsd:guard, gsd:dispatch, gsd:plan-revision-conflicts), which
workflow-fragments parses as a literal. So this suite asserts the
shipped text is convertible rather than asserting the transform is
broad, and pins the marker family as explicit negative space.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(#4324): stop unconvertible colon tokens reaching the user
The install rewrite is gated on an exact match against the commands/gsd
stem list, so a /gsd:<token> whose token is not a registered stem
survives the install and reaches the user as the deprecated colon form.
That gate is load-bearing -- it protects the gsd:section /
gsd:protected / gsd:loop-host marker family -- so the fix is in the
shipped text, and the source stays colon per CONTEXT.md's two-tier rule.
- quick-batch command + skill description: close the command token at a
boundary so `/gsd:quick`-shaped converts instead of being skipped.
- gsd-code-fixer (both variants): execute-plan and diagnose-issues are
workflows, not commands, so they never converted and rendered beside
two hyphenated siblings on the same line. Name them as workflows.
- help topic-mode: the extraction rule hard-coded a colon prefix that
the converted full.md never ships, so --brief could never match a
signature line and silently fell back on every topic. Describe the
signature line without a literal prefix.
- update.md: drop the prefix from prose describing a stale command.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* chore(#4324): add changeset fragment
pr:0 placeholder is backfilled with the real number once the PR exists.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(#4324): locate the help summary per reference variant
Adversarial review finding. Restoring the signature-line match (the
#4324 fix) activated a latent defect in the clause next to it: compact
scope emitted "the single non-blank line immediately after" the
signature, and that clause is only correct for full.md.
full.compact.md puts the summary on the signature line itself, after an
em-dash, and its next non-blank line is an unrelated "Usage:" line. Both
variants ship and both are served, so before this commit the compact
variant would have emitted the wrong line as the summary. It was masked
until now only because the stale colon prefix meant no signature line
ever matched at all.
Name the two placements and pick per line, and say explicitly that a
Usage: line is never a summary.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(#4324): de-vacuum the help parity check, narrow the marker waiver
Two adversarial review findings against the #4324 coverage.
The help-parity assertion went vacuous the moment the fix landed: once
topic.md stops spelling a literal prefix, the matched set is empty and
the assertion holds for any rewording, correct or not. It now also
asserts across BOTH served reference variants that each ships signature
lines under the hyphen prefix, that the two genuinely disagree about
where the summary sits, and that topic.md still names both placements
and the Usage: guard.
The marker waiver keyed on "sits inside an HTML comment", which waves
through a real broken reference that happens to be commented out --
`<!-- see /gsd:typo-cmd -->` scored clean. Enumerate the six marker
families instead. Verified the narrowed rule catches that probe and
still passes over the tree; it also surfaced a seventh family,
write-continue, that the broad rule was hiding.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(#4324): normalize the namespace in skill descriptions
Both hyphen-namespace skill converters ran the hyphen transform over the
body but rebuilt the frontmatter description from the raw field, so a
/gsd:<cmd> mention in a command description survived into the installed
SKILL.md -- the exact field the host's skill picker renders, which is
the surface this issue was filed about.
The local flat-command path was already correct because it rewrites the
whole file; only the skills path, used by a global install, was
affected. Confirmed by installing into a fake HOME before and after.
Fixed in both copies: bin/install.js and the src/ source of truth that
compiles into gsd-core/bin/lib.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(#4324): assert descriptions through the real converters
The previous version of this check called transformContentToHyphen on
the description line itself and passed, while a real install still
shipped the colon form -- the converter never calls that transform on
the description. It asserted a proxy for the behaviour instead of the
behaviour.
Drive convertClaudeCommandToClaudeSkill and
convertClaudeCommandToClineSkill over every registered command and
assert on the emitted description. Verified it fails against the
pre-fix converters and passes against the fixed ones.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* chore(#4324): regenerate skills after the description change
skills/<name>/SKILL.md is generated by gen-plugin-skills, not
hand-maintained, and lint:generated-sync caught the hand edit. The
regenerated file emits the hyphen form, which also corrects the
assumption behind the scan comment in the namespace test: skills/ is
runtime-emitter output, not colon source.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(#4324): re-sanction normalizeKimiSkillName's real end line
The description-normalisation fix inserted five lines above
normalizeKimiSkillName in src/runtime-artifact-conversion.cts, moving its
closing brace from 635 to 640. MAJOR-1 pins that line deliberately, so the
planted violation landed INSIDE the exempted body and went unflagged --
0 !== 1.
Re-sanction the value rather than derive it: the array is named
sanctionedRealEndLines, and a pinned line that fails loudly on drift is
the design. Deriving it would remove the human check the name asks for.
Verified by executing all four MAJOR-1 rows against the real tree: each
planted violation is flagged at realEndLine+1 and each unmodified file
stays exempt.
Emitted-Drift-Ack-Growth: gsd-code-fixer.md — names execute-plan and diagnose-issues as workflows rather than as slash commands that do not exist
Emitted-Drift-Ack-Growth: gsd-code-fixer.compact.md — same rewording as its full sibling, kept byte-consistent with it
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* chore(#4324): backfill the changeset PR number
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: sim <sim@local>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>