
# SKILL.md Unified Strict Standard

**Status:** Normative  
**Version:** 2.0.0  
**Sources synthesized:** Agent Skills spec (agentskills.io), anthropics/skills, anthropics/claude-code plugin-dev, openai/skills, github/awesome-copilot, Mintlify, Skills Directory, Geeksfino/openskills, addyosmani/agent-skills  
**Scope:** Cross-host portable core (Claude Code, Codex CLI, GitHub Copilot CLI, OpenClaw, compatible hosts)

---

## 1. Executive Summary

This document defines a single, maximally strict specification for `SKILL.md` bundles, synthesized from all major skill ecosystem implementations and deep-research outputs across multiple AI providers. The portable profile is intentionally narrower than the full ecosystem because the source corpus agrees on the core artifact model — directory-scoped skill, required `SKILL.md`, YAML frontmatter plus Markdown body, progressive disclosure, and optional bundled resources — but diverges on frontmatter breadth, host-specific runtime controls, install/discovery paths, and metadata overlays.

The result is a **closed portable core** with exactly two required frontmatter fields (`name` and `description`), a canonical root layout, a fixed body section order, a deterministic 9-stage validation pipeline, and a mandatory overlay boundary. This is the strictest rule set that remains compatible with the shared open spec, Anthropic product docs, OpenAI product docs, and GitHub product docs without relying on host-specific semantics such as Claude Code frontmatter extensions, Codex `agents/openai.yaml`, or GitHub CLI provenance injection.

All best practices identified across the source corpus are elevated to mandatory requirements unless they provably break parsing or cross-host compatibility in a major runtime.

---

## 2. Source Model & Priority

### 2.1 Inclusion criteria

A rule is included in this standard only if all of the following are true:

1. The rule is explicit in a cited source or is a necessary inference from multiple cited sources.
2. The rule is machine-testable.
3. The rule applies to the skill artifact itself: `SKILL.md`, bundled files, or deterministic validation/release behavior.
4. The rule does not depend on undocumented host behavior.
5. If the rule is not in the portable intersection, it is classified as overlay-only or `UNKNOWN`, not silently promoted into the core.

### 2.2 What counts as breaking compatibility

A rule **breaks compatibility** if any major documented runtime would, for the same bundle, do at least one of the following:

- reject parsing or discovery;
- assign materially different execution meaning to the same field;
- require different frontmatter contents for correct operation;
- mutate `SKILL.md` in a way that invalidates the portable core;
- require host-specific install/discovery location knowledge inside the bundle;
- require host-specific runtime semantics (tool preapproval, subagents, injected metadata) to preserve core meaning.

### 2.3 Source priority

| Priority | Source                                                     | Role                            |
| -------- | ---------------------------------------------------------- | ------------------------------- |
| 1        | Agent Skills Specification (agentskills.io/specification)  | Canonical cross-platform format |
| 2        | Anthropic Platform Docs (platform.claude.com)              | Platform-specific constraints   |
| 3        | Anthropic Skills Repository (github.com/anthropics/skills) | Reference implementation        |
| 4        | OpenAI Skills (developers.openai.com, github.com/openai)   | Cross-platform compatibility    |
| 5        | GitHub Copilot (github.com/github/awesome-copilot)         | Cross-platform compatibility    |
| 6        | Mintlify Blog (mintlify.com)                               | Community guidance              |
| 7        | Skills Directory (skillsdirectory.com)                     | Community guidance              |
| 8        | Geeksfino/openskills, addyosmani/agent-skills              | Community implementations       |

Where sources conflict, the higher-ranked source wins. Where a higher-ranked source is silent and a lower-ranked source specifies a rule, the rule is adopted if it does not break compatibility.

### 2.4 Source registry with snapshot dates

The following table is the reproducible registry of sources used to derive this standard. Snapshots were captured on 2026-04-24.

| URL                                                                                                        | Class                     | Role in conclusion                                           |
| ---------------------------------------------------------------------------------------------------------- | ------------------------- | ------------------------------------------------------------ |
| `https://agentskills.io/specification`                                                                     | official                  | Normative core of the format                                 |
| `https://agentskills.io/home`                                                                              | official                  | Progressive disclosure model and base structure              |
| `https://github.com/anthropics/skills/blob/main/spec/agent-skills-spec.md`                                 | official redirect         | Confirms the spec moved to agentskills.io                    |
| `https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview`                               | official                  | Anthropic runtime model                                      |
| `https://github.com/anthropics/skills`                                                                     | official                  | Anthropic reference repository                               |
| `https://github.com/anthropics/skills/blob/main/skills/skill-creator/SKILL.md`                             | official                  | Authoring, eval loop, optional `compatibility`               |
| `https://github.com/anthropics/claude-code/blob/main/plugins/plugin-dev/skills/skill-development/SKILL.md` | official                  | Claude-specific strict authoring style                       |
| `https://developers.openai.com/api/docs/guides/tools-skills`                                               | official                  | Hosted API validation, upload limits, bundle rules           |
| `https://github.com/openai/skills`                                                                         | official                  | Codex skill catalog / distribution model                     |
| `https://github.com/openai/skills/blob/main/skills/.system/skill-creator/SKILL.md`                         | official                  | Codex authoring guidance, `agents/openai.yaml`               |
| `https://github.com/github/awesome-copilot/blob/main/docs/README.skills.md`                                | official/community hybrid | GitHub community catalog conventions                         |
| `https://github.com/github/awesome-copilot`                                                                | official/community hybrid | GitHub distribution ecosystem                                |
| `https://www.mintlify.com/blog/skill-md`                                                                   | vendor blog               | Web discovery profile `/.well-known/skills/default/skill.md` |
| `https://www.skillsdirectory.com/docs/skill-md-format`                                                     | community docs            | Alternative fields and body structure                        |
| `https://github.com/Geeksfino/openskills`                                                                  | community runtime         | Syntactic compatibility claim with Claude skills             |
| `https://github.com/addyosmani/agent-skills`                                                               | community pack            | Strict engineering patterns for content design               |

Evidence priority: **agentskills.io → Anthropic docs/repos → OpenAI docs/repos → GitHub docs/blog → vendor/community sources**.

### 2.5 Extraction categories

The source corpus yields rules in five categories: syntax/schema (frontmatter fields, name/description constraints, YAML structure); structure/layout (directory shape, optional resource folders, file references, install/discovery locations); authoring guidance (imperative style, concise descriptions, examples, templates, gotchas, verification); runtime behavior (progressive disclosure, automatic invocation from `description`, host-specific injection/approval behavior); and validation/limits (name/description caps, under-500-line body, one-level references, evaluation/testing guidance).

---

## 3. Consensus vs Conflicts

### 3.1 Consensus (all sources agree)

All cited sources consistently agree on the following:

- A skill is a directory-level artifact with a required root `SKILL.md`.
- `SKILL.md` is YAML frontmatter followed by Markdown instructions.
- `name` and `description` are the core discovery fields; both are required.
- Progressive disclosure is fundamental: metadata loaded first, body on activation, resources on demand.
- The common portable resource directories are `scripts/`, `references/`, and `assets/`.
- The main `SKILL.md` must remain short; the hard boundary repeated in the official corpus is 500 lines.
- The `description` must say both **what** the skill does and **when** it should trigger.
- Real testing matters: syntax validation alone is not sufficient for a production skill.

### 3.2 Conflict resolution table

| ID    | Conflict                                                             | Sources                                                                                         | Decision                                                                          | Justification                                                                                                        |
| ----- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| CR-01 | Reserved words in `name`                                             | Spec: silent; Anthropic: forbids `anthropic`, `claude`                                          | Adopt Anthropic's restriction                                                     | Prevents namespace collision in the dominant runtime; harmless elsewhere                                             |
| CR-02 | XML tags forbidden in `name`/`description`                           | Spec: silent; Anthropic: forbids XML tags                                                       | Adopt Anthropic's restriction                                                     | Prevents injection; strict is safer                                                                                  |
| CR-03 | `name` must match parent directory                                   | Spec: requires; Anthropic API: not applicable (uploaded)                                        | Conditional: enforce for filesystem skills; skip for API-uploaded skills          | Filesystem skills need this for discovery; API skills are identified by `skill_id`                                   |
| CR-04 | Optional frontmatter fields (`license`, `compatibility`, etc.)       | Spec: defines them; Anthropic docs: only `name`/`description`                                   | Exclude from portable core; treat as overlay-eligible optional fields             | OpenAI official skill-creator says not to include other YAML fields; conflict makes them unsafe in the portable core |
| CR-05 | `allowed-tools` type and semantics                                   | Spec: space-separated string, experimental; GitHub: string or string[], auto-approval semantics | Exclude from portable core; document as overlay-only                              | Type and behavior differ across runtimes; cannot be included without breaking compatibility or semantic drift        |
| CR-06 | GitHub-specific flags (`user-invocable`, `disable-model-invocation`) | GitHub CLI only                                                                                 | GitHub-only overlay; not part of canonical `SKILL.md`                             | Not present in spec, Anthropic, or OpenAI; would break portability if included                                       |
| CR-07 | Community fields (`version`, `author`, `tags`, `requires`)           | Skills Directory; not in spec                                                                   | Exclude from core; move to `metadata` or companion docs if needed                 | Community-only docs are insufficient authority for portable core                                                     |
| CR-08 | Description voice: imperative vs third-person                        | Agent Skills: imperative; Anthropic: third-person                                               | Adopt third-person: `This skill should be used when…`                             | Anthropic docs explicitly warn that non-third-person voice hurts discovery                                           |
| CR-09 | Frontmatter optional vs required                                     | GitHub Copilot SDK: optional; spec/Anthropic/OpenAI/GitHub CLI: required                        | Mandatory frontmatter with both `name` and `description`                          | Stricter rule; compatible with all major runtimes; fallback-to-directory-name remains a runtime convenience only     |
| CR-10 | Web `skill.md` vs bundle directory                                   | Mintlify: web discovery artifact; runtimes: local folder                                        | Exclude web `skill.md` from runtime core; treat as a separate publication profile | Different deployment model; cannot be combined without breaking runtime expectations                                 |
| CR-11 | Body length limits                                                   | Multiple sources                                                                                | 500 lines hard boundary; additionally ≤ ~5000 tokens                              | Consistent with spec, Anthropic, and OpenAI                                                                          |
| CR-12 | Duplicate-name semantics                                             | Codex vs GitHub CLI differ                                                                      | Globally unique skill name per discovery scope is mandatory                       | Avoids nondeterminism in resolution order                                                                            |

---

## 4. Final Unified Specification

### 4.1 Scope

This specification defines a **portable core** and a **host overlay boundary**. A skill is portable-core compliant only if it passes Sections 5–8 with no reliance on host-specific fields, host-specific discovery paths, host-specific prompt placement, or host-specific execution policy.

### 4.2 Core model

A portable skill:

1. **MUST** be a single directory whose basename exactly equals the frontmatter `name` (filesystem skills).
2. **MUST** contain exactly one root file named `SKILL.md`. Case variants (`skill.md`, `Skill.md`) **MUST NOT** exist.
3. **MUST** begin `SKILL.md` with YAML frontmatter followed by a Markdown body.
4. **MUST** contain only `name` and `description` in the portable core frontmatter.
5. **MUST** treat `description` as the sole authoritative trigger surface for automatic invocation.
6. **MUST** use only the shared resource model: `scripts/`, `references/`, `assets/`.
7. **MUST** keep all portable file references relative, one level deep from the skill root, using forward slashes only.
8. **MUST** keep `SKILL.md` at or below 500 normalized lines.
9. **MUST** write all instructions in imperative or infinitive form.
10. **MUST NOT** rely on host-only fields or overlays to preserve its core meaning.

### 4.3 Overlay system

1. **Core first**: validate the portable core alone.
2. **Overlay second**: apply one host overlay per target host.
3. **No semantic override**: overlays **MUST NOT** change core `name`, core `description`, or core body meaning.
4. **Additive only**: overlays may add host UI metadata, discovery/install settings, invocation policy, tool dependency declarations, or host execution controls.
5. **Derived artifact rule**: if a host can express extensions only by mutating `SKILL.md` frontmatter, the mutated file is a **host build artifact**, not the portable source of truth.

The only officially documented in-bundle overlay file in the corpus is `agents/openai.yaml` for Codex. This standard reserves `agents/` as the overlay namespace. All other overlay filenames are host-specific and out of portable-core scope.

---

### 4.4 Terminology and artifact model

A **skill** is a self-contained directory bundle that teaches an agent a reusable capability. The bundle is not merely a prompt fragment: it is a portable instructional artifact with optional scripts, references, and assets that can be loaded progressively by compatible hosts.

A **portable core skill** is the minimum cross-host bundle that should parse and preserve meaning across documented runtimes. It contains a root `SKILL.md`, only portable frontmatter, Markdown instructions, and optional portable resource directories.

A **host overlay** is any host-specific metadata, runtime configuration, UI hint, approval model, provenance field, or installation detail that is useful for a specific ecosystem but not part of the portable core.

A **release artifact** is the distributable skill bundle after validation, trigger testing, script checks, reference checks, and overlay separation. It should not contain authoring-only files unless those files are part of a documented host overlay.

A **publication profile** is a way to expose skill-like content outside the runtime bundle itself, such as a web-discovery `skill.md`. Publication profiles can describe or advertise a skill, but they do not redefine the portable runtime bundle.

The standard deliberately separates these concepts because the source corpus uses the same word, “skill,” for several related but distinct things: runtime bundles, authoring templates, marketplace packages, web-discovery documents, and host-specific plugin resources.

### 4.5 Conformance profiles

This standard uses profiles to separate the minimum portable runtime contract from stricter authoring, release, and host-extension requirements. Profiles are cumulative unless stated otherwise.

#### Profile P0 — Portable Runtime Core

P0 is the smallest profile a runtime can reliably consume without knowing any specific host implementation.

A P0 skill MUST:

- be a directory containing exactly one `SKILL.md` at the skill root;
- have valid YAML frontmatter;
- provide at least `name` and `description` in frontmatter;
- keep the portable frontmatter free from host-specific metadata;
- keep all referenced files inside the skill root;
- avoid symlinks, hidden files, and unsafe path traversal;
- be understandable from `SKILL.md` alone;
- place optional supporting material in portable directories such as `scripts/`, `references/`, and `assets/`.

A P0 runtime MAY ignore all files except `SKILL.md`, but if it does use supporting files, it MUST resolve them relative to the skill root.

#### Profile P1 — Strict Authoring Profile

P1 is the recommended profile for authored skills that should be readable, reviewable, and reusable across runtimes.

A P1 skill SHOULD:

- follow the canonical section order;
- provide clear activation/trigger language in the description and body;
- document preconditions, defaults, workflow, decision logic, output format, gotchas, boundaries, verification, and examples;
- use stable relative paths for supporting files;
- avoid time-sensitive claims unless they are explicitly scoped;
- avoid machine-specific assumptions unless they are marked as local examples;
- provide enough context for a model to decide when not to use the skill.

P1 is stricter than the minimum runtime core but still portable.

#### Profile P2 — Release-Ready Profile

P2 is the profile for skills intended for distribution, registry publication, team reuse, or production-like usage.

A P2 skill MUST satisfy P0 and SHOULD satisfy P1. It additionally requires release evidence:

- validation report;
- trigger tests;
- at least one positive example and one negative example;
- script execution evidence if scripts are included;
- resource-size review for assets and references;
- compatibility notes for claimed hosts;
- version/change notes if distributed through a registry or repository.

P2 does not mean the skill is universally safe. It means the author has supplied enough evidence for a reviewer or registry to evaluate it.

#### Profile H — Host Overlay Profile

Profile H covers host-specific extensions, generated artifacts, local runtime configuration, and compatibility glue.

Host overlays MAY contain:

- host manifests;
- registry metadata;
- permissions or tool allowlists;
- install hooks;
- model/runtime preferences;
- generated indexes;
- IDE or CLI integration files;
- evaluation metadata specific to a platform.

Host overlays MUST NOT mutate the portable semantic meaning of the skill. A host may adapt packaging, discovery, and execution metadata, but the portable core remains the canonical source of human/model instructions.

## 5. Frontmatter Schema

### 5.1 Portable core (source of truth)

```yaml
---
name: skill-name
description: This skill should be used when… [capability clause and explicit trigger clause].
---
```

The portable core requires exactly `name` and `description`. No other keys are permitted.

### 5.2 Allowlist (portable core)

| Field         | Status   | Type   | Constraint                                                                                                            |
| ------------- | -------- | ------ | --------------------------------------------------------------------------------------------------------------------- |
| `name`        | REQUIRED | string | 1–64 chars; matches `^[a-z0-9]+(?:-[a-z0-9]+)*$`; matches parent directory name; no `<>`; not `anthropic` or `claude` |
| `description` | REQUIRED | string | 10–1024 chars; third-person; no `<>`; contains capability clause + explicit trigger token                             |

### 5.3 Denylist (portable core MUST NOT contain)

The portable core frontmatter **MUST NOT** contain any of the following keys: `license`, `compatibility`, `metadata`, `allowed-tools`, `version`, `author`, `tags`, `requires`, `when_to_use`, `argument-hint`, `arguments`, `disable-model-invocation`, `user-invocable`, `context`, `agent`, `hooks`, `paths`, `shell`, any provenance keys injected by host tooling, or any unknown top-level key.

### 5.3a Unknown fields policy

Any frontmatter key not in the portable core allowlist **MUST** be treated as a validation WARNING, not a FAIL. Runtimes **MUST** ignore unknown keys to preserve forward compatibility. Validators **MUST** report them so authors are aware. Authors **SHOULD NOT** include undocumented fields in the portable source `SKILL.md`; if a host requires additional fields, they belong in a host build artifact or an overlay file.

### 5.4 Optional fields (overlay-eligible)

These fields are valid in host build artifacts and host-specific overlays, but **MUST NOT** appear in the portable source `SKILL.md`:

| Field                      | Type            | Constraint                                                       | Classification            |
| -------------------------- | --------------- | ---------------------------------------------------------------- | ------------------------- |
| `license`                  | string          | Short license identifier or reference to bundled license file    | Optional overlay field    |
| `compatibility`            | string          | 1–500 chars; real env/product/runtime requirements only          | Optional overlay field    |
| `metadata`                 | map<string,str> | String keys and string values only; no nested maps or lists      | Optional overlay field    |
| `allowed-tools`            | string          | Space-separated tool identifiers; type conflicts with GitHub CLI | Experimental overlay only |
| `user-invocable`           | bool            | GitHub CLI only                                                  | GitHub overlay only       |
| `disable-model-invocation` | bool            | GitHub CLI only                                                  | GitHub overlay only       |

### 5.5 Field constraints

`name` **MUST** satisfy all of:

- length 1–64;
- matches `^[a-z0-9]+(?:-[a-z0-9]+)*$` (lowercase, digits, single hyphens as separators);
- no leading or trailing hyphen;
- no consecutive hyphens (`--`);
- exact match to the parent directory basename (filesystem skills);
- no XML/HTML tags (`<`, `>`);
- not equal to `anthropic` or `claude` (case-insensitive).

`description` **MUST** satisfy all of:

- length 10–1024;
- single-line string;
- non-empty after trimming;
- no XML/HTML tags;
- third-person form;
- contains both a capability clause and an explicit trigger token from the set: `Use when`, `Use this when`, `Use this skill when`, `Use whenever`, `Trigger when`, `Trigger whenever`.

### 5.6 Regex definitions

```
NAME_REGEX        = ^[a-z0-9]+(?:-[a-z0-9]+)*$
NO_XML_TAG_REGEX  = </?[A-Za-z][^>]*>
TRIGGER_TOKEN     = (Use when|Use this when|Use this skill when|Use whenever|Trigger when|Trigger whenever)
PATH_REGEX        = ^(scripts|references|assets)/[A-Za-z0-9][A-Za-z0-9._-]*$
```

### 5.7a Formal YAML schema

The following machine-readable schema defines all validation constraints for the portable core frontmatter. This is the authoritative reference for implementing a conformant validator.

```yaml
# SKILL.md Portable Core Frontmatter Schema
# Version: 2.0.0

name:
  type: string
  required: true
  minLength: 1
  maxLength: 64
  pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$"
  forbiddenSubstring: "--"
  forbiddenValues:
    - "anthropic" # case-insensitive
    - "claude" # case-insensitive
  forbiddenChars: ["<", ">"]
  mustMatchParentDir: true # conditional: filesystem skills only

description:
  type: string
  required: true
  minLength: 10
  maxLength: 1024
  forbiddenChars: ["<", ">"]
  mustContainTriggerToken: true
  # Recognized trigger tokens:
  # "Use when", "Use this when", "Use this skill when",
  # "Use whenever", "Trigger when", "Trigger whenever"

additionalProperties: false
# Any key not listed above is a WARNING (runtimes MUST ignore; validators MUST report)
```

### 5.8 YAML restrictions

The portable core frontmatter **MUST** be a single YAML mapping with exactly two scalar string values. Multiline scalars, nested mappings, lists, anchors, aliases, merge keys, and tags are forbidden in the portable core.

---

### 5.9 Source-field mapping and preservation notes

The broader source corpus contains several fields that are valid or documented in at least one ecosystem but unsafe in the closed portable core. They are preserved here as a mapping so implementers do not accidentally treat omission from the core as loss of information.

| Field or construct                     | Seen in source family                  | Portable-core status          | Correct handling                                                                                           |
| -------------------------------------- | -------------------------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `license`                              | Agent Skills, GitHub-oriented examples | Overlay/release metadata      | Prefer root `LICENSE.txt` for distribution; keep out of portable frontmatter                               |
| `compatibility`                        | Anthropic skill-creator guidance       | Overlay/release metadata      | Record in release manifest or host overlay unless targeting only compatible hosts                          |
| `metadata`                             | Agent Skills extension mechanism       | Overlay metadata              | Use namespaced overlay keys; do not rely on runtime semantics                                              |
| `allowed-tools`                        | Agent Skills experimental field        | Experimental overlay          | Treat as advisory unless the host explicitly enforces it                                                   |
| `version`                              | Claude Code plugin-dev examples        | Release metadata only         | Use release manifest; never require core runtimes to parse it                                              |
| `author`                               | Community catalogs                     | Release metadata only         | Use package metadata or catalog entry                                                                      |
| `tags`                                 | Community catalogs                     | Discovery metadata only       | Use registry/catalog metadata                                                                              |
| `requires` / dependencies              | Community/runtime-specific examples    | Overlay or `## Preconditions` | Express user-visible requirements in `## Preconditions`; host-specific dependency logic belongs in overlay |
| `user-invocable`                       | GitHub/Copilot-related conventions     | Host overlay                  | Do not put in portable core                                                                                |
| `disable-model-invocation`             | GitHub/Copilot-related conventions     | Host overlay                  | Do not put in portable core                                                                                |
| `agents/openai.yaml`                   | OpenAI/Codex skill ecosystem           | OpenAI overlay                | Keep under host overlay or clearly mark as OpenAI-specific                                                 |
| `/.well-known/skills/default/skill.md` | Mintlify web-discovery profile         | Publication profile           | Treat as discoverability metadata, not a runtime bundle layout                                             |

Unknown keys are never silently accepted as portable. A strict validator must report them. A runtime may ignore them, but an authoring or release gate should either remove them or move them into a documented overlay.

## 6. Filesystem Layout

### 6.1 Canonical structure

```text
<skill-name>/
├── SKILL.md                   # REQUIRED
├── LICENSE.txt                # optional
├── scripts/                   # optional: executable code
│   └── <file>                 # self-contained; documented dependencies
├── references/                # optional: supplementary documentation
│   └── <file>                 # one level only; TOC required if >100 lines
├── assets/                    # optional: static resources, templates
│   └── <file>                 # max 5 MB per file
└── agents/                    # optional: overlay namespace only
    └── openai.yaml            # Codex overlay (OpenAI-specific)
```

### 6.2 Root allowlist

Portable-core root entries: required `SKILL.md`; optional `LICENSE.txt`, `scripts/`, `references/`, `assets/`, `agents/`. Any other top-level file or directory **MUST FAIL** portable-core validation. This explicitly excludes `README.md`, `CHANGELOG.md`, `templates/`, `examples/`, `evals/`, and `tests/` from the portable bundle root.

Rationale for excluding `README.md`: agents may hallucinate reading `README.md` instead of `SKILL.md`, causing context window bloat and incorrect behavior. Any documentation that would go into a README **MUST** be placed in `SKILL.md` or `references/`.

Rationale for excluding `examples/` and `evals/`: these are valid authoring-time artifacts and may exist in the author's working directory, but they are not part of the distributed portable bundle.

### 6.3 Directory constraints

| Constraint          | Rule                                                                                                |
| ------------------- | --------------------------------------------------------------------------------------------------- |
| Root directory name | MUST exactly match `name` field in frontmatter (filesystem skills)                                  |
| `SKILL.md` location | MUST be at the root of the skill directory                                                          |
| `SKILL.md` filename | MUST be exactly `SKILL.md` (case-sensitive)                                                         |
| Reference depth     | File references from `SKILL.md` MUST be exactly one level deep; nested subdirectories are forbidden |
| Reference chains    | Cascading reference chains (A→B→C) are forbidden                                                    |
| `scripts/` contents | Each script MUST be self-contained or clearly document its dependencies                             |
| Asset file size     | Files inside `assets/` MUST NOT exceed 5 MB per file                                                |

### 6.4 Path rules

Portable path references **MUST** satisfy all of: forward slashes only; no `..`; no absolute paths; no Windows drive prefixes; exactly one path segment after the core directory name; target file must exist; path matches `^(scripts|references|assets)/[A-Za-z0-9][A-Za-z0-9._-]*$`.

### 6.5 Low-level portability rules

- All text files in the portable core **MUST** be UTF-8.
- UTF-8 BOM **MUST FAIL**.
- `CRLF` line endings are accepted but normalized to `LF` before validation; bare `CR` **MUST FAIL**.
- Symlinks **MUST FAIL** in the portable core.
- Hidden files and hidden directories inside the skill root **MUST FAIL**.
- Case-insensitive filename collisions **MUST FAIL**.

---

### 6.6 Directory-specific rules

#### `scripts/`

The `scripts/` directory is for executable or importable helpers that materially improve reliability, repeatability, or deterministic processing. A script should be included only when the body instructions alone are insufficient or would cause fragile manual work.

Rules:

- scripts must be referenced from `SKILL.md` or from a referenced document;
- scripts must use relative paths and must not assume a global installation path;
- scripts must fail with non-zero exit status on unrecoverable error;
- scripts should expose clear CLI usage and deterministic output;
- scripts should avoid network access unless the skill explicitly documents that requirement;
- scripts must not require credentials unless the preconditions and host permission model explicitly cover them.

#### `references/`

The `references/` directory is for detailed material that should not be loaded into the model context unless needed: domain rules, long examples, schemas, compatibility tables, checklists, or procedural manuals.

Rules:

- each referenced document must have a clear reason to exist;
- `SKILL.md` must explain when to read each reference;
- reference files should be short enough to load selectively;
- large reference files should contain a table of contents;
- references must not contradict the root `SKILL.md`.

#### `assets/`

The `assets/` directory is for non-instructional resources such as templates, sample inputs, images, schemas, generated fixtures, or static files used by scripts.

Rules:

- assets should be named descriptively;
- generated or bulky assets should be excluded unless required for execution;
- asset formats should be portable and documented;
- binary assets should be small enough for the target host upload/runtime limits.

#### `agents/` and other overlay directories

Host-specific directories are allowed only as overlays. They must not be required to understand the portable skill body. If a host-specific file changes runtime behavior, the portable core must still be valid without it, or the package must be explicitly labeled as host-specific rather than portable.

## 7. Content Rules

### 7.1 Mandatory section order

The Markdown body of `SKILL.md` **MUST** contain these headings in this exact order:

```
# <Human-Readable Title>
## Purpose
## Preconditions
## Defaults
## Workflow
## Decision Logic
## Supporting Files
## Output Format
## Gotchas
## Boundaries
## Verification
## Examples
```

If a section is not applicable, its content **MUST** be exactly `NONE`.

### 7.2 Section rules

- `# <Human-Readable Title>`: one line only; matches or closely reflects the `name` field.
- `## Purpose`: one paragraph stating scope and task outcome; **MUST NOT** introduce trigger criteria absent from `description`.
- `## Preconditions`: bullet list of required tools, packages, files, credentials, or environment assumptions; otherwise `NONE`. Dependencies belong here because `compatibility` is excluded from the portable core.
- `## Defaults`: states which option or mode applies when the user does not specify; mandatory when any choice point exists; the "default instead of menu" rule.
- `## Workflow`: numbered list; each step **MUST** start with an imperative verb. Steps that execute scripts **MUST** name the exact `scripts/<file>` path.
- `## Decision Logic`: a Markdown table with exact columns `Condition | Action | Default`. Exactly one row **MUST** mark `Default` as `YES`. If there is no branching, the single row is `All cases | Follow Workflow | YES`.
- `## Supporting Files`: bullet list in the form `- path — purpose — load condition`, or `NONE`. Every referenced bundled file **MUST** appear here exactly once.
- `## Output Format`: a fenced template or explicit prose schema. If no fixed structure exists, write exactly `No fixed output format.` Templates are mandatory where output structure matters.
- `## Gotchas`: bullet list or `NONE`. Every bullet **MUST** start with `- **Never**`, `- **Always**`, or `- **Do not**`. Non-obvious pitfalls and tribal knowledge belong here.
- `## Boundaries`: explicit list of unsupported cases, forbidden operations, or hard limits. `NONE` only if truly unlimited. This prevents the agent from attempting impossible actions.
- `## Verification`: checklist format only; every item **MUST** start with `- [ ]`. States measurable completion criteria. Mandatory; cannot be `NONE`.
- `## Examples`: exactly two subsections, `### In Scope` and `### Out of Scope`. `In Scope` shows a valid triggering example; `Out of Scope` shows a reject or non-triggering case.

### 7.3 Authoring rules

1. Instructional prose in `Workflow`, `Decision Logic`, `Gotchas`, and `Verification` **MUST** use imperative or infinitive form. Sentences in those sections **MUST NOT** begin with `You` or `Your`.
2. `description` and introductory prose **MUST** use third-person form (`This skill should be used when…`).
3. Terminology **MUST** be consistent throughout the file. The same concept **MUST NOT** be renamed across sections.
4. Unqualified time-sensitive words — `today`, `tomorrow`, `currently`, `latest`, `recent`, `newest` — **MUST NOT** appear unless the same sentence includes an ISO date (`YYYY-MM-DD`).
5. Machine-specific paths, Windows-style paths, and hardcoded user-home paths **MUST NOT** appear in portable instructions.
6. If multiple frameworks, products, or domains are supported, `SKILL.md` **MUST** route to separate `references/<file>` variants rather than embedding all variant detail in the body.
7. If a reference file exceeds 100 lines, it **MUST** include a table of contents within its first 20 lines.
8. If a reference file exceeds 10,000 words, the `## Supporting Files` entry **MUST** include a search hint in backticks.
9. The body **MUST NOT** contain setup notes about how the skill was authored, tested, or published.

### 7.4 Trigger semantics

Automatic invocation authority is defined solely by frontmatter `description`. `Purpose`, `Examples`, and any other body text are secondary documentation and **MUST NOT** broaden or contradict the trigger boundary in `description`. If there is any contradiction, `description` wins and the skill **FAILS** validation.

### 7.5 Error-prevention patterns

| Gotcha                   | Prevention                                                                                                         |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| Frontmatter not parsed   | MUST start with `---` on line 1, end with `---` on its own line; no content before opening `---`                   |
| YAML parse errors        | All string values containing special YAML characters (`:`, `#`, `{`, `}`, `[`, `]`, `&`, `*`, etc.) MUST be quoted |
| `metadata` value types   | All metadata values MUST be strings; numeric values MUST be quoted                                                 |
| Name/directory mismatch  | Validator MUST check that directory name matches `name` field for filesystem skills                                |
| Reserved word collision  | Validator MUST reject `name` values of `anthropic` or `claude` (case-insensitive)                                  |
| XML injection            | Validator MUST reject `<` or `>` in `name` or `description`                                                        |
| Consecutive hyphens      | Validator MUST reject `--` in `name`                                                                               |
| Empty description        | Validator MUST reject descriptions that are empty after trimming                                                   |
| Circular file references | Validator SHOULD detect and warn on circular reference chains                                                      |
| Vague description        | Validator MUST warn if description is < 10 characters or lacks a recognized trigger token                          |

---

### 7.6 Progressive disclosure rules

The root `SKILL.md` is the activation and routing layer, not a dumping ground. It should contain enough information for the agent to decide what to do, what to read next, and how to produce a correct output. Detailed reference material should be moved into `references/`, reusable operations into `scripts/`, and static supporting material into `assets/`.

A good root body answers these questions quickly:

1. What capability does this skill provide?
2. When should it activate?
3. What are the safe defaults?
4. What workflow should the agent follow?
5. What files should the agent load only under specific conditions?
6. What must the final answer contain?
7. What mistakes must be avoided?
8. How can the output be verified?

Progressive disclosure fails when `SKILL.md` is so large that activation itself consumes too much context, or when the root body is so vague that the agent cannot know which reference or script to load.

### 7.7 Description authoring rules

The description is the primary routing signal. It must be more than a short label. It should include capability, trigger conditions, and enough keywords to support semantic matching.

Preferred portable pattern:

```text
This skill should be used when the user asks to <task>, <related task>, or <trigger context>, especially when <specific condition>.
```

Acceptable variants:

```text
Use this skill when the user asks to <task>...
```

```text
Use whenever the user mentions <domain>, even if they do not explicitly ask for <exact term>.
```

The source corpus disagrees on grammatical person. Some official guidance frames the description as an instruction to the agent (“Use this skill when…”), while Claude Code plugin-dev examples often prefer third-person phrasing (“This skill should be used when…”). This standard permits both, but the stricter house style is third-person because it avoids accidental direct user-facing wording and works well as metadata.

Bad descriptions:

```text
Helps with PDFs.
```

```text
Useful for data.
```

```text
This skill contains scripts and references.
```

Good descriptions:

```text
This skill should be used when the user asks to extract text or tables from PDFs, fill PDF forms, merge PDF files, or debug PDF document-processing failures.
```

```text
This skill should be used when the user asks to review a database migration, inspect table relationships, validate schema changes, or identify downstream PostgreSQL compatibility risks.
```

### 7.8 Content scope rules

The root body should not include long background essays, full API references, large code listings, full benchmark reports, or exhaustive domain manuals. Those belong in references or external documentation. The root body should include operationally necessary instruction: defaults, decision logic, workflow, output contract, gotchas, verification, and examples.

The skill must not overclaim. If a skill only reviews API contracts, it should not imply it can generate clients, deploy services, or execute migrations. Boundaries are part of the specification because they reduce unsafe or irrelevant activation.

### 7.9 Portability clarifications for sensitive content classes

#### Time-sensitive content

Skills SHOULD avoid embedding facts that decay quickly, such as current pricing, current API limits, current model rankings, live legal requirements, dependency versions, or hosted-service UI paths.

If time-sensitive content is unavoidable, the skill SHOULD:

- state the date or version context;
- describe how to verify freshness;
- avoid presenting stale examples as normative requirements;
- prefer procedures for checking current truth over hard-coded claims.

Bad pattern:

```markdown
Use model X because it is currently the best coding model.
```

Better pattern:

```markdown
Select the coding model from the configured model policy. If no policy exists, compare currently available models using the project evaluation harness before changing defaults.
```

#### Machine-specific content

Portable skills MUST NOT depend on one author's local paths, usernames, shells, package managers, editor configuration, API keys, hostnames, private repositories, or environment variables unless those details are explicitly marked as examples or moved to host/local overlays.

Bad pattern:

```markdown
Run `/Users/alice/dev/project/scripts/build.sh`.
```

Better pattern:

```markdown
Run `scripts/build.sh` from the skill root, or use the host overlay to map this step to a local project path.
```

#### Terminology consistency

A skill SHOULD use one term consistently for each concept. For example, avoid mixing `skill`, `agent skill`, `plugin`, `workflow`, and `tool pack` unless the distinction matters.

Recommended usage:

- `skill` — the portable instruction bundle;
- `host` — the runtime, IDE, CLI, registry, or agent platform consuming the skill;
- `overlay` — host-specific metadata outside the portable core;
- `supporting file` — scripts, references, assets, schemas, templates, or examples referenced by the skill.

#### Visual and document workflows

Skills for PDFs, documents, slides, images, spreadsheets, and visual inspection SHOULD explicitly say when the model must inspect rendered output rather than relying only on extracted text.

For example, a PDF skill SHOULD distinguish:

- text extraction;
- page rendering;
- table inspection;
- figure/chart inspection;
- OCR fallback;
- citation or source anchoring.

#### Safety and permissions

Portable skills SHOULD express required capabilities abstractly rather than binding them to a particular product permission model.

Good pattern:

```markdown
Requires permission to read repository files and run local validation commands.
```

Overlay-specific policy can then map that requirement to an actual tool allowlist or permission grant.

## 8. Validation Model

Validation is a deterministic **PASS/FAIL** pipeline. A stage that produces FAIL stops the pipeline.

### Stage 0 — normalization

1. Resolve the skill directory path.
2. Reject symlinks anywhere in the portable core.
3. Decode `SKILL.md` and all referenced text files as UTF-8; reject BOM.
4. Normalize `CRLF` to `LF`; reject bare `CR`.
5. Build a case-insensitive inventory of all root entries; reject collisions.

### Stage 1 — root inventory

```
Is SKILL.md present at root?                                → FAIL if no
Is exactly one SKILL.md present?                            → FAIL if more than one
Are there any disallowed root entries?                      → FAIL if yes
Are there any symlinks?                                     → FAIL if yes
Are there any hidden files or directories?                  → FAIL if yes
```

### Stage 2 — frontmatter parse

```
Does SKILL.md start with "---" on line 1?                   → FAIL if no
Does SKILL.md contain a closing "---"?                      → FAIL if no
Is content between "---" delimiters valid YAML?             → FAIL if no
Is the frontmatter a mapping (not a list or scalar)?        → FAIL if no
```

### Stage 3 — required field check

```
Is `name` present?                                          → FAIL if no
Is `name` a string?                                         → FAIL if no
Does `name` match NAME_REGEX?                               → FAIL if no
Does `name` contain "--"?                                   → FAIL if yes
Is `name` case-insensitively "anthropic" or "claude"?       → FAIL if yes
Does `name` contain "<" or ">"?                             → FAIL if yes
Is 1 ≤ len(name) ≤ 64?                                      → FAIL if no
Is `description` present?                                   → FAIL if no
Is `description` a string?                                  → FAIL if no
Is 10 ≤ len(description.trim()) ≤ 1024?                     → FAIL if no
Does `description` contain "<" or ">"?                      → FAIL if yes
```

### Stage 4 — denylist check

```
Does frontmatter contain any key not in {name, description}? → FAIL if yes
```

### Stage 5 — directory name consistency (filesystem skills only)

```
Does basename(skill-dir) == name?                           → FAIL if no
```

### Stage 6 — body check

```
Is there content after the closing "---"?                   → WARN if no
Is body ≤ 500 lines?                                        → WARN if exceeds
Are all mandatory sections present in correct order?        → WARN for each missing section
Are all mandatory sections with content either prose/list or "NONE"? → WARN if not
Does `## Verification` contain at least one "- [ ]" item?  → WARN if not
Does `## Decision Logic` contain a row with "YES"?          → WARN if not
```

### Stage 7 — path check

```
Do any referenced file paths fail PATH_REGEX?               → FAIL if yes
Do any referenced files not exist on disk?                  → WARN if yes
Are any reference paths more than one level deep?           → FAIL if yes
Are there circular reference chains?                        → WARN if yes
```

### Stage 8 — trigger quality check

```
Does `description` contain a recognized trigger token?      → WARN if no
Is `description` ≥ 10 characters (after trim)?              → FAIL if no
Does `description` appear self-contradictory vs body?       → WARN if detected
```

### 8.1 PASS/FAIL summary table

| Check                         | PASS condition                                          | FAIL condition                    |
| ----------------------------- | ------------------------------------------------------- | --------------------------------- |
| `SKILL.md` exists             | File found at `<skill-dir>/SKILL.md`                    | File not found                    |
| Frontmatter delimiters        | Exactly 2 `---` lines; line 1 opening; separate closing | Missing, misordered, or extra     |
| YAML validity                 | YAML parser produces a mapping                          | Parser throws error               |
| `name` present                | Key exists                                              | Key missing                       |
| `name` pattern                | Matches `NAME_REGEX`                                    | Does not match                    |
| `name` no consecutive hyphens | Does not contain `--`                                   | Contains `--`                     |
| `name` not reserved           | Case-insensitive match against reserved set fails       | Matches reserved word             |
| `name` no XML                 | Does not contain `<` or `>`                             | Contains `<` or `>`               |
| `name` length                 | 1 ≤ len ≤ 64                                            | len < 1 or len > 64               |
| `description` present         | Key exists                                              | Key missing                       |
| `description` non-empty       | Trimmed length ≥ 10                                     | Trimmed length < 10               |
| `description` length          | 10 ≤ len ≤ 1024                                         | len < 10 or len > 1024            |
| `description` no XML          | Does not contain `<` or `>`                             | Contains `<` or `>`               |
| No extra frontmatter keys     | Only `name` and `description` present                   | Any other key present             |
| Directory match               | `basename(skill-dir) == name`                           | Mismatch (filesystem skills only) |
| Reference depth               | Path matches `PATH_REGEX`                               | Deeper than one level             |

### 8.3 Bash-operational validation commands

The following commands can be run directly in the skill directory to operationalize the pipeline. Each returns non-zero or non-empty output on failure.

```bash
# Stage 5: directory name matches frontmatter name
[ "$(basename "$PWD")" = "$(grep '^name:' SKILL.md | head -1 | awk '{print $2}')" ] || echo "FAIL: name/dir mismatch"

# Stage 6a: no extraneous root files (README, CHANGELOG, INSTALL)
ls | grep -E -i '^(README|CHANGELOG|INSTALL)' && echo "FAIL: extraneous root files found"

# Stage 6b: body line count
[ "$(wc -l < SKILL.md)" -le 500 ] || echo "WARN: body exceeds 500 lines"

# Stage 6c: body has at least one H1 heading
grep -q '^# ' SKILL.md || echo "WARN: no H1 heading found"

# Stage 7a: asset files over 5 MB
find assets/ -type f -size +5M 2>/dev/null && echo "FAIL: asset exceeds 5 MB"

# Stage 7b: nested subdirectories in references/
find references/ -mindepth 2 -type f 2>/dev/null && echo "FAIL: references/ has nested files"

# Stage 7c: nested subdirectories in scripts/
find scripts/ -mindepth 2 -type f 2>/dev/null && echo "FAIL: scripts/ has nested files"

# Stage 0: no symlinks anywhere in portable core
find . -maxdepth 3 -type l 2>/dev/null && echo "FAIL: symlinks present"

# Stage 0: no hidden files or directories
find . -maxdepth 2 -name '.*' ! -name '.' 2>/dev/null && echo "FAIL: hidden files present"
```

All commands returning empty output and exit code 0 indicate the corresponding check passed.

### 8.4 WARNING conditions (non-blocking)

| Check                      | WARN condition                                                         |
| -------------------------- | ---------------------------------------------------------------------- |
| Body length                | Body exceeds 500 lines                                                 |
| Body tokens                | Body exceeds ~5000 tokens                                              |
| Missing mandatory sections | Any mandatory section absent or out of order                           |
| Missing trigger token      | `description` lacks a recognized trigger token from the canonical set  |
| Missing referenced file    | Referenced file does not exist                                         |
| Circular references        | Reference chain forms a cycle                                          |
| Vague description          | Description < 50 characters or lacks specific trigger keywords         |
| Missing verification items | `## Verification` does not contain at least one `- [ ]` item           |
| Missing decision default   | `## Decision Logic` table lacks a row with `YES` in the Default column |

---

### 8.5 Validation pseudocode

The following pseudocode is intentionally conservative. It is not the only valid implementation, but it preserves the major checks required by this standard.

```python
import re
from pathlib import Path

import yaml

NAME_RE = re.compile(r"^(?!.*--)[a-z0-9]([a-z0-9-]*[a-z0-9])?$")
CORE_KEYS = {"name", "description"}
ROOT_ALLOWLIST = {"SKILL.md", "LICENSE.txt", "scripts", "references", "assets", "agents", ".overlays"}


def validate(skill_dir: Path) -> list[Issue]:
    issues: list[Issue] = []
    skill_md = skill_dir / "SKILL.md"

    if not skill_md.exists():
        return [FAIL("SKILL.md not found")]
    if not skill_md.is_file():
        return [FAIL("SKILL.md is not a regular file")]

    for path in skill_dir.rglob("*"):
        rel = path.relative_to(skill_dir)
        if path.is_symlink():
            issues.append(FAIL(f"symlink not allowed: {rel}"))
        if any(part.startswith(".") and part not in {".overlays"} for part in rel.parts):
            issues.append(FAIL(f"hidden path not allowed in portable core: {rel}"))

    for item in skill_dir.iterdir():
        if item.name not in ROOT_ALLOWLIST:
            issues.append(FAIL(f"unexpected root item: {item.name}"))

    try:
        text = skill_md.read_text(encoding="utf-8")
    except UnicodeDecodeError:
        return [FAIL("SKILL.md is not valid UTF-8")]

    if text.startswith("\ufeff"):
        issues.append(FAIL("UTF-8 BOM is not allowed"))
    if "\r" in text:
        issues.append(FAIL("CRLF/CR line endings are not allowed"))
    if not text.startswith("---\n"):
        return [FAIL("SKILL.md must start with YAML frontmatter delimiter")]

    close = text.find("\n---\n", 4)
    if close == -1:
        return [FAIL("closing YAML frontmatter delimiter not found")]

    fm_text = text[4:close]
    body = text[close + 5:]

    try:
        frontmatter = yaml.safe_load(fm_text)
    except yaml.YAMLError as exc:
        return [FAIL(f"invalid YAML frontmatter: {exc}")]

    if not isinstance(frontmatter, dict):
        return [FAIL("frontmatter must be a mapping")]

    missing = CORE_KEYS - set(frontmatter)
    for key in sorted(missing):
        issues.append(FAIL(f"missing required frontmatter key: {key}"))

    unknown = set(frontmatter) - CORE_KEYS
    for key in sorted(unknown):
        issues.append(WARN(f"non-core frontmatter key should move to overlay: {key}"))

    name = frontmatter.get("name")
    description = frontmatter.get("description")

    if not isinstance(name, str) or not name.strip():
        issues.append(FAIL("name must be a non-empty string"))
    elif not (1 <= len(name) <= 64):
        issues.append(FAIL("name must be 1-64 characters"))
    elif not NAME_RE.fullmatch(name):
        issues.append(FAIL("name does not match portable regex"))
    elif skill_dir.name != name:
        issues.append(FAIL("skill directory name must match frontmatter name"))

    if not isinstance(description, str) or not description.strip():
        issues.append(FAIL("description must be a non-empty string"))
    elif not (1 <= len(description) <= 1024):
        issues.append(FAIL("description must be 1-1024 characters"))
    else:
        lowered = description.lower()
        if len(description) < 50:
            issues.append(WARN("description is likely too short for reliable routing"))
        if not any(token in lowered for token in ("when", "use", "asks", "mentions")):
            issues.append(WARN("description may lack trigger context"))

    if not body.strip():
        issues.append(FAIL("Markdown body is empty"))

    body_lines = body.splitlines()
    if len(body_lines) > 500:
        issues.append(FAIL("Markdown body exceeds 500 lines"))
    if len(body) // 4 > 5000:
        issues.append(WARN("Markdown body may exceed 5000 tokens"))

    for required_heading in (
        "## Purpose", "## Preconditions", "## Defaults", "## Workflow", "## Decision Logic",
        "## Supporting Files", "## Output Format", "## Gotchas", "## Boundaries",
        "## Verification", "## Examples",
    ):
        if required_heading not in body:
            issues.append(FAIL(f"missing mandatory body section: {required_heading}"))

    for match in re.finditer(r"\[[^\]]*\]\(([^)]+)\)", body):
        target = match.group(1).strip()
        if target.startswith(("http://", "https://", "mailto:")):
            continue
        if target.startswith(("/", "~", "..")):
            issues.append(FAIL(f"non-portable reference path: {target}"))
            continue
        resolved = (skill_dir / target).resolve()
        if not str(resolved).startswith(str(skill_dir.resolve())):
            issues.append(FAIL(f"reference escapes skill root: {target}"))
        elif not resolved.exists():
            issues.append(FAIL(f"referenced file does not exist: {target}"))

    return issues
```

### 8.6 Extended semantic validation stages

The deterministic validation stages above are the minimum strict validation pipeline. Release-quality validators SHOULD add semantic checks that catch skills that are syntactically valid but operationally weak.

#### Script validation

If `scripts/` exists, validators SHOULD check that:

- scripts are referenced from `SKILL.md` or clearly documented;
- executable scripts have the expected executable bit where the host supports it;
- scripts use portable interpreters where possible;
- scripts do not rely on absolute author-machine paths;
- scripts do not silently require secrets;
- scripts fail visibly when prerequisites are missing;
- scripts are small enough to audit or are accompanied by a clear reference explanation.

Script validation MUST distinguish between:

- portable helper scripts that are part of the skill;
- host installation scripts that belong in overlays;
- project-specific scripts that should remain outside the portable bundle.

#### Semantic lint

Semantic lint is non-deterministic or partially heuristic validation. It SHOULD produce warnings, not hard failures, unless a registry explicitly chooses a stricter profile.

Semantic lint SHOULD detect:

- vague descriptions that do not identify triggers;
- descriptions that are too broad and would over-activate;
- missing negative examples;
- missing boundaries;
- claims that depend on live external facts;
- references to unavailable local files;
- workflow steps that cannot be performed with declared capabilities;
- examples that contradict the stated boundaries;
- instructions that imply hidden host-specific permissions;
- duplicated content that inflates context without adding decision value.

Semantic lint is useful because skills are consumed by models, not only by parsers. A schema-valid skill can still be harmful if it teaches the model to activate at the wrong time, assume unavailable tools, or ignore verification.

#### Overlay boundary validation

Overlay boundary validation checks that host-specific material has not leaked into the portable core.

Validators SHOULD warn when portable `SKILL.md` contains:

- host names used as normative requirements rather than examples;
- IDE-specific commands as the only supported path;
- runtime-specific permission syntax;
- generated metadata;
- registry-only fields;
- local installation steps;
- private filesystem paths;
- environment-specific secrets or tokens;
- claims such as “works in host X” without corresponding overlay or test evidence.

Validators SHOULD also check that overlays do not contradict the portable core. For example, if the portable skill says scripts are optional but a host overlay makes script execution mandatory, that difference must be documented as host behavior rather than presented as portable truth.

## 9. Release Gate

A skill **MUST** pass all PASS/FAIL checks in §8.1 before release. A skill **SHOULD** pass all WARNING checks in §8.2. Syntactic validation alone is not sufficient.

### 9.1 Minimum evaluation requirements

| Eval type                        | Requirement                                                                    |
| -------------------------------- | ------------------------------------------------------------------------------ |
| Structural validation            | Pass all PASS/FAIL checks via `skills-ref validate` or equivalent              |
| Trigger accuracy (positive)      | Agent correctly activates the skill for ≥ 5 relevant prompts                   |
| Trigger accuracy (negative)      | Agent does NOT activate for ≥ 5 irrelevant prompts                             |
| Trigger accuracy (ambiguous)     | ≥ 3 borderline prompts documented with expected behavior                       |
| Instruction following            | Agent follows ≥ 90% of step-by-step instructions in the body                   |
| Edge case coverage               | Agent handles ≥ 3 documented edge cases correctly                              |
| Script execution (if `scripts/`) | Each script runs to completion without unhandled errors in a clean environment |

### 9.2 Verification model

```
1. Run structural validation (§8.1)          → MUST PASS all
2. Run warning checks (§8.2)                 → REVIEW each; accept or fix
3. Run trigger evals (positive + negative)   → MUST meet thresholds in §9.1
4. Run instruction-following evals           → MUST follow ≥ 90% of steps
5. Run script execution tests                → ALL scripts MUST complete without error
6. Run edge case tests                       → MUST handle ≥ 3 documented edge cases
7. Release
```

### 9.3 Trigger testing protocol

For each skill, define a trigger test set. Positive triggers (5+): prompts that SHOULD activate the skill. Negative triggers (5+): prompts that SHOULD NOT activate the skill. Ambiguous triggers (3+): borderline prompts with documented expected behavior. All positive triggers MUST activate. All negative triggers MUST NOT activate. Ambiguous triggers are documented, not required to pass.

### 9.4 Script execution guarantees

- Every script in `scripts/` MUST execute successfully in a clean environment matching the `## Preconditions` section.
- Scripts MUST produce deterministic output for deterministic input.
- Scripts MUST exit with code 0 on success and non-zero on failure.
- Scripts MUST include error messages on failure (no silent failures).
- Scripts MUST generate LLM-friendly standard output (truncate massive payloads, suppress irrelevant stack traces, provide explicit success/failure codes).

---

### 9.5 Required release evidence

A release candidate should include evidence, either in CI logs, release notes, or an external release manifest, that the following checks were performed:

| Evidence                         | Required for portable release | Notes                                            |
| -------------------------------- | ----------------------------- | ------------------------------------------------ |
| Frontmatter validation output    | MUST                          | Include parser, schema, and regex result         |
| Body structure validation output | MUST                          | Include required-heading and length checks       |
| Directory inventory              | MUST                          | Show root files and optional directories         |
| Broken-reference check           | MUST                          | Include missing file/link failures if any        |
| Script execution logs            | MUST if `scripts/` exists     | Include command, exit code, and sanitized output |
| Trigger evaluation set           | MUST                          | Include positive and negative trigger prompts    |
| Regression examples              | SHOULD                        | Useful when revising an existing skill           |
| Host overlay validation          | MUST if overlays exist        | Validate each claimed host separately            |
| Known limitations                | MUST                          | Include unresolved host/runtime uncertainty      |

A skill must not claim compatibility with a host unless either the host’s documented validator accepts the bundle or the release evidence explains the exact compatibility boundary.

### 9.6 Host-compatibility claims

Compatibility claims must be precise. Avoid labels like “works everywhere” unless the artifact is limited to the portable core and has no hidden host assumptions.

Recommended labels:

- `portable-core`: uses only `name`, `description`, Markdown body, and portable resource directories;
- `openai-overlay`: includes OpenAI-specific overlay files or release metadata;
- `claude-overlay`: includes Claude-specific authoring or plugin metadata;
- `github-overlay`: includes GitHub/Copilot-specific metadata or catalog conventions;
- `web-discovery-profile`: intended for publication/discovery, not necessarily a runtime bundle.

A package can include multiple overlays, but each overlay must be separable from the portable core.

## 10. Overlay System

### 10.1 Portable core vs host-specific overlays

**Portable core** (MUST work on all hosts):

- `SKILL.md` with only `name` and `description` in frontmatter
- `scripts/`, `references/`, `assets/` contents using portable conventions
- All file paths using forward slashes, one level deep

**Host-specific overlays** (outside the portable bundle or in `agents/`):

```
<skill-name>/
├── SKILL.md                    # Portable core
├── scripts/                    # Portable
├── references/                 # Portable
├── assets/                     # Portable
└── agents/
    └── openai.yaml             # Codex: interface, policy, dependencies
```

GitHub CLI mutations (`allowed-tools`, `user-invocable`, `disable-model-invocation`) are permitted only in GitHub-specific build artifacts, not in the portable source `SKILL.md`.

### 10.2 Separation rules

| Portable (in `SKILL.md`)    | Host-specific overlay (outside core)                 |
| --------------------------- | ---------------------------------------------------- |
| `name`, `description`       | UI display names, colors, icons, provenance metadata |
| Core instructions           | Host-specific tool integrations and preapprovals     |
| Generic trigger description | Host-specific command bindings                       |
| Standard scripts            | Host-optimized script variants                       |
| `scripts/`, `references/`   | `agents/openai.yaml`, GitHub CLI knobs               |

### 10.3 Migration table

| Source profile                         | What to change                                                                                 | Result                             |
| -------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------- |
| agentskills / Anthropic minimal        | Verify reserved words, XML tags, 500 lines, one-level refs, mandatory sections                 | Already close to portable core     |
| OpenAI/Codex skill                     | Keep `name`/`description`; move `agents/openai.yaml` to overlay; remove extra top-level fields | Portable core + OpenAI overlay     |
| OpenAI API hosted skill bundle         | Guarantee exactly one `SKILL.md`, one top-level folder in zip, size limits                     | Hosted-compatible package          |
| GitHub CLI skill                       | Move `user-invocable`, `disable-model-invocation`, `allowed-tools` out of source `SKILL.md`    | Cross-host source + GitHub overlay |
| GitHub Copilot SDK without frontmatter | Add mandatory YAML frontmatter; do not rely on directory-name fallback                         | Portable strict skill              |
| Skills Directory style                 | Remove top-level `version`, `author`, `tags`, `requires`; move to overlay docs                 | Strict-core compatible             |
| Mintlify `skill.md`                    | Convert to folder skill with `SKILL.md`; keep web path only as a publish artifact              | Separate web-discovery profile     |
| Anthropic plugin-dev style             | Remove `version: 0.1.0` from top-level; remove `examples/` from bundle root                    | Claude-friendly and portable       |

---

### 10.4 Overlay manifest pattern

For projects that need rich metadata without polluting portable `SKILL.md`, use a release or overlay manifest outside the portable frontmatter. The exact filename is project-specific unless a host documents one. A conservative internal convention is:

```text
<skill-name>/
├── SKILL.md
├── references/
├── scripts/
├── assets/
└── .overlays/
    ├── release.yaml
    ├── openai/
    │   └── agents/openai.yaml
    ├── claude/
    │   └── manifest.yaml
    └── github/
        └── manifest.yaml
```

Example release manifest:

```yaml
schema_version: 1
skill_name: api-contract-review
version: 1.2.0
license: MIT
authors:
  - Example Team
compatibility:
  portable_core: true
  openai: tested
  claude: untested
  github: untested
evidence:
  frontmatter_validation: passed
  body_validation: passed
  trigger_eval: passed
  script_execution: passed
```

This manifest is not part of the portable runtime contract. It is packaging and release metadata. Validators may read it, but agents should not require it to understand the skill.

### 10.5 Recommended host overlay layout

A multi-host repository MAY use this layout:

```text
<skill-name>/
  SKILL.md
  scripts/
  references/
  assets/
  overlays/
    openai/
      manifest.yaml
      generated/
    github/
      manifest.yaml
      gh-skill.yaml
    claude-code/
      plugin.yaml
    openclaw/
      manifest.yaml
      policy.yaml
```

The exact overlay directory names are not normative. The boundary is normative: host-specific files live outside the portable root contract and cannot be required to understand the portable skill.

#### OpenAI/Codex overlay

An OpenAI/Codex overlay may contain packaging metadata, generated indexes, validation outputs, or runtime-specific declarations required by that host.

It MUST NOT introduce portable-frontmatter keys into `SKILL.md` merely because a host supports them. Host metadata belongs in the overlay unless it is also valid portable core metadata.

#### GitHub overlay

A GitHub overlay may contain `gh skill` metadata, repository publication metadata, CI validation workflows, or Copilot-specific packaging artifacts.

Repository metadata such as license, changelog, release workflow, and contribution policy belongs at repository level, not inside the portable skill bundle unless the skill itself explicitly needs that material as supporting reference content.

#### Claude Code overlay

A Claude Code or plugin-development overlay may include plugin manifests, command registration, install hooks, local runtime configuration, and permission declarations.

Plugin lifecycle mechanics should not be treated as portable skill requirements. The portable core describes what the model should know and do; the overlay describes how one host installs, discovers, grants, or executes it.

#### OpenClaw/custom runtime overlay

A custom runtime overlay may include:

- tool contracts;
- permission policies;
- routing metadata;
- trigger scoring hints;
- memory-suggestion policies;
- execution sandbox declarations;
- evaluation harness metadata;
- observability configuration.

These are valid host concerns, but they must remain separable from the portable instruction bundle.

## 11. Final Classification

### 11.1 Normative requirements (MUST)

1. `SKILL.md` MUST exist at the root of the skill directory.
2. Frontmatter MUST be valid YAML delimited by `---`.
3. Frontmatter MUST be a single mapping with exactly two keys: `name` and `description`.
4. `name` MUST be present, 1–64 characters, matching `NAME_REGEX`, no `--`, no `<>`, not reserved.
5. `description` MUST be present, 10–1024 characters, non-empty after trim, no `<>`, third-person.
6. `description` MUST contain a recognized trigger token.
7. For filesystem skills, directory name MUST match `name`.
8. Root MUST contain only allowlisted entries.
9. File references MUST use relative paths, one level deep, forward slashes.
10. Scripts MUST exit 0 on success, non-zero on failure, with error output on failure.
11. All text files MUST be UTF-8, no BOM, no bare CR.
12. `SKILL.md` MUST NOT contain references to host-specific fields in instructions.

### 11.2 Strong recommendations (SHOULD)

1. `description` SHOULD describe both capability and trigger, ≥ 50 characters, with specific keywords.
2. Body SHOULD be ≤ 500 lines and ≤ 5000 tokens.
3. All mandatory sections SHOULD be present in canonical order.
4. Reference files SHOULD be ≤ 1 level deep.
5. Reference files SHOULD include a table of contents if > 100 lines.
6. Scripts SHOULD be self-contained or clearly document dependencies.
7. Detailed reference material SHOULD be moved to separate files.

### 11.3 Optional (MAY)

1. `LICENSE.txt` MAY be present at root.
2. `scripts/`, `references/`, `assets/` directories MAY be present.
3. `agents/openai.yaml` MAY be present as an OpenAI-specific overlay.
4. Additional host-specific files MAY exist in `agents/` subdirectories.

### 11.4 Prohibited (MUST NOT)

1. `name` MUST NOT contain uppercase, underscores, spaces, or special characters beyond `a-z`, `0-9`, `-`.
2. `name` MUST NOT start or end with a hyphen.
3. `name` MUST NOT contain consecutive hyphens (`--`).
4. `name` MUST NOT be `anthropic` or `claude` (case-insensitive).
5. `name` and `description` MUST NOT contain `<` or `>`.
6. Frontmatter MUST NOT contain any key other than `name` and `description`.
7. Root MUST NOT contain `README.md`, `CHANGELOG.md`, `examples/`, `evals/`, `tests/`, `templates/` or any other non-allowlisted entry.
8. File reference chains MUST NOT exceed 1 hop (cascading references forbidden).
9. Scripts MUST NOT fail silently.
10. Symlinks MUST NOT appear in the portable core.

### 11.5 Element classification summary

| Element                                    | Classification                                           |
| ------------------------------------------ | -------------------------------------------------------- |
| `name`                                     | Required (portable core)                                 |
| `description`                              | Required (portable core)                                 |
| `license`                                  | Overlay-eligible optional field                          |
| `compatibility`                            | Overlay-eligible optional field                          |
| `metadata`                                 | Overlay-eligible optional field                          |
| `allowed-tools`                            | Experimental overlay only (type conflicts across hosts)  |
| `user-invocable`                           | GitHub overlay only                                      |
| `disable-model-invocation`                 | GitHub overlay only                                      |
| `version`, `author`, `tags`, `requires`    | Incompatible in core (move to overlay docs if needed)    |
| `scripts/`, `references/`, `assets/`       | Optional (portable core)                                 |
| `agents/openai.yaml`                       | Optional (OpenAI overlay)                                |
| `LICENSE.txt`                              | Optional (portable safe)                                 |
| `README.md`, `CHANGELOG.md`                | Forbidden at bundle root                                 |
| `examples/`, `evals/`, `tests/`            | Forbidden at bundle root (authoring-time artifacts only) |
| `templates/`                               | Forbidden at bundle root (move content to `assets/`)     |
| Web `/.well-known/skills/default/skill.md` | Separate publication profile, not a runtime bundle       |

---

### 11.6 Extended conflict log

The following conflict log preserves lower-level decisions from the source corpus. It is intentionally more detailed than the summary table because these conflicts are the areas where future authors are most likely to accidentally reintroduce non-portable behavior.

| Conflict                                    | Source divergence                                                                                       | Resolution                                                                                                          |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `name` required vs directory fallback       | Agent Skills requires `name`; some GitHub/Copilot-oriented material allows directory-name fallback      | `name` is required; directory fallback is host behavior and must not be relied on                                   |
| Extra frontmatter fields                    | Agent Skills permits several optional fields; OpenAI guidance is stricter                               | portable core is exactly `name` and `description`; extra fields move to overlay/release metadata                    |
| `metadata`                                  | Open spec allows arbitrary metadata; strict hosted guidance rejects extra frontmatter                   | overlay-only; no runtime meaning in portable core                                                                   |
| `compatibility`                             | Anthropic skill-creator guidance uses it; OpenAI strict guidance excludes it                            | release metadata or overlay-only                                                                                    |
| `license`                                   | Some specs allow frontmatter license; package repos often include license files                         | prefer `LICENSE.txt`; do not require frontmatter license for portability                                            |
| `version`                                   | Claude Code plugin-dev examples use version; core spec does not require it                              | release manifest only; not portable frontmatter                                                                     |
| Description person                          | Some guidance says “Use this skill when”; Claude-oriented examples say “This skill should be used when” | both parse; house style uses third-person; validators should check trigger semantics, not exact phrase only         |
| Body length                                 | Sources mention 500 lines, 5000 tokens, 1500-2000 words, or 3000 words                                  | hard portable limit is 500 lines; token/word targets are guidance unless a host enforces them                       |
| Mandatory body sections                     | Canonical spec allows flexible Markdown; strict authoring benefits from a fixed structure               | this standard requires fixed sections for strict profile; looser hosts may still accept less structure              |
| `README.md` at root                         | Common OSS convention; skill bundles rely on `SKILL.md` as root instruction file                        | forbidden in strict portable runtime bundle root; put long docs in `references/` or package docs outside the bundle |
| `examples/`, `tests/`, `evals/` directories | Useful for authoring; not common portable runtime directories                                           | authoring-time only unless documented as overlay; release evidence may live outside runtime bundle                  |
| `templates/` directory                      | Some projects use templates directly; portable corpus uses `assets/`                                    | put templates under `assets/` for runtime bundles                                                                   |
| `scripts/` execution                        | Hosts differ on sandboxing, permissions, and preapproval                                                | scripts may exist, but release must test them; runtime permission is host-specific                                  |
| File reference depth                        | Some examples use nested files; strict guidance favors shallow resources                                | root references should be one level deep when possible; deep nesting is warning or fail depending profile           |
| Web-discovery `skill.md`                    | Mintlify uses `/.well-known/.../skill.md`; runtime bundles use root `SKILL.md`                          | separate publication profile; do not conflate with runtime bundle                                                   |
| WASM/WASI skill runtimes                    | OpenSkills-like systems may compile executable components                                               | out of portable Markdown parsing scope; use overlay/runtime-specific packaging                                      |

## 12A. Packaging Model

### 12A.1 Portable bundle

A portable bundle is the smallest distributable unit that another runtime can consume without host-specific knowledge.

A portable bundle contains:

```text
<skill-name>/
  SKILL.md
  scripts/        # optional
  references/     # optional
  assets/         # optional
```

A portable bundle SHOULD NOT contain:

- repository-level documentation such as `README.md` or `CHANGELOG.md` unless explicitly allowed by a host profile;
- generated indexes;
- package-manager lockfiles;
- IDE configuration;
- host plugin manifests;
- local environment files;
- CI/CD workflow files;
- registry publication metadata.

Those files may exist in a source repository, but they are not part of the portable runtime bundle.

### 12A.2 Multi-skill repository

A multi-skill repository may contain many skills plus repository-level governance files.

Recommended structure:

```text
skills-repo/
  README.md
  CHANGELOG.md
  LICENSE
  skills/
    postgres-schema-audit/
      SKILL.md
    api-contract-review/
      SKILL.md
  overlays/
    github/
    openai/
    custom-runtime/
  validators/
  tests/
```

In this model, repository-level files are allowed because the repository is not itself a portable skill bundle. Export tooling SHOULD be able to materialize each portable bundle independently.

### 12A.3 Generated host artifacts

Generated host artifacts SHOULD be reproducible from the portable core and overlay metadata.

Generated artifacts include:

- compiled registries;
- embedding indexes;
- trigger indexes;
- host manifests;
- packaged archives;
- validation reports;
- generated documentation;
- runtime cache files.

Generated artifacts SHOULD NOT be treated as source of truth. If a generated artifact contradicts `SKILL.md`, the portable source wins unless the host explicitly documents the artifact as an override.

## 12B. Migration Guide

### 12B.1 From Agent Skills / Anthropic-style minimal skills

Keep the existing `SKILL.md` as the core artifact.

Recommended migration:

- ensure `name` and `description` exist in frontmatter;
- tighten the description so it clearly identifies activation triggers;
- add missing strict-authoring sections if targeting P1;
- move large examples or references into `references/`;
- move host-specific metadata into an overlay;
- run deterministic validation before publishing.

### 12B.2 From OpenAI/Codex skills

Use the existing skill body as the portable core when possible.

Recommended migration:

- preserve portable instruction content in `SKILL.md`;
- move OpenAI/Codex-specific packaging, registry, or runtime metadata into `overlays/openai/`;
- remove non-portable frontmatter keys from the portable frontmatter;
- keep generated artifacts outside the portable bundle;
- document compatibility claims with validation evidence.

### 12B.3 From GitHub CLI/Copilot skills

Recommended migration:

- preserve the skill instructions in `SKILL.md`;
- move GitHub-specific metadata to `overlays/github/`;
- keep repository-level docs at repository level;
- separate CLI packaging from portable model instructions;
- ensure examples do not assume GitHub unless the skill is intentionally GitHub-specific.

### 12B.4 From Claude Code plugin-development style

Claude Code plugin structures often mix command registration, tool permissions, lifecycle hooks, and instruction text.

Recommended migration:

- extract model-facing instructions into `SKILL.md`;
- move command registration and lifecycle metadata into `overlays/claude-code/`;
- move permission declarations into overlay policy files;
- keep portable examples independent of one local CLI installation;
- document any host-required behavior as host-specific.

### 12B.5 From Skills Directory / community catalog style

Community catalogs often include rich metadata, tags, categories, screenshots, examples, and ratings.

Recommended migration:

- keep only portable runtime metadata in frontmatter;
- move catalog metadata into registry or overlay files;
- preserve useful examples in `SKILL.md` or `references/`;
- preserve screenshots or diagrams in `assets/` only if they are needed for skill execution or explanation;
- do not confuse popularity metadata with runtime semantics.

### 12B.6 From Mintlify/web `skill.md`

A web-discovery `skill.md` is not equivalent to a portable agent skill bundle.

Recommended migration:

- treat web `skill.md` as discovery or documentation metadata;
- extract reusable agent instructions into a proper `SKILL.md` bundle;
- avoid assuming website navigation metadata is model-execution metadata;
- keep web publishing configuration outside the portable bundle;
- use `rel=alternate`, `llms.txt`, or site metadata as web-discovery mechanisms, not as the skill runtime contract.

## 12. Examples

### 12.1 Minimal portable skill

```markdown
---
name: postgres-schema-audit
description: This skill should be used when the user asks to inspect a PostgreSQL schema, trace table relationships, explain column usage, or validate migration impact across related tables.
---

# Postgres schema audit

## Purpose

Audit a PostgreSQL schema and explain structural impact before changing it.

## Preconditions

- psql CLI available and connected to target database

## Defaults

Use `psql` metadata queries first. Read `references/schema-conventions.md` only when naming or relationship rules are unclear.

## Workflow

1. Inspect tables, columns, indexes, constraints, and foreign keys.
2. Identify upstream and downstream dependencies.
3. State migration risks before proposing changes.
4. Produce a concise impact summary.

## Decision Logic

| Condition                | Action                          | Default |
| ------------------------ | ------------------------------- | ------- |
| Migration proposed       | Include rollback path in output | NO      |
| All cases (no migration) | Produce structural summary only | YES     |

## Supporting Files

- `references/schema-conventions.md` — naming conventions and relationship patterns — load when naming or relationship rules are ambiguous

## Output Format

Markdown report with sections: Affected Tables, Constraints, Migration Risks (if any), Rollback Concerns (if any).

## Gotchas

- **Do not** invent schema details not visible in the live schema or bundled references.
- **Always** apply `deleted_at IS NULL` filters when querying soft-deleted tables.
- **Never** assume historical tables use `_history`; they use `_archive`.

## Boundaries

- Does not execute migrations or DDL statements.
- Does not infer undocumented semantics from column names alone.

## Verification

- [ ] Output lists all affected tables by name.
- [ ] Output lists all affected constraints.
- [ ] If a migration is proposed, output includes at least one rollback concern.

## Examples

### In Scope

User: "What would break if I drop the `orders` table?"
Expected: Structural analysis identifying foreign keys, dependent views, and migration risks.

### Out of Scope

User: "Run the migration script."
Expected: Decline; this skill does not execute DDL.
```

### 12.2 Full strict skill with overlay

```markdown
---
name: api-contract-review
description: This skill should be used when the user asks to design, review, or change an API contract, compare request/response schemas, assess backward compatibility, or evaluate interface boundaries before implementation.
---

# API contract review

## Purpose

Review API contracts before implementation or release.

## Preconditions

- Access to OpenAPI or JSON Schema files
- A diff-capable shell environment

## Defaults

Use bundled schema references before proposing contract changes. Prefer backward-compatible changes. Prefer additive evolution over breaking mutation.

## Workflow

1. Read the current contract files.
2. Identify changed endpoints, fields, enums, and error shapes.
3. Classify each change as additive, behavior-changing, or breaking.
4. Check client impact, versioning impact, and migration impact.
5. Run `scripts/check_openapi_diff.py` to verify diff output.
6. Produce a decision with evidence.

## Decision Logic

| Condition                | Action                                           | Default |
| ------------------------ | ------------------------------------------------ | ------- |
| Breaking change detected | Name blast radius, migration path, rollback path | NO      |
| Additive change only     | Confirm backward compatibility and document      | YES     |

## Supporting Files

- `references/compatibility-rules.md` — versioning and compatibility policy — load when assessing backward compatibility
- `references/error-model.md` — canonical error semantics — load when evaluating error shape changes
- `scripts/check_openapi_diff.py` — structural diff helper — run in step 5

## Output Format
```

# API Contract Review

## Change Classification

...

## Affected Consumers

...

## Backward-Compatibility Assessment

...

## Migration Recommendation

...

## Unanswered Questions

...

```

## Gotchas
- **Do not** treat `nullable: true` and "field omitted" as equivalent.
- **Never** approve a breaking change without naming its blast radius.
- **Always** treat error-body shape changes as contract changes, even with identical HTTP status codes.
- **Do not** infer undocumented semantics from field names alone.

## Boundaries
- Does not execute schema migrations.
- Does not generate client code.
- Does not assess performance impact.

## Verification
- [ ] Output includes a change classification for each modified endpoint or field.
- [ ] Output names all affected consumers.
- [ ] Output includes a backward-compatibility assessment.
- [ ] Output includes a migration recommendation.
- [ ] Output lists explicit unanswered questions.

## Examples

### In Scope
User: "I'm adding a required field to the /orders POST body. Is that breaking?"
Expected: Classification as breaking, blast radius analysis, migration path suggestion.

### Out of Scope
User: "Generate a Python client for this API."
Expected: Decline; this skill reviews contracts, not generates clients.
```

**Corresponding layout:**

```text
api-contract-review/
├── SKILL.md
├── references/
│   ├── compatibility-rules.md
│   └── error-model.md
├── scripts/
│   └── check_openapi_diff.py
├── assets/
│   └── contract-template.yaml
└── agents/
    └── openai.yaml
```

### 12.3 PDF processing skill pattern

This example is preserved because it demonstrates a common non-code skill with scripts, references, fallback logic, and concrete gotchas.

```markdown
---
name: pdf-processing
description: This skill should be used when the user asks to extract text or tables from PDF files, fill PDF forms, merge PDF documents, debug scanned-document extraction, or work with PDF forms and OCR.
---

# PDF Processing

## Purpose

Process PDF documents reliably, including text extraction, table extraction, form inspection, form filling, OCR fallback, and merging.

## Preconditions

- Python PDF tooling is available in the target environment.
- OCR tooling is available before handling scanned PDFs.

## Defaults

Use direct text extraction first. Fall back to OCR only when direct extraction returns no useful text. Prefer deterministic scripts for form inspection and filling.

## Workflow

1. Inspect whether the PDF contains selectable text.
2. Extract text with a PDF parser when possible.
3. Detect scanned or image-only pages.
4. Use OCR fallback for scanned pages.
5. For forms, inspect fields before filling values.
6. Validate output by reopening the generated PDF or checking extracted text.

## Decision Logic

| Condition                               | Action                                     | Default |
| --------------------------------------- | ------------------------------------------ | ------- |
| `extract_text()` returns useful text    | Use direct extraction                      | YES     |
| text extraction returns empty or `None` | Use OCR fallback                           | NO      |
| PDF contains form fields                | Run field-inspection script before filling | YES     |
| merged cells break table extraction     | Use alternate table extractor              | NO      |

## Supporting Files

- `references/form-filling.md` — detailed form field mapping guide — read when filling multi-page forms.
- `references/ocr-guide.md` — OCR setup and language packs — read when direct extraction returns no useful text.
- `scripts/analyze_form.py` — extracts form field names and metadata.
- `scripts/fill_form.py` — fills fields from a values file and writes a new PDF.

## Output Format

Return a concise Markdown report with extracted text summary, extraction method used, files produced, and unresolved extraction issues.

## Gotchas

- Scanned PDFs may return `None` from direct text extraction.
- Table extraction can fail on merged cells or visually aligned columns.
- Form field names may be non-human-readable and must be inspected before filling.
- OCR language packs must match the document language.

## Boundaries

- Does not bypass password protection.
- Does not guarantee perfect OCR accuracy.
- Does not alter original PDFs in place.

## Verification

- [ ] Output file exists when a file is generated.
- [ ] Extracted text is non-empty or OCR failure is explicitly reported.
- [ ] Form fields are listed before form filling.
- [ ] The original file remains unchanged.

## Examples

### In Scope

User: "Extract text from this scanned invoice PDF."
Expected: Detect poor direct extraction, use OCR fallback, report confidence and unresolved pages.

### Out of Scope

User: "Remove the password from this protected PDF."
Expected: Decline; password bypass is outside the skill boundary.
```

---

## 13. Compliance Tiers

Skills may conform to this standard at one of four levels. Tooling, registries, and review processes should communicate which tier is required.

| Tier         | Definition                                                                                                                                           |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Strict**   | Passes all MUST and MUST NOT checks; no WARNING conditions present; all mandatory sections in correct order; release gate evals completed            |
| **Standard** | Passes all MUST and MUST NOT checks; minor SHOULD violations permitted (e.g., missing one non-critical section, description slightly below 50 chars) |
| **Valid**    | No MUST violations; may fail SHOULD or MAY guidance; WARNING conditions may be present but acknowledged                                              |
| **Invalid**  | Any MUST violation; not safe for distribution or production invocation                                                                               |

A skill distributed through a public registry **SHOULD** meet at minimum the **Standard** tier. Skills used in production automation **SHOULD** meet the **Strict** tier.

## 14. Limitations

1. **No live runtime validation**: compatibility is inferred from official specifications, documentation, product guidance, and documented validation behavior, not from runtime black-box tests. The conservative decisions around `allowed-tools` and GitHub-specific fields are intentional.

2. **Experimental fields**: `allowed-tools` is marked experimental in the spec. Its behavior across runtimes is not guaranteed.

3. **Token counting imprecision**: the "≤ 5000 tokens" recommendation is approximate. Different tokenizers produce different counts. Validators should use the target runtime's tokenizer; otherwise, approximately 1 token ≈ 4 characters for English text.

4. **GitHub provenance metadata**: GitHub `gh skill` writes provenance metadata into frontmatter, but no stable public schema contract exists for those auto-generated keys. They are not included in the canonical author-written schema.

5. **No versioning mechanism**: the current spec does not define a versioning mechanism for skills. This standard does not introduce one.

6. **No namespacing for skill names**: the `name` field has no namespace mechanism; collision between skills from different authors is possible and is a known gap not addressed by any scraped source.

7. **Overlay filenames for Claude Code and GitHub**: only `agents/openai.yaml` is explicitly documented. Claude Code and GitHub overlay filenames are classified as UNKNOWN and out of portable-core scope until separately documented.

8. **WASM/WASI compilation**: this specification covers native scripts and Markdown definitions. Advanced sandboxed runtimes (such as OpenSkills' WASM execution environment) require external compilation steps — for example, compiling JS/TS to `.wasm` components — which fall outside the scope of raw `SKILL.md` parsing and are not addressed here.

9. **Dynamic context**: this standard cannot statically guarantee that an agent will choose to read a specific reference file. Authors must rely on strong trigger descriptions within `SKILL.md` and explicit `## Supporting Files` entries to guide the model toward the correct resources.

## 15. Implementation Notes for Validators and Registries

### 15.1 Validator behavior

A validator should distinguish hard failures from authoring warnings. Hard failures indicate the bundle is invalid as a strict portable skill. Warnings indicate portability risk, weak trigger quality, vague descriptions, excessive context weight, untested scripts, or host-specific material that should be moved to an overlay.

Recommended validator outputs:

- machine-readable JSON for CI;
- human-readable Markdown for review;
- stable issue codes for suppression and regression tracking;
- explicit path, line, and rule identifier where possible.

Example issue shape:

```json
{
  "severity": "FAIL",
  "code": "FM_UNKNOWN_CORE_KEY",
  "path": "SKILL.md",
  "line": 4,
  "message": "Top-level frontmatter key 'version' is not part of the portable core. Move it to release metadata or a host overlay."
}
```

### 15.2 Registry behavior

A registry should not rewrite portable `SKILL.md` in place to inject provenance, catalog tags, install metadata, analytics fields, or UI hints. If metadata is needed, store it outside the bundle or inside a clearly separated overlay. Mutation of `SKILL.md` is allowed only when the target registry is explicitly host-specific and no portable compatibility claim is made.

### 15.3 Authoring-time artifacts

Authoring-time artifacts are valuable but should not be confused with the runtime bundle. Examples include drafts, eval datasets, test fixtures, CI configs, changelogs, contribution guides, screenshots, and benchmark notes. They may live beside the source project, but strict release packaging should include only the runtime bundle and documented overlays.

### 15.4 Preservation policy

This standard preserves source material by classification rather than by verbatim appendix. When two sources express the same rule differently, the rule is stated once in canonical language. When sources conflict, the rejected alternative is retained in conflict logs, mapping tables, migration tables, or limitations. When a source provides a useful example, the example is normalized into the strict body template rather than copied as an incompatible fragment.

## 16. Consolidation Notes

This merged standard intentionally uses the larger strict document as the canonical base and integrates the unique high-value material from the smaller consolidated document. The merge preserves strict validation logic, source-priority rules, conflict tables, examples, schemas, validation commands, release-gate evidence, classification tables, overlay boundaries, packaging rules, and migration guidance.

Material was not removed merely because it was verbose. Content should be removed only when it is true duplication, contradicted by the normative model, or belongs exclusively in host-specific overlays.

The resulting standard is intentionally standards-heavy. Its purpose is not to be the smallest possible authoring guide; it is to be a canonical reference that can support validators, registries, authoring tools, runtime implementers, and human reviewers.
