refactor(skills): retrofit the corpus to the ADR-0020 context contract #129

Merged
Defame1297 merged 89 commits from refactor/adr0020-skill-retrofit into main 2026-09-01 13:47:47 +00:00
42 changed files with 540 additions and 342 deletions
Showing only changes of commit dac9cad912 - Show all commits

View File

@@ -20,7 +20,7 @@ metadata:
- Do not narrate PASS/FAIL per check while auditing. Gather findings internally and surface them only in the Step 4 report. Narrating each check as you go is the default failure mode here.
- Agents take the same 250/400-character description gates as skills and **no body word gate at all** — an agent body becomes the system prompt of a fresh context, so the 900-word skill ceiling does not transfer. Judge an over-long agent body through the delegation check, never by word count.
- At plugin/APM scope the agent is a single vendor-neutral file by design: never raise a pair-consistency finding there, and provider safety stops meaning Claude-Code-versus-Copilot field leakage.
- At plugin/APM scope the agent is a single vendor-neutral file by design, so provider safety stops meaning Claude-Code-versus-Copilot field leakage there.
- Vale reporting `0 files` scanned means NOT RUN, not clean. Fall back to full Step 3 judgment for every dimension it would have covered.
## Step 1 — Deterministic checks
@@ -30,7 +30,7 @@ Resolve all three paths against this skill's own directory so they work from a r
```bash
bash scripts/validate.sh <agent-file>
bash scripts/validate-provenance.sh <agent-file>
scripts/vale-wrap.sh <agent-file> [<counterpart-file>]
bash scripts/vale-wrap.sh <agent-file> [<counterpart-file>]
```
`validate.sh` takes either half of a project/user-scope pair or the single plugin/APM-scope file, detects the provider from the extension and the scope by walking up, then checks required fields, kebab-case `name`, `FILL IN:` placeholders, template HTML comments left in frontmatter, the ADR-0020 description budget (250 chars SUGGESTION, 400 FAIL, measured on the folded YAML value) and the fields that scope permits. Its findings become the `### Structure` dimension — its FAILs and its SUGGESTIONs both — except the ones the Step 2 scope contract re-routes.

View File

@@ -38,9 +38,9 @@ whose vocabulary differs per harness — Claude Code names its own tools, Copilo
other, and `apm compile` copies frontmatter verbatim with no per-target integrator to reconcile
them. `disallowedTools` is a **denylist**, and denying by name is safe under verbatim copy: a name
the other harness does not recognise denies nothing, so the worst case is that the fence is absent
there, never that the wrong capability is granted. Claude Code honours it for plugin subagents —
`docs/research/docs/claude-code-plugins/agent-definition.md:99` names the fields plugin agents
silently ignore (`hooks`, `mcpServers`, `permissionMode`) and `disallowedTools` is not among them.
there, never that the wrong capability is granted. Claude Code honours it for plugin subagents: its
plugin agent-definition reference names the fields plugin agents silently ignore (`hooks`,
`mcpServers`, `permissionMode`), and `disallowedTools` is not among them.
`disallowedTools` also appears in `claude-code-only-fields` above, and that stays correct: at
project/user scope it is still a Claude-only field and must not appear in a Copilot `.agent.md`.

View File

@@ -4,7 +4,7 @@ Authors, scaffolds, compiles, and audits apm packages and marketplaces.
## What it does
Covers the apm.yml lifecycle a session moves through repeatedly: configuring/scaffolding a package manifest, resolving/fetching its declared dependencies, building or registering a marketplace, compiling/packing/publishing a distributable, and validating integrity via apm audit. Dispatches by requested action to one of five reference files, each self-contained for its concern.
Covers the apm.yml lifecycle a session moves through repeatedly: configuring/scaffolding a package manifest, resolving/fetching its declared dependencies, building or registering a marketplace, compiling/packing/publishing a distributable, and validating integrity via apm audit. Dispatches on the resolved flow to one of five reference files; each carries that flow's traps and names a sibling file where one flow genuinely depends on another's detail.
## Before you start
@@ -24,7 +24,7 @@ Requires the `apm` binary and (for runtime-driven scripts) an agent runtime alre
| File | Purpose |
|------|---------|
| `SKILL.md` | Dispatch table and the two gotchas common to every branch (MCP secret indirection, the `experimental enable registries` precondition) |
| `SKILL.md` | Dispatch table and the three gotchas common to every branch (MCP secret indirection, the `experimental enable registries` precondition, the unchecked `type:` field) |
| `references/configure.md` | apm.yml schema, apm plugin init, dependency forms, MCP secrets, `includes:`, registries; `type:` and `experimental enable registries` traps |
| `references/install.md` | apm install, apm install [PACKAGE_REF], --update, --target agent-skills |
| `references/marketplace.md` | Building/registering a marketplace, `marketplace add` vs `package add`, package registration, versioning, Claude Code reserved-name/publish-confirm gotchas |

View File

@@ -1,11 +1,10 @@
---
name: apm-workflow
description: >
Use when the user wants to author, scaffold, install, compile, publish, or
audit an apm package, an apm.yml manifest, or an apm marketplace, or register
someone else's to consume — even when they do not say "apm"
explicitly, e.g. "set up the package manifest". Not the apm binary itself or
an agent runtime -> `apm-install`.
Use when managing an apm package, its apm.yml manifest, or an apm
marketplace — authoring through publishing — even when the user does not say
"apm", e.g. "set up the package manifest". Not the apm binary or an agent
runtime -> `apm-install`.
metadata:
category: apm
source_keys:
@@ -16,18 +15,19 @@ metadata:
- MCP server secrets in `apm.yml` (headers, env vars) must use `${VAR}` indirection, never literal values, so they resolve at install or runtime and are never committed.
- `apm experimental enable registries` must run before a `registries:` block or `registry.*` config takes effect anywhere — configure, install or publish. Without it, declaring one silently does nothing: no error, no warning.
- `apm.yml`'s `type:` selects which primitives are processed and is never checked against what `.apm/` holds, so `apm install` and `apm compile` can exit 0 having shipped none of the ones you expected. Set it to cover every primitive the package ships, and confirm the deployed output, not the exit code. Mechanics: `references/configure.md`.
## Step 1 — Dispatch
| Invocation | Action | Reference |
| Condition | Flow | Reference |
|---|---|---|
| `/apm-workflow configure` | Author/edit `apm.yml`; scaffold a new package (`apm plugin init`) | `references/configure.md` |
| `/apm-workflow install` | Resolve/fetch dependencies declared in `apm.yml` (`apm install`, `apm install [PACKAGE_REF]`) | `references/install.md` |
| `/apm-workflow marketplace` | Build a marketplace, register packages into it (local: hand-edit `apm.yml`; remote: `apm marketplace package add`), or register a marketplace as a consumer (`apm marketplace init/check/package add/add`) | `references/marketplace.md` |
| `/apm-workflow compile` | Generate per-target output, bundle, or publish (`apm compile`, `apm pack`, `apm publish`) | `references/compile.md` |
| `/apm-workflow audit` | Validate integrity/policy or wire a CI gate (`apm audit`, `apm audit --ci`) | `references/audit.md` |
| Author or edit `apm.yml`, or scaffold a new package (`apm plugin init`) | configure | `references/configure.md` |
| Resolve or fetch the dependencies `apm.yml` declares (`apm install`, `apm install [PACKAGE_REF]`) | install | `references/install.md` |
| Build a marketplace, register a package into it (local: hand-edit `apm.yml`; remote: `apm marketplace package add`), or register someone else's as a consumer (`apm marketplace init/check/package add/add`) | marketplace | `references/marketplace.md` |
| Generate per-target output, bundle, or publish (`apm compile`, `apm pack`, `apm publish`) | compile | `references/compile.md` |
| Validate integrity/policy or wire a CI gate (`apm audit`, `apm audit --ci`) | audit | `references/audit.md` |
Read only the reference file matching the requested action — each is self-contained for its concern, and each carries the traps specific to its flow.
Read the reference file matching the resolved flow — it carries that flow's own traps, and names a sibling file wherever one flow genuinely depends on another's detail.
## Step 2 — Execute

View File

@@ -51,7 +51,7 @@ apm publish --package acme/my-skill
Publishes a producer package (root containing `apm.yml`, `.apm/`, and optionally a `registries:` block) to a registry. Always dry-run with `-v` first — publishing is not trivially reversible once a version tag is claimed on a registry.
Publishing to a named registry requires `apm experimental enable registries` to have already run — see `references/configure.md`'s Gotchas for the full precondition and its silent-no-op failure mode.
Publishing to a named registry requires `apm experimental enable registries` to have already run — see `SKILL.md`'s Gotchas for the precondition and its silent-no-op failure mode.
## Run

View File

@@ -35,8 +35,6 @@ version: 1.0.0
- `registries` — named registry endpoints for shorthand dependency resolution
- `marketplace` — owner + packages list; see `references/marketplace.md` for the full marketplace workflow
See `docs/research/docs/microsoft-apm/configuration.md` for the complete annotated schema.
## Bumping a package's own version (repo policy)
apm ships no version-bump command, so `version:` in a package's own `apm.yml` is a hand edit.

View File

@@ -19,4 +19,4 @@ With no arguments, resolves and installs everything declared under `dependencies
`--target agent-skills` generates the vendor-neutral output directory instead of a Claude/Copilot-specific one — for IDE-agnostic tool support.
If a `PACKAGE_REF` resolves through a named registry rather than a plain git source, `apm experimental enable registries` must already have been run — see `references/configure.md`'s Gotchas for the full precondition and its silent-no-op failure mode.
If a `PACKAGE_REF` resolves through a named registry rather than a plain git source, `apm experimental enable registries` must already have been run — see `SKILL.md`'s Gotchas for the precondition and its silent-no-op failure mode.

View File

@@ -4,7 +4,7 @@ Guided entry point for building or improving something in any plugin of this rep
## What it does
Grills the user's intent via `bin:grill-with-docs` (inline, interactive) against this repo's `CONTEXT.md` and `docs/adr/`, classifies the target artifact type (skill, agent/subagent definition, plugin, or marketplace entry), announces the classification, then routes to the matching author skill — chaining more than one, in dependency order, if the intent spans multiple artifact types.
Grills the user's intent via `grill-with-docs` (inline, interactive) against this repo's `CONTEXT.md` and `docs/adr/`, classifies the target artifact type (skill, agent/subagent definition, plugin, or marketplace entry), announces the classification, then routes to the matching author skill — chaining more than one, in dependency order, if the intent spans multiple artifact types.
Author-skill invocation defaults to a fork subagent (inherits the grilled-intent context) and falls back to inline when forking isn't possible or the routed flow needs live user interaction (clarifying questions, a HITL gate). After a `skill-author` or `agent-author` route finishes — each already closes out with its own inline audit — forge spins up a separate clean-context subagent to independently re-run the matching audit skill (`skill-audit` / `agent-audit`) as a distinct check on the finished artifact, not a duplicate of the inline one. If that clean audit turns up any unresolved finding, forge loops — re-invoke the author skill to resolve it, re-run the clean audit — until the clean audit comes back with nothing unresolved. `apm-workflow` routes (plugin, marketplace entry) get no recheck: they have no audit counterpart, and no automatic terminal check either — `apm audit` is a separate `apm-workflow` action, not a closing step of the configure or marketplace flow — so forge verifies those routes by reading the written manifest back against the grilled intent.

View File

@@ -1,12 +1,11 @@
---
name: forge
description: >
Use when the user wants to build, add, or improve something but has not yet
named the artifact type — skill, agent, plugin, or marketplace entry; "a
skill for the gitea plugin, or an agent?". Grills the intent, classifies the
artifact, then routes to the matching author skill. Do not use when the type
is already named — invoke `skill-author`, `agent-author` or `apm-workflow`
directly.
Use when the user wants to build or improve something but has not yet named
the artifact type — skill, agent, plugin, or marketplace entry; "a skill for
the gitea plugin, or an agent?". Routes to the matching author skill. Do not
use when the type is already named — invoke `skill-author`, `agent-author`
or `apm-workflow` directly.
metadata:
category: factory
source_keys:
@@ -18,11 +17,11 @@ metadata:
## Gotchas
- forge is an optional guided entry point, not a gate — `skill-author`, `skill-audit`, `agent-author`, `agent-audit` and `apm-workflow` all stay directly invokable, and forge never intercepts a direct call to one.
- Claude Code's skill-level `context: fork` frontmatter field and the `/fork` subagent command are opposites despite the shared word: `context: fork` isolates (fresh context, no parent access), while `/fork` inherits the full conversation. Every routing branch below turns on that distinction.
- Claude Code's skill-level `context: fork` frontmatter field and the `/fork` subagent command are opposites despite the shared word: `context: fork` isolates (fresh context, no parent access), while `/fork` inherits the full conversation. The route reference each classification loads spends that distinction: `references/author-routes.md` chooses between the two, `references/apm-routes.md` rules the fork out.
## Step 1 — Grill the intent
Call `bin:grill-with-docs` unless a grill session has already run and is available in the context.
Call `grill-with-docs` unless a grill session has already run and is available in the context.
Grilling regularly overturns the artifact type assumed at the start, or splits one idea into several artifacts, so it runs before classification rather than confirming it. Run it inline in the current conversation — grilling is interactive and a subagent cannot hold the back-and-forth.
@@ -48,4 +47,4 @@ When the intent spans several rows, chain the routes in dependency order — an
## Step 3 — Closing gates, common to every route
- **Resolve before closing.** A route is finished only when its verification reports nothing unresolved. An actionable finding reopens the route; it is never reported onward as a caveat.
- **Bump the package version.** If the finished route's completion message carries no evidence of a package version bump, read `references/version-bump.md`.
- **Bump the package version.** A skill route always lands here: `skill-author` moves only a skill's own `metadata.version`, which is not the package `apm.yml`'s number — so read `references/version-bump.md` after one. `agent-author` and the apm routes bump the package themselves at plugin scope; after those, read it only when their output does not say they did.

View File

@@ -5,9 +5,12 @@ source_keys:
# Bumping the package version after a route
Reached from `SKILL.md` Step 3 when a route has finished and its completion message carries no
evidence that the package version was bumped. The author skills bump it themselves in some flows,
so check their output before doing anything here — a second bump for one artifact is wrong.
Reached from `SKILL.md` Step 3 after a route has finished. A skill route always lands here:
`skill-author` moves only a skill's own `metadata.version`, which is not the package manifest's
number, so the package version is still behind when it reports done. `agent-author` bumps the
resolved package's `apm.yml` itself at plugin/APM scope, and `apm-workflow`'s configure flow
carries the same policy — read those routes' output before acting here, because a second bump for
one change is wrong.
## Find the owning package
@@ -33,5 +36,5 @@ brief:
Clean context rather than a fork is the point: the bump decision is made independently, without
anchoring on the authoring conversation that just argued for the artifact's significance.
Then report to the user: "Updated `<package-name>` version from X.Y.Z to X.Y.Z to reflect the new
`<artifact-name>`."
Then report to the user: "Updated `<package-name>` version from `<old>` to `<new>` to reflect the
new `<artifact-name>`."

View File

@@ -6,7 +6,7 @@ Audit a skill directory against the agentskills.io specification and the house c
1. Runs `scripts/validate.sh` and `scripts/validate-provenance.sh` for structural and provenance checks, plus `scripts/vale-wrap.sh` — a Vale prefilter that deterministically flags non-imperative description openers, composition and architecture notes, vague wording, padding phrases, and "There is/are" sentence openers
2. Reads all files in the skill directory
3. Applies qualitative checks across five dimension groups, loading one rubric from `references/` per group
3. Applies qualitative checks across five dimension groups — always loading `references/finding-criteria.md`, then one rubric from `references/` per group the criteria put in play
4. Outputs a compact findings report — findings only, grouped by dimension, each with Why and Fix — and a result block with handoff to `skill-author`
`validate.sh` enforces two independent length families that must not be conflated: the agentskills.io spec conformance ceilings (500 lines, 2,770 words, both counting the whole file) and the ADR-0020 context budget (250/400 description characters, 600/900 body-only words).
@@ -35,6 +35,7 @@ Provide the path to the skill directory to audit when invoking.
| `assets/vale/styles/Kyberforge/PaddingPhrase.yml` | Vale rule — flags generic "see references/" padding phrasing in conditional references |
| `assets/vale/styles/Kyberforge/SentenceOpenerThereIs.yml` | Vale rule — flags body sentences starting with "There is"/"There are" |
| `assets/vale/styles/Kyberforge/VagueWording.yml` | Vale rule — flags known filler wording (e.g. "helps with", "utilize") |
| `references/finding-criteria.md` | Every dimension's FAIL and SUGGESTION criteria — the one Step 3 file loaded on every run; it decides which rubrics below are worth loading |
| `references/description-quality.md` | Rubric for the description dimension — three-part shape, the 250/400-character budget, the hand-invoked (`disable-model-invocation`) contract, and the internal-mechanics FAIL |
| `references/body-discipline.md` | Rubric for the body-discipline dimension — the core test, the 600/900 body-only budget against the 2,770-word whole-file backstop, the mandatory-dispatch rule, and the Gotchas constraints |
| `references/patterns.md` | Rubric for the patterns dimension — which instruction construct fits which job, and how each is correctly formed |

View File

@@ -30,7 +30,7 @@ Resolve all three paths against this skill's own directory so they work from a r
```bash
bash scripts/validate.sh <skill-dir>
bash scripts/validate-provenance.sh <skill-dir>
scripts/vale-wrap.sh <skill-dir>/SKILL.md
bash scripts/vale-wrap.sh <skill-dir>/SKILL.md
```
`validate.sh` findings become the `### Structure` dimension — its FAILs and its SUGGESTIONs both.
@@ -53,9 +53,9 @@ Read `SKILL.md`, `README.md`, and every text file under `scripts/`, `references/
## Step 3 — Qualitative audit
Load a dimension's rubric before judging that dimension. Each is self-contained, and each is grounded in the agentskills.io specification plus the house context-budget contract (ADR-0020).
Read `references/finding-criteria.md` first — every dimension's FAIL and SUGGESTION criteria. Load the rubric below only for a dimension the criteria put in play: one carrying a candidate finding, or one where the criterion alone does not settle the call.
| Dimension | Read |
| Dimension | Rubric |
|---|---|
| description | `references/description-quality.md` |
| body-discipline | `references/body-discipline.md` |
@@ -63,7 +63,7 @@ Load a dimension's rubric before judging that dimension. Each is self-contained,
| file-structure, internal-consistency | `references/file-structure.md` |
| formatting, scripts | `references/formatting-and-scripts.md` |
Cite file and line number for every finding.
Each rubric is self-contained and grounded in the agentskills.io specification plus the house context budget (ADR-0020). Cite file and line number for every finding.
## Step 4 — Report

View File

@@ -80,14 +80,28 @@ table** plus the gates common to every branch, and each flow lives in its own se
`references/` file. Inlining all of them is a FAIL regardless of word count, because every
invocation then pays for every branch it did not take.
The reference shape in this repo is `apm-workflow`: a **237-word body** dispatching to roughly
3,400 words of references across five mutually exclusive invocations. Its whole-file count is 304
words — cite 237 when calibrating a body, or the conflation this section warns against reappears
in the finding itself.
The reference shape in this repo is `apm-workflow`: a **294-word body** dispatching to 3,154 words
of references across five mutually exclusive flows. Its whole-file count is 348 words — cite 294
when calibrating a body, or the conflation this section warns against reappears in the finding
itself. The 3,154 counts the five flow files only; `references/sources.md` is a provenance record
and is never loaded at runtime, so counting it inflates the dispatched total.
Note its wiring: a three-column table (invocation, action, reference file) closed by one line,
*"Read only the reference file matching the requested action …"* That is the endorsed shape, and it
is why the literal-conditional requirement above exempts a body that dispatches. Do not flag it.
### What earns the wiring exemption
A dispatch table earns the exemption above on its properties, not on which skill it appears in.
Audit any dispatching body against these four:
- Every flow the skill handles has a row, and every row names a target file that exists on disk.
- Each row pairs a condition the agent can evaluate from the request with exactly one target. A row
keyed on a literal slash invocation fails this: a model-invoked activation never produces that
string, so the routing silently falls to whatever else the row carries.
- One line after the table tells the agent to read the file its row matched, and only that one.
- The gates every branch needs sit in the body, not inside one flow's file — see the reachability
precondition below.
A table missing any of the four is not exempt, and the literal-conditional requirement applies to it
as written. The exemption covers the wiring form only: every other rule in this file applies to a
dispatching skill exactly as it applies to any other.
## Gotchas sections
@@ -184,24 +198,5 @@ Use pypdf, pdfplumber, PyMuPDF, or pdf2image...
Use pdfplumber for text extraction. For scanned PDFs requiring OCR, use pdf2image instead.
```
## Auditing guidance
Flag as FAIL if:
- A sentence answers "no" to the core test — it is padding
- The body exceeds 900 words counted body-only (`validate.sh` reports it)
- Two or more mutually exclusive flows are inlined instead of dispatched
- A Gotcha paraphrases a step in the body below it that every branch reaching the Gotcha also
reaches
- A decision point presents a menu of options with no default
- An instruction repeats content already in the description
- A prescriptive sequence is used where flexibility is fine, or the reverse
Flag as SUGGESTION if:
- The body exceeds 600 words counted body-only but stays at or under 900
- The Gotchas section carries more than five entries
- The Gotchas section exceeds 25% of the body
- A rationale is missing from an include/exclude rule — present but unexplained
- Gotchas are correct but placed late in the body rather than near the top
- Content that only one branch reaches is inlined where a `references/` file would serve
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -80,38 +80,5 @@ description: >
(`data-model` is illustrative. In a real description the target has to resolve.)
## Auditing guidance
Flag as FAIL if:
- **Over 400 characters.** Measured on the folded YAML value, not the raw source lines.
`validate.sh` reports the number; do not re-derive it, but do point the Fix at what to cut.
- **Internal mechanics appear in the description.** Any of:
- capability enumeration or a feature list;
- output-format detail ("Produces a compact findings report with Why and Fix per finding");
- composition or architecture notes ("composes X rather than duplicating Y", "a cross-cutting
shared skill", "the human-facing entry point", "replaces the old flat invocation");
- implementation detail ("self-validates via a bundled deterministic script").
None of it can change a routing decision and all of it is preloaded.
`Kyberforge.CompositionNote` catches the common phrasings deterministically; the rest is
judgment. This is the rule that deflates a description, so apply it before reaching for length.
- **The same trigger stated twice in two registers** — a verb list, then the same verbs re-quoted
as user phrasings, usually in the same order. One register, whichever routes better.
- **Descriptive rather than imperative phrasing** (`This skill ...`, `This is the ...`).
`Kyberforge.DescriptionOpener` catches any opener matching `^This`.
- **Vague capabilities** ("helps with APIs" where "parses and validates OpenAPI specs" was
available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is
judgment.
- **A boundary clause naming a target that does not resolve** to a real skill directory or agent
file in the authoring source. `validate.sh` reports the unresolved name.
- **Trigger-list, boundary or indirect-trigger content on a hand-invoked skill** — see Step 0.
- **Over 1024 characters** — the agentskills.io specification ceiling, unchanged and independent
of the 400-character house ceiling above.
Flag as SUGGESTION if:
- **Over 250 characters** but at or under 400. This tier is what moves the corpus average; the FAIL
tier only stops outliers. Report it rather than treating a 399-character description as clean.
- A near-miss exclusion is present but targets a weak near-miss.
- An indirect trigger is present and warranted but could name the omitted phrasing more precisely.
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -24,9 +24,19 @@ knows to look at. Flag any other directory as a FAIL.
## Cross-plugin path references
A plugin is copied to a cache on install, and a path that climbs out of the skill directory stops
resolving there. Flag any `../`, `../../`, or absolute repo path (`plugins/<plugin>/skills/<other>/`
and its APM-native equivalent `.apm/skills/<other>/`) appearing in `SKILL.md`, `scripts/`,
`references/` or `assets/`.
resolving there. Flag a path in `SKILL.md`, `scripts/`, `references/` or `assets/` when it
**resolves outside the skill directory** — an absolute repo path
(`plugins/<plugin>/skills/<other>/` and its APM-native equivalent `.apm/skills/<other>/`), a
plugin-root path (`docs/`, `bin/`), or a `../` chain that leaves the skill root.
Resolve before flagging, twice over:
- **Resolve the path.** `$SKILL_DIR/../assets/templates` climbs one level from a `scripts/`
directory and lands back inside the same skill, so it resolves in a cache install and is not a
finding. A bare `../` is not the defect; leaving the skill is.
- **Skip fenced code blocks.** A path inside a fenced block is an example, and rubrics quote outside
paths deliberately as negative examples of what not to write. Flag a fenced path only when the
surrounding prose presents it as the form to copy.
**Referring to another skill's file.** There is one sanctioned spelling, and it is possessive:
`skill-audit's references/validation-scripts.md`. Write the skill by name and let the reader
@@ -39,9 +49,10 @@ on-disk check. Flag any other spelling of a cross-skill reference.
Two directories are exempt, and the exemptions are structural rather than discretionary:
- **`references/sources.md`.** Its `Research doc:` fields are development-time provenance pointers,
not runtime references. They are expected to be unresolvable after install, and
`validate-provenance.sh` handles that by skipping upstream checks silently when the path is
absent. Flagging them would make every correctly-provenanced skill fail.
not runtime references. They are expected to be unresolvable after install, so
`validate-provenance.sh` does not treat an absent path as a FAIL — it emits an INFO naming the
slug and stating that checks 7 and 8 did not run for it. Flagging them as broken references
would make every correctly-provenanced skill fail.
- **`tests/`.** Test files are dev-only and may reference repo-level infrastructure such as a shared
`tests/test_helper/`. The exemption is conditional on the dependency being declared: if `tests/`
exists and `tests/README.md` is absent or does not document it, that is a FAIL.
@@ -60,19 +71,5 @@ The skill has to agree with itself. Three checks:
A stale README row is the most common finding here and the easiest to miss from inside an
authoring pass, because the author knows what was intended and reads it into the gap.
## Auditing guidance
Flag as FAIL if:
- A directory outside the four permitted ones exists
- Test files sit in `scripts/`
- A non-spec file sits at the skill root
- A cross-plugin or parent-relative path appears outside the two exempt locations
- `tests/` exists but `tests/README.md` is missing or does not document its repo-level dependency
- `README.md` is absent, or its file table has a missing or stale row
- `SKILL.md` describes a script invocation the script does not accept
Flag as SUGGESTION if:
- An optional directory exists but holds only a placeholder README
- `README.md` is accurate but describes a file's purpose more thinly than `SKILL.md` does
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -0,0 +1,132 @@
---
source_keys:
- agentskills-spec
- agentskills-best-practices
- agentskills-optimizing-descriptions
- agentskills-using-scripts
---
# Finding Criteria
Every FAIL and SUGGESTION criterion, for every qualitative dimension, and nothing else. The
reasoning each criterion stands on, its worked examples and its house rules stay in that
dimension's rubric, which Step 3 loads only for a dimension this file puts in play.
Two rules on using it:
- A criterion that plainly applies is a finding. Write it up citing file and line.
- A criterion that might apply, or whose call the wording here does not settle, is a reason to load
that dimension's rubric — never a reason to drop the candidate. This file decides which rubrics
to read; it does not settle a close call on its own.
## description — `references/description-quality.md`
Flag as FAIL if:
- **Over 400 characters.** Measured on the folded YAML value, not the raw source lines.
`validate.sh` reports the number; do not re-derive it, but do point the Fix at what to cut.
- **Internal mechanics appear in the description.** Any of:
- capability enumeration or a feature list;
- output-format detail ("Produces a compact findings report with Why and Fix per finding");
- composition or architecture notes ("composes X rather than duplicating Y", "a cross-cutting
shared skill", "the human-facing entry point", "replaces the old flat invocation");
- implementation detail ("self-validates via a bundled deterministic script").
None of it can change a routing decision and all of it is preloaded.
`Kyberforge.CompositionNote` catches the common phrasings deterministically; the rest is
judgment. This is the rule that deflates a description, so apply it before reaching for length.
- **The same trigger stated twice in two registers** — a verb list, then the same verbs re-quoted
as user phrasings, usually in the same order. One register, whichever routes better.
- **Descriptive rather than imperative phrasing** (`This skill ...`, `This is the ...`).
`Kyberforge.DescriptionOpener` catches any opener matching `^This`.
- **Vague capabilities** ("helps with APIs" where "parses and validates OpenAPI specs" was
available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is
judgment.
- **A boundary clause naming a target that does not resolve** to a real skill directory or agent
file in the authoring source. `validate.sh` reports the unresolved name.
- **Trigger-list, boundary or indirect-trigger content on a hand-invoked skill** — see Step 0 of
`references/description-quality.md`.
- **Over 1024 characters** — the agentskills.io specification ceiling, unchanged and independent
of the 400-character house ceiling above.
Flag as SUGGESTION if:
- **Over 250 characters** but at or under 400. This tier is what moves the corpus average; the FAIL
tier only stops outliers. Report it rather than treating a 399-character description as clean.
- A near-miss exclusion is present but targets a weak near-miss.
- An indirect trigger is present and warranted but could name the omitted phrasing more precisely.
## body-discipline — `references/body-discipline.md`
Flag as FAIL if:
- A sentence answers "no" to the core test — it is padding
- The body exceeds 900 words counted body-only (`validate.sh` reports it)
- Two or more mutually exclusive flows are inlined instead of dispatched
- A Gotcha paraphrases a step in the body below it that every branch reaching the Gotcha also
reaches
- A decision point presents a menu of options with no default
- An instruction repeats content already in the description
- A prescriptive sequence is used where flexibility is fine, or the reverse
Flag as SUGGESTION if:
- The body exceeds 600 words counted body-only but stays at or under 900
- The Gotchas section carries more than five entries
- The Gotchas section exceeds 25% of the body
- A rationale is missing from an include/exclude rule — present but unexplained
- Gotchas are correct but placed late in the body rather than near the top
- Content that only one branch reaches is inlined where a `references/` file would serve
## patterns — `references/patterns.md`
Flag as FAIL if:
- A Gotcha entry is a general tip or a reminder rather than a fact that defies a reasonable
assumption
- An inner code fence is unescaped inside a markdown block, breaking the render
- A checklist wraps a single step
- A conditional reference gives no trigger — `Kyberforge.PaddingPhrase` reports the common form
- The agent must produce a specific format and no output template is given
Flag as SUGGESTION if:
- Gotchas are correctly formed but placed late in the body
- An output template is present but permissive where the consumer needs it exact
- A conditional reference names a trigger that is real but broader than the branch it guards
## file-structure and internal-consistency — `references/file-structure.md`
Flag as FAIL if:
- A directory outside the four permitted ones exists
- Test files sit in `scripts/`
- A non-spec file sits at the skill root
- A path that resolves outside the skill directory appears outside the two exempt locations, in
prose rather than in a fenced example
- `tests/` exists but `tests/README.md` is missing or does not document its repo-level dependency
- `README.md` is absent, or its file table has a missing or stale row
- `SKILL.md` describes a script invocation the script does not accept
Flag as SUGGESTION if:
- An optional directory exists but holds only a placeholder README
- `README.md` is accurate but describes a file's purpose more thinly than `SKILL.md` does
## formatting and scripts — `references/formatting-and-scripts.md`
Flag as FAIL if:
- A script prompts interactively, in any form
- A script exposes no `--help`
- A destructive script has no `--dry-run`
- Data and diagnostics share a stream, so the output cannot be piped
- A relative path named in the body does not resolve
- Heading levels are inconsistent enough to break the document's structure
Flag as SUGGESTION if:
- Exit codes are meaningful but undocumented in `--help`
- A code block is untagged where a language applies
- A script is idempotent in practice but does not say so, leaving a re-run's safety unclear
- List indentation or section spacing is inconsistent without breaking the render

View File

@@ -44,20 +44,5 @@ follow from that:
undocumented one is a coin flip.
- **`--dry-run` present for destructive operations.**
## Auditing guidance
Flag as FAIL if:
- A script prompts interactively, in any form
- A script exposes no `--help`
- A destructive script has no `--dry-run`
- Data and diagnostics share a stream, so the output cannot be piped
- A relative path named in the body does not resolve
- Heading levels are inconsistent enough to break the document's structure
Flag as SUGGESTION if:
- Exit codes are meaningful but undocumented in `--help`
- A code block is untagged where a language applies
- A script is idempotent in practice but does not say so, leaving a re-run's safety unclear
- List indentation or section spacing is inconsistent without breaking the render
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -50,19 +50,5 @@ forms are judgment.
`references/` when only one dispatch branch produces that output. A template inlined for a branch
most invocations never take is body-discipline padding.
## Auditing guidance
Flag as FAIL if:
- A Gotcha entry is a general tip or a reminder rather than a fact that defies a reasonable
assumption
- An inner code fence is unescaped inside a markdown block, breaking the render
- A checklist wraps a single step
- A conditional reference gives no trigger — `Kyberforge.PaddingPhrase` reports the common form
- The agent must produce a specific format and no output template is given
Flag as SUGGESTION if:
- Gotchas are correctly formed but placed late in the body
- An output template is present but permissive where the consumer needs it exact
- A conditional reference names a trigger that is real but broader than the branch it guards
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -15,7 +15,7 @@
- **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/body-discipline.md, references/description-quality.md, references/patterns.md, references/file-structure.md, references/formatting-and-scripts.md, references/validation-scripts.md
- **Contributing files:** SKILL.md, references/body-discipline.md, references/description-quality.md, references/patterns.md, references/file-structure.md, references/formatting-and-scripts.md, references/finding-criteria.md, references/validation-scripts.md
- **Status:** `extracted`
## agentskills-best-practices
@@ -23,7 +23,7 @@
- **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, references/body-discipline.md, references/patterns.md
- **Contributing files:** SKILL.md, references/body-discipline.md, references/patterns.md, references/finding-criteria.md
- **Status:** `extracted`
## agentskills-optimizing-descriptions
@@ -31,7 +31,7 @@
- **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, references/description-quality.md
- **Contributing files:** SKILL.md, references/description-quality.md, references/finding-criteria.md
- **Status:** `extracted`
## agentskills-evaluating-skills
@@ -47,7 +47,7 @@
- **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/formatting-and-scripts.md, references/validation-scripts.md
- **Contributing files:** SKILL.md, references/formatting-and-scripts.md, references/finding-criteria.md, references/validation-scripts.md
- **Status:** `extracted`
## agentskills-quickstart

View File

@@ -63,6 +63,11 @@ or Codex, and `.apm/` source compiles for all three, so routing to one is a port
gate is right to fail it and there is no allowlist. If a built-in genuinely needs mentioning, write
it un-slashed — ``the `compact` built-in`` — which makes no routing claim and is not checked.
**One arrow, one target.** The resolver reads only the first name after an arrow, so a second is
checked by nothing and the gate emits a SUGGESTION naming both. Split instead of conjoining:
`Not <thing> -> first-skill. Not <other thing> -> second-skill.`, never
`Not <thing> -> first-skill or second-skill`.
**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
@@ -118,11 +123,25 @@ If <condition>, read `references/<file>.md`.
A generic pointer ("see references/ for details") is a Vale error — the agent cannot act on it.
**A dispatch table is the wiring.** Where the body dispatches, a row already pairs a condition with
a target, which is what the literal form encodes — so do not restate each row underneath as a prose
conditional. That duplicates the routing in the one body whose whole purpose is to be short. The
literal form is what a reference loaded *without* a table needs: a mid-procedure deepening, an
escape hatch, an error path. A table earns this on four properties — every flow has a row and every
row's target exists on disk; each row pairs exactly one target with a condition the agent can
evaluate from the request, never a literal slash invocation; one line after the table names the
matched file as the only one to read; and the gates every branch needs sit in the body, not inside
one flow's file. That last one is the property the `git-commits` v0.1.2 failure turned on, and it is
the one a dispatch split is most likely to break. `skill-audit`'s `references/body-discipline.md`
carries the audit-side form of the same exemption; the two lists are the same four properties, and
an edit to either belongs in both.
**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: the `apm-workflow` skill — a **237-word body** dispatching to 3,416 words of
references. Calibrate against 237: that file's whole-file count is 304 words, and aiming at that
number instead overshoots the body budget by ~30%.
file. Exemplar: the `apm-workflow` skill — a **294-word body** dispatching to 3,154 words of
references across five flow files. Calibrate against 294: that file's whole-file count is 348
words, and aiming at that number instead overshoots the body budget by ~18%. The 3,154 excludes
`references/sources.md`, which is a provenance record and is never loaded at runtime.
**Length.** 600 words SUGGESTION, 900 words FAIL, counting the **body only** — everything after
the frontmatter's closing `---`.
@@ -130,10 +149,20 @@ 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.
gets wrong by acting sensibly. "Write a descriptive commit message" is not one; the agent does it
unprompted and nothing in the environment argues against it. A safety gate is a different case,
even where the agent knows the rule — see the paraphrase bullet below.
- More than five entries is a SUGGESTION — five is the guideline, not a ceiling.
- 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 Gotcha that paraphrases a step in the body below it is a **FAIL**, but deleting it is correct
only when the surviving copy is **reachable from every branch that reaches the Gotcha**. In a
dispatch body it often is not: each flow file loads alone, so a step in one is invisible to an
invocation that took another branch. Where the restated rule is a safety gate more than one flow
needs, move it into the body's common-gates section instead of dropping it. `git-commits` v0.1.2
is the worked failure: the retrofit deleted its always-loaded "never commit secrets" Gotcha in
favour of a step in one flow file, and left the history-rewrite branch — which stages and
`--amend`s, committing new content exactly as a fresh commit does — with no such check anywhere
in its loaded context, against this repo's governance hard prohibitions. v0.1.3 carries the rule
as a gate on every flow.
- 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.

View File

@@ -96,6 +96,13 @@ them for you. After every retrofit that adds, removes or renames a file:
content moved into it, and remove any file the retrofit deleted. This is the one that gets
missed: `sources.md` keeps citing sections of `SKILL.md` that no longer exist, the
provenance check still exits 0, and the stale claim survives review.
- [ ] **Reachability of every relocated gate.** For each Gotcha or gate the retrofit moved out of
the body, list the flows that need it and confirm each one reaches the surviving copy. A gate
that lands in a single flow file is invisible to every other branch, and no gate detects
that: `/skill-audit` reads whichever file it was handed, and the word counts improve either
way. Where more than one flow needs it, the copy belongs in the body's common-gates section,
not in a flow file. Grep the skill for the gate's key term and check every branch that hits
zero.
- [ ] Re-run `/skill-audit` and confirm its `### Provenance` dimension does not report the new
file as missing `source_keys`.

View File

@@ -20,7 +20,7 @@ metadata:
- Do not narrate PASS/FAIL per check while auditing. Gather findings internally and surface them only in the Step 4 report. Narrating each check as you go is the default failure mode here.
- Agents take the same 250/400-character description gates as skills and **no body word gate at all** — an agent body becomes the system prompt of a fresh context, so the 900-word skill ceiling does not transfer. Judge an over-long agent body through the delegation check, never by word count.
- At plugin/APM scope the agent is a single vendor-neutral file by design: never raise a pair-consistency finding there, and provider safety stops meaning Claude-Code-versus-Copilot field leakage.
- At plugin/APM scope the agent is a single vendor-neutral file by design, so provider safety stops meaning Claude-Code-versus-Copilot field leakage there.
- Vale reporting `0 files` scanned means NOT RUN, not clean. Fall back to full Step 3 judgment for every dimension it would have covered.
## Step 1 — Deterministic checks
@@ -30,7 +30,7 @@ Resolve all three paths against this skill's own directory so they work from a r
```bash
bash scripts/validate.sh <agent-file>
bash scripts/validate-provenance.sh <agent-file>
scripts/vale-wrap.sh <agent-file> [<counterpart-file>]
bash scripts/vale-wrap.sh <agent-file> [<counterpart-file>]
```
`validate.sh` takes either half of a project/user-scope pair or the single plugin/APM-scope file, detects the provider from the extension and the scope by walking up, then checks required fields, kebab-case `name`, `FILL IN:` placeholders, template HTML comments left in frontmatter, the ADR-0020 description budget (250 chars SUGGESTION, 400 FAIL, measured on the folded YAML value) and the fields that scope permits. Its findings become the `### Structure` dimension — its FAILs and its SUGGESTIONs both — except the ones the Step 2 scope contract re-routes.

View File

@@ -38,9 +38,9 @@ whose vocabulary differs per harness — Claude Code names its own tools, Copilo
other, and `apm compile` copies frontmatter verbatim with no per-target integrator to reconcile
them. `disallowedTools` is a **denylist**, and denying by name is safe under verbatim copy: a name
the other harness does not recognise denies nothing, so the worst case is that the fence is absent
there, never that the wrong capability is granted. Claude Code honours it for plugin subagents —
`docs/research/docs/claude-code-plugins/agent-definition.md:99` names the fields plugin agents
silently ignore (`hooks`, `mcpServers`, `permissionMode`) and `disallowedTools` is not among them.
there, never that the wrong capability is granted. Claude Code honours it for plugin subagents: its
plugin agent-definition reference names the fields plugin agents silently ignore (`hooks`,
`mcpServers`, `permissionMode`), and `disallowedTools` is not among them.
`disallowedTools` also appears in `claude-code-only-fields` above, and that stays correct: at
project/user scope it is still a Claude-only field and must not appear in a Copilot `.agent.md`.

View File

@@ -4,7 +4,7 @@ Authors, scaffolds, compiles, and audits apm packages and marketplaces.
## What it does
Covers the apm.yml lifecycle a session moves through repeatedly: configuring/scaffolding a package manifest, resolving/fetching its declared dependencies, building or registering a marketplace, compiling/packing/publishing a distributable, and validating integrity via apm audit. Dispatches by requested action to one of five reference files, each self-contained for its concern.
Covers the apm.yml lifecycle a session moves through repeatedly: configuring/scaffolding a package manifest, resolving/fetching its declared dependencies, building or registering a marketplace, compiling/packing/publishing a distributable, and validating integrity via apm audit. Dispatches on the resolved flow to one of five reference files; each carries that flow's traps and names a sibling file where one flow genuinely depends on another's detail.
## Before you start
@@ -24,7 +24,7 @@ Requires the `apm` binary and (for runtime-driven scripts) an agent runtime alre
| File | Purpose |
|------|---------|
| `SKILL.md` | Dispatch table and the two gotchas common to every branch (MCP secret indirection, the `experimental enable registries` precondition) |
| `SKILL.md` | Dispatch table and the three gotchas common to every branch (MCP secret indirection, the `experimental enable registries` precondition, the unchecked `type:` field) |
| `references/configure.md` | apm.yml schema, apm plugin init, dependency forms, MCP secrets, `includes:`, registries; `type:` and `experimental enable registries` traps |
| `references/install.md` | apm install, apm install [PACKAGE_REF], --update, --target agent-skills |
| `references/marketplace.md` | Building/registering a marketplace, `marketplace add` vs `package add`, package registration, versioning, Claude Code reserved-name/publish-confirm gotchas |

View File

@@ -1,11 +1,10 @@
---
name: apm-workflow
description: >
Use when the user wants to author, scaffold, install, compile, publish, or
audit an apm package, an apm.yml manifest, or an apm marketplace, or register
someone else's to consume — even when they do not say "apm"
explicitly, e.g. "set up the package manifest". Not the apm binary itself or
an agent runtime -> `apm-install`.
Use when managing an apm package, its apm.yml manifest, or an apm
marketplace — authoring through publishing — even when the user does not say
"apm", e.g. "set up the package manifest". Not the apm binary or an agent
runtime -> `apm-install`.
metadata:
category: apm
source_keys:
@@ -16,18 +15,19 @@ metadata:
- MCP server secrets in `apm.yml` (headers, env vars) must use `${VAR}` indirection, never literal values, so they resolve at install or runtime and are never committed.
- `apm experimental enable registries` must run before a `registries:` block or `registry.*` config takes effect anywhere — configure, install or publish. Without it, declaring one silently does nothing: no error, no warning.
- `apm.yml`'s `type:` selects which primitives are processed and is never checked against what `.apm/` holds, so `apm install` and `apm compile` can exit 0 having shipped none of the ones you expected. Set it to cover every primitive the package ships, and confirm the deployed output, not the exit code. Mechanics: `references/configure.md`.
## Step 1 — Dispatch
| Invocation | Action | Reference |
| Condition | Flow | Reference |
|---|---|---|
| `/apm-workflow configure` | Author/edit `apm.yml`; scaffold a new package (`apm plugin init`) | `references/configure.md` |
| `/apm-workflow install` | Resolve/fetch dependencies declared in `apm.yml` (`apm install`, `apm install [PACKAGE_REF]`) | `references/install.md` |
| `/apm-workflow marketplace` | Build a marketplace, register packages into it (local: hand-edit `apm.yml`; remote: `apm marketplace package add`), or register a marketplace as a consumer (`apm marketplace init/check/package add/add`) | `references/marketplace.md` |
| `/apm-workflow compile` | Generate per-target output, bundle, or publish (`apm compile`, `apm pack`, `apm publish`) | `references/compile.md` |
| `/apm-workflow audit` | Validate integrity/policy or wire a CI gate (`apm audit`, `apm audit --ci`) | `references/audit.md` |
| Author or edit `apm.yml`, or scaffold a new package (`apm plugin init`) | configure | `references/configure.md` |
| Resolve or fetch the dependencies `apm.yml` declares (`apm install`, `apm install [PACKAGE_REF]`) | install | `references/install.md` |
| Build a marketplace, register a package into it (local: hand-edit `apm.yml`; remote: `apm marketplace package add`), or register someone else's as a consumer (`apm marketplace init/check/package add/add`) | marketplace | `references/marketplace.md` |
| Generate per-target output, bundle, or publish (`apm compile`, `apm pack`, `apm publish`) | compile | `references/compile.md` |
| Validate integrity/policy or wire a CI gate (`apm audit`, `apm audit --ci`) | audit | `references/audit.md` |
Read only the reference file matching the requested action — each is self-contained for its concern, and each carries the traps specific to its flow.
Read the reference file matching the resolved flow — it carries that flow's own traps, and names a sibling file wherever one flow genuinely depends on another's detail.
## Step 2 — Execute

View File

@@ -51,7 +51,7 @@ apm publish --package acme/my-skill
Publishes a producer package (root containing `apm.yml`, `.apm/`, and optionally a `registries:` block) to a registry. Always dry-run with `-v` first — publishing is not trivially reversible once a version tag is claimed on a registry.
Publishing to a named registry requires `apm experimental enable registries` to have already run — see `references/configure.md`'s Gotchas for the full precondition and its silent-no-op failure mode.
Publishing to a named registry requires `apm experimental enable registries` to have already run — see `SKILL.md`'s Gotchas for the precondition and its silent-no-op failure mode.
## Run

View File

@@ -35,8 +35,6 @@ version: 1.0.0
- `registries` — named registry endpoints for shorthand dependency resolution
- `marketplace` — owner + packages list; see `references/marketplace.md` for the full marketplace workflow
See `docs/research/docs/microsoft-apm/configuration.md` for the complete annotated schema.
## Bumping a package's own version (repo policy)
apm ships no version-bump command, so `version:` in a package's own `apm.yml` is a hand edit.

View File

@@ -19,4 +19,4 @@ With no arguments, resolves and installs everything declared under `dependencies
`--target agent-skills` generates the vendor-neutral output directory instead of a Claude/Copilot-specific one — for IDE-agnostic tool support.
If a `PACKAGE_REF` resolves through a named registry rather than a plain git source, `apm experimental enable registries` must already have been run — see `references/configure.md`'s Gotchas for the full precondition and its silent-no-op failure mode.
If a `PACKAGE_REF` resolves through a named registry rather than a plain git source, `apm experimental enable registries` must already have been run — see `SKILL.md`'s Gotchas for the precondition and its silent-no-op failure mode.

View File

@@ -4,7 +4,7 @@ Guided entry point for building or improving something in any plugin of this rep
## What it does
Grills the user's intent via `bin:grill-with-docs` (inline, interactive) against this repo's `CONTEXT.md` and `docs/adr/`, classifies the target artifact type (skill, agent/subagent definition, plugin, or marketplace entry), announces the classification, then routes to the matching author skill — chaining more than one, in dependency order, if the intent spans multiple artifact types.
Grills the user's intent via `grill-with-docs` (inline, interactive) against this repo's `CONTEXT.md` and `docs/adr/`, classifies the target artifact type (skill, agent/subagent definition, plugin, or marketplace entry), announces the classification, then routes to the matching author skill — chaining more than one, in dependency order, if the intent spans multiple artifact types.
Author-skill invocation defaults to a fork subagent (inherits the grilled-intent context) and falls back to inline when forking isn't possible or the routed flow needs live user interaction (clarifying questions, a HITL gate). After a `skill-author` or `agent-author` route finishes — each already closes out with its own inline audit — forge spins up a separate clean-context subagent to independently re-run the matching audit skill (`skill-audit` / `agent-audit`) as a distinct check on the finished artifact, not a duplicate of the inline one. If that clean audit turns up any unresolved finding, forge loops — re-invoke the author skill to resolve it, re-run the clean audit — until the clean audit comes back with nothing unresolved. `apm-workflow` routes (plugin, marketplace entry) get no recheck: they have no audit counterpart, and no automatic terminal check either — `apm audit` is a separate `apm-workflow` action, not a closing step of the configure or marketplace flow — so forge verifies those routes by reading the written manifest back against the grilled intent.

View File

@@ -1,12 +1,11 @@
---
name: forge
description: >
Use when the user wants to build, add, or improve something but has not yet
named the artifact type — skill, agent, plugin, or marketplace entry; "a
skill for the gitea plugin, or an agent?". Grills the intent, classifies the
artifact, then routes to the matching author skill. Do not use when the type
is already named — invoke `skill-author`, `agent-author` or `apm-workflow`
directly.
Use when the user wants to build or improve something but has not yet named
the artifact type — skill, agent, plugin, or marketplace entry; "a skill for
the gitea plugin, or an agent?". Routes to the matching author skill. Do not
use when the type is already named — invoke `skill-author`, `agent-author`
or `apm-workflow` directly.
metadata:
category: factory
source_keys:
@@ -18,11 +17,11 @@ metadata:
## Gotchas
- forge is an optional guided entry point, not a gate — `skill-author`, `skill-audit`, `agent-author`, `agent-audit` and `apm-workflow` all stay directly invokable, and forge never intercepts a direct call to one.
- Claude Code's skill-level `context: fork` frontmatter field and the `/fork` subagent command are opposites despite the shared word: `context: fork` isolates (fresh context, no parent access), while `/fork` inherits the full conversation. Every routing branch below turns on that distinction.
- Claude Code's skill-level `context: fork` frontmatter field and the `/fork` subagent command are opposites despite the shared word: `context: fork` isolates (fresh context, no parent access), while `/fork` inherits the full conversation. The route reference each classification loads spends that distinction: `references/author-routes.md` chooses between the two, `references/apm-routes.md` rules the fork out.
## Step 1 — Grill the intent
Call `bin:grill-with-docs` unless a grill session has already run and is available in the context.
Call `grill-with-docs` unless a grill session has already run and is available in the context.
Grilling regularly overturns the artifact type assumed at the start, or splits one idea into several artifacts, so it runs before classification rather than confirming it. Run it inline in the current conversation — grilling is interactive and a subagent cannot hold the back-and-forth.
@@ -48,4 +47,4 @@ When the intent spans several rows, chain the routes in dependency order — an
## Step 3 — Closing gates, common to every route
- **Resolve before closing.** A route is finished only when its verification reports nothing unresolved. An actionable finding reopens the route; it is never reported onward as a caveat.
- **Bump the package version.** If the finished route's completion message carries no evidence of a package version bump, read `references/version-bump.md`.
- **Bump the package version.** A skill route always lands here: `skill-author` moves only a skill's own `metadata.version`, which is not the package `apm.yml`'s number — so read `references/version-bump.md` after one. `agent-author` and the apm routes bump the package themselves at plugin scope; after those, read it only when their output does not say they did.

View File

@@ -5,9 +5,12 @@ source_keys:
# Bumping the package version after a route
Reached from `SKILL.md` Step 3 when a route has finished and its completion message carries no
evidence that the package version was bumped. The author skills bump it themselves in some flows,
so check their output before doing anything here — a second bump for one artifact is wrong.
Reached from `SKILL.md` Step 3 after a route has finished. A skill route always lands here:
`skill-author` moves only a skill's own `metadata.version`, which is not the package manifest's
number, so the package version is still behind when it reports done. `agent-author` bumps the
resolved package's `apm.yml` itself at plugin/APM scope, and `apm-workflow`'s configure flow
carries the same policy — read those routes' output before acting here, because a second bump for
one change is wrong.
## Find the owning package
@@ -33,5 +36,5 @@ brief:
Clean context rather than a fork is the point: the bump decision is made independently, without
anchoring on the authoring conversation that just argued for the artifact's significance.
Then report to the user: "Updated `<package-name>` version from X.Y.Z to X.Y.Z to reflect the new
`<artifact-name>`."
Then report to the user: "Updated `<package-name>` version from `<old>` to `<new>` to reflect the
new `<artifact-name>`."

View File

@@ -6,7 +6,7 @@ Audit a skill directory against the agentskills.io specification and the house c
1. Runs `scripts/validate.sh` and `scripts/validate-provenance.sh` for structural and provenance checks, plus `scripts/vale-wrap.sh` — a Vale prefilter that deterministically flags non-imperative description openers, composition and architecture notes, vague wording, padding phrases, and "There is/are" sentence openers
2. Reads all files in the skill directory
3. Applies qualitative checks across five dimension groups, loading one rubric from `references/` per group
3. Applies qualitative checks across five dimension groups — always loading `references/finding-criteria.md`, then one rubric from `references/` per group the criteria put in play
4. Outputs a compact findings report — findings only, grouped by dimension, each with Why and Fix — and a result block with handoff to `skill-author`
`validate.sh` enforces two independent length families that must not be conflated: the agentskills.io spec conformance ceilings (500 lines, 2,770 words, both counting the whole file) and the ADR-0020 context budget (250/400 description characters, 600/900 body-only words).
@@ -35,6 +35,7 @@ Provide the path to the skill directory to audit when invoking.
| `assets/vale/styles/Kyberforge/PaddingPhrase.yml` | Vale rule — flags generic "see references/" padding phrasing in conditional references |
| `assets/vale/styles/Kyberforge/SentenceOpenerThereIs.yml` | Vale rule — flags body sentences starting with "There is"/"There are" |
| `assets/vale/styles/Kyberforge/VagueWording.yml` | Vale rule — flags known filler wording (e.g. "helps with", "utilize") |
| `references/finding-criteria.md` | Every dimension's FAIL and SUGGESTION criteria — the one Step 3 file loaded on every run; it decides which rubrics below are worth loading |
| `references/description-quality.md` | Rubric for the description dimension — three-part shape, the 250/400-character budget, the hand-invoked (`disable-model-invocation`) contract, and the internal-mechanics FAIL |
| `references/body-discipline.md` | Rubric for the body-discipline dimension — the core test, the 600/900 body-only budget against the 2,770-word whole-file backstop, the mandatory-dispatch rule, and the Gotchas constraints |
| `references/patterns.md` | Rubric for the patterns dimension — which instruction construct fits which job, and how each is correctly formed |

View File

@@ -30,7 +30,7 @@ Resolve all three paths against this skill's own directory so they work from a r
```bash
bash scripts/validate.sh <skill-dir>
bash scripts/validate-provenance.sh <skill-dir>
scripts/vale-wrap.sh <skill-dir>/SKILL.md
bash scripts/vale-wrap.sh <skill-dir>/SKILL.md
```
`validate.sh` findings become the `### Structure` dimension — its FAILs and its SUGGESTIONs both.
@@ -53,9 +53,9 @@ Read `SKILL.md`, `README.md`, and every text file under `scripts/`, `references/
## Step 3 — Qualitative audit
Load a dimension's rubric before judging that dimension. Each is self-contained, and each is grounded in the agentskills.io specification plus the house context-budget contract (ADR-0020).
Read `references/finding-criteria.md` first — every dimension's FAIL and SUGGESTION criteria. Load the rubric below only for a dimension the criteria put in play: one carrying a candidate finding, or one where the criterion alone does not settle the call.
| Dimension | Read |
| Dimension | Rubric |
|---|---|
| description | `references/description-quality.md` |
| body-discipline | `references/body-discipline.md` |
@@ -63,7 +63,7 @@ Load a dimension's rubric before judging that dimension. Each is self-contained,
| file-structure, internal-consistency | `references/file-structure.md` |
| formatting, scripts | `references/formatting-and-scripts.md` |
Cite file and line number for every finding.
Each rubric is self-contained and grounded in the agentskills.io specification plus the house context budget (ADR-0020). Cite file and line number for every finding.
## Step 4 — Report

View File

@@ -80,14 +80,28 @@ table** plus the gates common to every branch, and each flow lives in its own se
`references/` file. Inlining all of them is a FAIL regardless of word count, because every
invocation then pays for every branch it did not take.
The reference shape in this repo is `apm-workflow`: a **237-word body** dispatching to roughly
3,400 words of references across five mutually exclusive invocations. Its whole-file count is 304
words — cite 237 when calibrating a body, or the conflation this section warns against reappears
in the finding itself.
The reference shape in this repo is `apm-workflow`: a **294-word body** dispatching to 3,154 words
of references across five mutually exclusive flows. Its whole-file count is 348 words — cite 294
when calibrating a body, or the conflation this section warns against reappears in the finding
itself. The 3,154 counts the five flow files only; `references/sources.md` is a provenance record
and is never loaded at runtime, so counting it inflates the dispatched total.
Note its wiring: a three-column table (invocation, action, reference file) closed by one line,
*"Read only the reference file matching the requested action …"* That is the endorsed shape, and it
is why the literal-conditional requirement above exempts a body that dispatches. Do not flag it.
### What earns the wiring exemption
A dispatch table earns the exemption above on its properties, not on which skill it appears in.
Audit any dispatching body against these four:
- Every flow the skill handles has a row, and every row names a target file that exists on disk.
- Each row pairs a condition the agent can evaluate from the request with exactly one target. A row
keyed on a literal slash invocation fails this: a model-invoked activation never produces that
string, so the routing silently falls to whatever else the row carries.
- One line after the table tells the agent to read the file its row matched, and only that one.
- The gates every branch needs sit in the body, not inside one flow's file — see the reachability
precondition below.
A table missing any of the four is not exempt, and the literal-conditional requirement applies to it
as written. The exemption covers the wiring form only: every other rule in this file applies to a
dispatching skill exactly as it applies to any other.
## Gotchas sections
@@ -184,24 +198,5 @@ Use pypdf, pdfplumber, PyMuPDF, or pdf2image...
Use pdfplumber for text extraction. For scanned PDFs requiring OCR, use pdf2image instead.
```
## Auditing guidance
Flag as FAIL if:
- A sentence answers "no" to the core test — it is padding
- The body exceeds 900 words counted body-only (`validate.sh` reports it)
- Two or more mutually exclusive flows are inlined instead of dispatched
- A Gotcha paraphrases a step in the body below it that every branch reaching the Gotcha also
reaches
- A decision point presents a menu of options with no default
- An instruction repeats content already in the description
- A prescriptive sequence is used where flexibility is fine, or the reverse
Flag as SUGGESTION if:
- The body exceeds 600 words counted body-only but stays at or under 900
- The Gotchas section carries more than five entries
- The Gotchas section exceeds 25% of the body
- A rationale is missing from an include/exclude rule — present but unexplained
- Gotchas are correct but placed late in the body rather than near the top
- Content that only one branch reaches is inlined where a `references/` file would serve
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -80,38 +80,5 @@ description: >
(`data-model` is illustrative. In a real description the target has to resolve.)
## Auditing guidance
Flag as FAIL if:
- **Over 400 characters.** Measured on the folded YAML value, not the raw source lines.
`validate.sh` reports the number; do not re-derive it, but do point the Fix at what to cut.
- **Internal mechanics appear in the description.** Any of:
- capability enumeration or a feature list;
- output-format detail ("Produces a compact findings report with Why and Fix per finding");
- composition or architecture notes ("composes X rather than duplicating Y", "a cross-cutting
shared skill", "the human-facing entry point", "replaces the old flat invocation");
- implementation detail ("self-validates via a bundled deterministic script").
None of it can change a routing decision and all of it is preloaded.
`Kyberforge.CompositionNote` catches the common phrasings deterministically; the rest is
judgment. This is the rule that deflates a description, so apply it before reaching for length.
- **The same trigger stated twice in two registers** — a verb list, then the same verbs re-quoted
as user phrasings, usually in the same order. One register, whichever routes better.
- **Descriptive rather than imperative phrasing** (`This skill ...`, `This is the ...`).
`Kyberforge.DescriptionOpener` catches any opener matching `^This`.
- **Vague capabilities** ("helps with APIs" where "parses and validates OpenAPI specs" was
available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is
judgment.
- **A boundary clause naming a target that does not resolve** to a real skill directory or agent
file in the authoring source. `validate.sh` reports the unresolved name.
- **Trigger-list, boundary or indirect-trigger content on a hand-invoked skill** — see Step 0.
- **Over 1024 characters** — the agentskills.io specification ceiling, unchanged and independent
of the 400-character house ceiling above.
Flag as SUGGESTION if:
- **Over 250 characters** but at or under 400. This tier is what moves the corpus average; the FAIL
tier only stops outliers. Report it rather than treating a 399-character description as clean.
- A near-miss exclusion is present but targets a weak near-miss.
- An indirect trigger is present and warranted but could name the omitted phrasing more precisely.
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -24,9 +24,19 @@ knows to look at. Flag any other directory as a FAIL.
## Cross-plugin path references
A plugin is copied to a cache on install, and a path that climbs out of the skill directory stops
resolving there. Flag any `../`, `../../`, or absolute repo path (`plugins/<plugin>/skills/<other>/`
and its APM-native equivalent `.apm/skills/<other>/`) appearing in `SKILL.md`, `scripts/`,
`references/` or `assets/`.
resolving there. Flag a path in `SKILL.md`, `scripts/`, `references/` or `assets/` when it
**resolves outside the skill directory** — an absolute repo path
(`plugins/<plugin>/skills/<other>/` and its APM-native equivalent `.apm/skills/<other>/`), a
plugin-root path (`docs/`, `bin/`), or a `../` chain that leaves the skill root.
Resolve before flagging, twice over:
- **Resolve the path.** `$SKILL_DIR/../assets/templates` climbs one level from a `scripts/`
directory and lands back inside the same skill, so it resolves in a cache install and is not a
finding. A bare `../` is not the defect; leaving the skill is.
- **Skip fenced code blocks.** A path inside a fenced block is an example, and rubrics quote outside
paths deliberately as negative examples of what not to write. Flag a fenced path only when the
surrounding prose presents it as the form to copy.
**Referring to another skill's file.** There is one sanctioned spelling, and it is possessive:
`skill-audit's references/validation-scripts.md`. Write the skill by name and let the reader
@@ -39,9 +49,10 @@ on-disk check. Flag any other spelling of a cross-skill reference.
Two directories are exempt, and the exemptions are structural rather than discretionary:
- **`references/sources.md`.** Its `Research doc:` fields are development-time provenance pointers,
not runtime references. They are expected to be unresolvable after install, and
`validate-provenance.sh` handles that by skipping upstream checks silently when the path is
absent. Flagging them would make every correctly-provenanced skill fail.
not runtime references. They are expected to be unresolvable after install, so
`validate-provenance.sh` does not treat an absent path as a FAIL — it emits an INFO naming the
slug and stating that checks 7 and 8 did not run for it. Flagging them as broken references
would make every correctly-provenanced skill fail.
- **`tests/`.** Test files are dev-only and may reference repo-level infrastructure such as a shared
`tests/test_helper/`. The exemption is conditional on the dependency being declared: if `tests/`
exists and `tests/README.md` is absent or does not document it, that is a FAIL.
@@ -60,19 +71,5 @@ The skill has to agree with itself. Three checks:
A stale README row is the most common finding here and the easiest to miss from inside an
authoring pass, because the author knows what was intended and reads it into the gap.
## Auditing guidance
Flag as FAIL if:
- A directory outside the four permitted ones exists
- Test files sit in `scripts/`
- A non-spec file sits at the skill root
- A cross-plugin or parent-relative path appears outside the two exempt locations
- `tests/` exists but `tests/README.md` is missing or does not document its repo-level dependency
- `README.md` is absent, or its file table has a missing or stale row
- `SKILL.md` describes a script invocation the script does not accept
Flag as SUGGESTION if:
- An optional directory exists but holds only a placeholder README
- `README.md` is accurate but describes a file's purpose more thinly than `SKILL.md` does
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -0,0 +1,132 @@
---
source_keys:
- agentskills-spec
- agentskills-best-practices
- agentskills-optimizing-descriptions
- agentskills-using-scripts
---
# Finding Criteria
Every FAIL and SUGGESTION criterion, for every qualitative dimension, and nothing else. The
reasoning each criterion stands on, its worked examples and its house rules stay in that
dimension's rubric, which Step 3 loads only for a dimension this file puts in play.
Two rules on using it:
- A criterion that plainly applies is a finding. Write it up citing file and line.
- A criterion that might apply, or whose call the wording here does not settle, is a reason to load
that dimension's rubric — never a reason to drop the candidate. This file decides which rubrics
to read; it does not settle a close call on its own.
## description — `references/description-quality.md`
Flag as FAIL if:
- **Over 400 characters.** Measured on the folded YAML value, not the raw source lines.
`validate.sh` reports the number; do not re-derive it, but do point the Fix at what to cut.
- **Internal mechanics appear in the description.** Any of:
- capability enumeration or a feature list;
- output-format detail ("Produces a compact findings report with Why and Fix per finding");
- composition or architecture notes ("composes X rather than duplicating Y", "a cross-cutting
shared skill", "the human-facing entry point", "replaces the old flat invocation");
- implementation detail ("self-validates via a bundled deterministic script").
None of it can change a routing decision and all of it is preloaded.
`Kyberforge.CompositionNote` catches the common phrasings deterministically; the rest is
judgment. This is the rule that deflates a description, so apply it before reaching for length.
- **The same trigger stated twice in two registers** — a verb list, then the same verbs re-quoted
as user phrasings, usually in the same order. One register, whichever routes better.
- **Descriptive rather than imperative phrasing** (`This skill ...`, `This is the ...`).
`Kyberforge.DescriptionOpener` catches any opener matching `^This`.
- **Vague capabilities** ("helps with APIs" where "parses and validates OpenAPI specs" was
available). `Kyberforge.VagueWording` catches the known filler; imprecision outside that list is
judgment.
- **A boundary clause naming a target that does not resolve** to a real skill directory or agent
file in the authoring source. `validate.sh` reports the unresolved name.
- **Trigger-list, boundary or indirect-trigger content on a hand-invoked skill** — see Step 0 of
`references/description-quality.md`.
- **Over 1024 characters** — the agentskills.io specification ceiling, unchanged and independent
of the 400-character house ceiling above.
Flag as SUGGESTION if:
- **Over 250 characters** but at or under 400. This tier is what moves the corpus average; the FAIL
tier only stops outliers. Report it rather than treating a 399-character description as clean.
- A near-miss exclusion is present but targets a weak near-miss.
- An indirect trigger is present and warranted but could name the omitted phrasing more precisely.
## body-discipline — `references/body-discipline.md`
Flag as FAIL if:
- A sentence answers "no" to the core test — it is padding
- The body exceeds 900 words counted body-only (`validate.sh` reports it)
- Two or more mutually exclusive flows are inlined instead of dispatched
- A Gotcha paraphrases a step in the body below it that every branch reaching the Gotcha also
reaches
- A decision point presents a menu of options with no default
- An instruction repeats content already in the description
- A prescriptive sequence is used where flexibility is fine, or the reverse
Flag as SUGGESTION if:
- The body exceeds 600 words counted body-only but stays at or under 900
- The Gotchas section carries more than five entries
- The Gotchas section exceeds 25% of the body
- A rationale is missing from an include/exclude rule — present but unexplained
- Gotchas are correct but placed late in the body rather than near the top
- Content that only one branch reaches is inlined where a `references/` file would serve
## patterns — `references/patterns.md`
Flag as FAIL if:
- A Gotcha entry is a general tip or a reminder rather than a fact that defies a reasonable
assumption
- An inner code fence is unescaped inside a markdown block, breaking the render
- A checklist wraps a single step
- A conditional reference gives no trigger — `Kyberforge.PaddingPhrase` reports the common form
- The agent must produce a specific format and no output template is given
Flag as SUGGESTION if:
- Gotchas are correctly formed but placed late in the body
- An output template is present but permissive where the consumer needs it exact
- A conditional reference names a trigger that is real but broader than the branch it guards
## file-structure and internal-consistency — `references/file-structure.md`
Flag as FAIL if:
- A directory outside the four permitted ones exists
- Test files sit in `scripts/`
- A non-spec file sits at the skill root
- A path that resolves outside the skill directory appears outside the two exempt locations, in
prose rather than in a fenced example
- `tests/` exists but `tests/README.md` is missing or does not document its repo-level dependency
- `README.md` is absent, or its file table has a missing or stale row
- `SKILL.md` describes a script invocation the script does not accept
Flag as SUGGESTION if:
- An optional directory exists but holds only a placeholder README
- `README.md` is accurate but describes a file's purpose more thinly than `SKILL.md` does
## formatting and scripts — `references/formatting-and-scripts.md`
Flag as FAIL if:
- A script prompts interactively, in any form
- A script exposes no `--help`
- A destructive script has no `--dry-run`
- Data and diagnostics share a stream, so the output cannot be piped
- A relative path named in the body does not resolve
- Heading levels are inconsistent enough to break the document's structure
Flag as SUGGESTION if:
- Exit codes are meaningful but undocumented in `--help`
- A code block is untagged where a language applies
- A script is idempotent in practice but does not say so, leaving a re-run's safety unclear
- List indentation or section spacing is inconsistent without breaking the render

View File

@@ -44,20 +44,5 @@ follow from that:
undocumented one is a coin flip.
- **`--dry-run` present for destructive operations.**
## Auditing guidance
Flag as FAIL if:
- A script prompts interactively, in any form
- A script exposes no `--help`
- A destructive script has no `--dry-run`
- Data and diagnostics share a stream, so the output cannot be piped
- A relative path named in the body does not resolve
- Heading levels are inconsistent enough to break the document's structure
Flag as SUGGESTION if:
- Exit codes are meaningful but undocumented in `--help`
- A code block is untagged where a language applies
- A script is idempotent in practice but does not say so, leaving a re-run's safety unclear
- List indentation or section spacing is inconsistent without breaking the render
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -50,19 +50,5 @@ forms are judgment.
`references/` when only one dispatch branch produces that output. A template inlined for a branch
most invocations never take is body-discipline padding.
## Auditing guidance
Flag as FAIL if:
- A Gotcha entry is a general tip or a reminder rather than a fact that defies a reasonable
assumption
- An inner code fence is unescaped inside a markdown block, breaking the render
- A checklist wraps a single step
- A conditional reference gives no trigger — `Kyberforge.PaddingPhrase` reports the common form
- The agent must produce a specific format and no output template is given
Flag as SUGGESTION if:
- Gotchas are correctly formed but placed late in the body
- An output template is present but permissive where the consumer needs it exact
- A conditional reference names a trigger that is real but broader than the branch it guards
The FAIL and SUGGESTION criteria for this dimension live in `references/finding-criteria.md`,
which Step 3 loads on every run.

View File

@@ -15,7 +15,7 @@
- **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/body-discipline.md, references/description-quality.md, references/patterns.md, references/file-structure.md, references/formatting-and-scripts.md, references/validation-scripts.md
- **Contributing files:** SKILL.md, references/body-discipline.md, references/description-quality.md, references/patterns.md, references/file-structure.md, references/formatting-and-scripts.md, references/finding-criteria.md, references/validation-scripts.md
- **Status:** `extracted`
## agentskills-best-practices
@@ -23,7 +23,7 @@
- **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, references/body-discipline.md, references/patterns.md
- **Contributing files:** SKILL.md, references/body-discipline.md, references/patterns.md, references/finding-criteria.md
- **Status:** `extracted`
## agentskills-optimizing-descriptions
@@ -31,7 +31,7 @@
- **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, references/description-quality.md
- **Contributing files:** SKILL.md, references/description-quality.md, references/finding-criteria.md
- **Status:** `extracted`
## agentskills-evaluating-skills
@@ -47,7 +47,7 @@
- **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/formatting-and-scripts.md, references/validation-scripts.md
- **Contributing files:** SKILL.md, references/formatting-and-scripts.md, references/finding-criteria.md, references/validation-scripts.md
- **Status:** `extracted`
## agentskills-quickstart

View File

@@ -63,6 +63,11 @@ or Codex, and `.apm/` source compiles for all three, so routing to one is a port
gate is right to fail it and there is no allowlist. If a built-in genuinely needs mentioning, write
it un-slashed — ``the `compact` built-in`` — which makes no routing claim and is not checked.
**One arrow, one target.** The resolver reads only the first name after an arrow, so a second is
checked by nothing and the gate emits a SUGGESTION naming both. Split instead of conjoining:
`Not <thing> -> first-skill. Not <other thing> -> second-skill.`, never
`Not <thing> -> first-skill or second-skill`.
**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
@@ -118,11 +123,25 @@ If <condition>, read `references/<file>.md`.
A generic pointer ("see references/ for details") is a Vale error — the agent cannot act on it.
**A dispatch table is the wiring.** Where the body dispatches, a row already pairs a condition with
a target, which is what the literal form encodes — so do not restate each row underneath as a prose
conditional. That duplicates the routing in the one body whose whole purpose is to be short. The
literal form is what a reference loaded *without* a table needs: a mid-procedure deepening, an
escape hatch, an error path. A table earns this on four properties — every flow has a row and every
row's target exists on disk; each row pairs exactly one target with a condition the agent can
evaluate from the request, never a literal slash invocation; one line after the table names the
matched file as the only one to read; and the gates every branch needs sit in the body, not inside
one flow's file. That last one is the property the `git-commits` v0.1.2 failure turned on, and it is
the one a dispatch split is most likely to break. `skill-audit`'s `references/body-discipline.md`
carries the audit-side form of the same exemption; the two lists are the same four properties, and
an edit to either belongs in both.
**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: the `apm-workflow` skill — a **237-word body** dispatching to 3,416 words of
references. Calibrate against 237: that file's whole-file count is 304 words, and aiming at that
number instead overshoots the body budget by ~30%.
file. Exemplar: the `apm-workflow` skill — a **294-word body** dispatching to 3,154 words of
references across five flow files. Calibrate against 294: that file's whole-file count is 348
words, and aiming at that number instead overshoots the body budget by ~18%. The 3,154 excludes
`references/sources.md`, which is a provenance record and is never loaded at runtime.
**Length.** 600 words SUGGESTION, 900 words FAIL, counting the **body only** — everything after
the frontmatter's closing `---`.
@@ -130,10 +149,20 @@ 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.
gets wrong by acting sensibly. "Write a descriptive commit message" is not one; the agent does it
unprompted and nothing in the environment argues against it. A safety gate is a different case,
even where the agent knows the rule — see the paraphrase bullet below.
- More than five entries is a SUGGESTION — five is the guideline, not a ceiling.
- 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 Gotcha that paraphrases a step in the body below it is a **FAIL**, but deleting it is correct
only when the surviving copy is **reachable from every branch that reaches the Gotcha**. In a
dispatch body it often is not: each flow file loads alone, so a step in one is invisible to an
invocation that took another branch. Where the restated rule is a safety gate more than one flow
needs, move it into the body's common-gates section instead of dropping it. `git-commits` v0.1.2
is the worked failure: the retrofit deleted its always-loaded "never commit secrets" Gotcha in
favour of a step in one flow file, and left the history-rewrite branch — which stages and
`--amend`s, committing new content exactly as a fresh commit does — with no such check anywhere
in its loaded context, against this repo's governance hard prohibitions. v0.1.3 carries the rule
as a gate on every flow.
- 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.

View File

@@ -96,6 +96,13 @@ them for you. After every retrofit that adds, removes or renames a file:
content moved into it, and remove any file the retrofit deleted. This is the one that gets
missed: `sources.md` keeps citing sections of `SKILL.md` that no longer exist, the
provenance check still exits 0, and the stale claim survives review.
- [ ] **Reachability of every relocated gate.** For each Gotcha or gate the retrofit moved out of
the body, list the flows that need it and confirm each one reaches the surviving copy. A gate
that lands in a single flow file is invisible to every other branch, and no gate detects
that: `/skill-audit` reads whichever file it was handed, and the word counts improve either
way. Where more than one flow needs it, the copy belongs in the body's common-gates section,
not in a flow file. Grep the skill for the gate's key term and check every branch that hits
zero.
- [ ] Re-run `/skill-audit` and confirm its `### Provenance` dimension does not report the new
file as missing `source_keys`.