Files
holocron/docs/adr/0022-skill-metadata-version-is-mandatory.md
Defame1297 a3e721e937 docs: retire the META.md guidance ADR-0022 overruled, bump touched plugins
Why: ADR-0022 made `metadata.version` mandatory in SKILL.md frontmatter, but three documents still
instructed the opposite — that `version:`, `source:`, `references:` and `when:` belong in a separate
META.md. That recommendation was never implemented: META.md exists exactly once in this repo, inside
a vendored third-party research example, and all 39 skills now contradict it. A stale instruction
that outranks nothing is worse than no instruction, because an author following it undoes the ADR.

Implementation notes:
- Two LESSONS.md entries deleted outright — their entire payload was the rejected fix. Two kept and
  rewritten: the copy-fill entry loses only its META-TEMPLATE clause, and the `model:` entry keeps
  the provider-extension fact and the invocation-time boundary rule, which stand on their own.
- One factual error corrected in passing: the `extracted` slug entry claimed provenance is recorded
  in META.md. It lives in `references/sources.md` keyed by `source_keys:`, verified against
  validate-provenance.sh.
- Both docs/notes files gain `metadata.version` in their required-field lists. Deleting the stale
  paragraph while leaving those lists silent would have re-created the gap.
- `bin/write-docs` carried `metadata.version: "1.0"` — the only non-semver value in the corpus, and
  the result of relocating its old top-level `version:` without normalising it. Now `1.0.0`.
  ADR-0022 records the relocation it previously omitted, which issue #127 had asked it to decide.

Impact: patch bumps for the four plugins whose `.apm/` content changed — bin, git, gitea,
kyberforge. core and lint are untouched and stay put. Root apm.yml's `executables.allow` key and
marketplace package versions move in lockstep; the marketplace release version is unchanged.

Refs: #127
ADR: 0022
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP
2026-09-09 05:15:41 +00:00

4.7 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.
  • bin/write-docs's top-level version: moves into metadata:, normalized to 1.0.0. It is the one skill that carried a version outside the metadata: block, which is why the table above counts bin as 0 — a top-level version: is not metadata.version, and nothing reads it. #127 raised it alongside the split because "does a skill carry a version" and "where does it live" are the same question. Its value (1.0) is not semver and carries no more real history than the 27 unversioned skills, so it is relocated and reset to the same 1.0.0 seed rather than preserved like git-commits's tracked 0.1.3.
  • 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", and a 28th — bin/write-docs — reaches the same value by relocating its top-level version: "1.0" into metadata:. 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.