Lint: enforce the 1,024 code-point ceiling on the four SKILL.md descriptions

Author: Imbad0202Created Sep 14, 2026Updated Sep 14, 2026
Labelsenhancement

Problem

The four SKILL.md frontmatter description fields carry the routing keywords, and every locale contribution appends to them. CONTRIBUTING.md (line 64) and docs/SETUP.md (line 453) both state the Agent Skills 1,024-character ceiling, but no lint enforces it. #856 took deep-research from 984 to 1,021 characters, three short of the ceiling, and the gap was found by hand during review. The next language would cross it silently.

Existing description checks (scripts/check_skill_inventory_parity.py, scripts/check_distribution_surface_claims.py) test inventory counts and claim wording, not length.

Unit

Count Unicode code points of the YAML-parsed description value, not UTF-8 bytes and not raw source characters. The Agent Skills specification says "Max 1024 characters"; its reference validator (skills-ref/src/skills_ref/validator.py) applies Python len(description) > 1024 to the parsed string, which is a code-point count. Bytes would give a different answer today: academic-paper on the #856 head is 867 code points but 1,025 UTF-8 bytes.

Current values (YAML-parsed, code points), main @ 91fc74d and the #856 head:

Skill main #856 head
deep-research 984 1,021
academic-paper 699 867
academic-paper-reviewer 699 878
academic-pipeline 595 783

Proposed lint

scripts/check_skill_description_length.py, wired into .github/workflows/spec-consistency.yml:

  • Parse the frontmatter of each of the four SKILL.md files the same way scripts/check_command_frontmatter_name.py does, then read description.
  • Fail when len(description) > 1024, when the value is missing or not a string, or when it is empty or whitespace-only.
  • Print the per-skill count on every run so a PR reviewer can see the remaining budget without recomputing it.
  • Do not trim, normalize, or fold the value before counting; count exactly what the parser returns.
  • Mutation tests: over-limit value fails; exactly 1,024 passes; whitespace-only fails; a folded multi-line YAML scalar is counted after folding; a description containing CJK and accented characters is counted in code points.

Out of scope: the Claude Code 1,536-character listing cap for description plus when_to_use. ARS does not set when_to_use, and the Claude Code counting implementation is not documented, so that cap is noted in docs only.

Why it matters for #862

The locale Phase 2 trigger budget needs one agreed number. With this lint in place, "all four descriptions under 1,024 code points" becomes a CI fact rather than a review-time measurement, and a locale pack that wants more trigger coverage has to make the case for a pack-level trigger surface instead of appending to the descriptions.

Refs #856, #862, #850.

Source: Imbad0202/academic-research-skills