Files
holocron/docs/adr/0022-skill-metadata-version-is-mandatory.md
Defame1297 60be7b3232 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
2026-09-07 20:36:24 +00:00

3.9 KiB

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.