# Publishing Skills

> Publish a standard skill package into this shared skill home — agree on its functional category, place it under skills/{category}/{name}/, activate it in skills/index.json, then maintain the README and verify binding. Use when adding, moving, or renaming a skill in VEMO_SKILLS. Placement + registration only — adoption stays a user-consent decision.

- Skill: `vemodalen-x/publishing-skills` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add vemodalen-x/publishing-skills`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vemodalen-x/publishing-skills/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: vemodalen-x (https://skillmd.com/u/vemodalen-x)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/vemodalen-x/publishing-skills

---


# Skill Publish

Place a standard skill package into this shared skill home, activate it explicitly, keep the README in lockstep, and
verify binding. This skill governs **placement + registration** inside the home — it does **not** adopt a skill into
any project's toolset (that is the Skill Scout's pipeline and always needs user consent; skill_spec §6).

**Registration is the precondition for everything downstream.** The lifecycle is **register → bind (+consent = adopt)
→ sync / contribute** (see `CONVENTIONS.md` §0): a skill that is not registered here is invisible to `syncing-frameworks`
(which compares released = registered + tagged versions) and to `contributing-framework-changes` (which PRs a registered skill).
This skill performs the *register* stage; binding and sync/contribute are downstream of it.

## Model (read first)
- **Activation is explicit.** `skills/index.json` is the single registration surface. Its normalized
  `<category>/<name>/SKILL.md` path selects the category and package; a folder that is absent from the index is inert
  and fails selfcheck. Repository placement metadata never enters model-visible frontmatter.
- **Naming is gated, not assumed.** A skill's `name`/`description` must pass the **`naming-skills`** validator (the
  authority for skill naming — name ≤64 / `[a-z0-9-]` / no edge hyphen / **gerund** / name==dir; description
  non-empty / ≤1024 / what+when / keywords) **before** registration. This skill references that rule, it does not
  restate it (consolidate-with-pointers); the gate runs at Step 0.5 and the whole-tree check at Step 5.
- **Categories are agreed-and-created, not a fixed enum.** Choose the functional category with the author. If
  `skills/<category>/` does not exist, create it and record the new category. The category set remains filesystem and
  index data, never a hardcoded enum.
  A category is a **functional grouping** (e.g. `governance/ orchestration/ research/`), not a framework repo.
- **README is part of the deliverable.** Every add / move / rename / remove updates the README (**Skill-Catalog row** +
  category-layout line + Use-via-Prompt entry + keyword-triggers row where applicable). The README ⇄ skills consistency
  is **machine-checked** by a multiset diff **plus a catalog-row completeness check** (Step 5), not a count compare — a
  count compare misses a rename or a wrong-folder placement. (Catalog-row format: `CONVENTIONS.md` §3.)
- **Identity-decoupled.** No org / account / project path is hardcoded. Targets are the local `skills/**` tree; the
  home repo is read from `git remote get-url origin` only if a remote reference is needed. Works for any consumer of
  this home (skill_spec §9). See `CONVENTIONS.md` for the full home-local convention set.
- **Regen is a build artifact.** A consuming project regenerates each skill into `.claude/skills/<name>/` (gitignored).
  Publishing a skill body obliges a **byte-identical regen check** (`diff -r`) wherever the home is consumed.

## Triggers
- **Manual / keyword**: "发布一个 skill" / "publish a skill" / "把这个 skill 归类" / "categorize this skill" /
  "add a skill to VEMO_SKILLS" / "新增 skill 到 skill 库".
- Not automatic — publishing is an authoring action, run on request.

## Pre-Check (Step 0, mandatory)
1. Confirm the working directory is a skill home (a `skills/` tree with a `README.md`, `VERSION`, `CHANGELOG.md`).
   If not → "Not a skill home (no skills/ + README/VERSION/CHANGELOG)" → **stop**.
2. Read the incoming skill's `SKILL.md` frontmatter. If `name:` or `description:` is missing, or repository-only
   `category:` is present, stop and normalize the source package first.
3. Agree on the target functional category with the author. If the skill already exists under another category, treat
   this as a move and confirm intent before relocating.

## Step 0.5 — Naming gate (mandatory, before placement)
Run the **`naming-skills`** validator on the incoming `SKILL.md` (it is the authority for skill naming; this skill
references it, it does not restate the rules). Registration is **blocked** unless every **hard** rule passes:
- `name` ≤ 64 chars, only `[a-z0-9-]`, no leading/trailing hyphen, **gerund (verb+ing)** form, and
  `name` == its parent directory name;
- `description` non-empty, ≤ 1024 chars, states what-it-does + when-to-use, with trigger keywords.
Any hard FAIL (incl. a non-gerund name — a hard rule in this ecosystem) → report the failing rule, ask the author to
fix the name/description, **stop**. Body/length advisories are INFO and do not block.

## Publish Flow
### Step 1 — Resolve package identity and category
Read `name:` from `SKILL.md`; take category from the user's publishing decision or the existing indexed path.

### Step 2 — Resolve the target folder
Target = `skills/<category>/<name>/`.
- If `skills/<category>/` **exists** → place into it.
- If `skills/<category>/` **does not exist** → **create** the folder (declare-and-create) and note "new category
  `<category>` created" for the report and the CHANGELOG.

### Step 3 — Place the body (and references)
Write `SKILL.md` and only necessary `agents/`, `references/`, `scripts/`, or `assets/` resources under the target.
Generate/validate `agents/openai.yaml`. For a **move**, relocate the existing folder
(`git mv skills/<old-cat>/<name> skills/<category>/<name>`) so history is preserved — never copy-then-delete.

Add the normalized `<category>/<name>/SKILL.md` path to `skills/index.json`. This index mutation is the registration
event; keep paths unique, local, bounded, and deterministic.

### Step 4 — Maintain the README (obligation)
Update `README.md`:
- **Skill Catalog** — add/update the skill's row: **category** (== indexed path category) · **skill**
  (`` `<category>/<name>` `` token, with `<name>` == frontmatter `name:`) · **does** · **when to use** · **boundary**.
  (Catalog-row format: `CONVENTIONS.md` §3. The `<category>/<name>` token is what the Step 5 multiset diff extracts.)
- **Layout section** — ensure the `<category>/` line lists the skill (add the category line if the category is new).
- **Use via Prompt** — add a trigger entry + a **Keyword-triggers sub-table** row **if** the skill is user-prompt-triggered.
- **R30**: never hardcode a version number in the README — point at `VERSION` + `CHANGELOG.md`.
(README entry-doc style: the R29+ entry-doc family in
`skills/orchestration/publishing-deliverables/references/readme-style.md` — incl. the bilingual pair.)

### Step 5 — Self-check (machine, before declaring done)
- **Three-way parity**: README catalog tokens == `skills/index.json` references == filesystem
  `skills/*/*/SKILL.md`. Report orphan rows, inert tree packages, dangling index references, and duplicates.
- **Name ⇄ indexed path**: frontmatter `name:` equals the indexed `<name>` directory; category is path-derived.
- **Identity grep-clean** (skill_spec §9): `grep -Ei '<org>|<account>'` on the new `SKILL.md` → 0 hits. (The home repo
  name as an example is allowed only if annotated "resolved at runtime".)
- **Naming conformance (whole tree)** — run **`naming-skills`** over every `skills/*/*/SKILL.md` and assert all
  **hard** rules green (name ≤64 / `[a-z0-9-]` / no edge hyphen / gerund / name==dir; description non-empty / ≤1024 /
  what+when / keywords). A FAIL here means a mis-named or stale skill slipped in — fix before declaring done.
- **Skill-Catalog completeness** (the row's *quality*; existence is already covered by the multiset diff above, so this
  does not re-assert it). For each `skills/*/*/SKILL.md`, in its Skill-Catalog row:
  - **derived-equality** (deterministic): the row's **category** cell **== indexed path category**, and the **skill**
    token's `<name>` **== frontmatter `name:`**. (Equality, not just non-empty — the category column is the user-facing
    "what category is this" answer; a non-empty-only check would let it drift and re-introduce the confusion this fixes.)
  - **curated non-empty**: **does** / **when to use** / **boundary** cells are all non-empty.
  - **trigger coverage**: every **prompt-triggered** skill has a row in the Use-via-Prompt **Keyword-triggers** sub-table.
  Run on both `README.md` and `README_zh.md` (R32 mirror). Any failure → fix before declaring done. (Format: `CONVENTIONS.md` §3.)

### Step 6 — Regen + verify (where the home is consumed)
In a consuming project: regenerate the skill into `.claude/skills/<name>/` and run
`diff -r skills/<category>/<name> .claude/skills/<name>` → must be clean (byte-identical; the copy is a build artifact).

### Step 7 — Version + changelog + ledger
- Bump `VERSION` (minor for a new skill / category; patch for a move or wording) and add a `CHANGELOG.md` entry
  (name the skill, its category, and any new category created). Keep **VERSION == CHANGELOG top == (at release) tag**.
- **PR-only + weekly train (ruled 2026-06-11)**: land the change via **branch → PR → merge** (no direct push to the
  default branch). The **tag + announcement** are cut by the **weekly Friday release train** — PRs merged by the Friday
  cutoff ride that train; unmerged PRs wait, and their contributions are not counted until merged.
- A publish is a workflow event — mirror it into the consuming project's `flow_log.md` when run there.

## Never touched
- A skill's **adoption** into a project toolset — that is the Skill Scout pipeline + a **user-consent red line**
  (skill_spec §6). This skill places and registers; it never decides a skill is adopted.
- Instance files / runtime ledgers, except the `flow_log.md` row recording a publish.
- The regenerated `.claude/skills/**` copies as a *source* — they are build artifacts; the home `skills/**` is edited.

## Notes
- **Who runs it**: the Skill Scout proposes a skill → the user consents → publishing places + registers it. The actor
  is a role constraint, not a separate categorization system — agents are framework-homed (registry_spec), there is no
  parallel agent-folder layout here.
- **Difference from a flat skill dump**: categorization is declared and machine-verified, so the home stays navigable
  and the README cannot silently drift from the tree.

