Files
holocron/plugins/kyberforge/skills/skill-author/SKILL.md
Defame1297 38f1ba4e03 fix(kyberforge): bridge apm content to Claude Code's flat plugin discovery
Claude Code's (and Copilot's) native plugin installer has zero awareness of
.apm/ nesting -- it convention-scans only flat skills/, agents/, commands/,
hooks.json at each plugin's root. Confirmed via strings on the installed
claude binary and live installs of git@holocron/gitea@holocron/kyberforge@
holocron, all reporting Skills(0) Agents(0) Hooks(0) post ADR-0015's apm
conversion. Root cause (apm_cli/core/plugin_manifest.py): apm's plugin.json
compiler deliberately strips skills/agents/commands keys, assuming the host
already auto-discovers those convention directories -- it has no model of
.apm/ being host-visible at all. Separately, apm's own bundle exporter
(apm_cli/bundle/plugin_exporter.py, behind `apm pack --format plugin`)
implements the correct .apm/ -> flat mapping, but only ever targeted
build/<name>-<version>/, a path nothing in marketplace.json's source: points
at.

scripts/sync-plugin-content.sh wraps that bundle exporter and copies its
agents/, skills/, commands/, instructions/, extensions/, and merged
hooks.json back into each plugin's own root as a second tracked
compiled-output category -- same governance status as
.claude-plugin/plugin.json: generated from .apm/, never hand-edited. tests/
subdirectories are excluded from the mirror (dev fixtures, not host-visible
runtime content; several hardcode a relative repo-root walk-up sized for the
.apm/-nested depth, which breaks when duplicated one level shallower).
Applied for real across all 6 plugins and verified two ways: `claude plugin
validate --strict` passes on every real plugin directory, and a live
`claude --plugin-dir <path> -p "list skills/agents"` behavioral test
confirms content is now actually discovered.

Also, from the same issue #90 review round:
- scripts/check-manifests.sh pointed at each plugin's root-level plugin.json
  (checking skills/hooks/mcpServers/agents pointer fields) -- that file was a
  stale near-duplicate of .claude-plugin/plugin.json nothing else read or
  wrote, now deleted across all 6 plugins. check-manifests.sh is rewritten to
  validate .claude-plugin/plugin.json instead, and drops the pointer-field
  checks entirely (nothing to check -- those fields are correctly absent by
  design). Content-presence drift is now check-plugin-content-sync's job, a
  new pre-push hook wired in .pre-commit-config.yaml.

docs/adr/0017 records the root cause and decision in full, including two
rejected alternatives (patching plugin.json's path fields directly -- apm's
compiler strips them on every run; pointing marketplace.json at apm pack's
build/ output -- a version-suffixed non-source directory nothing can install
from without an extra build step). ADR-0015 and CONTEXT.md are updated to
point at it.

Refs: #90
2026-08-13 16:59:03 +00:00

307 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: skill-author
description: >
Use when the user wants to create a new skill from scratch ("write a skill
for X", "build a skill that does Y", "create a SKILL.md for Z") or improve
an existing one ("improve this skill", "fix based on feedback", "apply these
audit findings", "update based on grill output"). Also use when the user provides inline feedback
about a skill's behavior and wants it applied, or when a grill session, eval
run, or audit has produced findings the user wants acted on — even if they
don't say "improve" explicitly. Do not use for read-only review — use
/skill-audit instead. Do not use to author agent definition files.
allowed-tools: Bash Read Write Edit
metadata:
category: factory
source_keys:
- agentskills-home
- agentskills-spec
- agentskills-best-practices
- agentskills-optimizing-descriptions
- agentskills-evaluating-skills
- agentskills-using-scripts
- agentskills-quickstart
---
## Gotchas
- Patching per symptom is the default failure mode. Three eval failures may all trace to one missing instruction — always identify the root cause before editing.
- Do not create new scripts unless a signal explicitly calls for it. Writing scripts from scratch requires transcript analysis that is out of scope here; flag the opportunity as a suggestion instead.
- Never spawn a subagent to audit or recheck your own work during an authoring pass. Run `/skill-audit` yourself, inline, in the same context as the edits you just made. A *separate* independent recheck via a clean-context subagent is the `/forge` skill's outer-loop responsibility exclusively — delegating it inward here duplicates that layer and introduces a race: a stray self-spawned subagent can have its worktree torn down by concurrent cleanup, destroying an uncommitted draft before it was ever safe.
## Route
Determine which flow to follow before touching the filesystem:
- **No skill directory at the target path** → follow **Creating a new skill**
- **Directory exists + at least one improvement signal present** → follow **Improving an existing skill**
- **Directory exists + no signals present** → ask: "No improvement signals found. Did you mean to create a new skill, or do you have feedback to apply?"
Signals include: grill session output, `/skill-audit` findings (PASS/FAIL punch list), inline user feedback, session context describing what went wrong.
**Before running the scaffold script**, judge whether the destination is meant to be inside an APM package — the script can't tell "no package here" apart from "package not scaffolded yet":
- Package intent but no `type:`-bearing `apm.yml` found at/above the destination (e.g. "add to my apm package", or a sibling `.apm/`/`apm.yml` exists nearby) → **stop**, tell the user to run `/apm-workflow configure` (`apm plugin init`, from inside the package directory) first, then retry. Don't fall through to standalone mode.
- Otherwise (a `~/`-rooted destination, or no package context implied) → run `scripts/new-skill.sh`; it resolves package vs. standalone automatically (see Step 1).
## Creating a new skill
### Prerequisites
Run `/grill-me` on the skill's design and research the target domain first.
Share those outputs in this conversation: grill context, research docs, examples, constraints.
Design for one coherent user intent — skills too narrow force multiple loads per task; too broad are hard to activate precisely.
**Before touching the filesystem, verify you have:**
- [ ] A clear purpose — what specific task will this skill handle?
- [ ] Trigger scenarios — when should an agent activate it, including indirect cases?
- [ ] Skill name (kebab-case) and destination path
- [ ] Capture `git log --oneline -1` now, before touching the filesystem — Step 7 needs it to verify a real commit landed
If any are missing, stop and ask the user before proceeding.
**Requires `/skill-audit`** — used in Step 7 for final validation. Both skills ship in the kyberforge plugin and are co-installed. If `/skill-audit` is unavailable, stop and ask the user to install the kyberforge plugin before continuing.
### Step 1 — Scaffold
Run the copy script with the skill name and a path inside or at the target:
```bash
bash scripts/new-skill.sh <skill-name> <path>
```
The script walks up from `<path>` for a package boundary: an ancestor `apm.yml` with a top-level `type:` field (`instructions`/`skill`/`hybrid`/`prompts`) means **package mode** — scaffolds into `<package-root>/.apm/skills/<skill-name>/`, not under `<path>` (a subdirectory of the package works fine as `<path>`). A `type:`-less `apm.yml` is a marketplace-only manifest, skipped. Hitting `.git` or the filesystem root first means **standalone mode** — scaffolds directly into `<path>/<skill-name>/`, same as before.
Examples:
```bash
# Package mode — packages/my-pkg/apm.yml already has `type: skill`
bash scripts/new-skill.sh my-tool packages/my-pkg/
# Standalone mode — no apm.yml/.git above ~/.agents/skills/
bash scripts/new-skill.sh my-tool ~/.agents/skills/
```
The script prints which mode it used and where the skill landed — read its output.
In package mode, read `references/deployment-modes.md` before adding any file references to SKILL.md.
### Step 2 — Update `apm.yml` includes (package mode only)
Skip in standalone mode. In package mode, check the resolved package's `apm.yml`: if `includes:` is an explicit list (not `auto`), append `.apm/skills/<skill-name>/` to it if not already present, preserving YAML formatting. If `includes: auto` or the field is absent, do nothing — `auto` already covers the new skill. Use Read/Edit directly on `apm.yml`; this isn't part of `scripts/new-skill.sh`.
### Step 3 — Fill in SKILL.md
Open the new skill's `SKILL.md` (the path Step 1 printed). Replace every `FILL IN:` placeholder.
**Frontmatter**
**`name`** — already set by the scaffold script. Must exactly match the directory name. Format: 1–64 characters, lowercase letters/numbers/hyphens only, no leading, trailing, or consecutive hyphens (`--`).
**`description`** — carries the entire triggering burden. Rules:
- Imperative: "Use when..." not "This skill..."
- Focus on user intent, not implementation — describe what the user is trying to achieve, not the skill's internal mechanics
- Specific about capabilities ("parses and validates OpenAPI specs", not "helps with APIs")
- Include indirect triggers: "even if the user doesn't mention X explicitly"
- Add "Do not use when..." only if a near-miss skill exists that could steal activations
- Hard limit: 1024 characters — count before finalizing
**Optional fields** — uncomment and fill in or remove entirely:
- `license` — include when distributing the skill externally
- `compatibility` — include if the skill requires specific tools, runtimes, or network access (max 500 characters)
- `metadata` — key-value map; use `author`, `version`, `category`; add `source_keys` now (see below) if research sources are in context
- `allowed-tools` — space-separated pre-approved tools; reduces permission prompts (experimental — support varies by client)
**`metadata.source_keys`** — if research sources are in context, list the relevant slugs here as you write the body; don't defer this to Step 6. Agents that fill in source_keys late tend to omit it entirely. Example:
```yaml
metadata:
source_keys:
- my-source-slug
- another-slug
```
**Embedding org-specific policy** — if a skill encodes a rule sourced from an org convention file (e.g. `core/instructions/*.md`), inline that content directly into the skill (SKILL.md or a `references/` file) rather than pointing to the file's path. Plugins must be self-contained and portable — the org file may not exist wherever the plugin is installed, and in this repo such files are meant to be deleted once their content is fully embedded downstream. Tag the inlined content with a `source_keys` entry using the same `references/sources.md` schema as Step 6, noting in the `Research doc:` field that the source is an org convention rather than a plugin research corpus entry, so provenance survives after the source file is gone.
**Body — include only what the agent lacks**
Rename the placeholder section heading to one that fits the skill's structure — `## Step 1`, `## Workflow`, `## Instructions`, etc.
Ask of every sentence: "Would the agent get this wrong without it?" Cut anything that answers "no."
**Include:**
- Non-obvious sequences or ordering constraints — the agent may skip or reorder steps without this
- Domain conventions the agent cannot infer from general knowledge — this is the core value a skill adds
- One default per decision point, plus one escape hatch — never a menu; menus cause the agent to pause or pick arbitrarily
- Gotchas — facts that defy reasonable assumptions; the agent will get these wrong every time without them
**Exclude:**
- Concepts the agent already knows (what JSON is, how HTTP works) — adds tokens without changing behavior
- Exhaustive option lists — pick a default; the agent doesn't benefit from choosing
- Steps the agent handles independently — over-specifying leads agents to follow unproductive paths
- Restatements of the description — it's already in context; repeating it wastes the token budget
**Patterns**
**Gotchas** — highest value; place near the top:
````markdown
## Gotchas
- <Fact that defies a reasonable assumption>
- <Non-obvious naming discrepancy or hidden constraint>
````
**Default with escape hatch** (not a menu):
````markdown
Use <X> for <task>. For <edge case>, use <Y> instead.
````
**Prescriptive sequence** (when order is critical or fragile):
````markdown
Run exactly:
```bash
<command>
```
Do not modify flags.
````
**Checklist** (multi-step workflows):
````markdown
- [ ] Step 1: ...
- [ ] Step 2: ...
````
**Conditional reference** (progressive disclosure — load only when needed):
````markdown
If <condition>, read `references/<file>.md`.
````
**Output format template** (when the skill produces structured output):
````markdown
Output format:
```
<field>: <value>
<field>: <value>
```
````
For longer templates, place in `assets/<name>.md` and reference conditionally.
**Size budget**
Keep `SKILL.md` under 500 lines; 5,000 tokens is the recommended body budget. When approaching the limit:
- Move reference material to `references/<topic>.md` and load it conditionally
- Bundle repeated executable logic into `scripts/` rather than reinventing each run
### Step 4 — Add scripts (if needed)
Place executable scripts in `scripts/`. Critical rule: **no interactive prompts** — agents run non-interactive; blocking on TTY input hangs indefinitely. Accept all input via flags, env vars, or stdin.
If adding a script, read `references/scripts.md` first — it covers the full contract: structured output, pinned versions, self-contained deps, idempotency, exit codes, dry-run, error messages, and output size limits.
If no scripts are needed, delete `scripts/README.md` and the `scripts/` directory.
### Step 5 — Add references, assets, and tests (if needed)
**`references/`** — additional documentation loaded on demand. One topic per file.
Reference conditionally from SKILL.md: `If <condition>, read references/<file>.md`.
Keep reference chains one level deep — a reference file that references another reference file is rarely loaded correctly.
**`assets/`** — static resources: templates, schemas, lookup tables.
Reference by relative path from SKILL.md.
**`tests/`** — test files for scripts in `scripts/`. Use when scripts are complex
enough to break silently. Test infrastructure (`.bats`, `*_test.*`) belongs here,
not in `scripts/`. See `tests/README.md` for setup instructions.
If not needed, delete the placeholder READMEs and their directories.
### Step 6 — Populate or delete `references/sources.md`
If a research `sources.md` is present in the conversation context:
1. Read it and filter to entries with `` `extracted` `` status only.
2. For each entry, determine which skill files it contributed to (SKILL.md and any files in references/ that drew from it). Update `Contributing files` accordingly — list skill files, not research topic files.
3. Write the updated content to `references/sources.md`. For each entry, include `- **Research doc:** <path>` where `<path>` is the relative path from the repo root to the plugin-level research sources file this entry was drawn from (e.g. `plugins/myplugin/docs/research/docs/<topic>/sources.md`). This field is required on every entry — it makes the provenance chain explicit and is validated by `/skill-audit`.
4. Add `source_keys` to the frontmatter of `SKILL.md` (under `metadata`) listing the slugs of sources that informed it.
5. For each file in `references/` that was informed by research sources, add `source_keys` frontmatter (same format as research topic files) listing the relevant slugs.
If no research `sources.md` is in context, delete `references/sources.md`.
### Step 7 — Validate and close
Before running the audit, confirm:
- [ ] Skill name matches the directory name exactly
- [ ] `description` field is present and non-empty
- [ ] Body has at least one non-empty section
- [ ] No `FILL IN:` placeholders remain in any file
Run `/skill-audit` on the skill directory Step 1 reported — either `<package-root>/.apm/skills/<skill-name>/` or `<path>/<skill-name>/`.
All FAIL findings must be resolved before the skill is considered done.
If the skill is versioned (`metadata.version`), set it to the next **minor** version (e.g. `0.2.0` → `0.3.0`). New skills without a prior version start at `0.1.0`.
**Commit verification.** Capture `git log --oneline -1` before Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the new skill files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the skill as done once the hash has actually changed.
## Improving an existing skill
### Step 1 — Verify inputs
Confirm the skill directory path exists and that at least one improvement signal is present in the conversation or a referenced file.
If the skill dir is missing, ask for it. If no signals are present, stop: "This skill applies existing signals to a skill. For a blind review without signals, use `/skill-audit` instead."
Capture `git log --oneline -1` now, before making any edits — Step 5 needs it to verify a real commit landed.
Signals can come from anywhere in the conversation or referenced files:
- Grill session output (most common predecessor in the factory sequence)
- `/skill-audit` findings (PASS/FAIL/SUGGESTION punch list)
- Human feedback (feedback.json, inline in conversation, PR or issue comments)
- Session context describing what went wrong
Also verify the `name` field in frontmatter matches the skill's directory name exactly.
### Step 2 — Gather and group signals
Read the current skill files (SKILL.md and any files in scripts/, references/, assets/, tests/). Then collect all signals from the conversation and any file paths the user has referenced.
Group signals by **root cause**, not symptom. Ask: "What single gap in the skill causes this cluster of failures?" One root cause → one fix. Do not make a separate edit for each symptom.
```text
Example:
- Session context: output format is wrong on every run
- Audit finding: no output template defined
- User feedback: "I always have to ask it to format the output"
→ Root cause: SKILL.md has no output format specification → one fix: add an output template
```
### Step 3 — Announce planned changes
Before editing, state:
- Which root causes were identified and what evidence supports each
- Which files will be changed and what will change in each
Then proceed — edits are reversible via git, no approval checkpoint needed.
### Step 4 — Apply changes
Edit any file in the skill directory that the signals point to: SKILL.md, scripts/, references/, assets/, tests/, README.md.
**Generalize, don't patch.** Find the underlying gap, not the specific example that failed. A fix scoped only to the test cases you've seen will overfit and perform worse on new inputs.
**Keep it lean.** Remove instructions that aren't pulling their weight. For every sentence you add, ask: "Would the agent get this wrong without it?" A shorter, focused skill consistently outperforms an exhaustive one.
**Explain the why.** Reasoning-based instructions outperform rigid directives. If you find yourself writing a rule in all caps (ALWAYS/NEVER), reframe it: explain why the behavior matters so the agent can apply judgment in edge cases.
If a signal points to a script or reference file, edit that file directly rather than adding a workaround in SKILL.md.
### Step 5 — Validate and close
Before running the audit, confirm:
- [ ] Skill name still matches the directory name
- [ ] No `FILL IN:` placeholders were introduced
- [ ] No previously-passing audit checks were broken by the edits
Run `/skill-audit` on the skill directory. Resolve any FAIL findings before considering the improvement complete.
If the skill is versioned (`metadata.version`), bump the **patch** version (e.g. `0.1.0` → `0.1.1`).
**Commit verification.** Capture `git log --oneline -1` at the start of Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the changed files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the improvement as done once the hash has actually changed.