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:
@@ -145,6 +145,81 @@ kyberforge-vale-audit-skill|skills/demo/SKILL.md|helps with
|
||||
kyberforge-vale-audit-agent|agents/demo.md|utilize
|
||||
EOF
|
||||
|
||||
# --- 1b. Every rule in the shipped style is asserted to FIRE, not merely to
|
||||
# exist. A Vale rule can be well-formed, load without a diagnostic, and match
|
||||
# nothing at all: `extends: existence` CONCATENATES multiple `raw:` entries
|
||||
# rather than alternating them, so a rule written as a list of alternatives
|
||||
# silently becomes one impossible expression, lints every file clean and exits
|
||||
# 0 — indistinguishable from a corpus with no violations. `Kyberforge.CompositionNote`
|
||||
# was written that way first and passed all 43 skill and agent files before the
|
||||
# defect was found by hand. Each rule gets its own fixture pass, with the token
|
||||
# it must quote attributed to the file that raised it, so one rule's alert can
|
||||
# never stand in for another's.
|
||||
echo ""
|
||||
echo "--- each Kyberforge description rule fires through both shipped hooks ---"
|
||||
write_desc_fixtures() {
|
||||
local skill_desc="$1" agent_desc="$2"
|
||||
cat > "$CONSUMER/skills/demo/SKILL.md" <<EOF
|
||||
---
|
||||
name: demo
|
||||
description: >
|
||||
$skill_desc across two
|
||||
physical lines of one folded block scalar.
|
||||
---
|
||||
|
||||
Body.
|
||||
EOF
|
||||
cat > "$CONSUMER/agents/demo.md" <<EOF
|
||||
---
|
||||
name: demo
|
||||
description: >
|
||||
$agent_desc across two
|
||||
physical lines of one folded block scalar.
|
||||
---
|
||||
|
||||
Body.
|
||||
EOF
|
||||
git -C "$CONSUMER" add -A
|
||||
}
|
||||
|
||||
run_rule_case() {
|
||||
local label="$1" hook_id="$2" fixture="$3" token="$4"
|
||||
local log="$WORK/rule-$label.log"
|
||||
set +e
|
||||
(cd "$CONSUMER" && pre-commit run "$hook_id" --all-files > "$log" 2>&1)
|
||||
local rc=$?
|
||||
set -e
|
||||
if grep -q "Skipped" "$log"; then
|
||||
fail "$hook_id matched no files for $label, so it proved nothing"
|
||||
sed 's/^/ /' "$log"
|
||||
elif [[ $rc -eq 0 ]]; then
|
||||
fail "$hook_id passed $fixture despite its flagged '$token' — $label matches nothing"
|
||||
sed 's/^/ /' "$log"
|
||||
elif alerts_for "$fixture" < "$log" | grep -qF "'$token'"; then
|
||||
pass "$label fires through $hook_id and quotes '$token' under $fixture"
|
||||
else
|
||||
fail "$hook_id failed, but no $label alert quoting '$token' was filed under $fixture"
|
||||
sed 's/^/ /' "$log"
|
||||
fi
|
||||
}
|
||||
|
||||
# CompositionNote: a distinct banned token per file shape.
|
||||
write_desc_fixtures \
|
||||
"Use when the caller wants a demo skill that composes other skills" \
|
||||
"Use when the caller wants a cross-cutting demo agent"
|
||||
run_rule_case "Kyberforge.CompositionNote" kyberforge-vale-audit-skill skills/demo/SKILL.md "composes"
|
||||
run_rule_case "Kyberforge.CompositionNote" kyberforge-vale-audit-agent agents/demo.md "cross-cutting"
|
||||
|
||||
# DescriptionOpener: the widened pattern catches every non-imperative "This..."
|
||||
# opener, not only the literal "This skill"/"This agent" pair it was anchored to
|
||||
# before. Both fixtures open with "This is", the form two shipped descriptions
|
||||
# used mid-sentence and which the old pattern could not express.
|
||||
write_desc_fixtures \
|
||||
"This is a demo skill for callers who want one" \
|
||||
"This is a demo agent for callers who want one"
|
||||
run_rule_case "Kyberforge.DescriptionOpener" kyberforge-vale-audit-skill skills/demo/SKILL.md "This"
|
||||
run_rule_case "Kyberforge.DescriptionOpener" kyberforge-vale-audit-agent agents/demo.md "This"
|
||||
|
||||
# --- 2. Clean files pass — the hooks gate, they don't just always fail ---
|
||||
echo ""
|
||||
echo "--- all three hooks pass clean files in an external consumer repo ---"
|
||||
|
||||
Reference in New Issue
Block a user