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

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

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

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

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

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

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

View File

@@ -0,0 +1,63 @@
---
source_keys:
- agentskills-spec
- agentskills-using-scripts
---
# Formatting and Scripts Reference
Upstream source: agentskills.io — specification (body content), using-scripts (designing scripts
for agentic use).
Read this when judging the **formatting** and **scripts** dimensions. Both are checklists of static
criteria that never vary by skill, which is exactly why they live here rather than in the body.
## Formatting
- Heading levels are consistent: H2 for main sections, H3 for subsections. A body that jumps from
H2 to H4, or opens on H3, reads as a fragment of a larger document.
- Code blocks carry a language tag wherever one applies — `bash`, `markdown`, `python`, `yaml`,
`text`. An untagged block loses syntax highlighting and, more importantly, loses the signal of
what the agent is meant to do with it.
- Whitespace is consistent: a blank line between sections, one list-indentation style throughout.
- No broken relative paths in file references. Every `references/…`, `scripts/…` and `assets/…`
path named in the body resolves against the skill directory.
## Scripts
A script in a skill is run by an agent with no terminal and no human to answer it. The criteria
follow from that:
- **No interactive TTY prompts** — no `read`, no `input()`, no `readline`. A script that blocks on
a prompt hangs the run with no diagnostic. `validate.sh` detects the common forms and reports
them under Structure; the judgment call is any prompt it cannot pattern-match. What counts is
where stdin comes from, not the word `read`: a `read` fed by a here-string, a here-doc, a pipe,
or a redirect from a file never touches a terminal and is not a finding. `validate.sh` excludes
those forms, so do not rewrite a working `read -r A B <<< "$line"` into parameter expansion to
satisfy this rule.
- **`--help` is exposed** and gives concise usage.
- **Data to stdout, diagnostics to stderr.** A caller piping the script has to be able to separate
the result from the commentary.
- **Idempotent** — "create if not exists" rather than "create", so a re-run after a partial failure
is safe.
- **Meaningful exit codes, documented in `--help`.** An agent branches on the exit code; an
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