Files
holocron/plugins/kyberforge/.apm/skills/skill-audit/references/body-discipline.md
Defame1297 7e80c09b13 fix(kyberforge): a dispatch table satisfies the reference-wiring rule
body-discipline.md required every reference load to use the literal
'If X, read references/file.md' form and called anything else a generic
pointer. ADR-0020's own cited dispatch exemplar, apm-workflow, uses a
bare table plus one closing line, so an author could not satisfy both --
and the rule reliably produced duplication in exactly the bodies the
contract exists to keep short.

Resolves #109 with its option 1: a table row already pairs a condition
with a target, so where a body dispatches, the table is the wiring. The
literal form is what a body needs when it loads a reference without a
table.

Two corrections to the issue as filed. There is no Vale conflict --
PaddingPhrase.yml only matches 'see references/ for more info' and never
fired on the exemplar, so this is a one-file prose fix and no rule
changes. And gitea-workflow carried the predicted duplication: a
three-row table restated underneath as three conditionals. Removed, body
227 -> 148 words.

Closes #109
2026-08-30 15:07:16 +00:00

10 KiB

source_keys
source_keys
agentskills-spec
agentskills-best-practices

Body Discipline Reference

Upstream source: agentskills.io — skill-authoring, best-practices. House contract: ADR-0020, the context budget.

The core test

For every sentence in the body, ask: "Would the agent get this wrong without this instruction?"

If no — cut it. The agent already knows it from general training. Adding it wastes tokens and dilutes the signal of what matters.

What the body is for

The body carries the decision procedure only: ordered steps, decision branches, gates, and which reference to load when.

Include content the agent lacks:

  • Project-specific conventions and domain procedures it cannot infer
  • Non-obvious edge cases and environment-specific gotchas
  • The specific tools or sequences to use — not the full range of options
  • One default per decision point with one escape hatch

Move to references/, behind an explicit "If X, read references/<file>.md" trigger — the literal conditional form, never a generic pointer. Write the real filename in the skill under audit; the angle brackets are a placeholder here, and a literal references/file.md in a body is an ERROR from the ADR-0020 gate because no such file exists on disk.

A dispatch table satisfies this requirement on its own. A table row already pairs a condition with a target, which is exactly what the literal form encodes; restating each row underneath as a prose conditional duplicates the routing in the one body whose whole purpose is to be short. Where a body dispatches, audit the table for condition/target completeness and stop there — do not require the conditional form as well. The literal form is what a body needs when it loads a reference without a dispatch table: a single mid-procedure deepening, an escape hatch, an error path.

Move:

  • Lookup tables and spec restatements
  • Output schemas, templates and example blocks
  • Rationale and justification prose
  • Anything only one branch of the procedure ever reaches

Do not include at all:

  • Concepts the agent already knows (what JSON is, how HTTP works, what a CSV is)
  • Exhaustive option lists — pick a default; the agent does not benefit from choosing
  • Steps the agent handles independently — over-specifying leads to unproductive paths
  • Restatements of the description, which is already in context

Two length families, measured differently

Do not conflate these, and do not report them as one finding.

Gate SUGGESTION FAIL Counts
Body budget (house, ADR-0020) 600 words 900 words the body only — everything after the frontmatter's closing ---
Spec conformance (agentskills.io) — 2,770 words / 500 lines the whole file, frontmatter included

The 2,770-word ceiling is a token-conformance backstop calibrated to the densest prose in the corpus; it says nothing about quality and a file can sit a thousand words inside it while failing the body budget. The 900-word ceiling is the quality gate: a body is loaded into the caller's live context and competes with the conversation already there. validate.sh reports both. Cite whichever one actually fired.

A word count cannot detect the defect it stands in for. Treat both numbers as backstops to the dispatch rule and the Gotchas constraint below, never as a substitute for them.

Dispatch is mandatory at two or more mutually exclusive flows

If a skill handles two or more flows that a single invocation cannot both take — separate subcommands, separate input types, separate lifecycle stages — the body carries a dispatch table plus the gates common to every branch, and each flow lives in its own self-contained 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 421-word body dispatching to roughly 3,000 words of references across five mutually exclusive invocations. Its whole-file count is 554 words — cite 421 when calibrating a body, or the conflation this section warns against reappears in the finding itself.

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.

Gotchas sections

The highest-value construct in a body, and the easiest to fill with noise. A Gotcha must state a fact that contradicts a reasonable default — something the agent gets wrong precisely by acting sensibly.

## Gotchas
- The `users` table uses soft deletes. Always include `WHERE deleted_at IS NULL`.
- User ID is `user_id` in the database, `uid` in auth, `accountId` in billing. Same value.

Constraints:

  • More than five entries is a SUGGESTION — five is the guideline, not a ceiling. Past five, the section is usually a summary of the body rather than a set of traps, and the agent stops reading it as a warning. It stays advisory because whether a given gotcha earns its place is judgment; validate.sh emits it through suggest() and the run still exits 0.
  • A Gotcha that paraphrases a step in the body below it is a FAIL. It has no independent content, and it teaches the agent that Gotchas can be skimmed because the real instruction is coming. This one is the auditor's call — no script detects it. The Fix is conditional: delete the Gotcha only if the surviving copy is reachable from every branch that needs it — see the reachability precondition below.
  • A Gotchas section exceeding 25% of the body is a SUGGESTION — the body has been inverted into a preamble. Same tier and same reasoning as the entry count, and independent of it: either can fire without the other.
  • Place the section near the top. A gotcha read after the mistake is worthless, which is also why Gotchas is the one construct exempt from moving to references/.

Worked negative example — git-commits v0.1.2 at commit 5e23250, a fixed pre-retrofit snapshot, not the current file. The live skill is v0.1.3 and matches none of the citations below; they are quoted as they stood before the ADR-0020 retrofit, and are not to be refreshed against HEAD. Read the snapshot with git show 5e23250:plugins/git/.apm/skills/git-commits/SKILL.md. That body carried twelve Gotchas, four of which restated content already below them or already in the description:

Gotcha Restates
:31 "SemVer mapping is not optional" the description
:32 "Confirmation gates are mandatory for destructive operations" step 9 at :52
:33 "Never skip hooks with --no-verify" step 9 at :52
:36 "Never commit secrets" step 2 at :45

All four are FAILs under the paraphrase rule. The entry count and the section's share of the body (387 of 1,102 words, 35%) are two further SUGGESTIONs on top — the script reports both, and neither fails the run on its own. What makes this worth auditing directly is that the four paraphrase FAILs pass every word gate there is; only reading the construct finds them.

The paraphrase rule has a reachability precondition

A Gotcha that restates a step may be deleted only when the surviving copy is reachable from every branch that needs it. In a dispatch body it usually is not: each flow file is loaded alone, so a step in one is invisible to an invocation that took another branch. When the restated rule is a safety gate more than one flow needs, the Fix is to move it into the body's common-gates section, never to drop it in favour of the per-flow copy.

Row four is the case that proves it. Following the rule literally, the retrofit deleted the always-loaded secrets Gotcha and kept step 2 of references/create-commit.md — but git-commits dispatches to exactly one flow file, and references/rewrite-history.md stages changes and runs --amend, which commits newly staged content exactly as a fresh commit does. A grep for secret across the skill in that state returned one hit, on a path two of three branches never reach: that branch could commit a credential with no check anywhere in its loaded context, against this repo's governance hard prohibition. v0.1.3 carries the rule as gate 2 of "Gates on every flow" instead.

So check reachability before writing the Fix. Rows one to three are unaffected — the description is loaded on every invocation, and confirmation is likewise a common gate rather than a per-flow step.

Calibrating control

Be prescriptive when operations are fragile, consistency matters, or a specific sequence must be followed:

Run exactly:
\`\`\`bash
python scripts/migrate.py --verify --backup
\`\`\`
Do not modify the command or add additional flags.

Give freedom when multiple approaches are valid. Explaining why outperforms rigid directives — agents make better decisions when they understand the purpose.

Defaults not menus

Never present a list of equivalent options — pick one and mention the alternative briefly:

# Too many options
Use pypdf, pdfplumber, PyMuPDF, or pdf2image...

# Default with escape hatch
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