refactor(kyberforge): move audit guidance out of the per-run rubric load

skill-audit loaded roughly 4,268 words of rubric on every run, most of it
criteria for findings a clean skill never triggers. The auditing guidance moves
into finding-criteria.md, read only when a finding is actually raised, cutting
a clean audit to about 999 words. The named-skill exemption is replaced with
properties, so the rubric stops carrying a list that ages the moment a skill
is renamed.

apm-workflow's `type:` trap sat in one flow while biting several, so it is
promoted to a common gate reachable from all of them; its claim to be
self-contained was untrue once it started routing to apm-install. skill-author's
contract had drifted from body-discipline.md and is realigned, and agent-audit's
field inventory is brought in line with the same split.
This commit is contained in:
2026-08-31 08:02:19 +00:00
parent e869912374
commit dac9cad912
42 changed files with 540 additions and 342 deletions

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`.