fix(presets): preserve argument-hint in preset SKILL.md generation#2978
Open
jawwad-ali wants to merge 1 commit into
Open
fix(presets): preserve argument-hint in preset SKILL.md generation#2978jawwad-ali wants to merge 1 commit into
jawwad-ali wants to merge 1 commit into
Conversation
Preset-provided and extension-override commands that declare `argument-hint:` in their frontmatter had it dropped from the generated Claude SKILL.md, and it was re-dropped when a preset was removed and its overridden skill restored. This is the preset-side analog of the extension fix in github#2903 / github#2916. Factor the argument-hint carry-over into a shared CommandRegistrar.apply_argument_hint() helper and apply it at the four preset skill-generation sites (register, reconcile override-restore, and the core/extension unregister-restore paths). The extension path from github#2916 now uses the same helper. The helper writes argument-hint into the frontmatter dict before serialization (so a folded multi-line description cannot be split into invalid YAML) and only for integrations that support it (those exposing inject_argument_hint -- currently Claude), leaving build_skill_frontmatter's shared shape unchanged for every other agent. Core templates carry no argument-hint, so the core-restore path is a no-op. No behavior change for non-Claude agents or the core path. Add regression tests covering a folding description (Claude) and the non-Claude gate (codex). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Follow-up to #2903 / #2916. That fix preserved
argument-hintfor extension commands when generating ClaudeSKILL.md; the same field is still dropped by the preset skill generators.When a preset-provided command (or a preset override of an extension command) declares
argument-hint:in its frontmatter, the generated.claude/skills/<name>/SKILL.mdloses it, because the preset generators build the skill frontmatter via the sharedCommandRegistrar.build_skill_frontmatter()(which only emitsname/description/compatibility/metadata) and never forwardargument-hint. It is also re-dropped on preset removal, when an overridden skill is restored from its source command — which silently undoes the #2916 extension fix in a real workflow (override an extension skill via a preset, then remove the preset).Change
Rather than copy the #2916 inline block to each site, this factors the carry-over into one helper and reuses it:
agents.py— newCommandRegistrar.apply_argument_hint(source_frontmatter, skill_frontmatter, integration). It copiesargument-hintfrom the parsed source command frontmatter into the skill frontmatter dict, beforeyaml.safe_dump(so a folded multi-linedescriptioncan't be split into invalid YAML — the failure mode fix(extensions): preserve argument-hint in extension Claude SKILL.md (#2903) #2916 documented), and only when the integration exposesinject_argument_hint.presets.py— applied at all fourbuild_skill_frontmattersites:_register_skills, the reconcile override-restore path, and the core/extension_unregister_skillsrestore paths.extensions.py— the fix(extensions): preserve argument-hint in extension Claude SKILL.md (#2903) #2916 inline block now calls the shared helper (no behavior change).Why it's safe (no behavior change for non-Claude agents or the core path)
inject_argument_hintis defined only onClaudeIntegration(not inherited), so thehasattrgate adds the key for Claude only —build_skill_frontmatter's shared shape is byte-identical for every other agent (codex, kimi, …).argument-hint(0 of 9templates/commands/*.md), so the core-template restore site is a deliberate no-op.get_integration(...)lookup is hoisted a few lines abovebuild_skill_frontmatterso the hint can be applied pre-serialization — is a pure reorder:get_integrationis a side-effect-free registry lookup, the same value still feedspost_process_skill_content, and there is no import cycle (it was already a method-local import).Scope
Kept focused per CONTRIBUTING. The init-time
agents.py::render_skill_commandgenerator also omitsargument-hint, but it takes anagent_name(no integration object) and so needs separate plumbing — deferred to a follow-up rather than widening this PR.Heads-up on overlapping PRs
Open PRs #2917 ("preserve non-ASCII characters in skill frontmatter") and #2103 touch the same
presets.pyskill-generation lines. The concerns are orthogonal —apply_argument_hintmutates the frontmatter dict before whatever dump function runs, so it composes cleanly with #2917'sdump_frontmatter()swap. Happy to rebase whichever lands first.Testing
uv run specify --help(exit 0)uv sync && uv run pytestDetails (Windows 11, Python 3.12.12):
uvx ruff check src/— All checks passeduv run pytest tests/test_presets.py tests/test_extension_skills.py tests/integrations/test_integration_claude.py -q— 397 passed, 2 skipped (the fix(extensions): preserve argument-hint in extension Claude SKILL.md (#2903) #2916 extension tests pass unchanged, confirming the refactor is behavior-preserving)uv run pytest— 3610 passed, 148 skipped, 14 failed; the 14 failures are pre-existing and environment-only (os.symlink→WinError 1314; creating symlinks needs elevation/Developer Mode on Windows), identical to cleanmainon this host and unrelated to this change.New tests in
tests/test_presets.py:test_argument_hint_preserved_for_preset_command— installs a preset command withargument-hintand a long, folding description; asserts the generatedSKILL.mdfrontmatter parses and retains bothargument-hintand the full description. (Fails onmainwithKeyError: 'argument-hint'.)test_argument_hint_not_added_for_non_claude_preset_command— same under a non-Claude skills agent (codex); assertsargument-hintis not present, proving the Claude-only gate.Manual sanity: this changes only the emitted
SKILL.mdfrontmatter — no slash command's behavior changes; generated files parse as valid YAML and surface the hint in Claude Code.AI Disclosure
Developed with Claude Code (Claude Opus 4.8) under my direction — identifying the parallel preset drop sites, factoring the shared helper, writing the regression tests, and running the verification above. I personally confirmed the no-op behavior for non-Claude agents and the core path, verified the override-restore reorder is behavior-preserving, and reviewed the full diff before submitting. I'll disclose if any review responses are AI-assisted as well.