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
3.0 KiB
source_keys
| source_keys | |||
|---|---|---|---|
|
Plugin/APM Scope Contract
Read this when the agent file sits at <package>/.apm/agents/<name>.agent.md — a single
vendor-neutral file inside an APM package, with no counterpart anywhere.
What is different here
apm compile copies an agent's frontmatter verbatim to every target harness. There is no
per-target integrator to reconcile a Claude-Code-only field with a Copilot-only one, so the file
cannot carry either (ADR-0016). That single fact drives everything below.
Frontmatter allowlist
The permitted keys are the apm-agent-allowlist section of references/field-inventory.md. Read
them from there. Do not recite the list in a finding, do not work from memory, and do not trust any
restatement of it you find elsewhere in this repo: the list is data with one home (ADR-0009), it
has changed before, and validate.sh parses that same section at load time, so a recitation is a
copy that can disagree with the check the agent just ran.
field-inventory.md records why a denylist-shaped field is admitted where an allowlist-shaped one
is not. Read that note before arguing with a finding about it.
Dimension routing
validate.sh findings land as follows at this scope:
| Finding | Dimension |
|---|---|
| any frontmatter key outside the allowlist; body over the 30,000-character Copilot limit | Provider safety |
everything else — missing or malformed field, name not matching the filename stem, empty body, absent frontmatter, template HTML comments, description length |
Structure |
| — | Pair consistency never applies |
Provider safety means something else here. At project/user scope it asks whether a field leaked across the Claude Code / Copilot boundary. At this scope there is no boundary and no pair: it asks whether every field survives a verbatim copy to every target. Report it in those terms — a finding phrased as "CC-only field in a Copilot file" is the wrong finding here.
Pair consistency never applies. There is one file by design. validate.sh never emits a
missing-counterpart FAIL at this scope, and neither do you, under any circumstance. Drop
pair-consistency from the Step 4 coverage line rather than reporting it clean.
Behaviour the schema cannot express
Read the description and body. If either implies a need the vendor-neutral frontmatter can no
longer express — a tool restriction, isolation, memory, or another Claude-only behaviour a
hand-authored CC file could have declared — flag it as a SUGGESTION, never a FAIL. This is a
known upstream schema limitation (ADR-0016), not an authoring mistake, and the finding exists to
give the author visibility into the gap rather than to imply the schema can be made to close it.
Example: a body saying "only use Read and Grep, never Edit" with no tools field to enforce it.
A denylist-shaped restriction is the available half of that — see field-inventory.md.