feat(kyberforge): enforce the ADR-0020 context contract for skills and agents

Skill name+description pairs are preloaded into every session, costing
~6,200 tokens across 39 skills before any skill is invoked. The authoring
rules mandated that growth: skill-author:104 and description-quality.md:21
both required padding, while skill-author:102 (the deflating rule) had no
FAIL condition behind it.

Gates (blocking, no baseline file):
- description 250 chars SUGGESTION / 400 FAIL, measured on the folded
  YAML value
- body-only 600 words SUGGESTION / 900 FAIL, independent of the unchanged
  whole-file 2770-word / 500-line spec backstop
- every boundary-clause routing target must resolve to a real skill or
  agent; catches skill-improve, neuledge-context and gitea-labels
- agents take the description gates but deliberately no body gate; a test
  pins that absence

Vale: DescriptionOpener widened to ^This\b, new CompositionNote rule
banning architecture notes from descriptions. 10 hits, 0 false positives.

Kyberforge's own four skills retrofitted: descriptions 3,364 -> 938 chars
(-72%), bodies 8,306 -> 2,487 words (-70%), all via the apm-workflow
dispatch pattern. Fixes the skill-improve dangling route and the
agent-author misroute to manual review.

Also fixes a pre-existing false positive where any line-initial 'read '
was flagged as interactive input, which had already caused two scripts to
be rewritten around it.

Refs: ADR-0020
This commit is contained in:
2026-08-14 21:13:13 +00:00
parent 1c6eababb0
commit 4a5c3c0cff
104 changed files with 6272 additions and 1880 deletions

View File

@@ -0,0 +1,187 @@
---
source_keys:
- agentskills-spec
- agentskills-best-practices
- agentskills-optimizing-descriptions
---
# The description and body contract
House contract, set by ADR-0020. Every rule here is enforced by `/skill-audit` —
`scripts/validate.sh` for the counts and the boundary targets, the bundled Vale styles for the
prose patterns, and its reference files for the judgment calls.
## Why the budget exists
A skill's `name` and `description` are loaded into every agent's context at the start of every
session, whether or not the skill is ever invoked. The body is loaded only on invocation, and then
competes with the caller's live conversation. Those are two different costs, so they get two
different ceilings — and a fat description is not merely expensive. A description that summarizes
the workflow gets followed *instead of* the body: a description saying "code review between tasks"
produced one review from a skill whose flowchart specified two.
## Description
A description carries exactly three things:
1. **Trigger clause** — when to invoke, imperative: "Use when ...", never "This skill ...".
Focus on user intent, not the skill's internal mechanics.
2. **At most one capability clause** — what it does, one clause, no enumeration. Be specific
("parses and validates OpenAPI specs", not "helps with APIs").
3. **Boundary clause** — form: `Not <thing> -> <skill-name>.` Add one only where a near-miss skill
could steal activations.
Banned from a description; move it to the body or to `README.md`:
- Capability enumeration or feature lists
- Output-format detail ("Produces a compact findings report with Why and Fix per finding")
- Composition or architecture notes ("composes X rather than duplicating Y", "This is a
cross-cutting shared skill", "the human-facing entry point")
- Implementation detail ("Self-validates via a bundled deterministic script")
- Restating the same trigger twice in two registers — a verb list, then the same verbs re-quoted
as user phrasings. This is a FAIL, not a suggestion.
**Indirect triggers are conditional, not mandatory.** Add "even if the user doesn't mention X
explicitly" only where the user's natural phrasing genuinely omits the domain word — true for the
`gitea-*` family, because people say "create an issue" rather than "create a Gitea issue"; false
for `git-commits`, where the user says "commit". Adding one everywhere is what inflated this
corpus, and it was deleted as a blanket rule.
**Boundary targets must resolve.** The name after the arrow is checked against real skill
directories under `plugins/*/.apm/skills/<name>/` and real agents under
`plugins/*/.apm/agents/<name>.agent.md`. A boundary clause naming a target that does not exist
sends the router nowhere and fails the audit. Check the target exists before writing it — do not
invent a plausible sibling name.
**Length.** 250 characters SUGGESTION, 400 characters FAIL, counting the frontmatter value only
with YAML folding resolved. The agentskills.io 1,024-character spec limit is unchanged and sits
above both. The SUGGESTION tier is the one that moves the average; treat 250 as the target and 400
as the outlier stop.
**Hand-invoked skills are exempt.** A skill carrying `disable-model-invocation: true` is absent
from the model-visible listing and is reached only by the user typing `/name`. It takes one plain
human-facing sentence — no trigger clause, no boundary clause, no indirect triggers. Worked
example: `plugins/bin/.apm/skills/zoom-out/SKILL.md`.
## Body
The body carries the **decision procedure only**: ordered steps, decision branches, gates, and
which reference to load when. Everything else moves to `references/`.
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 — 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
Exclude:
- Concepts the agent already knows (what JSON is, how HTTP works) — tokens without behavior change
- Exhaustive option lists — pick a default; the agent does not benefit from choosing
- Steps the agent handles independently — over-specifying leads agents down unproductive paths
- Restatements of the description — it is already in context
Move to `references/`: lookup tables, spec restatements, output schemas, templates, example
blocks, rationale prose, and any content only one branch reaches. Each reference file is
self-contained for its concern, and every one is wired from the body with the literal conditional
form:
````markdown
If <condition>, read `references/<file>.md`.
````
A generic pointer ("see references/ for details") is a Vale error — the agent cannot act on it.
**Dispatch is mandatory at two or more mutually exclusive flows.** The body carries the dispatch
table and the gates common to every branch; each flow gets its own self-contained `references/`
file. Exemplar: `plugins/kyberforge/.apm/skills/apm-workflow/SKILL.md` — a 554-word body
dispatching to 3,006 words of references.
**Length.** 600 words SUGGESTION, 900 words FAIL, counting the **body only** — everything after
the frontmatter's closing `---`.
## Gotchas section
- Each entry must state a fact that **contradicts a reasonable default** — something the agent
gets wrong by acting sensibly. "Never commit secrets" is not one; the agent already knows.
- Maximum five entries.
- A Gotcha that paraphrases a step in the body below it is a **FAIL**. If the rule is already a
step, it is not a gotcha.
- A Gotchas section exceeding 25% of the body is a SUGGESTION.
- Place the section near the top — a gotcha read after the mistake is worthless.
## Two size gates, two measurements
| Gate | SUGGESTION | FAIL | Counts |
|---|---|---|---|
| description | 250 chars | 400 chars | the `description:` value only |
| body | 600 words | 900 words | the body only, after the closing `---` |
| spec backstop | — | 1,024 chars | the `description:` value only |
| spec backstop | — | 2,770 words / 500 lines | the **whole file**, frontmatter included |
The 600/900 pair and the 2,770/500 pair are not the same measurement and must not be unified: the
first is a quality gate on what the caller's context absorbs, the second a conformance backstop on
the file. A skill can sit well inside one and fail the other.
When a body approaches its ceiling, relocate rather than delete — move reference material to
`references/<topic>.md` behind a conditional trigger, and bundle repeated executable logic into
`scripts/` rather than reinventing it each run.
## Body patterns
**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: ...
````
**Dispatch table** (two or more mutually exclusive flows):
````markdown
| Condition | Flow | Reference |
|---|---|---|
| <condition> | <flow> | `references/<file>.md` |
````
**Output format template** (when the skill produces structured output):
````markdown
Output format:
```
<field>: <value>
```
````
For longer templates, place them in `assets/<name>.md` and reference conditionally.
## 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 the create flow's 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.

View File

@@ -0,0 +1,173 @@
---
source_keys:
- agentskills-home
- agentskills-spec
- agentskills-best-practices
- agentskills-quickstart
- agentskills-using-scripts
---
# Creating a new skill
Return to `SKILL.md` Step 4 once Step 6 below is done — validation, versioning and commit
verification are shared with the improve flow and are not repeated here.
## 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?
- [ ] Skill name (kebab-case) and destination path
If any are missing, stop and ask the user before proceeding.
**Requires `/skill-audit`** — used in `SKILL.md` Step 4 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.
## Package-intent gate
Judge whether the destination is meant to be inside an APM package before running the scaffold
script — the script cannot tell "no package here" apart from "package not scaffolded yet":
- Package intent but no `type:`-bearing `apm.yml` found at or 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. Do not fall through to standalone mode.
- Otherwise (a `~/`-rooted destination, or no package context implied) → continue to Step 1.
## 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>/`.
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 is not part of
`scripts/new-skill.sh`.
## Step 3 — Fill in SKILL.md
Open the new skill's `SKILL.md` (the path Step 1 printed) and replace every `FILL IN:`
placeholder. The scaffold template already carries the compliant frontmatter and body skeleton —
fill it rather than restructuring it.
**`name`** — already set by the scaffold script. Must exactly match the directory name. Format:
1–64 characters, lowercase letters, numbers and hyphens only; no leading, trailing or consecutive
hyphens (`--`).
**`description`** — carries the entire triggering burden and is preloaded every session. Write it
against `references/contract.md`, which holds the three-part shape, the banned content, the
boundary-clause form and the length tiers. A hand-invoked skill (`SKILL.md` Step 2) takes one
plain sentence and `disable-model-invocation: true` instead.
**Optional frontmatter** — 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 (Step 6)
if research sources are in context
- `allowed-tools` — space-separated pre-approved tools; reduces permission prompts (experimental —
support varies by client)
- `disable-model-invocation` — hand-invoked skills only
**`metadata.source_keys`** — if research sources are in context, list the relevant slugs as you
write the body; do not 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
```
**Body** — write the decision procedure only, following the body rules and patterns in
`references/contract.md`. Rename the placeholder section headings to ones that fit the skill's
structure.
## Step 4 — Add scripts (if needed)
Place executable scripts in `scripts/`. Critical rule: **no interactive prompts** — agents run
non-interactive, and 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 with the literal form ``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`.
Then return to `SKILL.md` Step 4.

View File

@@ -0,0 +1,82 @@
---
source_keys:
- agentskills-best-practices
- agentskills-evaluating-skills
- agentskills-optimizing-descriptions
---
# Improving an existing skill
Return to `SKILL.md` Step 4 once Step 4 below is done — validation, versioning and commit
verification are shared with the create flow and are not repeated here.
## 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 directory 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."
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. Patching per symptom is the default failure mode:
three eval failures may all trace to one missing instruction. 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, do not patch.** Find the underlying gap, not the specific example that failed. A fix
scoped only to the test cases you have seen will overfit and perform worse on new inputs.
**Keep it lean.** Remove instructions that are not 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.
**Retrofit before extending.** Any edit to a skill that predates ADR-0020 has to bring it into the
contract first — the gates are hot and carry no baseline file, so a one-line fix to a
non-compliant skill cannot be committed until the description and body meet
`references/contract.md`. Treat that retrofit as part of the same change, not a follow-up.
If a signal points to a script or reference file, edit that file directly rather than adding a
workaround in SKILL.md.
Then return to `SKILL.md` Step 4.

View File

@@ -18,7 +18,7 @@ source_keys:
- **URL:** https://agentskills.io/home.md
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
- **Description:** Agent Skills overview — what it is, why it exists, progressive disclosure model, ecosystem of 35+ implementing tools
- **Contributing files:** SKILL.md
- **Contributing files:** SKILL.md, references/create.md
- **Status:** `extracted`
## agentskills-spec
@@ -26,7 +26,7 @@ source_keys:
- **URL:** https://agentskills.io/specification.md
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
- **Description:** Complete SKILL.md format specification — frontmatter fields, constraints, body content, optional directories, progressive disclosure levels, file references, validation
- **Contributing files:** SKILL.md, references/deployment-modes.md
- **Contributing files:** SKILL.md, references/create.md, references/contract.md, references/deployment-modes.md
- **Status:** `extracted`
## agentskills-best-practices
@@ -34,7 +34,7 @@ source_keys:
- **URL:** https://agentskills.io/skill-creation/best-practices.md
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
- **Description:** Best practices for skill creators — starting from real expertise, spending context wisely, calibrating control, instruction patterns (gotchas, templates, checklists, validation loops)
- **Contributing files:** SKILL.md
- **Contributing files:** SKILL.md, references/create.md, references/improve.md, references/contract.md
- **Status:** `extracted`
## agentskills-optimizing-descriptions
@@ -42,7 +42,7 @@ source_keys:
- **URL:** https://agentskills.io/skill-creation/optimizing-descriptions.md
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
- **Description:** How to systematically test and improve skill descriptions for triggering accuracy — eval queries, trigger rate testing, train/validation splits, optimization loop
- **Contributing files:** SKILL.md
- **Contributing files:** SKILL.md, references/improve.md, references/contract.md
- **Status:** `extracted`
## agentskills-evaluating-skills
@@ -50,7 +50,7 @@ source_keys:
- **URL:** https://agentskills.io/skill-creation/evaluating-skills.md
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
- **Description:** Eval-driven skill quality improvement — test case design, workspace structure, assertion writing, grading, benchmarking, human review, iteration loop
- **Contributing files:** SKILL.md
- **Contributing files:** SKILL.md, references/improve.md
- **Status:** `extracted`
## agentskills-using-scripts
@@ -58,7 +58,7 @@ source_keys:
- **URL:** https://agentskills.io/skill-creation/using-scripts.md
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
- **Description:** Using scripts in skills — one-off commands, self-contained scripts with inline dependencies, designing scripts for agentic use (no interactive prompts, --help, structured output, idempotency)
- **Contributing files:** SKILL.md, references/scripts.md
- **Contributing files:** SKILL.md, references/create.md, references/scripts.md
- **Status:** `extracted`
## agentskills-quickstart
@@ -66,5 +66,5 @@ source_keys:
- **URL:** https://agentskills.io/skill-creation/quickstart.md
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
- **Description:** Step-by-step guide to creating a first skill (roll-dice example), how discovery/activation/execution work in practice
- **Contributing files:** SKILL.md
- **Contributing files:** SKILL.md, references/create.md
- **Status:** `extracted`