Fix validator nested-name misparse, unify with CI, add authorized-use banner

Issues found in review:

1. tools/validate-skill.py: parse_frontmatter operated on the stripped line, so
   an indented nested `name:` (under framework-mapping lists, e.g.
   `name: 'Create Fake Materials: Fake Website'`) clobbered the skill's
   top-level `name`. That produced 94 spurious "invalid kebab-case name"
   failures out of 762. Now indented (non-list) key lines are ignored, so only
   top-level keys define frontmatter fields. Result: 762/762 pass.

2. Two divergent validators: the CI workflow had its own weaker inline parser
   (no subdomain/tag/description checks) requiring a different field set than
   tools/validate-skill.py. CI now delegates to tools/validate-skill.py --all
   (single source of truth); REQUIRED_FIELDS aligned to include
   version/author/license. The duplicate-name and stats steps are unchanged.

3. README: added an explicit authorized-&-lawful-use disclaimer next to the
   existing "not affiliated with Anthropic" note, since the library ships
   offensive/dual-use techniques.

No skill content changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Homan Ansari
2026-06-22 18:09:19 +02:00
co-authored by Claude Opus 4.8
parent 13a1c4afd9
commit 5f5edbb30b
3 changed files with 20 additions and 53 deletions
+12 -1
View File
@@ -10,7 +10,10 @@ import re
import sys
import glob
REQUIRED_FIELDS = ["name", "description", "domain", "subdomain", "tags"]
# Kept in sync with the CI workflow (.github/workflows/validate-skills.yml),
# which now delegates to this script so there is a single source of truth.
REQUIRED_FIELDS = ["name", "description", "domain", "subdomain", "tags",
"version", "author", "license"]
# Canonical subdomain → set of accepted aliases (including canonical itself).
# When a skill uses an alias, the validator accepts it but the canonical form
@@ -132,6 +135,14 @@ def parse_frontmatter(text):
data[current_key] = list(list_values) # copy so future mutations don't leak
continue
# Only TOP-LEVEL keys (column 0) define frontmatter fields. An indented
# ``key: value`` line belongs to a nested structure (e.g. a framework
# mapping object that has its own ``name:``/``id:``) and must NOT be
# treated as a top-level field — otherwise a nested ``name:`` clobbers
# the skill's real ``name``.
if line[:1].isspace():
continue
# Handle inline list: tags: [a, b, c]
m = re.match(r"^(\w[\w_-]*):\s*\[(.+)\]\s*$", stripped)
if m: