skill-scaffold — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited skill-scaffold (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Skill scaffolding is protocol-backed authoring, not free-form prompt writing. A new skill is not just a Markdown file; it is a package contract that has to be discoverable by simple Agent Skills runtimes, queryable by Skill Graph tooling, understandable to a future agent, and honest about its evidence state.
The scaffold separates six layers:
name and description, for runtimes that preload only minimal metadata.audit-state.json for schema version, owner, freshness, drift, eval state, routing-eval state, lifecycle, portability, runtime telemetry, and the audit verdicts.references/, scripts/, and assets/ that load on demand instead of bloating the body.Separating these layers is what turns a text-heavy instruction file into a routable graph node rather than a decorative Markdown file.
# TEMPLATE NOTE: lines and > **TEMPLATE NOTE:** blockquotes only; keep field-purpose comments) → verify → commitSKILL.md (flat agent-facing frontmatter) plus a sibling audit-state.json (audit/eval/provenance state the audit loop owns). What lives where, and the minimal honest sidecar seedname (directory-matching, 1-64 chars), description (≤ 1024 chars for export), subject, optional subjects[], public, free-text scope, taxonomy_domain when useful, stability, the activation surfaces, relations, grounding, allowed-tools, compatibility, and the five flat Understanding fields when comprehension_state: present is set in the sidecarkeywords / examples / anti_examples plus the exact-match triggers and paths; and the optional project-fit precision fields a project-anchored skill can declare — dependencies (required packages), codebase_layer (architectural layer), applicable_tasks (task types), environment (target environments), internal_tools (project scripts whose presence makes the skill apply), and project_adoption_stage (legacy / current-standard / experimental-migration / deprecated). Each is optional; add only the ones that genuinely narrow when the skill should fireschema_version, version, owner, freshness, drift_check, the eval_* triple, routing_eval, comprehension_state, portability, lifecycle, runtime_telemetry, and the four Audit Status verdicts — all in audit-state.json, never in frontmatterreferences//scripts//assets/ loaded on demand) and what it implies for where each piece of knowledge belongsmetadata: export shape for Agent-Skills release packages, and the compatibility risk when a target runtime recognizes only a subset of fieldsname+description spec; extensions ride in the metadata extension channel and are nested by the exporter, so portability is safe without hand-writing the export shapetype archetypesmental_model, purpose, concept_boundary, analogy, and misconception; the legacy nested concept block is retireddescription, keywords, examples, anti_examples, scope, relations.suppresses, and ## Coverage divide discovery, activation, boundary, scope, and teaching responsibilities — and why each must stay in its own layer# TEMPLATE NOTE: lines and > **TEMPLATE NOTE:** blockquotes are authoring scaffolding (strip on derivation), while field-purpose comments (no TEMPLATE NOTE: prefix) are co-located documentation (keep in production). See skill-metadata-protocol/SKILL_METADATA_PROTOCOL.md § Inline field comments — the authoring conventionkeywords and user-voice examples from real domain vocabulary so the right skill is injected at the right time, and typing relations edges explicitly rather than dumping unstructured adjacencypublic private-data gate, provenance for outbound references, minimum tool permissions, and treating imported/tool/generated content as evidence rather than instructionsrouting_eval: absent in the sidecar and only flipping to present after the routing harness exits 0 on the skill's own examples + anti-examplesgrounding.truth_sources, why object entries with note are preferred, when URL truth sources are acceptable vs hashable local paths, and why URL fetching/hashing is a separate evidence stepA scaffold teaches by example, not by placeholder. A concrete, internally consistent specimen of a finished skill is a more reliable authoring reference than abstract instruction — but only if the author understands which parts are permanent contract and which parts are temporary teaching braces. The teaching layer — meta-commentary about how to read and adapt the scaffold — must live in structurally distinct slots that disappear when the author tightens a new skill, never in the ## H2 section slots that AI agents copy verbatim.
Because an AI agent is a reasoning engine bound by its context window, a skill must establish precise retrieval hooks (keywords, examples, relations) so the context pipeline injects it at the right time — and the body must capture expert judgment (the why and when), not just transcribe data (the what). Authoring is also a verification-first discipline: lightweight lint is the first smoke test, but protocol consistency, routing evals, drift checks, and human review are what answer "did I do this right?" for the full contract.
The main quality failure is not a missing heading. It is a false contract: a skill that routes too broadly, carries a copied sidecar attestation, points to stale sources, grants tools it does not need, exposes private data, or teaches an agent to follow the wrong body because the author left scaffold text in place.
Authoring choices only make sense once you know when each piece of a skill enters the agent's context. The Agent Skills open standard (the base SKILL.md format this protocol extends) loads a skill in three tiers, cheapest first. Knowing which tier a piece of knowledge lands in is the single best guide to where to put it.
| Tier | What loads | When | Authoring implication |
|---|---|---|---|
| 1 — Metadata | The frontmatter read at startup to decide activation. In the base Agent Skills spec that is name + description only; a Skill-Graph-aware router additionally indexes the protocol activation/classification fields (subject, keywords, examples) carried in the metadata extension channel | Always — scanned for every query to decide activation | Must be self-sufficient for routing. Keep it tight and pushy; front-load the core use case because some clients preload only this tier. Cost is paid on every request, so bloat here taxes the whole library. |
| 2 — Body | The Markdown body below the frontmatter | Only after the skill activates | Can be richer than the frontmatter, but it is dead weight until the skill fires. Put the operational guidance the agent needs the moment it is working in this domain. |
| 3 — Bundled resources | Files in the skill directory (references/, scripts/, assets/, evals/) | On demand, only when the body points the agent at them | Push deep reference material, long tables, worked examples, and large specs here — not into the body. A body that inlines a 400-line spec forces tier-2 cost the agent rarely needs. |
Three consequences for a new skill:
description, keywords, examples, subject) is read cheaply up front; everything an agent needs to use it lives in tier 2+. Conflating them bloats the always-loaded tier.references/<topic>.md file the body links to (tier 3), keeping the body scannable.SKILL.md + sibling audit-state.json is the minimum; bundled references/, scripts/, and eval fixtures (evals/) are first-class parts of the skill that the progressive-disclosure model loads lazily.The Skill Metadata Protocol is a superset of the Agent Skills open standard — the same base SKILL.md format adopted across Claude Code, Codex, Gemini, Copilot, Cursor, and other tools. Understanding the relationship prevents two authoring mistakes: hand-writing the export shape, and fearing that protocol fields will break portability.
name and description. name must be lowercase letters/numbers/hyphens, ≤ 64 chars, must not start or end with a hyphen, and must match the parent directory — a mismatch means the skill silently fails to load. description carries a hard ceiling (≤ 1024 characters at the export/marketplace layer). Everything else the protocol adds (subject, public, scope, relations, grounding, the sidecar) is an extension.name + description at startup to decide activation and defines metadata as the designated extension channel for everything else, while compliant runtimes ignore frontmatter keys they don't recognize. The protocol's extension fields live in that channel, so a plain Agent-Skills runtime sees a valid two-field skill while a Skill-Graph-aware consumer reads the full contract. Do not rely on scattering arbitrary unrecognized top-level keys and hoping a runtime ignores them — metadata is the contract-sanctioned home for the extension.examples/skill-metadata-template.md) every protocol field is a top-level key with a field-purpose comment above it — that is the shape you copy and edit. The Agent-Skills export encodes the protocol extensions under a metadata: block (and JSON-stringifies structured values such as grounding) so the public release stays standard-compatible. That nested encoding is a build artifact produced by the exporter (node scripts/export-marketplace-skills.js) — never hand-write it into a new skill. (Encoding doctrine: AGENTS.md § Public Distribution.)portability.readiness is declared (claim only) → scripted (export tooling exists) → verified (proven with an export receipt). Do not assert verified until an export run has produced the plain Agent-Skills SKILL.md and it validated.Different runtimes read different subsets of fields. Author the richest canonical contract, but know what each consumer actually sees:
| Consumer surface | Practical rule |
|---|---|
| Base Agent Skills format | A skill is a folder with SKILL.md; name + description are the minimum discovery fields. name must match the parent directory and fit the base name rule; description must fit the base length rule and say what the skill does and when to use it. Move long references into references/, scripts/, or assets/ when only needed on demand. |
| Codex-style progressive disclosure | Initial context may contain only each skill's name, description, and path, so the first sentence of description must carry the core use case. The full body loads only after selection. |
| Claude Code-style skills | Runtime features such as invocation control, subagent context, dynamic shell insertion, and tool permissions may exist, but they are runtime features, not Skill Metadata Protocol fields. Add them only when the target runtime needs them. |
| OpenCode-style skills | OpenCode recognizes a small frontmatter subset (name, description, license, compatibility, metadata) and ignores unknown top-level fields. If exporting for a strict consumer, verify the exported shape rather than assuming every Skill Graph field is read. |
| Skill Graph canonical source | Authors write flat protocol-native frontmatter with native YAML objects/arrays plus a sibling sidecar. Manifest generation joins SKILL.md and audit-state.json; lint and audit tools enforce honesty beyond what plain runtimes see. |
| Generated Agent Skills release | The exporter creates the nested metadata: map and JSON-stringified structured values required by the public release shape. Treat that form as a build artifact, not the source shape to copy while authoring. |
If a runtime ignores your rich metadata, description and body organization carry more load; if Skill Graph consumes the skill, the machine-readable activation and relation fields carry more load. A good scaffold serves both without collapsing them into one overloaded paragraph. External runtime documentation can be a valid truth source, but never as a bare, unexplained URL — use a truth-source object with a note recording why the URL is evidence, then run or record a fetch/verification route before treating it as truth-certified.
A skill is two files (ADR-0019): the agent-facing SKILL.md frontmatter above, and a sibling audit-state.json that holds the audit/eval/provenance state the Skill Audit Loop owns. These fields belong in the sidecar and must never be written into SKILL.md frontmatter: schema_version, version, owner, freshness, drift_check, the eval_* triple, routing_eval, comprehension_state, portability, lifecycle, runtime_telemetry, and the four Audit Status verdicts (structural_verdict, truth_verdict, comprehension_verdict, application_verdict). The manifest join recombines the two files; an author who pastes verdict or eval comments into frontmatter is modelling the wrong shape.
When you author a new skill, seed the minimal honest sidecar and leave the verdict and telemetry fields absent until a real audit or eval run writes evidence. Never copy another skill's verdicts, an eval_state: passing, or a telemetry block into a new skill — that is a fabricated attestation (the same doc-lie class as eval_state: passing with no run receipt).
{
"schema_version": 8,
"version": "1.0.0",
"owner": "your-team-or-handle",
"freshness": "YYYY-MM-DD",
"drift_check": { "last_verified": "YYYY-MM-DD" },
"eval_artifacts": "none",
"eval_state": "unverified",
"routing_eval": "absent"
}Rules:
schema_version, owner, freshness, drift_check, eval_artifacts, eval_state, routing_eval. version is optional but recommended for content tracking. Validate against schemas/skill-audit-state.schema.json.structural_verdict, truth_verdict, comprehension_verdict, application_verdict, lint_verdict, last_audited, and last_changed absent until the audit loop or checker writes evidence. The four verdicts default to UNVERIFIED — the honest starting state.runtime_telemetry, eval scores, failed IDs, or verdicts. Those are receipts for that skill, not defaults for yours.examples/skill-audit-state-template.md; it is not auto-generated. Full field guidance lives in that template.Native skill creators and generator skills (Claude/Codex/OpenCode $skill-creator-style helpers) are useful drafting tools. They are not the final authority for a Skill Graph skill.
Use them for:
SKILL.md from a well-described workflow.Do not use them for:
routing_eval: present, eval_state: passing, or any audit verdict — they draft and review, they do not execute the quantitative evals or local schema/sidecar receipts.public: true without a private-content review.The safe handoff is: generator draft → author review against current truth sources → adapt to the template pair → strip scaffold-only notes → run the deterministic gates → record only evidence-backed state. Treat generated drafts as untrusted proposals: inspect, adapt, verify, then commit.
Skill authoring touches publishable output and pulls in outside material that future agents may obey; treat it as a supply-chain surface. Four boundaries keep a new skill safe.
public: true asserts the skill body and every bundled reference carry no private data — no secrets, API keys, customer/personal/financial data, internal-only operational doctrine, or internal-only file paths. When a skill must reference private surfaces, set public: false (the fail-safe default) so the marketplace exporter never publishes it. Project anchoring (project[]) is a separate axis from publishability.allowed-tools should list the minimum tools the skill needs for runtimes that honor it — a skill that teaches reading Markdown does not need write or shell permissions. It is not a substitute for runtime permissions. A skill that bundles executable scripts/ must document their dependencies and failure behavior, and references should be focused enough to load on demand without overwhelming context.Each step is a gate. Skipping a gate can leave a skill that looks plausible in a text editor but fails as a routable graph node or a portable Agent Skills package.
Step 0 (precondition): prove a new node is justified. Search the existing skill library and any project-specific redundancy registry. If the intended subject is already covered, improve the existing skill or record the distinct grounding evidence that justifies a separate node. Do not create a synonym skill just because the proposed title is better — a duplicate without contradicting evidence wastes context and weakens routing precision.
audit-state.json; do not hand-author the generated nested metadata: shape or JSON-stringify structured fields such as grounding and relations. Plain Agent Skills exports must still respect the base name/description length and directory-name constraints, and simple runtimes may preload only those two fields.examples/skill-metadata-template.md to skills/<your-skill-name>/SKILL.md and seed a sibling audit-state.json from examples/skill-audit-state-template.md. Do not rename the template in place; it stays as the canonical specimen.name, the body title, description, scope, keywords, examples, anti_examples, and any paths or triggers. Confirm name is lowercase-kebab, ≤ 64 chars, does not start/end with a hyphen, and exactly matches the parent directory — a mismatch silently fails to load. description must fit the export limit while still carrying trigger and boundary language. Every reference to skill-metadata-template must be gone unless it appears as a deliberate source citation.subject, optional subjects[] only for a genuine two-shelf skill, public, free-text scope, taxonomy_domain only when the shelf is crowded enough to need a sub-path, and project[] only when project anchoring is true. Add the optional project-fit precision fields (dependencies, codebase_layer, applicable_tasks, environment, internal_tools, project_adoption_stage) only when they encode a real routing or lifecycle constraint — for a portable principle-grounded skill they are usually omitted; for a project-anchored skill they sharpen routing.description as the compact discovery summary for runtimes that preload it; keywords for fuzzy activation terms; examples/anti_examples for realistic positive/negative prompts; the project-fit fields for deterministic filters; relations.suppresses for ownership exclusions; paths only for file-surface ownership. Do not stuff every activation concern into description.## Coverage, a short model/stance section such as ## Philosophy, the main workflow/tables/checklists the agent will actually use, ## Verification, and ## Do NOT Use When. Remove sections that do not apply — do not keep placeholder content. Move deep reference material the agent consults occasionally into a references/<topic>.md file (progressive-disclosure tier 3) rather than inlining it.comprehension_state: present in the sidecar. Add grounding.truth_sources when the skill is anchored to a protocol, spec, codebase, vendor document, or public standard. Prefer object truth-source entries with note: local entries can be hashed precisely by the drift tool, while URL entries need an explicit provenance reason and a separate fetch/verification receipt before they support truth certification.public is true only if the body and references carry no private data. Reduce allowed-tools to the minimum the skill actually needs.eval_artifacts: none, eval_state: unverified, routing_eval: absent) and leave verdicts/telemetry absent. New authors seed required state; they do not stamp verdicts. (See § The audit-state.json Sidecar.)skill-metadata-protocol/SKILL_METADATA_PROTOCOL.md § Inline field comments — the authoring convention):> **TEMPLATE NOTE:** body blockquote and every YAML comment line beginning with # TEMPLATE NOTE:. These are scaffolding about the template itself — never field semantics. Shipping them in a derived skill is the most common authoring mistake.TEMPLATE NOTE: prefix and read like # subject: primary browse shelf — what the skill teaches. followed by the enum values. They are co-located documentation, so the derived skill's frontmatter stays self-explanatory to readers and cold-start agents.Verification (both must hold):
grep -n "TEMPLATE NOTE" skills/<your-skill>/SKILL.md returns zero hits — scaffolding stripped.grep -c "^\s*#" skills/<your-skill>/SKILL.md returns a count similar to the template's (roughly 30-50 depending on which optional fields you kept) — field-purpose comments preserved. Do not strip all comments just to shorten the file.node scripts/skill-lint.js skills/<your-skill> first (must show 0 errors), then the checks that match the surfaces you changed — node scripts/check-protocol-consistency.js for protocol-tier changes, the routing-eval harness for asserted examples/anti-examples, drift record/check for local truth sources, and export verification when the skill targets a plain SKILL.md consumer.Pick body sections from the skill's intent and expected use, not from the retired type archetype axis. Because the body is progressive-disclosure tier 2 (loaded only when the skill is active), design it for the agent that is already working in this domain — not for a router (tier 1) and not for occasional reference lookups (tier 3, which belong in references/).
| Skill intent | Use when | Body sections to include |
|---|---|---|
| Teaches a reusable capability | The user may jump to the section they need | ## Coverage, a model/stance section, decision tables or recipes, ## Verification, ## Do NOT Use When |
| Orchestrates a sequence | The agent must follow steps in order every time | ## Coverage, ## Workflow with numbered steps, checkpoints, failure handling, ## Verification, ## Do NOT Use When |
| Routes between skills | The task is choosing the owner skill or surfacing coverage gaps | ## Coverage, ## Routing Rules, examples/anti-examples, relation semantics, ## Verification, ## Do NOT Use When |
| Specializes a broader skill | The skill narrows a parent discipline for one project, stack, or domain | ## Coverage, the override rules, relation/grounding notes, inherited boundaries, ## Verification, ## Do NOT Use When |
| Wraps a tool or API | The agent must call a tool safely and repeatably | ## Coverage, prerequisites, the command/API contract, error handling, permissions, examples, ## Verification, ## Do NOT Use When |
The fastest way to pick wrong is to let an old archetype name drive the body. Current v8 classification tells where the skill belongs and where it deploys; the body still has to be designed for how the agent will use the instruction.
For high-precision, codebase-fingerprint activation, a project-anchored skill can declare these optional fields. Omit them for a portable principle-grounded skill — they narrow when a skill should fire and are noise when there is no real constraint to encode.
| Field | Representative values | Use when |
|---|---|---|
project_adoption_stage | legacy, current-standard, experimental-migration, deprecated | The skill's guidance depends on the project's lifecycle posture for the pattern it teaches. |
codebase_layer | api, ui, database, infrastructure, tests | The skill applies to one architectural layer, not the whole repo. |
applicable_tasks | debugging, refactoring, code-generation, code-review | The skill is relevant to a specific task intent rather than any task. |
environment | browser, node, edge, ios, android | The skill's instructions are environment-specific. |
internal_tools | e.g. acme-deploy-cli, internal-auth-proxy | The skill only applies where a named internal tool/script is present. |
dependencies | required packages/frameworks | The skill assumes a specific package is in the project. |
Do not collapse discovery, activation, boundary, scope, and teaching into one field. Each layer serves a different consumer:
| Layer | Field or section | Owns |
|---|---|---|
| Discovery summary | description | Compact statement of what the skill is about and the first use case a minimal runtime needs to see. |
| Fuzzy activation | keywords | Phrases users actually type. Keep to the v8 cap (≤ 10); no keyword stuffing. |
| Positive/negative prompts | examples, anti_examples | Realistic routing evidence and hard negatives. |
| Project/codebase fit | dependencies, paths, codebase_layer, applicable_tasks, environment, internal_tools, project_adoption_stage | Deterministic routing filters for package presence, file ownership, architecture layer, task intent, runtime context, internal tooling, or lifecycle state. |
| Scope summary | scope | Frontmatter-level in/out statement for readers and tools scanning metadata. |
| Ownership exclusion | relations.suppresses | Directional routing exclusion when this skill wins. Ownership wording, not "defer to X." |
| Teaching map | ## Coverage | Body-level list of distinct topics the agent learns after activation. |
| Procedure | Workflow/checklist sections | What the agent actually does. |
description and ## Coverage look like duplicates and are not. description (≤ 3 sentences guideline, ≤ 1024 chars hard limit, frontmatter) is the routing contract — pushy, specific, boundary-aware, read at startup (tier 1), so its budget is the tightest in the whole skill; include an explicit "Do NOT use for…" clause so the router doesn't over-activate. ## Coverage (bulleted list, body, tier 2, paid only on activation) is the scope map — it enumerates the distinct topics the skill teaches and must not restate description as a single line or read as a checklist of placeholder commitments. If you can drop your description into ## Coverage without changing meaning, both layers are wrong: rewrite description until it is too pushy for the body, then rewrite ## Coverage until it is too enumerative for the description. The two ceilings on description apply at once — the ≤ 3-sentence guideline is a routing-quality heuristic (longer descriptions dilute the activation signal), while ≤ 1024 characters is a hard export limit enforced at the marketplace layer; satisfy the hard limit first, then tighten for routing quality.
Routing-eval honesty — the pre-flip command. A new skill starts at routing_eval: absent in the sidecar. Flip it to present only after the routing harness exits 0 on the skill's own examples + anti_examples. Run the pre-flip check without --only-asserted:
node bin/skill-graph.js routing-eval --skill <name>Do not add --only-asserted to the pre-flip run. The harness resolves the --skill <name> target first (scripts/skill-graph-routing-eval.js:544 — target.filter(s => s.name === skillFilter)); --only-asserted then prunes any skill not already marked routing_eval: present (:545). A skill still at absent survives name resolution but is then pruned to an empty set, which triggers the skill "<name>" not found in manifest error and exit 1 (:547-548). So --only-asserted is for the ongoing gated/CI run after the skill is asserted — never for pre-flip verification.
| Mistake | Symptom | Fix |
|---|---|---|
| Placeholder sludge | description: "Use when... for...", paths like your/file.md, todo markers | Search for your-, path/to/, todo, lorem, and the source-template name. Zero hits before commit unless cited deliberately. |
| Name/folder mismatch | Skill silently fails to load; the router never sees it | name must be lowercase-kebab, ≤ 64 chars, not start/end with a hyphen, and exactly equal the parent directory name. Rename folder and name together. skill-lint.js checks alignment. |
| Missing sidecar | SKILL.md exists with no sibling audit-state.json | Seed the sidecar with the 7 required honest defaults before lint/review. |
| Sidecar state in frontmatter | schema_version / eval_state / routing_eval / drift_check / Audit Status verdicts written into SKILL.md | Those fields live in audit-state.json (ADR-0019). Frontmatter carries only agent-facing fields. (See § The audit-state.json Sidecar.) |
| Sidecar copy fraud | A new skill's audit-state.json carries eval_state: passing, copied verdicts, telemetry, scores, or false freshness dates | Reset to new-skill defaults; verdicts and telemetry are receipts for the skill that earned them, not template content. |
| Cargo-culted teaching layer | > **TEMPLATE NOTE:** blocks survive into the derived skill | grep -n "TEMPLATE NOTE" skills/<name>/SKILL.md returns nothing. |
| Comment over-strip | The derived skill has no frontmatter comments at all | Restore field-purpose comments above retained fields; only TEMPLATE NOTE lines/blockquotes are scaffold. |
| Description-Coverage collapse | description, scope, and ## Coverage say the same thing in different shapes | Rewrite each layer for its consumer: discovery summary, in/out statement, body topic map. |
| Activation-surface collapse | All triggers, hard negatives, and exclusions are packed into description | Move fuzzy terms to keywords, prompt cases to examples/anti_examples, ownership exclusions to relations.suppresses. |
| Generic-keyword filler | keywords: ["ai","tool","help"] or examples omitted entirely | Use specific domain vocabulary and exact phrases from realistic user prompts; recall depends on it. |
| Relation dumping | related: has 15 vague items; edges are untyped; suppresses: is empty where it should own a boundary | Type edges explicitly; use suppresses (with {skill, reason}) for ownership boundaries; avoid generic adjacency sprawl. |
| Shallow transcription | The body lists what (facts/data) but never why/when (the expert judgment) | Encode the judgment and context an expert would apply, not just the data an agent could already look up. |
| Project-fit field omission | A framework, layer, task type, environment, internal tool, or lifecycle state is required but only implied in prose | Add the appropriate optional field: dependencies, codebase_layer, applicable_tasks, environment, internal_tools, or project_adoption_stage. |
| Description over the hard limit | Export check fails even though lint-in-editor looked fine | Keep description ≤ 1024 chars. If the canonical description must stay long, add an EXPORT_DESCRIPTION_OVERRIDES entry rather than shortening the source. |
Hand-written metadata: nesting | Author types the nested Agent-Skills export shape (or JSON-stringified grounding) into a new skill's source | Author the flat protocol-native shape (top-level keys); the nested metadata: block is generated by the exporter. |
| Reference dump in the body | A 200+ line spec/table inlined into a tier-2 body the agent rarely needs | Move it to references/<topic>.md (tier 3, loaded on demand) and link from the body. |
| Native creator overtrust | A generated skill is committed without schema, privacy, sidecar, relation, and routing checks | Treat native creator output as a draft; run the local authoring gates before commit. |
| Inflated routing_eval | routing_eval: present set without running the harness | Default to absent in audit-state.json. Flip only after node bin/skill-graph.js routing-eval --skill <name> (no --only-asserted) returns PASS on the skill's own cases. |
| Stale protocol version | Sidecar schema_version: 7 paired with retired schema names, old concept-block advice, or the deprecated audit_verdict aggregate | Update truth sources, protocol labels, Understanding fields, Audit Status fields, and migration notes together. |
| Retired archetype language | New skill guidance asks for type: capability / workflow / router / overlay | Replace with v8 subject, optional subjects[], public, free-text scope, and body structure chosen by intent. |
| Dangling relation targets | A relations.* edge points to a skill not in the library (note: anti_examples are prompt strings and need no matching skill — only relation targets are skill names that must exist) | Point every relations.* edge at an existing sibling skill, or author that skill first. |
| Unprovenanced URL grounding | grounding.truth_sources contains a bare external URL with no reason or fetch/verification route | Use an object entry with path and note; treat it as external-unhashed until the URL is fetched or otherwise verified. |
| Tool privilege creep | allowed-tools includes write or shell tools for an instruction-only skill | Reduce to the minimum target-runtime tools, or omit when the runtime does not honor it. |
| Lint-skipped commit | A new skill is committed without focused lint | Run node scripts/skill-lint.js skills/<name> before every commit; fix all errors. |
Use this checklist as the authoring gate before committing a skill. Every item must pass.
SKILL.md and a sibling audit-state.json.name is lowercase-kebab, ≤ 64 chars, does not start/end with a hyphen, and matches the parent directory exactly.subject, optional subjects[], public, scope, taxonomy_domain, and project[] are true under current v8 semantics; subject is one of the twelve closed values.dependencies, paths, codebase_layer, applicable_tasks, environment, internal_tools, project_adoption_stage) are present only when they encode a real routing or lifecycle constraint.schema_version, version, owner, freshness, drift_check, eval_*, routing_eval, comprehension_state, portability, lifecycle, runtime_telemetry, the four verdicts) appears in SKILL.md frontmatter.audit-state.json has the 7 required seed fields and no copied verdicts, telemetry, scores, or false freshness claims; verdict/telemetry fields are absent until a real run writes them.description, scope, keywords, examples, anti_examples, project-fit fields, relations.suppresses, and ## Coverage each serve their own layer (no collapse).description: is ≤ 3 sentences (guideline), ≤ 1024 characters (hard limit), contains pushy trigger phrases, and names an explicit negative boundary.## Coverage is a scope map of distinct topics, not a one-line restate of the description.keywords and examples reflect actual user vocabulary, avoiding generic filler terms; anti_examples cover near-miss queries and are paired with relations.suppresses where they mark a confusable boundary.references/, not inlined in the body.public reflects the truth: true only if the body and references carry no private data; false otherwise (fail-safe). Public/private review found no secrets, personal/customer/financial data, private operational details, or unprovenanced outbound URLs/images in a public: true skill.drift_check (in the sidecar) is an object with last_verified; local truth_source_hashes are recorded only when the drift tool can compute them, while URL truth sources remain explicit, external-unhashed, and separately fetched/verified when treated as truth-certified.comprehension_state: present in the sidecar) or omitted entirely.compatibility is an object (not a free-text string) and valid for the target runtime/export shape when present.allowed-tools is minimal and matches the body; no skill grants tools just because the source template had them.metadata: Agent-Skills export shape (or JSON-stringified grounding) was hand-authored into the source — the exporter generates it.eval_artifacts, eval_state, routing_eval in audit-state.json reflect the actual skill state — no inflation.relations.* entry points to a skill that exists in the target repo; suppresses entries use the {skill, reason} form with an ownership reason.your-skill-name, path/to/file, todo, source-template name) remains.> **TEMPLATE NOTE:** blockquotes or # TEMPLATE NOTE: YAML comments remain — scaffolding fully stripped (grep -n "TEMPLATE NOTE" skills/<name>/SKILL.md returns zero hits).grep -c "^\s*#" skills/<name>/SKILL.md is roughly the same magnitude as the template's, not zero.node scripts/skill-lint.js skills/<name> returns 0 errors against the new skill.node scripts/check-protocol-consistency.js passes when protocol-tier docs, schema, sample, or manifest behavior changed.routing_eval: present, the pre-flip run node bin/skill-graph.js routing-eval --skill <name> (without --only-asserted) returned verdict PASS on the skill's own examples and anti-examples.note and a recorded fetch/verification route before it is treated as truth-certified.| Use instead | When |
|---|---|
| Direct documentation work | Writing general technical documentation (guides, tutorials, references) — not a skill specifically. |
refactor | Modifying an existing skill's content while preserving its identity. |
skill-infrastructure | Auditing the metadata health, manifests, drift, or export parity of skills already in the library. |
skill-router | Diagnosing why a router does or does not activate an existing skill for a request. |
best-practice | Running a broad final-pass quality check across an already-authored skill or other artifact. |
code-review | Reviewing the technical correctness, safety, or maintainability of a skill's domain content once authored. |
skill-metadata-protocol/SKILL_METADATA_PROTOCOL.md § Inline field comments — the authoring convention — the field-purpose-comment vs TEMPLATE NOTE distinction this skill enforces.examples/skill-metadata-template.md — the canonical specimen this skill teaches authors to derive from (flat protocol-native shape).examples/skill-audit-state-template.md — the audit-state.json sidecar seed and full field guidance.docs/adr/0019-audit-state-sidecar-separation.md — why audit/eval/provenance state lives in the sidecar, not frontmatter.docs/adr/0020-twelve-shelf-competency-reaxis.md — the twelve closed subject shelves the classifier picks from.AGENTS.md § Public Distribution — Canonical URL Contract — the export/encoding doctrine (flat source → generated nested metadata:).github.com/anthropics/skills (and the directory specs at agentskills.io/specification, developers.openai.com/codex/skills, code.claude.com/docs/en/skills, opencode.ai/docs/skills/) — the base SKILL.md format the Skill Metadata Protocol extends; source for the three-tier progressive-disclosure model, the name/description base contract, the metadata extension channel, and per-runtime recognized-field behavior. (Provenance: upstream standard the protocol adopts, confirmed in `CLAUDE.md`/`AGENTS.md`; runtime/spec detail verified via the public Agent Skills and vendor skill docs, June 2026. Treat each external URL as external-unhashed until fetched/verified.)<!-- skill-graph-context:start (generated — do not edit by hand) -->
Classification
agent-opstrueagent/skill-systemWhen to use
Not for
skill-routerskill-infrastructureRelated skills
best-practice, methodical, no-cutting-cornersnaming-conventions, refactor, best-practice, methodical, no-cutting-corners, context-engineeringConcept
Grounding
hybridexamples/skill-metadata-template.md, examples/skill-audit-state-template.md, skill-metadata-protocol/SKILL_METADATA_PROTOCOL.md, schemas/SKILL_METADATA_PROTOCOL_schema.json, schemas/skill-audit-state.schema.json, skill-metadata-protocol/field-reference.md, docs/adr/0019-audit-state-sidecar-separation.md, docs/adr/0020-twelve-shelf-competency-reaxis.md, https://agentskills.io/specification, https://developers.openai.com/codex/skills, https://code.claude.com/docs/en/skills, https://opencode.ai/docs/skills/Keywords
skill authoring, new skill, writing a skill, skill scaffold, skill template, audit-state sidecar, skill frontmatter, v8 classification, description vs coverage, routing eval<!-- skill-graph-context:end -->
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.