fix(skills): keep unmodeled Copilot SKILL.md frontmatter through the round-trip - #2587
Merged
Merged
Conversation
…round-trip CopilotSkill.toRulesyncSkill built the copilot: section by copying six known keys, so a hand-authored SKILL.md field rulesync does not model was dropped on import and erased from the file on the next generate — even though the frontmatter schema is a looseObject that parsed it fine. Both directions now carry the residual keys, as PR #2580 did for CopilotRuleFrontmatterSchema. Also refresh the stale copilotcli-hooks note: upstream documents ~/.copilot/hooks/ as the user-level hooks directory, so the location is no longer a rulesync convention (only the filename is). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Address review: copilot and copilotcli write the same SKILL.md path and copilotcli is generated last, so with both targets enabled the residual keys the previous commit preserved were dropped again on generate. The copilotcli class now spreads the same way, and the docs note that a residual key rides one section only, like the modeled fields. Also pin the section-vs-canonical precedence both classes rely on: the section is spread first, so name and description are never shadowed by it. Note that this reorders existing SKILL.md output, putting section keys ahead of name/description. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 6, 2026
Merged
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.
Summary
Two independent items from the Copilot follow-up issues.
(a) Residual-key skill round-trip (#2401)
CopilotSkillFrontmatterSchemais az.looseObject, so a hand-authored SKILL.md field Rulesync does not model parsed fine — buttoRulesyncSkillbuilt thecopilot:section by explicitly copying six known keys, so the field was dropped on import and then erased from the file on the next generate. Same fix class as #2580 applied toCopilotRuleFrontmatterSchema:toRulesyncSkillspreads all residual keys (everything exceptname/description, which have canonical homes) into the tool section;fromRulesyncSkillspreads the section back out, so the value survives regeneration rather than only living in.rulesync. The section is spread first, so the canonicalname/descriptionand the resolved invocation gates still own their keys.copilot-skill.tsandcopilotcli-skill.ts. The two targets write the same.github/skills/<name>/SKILL.mdpath andcopilotcliis generated last, so fixing onlycopilotwould have left the field dropped again in the common both-targets configuration.copilot:andcopilotcli:skills sections ofdocs/reference/file-formats.md, including the caveat that a residual key rides one section only, exactly like the modeled fields.Note: because the section is now spread before
name/description, generated SKILL.md files put the section keys first. This is a key-order change only, no semantic difference, and it matches whatcopilot-rule.tsalready does.(b) Stale comment (#2402)
copilotcli-hooks.tssaid the global hooks location was "a rulesync convention pending official documentation". Upstream documents it: "User-level hook files —*.jsonfiles in the user-level hooks directory. By default this is~/.copilot/hooks/on macOS and Linux, or%USERPROFILE%\\.copilot\\hooks\\on Windows" (github/docscontent/copilot/reference/hooks-reference.md). The comment now says the directory is documented and only the filename is Rulesync's choice, and notes thatCOPILOT_HOMErelocates it upstream while Rulesync does not read that variable yet.Testing
copilot-skill.test.ts/copilotcli-skill.test.ts: a field beyond the schema survives import into the tool section and is written back to the generated SKILL.md.name/descriptiondoes not shadow the canonical values, while its other keys are still kept.pnpm cicheckgreen;vitest run --config vitest.e2e.config.ts src/e2e/e2e-skills.spec.tsgreen (130 tests).Part of #2401
Part of #2402