Problem
Each component currently has multiple hand-authored manifestations (today: prompt.md and skill/SKILL.md; tomorrow: possibly agent/AGENT.md, Gemini extensions, OpenAI Assistants, etc.). Keeping those files consistent by hand drifts — version numbers, descriptions, and prompt bodies all diverge over time. Adding support for a new LLM platform today requires touching N files per component.
Proposal
Declare components/<name>/prompt.md (frontmatter + body) and components/<name>/schema.json the single source of truth for every component. All platform-specific wrappers are derived artifacts produced by a generator script and validated in CI.
Canonical (hand-authored)
components/<name>/prompt.md — frontmatter (name, version, description, category, domain, status, tags, audience) + prompt body
components/<name>/schema.json
components/<name>/README.md, CHANGELOG.md, evals/
Generated (committed, never hand-edited)
.claude-plugin/marketplace.json at repo root
components/<name>/.claude-plugin/plugin.json
components/<name>/skills/<name>/SKILL.md (frontmatter and body both derived from prompt.md)
- future:
components/<name>/gemini/gemini-extension.json, components/<name>/openai/assistant.json, etc.
Generator
.github/scripts/generate_wrappers.py scans components/, parses each prompt.md, and writes every derived artifact. Idempotent. Each new platform target is a new render function following the same pattern; canonical sources do not change.
CI
.github/workflows/generate-wrappers.yml runs the generator and fails on git diff --exit-code. Contributors run the script locally before committing — a failure signals that the committed wrappers are stale relative to the canonical sources.
Acceptance criteria
Out of scope (tracked separately)
Relationship to other issues
Problem
Each component currently has multiple hand-authored manifestations (today:
prompt.mdandskill/SKILL.md; tomorrow: possiblyagent/AGENT.md, Gemini extensions, OpenAI Assistants, etc.). Keeping those files consistent by hand drifts — version numbers, descriptions, and prompt bodies all diverge over time. Adding support for a new LLM platform today requires touching N files per component.Proposal
Declare
components/<name>/prompt.md(frontmatter + body) andcomponents/<name>/schema.jsonthe single source of truth for every component. All platform-specific wrappers are derived artifacts produced by a generator script and validated in CI.Canonical (hand-authored)
components/<name>/prompt.md— frontmatter (name,version,description,category,domain,status,tags,audience) + prompt bodycomponents/<name>/schema.jsoncomponents/<name>/README.md,CHANGELOG.md,evals/Generated (committed, never hand-edited)
.claude-plugin/marketplace.jsonat repo rootcomponents/<name>/.claude-plugin/plugin.jsoncomponents/<name>/skills/<name>/SKILL.md(frontmatter and body both derived fromprompt.md)components/<name>/gemini/gemini-extension.json,components/<name>/openai/assistant.json, etc.Generator
.github/scripts/generate_wrappers.pyscanscomponents/, parses eachprompt.md, and writes every derived artifact. Idempotent. Each new platform target is a new render function following the same pattern; canonical sources do not change.CI
.github/workflows/generate-wrappers.ymlruns the generator and fails ongit diff --exit-code. Contributors run the script locally before committing — a failure signals that the committed wrappers are stale relative to the canonical sources.Acceptance criteria
description:has been migrated from every existingskill/SKILL.mdinto the correspondingprompt.mdfrontmatter.components/*/skill/directories removed.templates/new-component/reflects the canonical-only layout (no hand-authoredskill/folder)..github/scripts/lint_components.pyupdated to reference the newskills/<name>/SKILL.mdpath.Out of scope (tracked separately)
Relationship to other issues
metadata.evalsfield toplugin.jsononce implemented — that field comes from a canonical source here too.