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

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

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

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

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

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

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

View File

@@ -10,11 +10,24 @@ name: SKILL_NAME
# Examples: my-tool, data-analyzer, pdf-processor
description: >
FILL IN: What does this skill do? State capabilities specifically
Use when FILL IN: trigger — when should an agent activate this skill?
FILL IN: at most ONE capability clause, stated specifically
(e.g. "parses and validates OpenAPI specs", not "helps with APIs").
Use when FILL IN: when should an agent activate this skill?
Include indirect triggers: even if the user doesn't mention X explicitly.
Do not use when FILL IN: near-miss exclusions — remove this line if none apply.
Not FILL IN: near-miss case -> FILL IN: real sibling skill name.
# Required. Preloaded into EVERY session whether or not the skill is invoked.
# Exactly three parts, in this order: trigger clause, at most one capability
# clause, boundary clause. Drop the boundary line if no near-miss skill exists.
# Budget: 250 characters target, 400 hard ceiling (counting this value only).
# Banned here: capability lists, output-format detail, composition notes,
# implementation detail, and restating one trigger twice in two registers.
# The boundary target must resolve to a real skill or agent — it is checked.
# Add "even if the user doesn't mention X explicitly" ONLY when the user's
# natural phrasing genuinely omits the domain word.
# disable-model-invocation: true
# Optional. Hand-invoked skills only (reached solely by the user typing
# /SKILL_NAME). With this set, replace the description above with ONE plain
# human-facing sentence — no trigger clause, no boundary clause.
# license: MIT
# Optional. License name (e.g. MIT, Apache-2.0) or relative path to a bundled
@@ -42,29 +55,30 @@ description: >
---
<!-- ============================================================
SKILL BODY
SKILL BODY — decision procedure ONLY
Include only what the agent lacks:
- Domain conventions the agent cannot infer from general knowledge
- Non-obvious sequences or ordering constraints
- One default per decision point + one escape hatch (never a menu)
- Gotchas — facts that defy reasonable assumptions
Keep here: ordered steps, decision branches, gates, and which reference
file to load when.
Omit:
- Concepts the agent already knows
- Exhaustive option lists
- Steps the agent handles independently
- Restatements of the description
Move to references/: lookup tables, spec restatements, output schemas,
templates, example blocks, rationale prose, and anything only one branch
reaches. Wire each one with the literal conditional form
"If <condition>, read `references/<file>.md`." — a generic
"see references/ for details" is a lint error.
Size budget: under 500 lines / 5000 tokens.
Move reference material to references/ and load it conditionally.
Bundle repeated executable logic into scripts/.
Budget: 600 words target, 900 hard ceiling, counting THIS BODY ONLY
(everything after the closing --- above). Separate from the whole-file
spec backstop of 2,770 words / 500 lines — do not conflate them.
Delete this comment block before shipping.
============================================================ -->
<!-- OPTIONAL: Gotchas section — highest-value content. Place near the top.
Add facts that defy reasonable assumptions or non-obvious constraints.
<!-- OPTIONAL but high-value: Gotchas. Place near the top — a gotcha read
after the mistake is worthless.
Each entry states a fact that CONTRADICTS a reasonable default:
something the agent gets wrong by acting sensibly. Maximum 5 entries.
An entry that paraphrases a step below it is a failure, not a gotcha.
## Gotchas
@@ -72,7 +86,22 @@ description: >
- FILL IN: non-obvious naming discrepancy or hidden constraint
-->
<!-- OPTIONAL: Multi-step workflow checklist.
<!-- DISPATCH — MANDATORY when this skill has two or more mutually exclusive
flows. Keep only the dispatch table plus the gates common to every
branch in this body; give each flow its own self-contained
references/ file. Delete this block for a single-flow skill.
## Step 1 — Dispatch
| Condition | Flow | Reference |
|---|---|---|
| FILL IN: condition | FILL IN: flow | `references/FILL IN.md` |
| FILL IN: condition | FILL IN: flow | `references/FILL IN.md` |
Read only the reference matching the resolved flow — each is self-contained.
-->
<!-- OPTIONAL: single-flow workflow checklist. Delete if the skill dispatches.
## Workflow
@@ -81,23 +110,12 @@ description: >
- [ ] Step 3: FILL IN
-->
<!-- OPTIONAL: Output format template — use when the agent must produce a specific format.
<!-- OPTIONAL: gates that apply to every branch — validation, versioning,
closing checks. Keep these in the body even when flows are dispatched.
## Output format
## Step N — Validate and close
Use this structure:
```markdown
# [FILL IN: Title]
## FILL IN: Section
FILL IN: what goes here
```
-->
<!-- OPTIONAL: Conditional reference — load documentation only when needed.
If FILL IN: condition, read `references/FILL IN: filename.md`.
FILL IN: the check that must pass before this skill reports done.
-->
## FILL IN: <section-name (e.g. Step 1, Workflow, Instructions)>

View File

@@ -5,9 +5,17 @@ without bloating its core context.
## When to add a reference file
Move content here when SKILL.md is approaching 500 lines, or when a topic
is only relevant in specific circumstances (error handling, edge cases,
domain-specific sub-procedures).
The SKILL.md body carries the decision procedure only. Everything else lives
here: lookup tables, spec restatements, output schemas, templates, example
blocks, rationale prose, and anything only one branch reaches.
Two triggers make a reference file mandatory rather than optional:
- The body is over its 600-word target (900 is a hard failure), counting the
body only — everything after the frontmatter's closing `---`.
- The skill has two or more mutually exclusive flows. The body then keeps only
a dispatch table plus the gates common to every branch, and each flow gets
its own self-contained file here (e.g. `create.md`, `improve.md`).
## How to reference from SKILL.md