refactor(skills): mandate metadata.version on every skill's frontmatter
Only 12 of 39 skills carried metadata.version, and adoption tracked which plugin a skill lived in rather than any stated rule: core, gitea and lint were consistent adopters, bin and kyberforge were consistent non-adopters, git was split with one outlier. There was no documented convention, and skill-author's own bump logic was already written as if presence were conditional. metadata.version is now required on every skill. The 19 skills here that never carried one (bin, kyberforge, gitea-files) are seeded at 1.0.0, not 0.1.0 -- that value stays reserved for a skill's actual creation point under skill-author's existing convention. The skill-frontmatter pre-commit hook now fails a SKILL.md missing the field, the same class of failure as a missing name/description. Full rationale in the new ADR. The git-plugin skills that also need this field follow in the next commit, bundled with issue #113's rtk normalization since both touch the same files. Refs: #127 ADR: 0022 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP
This commit is contained in:
70
docs/adr/0022-skill-metadata-version-is-mandatory.md
Normal file
70
docs/adr/0022-skill-metadata-version-is-mandatory.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Every skill's `metadata.version` is mandatory, not a per-plugin option
|
||||
|
||||
**Status: accepted (2026-09-07).**
|
||||
|
||||
## Context
|
||||
|
||||
`metadata.version` is optional SKILL.md frontmatter (`create.md`'s "Optional frontmatter" list:
|
||||
"uncomment and fill in, or remove entirely"). `skill-author`'s own bump logic was written
|
||||
conditionally — "with `metadata.version` present, bump the minor version on create... and the
|
||||
patch version on improve" — which only makes sense if presence is a real per-skill choice.
|
||||
|
||||
Adoption never followed a rule; it followed the plugin. Of 39 skills, 12 carry a version:
|
||||
|
||||
| Plugin | Has it | Total |
|
||||
|---|---|---|
|
||||
| `core` | 3 | 3 |
|
||||
| `gitea` | 6 | 7 |
|
||||
| `lint` | 2 | 2 |
|
||||
| `git` | 1 | 9 |
|
||||
| `bin` | 0 | 11 |
|
||||
| `kyberforge` | 0 | 7 |
|
||||
|
||||
`core`, `gitea` and `lint` are consistent adopters (`gitea-files` the one gap); `bin` and
|
||||
`kyberforge` are consistent non-adopters; `git` has one outlier (`git-commits`, versioned for no
|
||||
plugin-specific reason found on inspection — no comment, no cross-reference, nothing distinguishing
|
||||
it from its eight siblings). Issue #127 raised this as an undocumented split: two house norms
|
||||
coexisting with no stated rule for which applies where, the same class of defect as an unstated
|
||||
`rtk`/bare-`git` convention (#113) found in the same audit pass.
|
||||
|
||||
## Decision
|
||||
|
||||
**Every skill's frontmatter carries `metadata.version`.** It is no longer optional, and no longer a
|
||||
per-plugin choice.
|
||||
|
||||
- **The 27 skills that never carried one are seeded at `1.0.0`**, not `0.1.0`. `0.1.0` is
|
||||
`skill-author`'s existing new-skill starting point, chosen for a skill with no revision history to
|
||||
its name yet. These 27 have all been through the ADR-0020 retrofit and repeated audit passes
|
||||
without ever tracking a version; crediting them with `0.1.0` would understate that, and there is
|
||||
no real history to justify seeding higher than a first stable release. `1.0.0` marks "versioned as
|
||||
of this retrofit," `0.1.0` keeps meaning "created and never yet revised."
|
||||
- **New skills still start at `0.1.0`.** `skill-author`'s create/improve bump convention is
|
||||
unchanged; only the presence of the field stops being conditional.
|
||||
- **The one outlier in the other direction, `git-commits`, keeps its existing value** (`0.1.3`) —
|
||||
it already had real tracked history under the old conditional rule, and this decision does not
|
||||
reset skills that were already compliant.
|
||||
- **`skill-frontmatter`'s pre-commit hook gains the check.** It already fails a SKILL.md missing
|
||||
`name:` or `description:`; a missing `metadata.version` is now the same class of failure, not a
|
||||
style nit an audit might or might not catch.
|
||||
|
||||
## Considered options
|
||||
|
||||
**Leave it per-plugin, document the split.** This was the initial framing of #127 and is coherent —
|
||||
`core`/`gitea`/`lint` keep it, `bin`/`kyberforge` don't, two outliers get normalized to match their
|
||||
plugin. Rejected on reconsideration: a rule that says "some plugins track this and some don't" is
|
||||
strictly harder to state, audit and onboard against than "every skill does," for a field whose entire
|
||||
job is answering "did this change since I last read it" — a question with the same shape everywhere
|
||||
it's asked, not one that varies by plugin domain.
|
||||
|
||||
**Drop the field corpus-wide.** Rejected: `skill-author` already depends on it to decide whether a
|
||||
create/improve pass owes a bump, so the 12 skills carrying it are not tracking dead weight — removing
|
||||
it discards real revision signal for no gain.
|
||||
|
||||
## Consequences
|
||||
|
||||
27 SKILL.md files gain `metadata.version: "1.0.0"`. `skill-author`'s `create.md` moves the field from
|
||||
"Optional frontmatter" to the required list, citing this ADR. `skill-author`'s own SKILL.md drops the
|
||||
"with `metadata.version` present" conditional in its bump-rule line, since presence is no longer in
|
||||
question. `.pre-commit-config.yaml`'s `skill-frontmatter` hook is extended to require the field,
|
||||
closing the gap #113 and #118 both named in the same audit pass: a stated rule with nothing enforcing
|
||||
it drifts the same way an unstated one does.
|
||||
Reference in New Issue
Block a user