Data Model

Command skill identity

FieldFormInvariant
command[a-z][a-z0-9-]*, member of CANONICAL_COMMANDSexplicit set, never a prefix match
skill namespec-kitty-<command>≤64 chars; equals folder; not a charter-skill or retired name
rel path.agents/skills/spec-kitty-<command>/SKILL.mdPOSIX separators in manifests
legacy rel path.agents/skills/spec-kitty.<command>/SKILL.mdread-only: migration + doctor only

Command-skill manifest entry (unchanged shape)

{path, content_hash, agents[], installed_at, spec_kitty_version}; schema path pattern accepts the canonical and the legacy form so a pre-migration manifest still loads.

State transitions (rename migration, per legacy entry)

legacy entry + file hash == entry hash  -> delete SKILL.md (+ empty folder) -> drop entry
legacy entry + file hash != entry hash  -> keep file, warn "no longer managed" -> drop entry
legacy entry + file missing             -> drop entry
legacy folder without entry             -> untouched (reported by doctor skills)

Frontmatter projection

shared root → keys ∈ ALLOWED; other top-level keys → metadata.<key>: "<str(value)>". native root → unchanged.