@@ -5,6 +5,80 @@ ROOT="${1:-skills}"
55FAILED=0
66COUNT=0
77
8+ trim () {
9+ printf ' %s' " $1 " | sed ' s/^[[:space:]]*//;s/[[:space:]]*$//'
10+ }
11+
12+ get_frontmatter_value () {
13+ local frontmatter=" $1 "
14+ local key=" $2 "
15+ printf ' %s\n' " $frontmatter " | sed -n " s/^$key :[[:space:]]*//p" | head -n1 | sed ' s/^"//;s/"$//'
16+ }
17+
18+ validate_csv_values () {
19+ local file=" $1 "
20+ local field=" $2 "
21+ local value=" $3 "
22+ local item
23+ local seen=0
24+
25+ IFS=' ,' read -r -a items <<< " $value"
26+ for item in " ${items[@]} " ; do
27+ item=" $( trim " $item " ) "
28+ if [[ -z " $item " ]]; then
29+ echo " FAIL $file : $field contains an empty entry"
30+ FAILED=1
31+ continue
32+ fi
33+ seen=1
34+ done
35+
36+ if [[ " $seen " -eq 0 ]]; then
37+ echo " FAIL $file : $field must contain at least one value"
38+ FAILED=1
39+ fi
40+ }
41+
42+ validate_capabilities () {
43+ local file=" $1 "
44+ local value=" $2 "
45+ local capability
46+
47+ validate_csv_values " $file " " capabilities" " $value "
48+
49+ IFS=' ,' read -r -a items <<< " $value"
50+ for capability in " ${items[@]} " ; do
51+ capability=" $( trim " $capability " ) "
52+ [[ -z " $capability " ]] && continue
53+ if [[ ! " $capability " =~ ^[a-z0-9]+ ([.-][a-z0-9]+)* $ ]]; then
54+ echo " FAIL $file : invalid capability '$capability '"
55+ FAILED=1
56+ fi
57+ done
58+ }
59+
60+ validate_activation_events () {
61+ local file=" $1 "
62+ local value=" $2 "
63+ local event
64+
65+ validate_csv_values " $file " " activation-events" " $value "
66+
67+ IFS=' ,' read -r -a items <<< " $value"
68+ for event in " ${items[@]} " ; do
69+ event=" $( trim " $event " ) "
70+ [[ -z " $event " ]] && continue
71+ case " $event " in
72+ user-prompt|session-start|pre-tool-use|post-tool-use|pre-compact|session-end)
73+ ;;
74+ * )
75+ echo " FAIL $file : unsupported activation event '$event '"
76+ FAILED=1
77+ ;;
78+ esac
79+ done
80+ }
81+
882if [[ ! -d " $ROOT " ]]; then
983 echo " ERROR: skills root not found: $ROOT "
1084 exit 1
@@ -22,11 +96,16 @@ for file in "$ROOT"/*/SKILL.md; do
2296 continue
2397 fi
2498
25- name=" $( printf ' %s\n' " $frontmatter " | sed -n ' s/^name:[[:space:]]*//p' | head -n1 | tr -d ' "' ) "
26- description=" $( printf ' %s\n' " $frontmatter " | sed -n ' s/^description:[[:space:]]*//p' | head -n1 | tr -d ' "' ) "
27- owner=" $( printf ' %s\n' " $frontmatter " | sed -n ' s/^owner:[[:space:]]*//p' | head -n1 | tr -d ' "' ) "
28- version=" $( printf ' %s\n' " $frontmatter " | sed -n ' s/^version:[[:space:]]*//p' | head -n1 | tr -d ' "' ) "
29- metadata_version=" $( printf ' %s\n' " $frontmatter " | sed -n ' s/^metadata-version:[[:space:]]*//p' | head -n1 | tr -d ' "' ) "
99+ name=" $( get_frontmatter_value " $frontmatter " " name" ) "
100+ description=" $( get_frontmatter_value " $frontmatter " " description" ) "
101+ owner=" $( get_frontmatter_value " $frontmatter " " owner" ) "
102+ version=" $( get_frontmatter_value " $frontmatter " " version" ) "
103+ metadata_version=" $( get_frontmatter_value " $frontmatter " " metadata-version" ) "
104+ capabilities=" $( get_frontmatter_value " $frontmatter " " capabilities" ) "
105+ activation_intents=" $( get_frontmatter_value " $frontmatter " " activation-intents" ) "
106+ activation_events=" $( get_frontmatter_value " $frontmatter " " activation-events" ) "
107+ activation_artifacts=" $( get_frontmatter_value " $frontmatter " " activation-artifacts" ) "
108+ risk_level=" $( get_frontmatter_value " $frontmatter " " risk-level" ) "
30109
31110 if [[ -z " $name " || -z " $description " || -z " $owner " || -z " $version " || -z " $metadata_version " ]]; then
32111 echo " FAIL $file : missing one of required keys (name, description, owner, version, metadata-version)"
@@ -48,8 +127,8 @@ for file in "$ROOT"/*/SKILL.md; do
48127 FAILED=1
49128 fi
50129
51- if [[ " $metadata_version " != " 1" ]]; then
52- echo " FAIL $file : metadata-version must be '1', got '$metadata_version '"
130+ if [[ " $metadata_version " != " 1" && " $metadata_version " != " 2 " ]]; then
131+ echo " FAIL $file : metadata-version must be '1' or '2' , got '$metadata_version '"
53132 FAILED=1
54133 fi
55134
@@ -63,6 +142,34 @@ for file in "$ROOT"/*/SKILL.md; do
63142 FAILED=1
64143 fi
65144
145+ if [[ " $metadata_version " == " 1" && (-n " $capabilities " || -n " $activation_intents " || -n " $activation_events " || -n " $activation_artifacts " || -n " $risk_level " ) ]]; then
146+ echo " FAIL $file : activation metadata requires metadata-version '2'"
147+ FAILED=1
148+ fi
149+
150+ if [[ " $metadata_version " == " 2" ]]; then
151+ if [[ -n " $capabilities " ]]; then
152+ validate_capabilities " $file " " $capabilities "
153+ fi
154+
155+ if [[ -n " $activation_intents " ]]; then
156+ validate_csv_values " $file " " activation-intents" " $activation_intents "
157+ fi
158+
159+ if [[ -n " $activation_events " ]]; then
160+ validate_activation_events " $file " " $activation_events "
161+ fi
162+
163+ if [[ -n " $activation_artifacts " ]]; then
164+ validate_csv_values " $file " " activation-artifacts" " $activation_artifacts "
165+ fi
166+
167+ if [[ -n " $risk_level " && " $risk_level " != " low" && " $risk_level " != " medium" && " $risk_level " != " high" ]]; then
168+ echo " FAIL $file : risk-level must be low, medium, or high"
169+ FAILED=1
170+ fi
171+ fi
172+
66173done
67174
68175# Enforce provider-agnostic skill packages.
0 commit comments